Selaa lähdekoodia

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

# Conflicts resolved:
#	Engine/source/console/consoleFunctions.cpp
Anis A. Hireche 9 vuotta sitten
vanhempi
commit
b3662d801a
42 muutettua tiedostoa jossa 606 lisäystä ja 115 poistoa
  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
    // triggers can be controlled from scripts.
    for( U32 i = 0; i < MaxTriggerKeys; i++ )
@@ -591,6 +606,16 @@ bool AIPlayer::getAIMove(Move *movePtr)
    return true;
 }
 
+void AIPlayer::setAiPose( S32 pose )  
+{  
+   mAiPose = pose;  
+}  
+  
+S32 AIPlayer::getAiPose()  
+{  
+   return mAiPose;   
+}
+
 /**
  * Utility function to throw callbacks. Callbacks always occure
  * on the datablock class.
@@ -1348,3 +1373,18 @@ DefineEngineMethod( AIPlayer, clearMoveTriggers, void, ( ),,
 {
    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 );
    Point3F getMoveDestination() const { return mMoveDestination; }
    void stopMove();
-
+   void setAiPose( S32 pose );
+   S32  getAiPose();
+	
    // Trigger sets/gets
    void setMoveTrigger( U32 slot, const bool isSet = true );
    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);
    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 );
 
    // 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!
       if (dStrlen(mFieldData.mFoliageFile) == 0) 
@@ -1134,7 +1134,7 @@ void fxFoliageReplicator::ProcessQuadrant(fxFoliageQuadrantNode* pParentNode, fx
 void fxFoliageReplicator::SyncFoliageReplicators(void)
 {
    // 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.
    SimSet *fxFoliageSet = dynamic_cast<SimSet*>(Sim::findObject("fxFoliageSet"));
@@ -1196,7 +1196,7 @@ void fxFoliageReplicator::DestroyFoliageItems()
 void fxFoliageReplicator::DestroyFoliage(void)
 {
    // 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.
       mPotentialFoliageNodes = 0;

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

@@ -224,7 +224,7 @@ void fxShapeReplicator::CreateShapes(void)
    }
 
    // 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...
       if (!mFieldData.mShapeFile) return;

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

@@ -3173,18 +3173,21 @@ void Player::updateMove(const Move* move)
    // Update the PlayerPose
    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(mSwimming);
+      stream->writeFlag(mJetting);  
+      stream->writeInt(mPose, NumPoseBits);
+	  
       stream->writeInt(mState,NumStateBits);
       if (stream->writeFlag(mState == RecoverState))
          stream->writeInt(mRecoverTicks,PlayerData::RecoverDelayBits);
@@ -6282,7 +6289,11 @@ void Player::unpackUpdate(NetConnection *con, BitStream *stream)
    if (stream->readFlag()) {
       mPredictionCount = sMaxPredictionTicks;
       mFalling = stream->readFlag();
-
+ 
+      mSwimming = stream->readFlag();
+      mJetting = stream->readFlag();  
+      mPose = (Pose)(stream->readInt(NumPoseBits)); 
+	  
       ActionState actionState = (ActionState)stream->readInt(NumStateBits);
       if (stream->readFlag()) {
          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;
 
    // Compute impulse
-   F32 d, n = -nv * (1.0f + restitution * rigid->restitution);
+   F32 d, n = -nv * (2.0f + restitution * rigid->restitution);
    Point3F a1,b1,c1;
    mCross(r1,normal,&a1);
    invWorldInertia.mulV(a1,&b1);
@@ -173,7 +173,7 @@ bool Rigid::resolveCollision(const Point3F& p, const Point3F &normal, Rigid* rig
 
    applyImpulse(r1,impulse);
    impulse.neg();
-   applyImpulse(r2,impulse);
+   rigid->applyImpulse(r2, impulse);
    return true;
 }
 

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

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

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

@@ -874,6 +874,7 @@ protected:
    /// @name Physical Properties
    /// @{
 
+   S32 mAiPose;                     ///< Current pose.
    F32 mEnergy;                     ///< Current enery level.
    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();
 }
 
+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);
 
 //-----------------------------------------------------------------------------

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

@@ -27,6 +27,7 @@
 #include "console/consoleInternal.h"
 #include "core/strings/stringUnit.h"
 #include "console/engineAPI.h"
+#include "core/stream/fileStream.h"
 
 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"
    );
 
+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, (),(),
    "Called whenever the DNS has been resolved.\n"
    );
@@ -355,7 +365,7 @@ void TCPObject::onConnectFailed()
    onConnectFailed_callback();
 }
 
-void TCPObject::finishLastLine()
+bool TCPObject::finishLastLine()
 {
    if(mBufferSize)
    {
@@ -364,6 +374,25 @@ void TCPObject::finishLastLine()
       dFree(mBuffer);
       mBuffer = 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));
 }
 
+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),, 
    "@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) );
 }
 
+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),, 
    "@brief Start listening on the specified port for connections.\n\n"
 
@@ -499,6 +561,29 @@ void processConnectedReceiveEvent(NetSocket sock, RawData incomingData)
       size -= 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)

+ 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, onLine, (const char* line));
+	DECLARE_CALLBACK(bool, onPacket, (const char* data));
+	DECLARE_CALLBACK(void, onEndReceive, ());
 	DECLARE_CALLBACK(void, onDNSResolved,());
 	DECLARE_CALLBACK(void, onDNSFailed, ());
 	DECLARE_CALLBACK(void, onConnected, ());
@@ -60,7 +62,9 @@ public:
    virtual ~TCPObject();
 
    void parseLine(U8 *buffer, U32 *start, U32 bufferLen);
-   void finishLastLine();
+   bool finishLastLine();
+   bool isBufferEmpty();
+   void emptyBuffer();
 
    static TCPObject *find(NetSocket tag);
 
@@ -81,6 +85,12 @@ public:
 
    bool processArguments(S32 argc, ConsoleValueRef *argv);
    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 removeFromTable();
 

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

@@ -61,7 +61,7 @@ CodeBlock::CodeBlock()
 CodeBlock::~CodeBlock()
 {
    // 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)
       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)
    {
-      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)
       {
          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);
 }
 
+inline U16 dAtous(const char *str, U32 base = 10)
+{
+   return strtoul(str, NULL, base);
+}
+
 inline F32 dAtof(const char *str)
 {
    return strtof(str, NULL);
 }
 
+inline F64 dAtod(const char *str)
+{
+   return strtod(str, NULL);
+}
 
 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());
 }
+
+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 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
    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);
       //mBandMod = 1.0f;
       //mCurrentBandColor = color;
@@ -411,7 +411,7 @@ void TimeOfDay::_getSunColor( ColorF *outColor ) const
 
    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);
       //mBandMod = 1.0f;
       //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, 
                                                             U32 numPrimitives, 
-                                                            GFXBufferType bufferType )
+                                                            GFXBufferType bufferType,
+                                                            void* data )
 {
    // Allocate a buffer to return
    GFXD3D9PrimitiveBuffer * res = new GFXD3D9PrimitiveBuffer(this, numIndices, numPrimitives, bufferType);
@@ -741,12 +742,13 @@ GFXPrimitiveBuffer * GFXD3D9Device::allocPrimitiveBuffer(   U32 numIndices,
    D3DPOOL pool = D3DPOOL_DEFAULT;
 
    // Assumptions:
-   //    - static buffers are write once, use many
+   //    - static buffers are write rarely, use many
    //    - dynamic buffers are write many, use many
    //    - volatile buffers are write once, use once
    // You may never read from a buffer.
    switch(bufferType)
    {
+   case GFXBufferTypeImmutable:
    case GFXBufferTypeStatic:
       pool = isD3D9Ex() ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
       break;
@@ -781,6 +783,14 @@ GFXPrimitiveBuffer * GFXD3D9Device::allocPrimitiveBuffer(   U32 numIndices,
       D3D9Assert(mD3DDevice->CreateIndexBuffer( sizeof(U16) * numIndices , usage, GFXD3D9IndexFormat[GFXIndexFormat16], pool, &res->ib, 0),
          "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;
 }
@@ -791,7 +801,8 @@ GFXPrimitiveBuffer * GFXD3D9Device::allocPrimitiveBuffer(   U32 numIndices,
 GFXVertexBuffer * GFXD3D9Device::allocVertexBuffer(   U32 numVerts, 
                                                       const GFXVertexFormat *vertexFormat, 
                                                       U32 vertSize, 
-                                                      GFXBufferType bufferType )
+                                                      GFXBufferType bufferType, 
+                                                      void* data)
 {
    PROFILE_SCOPE( GFXD3D9Device_allocVertexBuffer );
 
@@ -808,7 +819,7 @@ GFXVertexBuffer * GFXD3D9Device::allocVertexBuffer(   U32 numVerts,
    res->mNumVerts = 0;
 
    // Assumptions:
-   //    - static buffers are write once, use many
+   //    - static buffers are write rarely, use many
    //    - dynamic buffers are write many, use many
    //    - volatile buffers are write once, use once
    // You may never read from a buffer.
@@ -850,6 +861,15 @@ GFXVertexBuffer * GFXD3D9Device::allocVertexBuffer(   U32 numVerts,
    }
 
    res->mNumVerts = numVerts;
+   
+   if(data)
+   {
+      void* dest;
+      res->lock(0, numVerts, &dest);
+      dMemcpy(dest, data, vertSize * numVerts);
+      res->unlock();
+   }
+   
    return res;
 }
 

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

@@ -298,10 +298,12 @@ public:
    virtual GFXVertexBuffer* allocVertexBuffer(  U32 numVerts, 
                                                 const GFXVertexFormat *vertexFormat,
                                                 U32 vertSize,
-                                                GFXBufferType bufferType );
+                                                GFXBufferType bufferType,
+                                                void* data = NULL );
    virtual GFXPrimitiveBuffer *allocPrimitiveBuffer(  U32 numIndices, 
                                                       U32 numPrimitives, 
-                                                      GFXBufferType bufferType );
+                                                      GFXBufferType bufferType,
+                                                      void* data = NULL );
    virtual void deallocVertexBuffer( GFXD3D9VertexBuffer *vertBuff );
    virtual GFXVertexDecl* allocVertexDecl( const GFXVertexFormat *vertexFormat );
    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;
    switch(mBufferType)
    {
+   case GFXBufferTypeImmutable:
    case GFXBufferTypeStatic:
       // flags |= D3DLOCK_DISCARD;
       break;

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

@@ -276,14 +276,16 @@ GFXNullDevice::~GFXNullDevice()
 GFXVertexBuffer *GFXNullDevice::allocVertexBuffer( U32 numVerts, 
                                                    const GFXVertexFormat *vertexFormat,
                                                    U32 vertSize, 
-                                                   GFXBufferType bufferType ) 
+                                                   GFXBufferType bufferType,
+                                                   void* data ) 
 {
    return new GFXNullVertexBuffer(GFX, numVerts, vertexFormat, vertSize, bufferType);
 }
 
 GFXPrimitiveBuffer *GFXNullDevice::allocPrimitiveBuffer( U32 numIndices, 
                                                          U32 numPrimitives, 
-                                                         GFXBufferType bufferType) 
+                                                         GFXBufferType bufferType,
+                                                         void* data ) 
 {
    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, 
                                                 const GFXVertexFormat *vertexFormat, 
                                                 U32 vertSize, 
-                                                GFXBufferType bufferType );
+                                                GFXBufferType bufferType,
+                                                void* data = NULL );
    virtual GFXPrimitiveBuffer *allocPrimitiveBuffer(  U32 numIndices, 
                                                       U32 numPrimitives, 
-                                                      GFXBufferType bufferType );
+                                                      GFXBufferType bufferType,
+                                                      void* data = NULL );
 
    virtual GFXVertexDecl* allocVertexDecl( const GFXVertexFormat *vertexFormat ) { return NULL; }
    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)
 {
-   AssertISV(false, "GBitmap::writeTGA - doesn't support writing tga files!")
+   AssertISV(false, "GBitmap::writeTGA - doesn't support writing tga files!");
 
    return false;
 }

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

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

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

@@ -39,8 +39,8 @@
 
 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.
       GFXBufferTypeDynamic,  ///< Dynamic vertex buffers are meant for vertices that can be changed
                    ///< often.  Vertices written into dynamic vertex buffers will remain valid
@@ -48,7 +48,8 @@ enum GFXBufferType
                    ///< allowed.
       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.
-      
+      GFXBufferTypeImmutable, ///< Immutable buffers must specify the data when creating the buffer. Cannot be modified.
+
       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;
 #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 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)
    {

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

@@ -355,23 +355,47 @@ GFXPrimitiveBuffer* GFXGLDevice::findVolatilePBO(U32 numIndices, U32 numPrimitiv
 GFXVertexBuffer *GFXGLDevice::allocVertexBuffer(   U32 numVerts, 
                                                    const GFXVertexFormat *vertexFormat, 
                                                    U32 vertSize, 
-                                                   GFXBufferType bufferType ) 
+                                                   GFXBufferType bufferType,
+                                                   void* data )  
 {
    if(bufferType == GFXBufferTypeVolatile)
       return findVolatileVBO(numVerts, vertexFormat, vertSize);
          
    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;
 }
 
-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)
-      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;
 }
 

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

@@ -173,8 +173,9 @@ protected:
    virtual GFXVertexBuffer *allocVertexBuffer(  U32 numVerts, 
                                                 const GFXVertexFormat *vertexFormat,
                                                 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
    // 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[GFXBufferTypeDynamic] = GL_DYNAMIC_DRAW;
    GFXGLBufferType[GFXBufferTypeVolatile] = GL_STREAM_DRAW;
+   GFXGLBufferType[GFXBufferTypeImmutable] = GL_STATIC_DRAW;
 
    // Primitives
    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;
 }
+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 ),,
    "Calculate the magnitude of the given 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 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
-   /*!
-      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.
@@ -86,27 +84,27 @@ public:
       #define ON_FAIL_ASSERTFATAL
    #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
-   #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
 
 /*!
@@ -121,10 +119,7 @@ public:
    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.
  */
-#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.

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

@@ -503,7 +503,7 @@ bool Net::openPort(S32 port, bool doBind)
 	  }
 
       if(error == NoError)
-         error = setBufferSize(udpSocket, 32768);
+         error = setBufferSize(udpSocket, 32768*8);
 
       if(error == NoError && !useVDP)
          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.
    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)
    {
       walk->mFirstProfilerData = 0;

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

@@ -32,6 +32,16 @@
 typedef signed _int64   S64;
 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

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

@@ -338,14 +338,10 @@ void RenderParticleMgr::render( SceneRenderState *state )
 void RenderParticleMgr::_initGFXResources()
 {
    // 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);
    CompositeQuadVert *verts = mScreenQuadVertBuff.lock();

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

@@ -964,7 +964,7 @@ void NetConnection::activateGhosting()
         // Iterate through the scope always objects...
         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.
             mGhostArray[j]->updateMask = 0;
@@ -1015,7 +1015,7 @@ void NetConnection::activateGhosting()
         // Iterate through the scope always objects...
         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.
             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 )
 {
    //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
    mTimes = new F32[count];

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

@@ -142,8 +142,8 @@ inline void CatmullRom<TYPE>::clear()
 template<typename TYPE>
 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.
    clear();