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

# Conflicts resolved:
#	Engine/source/console/consoleFunctions.cpp
This commit is contained in:
Anis A. Hireche 2016-02-26 21:58:01 +01:00
commit b3662d801a
42 changed files with 606 additions and 115 deletions

View file

@ -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();
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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;
}

View file

@ -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 ),

View file

@ -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).

View file

@ -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);
//-----------------------------------------------------------------------------

View file

@ -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)

View file

@ -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();

View file

@ -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();

View file

@ -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

View file

@ -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--;

View file

@ -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)
{

View file

@ -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);
}

View file

@ -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);
/// @}

View file

@ -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;

View file

@ -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;
}

View file

@ -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 );

View file

@ -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;

View file

@ -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);
}

View file

@ -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 ) { }

View file

@ -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;
}

View file

@ -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;
/// @}

View file

@ -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.
};

View file

@ -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
}

View file

@ -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)
{

View file

@ -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;
}

View file

@ -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

View file

@ -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;

View file

@ -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"

View file

@ -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;
}
//--------------------------------------

View file

@ -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.

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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();

View file

@ -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;

View file

@ -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];

View file

@ -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();