Explorar o código

Merge remote-tracking branch 'refs/remotes/origin/development' into pr/1334

# Conflicts resolved:
#	Engine/source/console/consoleFunctions.cpp
Anis A. Hireche %!s(int64=9) %!d(string=hai) anos
pai
achega
b3662d801a
Modificáronse 42 ficheiros con 606 adicións e 115 borrados
  1. 40 0
      Engine/source/T3D/aiPlayer.cpp
  2. 3 1
      Engine/source/T3D/aiPlayer.h
  3. 45 0
      Engine/source/T3D/decal/decalManager.cpp
  4. 3 3
      Engine/source/T3D/fx/fxFoliageReplicator.cpp
  5. 1 1
      Engine/source/T3D/fx/fxShapeReplicator.cpp
  6. 23 12
      Engine/source/T3D/player.cpp
  7. 2 2
      Engine/source/T3D/rigid.cpp
  8. 1 0
      Engine/source/T3D/shapeBase.cpp
  9. 1 0
      Engine/source/T3D/shapeBase.h
  10. 20 0
      Engine/source/app/game.cpp
  11. 86 1
      Engine/source/app/net/tcpObject.cpp
  12. 11 1
      Engine/source/app/net/tcpObject.h
  13. 1 1
      Engine/source/console/codeBlock.cpp
  14. 16 0
      Engine/source/console/consoleFunctions.h
  15. 1 1
      Engine/source/core/idGenerator.h
  16. 9 0
      Engine/source/core/strings/stringFunctions.h
  17. 100 0
      Engine/source/core/util/str.cpp
  18. 1 0
      Engine/source/core/util/str.h
  19. 2 2
      Engine/source/environment/timeOfDay.cpp
  20. 24 4
      Engine/source/gfx/D3D9/gfxD3D9Device.cpp
  21. 4 2
      Engine/source/gfx/D3D9/gfxD3D9Device.h
  22. 1 0
      Engine/source/gfx/D3D9/pc/gfxD3D9PrimitiveBuffer.pc.cpp
  23. 4 2
      Engine/source/gfx/Null/gfxNullDevice.cpp
  24. 4 2
      Engine/source/gfx/Null/gfxNullDevice.h
  25. 1 1
      Engine/source/gfx/bitmap/loaders/bitmapTga.cpp
  26. 4 2
      Engine/source/gfx/gfxDevice.h
  27. 4 3
      Engine/source/gfx/gfxEnums.h
  28. 13 0
      Engine/source/gfx/gfxPrimitiveBuffer.cpp
  29. 2 0
      Engine/source/gfx/gfxPrimitiveBuffer.h
  30. 31 7
      Engine/source/gfx/gl/gfxGLDevice.cpp
  31. 3 2
      Engine/source/gfx/gl/gfxGLDevice.h
  32. 1 0
      Engine/source/gfx/gl/gfxGLEnumTranslate.cpp
  33. 88 0
      Engine/source/math/mathTypes.cpp
  34. 0 18
      Engine/source/platform/platformAssert.cpp
  35. 24 29
      Engine/source/platform/platformAssert.h
  36. 1 1
      Engine/source/platform/platformNet.cpp
  37. 12 4
      Engine/source/platform/profiler.cpp
  38. 10 0
      Engine/source/platform/types.visualc.h
  39. 4 8
      Engine/source/renderInstance/renderParticleMgr.cpp
  40. 2 2
      Engine/source/sim/netGhost.cpp
  41. 1 1
      Engine/source/util/catmullRom.cpp
  42. 2 2
      Engine/source/util/catmullRom.h

+ 40 - 0
Engine/source/T3D/aiPlayer.cpp

@@ -563,6 +563,21 @@ bool AIPlayer::getAIMove(Move *movePtr)
          }
          }
    }
    }
 
 
+   Pose desiredPose = mPose;
+
+   if ( mSwimming )  
+      desiredPose = SwimPose;   
+   else if ( mAiPose == 1 && canCrouch() )   
+      desiredPose = CrouchPose;  
+   else if ( mAiPose == 2 && canProne() )  
+      desiredPose = PronePose;  
+   else if ( mAiPose == 3 && canSprint() )  
+      desiredPose = SprintPose;  
+   else if ( canStand() )  
+      desiredPose = StandPose;  
+  
+   setPose( desiredPose );
+   
    // Replicate the trigger state into the move so that
    // Replicate the trigger state into the move so that
    // triggers can be controlled from scripts.
    // triggers can be controlled from scripts.
    for( U32 i = 0; i < MaxTriggerKeys; i++ )
    for( U32 i = 0; i < MaxTriggerKeys; i++ )
@@ -591,6 +606,16 @@ bool AIPlayer::getAIMove(Move *movePtr)
    return true;
    return true;
 }
 }
 
 
+void AIPlayer::setAiPose( S32 pose )  
+{  
+   mAiPose = pose;  
+}  
+  
+S32 AIPlayer::getAiPose()  
+{  
+   return mAiPose;   
+}
+
 /**
 /**
  * Utility function to throw callbacks. Callbacks always occure
  * Utility function to throw callbacks. Callbacks always occure
  * on the datablock class.
  * on the datablock class.
@@ -1348,3 +1373,18 @@ DefineEngineMethod( AIPlayer, clearMoveTriggers, void, ( ),,
 {
 {
    object->clearMoveTriggers();
    object->clearMoveTriggers();
 }
 }
+
+DefineEngineMethod( AIPlayer, setAiPose, void, ( S32 pose ),,  
+   "@brief Sets the AiPose for an AI object.\n"
+   "@param pose StandPose=0, CrouchPose=1, PronePose=2, SprintPose=3.\n"
+   "Uses the new AiPose variable from shapebase (as defined in its PlayerData datablock).\n")  
+{  
+   object->setAiPose(pose);  
+}  
+  
+DefineEngineMethod( AIPlayer, getAiPose, S32, (),,  
+   "@brief Get the object's current AiPose.\n"
+   "@return StandPose=0, CrouchPose=1, PronePose=2, SprintPose=3.\n")  
+{  
+   return object->getAiPose();  
+}

+ 3 - 1
Engine/source/T3D/aiPlayer.h

@@ -179,7 +179,9 @@ public:
    void setMoveDestination( const Point3F &location, bool slowdown );
    void setMoveDestination( const Point3F &location, bool slowdown );
    Point3F getMoveDestination() const { return mMoveDestination; }
    Point3F getMoveDestination() const { return mMoveDestination; }
    void stopMove();
    void stopMove();
-
+   void setAiPose( S32 pose );
+   S32  getAiPose();
+	
    // Trigger sets/gets
    // Trigger sets/gets
    void setMoveTrigger( U32 slot, const bool isSet = true );
    void setMoveTrigger( U32 slot, const bool isSet = true );
    bool getMoveTrigger( U32 slot ) const;
    bool getMoveTrigger( U32 slot ) const;

+ 45 - 0
Engine/source/T3D/decal/decalManager.cpp

@@ -1744,3 +1744,48 @@ DefineEngineFunction( decalManagerRemoveDecal, bool, ( S32 decalID ),,
    gDecalManager->removeDecal(inst);
    gDecalManager->removeDecal(inst);
    return true;
    return true;
 }
 }
+
+DefineEngineFunction( decalManagerEditDecal, bool, ( S32 decalID, Point3F pos, Point3F normal, F32 rotAroundNormal, F32 decalScale ),,
+   "Edit specified decal of the decal manager.\n"
+   "@param decalID ID of the decal to edit.\n"
+   "@param pos World position for the decal.\n"
+   "@param normal Decal normal vector (if the decal was a tire lying flat on a "
+   "surface, this is the vector pointing in the direction of the axle).\n"
+   "@param rotAroundNormal Angle (in radians) to rotate this decal around its normal vector.\n"
+   "@param decalScale Scale factor applied to the decal.\n"
+   "@return Returns true if successful, false if decalID not found.\n"
+   "" )
+{
+   DecalInstance *decalInstance = gDecalManager->getDecal( decalID );
+   if( !decalInstance )
+		return false;
+
+   //Internally we need Point3F tangent instead of the user friendly F32 rotAroundNormal
+   MatrixF mat( true );
+   MathUtils::getMatrixFromUpVector( normal, &mat );
+
+   AngAxisF rot( normal, rotAroundNormal );
+   MatrixF rotmat;
+   rot.setMatrix( &rotmat );
+   mat.mul( rotmat );
+
+   Point3F tangent;
+   mat.getColumn( 1, &tangent );
+   
+   //if everything is unchanged just do nothing and  return "everything is ok"
+   if ( pos.equal(decalInstance->mPosition) &&
+        normal.equal(decalInstance->mNormal) &&
+        tangent.equal(decalInstance->mTangent) &&
+        mFabs( decalInstance->mSize - (decalInstance->mDataBlock->size * decalScale) ) < POINT_EPSILON )
+           return true;
+
+   decalInstance->mPosition = pos;
+   decalInstance->mNormal = normal;
+   decalInstance->mTangent = tangent;
+   decalInstance->mSize = decalInstance->mDataBlock->size * decalScale;
+
+   gDecalManager->clipDecal( decalInstance, NULL, NULL);
+   
+   gDecalManager->notifyDecalModified( decalInstance );
+   return true;
+}

+ 3 - 3
Engine/source/T3D/fx/fxFoliageReplicator.cpp

@@ -426,7 +426,7 @@ void fxFoliageReplicator::CreateFoliage(void)
    Point3F	MaxPoint(  0.5,  0.5,  0.5 );
    Point3F	MaxPoint(  0.5,  0.5,  0.5 );
 
 
    // Check Host.
    // Check Host.
-   AssertFatal(isClientObject(), "Trying to create Foliage on Server, this is bad!")
+   AssertFatal(isClientObject(), "Trying to create Foliage on Server, this is bad!");
 
 
       // Cannot continue without Foliage Texture!
       // Cannot continue without Foliage Texture!
       if (dStrlen(mFieldData.mFoliageFile) == 0) 
       if (dStrlen(mFieldData.mFoliageFile) == 0) 
@@ -1134,7 +1134,7 @@ void fxFoliageReplicator::ProcessQuadrant(fxFoliageQuadrantNode* pParentNode, fx
 void fxFoliageReplicator::SyncFoliageReplicators(void)
 void fxFoliageReplicator::SyncFoliageReplicators(void)
 {
 {
    // Check Host.
    // Check Host.
-   AssertFatal(isServerObject(), "We *MUST* be on server when Synchronising Foliage!")
+   AssertFatal(isServerObject(), "We *MUST* be on server when Synchronising Foliage!");
 
 
       // Find the Replicator Set.
       // Find the Replicator Set.
    SimSet *fxFoliageSet = dynamic_cast<SimSet*>(Sim::findObject("fxFoliageSet"));
    SimSet *fxFoliageSet = dynamic_cast<SimSet*>(Sim::findObject("fxFoliageSet"));
@@ -1196,7 +1196,7 @@ void fxFoliageReplicator::DestroyFoliageItems()
 void fxFoliageReplicator::DestroyFoliage(void)
 void fxFoliageReplicator::DestroyFoliage(void)
 {
 {
    // Check Host.
    // Check Host.
-   AssertFatal(isClientObject(), "Trying to destroy Foliage on Server, this is bad!")
+   AssertFatal(isClientObject(), "Trying to destroy Foliage on Server, this is bad!");
 
 
       // Destroy Quad-tree.
       // Destroy Quad-tree.
       mPotentialFoliageNodes = 0;
       mPotentialFoliageNodes = 0;

+ 1 - 1
Engine/source/T3D/fx/fxShapeReplicator.cpp

@@ -224,7 +224,7 @@ void fxShapeReplicator::CreateShapes(void)
    }
    }
 
 
    // Check Shapes.
    // Check Shapes.
-   AssertFatal(mCurrentShapeCount==0,"Shapes already present, this should not be possible!")
+   AssertFatal(mCurrentShapeCount==0,"Shapes already present, this should not be possible!");
 
 
       // Check that we have a shape...
       // Check that we have a shape...
       if (!mFieldData.mShapeFile) return;
       if (!mFieldData.mShapeFile) return;

+ 23 - 12
Engine/source/T3D/player.cpp

@@ -3173,18 +3173,21 @@ void Player::updateMove(const Move* move)
    // Update the PlayerPose
    // Update the PlayerPose
    Pose desiredPose = mPose;
    Pose desiredPose = mPose;
 
 
-   if ( mSwimming )
-      desiredPose = SwimPose; 
-   else if ( runSurface && move->trigger[sCrouchTrigger] && canCrouch() )     
-      desiredPose = CrouchPose;
-   else if ( runSurface && move->trigger[sProneTrigger] && canProne() )
-      desiredPose = PronePose;
-   else if ( move->trigger[sSprintTrigger] && canSprint() )
-      desiredPose = SprintPose;
-   else if ( canStand() )
-      desiredPose = StandPose;
+   if ( !mIsAiControlled )
+   {
+      if ( mSwimming )
+         desiredPose = SwimPose; 
+      else if ( runSurface && move->trigger[sCrouchTrigger] && canCrouch() )     
+         desiredPose = CrouchPose;
+      else if ( runSurface && move->trigger[sProneTrigger] && canProne() )
+         desiredPose = PronePose;
+      else if ( move->trigger[sSprintTrigger] && canSprint() )
+         desiredPose = SprintPose;
+      else if ( canStand() )
+         desiredPose = StandPose;
 
 
-   setPose( desiredPose );
+      setPose( desiredPose );
+   }
 }
 }
 
 
 
 
@@ -6186,6 +6189,10 @@ U32 Player::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
    {
    {
       stream->writeFlag(mFalling);
       stream->writeFlag(mFalling);
 
 
+      stream->writeFlag(mSwimming);
+      stream->writeFlag(mJetting);  
+      stream->writeInt(mPose, NumPoseBits);
+	  
       stream->writeInt(mState,NumStateBits);
       stream->writeInt(mState,NumStateBits);
       if (stream->writeFlag(mState == RecoverState))
       if (stream->writeFlag(mState == RecoverState))
          stream->writeInt(mRecoverTicks,PlayerData::RecoverDelayBits);
          stream->writeInt(mRecoverTicks,PlayerData::RecoverDelayBits);
@@ -6282,7 +6289,11 @@ void Player::unpackUpdate(NetConnection *con, BitStream *stream)
    if (stream->readFlag()) {
    if (stream->readFlag()) {
       mPredictionCount = sMaxPredictionTicks;
       mPredictionCount = sMaxPredictionTicks;
       mFalling = stream->readFlag();
       mFalling = stream->readFlag();
-
+ 
+      mSwimming = stream->readFlag();
+      mJetting = stream->readFlag();  
+      mPose = (Pose)(stream->readInt(NumPoseBits)); 
+	  
       ActionState actionState = (ActionState)stream->readInt(NumStateBits);
       ActionState actionState = (ActionState)stream->readInt(NumStateBits);
       if (stream->readFlag()) {
       if (stream->readFlag()) {
          mRecoverTicks = stream->readInt(PlayerData::RecoverDelayBits);
          mRecoverTicks = stream->readInt(PlayerData::RecoverDelayBits);

+ 2 - 2
Engine/source/T3D/rigid.cpp

@@ -156,7 +156,7 @@ bool Rigid::resolveCollision(const Point3F& p, const Point3F &normal, Rigid* rig
       return false;
       return false;
 
 
    // Compute impulse
    // Compute impulse
-   F32 d, n = -nv * (1.0f + restitution * rigid->restitution);
+   F32 d, n = -nv * (2.0f + restitution * rigid->restitution);
    Point3F a1,b1,c1;
    Point3F a1,b1,c1;
    mCross(r1,normal,&a1);
    mCross(r1,normal,&a1);
    invWorldInertia.mulV(a1,&b1);
    invWorldInertia.mulV(a1,&b1);
@@ -173,7 +173,7 @@ bool Rigid::resolveCollision(const Point3F& p, const Point3F &normal, Rigid* rig
 
 
    applyImpulse(r1,impulse);
    applyImpulse(r1,impulse);
    impulse.neg();
    impulse.neg();
-   applyImpulse(r2,impulse);
+   rigid->applyImpulse(r2, impulse);
    return true;
    return true;
 }
 }
 
 

+ 1 - 0
Engine/source/T3D/shapeBase.cpp

@@ -879,6 +879,7 @@ IMPLEMENT_CALLBACK( ShapeBase, validateCameraFov, F32, (F32 fov), (fov),
 ShapeBase::ShapeBase()
 ShapeBase::ShapeBase()
  : mDataBlock( NULL ),
  : mDataBlock( NULL ),
    mIsAiControlled( false ),
    mIsAiControlled( false ),
+   mAiPose( 0 ),
    mControllingObject( NULL ),
    mControllingObject( NULL ),
    mMoveMotion( false ),
    mMoveMotion( false ),
    mShapeBaseMount( NULL ),
    mShapeBaseMount( NULL ),

+ 1 - 0
Engine/source/T3D/shapeBase.h

@@ -874,6 +874,7 @@ protected:
    /// @name Physical Properties
    /// @name Physical Properties
    /// @{
    /// @{
 
 
+   S32 mAiPose;                     ///< Current pose.
    F32 mEnergy;                     ///< Current enery level.
    F32 mEnergy;                     ///< Current enery level.
    F32 mRechargeRate;               ///< Energy recharge rate (in units/tick).
    F32 mRechargeRate;               ///< Energy recharge rate (in units/tick).
 
 

+ 20 - 0
Engine/source/app/game.cpp

@@ -202,6 +202,26 @@ DefineConsoleFunction( getRealTime, S32, (), , "()"
    return Platform::getRealMilliseconds();
    return Platform::getRealMilliseconds();
 }
 }
 
 
+ConsoleFunction( getLocalTime, const char *, 1, 1, "Return the current local time as: weekday month day year hour min sec.\n\n"
+                "Local time is platform defined.")
+{
+   Platform::LocalTime lt;
+   Platform::getLocalTime(lt);
+
+   static const U32 bufSize = 128;
+   char *retBuffer = Con::getReturnBuffer(bufSize);
+   dSprintf(retBuffer, bufSize, "%d %d %d %d %02d %02d %02d",
+      lt.weekday,
+      lt.month + 1,
+      lt.monthday,
+      lt.year + 1900,
+      lt.hour,
+      lt.min,
+      lt.sec);
+
+   return retBuffer;
+}
+
 ConsoleFunctionGroupEnd(Platform);
 ConsoleFunctionGroupEnd(Platform);
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------

+ 86 - 1
Engine/source/app/net/tcpObject.cpp

@@ -27,6 +27,7 @@
 #include "console/consoleInternal.h"
 #include "console/consoleInternal.h"
 #include "core/strings/stringUnit.h"
 #include "core/strings/stringUnit.h"
 #include "console/engineAPI.h"
 #include "console/engineAPI.h"
+#include "core/stream/fileStream.h"
 
 
 TCPObject *TCPObject::table[TCPObject::TableSize] = {0, };
 TCPObject *TCPObject::table[TCPObject::TableSize] = {0, };
 
 
@@ -138,6 +139,15 @@ IMPLEMENT_CALLBACK(TCPObject, onLine, void, (const char* line), (line),
    "@param line Data sent from the server.\n"
    "@param line Data sent from the server.\n"
    );
    );
 
 
+IMPLEMENT_CALLBACK(TCPObject, onPacket, bool, (const char* data), (data),
+   "@brief Called when we get a packet with no newlines or nulls (probably websocket).\n\n"
+   "@param data Data sent from the server.\n"
+   "@return true if script handled the packet.\n"
+   );
+IMPLEMENT_CALLBACK(TCPObject, onEndReceive, void, (), (),
+   "@brief Called when we are done reading all lines.\n\n"
+   );
+
 IMPLEMENT_CALLBACK(TCPObject, onDNSResolved, void, (),(),
 IMPLEMENT_CALLBACK(TCPObject, onDNSResolved, void, (),(),
    "Called whenever the DNS has been resolved.\n"
    "Called whenever the DNS has been resolved.\n"
    );
    );
@@ -355,7 +365,7 @@ void TCPObject::onConnectFailed()
    onConnectFailed_callback();
    onConnectFailed_callback();
 }
 }
 
 
-void TCPObject::finishLastLine()
+bool TCPObject::finishLastLine()
 {
 {
    if(mBufferSize)
    if(mBufferSize)
    {
    {
@@ -364,6 +374,25 @@ void TCPObject::finishLastLine()
       dFree(mBuffer);
       dFree(mBuffer);
       mBuffer = 0;
       mBuffer = 0;
       mBufferSize = 0;
       mBufferSize = 0;
+
+      return true;
+   }
+
+   return false;
+}
+
+bool TCPObject::isBufferEmpty()
+{
+   return (mBufferSize <= 0);
+}
+
+void TCPObject::emptyBuffer()
+{
+   if(mBufferSize)
+   {
+      dFree(mBuffer);
+      mBuffer = 0;
+      mBufferSize = 0;
    }
    }
 }
 }
 
 
@@ -400,6 +429,25 @@ void TCPObject::send(const U8 *buffer, U32 len)
    Net::sendtoSocket(mTag, buffer, S32(len));
    Net::sendtoSocket(mTag, buffer, S32(len));
 }
 }
 
 
+bool TCPObject::sendFile(const char* fileName)
+{
+   //Open the file for reading
+   FileStream readFile;
+   if(!readFile.open(fileName, Torque::FS::File::Read))
+   {
+      return false;
+   }
+
+   //Read each byte into our buffer
+   Vector<U8> buffer(readFile.getStreamSize());
+   readFile.read(buffer.size(), &buffer);
+
+   //Send the buffer
+   send(buffer.address(), buffer.size());
+
+   	return true;
+}
+
 DefineEngineMethod(TCPObject, send, void, (const char *data),, 
 DefineEngineMethod(TCPObject, send, void, (const char *data),, 
    "@brief Transmits the data string to the connected computer.\n\n"
    "@brief Transmits the data string to the connected computer.\n\n"
 
 
@@ -421,6 +469,20 @@ DefineEngineMethod(TCPObject, send, void, (const char *data),,
    object->send( (const U8*)data, dStrlen(data) );
    object->send( (const U8*)data, dStrlen(data) );
 }
 }
 
 
+DefineEngineMethod(TCPObject, sendFile, bool, (const char *fileName),, 
+   "@brief Transmits the file in binary to the connected computer.\n\n"
+
+   "@param fileName The filename of the file to transfer.\n")
+{
+   return object->sendFile(fileName);
+}
+
+DefineEngineMethod(TCPObject, finishLastLine, void, (),, 
+   "@brief Eat the rest of the lines.\n")
+{
+   object->finishLastLine();
+}
+
 DefineEngineMethod(TCPObject, listen, void, (U32 port),, 
 DefineEngineMethod(TCPObject, listen, void, (U32 port),, 
    "@brief Start listening on the specified port for connections.\n\n"
    "@brief Start listening on the specified port for connections.\n\n"
 
 
@@ -499,6 +561,29 @@ void processConnectedReceiveEvent(NetSocket sock, RawData incomingData)
       size -= ret;
       size -= ret;
       buffer += ret;
       buffer += ret;
    }
    }
+
+   //If our buffer now has something in it then it's probably a web socket packet and lets handle it
+   if(!tcpo->isBufferEmpty())
+   {
+      //Copy all the data into a string (may be a quicker way of doing this)
+      U8 *data = (U8*)incomingData.data;
+      String temp;
+      for(S32 i = 0; i < incomingData.size; i++)
+      {
+         temp += data[i];
+      }
+
+      //Send the packet to script
+      bool handled = tcpo->onPacket_callback(temp);
+
+      //If the script did something with it, clear the buffer
+      if(handled)
+      {
+         tcpo->emptyBuffer();
+      }
+   }
+
+   tcpo->onEndReceive_callback();
 }
 }
 
 
 void processConnectedAcceptEvent(NetSocket listeningPort, NetSocket newConnection, NetAddress originatingAddress)
 void processConnectedAcceptEvent(NetSocket listeningPort, NetSocket newConnection, NetAddress originatingAddress)

+ 11 - 1
Engine/source/app/net/tcpObject.h

@@ -36,6 +36,8 @@ public:
 
 
 	DECLARE_CALLBACK(void, onConnectionRequest, (const char* address, const char* ID));
 	DECLARE_CALLBACK(void, onConnectionRequest, (const char* address, const char* ID));
 	DECLARE_CALLBACK(void, onLine, (const char* line));
 	DECLARE_CALLBACK(void, onLine, (const char* line));
+	DECLARE_CALLBACK(bool, onPacket, (const char* data));
+	DECLARE_CALLBACK(void, onEndReceive, ());
 	DECLARE_CALLBACK(void, onDNSResolved,());
 	DECLARE_CALLBACK(void, onDNSResolved,());
 	DECLARE_CALLBACK(void, onDNSFailed, ());
 	DECLARE_CALLBACK(void, onDNSFailed, ());
 	DECLARE_CALLBACK(void, onConnected, ());
 	DECLARE_CALLBACK(void, onConnected, ());
@@ -60,7 +62,9 @@ public:
    virtual ~TCPObject();
    virtual ~TCPObject();
 
 
    void parseLine(U8 *buffer, U32 *start, U32 bufferLen);
    void parseLine(U8 *buffer, U32 *start, U32 bufferLen);
-   void finishLastLine();
+   bool finishLastLine();
+   bool isBufferEmpty();
+   void emptyBuffer();
 
 
    static TCPObject *find(NetSocket tag);
    static TCPObject *find(NetSocket tag);
 
 
@@ -81,6 +85,12 @@ public:
 
 
    bool processArguments(S32 argc, ConsoleValueRef *argv);
    bool processArguments(S32 argc, ConsoleValueRef *argv);
    void send(const U8 *buffer, U32 bufferLen);
    void send(const U8 *buffer, U32 bufferLen);
+
+   ///Send an entire file over tcp
+   ///@arg fileName Full path to file you want to send
+   ///@return true if file was sent, false if not (file doesn't exist)
+   bool sendFile(const char* fileName);
+
    void addToTable(NetSocket newTag);
    void addToTable(NetSocket newTag);
    void removeFromTable();
    void removeFromTable();
 
 

+ 1 - 1
Engine/source/console/codeBlock.cpp

@@ -61,7 +61,7 @@ CodeBlock::CodeBlock()
 CodeBlock::~CodeBlock()
 CodeBlock::~CodeBlock()
 {
 {
    // Make sure we aren't lingering in the current code block...
    // Make sure we aren't lingering in the current code block...
-   AssertFatal(smCurrentCodeBlock != this, "CodeBlock::~CodeBlock - Caught lingering in smCurrentCodeBlock!")
+   AssertFatal(smCurrentCodeBlock != this, "CodeBlock::~CodeBlock - Caught lingering in smCurrentCodeBlock!");
 
 
    if(name)
    if(name)
       removeFromCodeList();
       removeFromCodeList();

+ 16 - 0
Engine/source/console/consoleFunctions.h

@@ -0,0 +1,16 @@
+#ifndef _CONSOLFUNCTIONS_H_
+#define _CONSOLFUNCTIONS_H_
+
+#ifndef _STRINGFUNCTIONS_H_
+#include "core/strings/stringFunctions.h"
+#endif
+
+bool isInt(const char* str);
+
+bool isFloat(const char* str);
+
+bool isValidIP(const char* ip);
+
+bool isValidPort(U16 port);
+
+#endif

+ 1 - 1
Engine/source/core/idGenerator.h

@@ -74,7 +74,7 @@ public:
 
 
    void free(U32 id)
    void free(U32 id)
    {
    {
-      AssertFatal(id >= mIdBlockBase, "IdGenerator::alloc: invalid id, id does not belong to this IdGenerator.")
+      AssertFatal(id >= mIdBlockBase, "IdGenerator::alloc: invalid id, id does not belong to this IdGenerator.");
       if(id == mNextId - 1)
       if(id == mNextId - 1)
       {
       {
          mNextId--;
          mNextId--;

+ 9 - 0
Engine/source/core/strings/stringFunctions.h

@@ -152,11 +152,20 @@ inline U32 dAtoui(const char *str, U32 base = 10)
    return strtoul(str, NULL, base);
    return strtoul(str, NULL, base);
 }
 }
 
 
+inline U16 dAtous(const char *str, U32 base = 10)
+{
+   return strtoul(str, NULL, base);
+}
+
 inline F32 dAtof(const char *str)
 inline F32 dAtof(const char *str)
 {
 {
    return strtof(str, NULL);
    return strtof(str, NULL);
 }
 }
 
 
+inline F64 dAtod(const char *str)
+{
+   return strtod(str, NULL);
+}
 
 
 inline char dToupper(const char c)
 inline char dToupper(const char c)
 {
 {

+ 100 - 0
Engine/source/core/util/str.cpp

@@ -1628,3 +1628,103 @@ String String::GetTrailingNumber(const char* str, S32& number)
 
 
    return base.substr(0, p - base.c_str());
    return base.substr(0, p - base.c_str());
 }
 }
+
+String String::GetFirstNumber(const char* str, U32& startPos, U32& endPos)
+{
+   // Check for trivial strings
+   if (!str || !str[0])
+      return String::EmptyString;
+
+   // Find the number at the end of the string
+   String base(str);
+   const char* p = base.c_str();
+   const char* end = base.c_str() + base.length() - 1;
+   bool dec = false;
+   startPos = 0;
+
+   //Check if we are just a digit
+   if(p == end && isdigit(*p))
+      return base;
+
+   //Look for the first digit
+   while ((p != end) && (dIsspace(*p) || !isdigit(*p)))
+   {
+      p++;
+      startPos++;
+   }
+
+   //Handle if we are at the end and found nothing
+   if(p == end && !isdigit(*p))
+      return "";
+
+   //update our end position at least to the start of our number
+   endPos = startPos;
+
+   //Backup our ptr
+   const char* backup = p;
+
+   //Check for any negative or decimal values
+   if(startPos > 0)
+   {
+      p--;
+      startPos--;
+      if(*p == '.')
+      {
+         dec = true;
+
+         //ignore any duplicate periods
+         while ((p != base.c_str()) && (*p == '.'))
+         {
+            p--;
+            startPos--;
+         }
+
+         //Found a decimal lets still check for negative sign
+         if(startPos > 0)
+         {
+            p--;
+            startPos--;
+            if((*p != '-') && (*p != '_'))
+            {
+               startPos++;
+               p++;
+            }
+         }
+      }
+      else if((*p != '-') && (*p != '_'))
+      {
+         //go back to where we where cause no decimal or negative sign found
+         startPos++;
+         p++;
+      }
+   }
+
+   //Restore where we were
+   p = backup;
+
+   //look for the end of the digits
+   bool justFoundDec = false;
+   while (p != end)
+   {
+      if(*p == '.')
+      {
+         if(dec && !justFoundDec)
+            break;
+         else
+         {
+            dec = true;
+            justFoundDec = true;
+         }
+      }
+      else if(!isdigit(*p))
+         break;
+      else if(justFoundDec)
+         justFoundDec = false;
+
+      p++;
+      endPos++;
+   }
+
+   U32 len = (!isdigit(*p)) ? endPos - startPos : (endPos + 1) - startPos;
+   return base.substr(startPos, len);
+}

+ 1 - 0
Engine/source/core/util/str.h

@@ -191,6 +191,7 @@ public:
    static String ToUpper(const String &string);
    static String ToUpper(const String &string);
 
 
    static String GetTrailingNumber(const char* str, S32& number);
    static String GetTrailingNumber(const char* str, S32& number);
+   static String GetFirstNumber(const char* str, U32& startPos, U32& endPos);
 
 
    /// @}
    /// @}
 
 

+ 2 - 2
Engine/source/environment/timeOfDay.cpp

@@ -402,7 +402,7 @@ void TimeOfDay::_getSunColor( ColorF *outColor ) const
    //simple check
    //simple check
    if ( mColorTargets[0].elevation != 0.0f )
    if ( mColorTargets[0].elevation != 0.0f )
    {
    {
-      AssertFatal(0, "TimeOfDay::GetColor() - First elevation must be 0.0 radians")
+      AssertFatal(0, "TimeOfDay::GetColor() - First elevation must be 0.0 radians");
       outColor->set(1.0f, 1.0f, 1.0f);
       outColor->set(1.0f, 1.0f, 1.0f);
       //mBandMod = 1.0f;
       //mBandMod = 1.0f;
       //mCurrentBandColor = color;
       //mCurrentBandColor = color;
@@ -411,7 +411,7 @@ void TimeOfDay::_getSunColor( ColorF *outColor ) const
 
 
    if ( mColorTargets[mColorTargets.size()-1].elevation != M_PI_F )
    if ( mColorTargets[mColorTargets.size()-1].elevation != M_PI_F )
    {
    {
-      AssertFatal(0, "Celestails::GetColor() - Last elevation must be PI")
+      AssertFatal(0, "Celestails::GetColor() - Last elevation must be PI");
       outColor->set(1.0f, 1.0f, 1.0f);
       outColor->set(1.0f, 1.0f, 1.0f);
       //mBandMod = 1.0f;
       //mBandMod = 1.0f;
       //mCurrentBandColor = color;
       //mCurrentBandColor = color;

+ 24 - 4
Engine/source/gfx/D3D9/gfxD3D9Device.cpp

@@ -731,7 +731,8 @@ void GFXD3D9Device::setShader( GFXShader *shader, bool force )
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 GFXPrimitiveBuffer * GFXD3D9Device::allocPrimitiveBuffer(   U32 numIndices, 
 GFXPrimitiveBuffer * GFXD3D9Device::allocPrimitiveBuffer(   U32 numIndices, 
                                                             U32 numPrimitives, 
                                                             U32 numPrimitives, 
-                                                            GFXBufferType bufferType )
+                                                            GFXBufferType bufferType,
+                                                            void* data )
 {
 {
    // Allocate a buffer to return
    // Allocate a buffer to return
    GFXD3D9PrimitiveBuffer * res = new GFXD3D9PrimitiveBuffer(this, numIndices, numPrimitives, bufferType);
    GFXD3D9PrimitiveBuffer * res = new GFXD3D9PrimitiveBuffer(this, numIndices, numPrimitives, bufferType);
@@ -741,12 +742,13 @@ GFXPrimitiveBuffer * GFXD3D9Device::allocPrimitiveBuffer(   U32 numIndices,
    D3DPOOL pool = D3DPOOL_DEFAULT;
    D3DPOOL pool = D3DPOOL_DEFAULT;
 
 
    // Assumptions:
    // Assumptions:
-   //    - static buffers are write once, use many
+   //    - static buffers are write rarely, use many
    //    - dynamic buffers are write many, use many
    //    - dynamic buffers are write many, use many
    //    - volatile buffers are write once, use once
    //    - volatile buffers are write once, use once
    // You may never read from a buffer.
    // You may never read from a buffer.
    switch(bufferType)
    switch(bufferType)
    {
    {
+   case GFXBufferTypeImmutable:
    case GFXBufferTypeStatic:
    case GFXBufferTypeStatic:
       pool = isD3D9Ex() ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
       pool = isD3D9Ex() ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
       break;
       break;
@@ -781,6 +783,14 @@ GFXPrimitiveBuffer * GFXD3D9Device::allocPrimitiveBuffer(   U32 numIndices,
       D3D9Assert(mD3DDevice->CreateIndexBuffer( sizeof(U16) * numIndices , usage, GFXD3D9IndexFormat[GFXIndexFormat16], pool, &res->ib, 0),
       D3D9Assert(mD3DDevice->CreateIndexBuffer( sizeof(U16) * numIndices , usage, GFXD3D9IndexFormat[GFXIndexFormat16], pool, &res->ib, 0),
          "Failed to allocate an index buffer.");
          "Failed to allocate an index buffer.");
    }
    }
+   
+   if(data)
+   {
+      void* dest;
+      res->lock(0, numIndices, &dest);
+      dMemcpy(dest, data, sizeof(U16) * numIndices);
+      res->unlock();
+   }
 
 
    return res;
    return res;
 }
 }
@@ -791,7 +801,8 @@ GFXPrimitiveBuffer * GFXD3D9Device::allocPrimitiveBuffer(   U32 numIndices,
 GFXVertexBuffer * GFXD3D9Device::allocVertexBuffer(   U32 numVerts, 
 GFXVertexBuffer * GFXD3D9Device::allocVertexBuffer(   U32 numVerts, 
                                                       const GFXVertexFormat *vertexFormat, 
                                                       const GFXVertexFormat *vertexFormat, 
                                                       U32 vertSize, 
                                                       U32 vertSize, 
-                                                      GFXBufferType bufferType )
+                                                      GFXBufferType bufferType, 
+                                                      void* data)
 {
 {
    PROFILE_SCOPE( GFXD3D9Device_allocVertexBuffer );
    PROFILE_SCOPE( GFXD3D9Device_allocVertexBuffer );
 
 
@@ -808,7 +819,7 @@ GFXVertexBuffer * GFXD3D9Device::allocVertexBuffer(   U32 numVerts,
    res->mNumVerts = 0;
    res->mNumVerts = 0;
 
 
    // Assumptions:
    // Assumptions:
-   //    - static buffers are write once, use many
+   //    - static buffers are write rarely, use many
    //    - dynamic buffers are write many, use many
    //    - dynamic buffers are write many, use many
    //    - volatile buffers are write once, use once
    //    - volatile buffers are write once, use once
    // You may never read from a buffer.
    // You may never read from a buffer.
@@ -850,6 +861,15 @@ GFXVertexBuffer * GFXD3D9Device::allocVertexBuffer(   U32 numVerts,
    }
    }
 
 
    res->mNumVerts = numVerts;
    res->mNumVerts = numVerts;
+   
+   if(data)
+   {
+      void* dest;
+      res->lock(0, numVerts, &dest);
+      dMemcpy(dest, data, vertSize * numVerts);
+      res->unlock();
+   }
+   
    return res;
    return res;
 }
 }
 
 

+ 4 - 2
Engine/source/gfx/D3D9/gfxD3D9Device.h

@@ -298,10 +298,12 @@ public:
    virtual GFXVertexBuffer* allocVertexBuffer(  U32 numVerts, 
    virtual GFXVertexBuffer* allocVertexBuffer(  U32 numVerts, 
                                                 const GFXVertexFormat *vertexFormat,
                                                 const GFXVertexFormat *vertexFormat,
                                                 U32 vertSize,
                                                 U32 vertSize,
-                                                GFXBufferType bufferType );
+                                                GFXBufferType bufferType,
+                                                void* data = NULL );
    virtual GFXPrimitiveBuffer *allocPrimitiveBuffer(  U32 numIndices, 
    virtual GFXPrimitiveBuffer *allocPrimitiveBuffer(  U32 numIndices, 
                                                       U32 numPrimitives, 
                                                       U32 numPrimitives, 
-                                                      GFXBufferType bufferType );
+                                                      GFXBufferType bufferType,
+                                                      void* data = NULL );
    virtual void deallocVertexBuffer( GFXD3D9VertexBuffer *vertBuff );
    virtual void deallocVertexBuffer( GFXD3D9VertexBuffer *vertBuff );
    virtual GFXVertexDecl* allocVertexDecl( const GFXVertexFormat *vertexFormat );
    virtual GFXVertexDecl* allocVertexDecl( const GFXVertexFormat *vertexFormat );
    virtual void setVertexDecl( const GFXVertexDecl *decl );
    virtual void setVertexDecl( const GFXVertexDecl *decl );

+ 1 - 0
Engine/source/gfx/D3D9/pc/gfxD3D9PrimitiveBuffer.pc.cpp

@@ -31,6 +31,7 @@ void GFXD3D9PrimitiveBuffer::lock(U32 indexStart, U32 indexEnd, void **indexPtr)
    U32 flags=0;
    U32 flags=0;
    switch(mBufferType)
    switch(mBufferType)
    {
    {
+   case GFXBufferTypeImmutable:
    case GFXBufferTypeStatic:
    case GFXBufferTypeStatic:
       // flags |= D3DLOCK_DISCARD;
       // flags |= D3DLOCK_DISCARD;
       break;
       break;

+ 4 - 2
Engine/source/gfx/Null/gfxNullDevice.cpp

@@ -276,14 +276,16 @@ GFXNullDevice::~GFXNullDevice()
 GFXVertexBuffer *GFXNullDevice::allocVertexBuffer( U32 numVerts, 
 GFXVertexBuffer *GFXNullDevice::allocVertexBuffer( U32 numVerts, 
                                                    const GFXVertexFormat *vertexFormat,
                                                    const GFXVertexFormat *vertexFormat,
                                                    U32 vertSize, 
                                                    U32 vertSize, 
-                                                   GFXBufferType bufferType ) 
+                                                   GFXBufferType bufferType,
+                                                   void* data ) 
 {
 {
    return new GFXNullVertexBuffer(GFX, numVerts, vertexFormat, vertSize, bufferType);
    return new GFXNullVertexBuffer(GFX, numVerts, vertexFormat, vertSize, bufferType);
 }
 }
 
 
 GFXPrimitiveBuffer *GFXNullDevice::allocPrimitiveBuffer( U32 numIndices, 
 GFXPrimitiveBuffer *GFXNullDevice::allocPrimitiveBuffer( U32 numIndices, 
                                                          U32 numPrimitives, 
                                                          U32 numPrimitives, 
-                                                         GFXBufferType bufferType) 
+                                                         GFXBufferType bufferType,
+                                                         void* data ) 
 {
 {
    return new GFXNullPrimitiveBuffer(GFX, numIndices, numPrimitives, bufferType);
    return new GFXNullPrimitiveBuffer(GFX, numIndices, numPrimitives, bufferType);
 }
 }

+ 4 - 2
Engine/source/gfx/Null/gfxNullDevice.h

@@ -115,10 +115,12 @@ protected:
    virtual GFXVertexBuffer *allocVertexBuffer(  U32 numVerts, 
    virtual GFXVertexBuffer *allocVertexBuffer(  U32 numVerts, 
                                                 const GFXVertexFormat *vertexFormat, 
                                                 const GFXVertexFormat *vertexFormat, 
                                                 U32 vertSize, 
                                                 U32 vertSize, 
-                                                GFXBufferType bufferType );
+                                                GFXBufferType bufferType,
+                                                void* data = NULL );
    virtual GFXPrimitiveBuffer *allocPrimitiveBuffer(  U32 numIndices, 
    virtual GFXPrimitiveBuffer *allocPrimitiveBuffer(  U32 numIndices, 
                                                       U32 numPrimitives, 
                                                       U32 numPrimitives, 
-                                                      GFXBufferType bufferType );
+                                                      GFXBufferType bufferType,
+                                                      void* data = NULL );
 
 
    virtual GFXVertexDecl* allocVertexDecl( const GFXVertexFormat *vertexFormat ) { return NULL; }
    virtual GFXVertexDecl* allocVertexDecl( const GFXVertexFormat *vertexFormat ) { return NULL; }
    virtual void setVertexDecl( const GFXVertexDecl *decl ) {  }
    virtual void setVertexDecl( const GFXVertexDecl *decl ) {  }

+ 1 - 1
Engine/source/gfx/bitmap/loaders/bitmapTga.cpp

@@ -483,7 +483,7 @@ static bool sReadTGA(Stream &stream, GBitmap *bitmap)
 
 
 static bool sWriteTGA(GBitmap *bitmap, Stream &stream, U32 compressionLevel)
 static bool sWriteTGA(GBitmap *bitmap, Stream &stream, U32 compressionLevel)
 {
 {
-   AssertISV(false, "GBitmap::writeTGA - doesn't support writing tga files!")
+   AssertISV(false, "GBitmap::writeTGA - doesn't support writing tga files!");
 
 
    return false;
    return false;
 }
 }

+ 4 - 2
Engine/source/gfx/gfxDevice.h

@@ -637,7 +637,8 @@ protected:
    virtual GFXVertexBuffer *allocVertexBuffer(  U32 numVerts, 
    virtual GFXVertexBuffer *allocVertexBuffer(  U32 numVerts, 
                                                 const GFXVertexFormat *vertexFormat, 
                                                 const GFXVertexFormat *vertexFormat, 
                                                 U32 vertSize, 
                                                 U32 vertSize, 
-                                                GFXBufferType bufferType ) = 0;
+                                                GFXBufferType bufferType,
+                                                void* data = NULL ) = 0;
 
 
    /// Called from GFXVertexFormat to allocate the hardware 
    /// Called from GFXVertexFormat to allocate the hardware 
    /// specific vertex declaration for rendering.
    /// specific vertex declaration for rendering.
@@ -674,7 +675,8 @@ protected:
    /// @note All index buffers use unsigned 16-bit indices.
    /// @note All index buffers use unsigned 16-bit indices.
    virtual GFXPrimitiveBuffer *allocPrimitiveBuffer(  U32 numIndices, 
    virtual GFXPrimitiveBuffer *allocPrimitiveBuffer(  U32 numIndices, 
                                                       U32 numPrimitives, 
                                                       U32 numPrimitives, 
-                                                      GFXBufferType bufferType ) = 0;
+                                                      GFXBufferType bufferType,
+                                                      void* data = NULL ) = 0;
 
 
    /// @}
    /// @}
 
 

+ 4 - 3
Engine/source/gfx/gfxEnums.h

@@ -39,8 +39,8 @@
 
 
 enum GFXBufferType
 enum GFXBufferType
 {
 {
-      GFXBufferTypeStatic,   ///< Static vertex buffers are created and filled one time.
-                   ///< incur a performance penalty.  Resizing a static vertex buffer is not
+      GFXBufferTypeStatic,   ///< Static vertex buffers are created and rarely updated.
+                   ///< Updating might incur a performance penalty.  Resizing a static vertex buffer is not
                    ///< allowed.
                    ///< allowed.
       GFXBufferTypeDynamic,  ///< Dynamic vertex buffers are meant for vertices that can be changed
       GFXBufferTypeDynamic,  ///< Dynamic vertex buffers are meant for vertices that can be changed
                    ///< often.  Vertices written into dynamic vertex buffers will remain valid
                    ///< often.  Vertices written into dynamic vertex buffers will remain valid
@@ -48,7 +48,8 @@ enum GFXBufferType
                    ///< allowed.
                    ///< allowed.
       GFXBufferTypeVolatile, ///< Volatile vertex or index buffers are meant for vertices or indices that are essentially
       GFXBufferTypeVolatile, ///< Volatile vertex or index buffers are meant for vertices or indices that are essentially
                    ///< only used once.  They can be resized without any performance penalty.
                    ///< only used once.  They can be resized without any performance penalty.
-      
+      GFXBufferTypeImmutable, ///< Immutable buffers must specify the data when creating the buffer. Cannot be modified.
+
       GFXBufferType_COUNT ///< Number of buffer types.
       GFXBufferType_COUNT ///< Number of buffer types.
 };
 };
 
 

+ 13 - 0
Engine/source/gfx/gfxPrimitiveBuffer.cpp

@@ -80,3 +80,16 @@ void GFXPrimitiveBufferHandle::set(GFXDevice *theDevice, U32 indexCount, U32 pri
       getPointer()->mDebugCreationPath = desc;
       getPointer()->mDebugCreationPath = desc;
 #endif
 #endif
 }
 }
+
+//-----------------------------------------------------------------------------
+// immutable
+//-----------------------------------------------------------------------------
+void GFXPrimitiveBufferHandle::immutable(GFXDevice *theDevice, U32 indexCount, U32 primitiveCount, void* data, String desc)
+{
+   StrongRefPtr<GFXPrimitiveBuffer>::operator=( theDevice->allocPrimitiveBuffer(indexCount, primitiveCount, GFXBufferTypeImmutable, data) );
+
+#ifdef TORQUE_DEBUG
+   if( desc.isNotEmpty() )
+      getPointer()->mDebugCreationPath = desc;
+#endif
+}

+ 2 - 0
Engine/source/gfx/gfxPrimitiveBuffer.h

@@ -140,6 +140,8 @@ public:
    }
    }
 
 
    void set(GFXDevice *theDevice, U32 indexCount, U32 primitiveCount, GFXBufferType bufferType, String desc = String::EmptyString );
    void set(GFXDevice *theDevice, U32 indexCount, U32 primitiveCount, GFXBufferType bufferType, String desc = String::EmptyString );
+   
+   void immutable(GFXDevice *theDevice, U32 indexCount, U32 primitiveCount, void* data, String desc = String::EmptyString );
 
 
    void lock(U16 **indexBuffer, GFXPrimitive **primitiveBuffer = NULL, U32 indexStart = 0, U32 indexEnd = 0)
    void lock(U16 **indexBuffer, GFXPrimitive **primitiveBuffer = NULL, U32 indexStart = 0, U32 indexEnd = 0)
    {
    {

+ 31 - 7
Engine/source/gfx/gl/gfxGLDevice.cpp

@@ -355,23 +355,47 @@ GFXPrimitiveBuffer* GFXGLDevice::findVolatilePBO(U32 numIndices, U32 numPrimitiv
 GFXVertexBuffer *GFXGLDevice::allocVertexBuffer(   U32 numVerts, 
 GFXVertexBuffer *GFXGLDevice::allocVertexBuffer(   U32 numVerts, 
                                                    const GFXVertexFormat *vertexFormat, 
                                                    const GFXVertexFormat *vertexFormat, 
                                                    U32 vertSize, 
                                                    U32 vertSize, 
-                                                   GFXBufferType bufferType ) 
+                                                   GFXBufferType bufferType,
+                                                   void* data )  
 {
 {
    if(bufferType == GFXBufferTypeVolatile)
    if(bufferType == GFXBufferTypeVolatile)
       return findVolatileVBO(numVerts, vertexFormat, vertSize);
       return findVolatileVBO(numVerts, vertexFormat, vertSize);
          
          
    GFXGLVertexBuffer* buf = new GFXGLVertexBuffer( GFX, numVerts, vertexFormat, vertSize, bufferType );
    GFXGLVertexBuffer* buf = new GFXGLVertexBuffer( GFX, numVerts, vertexFormat, vertSize, bufferType );
-   buf->registerResourceWithDevice(this);
+   buf->registerResourceWithDevice(this);   
+
+   if(data)
+   {
+      void* dest;
+      buf->lock(0, numVerts, &dest);
+      dMemcpy(dest, data, vertSize * numVerts);
+      buf->unlock();
+   }
+
    return buf;
    return buf;
 }
 }
 
 
-GFXPrimitiveBuffer *GFXGLDevice::allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType ) 
+GFXPrimitiveBuffer *GFXGLDevice::allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType, void* data ) 
 {
 {
+   GFXPrimitiveBuffer* buf;
+   
    if(bufferType == GFXBufferTypeVolatile)
    if(bufferType == GFXBufferTypeVolatile)
-      return findVolatilePBO(numIndices, numPrimitives);
-         
-   GFXGLPrimitiveBuffer* buf = new GFXGLPrimitiveBuffer(GFX, numIndices, numPrimitives, bufferType);
-   buf->registerResourceWithDevice(this);
+   {
+      buf = findVolatilePBO(numIndices, numPrimitives);
+   }
+   else
+   {
+      buf = new GFXGLPrimitiveBuffer(GFX, numIndices, numPrimitives, bufferType);
+      buf->registerResourceWithDevice(this);
+   }
+   
+   if(data)
+   {
+      void* dest;
+      buf->lock(0, numIndices, &dest);
+      dMemcpy(dest, data, sizeof(U16) * numIndices);
+      buf->unlock();
+   }
    return buf;
    return buf;
 }
 }
 
 

+ 3 - 2
Engine/source/gfx/gl/gfxGLDevice.h

@@ -173,8 +173,9 @@ protected:
    virtual GFXVertexBuffer *allocVertexBuffer(  U32 numVerts, 
    virtual GFXVertexBuffer *allocVertexBuffer(  U32 numVerts, 
                                                 const GFXVertexFormat *vertexFormat,
                                                 const GFXVertexFormat *vertexFormat,
                                                 U32 vertSize, 
                                                 U32 vertSize, 
-                                                GFXBufferType bufferType );
-   virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType );
+                                                GFXBufferType bufferType,
+                                                void* data = NULL);
+   virtual GFXPrimitiveBuffer *allocPrimitiveBuffer( U32 numIndices, U32 numPrimitives, GFXBufferType bufferType, void* data = NULL );
    
    
    // NOTE: The GL device doesn't need a vertex declaration at
    // NOTE: The GL device doesn't need a vertex declaration at
    // this time, but we need to return something to keep the system
    // this time, but we need to return something to keep the system

+ 1 - 0
Engine/source/gfx/gl/gfxGLEnumTranslate.cpp

@@ -45,6 +45,7 @@ void GFXGLEnumTranslate::init()
    GFXGLBufferType[GFXBufferTypeStatic] = GL_STATIC_DRAW;
    GFXGLBufferType[GFXBufferTypeStatic] = GL_STATIC_DRAW;
    GFXGLBufferType[GFXBufferTypeDynamic] = GL_DYNAMIC_DRAW;
    GFXGLBufferType[GFXBufferTypeDynamic] = GL_DYNAMIC_DRAW;
    GFXGLBufferType[GFXBufferTypeVolatile] = GL_STREAM_DRAW;
    GFXGLBufferType[GFXBufferTypeVolatile] = GL_STREAM_DRAW;
+   GFXGLBufferType[GFXBufferTypeImmutable] = GL_STATIC_DRAW;
 
 
    // Primitives
    // Primitives
    GFXGLPrimType[GFXPointList] = GL_POINTS;
    GFXGLPrimType[GFXPointList] = GL_POINTS;

+ 88 - 0
Engine/source/math/mathTypes.cpp

@@ -660,6 +660,66 @@ DefineConsoleFunction( VectorScale, VectorF, ( VectorF a, F32 scalar ),,
 {
 {
    return a * scalar;
    return a * scalar;
 }
 }
+DefineConsoleFunction( VectorMul, VectorF, ( VectorF a, VectorF b ),,
+   "Multiplies two vectors.\n"
+   "@param a The first vector.\n"
+   "@param b The second vector.\n"
+   "@return The vector @a a * @a b.\n\n"
+   "@tsexample\n"
+	"//-----------------------------------------------------------------------------\n"
+	"//\n"
+	"// VectorMul( %a, %b );\n"
+	"//\n"
+	"// The multiplication of vector a, (ax, ay, az), and vector b, (bx, by, bz) is:\n"
+	"//\n"
+	"//     a * b = ( ax * bx, ay * by, az * bz )\n"
+	"//\n"
+	"//-----------------------------------------------------------------------------\n\n"
+
+	"%a = \"1 0 0\";\n"
+	"%b = \"0 1 0\";\n\n"
+
+	"// %r = \"( 1 * 0, 0 * 1, 0 * 0 )\";\n"
+	"// %r = \"0 0 0\";\n"
+	"%r = VectorMul( %a, %b );\n"
+   "@endtsexample\n\n"
+   "@ingroup Vectors" )
+{
+   return a * b;
+}
+
+DefineConsoleFunction( VectorDiv, VectorF, ( VectorF a, VectorF b ),,
+   "Divide two vectors.\n"
+   "@param a The first vector.\n"
+   "@param b The second vector.\n"
+   "@return The vector @a a / @a b.\n\n"
+   "@tsexample\n"
+	"//-----------------------------------------------------------------------------\n"
+	"//\n"
+	"// VectorDiv( %a, %b );\n"
+	"//\n"
+	"// The division of vector a, (ax, ay, az), and vector b, (bx, by, bz) is:\n"
+	"//\n"
+	"//     a * b = ( ax / bx, ay / by, az / bz )\n"
+	"//\n"
+	"//-----------------------------------------------------------------------------\n\n"
+
+	"%a = \"1 1 1\";\n"
+	"%b = \"2 2 2\";\n\n"
+
+	"// %r = \"( 1 / 2, 1 / 2, 1 / 2 )\";\n"
+	"// %r = \"0.5 0.5 0.5\";\n"
+	"%r = VectorDiv( %a, %b );\n"
+   "@endtsexample\n\n"
+   "@ingroup Vectors" )
+{
+   //this is kind of bad, but so is dividing by 0
+   if(b.x == 0) b.x = 0.000001f;
+   if(b.y == 0) b.y = 0.000001f;
+   if(b.z == 0) b.z = 0.000001f;
+   
+   return a / b;
+}
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
@@ -790,6 +850,34 @@ DefineConsoleFunction( VectorDist, F32, ( VectorF a, VectorF b ),,
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+DefineConsoleFunction( VectorMidPoint, VectorF, ( VectorF a, VectorF b ),,
+   "Gets the midpoint between the two vectors.\n"
+   "@param a The first vector.\n"
+   "@param b The second vector.\n"
+   "@return The vector (@a a + @a b) / 2.\n\n"
+   "@tsexample\n"
+      "//-----------------------------------------------------------------------------\n"
+      "//\n"
+      "// VectorMidPoint( %a, %b );\n"
+      "//\n"
+      "// The midpoint of vector a, (ax, ay, az), and vector b, (bx, by, bz) is:\n"
+      "//\n"
+	  "//     (a + b)/2 = ( (ax + bx) /2, ay + by) /2, (az + bz) /2 )\n"
+      "//\n"
+      "//-----------------------------------------------------------------------------\n"
+//      "%a = \"1 0 0\";\n"
+//      "%b = \"0 1 0\";\n\n"
+//      "// %r = \"( 1 + 0, 0 + 1, 0 + 0 )\";\n"
+//      "// %r = \"1 1 0\";\n"
+//      "%r = VectorAdd( %a, %b );\n"
+   "@endtsexample\n\n"
+   "@ingroup Vectors")
+{
+   return (a + b)/2.0f;
+}
+
+//-----------------------------------------------------------------------------
+
 DefineConsoleFunction( VectorLen, F32, ( VectorF v ),,
 DefineConsoleFunction( VectorLen, F32, ( VectorF v ),,
    "Calculate the magnitude of the given vector.\n"
    "Calculate the magnitude of the given vector.\n"
    "@param v A vector.\n"
    "@param v A vector.\n"

+ 0 - 18
Engine/source/platform/platformAssert.cpp

@@ -69,24 +69,6 @@ bool PlatformAssert::displayMessageBox(const char *title, const char *message, b
 }
 }
 
 
 static const char *typeName[] = { "Unknown", "Fatal-ISV", "Fatal", "Warning" };
 static const char *typeName[] = { "Unknown", "Fatal-ISV", "Fatal", "Warning" };
-//------------------------------------------------------------------------------
-static bool askToEnterDebugger(const char* message )
-{
-   static bool haveAsked = false;
-   static bool useDebugger = true;
-   if(!haveAsked )
-   {
-      static char tempBuff[1024];
-      dSprintf( tempBuff, 1024, "Torque has encountered an assertion with message\n\n"
-         "%s\n\n"
-         "Would you like to use the debugger? If you cancel, you won't be asked"
-         " again until you restart Torque.", message);
-
-      useDebugger = Platform::AlertOKCancel("Use debugger?", tempBuff );
-      haveAsked = true;
-   }
-   return useDebugger;
-}
 
 
 //--------------------------------------
 //--------------------------------------
 
 

+ 24 - 29
Engine/source/platform/platformAssert.h

@@ -64,19 +64,17 @@ public:
 
 
 
 
 #ifdef TORQUE_ENABLE_ASSERTS
 #ifdef TORQUE_ENABLE_ASSERTS
-   /*!
-      Assert that the statement x is true, and continue processing.
+/*!
+   Assert that the statement x is true, and continue processing.
 
 
-      If the statment x is true, continue processing.
+   If the statment x is true, continue processing.
 
 
-      If the statement x is false, log the file and line where the assert occured,
-      the message y and continue processing.
+   If the statement x is false, log the file and line where the assert occured,
+   the message y and continue processing.
 
 
-      These asserts are only present in DEBUG builds.
-    */
-   #define AssertWarn(x, y)      \
-         { if ((x)==0) \
-            ::PlatformAssert::processAssert(::PlatformAssert::Warning, __FILE__, __LINE__,  y); }
+   These asserts are only present in DEBUG builds.
+   */
+#define AssertWarn(x, y) (void)(!!(x) || ::PlatformAssert::processAssert(::PlatformAssert::Warning, __FILE__, __LINE__,  y))
 
 
    /*!
    /*!
       Helper macro called when AssertFatal failed.
       Helper macro called when AssertFatal failed.
@@ -86,27 +84,27 @@ public:
       #define ON_FAIL_ASSERTFATAL
       #define ON_FAIL_ASSERTFATAL
    #endif
    #endif
 
 
-   /*!
-      Assert that the statement x is true, otherwise halt.
+/*!
+   Assert that the statement x is true, otherwise halt.
 
 
-      If the statement x is true, continue processing.
+   If the statement x is true, continue processing.
 
 
-      If the statement x is false, log the file and line where the assert occured,
-      the message y and displaying a dialog containing the message y. The user then
-      has the option to halt or continue causing the debugger to break.
+   If the statement x is false, log the file and line where the assert occured,
+   the message y and displaying a dialog containing the message y. The user then
+   has the option to halt or continue causing the debugger to break.
 
 
-      These asserts are only present in DEBUG builds.
+   These asserts are only present in DEBUG builds.
 
 
-      This assert is very useful for verifying data as well as function entry and
-      exit conditions.
-    */
-   #define AssertFatal(x, y)         \
-      { if (((bool)(x))==false) \
-         { if ( ::PlatformAssert::processAssert(::PlatformAssert::Fatal, __FILE__, __LINE__,  y) ) { ::Platform::debugBreak(); } } } 
+   This assert is very useful for verifying data as well as function entry and
+   exit conditions.
+   */
+#define AssertFatal(x, y) ((!(x) && ::PlatformAssert::processAssert(::PlatformAssert::Fatal, __FILE__, __LINE__,  y)) ? ::Platform::debugBreak() : (void)0)                                                                  \
 
 
 #else
 #else
-   #define AssertFatal(x, y)   { TORQUE_UNUSED(x); TORQUE_UNUSED(y); }
-   #define AssertWarn(x, y)    { TORQUE_UNUSED(x); TORQUE_UNUSED(y); }
+
+#define AssertFatal(x, y) TORQUE_UNUSED(x)
+#define AssertWarn(x, y)  TORQUE_UNUSED(x)
+
 #endif
 #endif
 
 
 /*!
 /*!
@@ -121,10 +119,7 @@ public:
    This assert should only be used for rare conditions where the application cannot continue
    This assert should only be used for rare conditions where the application cannot continue
    execution without seg-faulting and you want to display a nice exit message.
    execution without seg-faulting and you want to display a nice exit message.
  */
  */
-#define AssertISV(x, y)  \
-   { if ((x)==0)         \
-{ if ( ::PlatformAssert::processAssert(::PlatformAssert::Fatal_ISV, __FILE__, __LINE__,  y) ) { ::Platform::debugBreak(); } } }
-
+#define AssertISV(x, y) ((!(x) && ::PlatformAssert::processAssert(::PlatformAssert::Fatal_ISV, __FILE__, __LINE__,  y)) ? ::Platform::debugBreak() : (void)0)                                                                  \
 
 
 /*!
 /*!
    Sprintf style string formating into a fixed temporary buffer.
    Sprintf style string formating into a fixed temporary buffer.

+ 1 - 1
Engine/source/platform/platformNet.cpp

@@ -503,7 +503,7 @@ bool Net::openPort(S32 port, bool doBind)
 	  }
 	  }
 
 
       if(error == NoError)
       if(error == NoError)
-         error = setBufferSize(udpSocket, 32768);
+         error = setBufferSize(udpSocket, 32768*8);
 
 
       if(error == NoError && !useVDP)
       if(error == NoError && !useVDP)
          error = setBroadcast(udpSocket, true);
          error = setBroadcast(udpSocket, true);

+ 12 - 4
Engine/source/platform/profiler.cpp

@@ -215,13 +215,21 @@ void Profiler::reset()
 {
 {
    mEnabled = false; // in case we're in a profiler call.
    mEnabled = false; // in case we're in a profiler call.
    ProfilerData * head = mProfileList;
    ProfilerData * head = mProfileList;
-   ProfilerData * curr = NULL;
-   while ((curr = head) != NULL)
+   ProfilerData * curr = head;
+
+   while ( curr )
    {
    {
-      head = head->mNextProfilerData;
-      free(curr);
+      head = curr->mNextProfilerData;
+      free( curr );
+
+      if ( head )
+         curr = head;
+      else
+         curr = NULL;
    }
    }
 
 
+   mProfileList = NULL;
+
    for(ProfilerRootData *walk = ProfilerRootData::sRootList; walk; walk = walk->mNextRoot)
    for(ProfilerRootData *walk = ProfilerRootData::sRootList; walk; walk = walk->mNextRoot)
    {
    {
       walk->mFirstProfilerData = 0;
       walk->mFirstProfilerData = 0;

+ 10 - 0
Engine/source/platform/types.visualc.h

@@ -32,6 +32,16 @@
 typedef signed _int64   S64;
 typedef signed _int64   S64;
 typedef unsigned _int64 U64;
 typedef unsigned _int64 U64;
 
 
+// The types.h version of TORQUE_UNUSED no longer works for recent versions of MSVC.
+// Since it appears that MS has made this impossible to do in a zero-overhead way,
+// just turn the warning off in release builds.
+#undef TORQUE_UNUSED
+#ifdef TORQUE_DEBUG
+#define TORQUE_UNUSED(var) ((0,0) ? (void)(var) : (void)0)
+#else
+#pragma warning(disable: 4189) // local variable is initialized but not referenced
+#define TORQUE_UNUSED(var) ((void)0)
+#endif
 
 
 //--------------------------------------
 //--------------------------------------
 // Compiler Version
 // Compiler Version

+ 4 - 8
Engine/source/renderInstance/renderParticleMgr.cpp

@@ -338,14 +338,10 @@ void RenderParticleMgr::render( SceneRenderState *state )
 void RenderParticleMgr::_initGFXResources()
 void RenderParticleMgr::_initGFXResources()
 {
 {
    // Screen quad
    // Screen quad
-   U16 *prims = NULL;
-   mScreenQuadPrimBuff.set(GFX, 4, 2, GFXBufferTypeStatic);
-   mScreenQuadPrimBuff.lock(&prims);
-   (*prims++) = 0;
-   (*prims++) = 1;
-   (*prims++) = 2;
-   (*prims++) = 3;
-   mScreenQuadPrimBuff.unlock();
+   U16 prims [] = {
+      0, 1, 2, 3,
+   };
+   mScreenQuadPrimBuff.immutable(GFX, 4, 2, prims);
 
 
    mScreenQuadVertBuff.set(GFX, 4, GFXBufferTypeStatic);
    mScreenQuadVertBuff.set(GFX, 4, GFXBufferTypeStatic);
    CompositeQuadVert *verts = mScreenQuadVertBuff.lock();
    CompositeQuadVert *verts = mScreenQuadVertBuff.lock();

+ 2 - 2
Engine/source/sim/netGhost.cpp

@@ -964,7 +964,7 @@ void NetConnection::activateGhosting()
         // Iterate through the scope always objects...
         // Iterate through the scope always objects...
         for (j = mGhostZeroUpdateIndex - 1; j >= 0; j--)
         for (j = mGhostZeroUpdateIndex - 1; j >= 0; j--)
         {
         {
-            AssertFatal((mGhostArray[j]->flags & GhostInfo::ScopeAlways) != 0, "NetConnection::activateGhosting:  Non-scope always in the scope always list.")
+            AssertFatal((mGhostArray[j]->flags & GhostInfo::ScopeAlways) != 0, "NetConnection::activateGhosting:  Non-scope always in the scope always list.");
 
 
             // Clear the ghost update mask and flags appropriately.
             // Clear the ghost update mask and flags appropriately.
             mGhostArray[j]->updateMask = 0;
             mGhostArray[j]->updateMask = 0;
@@ -1015,7 +1015,7 @@ void NetConnection::activateGhosting()
         // Iterate through the scope always objects...
         // Iterate through the scope always objects...
         for (j = mGhostZeroUpdateIndex - 1; j >= 0; j--)
         for (j = mGhostZeroUpdateIndex - 1; j >= 0; j--)
         {
         {
-            AssertFatal((mGhostArray[j]->flags & GhostInfo::ScopeAlways) != 0, "NetConnection::activateGhosting:  Non-scope always in the scope always list.")
+            AssertFatal((mGhostArray[j]->flags & GhostInfo::ScopeAlways) != 0, "NetConnection::activateGhosting:  Non-scope always in the scope always list.");
 
 
             // Clear the ghost update mask and flags appropriately.
             // Clear the ghost update mask and flags appropriately.
             mGhostArray[j]->updateMask = 0;
             mGhostArray[j]->updateMask = 0;

+ 1 - 1
Engine/source/util/catmullRom.cpp

@@ -48,7 +48,7 @@ CatmullRomBase::CatmullRomBase()
 void CatmullRomBase::_initialize( U32 count, const F32 *times )
 void CatmullRomBase::_initialize( U32 count, const F32 *times )
 {
 {
    //AssertFatal( times, "CatmullRomBase::_initialize() - Got null position!" )
    //AssertFatal( times, "CatmullRomBase::_initialize() - Got null position!" )
-   AssertFatal( count > 1, "CatmullRomBase::_initialize() - Must have more than 2 points!" )
+   AssertFatal( count > 1, "CatmullRomBase::_initialize() - Must have more than 2 points!" );
 
 
    // set up arrays
    // set up arrays
    mTimes = new F32[count];
    mTimes = new F32[count];

+ 2 - 2
Engine/source/util/catmullRom.h

@@ -142,8 +142,8 @@ inline void CatmullRom<TYPE>::clear()
 template<typename TYPE>
 template<typename TYPE>
 inline void CatmullRom<TYPE>::initialize( U32 count, const TYPE *positions, const F32 *times )
 inline void CatmullRom<TYPE>::initialize( U32 count, const TYPE *positions, const F32 *times )
 {
 {
-   AssertFatal( positions, "CatmullRom::initialize - Got null position!" )
-   AssertFatal( count > 1, "CatmullRom::initialize - Must have more than 2 points!" )
+   AssertFatal( positions, "CatmullRom::initialize - Got null position!" );
+   AssertFatal( count > 1, "CatmullRom::initialize - Must have more than 2 points!" );
 
 
    // Clean up any previous state.
    // Clean up any previous state.
    clear();
    clear();