Browse Source

Resolves merging-order conflicts for the vehicle physics PR, as well as correcting cmake not blacklisting the componentGroup files if TORQUE_EXPERIMENTAL_EC was flipped off.

Areloch 9 years ago
parent
commit
3a73344abb
36 changed files with 357 additions and 46 deletions
  1. 22 0
      Engine/source/T3D/physics/bullet/btBody.cpp
  2. 2 0
      Engine/source/T3D/physics/bullet/btBody.h
  3. 15 10
      Engine/source/T3D/physics/bullet/btPlayer.cpp
  4. 4 0
      Engine/source/T3D/physics/bullet/btPlayer.h
  5. 4 0
      Engine/source/T3D/physics/physicsBody.h
  6. 19 1
      Engine/source/T3D/physics/physx3/px3Body.cpp
  7. 2 0
      Engine/source/T3D/physics/physx3/px3Body.h
  8. 30 0
      Engine/source/T3D/physics/physx3/px3Player.cpp
  9. 2 2
      Engine/source/T3D/physics/physx3/px3Player.h
  10. 58 1
      Engine/source/T3D/physics/physx3/px3World.cpp
  11. 5 0
      Engine/source/T3D/physics/physx3/px3World.h
  12. 42 1
      Engine/source/T3D/vehicles/vehicle.cpp
  13. 7 0
      Engine/source/T3D/vehicles/vehicle.h
  14. 1 1
      Engine/source/materials/materialFeatureTypes.cpp
  15. 2 1
      Engine/source/materials/processedShaderMaterial.cpp
  16. 13 1
      Engine/source/navigation/navMesh.cpp
  17. 1 0
      Engine/source/scene/sceneObject.cpp
  18. 1 0
      Engine/source/scene/sceneObject.h
  19. 4 1
      Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp
  20. 4 1
      Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp
  21. 0 3
      Templates/Empty/game/tools/materialEditor/scripts/materialEditor.ed.cs
  22. 3 1
      Templates/Empty/game/tools/shapeEditor/scripts/shapeEditor.ed.cs
  23. 6 2
      Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs
  24. 6 1
      Templates/Full/game/scripts/client/default.bind.cs
  25. 12 2
      Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl
  26. 12 2
      Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl
  27. 12 2
      Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl
  28. 11 2
      Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl
  29. 12 2
      Templates/Full/game/shaders/common/lighting/advanced/spotLightP.hlsl
  30. 11 2
      Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl
  31. 23 0
      Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui
  32. 0 3
      Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs
  33. 3 1
      Templates/Full/game/tools/shapeEditor/scripts/shapeEditor.ed.cs
  34. 6 2
      Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs
  35. 1 0
      Templates/Full/game/tools/worldEditor/scripts/menus.ed.cs
  36. 1 1
      Tools/CMake/torque3d.cmake

+ 22 - 0
Engine/source/T3D/physics/bullet/btBody.cpp

@@ -442,3 +442,25 @@ void BtBody::findContact(SceneObject **contactObject,
       }
    }
 }
+
+void BtBody::moveKinematicTo(const MatrixF &transform)
+{
+   AssertFatal(mActor, "BtBody::moveKinematicTo - The actor is null!");
+
+   U32 bodyflags = mActor->getCollisionFlags();
+   const bool isKinematic = bodyflags & BF_KINEMATIC;
+   if (!isKinematic)
+   {
+      Con::errorf("BtBody::moveKinematicTo is only for kinematic bodies.");
+      return;
+   }
+
+   if (mCenterOfMass)
+   {
+      MatrixF xfm;
+      xfm.mul(transform, *mCenterOfMass);
+      mActor->setCenterOfMassTransform(btCast<btTransform>(xfm));
+   }
+   else
+      mActor->setCenterOfMassTransform(btCast<btTransform>(transform));
+}

+ 2 - 0
Engine/source/T3D/physics/bullet/btBody.h

@@ -113,6 +113,8 @@ public:
    virtual void applyImpulse( const Point3F &origin, const Point3F &force );
 
    virtual void findContact(SceneObject **contactObject, VectorF *contactNormal, Vector<SceneObject*> *outOverlapObjects) const;
+   virtual void moveKinematicTo(const MatrixF &xfm);
+
 };
 
 #endif // _T3D_PHYSICS_BTBODY_H_

+ 15 - 10
Engine/source/T3D/physics/bullet/btPlayer.cpp

@@ -71,6 +71,7 @@ void BtPlayer::init( const char *type,
    mObject = obj;
    mWorld = (BtWorld*)world;
 
+   mSlopeAngle = runSurfaceCos;
    mStepHeight = stepHeight;
 
    //if ( dStricmp( type, "Capsule" ) == 0 )
@@ -102,6 +103,17 @@ Point3F BtPlayer::move( const VectorF &disp, CollisionList &outCol )
 {
    AssertFatal( mGhostObject, "BtPlayer::move - The controller is null!" );
 
+   if (!mWorld->isEnabled())
+   {
+      btTransform currentTrans = mGhostObject->getWorldTransform();
+      btVector3 currentPos = currentTrans.getOrigin();
+
+      Point3F returnPos = btCast<Point3F>(currentPos);
+     
+      returnPos.z -= mOriginOffset;
+      return returnPos;
+   }
+
    // First recover from any penetrations from the previous tick.
    U32 numPenetrationLoops = 0;
    bool touchingContact = false;
@@ -305,16 +317,9 @@ bool BtPlayer::_sweep( btVector3 *inOutCurrPos, const btVector3 &disp, Collision
          col.normal = btCast<Point3F>( callback.m_hitNormalWorld );
          col.object = PhysicsUserData::getObject( callback.m_hitCollisionObject->getUserPointer() );
 
-         if (disp.z() < 0.0f)
-         {
-            // We're sweeping down as part of the stepping routine.    In this
-            // case we want to have the collision normal only point in the opposite direction.
-            // i.e. up  If we include the sideways part of the normal then the Player class
-            // velocity calculations using this normal will affect the player's forwards
-            // momentum.  This is especially noticable on stairs as the rounded bottom of
-            // the capsule slides up the corner of a stair.
-            col.normal.set(0.0f, 0.0f, 1.0f);
-         }
+         F32 vd = col.normal.z;
+         if (vd < mSlopeAngle)
+            return false;
       }
 
       return true;

+ 4 - 0
Engine/source/T3D/physics/bullet/btPlayer.h

@@ -57,6 +57,10 @@ protected:
    ///
    F32 mOriginOffset;
 
+   ///
+   F32 mSlopeAngle;
+   ///
+
    ///
    F32 mStepHeight;
    ///

+ 4 - 0
Engine/source/T3D/physics/physicsBody.h

@@ -117,6 +117,10 @@ public:
    virtual void findContact(SceneObject **contactObject,
       VectorF *contactNormal,
       Vector<SceneObject*> *outOverlapObjects) const = 0;
+
+   ///
+   virtual void moveKinematicTo(const MatrixF &xfm) = 0;
+
 };
 
 

+ 19 - 1
Engine/source/T3D/physics/physx3/px3Body.cpp

@@ -468,4 +468,22 @@ void Px3Body::findContact(SceneObject **contactObject,
       }
    }
 
-}
+}void Px3Body::moveKinematicTo(const MatrixF &transform)
+{
+   AssertFatal(mActor, "Px3Body::moveKinematicTo - The actor is null!");
+
+   const bool isKinematic = mBodyFlags & BF_KINEMATIC;
+   if (!isKinematic)
+   {
+      Con::errorf("Px3Body::moveKinematicTo is only for kinematic bodies.");
+      return;
+   }
+
+   mWorld->lockScene();
+
+   physx::PxRigidDynamic *actor = mActor->is<physx::PxRigidDynamic>();
+   actor->setKinematicTarget(px3Cast<physx::PxTransform>(transform));
+
+   mWorld->unlockScene();
+}
+

+ 2 - 0
Engine/source/T3D/physics/physx3/px3Body.h

@@ -120,6 +120,8 @@ public:
 
    virtual void findContact(SceneObject **contactObject, VectorF *contactNormal,
       Vector<SceneObject*> *outOverlapObjects) const;
+   virtual void moveKinematicTo(const MatrixF &xfm);
+
 };
 
 #endif // _PX3BODY_H_

+ 30 - 0
Engine/source/T3D/physics/physx3/px3Player.cpp

@@ -329,3 +329,33 @@ Box3F Px3Player::getWorldBounds()
    return px3Cast<Box3F>( bounds );
 }
 
+bool Px3Player::testSpacials(const Point3F &nPos, const Point3F &nSize) const
+{
+   F32 offset = nSize.z * 0.5f;
+   F32 radius = getMax(nSize.x, nSize.y) * 0.5f - mSkinWidth;
+   F32 height = (nSize.z - (radius * 2.0f)) * 0.5f;
+   height -= mSkinWidth * 2.0f;
+   physx::PxCapsuleGeometry geom(radius, height);
+
+   physx::PxVec3 pos(nPos.x, nPos.y, nPos.z + offset);
+   physx::PxQuat orientation(Float_HalfPi, physx::PxVec3(0.0f, 1.0f, 0.0f));
+
+   physx::PxOverlapBuffer hit;
+   physx::PxQueryFilterData queryFilter(physx::PxQueryFlag::eANY_HIT | physx::PxQueryFlag::eSTATIC | physx::PxQueryFlag::eDYNAMIC);
+   queryFilter.data.word0 = PX3_DEFAULT;
+   bool hasHit = mWorld->getScene()->overlap(geom, physx::PxTransform(pos, orientation), hit, queryFilter);
+
+   return !hasHit;   // Return true if there are no overlapping objects
+}
+
+void Px3Player::setSpacials(const Point3F &nPos, const Point3F &nSize)
+{
+   mOriginOffset = nSize.z * 0.5f;
+   F32 radius = getMax(nSize.x, nSize.y) * 0.5f - mSkinWidth;
+   F32 height = nSize.z - (radius * 2.0f);
+   height -= mSkinWidth * 2.0f;
+
+   mWorld->releaseWriteLock();
+   mController->resize(height);
+   px3GetFirstShape(mController->getActor())->getCapsuleGeometry(mGeometry);
+}

+ 2 - 2
Engine/source/T3D/physics/physx3/px3Player.h

@@ -94,8 +94,8 @@ public:
                         PhysicsWorld *world );
    virtual Point3F move( const VectorF &displacement, CollisionList &outCol );
    virtual void findContact( SceneObject **contactObject, VectorF *contactNormal, Vector<SceneObject*> *outOverlapObjects ) const;
-   virtual bool testSpacials( const Point3F &nPos, const Point3F &nSize ) const { return true; }
-   virtual void setSpacials( const Point3F &nPos, const Point3F &nSize ) {}
+   virtual bool testSpacials( const Point3F &nPos, const Point3F &nSize ) const;
+   virtual void setSpacials( const Point3F &nPos, const Point3F &nSize );
    virtual void enableCollision();
    virtual void disableCollision();
 };

+ 58 - 1
Engine/source/T3D/physics/physx3/px3World.cpp

@@ -62,7 +62,8 @@ Px3World::Px3World(): mScene( NULL ),
    mIsEnabled( false ),
    mEditorTimeScale( 1.0f ),
    mAccumulator( 0 ),
-   mControllerManager( NULL )
+   mControllerManager(NULL),
+   mIsSceneLocked(false)
 {
 }
 
@@ -335,6 +336,62 @@ void Px3World::releaseWriteLock()
 	//AssertFatal( mScene->isWritable(), "PhysX3World::releaseWriteLock() - We should have been writable now!" );
 }
 
+void Px3World::lockScenes()
+{
+   Px3World *world = dynamic_cast<Px3World*>(PHYSICSMGR->getWorld("server"));
+
+   if (world)
+      world->lockScene();
+
+   world = dynamic_cast<Px3World*>(PHYSICSMGR->getWorld("client"));
+
+   if (world)
+      world->lockScene();
+}
+
+void Px3World::unlockScenes()
+{
+   Px3World *world = dynamic_cast<Px3World*>(PHYSICSMGR->getWorld("server"));
+
+   if (world)
+      world->unlockScene();
+
+   world = dynamic_cast<Px3World*>(PHYSICSMGR->getWorld("client"));
+
+   if (world)
+      world->unlockScene();
+}
+
+void Px3World::lockScene()
+{
+   if (!mScene)
+      return;
+
+   if (mIsSceneLocked)
+   {
+      Con::printf("Px3World: Attempting to lock a scene that is already locked.");
+      return;
+   }
+
+   mScene->lockWrite();
+   mIsSceneLocked = true;
+}
+
+void Px3World::unlockScene()
+{
+   if (!mScene)
+      return;
+
+   if (!mIsSceneLocked)
+   {
+      Con::printf("Px3World: Attempting to unlock a scene that is not locked.");
+      return;
+   }
+
+   mScene->unlockWrite();
+   mIsSceneLocked = false;
+}
+
 bool Px3World::castRay( const Point3F &startPnt, const Point3F &endPnt, RayInfo *ri, const Point3F &impulse )
 {
     

+ 5 - 0
Engine/source/T3D/physics/physx3/px3World.h

@@ -56,6 +56,7 @@ protected:
 	bool mIsEnabled;
 	bool mIsSimulating;
 	bool mIsServer;
+   bool mIsSceneLocked;
 	U32 mTickCount;
 	ProcessList *mProcessList;
 	F32 mEditorTimeScale;
@@ -96,11 +97,15 @@ public:
 	void releaseWriteLock();
 	bool isServer(){return mIsServer;}
 	physx::PxController* createController( physx::PxControllerDesc &desc );
+   void lockScene();
+   void unlockScene();
 	//static
 	static bool restartSDK( bool destroyOnly = false, Px3World *clientWorld = NULL, Px3World *serverWorld = NULL );
 	static void releaseWriteLocks();
 	static physx::PxCooking *getCooking();
    static void setTiming(F32 stepTime,U32 maxIterations);
+   static void lockScenes();
+   static void unlockScenes();
 };
 
 #endif // _PX3WORLD_H_

+ 42 - 1
Engine/source/T3D/vehicles/vehicle.cpp

@@ -46,6 +46,9 @@
 #include "gfx/primBuilder.h"
 #include "gfx/gfxDrawUtil.h"
 #include "materials/materialDefinition.h"
+#include "T3D/physics/physicsPlugin.h"
+#include "T3D/physics/physicsBody.h"
+#include "T3D/physics/physicsCollision.h"
 
 
 namespace {
@@ -203,7 +206,8 @@ VehicleData::VehicleData()
    dMemset(waterSound, 0, sizeof(waterSound));
 
    collDamageThresholdVel = 20;
-   collDamageMultiplier   = 0.05f;
+   collDamageMultiplier = 0.05f;
+   enablePhysicsRep = true;
 }
 
 
@@ -315,6 +319,7 @@ void VehicleData::packData(BitStream* stream)
    stream->write(softSplashSoundVel);
    stream->write(medSplashSoundVel);
    stream->write(hardSplashSoundVel);
+   stream->write(enablePhysicsRep);
 
    // write the water sound profiles
    for(i = 0; i < MaxSounds; i++)
@@ -411,6 +416,7 @@ void VehicleData::unpackData(BitStream* stream)
    stream->read(&softSplashSoundVel);
    stream->read(&medSplashSoundVel);
    stream->read(&hardSplashSoundVel);
+   stream->read(&enablePhysicsRep);
 
    // write the water sound profiles
    for(i = 0; i < MaxSounds; i++)
@@ -465,6 +471,11 @@ void VehicleData::unpackData(BitStream* stream)
 
 void VehicleData::initPersistFields()
 {
+   addGroup("Physics");
+   addField("enablePhysicsRep", TypeBool, Offset(enablePhysicsRep, VehicleData),
+      "@brief Creates a representation of the object in the physics plugin.\n");
+   endGroup("Physics");
+
    addField( "jetForce", TypeF32, Offset(jetForce, VehicleData),
       "@brief Additional force applied to the vehicle when it is jetting.\n\n"
       "For WheeledVehicles, the force is applied in the forward direction. For "
@@ -682,6 +693,8 @@ Vehicle::Vehicle()
    mWorkingQueryBox.minExtents.set(-1e9f, -1e9f, -1e9f);
    mWorkingQueryBox.maxExtents.set(-1e9f, -1e9f, -1e9f);
    mWorkingQueryBoxCountDown = sWorkingQueryBoxStaleThreshold;
+
+   mPhysicsRep = NULL;
 }
 
 U32 Vehicle::getCollisionMask()
@@ -695,6 +708,25 @@ Point3F Vehicle::getVelocity() const
    return mRigid.linVelocity;
 }
 
+void Vehicle::_createPhysics()
+{
+   SAFE_DELETE(mPhysicsRep);
+
+   if (!PHYSICSMGR || !mDataBlock->enablePhysicsRep)
+      return;
+
+   TSShape *shape = mShapeInstance->getShape();
+   PhysicsCollision *colShape = NULL;
+   colShape = shape->buildColShape(false, getScale());
+
+   if (colShape)
+   {
+      PhysicsWorld *world = PHYSICSMGR->getWorld(isServerObject() ? "server" : "client");
+      mPhysicsRep = PHYSICSMGR->createBody();
+      mPhysicsRep->init(colShape, 0, PhysicsBody::BF_KINEMATIC, this, world);
+      mPhysicsRep->setTransform(getTransform());
+   }
+}
 //----------------------------------------------------------------------------
 
 bool Vehicle::onAdd()
@@ -776,11 +808,15 @@ bool Vehicle::onAdd()
    mConvex.box.maxExtents.convolve(mObjScale);
    mConvex.findNodeTransform();
 
+   _createPhysics();
+
    return true;
 }
 
 void Vehicle::onRemove()
 {
+   SAFE_DELETE(mPhysicsRep);
+
    U32 i=0;
    for( i=0; i<VehicleData::VC_NUM_DUST_EMITTERS; i++ )
    {
@@ -880,6 +916,11 @@ void Vehicle::processTick(const Move* move)
       setPosition(mRigid.linPosition, mRigid.angPosition);
       setMaskBits(PositionMask);
       updateContainer();
+
+      //TODO: Only update when position has actually changed
+      //no need to check if mDataBlock->enablePhysicsRep is false as mPhysicsRep will be NULL if it is
+      if (mPhysicsRep)
+         mPhysicsRep->moveKinematicTo(getTransform());
    }
 }
 

+ 7 - 0
Engine/source/T3D/vehicles/vehicle.h

@@ -127,6 +127,8 @@ struct VehicleData: public ShapeBaseData
    F32 splashFreqMod;
    F32 splashVelEpsilon;
 
+   bool enablePhysicsRep;
+
    //
    VehicleData();
    bool preload(bool server, String &errorStr);
@@ -142,6 +144,7 @@ struct VehicleData: public ShapeBaseData
 
 
 //----------------------------------------------------------------------------
+class PhysicsBody;
 
 class Vehicle: public ShapeBase
 {
@@ -177,6 +180,8 @@ class Vehicle: public ShapeBase
       Point3F cameraRotVec;
    };
 
+   PhysicsBody *mPhysicsRep;
+
    StateDelta mDelta;
    S32 mPredictionCount;            ///< Number of ticks to predict
    VehicleData* mDataBlock;
@@ -262,6 +267,8 @@ public:
    bool onAdd();
    void onRemove();
 
+   void _createPhysics();
+
    /// Interpolates between move ticks @see processTick
    /// @param   dt   Change in time between the last call and this call to the function
    void interpolateTick(F32 dt);

+ 1 - 1
Engine/source/materials/materialFeatureTypes.cpp

@@ -30,7 +30,6 @@ ImplementFeatureType( MFT_VertTransform, MFG_Transform, 0, true );
 
 ImplementFeatureType( MFT_TexAnim, MFG_PreTexture, 1.0f, true );
 ImplementFeatureType( MFT_Parallax, MFG_PreTexture, 2.0f, true );
-ImplementFeatureType( MFT_DiffuseVertColor, MFG_PreTexture, 3.0f, true );
 
 ImplementFeatureType( MFT_AccuScale, MFG_PreTexture, 4.0f, true );
 ImplementFeatureType( MFT_AccuDirection, MFG_PreTexture, 4.0f, true );
@@ -42,6 +41,7 @@ ImplementFeatureType( MFT_DiffuseMap, MFG_Texture, 2.0f, true );
 ImplementFeatureType( MFT_OverlayMap, MFG_Texture, 3.0f, true );
 ImplementFeatureType( MFT_DetailMap, MFG_Texture, 4.0f, true );
 ImplementFeatureType( MFT_DiffuseColor, MFG_Texture, 5.0f, true );
+ImplementFeatureType( MFT_DiffuseVertColor, MFG_Texture, 6.0f, true );
 ImplementFeatureType( MFT_AlphaTest, MFG_Texture, 7.0f, true );
 ImplementFeatureType( MFT_SpecularMap, MFG_Texture, 8.0f, true );
 ImplementFeatureType( MFT_NormalMap, MFG_Texture, 9.0f, true );

+ 2 - 1
Engine/source/materials/processedShaderMaterial.cpp

@@ -1153,7 +1153,8 @@ void ProcessedShaderMaterial::_setShaderConstants(SceneRenderState * state, cons
 
    // Deferred Shading: Determine Material Info Flags
    S32 matInfoFlags = 
-            (mMaterial->mEmissive[stageNum] ? 1 : 0);
+            (mMaterial->mEmissive[stageNum] ? 1 : 0) | //emissive
+            (mMaterial->mSubSurface[stageNum] ? 2 : 0); //subsurface
    mMaterial->mMatInfoFlags[stageNum] = matInfoFlags / 255.0f;
    shaderConsts->setSafe(handles->mMatInfoFlagsSC, mMaterial->mMatInfoFlags[stageNum]);   
    if( handles->mAccuScaleSC->isValid() )

+ 13 - 1
Engine/source/navigation/navMesh.cpp

@@ -145,6 +145,17 @@ DefineConsoleFunction(NavMeshUpdateAroundObject, void, (S32 objid, bool remove),
       obj->enableCollision();
 }
 
+
+DefineConsoleFunction(NavMeshIgnore, void, (S32 objid, bool _ignore), (0, true),
+   "@brief Flag this object as not generating a navmesh result.")
+{
+   SceneObject *obj;
+   if(!Sim::findObject(objid, obj))
+      return;
+
+      obj->mPathfindingIgnore = _ignore;
+}
+
 DefineConsoleFunction(NavMeshUpdateOne, void, (S32 meshid, S32 objid, bool remove), (0, 0, false),
    "@brief Update all tiles in a given NavMesh that intersect the given object's world box.")
 {
@@ -839,6 +850,7 @@ void NavMesh::buildNextTile()
 static void buildCallback(SceneObject* object,void *key)
 {
    SceneContainer::CallbackInfo* info = reinterpret_cast<SceneContainer::CallbackInfo*>(key);
+   if (!object->mPathfindingIgnore)
    object->buildPolyList(info->context,info->polyList,info->boundingBox,info->boundingSphere);
 }
 
@@ -861,7 +873,7 @@ unsigned char *NavMesh::buildTileData(const Tile &tile, TileData &data, U32 &dat
    data.geom.clear();
    info.polyList = &data.geom;
    info.key = this;
-   getContainer()->findObjects(box, StaticShapeObjectType | TerrainObjectType, buildCallback, &info);
+   getContainer()->findObjects(box, StaticObjectType | DynamicShapeObjectType, buildCallback, &info);
 
    // Parse water objects into the same list, but remember how much geometry was /not/ water.
    U32 nonWaterVertCount = data.geom.getVertCount();

+ 1 - 0
Engine/source/scene/sceneObject.cpp

@@ -144,6 +144,7 @@ SceneObject::SceneObject()
    mIsScopeAlways = false;
 
    mAccuTex = NULL;
+   mPathfindingIgnore = false;
 }
 
 //-----------------------------------------------------------------------------

+ 1 - 0
Engine/source/scene/sceneObject.h

@@ -371,6 +371,7 @@ class SceneObject : public NetObject, private SceneContainer::Link, public Proce
 
       SceneObject();
       virtual ~SceneObject();
+      bool mPathfindingIgnore;
 
       /// Triggered when a SceneObject onAdd is called.
       static Signal< void( SceneObject* ) > smSceneObjectAdd;

+ 4 - 1
Engine/source/shaderGen/GLSL/shaderFeatureGLSL.cpp

@@ -1194,7 +1194,10 @@ void DiffuseVertColorFeatureGLSL::processPix(   Vector<ShaderComponent*> &compon
    }
    
    MultiLine* meta = new MultiLine;
-   meta->addStatement( new GenOp( "   @;\r\n", assignColor( vertColor, Material::Mul ) ) );
+   if (fd.features[MFT_isDeferred])
+      meta->addStatement(new GenOp("   @;\r\n", assignColor(vertColor, Material::Mul, NULL, ShaderFeature::RenderTarget1)));
+   else
+      meta->addStatement(new GenOp("   @;\r\n", assignColor(vertColor, Material::Mul)));
    output = meta;
 }
 

+ 4 - 1
Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp

@@ -1258,7 +1258,10 @@ void DiffuseVertColorFeatureHLSL::processPix(   Vector<ShaderComponent*> &compon
    }
    
    MultiLine* meta = new MultiLine;
-   meta->addStatement( new GenOp( "   @;\r\n", assignColor( vertColor, Material::Mul ) ) );
+   if (fd.features[MFT_isDeferred])
+      meta->addStatement(new GenOp("   @;\r\n", assignColor(vertColor, Material::Mul, NULL, ShaderFeature::RenderTarget1)));
+   else
+      meta->addStatement(new GenOp("   @;\r\n", assignColor(vertColor, Material::Mul)));
    output = meta;
 }
 

+ 0 - 3
Templates/Empty/game/tools/materialEditor/scripts/materialEditor.ed.cs

@@ -918,9 +918,6 @@ function MaterialEditorGui::guiSync( %this, %material )
    MaterialEditorPropertiesWindow-->vertLitCheckbox.setValue((%material).vertLit[%layer]);
    MaterialEditorPropertiesWindow-->vertColorSwatch.color = (%material).vertColor[%layer];
    MaterialEditorPropertiesWindow-->subSurfaceCheckbox.setValue((%material).subSurface[%layer]);
-   MaterialEditorPropertiesWindow-->subSurfaceColorSwatch.color = (%material).subSurfaceColor[%layer];
-   MaterialEditorPropertiesWindow-->subSurfaceRolloffTextEdit.setText((%material).subSurfaceRolloff[%layer]);
-   MaterialEditorPropertiesWindow-->minnaertTextEdit.setText((%material).minnaertConstant[%layer]);
 
    // Animation properties
    MaterialEditorPropertiesWindow-->RotationAnimation.setValue(0);

+ 3 - 1
Templates/Empty/game/tools/shapeEditor/scripts/shapeEditor.ed.cs

@@ -380,7 +380,8 @@ function ShapeEdSelectWindow::navigate( %this, %address )
 
       // Ignore assets in the tools folder
       %fullPath = makeRelativePath( %fullPath, getMainDotCSDir() );
-      %splitPath = strreplace( %fullPath, "/", " " );
+      %splitPath = strreplace( %fullPath, " ", "_" );
+      %splitPath = strreplace( %splitPath, "/", " " );
       if ( getWord( %splitPath, 0 ) $= "tools" )
       {
          %fullPath = findNextFileMultiExpr( %filePatterns );
@@ -393,6 +394,7 @@ function ShapeEdSelectWindow::navigate( %this, %address )
       // Add this file's path ( parent folders ) to the
       // popup menu if it isn't there yet.
       %temp = strreplace( %pathFolders, " ", "/" );
+      %temp = strreplace( %temp, "_", " " );
       %r = ShapeEdSelectMenu.findText( %temp );
       if ( %r == -1 )
          ShapeEdSelectMenu.add( %temp );

+ 6 - 2
Templates/Empty/game/tools/worldEditor/scripts/editors/creator.ed.cs

@@ -318,7 +318,8 @@ function EWCreatorWindow::navigate( %this, %address )
          }
 
          %fullPath = makeRelativePath( %fullPath, getMainDotCSDir() );                                  
-         %splitPath = strreplace( %fullPath, "/", " " );     
+         %splitPath = strreplace( %fullPath, " ", "_" );
+         %splitPath = strreplace( %splitPath, "/", " " );    
          if( getWord(%splitPath, 0) $= "tools" )
          {
             %fullPath = findNextFileMultiExpr( getFormatExtensions() );
@@ -332,6 +333,7 @@ function EWCreatorWindow::navigate( %this, %address )
          // Add this file's path (parent folders) to the
          // popup menu if it isn't there yet.
          %temp = strreplace( %pathFolders, " ", "/" );         
+         %temp = strreplace( %temp, "_", " " );
          %r = CreatorPopupMenu.findText( %temp );
          if ( %r == -1 )
          {
@@ -430,7 +432,8 @@ function EWCreatorWindow::navigate( %this, %address )
       while ( %fullPath !$= "" )
       {         
          %fullPath = makeRelativePath( %fullPath, getMainDotCSDir() );                                  
-         %splitPath = strreplace( %fullPath, "/", " " );     
+         %splitPath = strreplace( %fullPath, " ", "_" );
+         %splitPath = strreplace( %splitPath, "/", " " );
          if( getWord(%splitPath, 0) $= "tools" )
          {
             %fullPath = findNextFile( %expr );
@@ -444,6 +447,7 @@ function EWCreatorWindow::navigate( %this, %address )
          // Add this file's path (parent folders) to the
          // popup menu if it isn't there yet.
          %temp = strreplace( %pathFolders, " ", "/" );         
+         %temp = strreplace( %temp, "_", " " );
          %r = CreatorPopupMenu.findText( %temp );
          if ( %r == -1 )
          {

+ 6 - 1
Templates/Full/game/scripts/client/default.bind.cs

@@ -618,7 +618,12 @@ GlobalActionMap.bind(keyboard, "ctrl o", bringUpOptions);
 function showMetrics(%val)
 {
    if(%val)
-      metrics("fps gfx shadow sfx terrain groundcover forest net");
+   {
+      if(!Canvas.isMember(FrameOverlayGui))
+         metrics("fps gfx shadow sfx terrain groundcover forest net");
+      else
+         metrics("");
+   }
 }
 GlobalActionMap.bind(keyboard, "ctrl F2", showMetrics);
 

+ 12 - 2
Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl

@@ -147,6 +147,17 @@ void main()
 	   return;
    }
 
+   vec4 colorSample = texture( colorBuffer, uvScene );
+   vec3 subsurface = vec3(0.0,0.0,0.0); 
+   if (getFlag( matInfo.r, 1 ))
+   {
+      subsurface = colorSample.rgb;
+      if (colorSample.r>colorSample.g)
+         subsurface = vec3(0.772549, 0.337255, 0.262745);
+	  else
+         subsurface = vec3(0.337255, 0.772549, 0.262745);
+	}
+	
    // Sample/unpack the normal/z data
    vec4 prepassSample = prepassUncondition( prePassBuffer, uvScene );
    vec3 normal = prepassSample.rgb;
@@ -258,6 +269,5 @@ void main()
       addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
    }
 
-   vec4 colorSample = texture( colorBuffer, uvScene );
-   OUT_col = AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
+   OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
 }

+ 12 - 2
Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl

@@ -89,6 +89,17 @@ void main()
 	   return;
    }
    
+   vec4 colorSample = texture( colorBuffer, uvScene );
+   vec3 subsurface = vec3(0.0,0.0,0.0); 
+   if (getFlag( matInfo.r, 1 ))
+   {
+      subsurface = colorSample.rgb;
+      if (colorSample.r>colorSample.g)
+         subsurface = vec3(0.772549, 0.337255, 0.262745);
+	  else
+         subsurface = vec3(0.337255, 0.772549, 0.262745);
+	}
+	
    // Sample/unpack the normal/z data
    vec4 prepassSample = prepassUncondition( prePassBuffer, uvScene );
    vec3 normal = prepassSample.rgb;
@@ -195,6 +206,5 @@ void main()
       addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
    }
 
-   vec4 colorSample = texture( colorBuffer, uvScene );
-   OUT_col = AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
+   OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
 }

+ 12 - 2
Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl

@@ -202,6 +202,17 @@ void main()
        return;
    }
    
+   vec4 colorSample = texture( colorBuffer, uv0 );
+   vec3 subsurface = vec3(0.0,0.0,0.0); 
+   if (getFlag( matInfo.r, 1 ))
+   {
+      subsurface = colorSample.rgb;
+      if (colorSample.r>colorSample.g)
+         subsurface = vec3(0.772549, 0.337255, 0.262745);
+	  else
+         subsurface = vec3(0.337255, 0.772549, 0.262745);
+	}
+	
    // Sample/unpack the normal/z data
    vec4 prepassSample = prepassUncondition( prePassBuffer, uv0 );
    vec3 normal = prepassSample.rgb;
@@ -312,6 +323,5 @@ void main()
       lightColorOut = debugColor;
    #endif
 
-   vec4 colorSample = texture( colorBuffer, uv0 );
-   OUT_col = AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); 
+   OUT_col = AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att); 
 }

+ 11 - 2
Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl

@@ -149,6 +149,16 @@ float4 main( ConvexConnectP IN ) : TORQUE_TARGET0
    {
        return float4(0.0, 0.0, 0.0, 0.0);
    }
+   float4 colorSample = TORQUE_TEX2D( colorBuffer, uvScene );
+   float3 subsurface = float3(0.0,0.0,0.0); 
+   if (getFlag( matInfo.r, 1 ))
+   {
+      subsurface = colorSample.rgb;
+      if (colorSample.r>colorSample.g)
+         subsurface = float3(0.772549, 0.337255, 0.262745);
+	  else
+         subsurface = float3(0.337255, 0.772549, 0.262745);
+	}
    
    // Sample/unpack the normal/z data
    float4 prepassSample = TORQUE_PREPASS_UNCONDITION( prePassBuffer, uvScene );
@@ -263,6 +273,5 @@ float4 main( ConvexConnectP IN ) : TORQUE_TARGET0
       addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
    }
 
-   float4 colorSample = TORQUE_TEX2D( colorBuffer, uvScene );
-   return AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
+   return AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
 }

+ 12 - 2
Templates/Full/game/shaders/common/lighting/advanced/spotLightP.hlsl

@@ -87,6 +87,17 @@ float4 main(   ConvexConnectP IN ) : TORQUE_TARGET0
        return float4(0.0, 0.0, 0.0, 0.0);
    }
 
+   float4 colorSample = TORQUE_TEX2D( colorBuffer, uvScene );
+   float3 subsurface = float3(0.0,0.0,0.0); 
+   if (getFlag( matInfo.r, 1 ))
+   {
+      subsurface = colorSample.rgb;
+      if (colorSample.r>colorSample.g)
+         subsurface = float3(0.772549, 0.337255, 0.262745);
+	  else
+         subsurface = float3(0.337255, 0.772549, 0.262745);
+	}
+	
    // Sample/unpack the normal/z data
    float4 prepassSample = TORQUE_PREPASS_UNCONDITION( prePassBuffer, uvScene );
    float3 normal = prepassSample.rgb;
@@ -194,6 +205,5 @@ float4 main(   ConvexConnectP IN ) : TORQUE_TARGET0
       addToResult = ( 1.0 - shadowed ) * abs(lightMapParams);
    }
 
-   float4 colorSample = TORQUE_TEX2D( colorBuffer, uvScene );
-   return AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
+   return AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
 }

+ 11 - 2
Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl

@@ -202,6 +202,16 @@ float4 main( FarFrustumQuadConnectP IN ) : TORQUE_TARGET0
        return float4(1.0, 1.0, 1.0, 0.0);
    }
    
+   float4 colorSample = TORQUE_TEX2D( colorBuffer, IN.uv0 );
+   float3 subsurface = float3(0.0,0.0,0.0); 
+   if (getFlag( matInfo.r, 1 ))
+   {
+      subsurface = colorSample.rgb;
+      if (colorSample.r>colorSample.g)
+         subsurface = float3(0.772549, 0.337255, 0.262745);
+	  else
+         subsurface = float3(0.337255, 0.772549, 0.262745);
+	}
    // Sample/unpack the normal/z data
    float4 prepassSample = TORQUE_PREPASS_UNCONDITION( prePassBuffer, IN.uv0 );
    float3 normal = prepassSample.rgb;
@@ -314,6 +324,5 @@ float4 main( FarFrustumQuadConnectP IN ) : TORQUE_TARGET0
       lightColorOut = debugColor;
    #endif
 
-   float4 colorSample = TORQUE_TEX2D( colorBuffer, IN.uv0 );
-   return AL_DeferredOutput(lightColorOut, colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
+   return AL_DeferredOutput(lightColorOut+subsurface*(1.0-Sat_NL_Att), colorSample.rgb, matInfo, addToResult, specular, Sat_NL_Att);
 }

+ 23 - 0
Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui

@@ -2240,6 +2240,29 @@
                            useMouseEvents = "0";
                            useInactiveState = "0";
                         };
+                        new GuiCheckBoxCtrl() {
+                           canSaveDynamicFields = "0";
+                           internalName = "subSurfaceCheckbox";
+                           Enabled = "1";
+                           isContainer = "0";
+                           Profile = "ToolsGuiCheckBoxProfile";
+                           HorizSizing = "right";
+                           VertSizing = "bottom";
+                           position = "8 46";
+                           Extent = "79 16";
+                           MinExtent = "8 2";
+                           canSave = "1";
+                           Visible = "1";
+                           Command = "MaterialEditorGui.updateActiveMaterial(\"subSurface[\" @ MaterialEditorGui.currentLayer @ \"]\", $ThisControl.getValue());";
+                           tooltipprofile = "ToolsGuiDefaultProfile";
+                           ToolTip = "Enables the use of subsurface scattering for this layer.";
+                           hovertime = "1000";
+                           text = "Sub Surface";
+                           groupNum = "-1";
+                           buttonType = "ToggleButton";
+                           useMouseEvents = "0";
+                           useInactiveState = "0";
+                        };
                      };
                   };
                };

+ 0 - 3
Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs

@@ -918,9 +918,6 @@ function MaterialEditorGui::guiSync( %this, %material )
    MaterialEditorPropertiesWindow-->vertLitCheckbox.setValue((%material).vertLit[%layer]);
    MaterialEditorPropertiesWindow-->vertColorSwatch.color = (%material).vertColor[%layer];
    MaterialEditorPropertiesWindow-->subSurfaceCheckbox.setValue((%material).subSurface[%layer]);
-   MaterialEditorPropertiesWindow-->subSurfaceColorSwatch.color = (%material).subSurfaceColor[%layer];
-   MaterialEditorPropertiesWindow-->subSurfaceRolloffTextEdit.setText((%material).subSurfaceRolloff[%layer]);
-   MaterialEditorPropertiesWindow-->minnaertTextEdit.setText((%material).minnaertConstant[%layer]);
 
    // Animation properties
    MaterialEditorPropertiesWindow-->RotationAnimation.setValue(0);

+ 3 - 1
Templates/Full/game/tools/shapeEditor/scripts/shapeEditor.ed.cs

@@ -380,7 +380,8 @@ function ShapeEdSelectWindow::navigate( %this, %address )
 
       // Ignore assets in the tools folder
       %fullPath = makeRelativePath( %fullPath, getMainDotCSDir() );
-      %splitPath = strreplace( %fullPath, "/", " " );
+      %splitPath = strreplace( %fullPath, " ", "_" );
+      %splitPath = strreplace( %splitPath, "/", " " );
       if ( getWord( %splitPath, 0 ) $= "tools" )
       {
          %fullPath = findNextFileMultiExpr( %filePatterns );
@@ -393,6 +394,7 @@ function ShapeEdSelectWindow::navigate( %this, %address )
       // Add this file's path ( parent folders ) to the
       // popup menu if it isn't there yet.
       %temp = strreplace( %pathFolders, " ", "/" );
+      %temp = strreplace( %temp, "_", " " );
       %r = ShapeEdSelectMenu.findText( %temp );
       if ( %r == -1 )
          ShapeEdSelectMenu.add( %temp );

+ 6 - 2
Templates/Full/game/tools/worldEditor/scripts/editors/creator.ed.cs

@@ -349,7 +349,8 @@ function EWCreatorWindow::navigate( %this, %address )
          }
 
          %fullPath = makeRelativePath( %fullPath, getMainDotCSDir() );                                  
-         %splitPath = strreplace( %fullPath, "/", " " );     
+         %splitPath = strreplace( %fullPath, " ", "_" );
+         %splitPath = strreplace( %splitPath, "/", " " );
          if( getWord(%splitPath, 0) $= "tools" )
          {
             %fullPath = findNextFileMultiExpr( getFormatExtensions() );
@@ -363,6 +364,7 @@ function EWCreatorWindow::navigate( %this, %address )
          // Add this file's path (parent folders) to the
          // popup menu if it isn't there yet.
          %temp = strreplace( %pathFolders, " ", "/" );         
+         %temp = strreplace( %temp, "_", " " );
          %r = CreatorPopupMenu.findText( %temp );
          if ( %r == -1 )
          {
@@ -461,7 +463,8 @@ function EWCreatorWindow::navigate( %this, %address )
       while ( %fullPath !$= "" )
       {         
          %fullPath = makeRelativePath( %fullPath, getMainDotCSDir() );                                  
-         %splitPath = strreplace( %fullPath, "/", " " );     
+         %splitPath = strreplace( %fullPath, " ", "_" );
+         %splitPath = strreplace( %splitPath, "/", " " );
          if( getWord(%splitPath, 0) $= "tools" )
          {
             %fullPath = findNextFile( %expr );
@@ -475,6 +478,7 @@ function EWCreatorWindow::navigate( %this, %address )
          // Add this file's path (parent folders) to the
          // popup menu if it isn't there yet.
          %temp = strreplace( %pathFolders, " ", "/" );         
+         %temp = strreplace( %temp, "_", " " );
          %r = CreatorPopupMenu.findText( %temp );
          if ( %r == -1 )
          {

+ 1 - 0
Templates/Full/game/tools/worldEditor/scripts/menus.ed.cs

@@ -262,6 +262,7 @@ function EditorGui::buildMenus(%this)
       barTitle = "Tools";
          
       item[0] = "Network Graph" TAB "n" TAB "toggleNetGraph();";
+      item[1] = "Profiler" TAB "ctrl F2" TAB "showMetrics(true);";
    };
    %this.menuBar.insert(%toolsMenu, %this.menuBar.getCount());
       

+ 1 - 1
Tools/CMake/torque3d.cmake

@@ -362,7 +362,7 @@ if(TORQUE_TOOLS)
     addPath("${srcDir}/forest/editor")
     addPath("${srcDir}/gui/editor")
     if(NOT TORQUE_EXPERIMENTAL_EC) 
-        set(BLACKLIST "entityGroup.cpp;entityGroup.h;mountingGroup.cpp;mountingGroup.h" )
+        set(BLACKLIST "entityGroup.cpp;entityGroup.h;mountingGroup.cpp;mountingGroup.h;componentGroup.cpp;componentGroup.h" )
     endif()
     addPath("${srcDir}/gui/editor/inspector")
     set(BLACKLIST "" )