diff --git a/.gitignore b/.gitignore index 36919d3768..d3f9aff55c 100644 --- a/.gitignore +++ b/.gitignore @@ -169,4 +169,7 @@ pip-log.txt console.log *.cached.dts !Engine/bin -My Projects/ \ No newline at end of file +My Projects/ +Project Manager.exe +projects.xml +Qt*.dll diff --git a/Engine/source/T3D/convexShape.cpp b/Engine/source/T3D/convexShape.cpp index 713f52ccdb..622b28fa25 100644 --- a/Engine/source/T3D/convexShape.cpp +++ b/Engine/source/T3D/convexShape.cpp @@ -367,7 +367,14 @@ void ConvexShape::writeFields( Stream &stream, U32 tabStop ) stream.write(2, "\r\n"); - for ( U32 i = 0; i < mSurfaces.size(); i++ ) + S32 count = mSurfaces.size(); + if ( count > smMaxSurfaces ) + { + Con::errorf( "ConvexShape has too many surfaces to save! Truncated value %d to maximum value of %d", count, smMaxSurfaces ); + count = smMaxSurfaces; + } + + for ( U32 i = 0; i < count; i++ ) { const MatrixF &mat = mSurfaces[i]; @@ -423,12 +430,18 @@ U32 ConvexShape::packUpdate( NetConnection *conn, U32 mask, BitStream *stream ) if ( stream->writeFlag( mask & UpdateMask ) ) { stream->write( mMaterialName ); - - const U32 surfCount = mSurfaces.size(); + + U32 surfCount = mSurfaces.size(); stream->writeInt( surfCount, 32 ); - for ( S32 i = 0; i < surfCount; i++ ) - mathWrite( *stream, mSurfaces[i] ); + for ( S32 i = 0; i < surfCount; i++ ) + { + QuatF quat( mSurfaces[i] ); + Point3F pos( mSurfaces[i].getPosition() ); + + mathWrite( *stream, quat ); + mathWrite( *stream, pos ); + } } return retMask; @@ -462,7 +475,14 @@ void ConvexShape::unpackUpdate( NetConnection *conn, BitStream *stream ) mSurfaces.increment(); MatrixF &mat = mSurfaces.last(); - mathRead( *stream, &mat ); + QuatF quat; + Point3F pos; + + mathRead( *stream, &quat ); + mathRead( *stream, &pos ); + + quat.setMatrix( &mat ); + mat.setPosition( pos ); } if ( isProperlyAdded() ) diff --git a/Engine/source/T3D/convexShape.h b/Engine/source/T3D/convexShape.h index ed9f23d2e0..d0f30eeaab 100644 --- a/Engine/source/T3D/convexShape.h +++ b/Engine/source/T3D/convexShape.h @@ -141,6 +141,10 @@ class ConvexShape : public SceneObject static bool smRenderEdges; + // To prevent bitpack overflows. + // This is only indirectly enforced by trucation when serializing. + static const S32 smMaxSurfaces = 100; + public: ConvexShape(); diff --git a/Engine/source/T3D/fps/guiHealthTextHud.cpp b/Engine/source/T3D/fps/guiHealthTextHud.cpp new file mode 100644 index 0000000000..a8a33d3f36 --- /dev/null +++ b/Engine/source/T3D/fps/guiHealthTextHud.cpp @@ -0,0 +1,200 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +// ---------------------------------------------------------------------------- +// A gui control that displays health or energy information. Based upon the +// stock healthBar control but rewritten by M.Hall to display a numerical value. +// ---------------------------------------------------------------------------- + +#include "platform/platform.h" +#include "gui/core/guiControl.h" +#include "console/consoleTypes.h" +#include "T3D/gameBase/gameConnection.h" +#include "T3D/shapeBase.h" +#include "gfx/gfxDrawUtil.h" + +class GuiHealthTextHud : public GuiControl +{ + typedef GuiControl Parent; + + bool mShowFrame; + bool mShowFill; + bool mShowEnergy; + bool mShowTrueHealth; + + ColorF mFillColor; + ColorF mFrameColor; + ColorF mTextColor; + ColorF mWarnColor; + + F32 mWarnLevel; + F32 mPulseThreshold; + S32 mPulseRate; + + F32 mValue; + +public: + GuiHealthTextHud(); + + void onRender(Point2I, const RectI &); + static void initPersistFields(); + DECLARE_CONOBJECT(GuiHealthTextHud); + DECLARE_CATEGORY("Gui Game"); + DECLARE_DESCRIPTION("Shows the damage or energy level of the current\n" + "PlayerObjectType control object as a numerical text display."); +}; + +// ---------------------------------------------------------------------------- + +IMPLEMENT_CONOBJECT(GuiHealthTextHud); + +ConsoleDocClass(GuiHealthTextHud, + "@brief Shows the health or energy value of the current PlayerObjectType control object.\n\n" + "This gui can be configured to display either the health or energy value of the current Player Object. " + "It can use an alternate display color if the health or drops below a set value. " + "It can also be set to pulse if the health or energy drops below a set value. " + "This control only works if a server connection exists and it's control object " + "is a PlayerObjectType. If either of these requirements is false, the control is not rendered.\n\n" + + "@tsexample\n" + "\n new GuiHealthTextHud()" + "{\n" + " fillColor = \"0.0 0.0 0.0 0.5\"; // Fills with a transparent black color\n" + " frameColor = \"1.0 1.0 1.0 1.0\"; // Solid white frame color\n" + " textColor = \"0.0 1.0 0.0 1.0\" // Solid green text color\n" + " warningColor = \"1.0 0.0 0.0 1.0\"; // Solid red color, used when damaged\n" + " showFill = \"true\";\n" + " showFrame = \"true\";\n" + " showTrueValue = \"false\";\n" + " showEnergy = \"false\";\n" + " warnThreshold = \"50\";\n" + " pulseThreshold = \"25\";\n" + " pulseRate = \"500\";\n" + " profile = \"GuiBigTextProfile\";\n" + "};\n" + "@endtsexample\n\n" + + "@ingroup GuiGame\n" +); + +GuiHealthTextHud::GuiHealthTextHud() +{ + mShowFrame = mShowFill = true; + mShowEnergy = false; + mShowTrueHealth = false; + + mFillColor.set(0, 0, 0, 0.5); + mFrameColor.set(1, 1, 1, 1); + mTextColor.set(0, 1, 0, 1); + mWarnColor.set(1, 0, 0, 1); + + mWarnLevel = 50.0f; + mPulseThreshold = 25.0f; + mPulseRate = 0; + + mValue = 0.2f; +} + +void GuiHealthTextHud::initPersistFields() +{ + addGroup("Colors"); + addField("fillColor", TypeColorF, Offset(mFillColor, GuiHealthTextHud), "Color for the background of the control."); + addField("frameColor", TypeColorF, Offset(mFrameColor, GuiHealthTextHud), "Color for the control's frame."); + addField("textColor", TypeColorF, Offset(mTextColor, GuiHealthTextHud), "Color for the text on this control."); + addField("warningColor", TypeColorF, Offset(mWarnColor, GuiHealthTextHud), "Color for the text when health is low."); + endGroup("Colors"); + + addGroup("View"); + addField("showFill", TypeBool, Offset(mShowFill, GuiHealthTextHud), "If true, draw the background."); + addField("showFrame", TypeBool, Offset(mShowFrame, GuiHealthTextHud), "If true, draw the frame."); + addField("showTrueValue", TypeBool, Offset(mShowTrueHealth, GuiHealthTextHud), "If true, we don't hardcode maxHealth to 100."); + addField("showEnergy", TypeBool, Offset(mShowEnergy, GuiHealthTextHud), "If true, display the energy value rather than the damage value."); + endGroup("View"); + + addGroup("Alert"); + addField("warnThreshold", TypeF32, Offset(mWarnLevel, GuiHealthTextHud), "The health level at which to use the warningColor."); + addField("pulseThreshold", TypeF32, Offset(mPulseThreshold, GuiHealthTextHud), "Health level at which to begin pulsing."); + addField("pulseRate", TypeS32, Offset(mPulseRate, GuiHealthTextHud), "Speed at which the control will pulse."); + endGroup("Alert"); + + Parent::initPersistFields(); +} + +// ---------------------------------------------------------------------------- + +void GuiHealthTextHud::onRender(Point2I offset, const RectI &updateRect) +{ + // Must have a connection and player control object + GameConnection* conn = GameConnection::getConnectionToServer(); + if (!conn) + return; + ShapeBase* control = dynamic_cast(conn->getControlObject()); + if (!control || !(control->getTypeMask() & PlayerObjectType)) + return; + + // Just grab the damage/energy right off the control object. + // Damage value 0 = no damage (full health). + if(mShowEnergy) + mValue = control->getEnergyLevel(); + else + { + if (mShowTrueHealth) + mValue = control->getMaxDamage() - control->getDamageLevel(); + else + mValue = 100 - (100 * control->getDamageValue()); + } + + // If enabled draw background first + if (mShowFill) + GFX->getDrawUtil()->drawRectFill(updateRect, mFillColor); + + // Prepare text and center it + S32 val = (S32)mValue; + char buf[256]; + dSprintf(buf, sizeof(buf), "%d", val); + offset.x += (getBounds().extent.x - mProfile->mFont->getStrWidth((const UTF8 *)buf)) / 2; + offset.y += (getBounds().extent.y - mProfile->mFont->getHeight()) / 2; + + ColorF tColor = mTextColor; + + // If warning level is exceeded switch to warning color + if(mValue < mWarnLevel) + { + tColor = mWarnColor; + + // If the pulseRate is set then pulse the text if health is below the threshold + if (mPulseRate != 0 && mValue < mPulseThreshold) + { + U32 time = Platform::getVirtualMilliseconds(); + F32 alpha = 2.0f * F32(time % mPulseRate) / F32(mPulseRate); + tColor.alpha = (alpha > 1.0f)? 2.0f - alpha: alpha; + } + } + + GFX->getDrawUtil()->setBitmapModulation(tColor); + GFX->getDrawUtil()->drawText(mProfile->mFont, offset, buf); + GFX->getDrawUtil()->clearBitmapModulation(); + + // If enabled draw the border last + if (mShowFrame) + GFX->getDrawUtil()->drawRect(updateRect, mFrameColor); +} \ No newline at end of file diff --git a/Engine/source/T3D/fx/explosion.cpp b/Engine/source/T3D/fx/explosion.cpp index 58b57bf157..b84efad3f3 100644 --- a/Engine/source/T3D/fx/explosion.cpp +++ b/Engine/source/T3D/fx/explosion.cpp @@ -151,7 +151,7 @@ DefineEngineFunction(calcExplosionCoverage, F32, (Point3F pos, S32 id, U32 covMa SceneObject* sceneObject = NULL; if (Sim::findObject(id, sceneObject) == false) { - Con::warnf(ConsoleLogEntry::General, "calcExplosionCoverage: couldn't find object: %s", id); + Con::warnf(ConsoleLogEntry::General, "calcExplosionCoverage: couldn't find object: %d", id); return 1.0f; } if (sceneObject->isClientObject() || sceneObject->getContainer() == NULL) { diff --git a/Engine/source/T3D/fx/particle.cpp b/Engine/source/T3D/fx/particle.cpp index 891f9353b7..2e331fb7ff 100644 --- a/Engine/source/T3D/fx/particle.cpp +++ b/Engine/source/T3D/fx/particle.cpp @@ -21,6 +21,7 @@ //----------------------------------------------------------------------------- #include "particle.h" #include "console/consoleTypes.h" +#include "console/typeValidators.h" #include "core/stream/bitStream.h" #include "math/mRandom.h" #include "math/mathIO.h" @@ -132,13 +133,13 @@ ParticleData::~ParticleData() //----------------------------------------------------------------------------- void ParticleData::initPersistFields() { - addField( "dragCoefficient", TYPEID< F32 >(), Offset(dragCoefficient, ParticleData), + addFieldV( "dragCoefficient", TYPEID< F32 >(), Offset(dragCoefficient, ParticleData), new FRangeValidator(0, 5), "Particle physics drag amount." ); addField( "windCoefficient", TYPEID< F32 >(), Offset(windCoefficient, ParticleData), "Strength of wind on the particles." ); - addField( "gravityCoefficient", TYPEID< F32 >(), Offset(gravityCoefficient, ParticleData), + addFieldV( "gravityCoefficient", TYPEID< F32 >(), Offset(gravityCoefficient, ParticleData), new FRangeValidator(-10, 10), "Strength of gravity on the particles." ); - addField( "inheritedVelFactor", TYPEID< F32 >(), Offset(inheritedVelFactor, ParticleData), + addFieldV( "inheritedVelFactor", TYPEID< F32 >(), Offset(inheritedVelFactor, ParticleData), &CommonValidators::NormalizedFloat, "Amount of emitter velocity to add to particle initial velocity." ); addField( "constantAcceleration", TYPEID< F32 >(), Offset(constantAcceleration, ParticleData), "Constant acceleration to apply to this particle." ); diff --git a/Engine/source/T3D/fx/particleEmitter.cpp b/Engine/source/T3D/fx/particleEmitter.cpp index eb0d120ed9..100fbe1854 100644 --- a/Engine/source/T3D/fx/particleEmitter.cpp +++ b/Engine/source/T3D/fx/particleEmitter.cpp @@ -26,6 +26,7 @@ #include "scene/sceneManager.h" #include "scene/sceneRenderState.h" #include "console/consoleTypes.h" +#include "console/typeValidators.h" #include "core/stream/bitStream.h" #include "core/strings/stringUnit.h" #include "math/mRandom.h" @@ -177,31 +178,31 @@ void ParticleEmitterData::initPersistFields() { addGroup( "ParticleEmitterData" ); - addField("ejectionPeriodMS", TYPEID< S32 >(), Offset(ejectionPeriodMS, ParticleEmitterData), + addFieldV("ejectionPeriodMS", TYPEID< S32 >(), Offset(ejectionPeriodMS, ParticleEmitterData), new IRangeValidator(1, 2047), "Time (in milliseconds) between each particle ejection." ); - addField("periodVarianceMS", TYPEID< S32 >(), Offset(periodVarianceMS, ParticleEmitterData), + addFieldV("periodVarianceMS", TYPEID< S32 >(), Offset(periodVarianceMS, ParticleEmitterData), new IRangeValidator(0, 2047), "Variance in ejection period, from 1 - ejectionPeriodMS." ); - addField( "ejectionVelocity", TYPEID< F32 >(), Offset(ejectionVelocity, ParticleEmitterData), + addFieldV( "ejectionVelocity", TYPEID< F32 >(), Offset(ejectionVelocity, ParticleEmitterData), new FRangeValidator(0, 655.35f), "Particle ejection velocity." ); - addField( "velocityVariance", TYPEID< F32 >(), Offset(velocityVariance, ParticleEmitterData), + addFieldV( "velocityVariance", TYPEID< F32 >(), Offset(velocityVariance, ParticleEmitterData), new FRangeValidator(0, 163.83f), "Variance for ejection velocity, from 0 - ejectionVelocity." ); - addField( "ejectionOffset", TYPEID< F32 >(), Offset(ejectionOffset, ParticleEmitterData), + addFieldV( "ejectionOffset", TYPEID< F32 >(), Offset(ejectionOffset, ParticleEmitterData), new FRangeValidator(0, 655.35f), "Distance along ejection Z axis from which to eject particles." ); - addField( "thetaMin", TYPEID< F32 >(), Offset(thetaMin, ParticleEmitterData), + addFieldV( "thetaMin", TYPEID< F32 >(), Offset(thetaMin, ParticleEmitterData), new FRangeValidator(0, 180.0f), "Minimum angle, from the horizontal plane, to eject from." ); - addField( "thetaMax", TYPEID< F32 >(), Offset(thetaMax, ParticleEmitterData), + addFieldV( "thetaMax", TYPEID< F32 >(), Offset(thetaMax, ParticleEmitterData), new FRangeValidator(0, 180.0f), "Maximum angle, from the horizontal plane, to eject particles from." ); - addField( "phiReferenceVel", TYPEID< F32 >(), Offset(phiReferenceVel, ParticleEmitterData), + addFieldV( "phiReferenceVel", TYPEID< F32 >(), Offset(phiReferenceVel, ParticleEmitterData), new FRangeValidator(0, 360.0f), "Reference angle, from the vertical plane, to eject particles from." ); - addField( "phiVariance", TYPEID< F32 >(), Offset(phiVariance, ParticleEmitterData), + addFieldV( "phiVariance", TYPEID< F32 >(), Offset(phiVariance, ParticleEmitterData), new FRangeValidator(0, 360.0f), "Variance from the reference angle, from 0 - 360." ); addField( "softnessDistance", TYPEID< F32 >(), Offset(softnessDistance, ParticleEmitterData), @@ -302,8 +303,8 @@ void ParticleEmitterData::packData(BitStream* stream) { Parent::packData(stream); - stream->writeInt(ejectionPeriodMS, 10); - stream->writeInt(periodVarianceMS, 10); + stream->writeInt(ejectionPeriodMS, 11); // must match limit on valid range in ParticleEmitterData::initPersistFields + stream->writeInt(periodVarianceMS, 11); stream->writeInt((S32)(ejectionVelocity * 100), 16); stream->writeInt((S32)(velocityVariance * 100), 14); if( stream->writeFlag( ejectionOffset != sgDefaultEjectionOffset ) ) @@ -352,8 +353,8 @@ void ParticleEmitterData::unpackData(BitStream* stream) { Parent::unpackData(stream); - ejectionPeriodMS = stream->readInt(10); - periodVarianceMS = stream->readInt(10); + ejectionPeriodMS = stream->readInt(11); + periodVarianceMS = stream->readInt(11); ejectionVelocity = stream->readInt(16) / 100.0f; velocityVariance = stream->readInt(14) / 100.0f; if( stream->readFlag() ) diff --git a/Engine/source/T3D/gameBase/extended/extendedGameProcess.cpp b/Engine/source/T3D/gameBase/extended/extendedGameProcess.cpp new file mode 100644 index 0000000000..c3d35eba6d --- /dev/null +++ b/Engine/source/T3D/gameBase/extended/extendedGameProcess.cpp @@ -0,0 +1,379 @@ +#include "platform/platform.h" +#include "T3D/gameBase/extended/extendedGameProcess.h" +#include "T3D/gameBase/extended/extendedMoveList.h" + +#include "platform/profiler.h" +#include "console/consoleTypes.h" +#include "core/dnet.h" +#include "core/stream/bitStream.h" +#include "core/frameAllocator.h" +#include "core/util/refBase.h" +#include "math/mPoint3.h" +#include "math/mMatrix.h" +#include "math/mathUtils.h" +#include "T3D/gameBase/gameBase.h" +#include "T3D/gameBase/gameConnection.h" +#include "T3D/fx/cameraFXMgr.h" + +MODULE_BEGIN( ProcessList ) + + MODULE_INIT + { + ExtendedServerProcessList::init(); + ExtendedClientProcessList::init(); + } + + MODULE_SHUTDOWN + { + ExtendedServerProcessList::shutdown(); + ExtendedClientProcessList::shutdown(); + } + +MODULE_END; + +void ExtendedServerProcessList::init() +{ + smServerProcessList = new ExtendedServerProcessList(); +} + +void ExtendedServerProcessList::shutdown() +{ + delete smServerProcessList; +} + +void ExtendedClientProcessList::init() +{ + smClientProcessList = new ExtendedClientProcessList(); +} + +void ExtendedClientProcessList::shutdown() +{ + delete smClientProcessList; +} + +//---------------------------------------------------------------------------- + + +namespace +{ + // local work class + struct GameBaseListNode + { + GameBaseListNode() + { + mPrev=this; + mNext=this; + mObject=NULL; + } + + GameBaseListNode * mPrev; + GameBaseListNode * mNext; + GameBase * mObject; + + void linkBefore(GameBaseListNode * obj) + { + // Link this before obj + mNext = obj; + mPrev = obj->mPrev; + obj->mPrev = this; + mPrev->mNext = this; + } + }; +} // namespace + +//-------------------------------------------------------------------------- +// ExtendedClientProcessList +//-------------------------------------------------------------------------- + +ExtendedClientProcessList::ExtendedClientProcessList() +{ +} + +bool ExtendedClientProcessList::advanceTime( SimTime timeDelta ) +{ + PROFILE_SCOPE( ExtendedClientProcessList_AdvanceTime ); + + if ( doBacklogged( timeDelta ) ) + return false; + + bool ret = Parent::advanceTime( timeDelta ); + ProcessObject *obj = NULL; + + AssertFatal( mLastDelta >= 0.0f && mLastDelta <= 1.0f, "mLastDelta is not zero to one."); + + obj = mHead.mProcessLink.next; + while ( obj != &mHead ) + { + if ( obj->isTicking() ) + obj->interpolateTick( mLastDelta ); + + obj = obj->mProcessLink.next; + } + + // Inform objects of total elapsed delta so they can advance + // client side animations. + F32 dt = F32(timeDelta) / 1000; + + // Update camera FX. + gCamFXMgr.update( dt ); + + obj = mHead.mProcessLink.next; + while ( obj != &mHead ) + { + obj->advanceTime( dt ); + obj = obj->mProcessLink.next; + } + + return ret; +} + +//---------------------------------------------------------------------------- +void ExtendedClientProcessList::onAdvanceObjects() +{ + PROFILE_SCOPE( ExtendedClientProcessList_OnAdvanceObjects ); + + GameConnection* connection = GameConnection::getConnectionToServer(); + if ( connection ) + { + // process any demo blocks that are NOT moves, and exactly one move + // we advance time in the demo stream by a move inserted on + // each tick. So before doing the tick processing we advance + // the demo stream until a move is ready + if ( connection->isPlayingBack() ) + { + U32 blockType; + do + { + blockType = connection->getNextBlockType(); + bool res = connection->processNextBlock(); + // if there are no more blocks, exit out of this function, + // as no more client time needs to process right now - we'll + // get it all on the next advanceClientTime() + if(!res) + return; + } + while ( blockType != GameConnection::BlockTypeMove ); + } + + connection->mMoveList->collectMove(); + advanceObjects(); + } + else + advanceObjects(); +} + +void ExtendedClientProcessList::onTickObject( ProcessObject *obj ) +{ + PROFILE_SCOPE( ExtendedClientProcessList_OnTickObject ); + + // In case the object deletes itself during its processTick. + SimObjectPtr safePtr = static_cast( obj ); + + // Each object is either advanced a single tick, or if it's + // being controlled by a client, ticked once for each pending move. + ExtendedMove* extMovePtr; + U32 numMoves; + GameConnection* con = obj->getControllingClient(); + if ( con && con->getControlObject() == obj ) + { + ExtendedMoveList* extMoveList = static_cast(con->mMoveList); + extMoveList->getExtMoves( &extMovePtr, &numMoves ); + if ( numMoves ) + { + // Note: should only have a single move at this point + AssertFatal(numMoves==1,"ClientProccessList::onTickObject: more than one move in queue"); + + #ifdef TORQUE_DEBUG_NET_MOVES + U32 sum = Move::ChecksumMask & obj->getPacketDataChecksum(obj->getControllingClient()); + #endif + + if ( obj->isTicking() ) + obj->processTick( extMovePtr ); + + if ( bool(safePtr) && obj->getControllingClient() ) + { + U32 newsum = Move::ChecksumMask & obj->getPacketDataChecksum( obj->getControllingClient() ); + + // set checksum if not set or check against stored value if set + extMovePtr->checksum = newsum; + + #ifdef TORQUE_DEBUG_NET_MOVES + Con::printf("move checksum: %i, (start %i), (move %f %f %f)", + movePtr->checksum,sum,movePtr->yaw,movePtr->y,movePtr->z); + #endif + } + con->mMoveList->clearMoves( 1 ); + } + } + else if ( obj->isTicking() ) + obj->processTick( 0 ); +} + +void ExtendedClientProcessList::advanceObjects() +{ + PROFILE_SCOPE( ExtendedClientProcessList_AdvanceObjects ); + + #ifdef TORQUE_DEBUG_NET_MOVES + Con::printf("Advance client time..."); + #endif + + Parent::advanceObjects(); + + #ifdef TORQUE_DEBUG_NET_MOVES + Con::printf("---------"); + #endif +} + +void ExtendedClientProcessList::clientCatchup( GameConnection * connection ) +{ + SimObjectPtr control = connection->getControlObject(); + if ( control ) + { + ExtendedMove * extMovePtr; + U32 numMoves; + U32 m = 0; + ExtendedMoveList* extMoveList = static_cast(connection->mMoveList); + extMoveList->getExtMoves( &extMovePtr, &numMoves ); + + #ifdef TORQUE_DEBUG_NET_MOVES + Con::printf("client catching up... (%i)", numMoves); + #endif + + preTickSignal().trigger(); + + if ( control->isTicking() ) + for ( m = 0; m < numMoves; m++ ) + control->processTick( extMovePtr++ ); + + extMoveList->clearMoves( m ); + } + + #ifdef TORQUE_DEBUG_NET_MOVES + Con::printf("---------"); + #endif +} + +//-------------------------------------------------------------------------- +// ServerProcessList +//-------------------------------------------------------------------------- + +ExtendedServerProcessList::ExtendedServerProcessList() +{ +} + +void ExtendedServerProcessList::onPreTickObject( ProcessObject *pobj ) +{ + if ( pobj->mIsGameBase ) + { + SimObjectPtr obj = getGameBase( pobj ); + + // Each object is either advanced a single tick, or if it's + // being controlled by a client, ticked once for each pending move. + GameConnection *con = obj->getControllingClient(); + + if ( con && con->getControlObject() == obj ) + { + ExtendedMove* extMovePtr; + U32 numMoves; + ExtendedMoveList* extMoveList = static_cast(con->mMoveList); + extMoveList->getExtMoves( &extMovePtr, &numMoves ); + + if ( numMoves == 0 ) + { + #ifdef TORQUE_DEBUG_NET_MOVES + Con::printf("no moves on object %i, skip tick",obj->getId()); + #endif + return; + } + } + } + + Parent::onPreTickObject (pobj ); +} + +void ExtendedServerProcessList::onTickObject( ProcessObject *pobj ) +{ + PROFILE_SCOPE( ExtendedServerProcessList_OnTickObject ); + + // Each object is either advanced a single tick, or if it's + // being controlled by a client, ticked once for each pending move. + + GameConnection *con = pobj->getControllingClient(); + + if ( pobj->mIsGameBase && con && con->getControlObject() == pobj ) + { + // In case the object is deleted during its own tick. + SimObjectPtr obj = getGameBase( pobj ); + + ExtendedMove* extMovePtr; + U32 m, numMoves; + ExtendedMoveList* extMoveList = static_cast(con->mMoveList); + extMoveList->getExtMoves( &extMovePtr, &numMoves ); + + // For debugging it can be useful to know when this happens. + //if ( numMoves > 1 ) + // Con::printf( "numMoves: %i", numMoves ); + + // Do we really need to test the control object each iteration? Does it change? + for ( m = 0; m < numMoves && con && con->getControlObject() == obj; m++, extMovePtr++ ) + { + #ifdef TORQUE_DEBUG_NET_MOVES + U32 sum = Move::ChecksumMask & obj->getPacketDataChecksum(obj->getControllingClient()); + #endif + + if ( obj->isTicking() ) + obj->processTick( extMovePtr ); + + if ( con && con->getControlObject() == obj ) + { + U32 newsum = Move::ChecksumMask & obj->getPacketDataChecksum( obj->getControllingClient() ); + + // check move checksum + if ( extMovePtr->checksum != newsum ) + { + #ifdef TORQUE_DEBUG_NET_MOVES + if( !obj->isAIControlled() ) + Con::printf("move %i checksum disagree: %i != %i, (start %i), (move %f %f %f)", + extMovePtr->id, extMovePtr->checksum,newsum,sum,extMovePtr->yaw,extMovePtr->y,extMovePtr->z); + #endif + + extMovePtr->checksum = Move::ChecksumMismatch; + } + else + { + #ifdef TORQUE_DEBUG_NET_MOVES + Con::printf("move %i checksum agree: %i == %i, (start %i), (move %f %f %f)", + extMovePtr->id, extMovePtr->checksum,newsum,sum,extMovePtr->yaw,extMovePtr->y,extMovePtr->z); + #endif + } + } + } + + extMoveList->clearMoves( m ); + } + else if ( pobj->isTicking() ) + pobj->processTick( 0 ); +} + +void ExtendedServerProcessList::advanceObjects() +{ + #ifdef TORQUE_DEBUG_NET_MOVES + Con::printf("Advance server time..."); + #endif + + Parent::advanceObjects(); + + // Credit all connections with the elapsed tick + SimGroup *clientGroup = Sim::getClientGroup(); + for(SimGroup::iterator i = clientGroup->begin(); i != clientGroup->end(); i++) + { + if (GameConnection *con = dynamic_cast(*i)) + { + con->mMoveList->advanceMove(); + } + } + + #ifdef TORQUE_DEBUG_NET_MOVES + Con::printf("---------"); + #endif +} diff --git a/Engine/source/T3D/gameBase/extended/extendedGameProcess.h b/Engine/source/T3D/gameBase/extended/extendedGameProcess.h new file mode 100644 index 0000000000..22d78488ee --- /dev/null +++ b/Engine/source/T3D/gameBase/extended/extendedGameProcess.h @@ -0,0 +1,60 @@ +#ifndef _GAMEPROCESS_EXTENDED_H_ +#define _GAMEPROCESS_EXTENDED_H_ + +//#include "T3D/gameBase/processList.h" +#ifndef _GAMEPROCESS_H_ +#include "T3D/gameBase/gameProcess.h" +#endif + +class GameBase; +class GameConnection; +struct Move; + +//---------------------------------------------------------------------------- + +/// List to keep track of GameBases to process. +class ExtendedClientProcessList : public ClientProcessList +{ + typedef ClientProcessList Parent; + +protected: + + // ProcessList + void onTickObject(ProcessObject *); + void advanceObjects(); + void onAdvanceObjects(); + +public: + + ExtendedClientProcessList(); + + // ProcessList + bool advanceTime( SimTime timeDelta ); + + // ClientProcessList + void clientCatchup( GameConnection *conn ); + + static void init(); + static void shutdown(); +}; + +class ExtendedServerProcessList : public ServerProcessList +{ + typedef ServerProcessList Parent; + +protected: + + // ProcessList + void onPreTickObject( ProcessObject *pobj ); + void onTickObject( ProcessObject *pobj ); + void advanceObjects(); + +public: + + ExtendedServerProcessList(); + + static void init(); + static void shutdown(); +}; + +#endif // _GAMEPROCESS_EXTENDED_H_ diff --git a/Engine/source/T3D/gameBase/extended/extendedMove.cpp b/Engine/source/T3D/gameBase/extended/extendedMove.cpp new file mode 100644 index 0000000000..0006318d0f --- /dev/null +++ b/Engine/source/T3D/gameBase/extended/extendedMove.cpp @@ -0,0 +1,258 @@ +#include "T3D/gameBase/extended/extendedMove.h" +#include "core/stream/bitStream.h" +#include "math/mathIO.h" +#include "core/module.h" +#include "console/consoleTypes.h" +#include "core/strings/stringFunctions.h" + +MODULE_BEGIN( ExtendedMoveManager ) + + MODULE_INIT_AFTER( MoveManager ) + MODULE_INIT + { + ExtendedMoveManager::init(); + } + +MODULE_END; + +S32 ExtendedMoveManager::mPosX[ExtendedMove::MaxPositionsRotations] = { 0, }; +S32 ExtendedMoveManager::mPosY[ExtendedMove::MaxPositionsRotations] = { 0, }; +S32 ExtendedMoveManager::mPosZ[ExtendedMove::MaxPositionsRotations] = { 0, }; +F32 ExtendedMoveManager::mRotAX[ExtendedMove::MaxPositionsRotations] = { 0, }; +F32 ExtendedMoveManager::mRotAY[ExtendedMove::MaxPositionsRotations] = { 0, }; +F32 ExtendedMoveManager::mRotAZ[ExtendedMove::MaxPositionsRotations] = { 0, }; +F32 ExtendedMoveManager::mRotAA[ExtendedMove::MaxPositionsRotations] = { 1, }; + +void ExtendedMoveManager::init() +{ + for(U32 i = 0; i < ExtendedMove::MaxPositionsRotations; ++i) + { + char varName[256]; + + dSprintf(varName, sizeof(varName), "mvPosX%d", i); + Con::addVariable(varName, TypeS32, &mPosX[i], + "X position of controller in millimeters. Only 13 bits are networked.\n" + "@ingroup Game"); + + dSprintf(varName, sizeof(varName), "mvPosY%d", i); + Con::addVariable(varName, TypeS32, &mPosY[i], + "Y position of controller in millimeters. Only 13 bits are networked.\n" + "@ingroup Game"); + + dSprintf(varName, sizeof(varName), "mvPosZ%d", i); + Con::addVariable(varName, TypeS32, &mPosZ[i], + "Z position of controller in millimeters. Only 13 bits are networked.\n" + "@ingroup Game"); + + dSprintf(varName, sizeof(varName), "mvRotX%d", i); + Con::addVariable(varName, TypeF32, &mRotAX[i], + "X rotation vector component of controller.\n" + "@ingroup Game"); + + dSprintf(varName, sizeof(varName), "mvRotY%d", i); + Con::addVariable(varName, TypeF32, &mRotAY[i], + "Y rotation vector component of controller.\n" + "@ingroup Game"); + + dSprintf(varName, sizeof(varName), "mvRotZ%d", i); + Con::addVariable(varName, TypeF32, &mRotAZ[i], + "Z rotation vector component of controller.\n" + "@ingroup Game"); + + dSprintf(varName, sizeof(varName), "mvRotA%d", i); + Con::addVariable(varName, TypeF32, &mRotAA[i], + "Angle rotation (in degrees) component of controller.\n" + "@ingroup Game"); + } +} + +const ExtendedMove NullExtendedMove; + +#define CLAMPPOS(x) (x<0 ? -((-x) & (1<<(MaxPositionBits-1))-1) : (x & (1<<(MaxPositionBits-1))-1)) +#define CLAMPROT(f) ((S32)(((f + 1) * .5) * ((1 << MaxRotationBits) - 1)) & ((1<(basemove); + + bool extendedDifferent = false; + for(U32 i=0; iposX[i]) || + (posY[i] != extBaseMove->posY[i]) || + (posZ[i] != extBaseMove->posZ[i]) || + (rotX[i] != extBaseMove->rotX[i]) || + (rotY[i] != extBaseMove->rotY[i]) || + (rotZ[i] != extBaseMove->rotZ[i]) || + (rotW[i] != extBaseMove->rotW[i]); + + extendedDifferent = extendedDifferent || check; + } + + if (alwaysWriteAll || stream->writeFlag(extendedDifferent)) + { + for(U32 i=0; iwriteFlag(posX[i] != extBaseMove->posX[i])) + stream->writeSignedInt(posX[i], MaxPositionBits); + if(stream->writeFlag(posY[i] != extBaseMove->posY[i])) + stream->writeSignedInt(posY[i], MaxPositionBits); + if(stream->writeFlag(posZ[i] != extBaseMove->posZ[i])) + stream->writeSignedInt(posZ[i], MaxPositionBits); + + // Rotation + if(stream->writeFlag(rotX[i] != extBaseMove->rotX[i])) + stream->writeInt(crotX[i], MaxRotationBits); + if(stream->writeFlag(rotY[i] != extBaseMove->rotY[i])) + stream->writeInt(crotY[i], MaxRotationBits); + if(stream->writeFlag(rotZ[i] != extBaseMove->rotZ[i])) + stream->writeInt(crotZ[i], MaxRotationBits); + if(stream->writeFlag(rotW[i] != extBaseMove->rotW[i])) + stream->writeInt(crotW[i], MaxRotationBits); + } + } +} + +void ExtendedMove::unpack(BitStream *stream, const Move * basemove) +{ + bool alwaysReadAll = basemove!=NULL; + if (!basemove) + basemove=&NullExtendedMove; + + // Standard Move stuff + bool isBaseMove = !unpackMove(stream, basemove, alwaysReadAll); + + // ExtendedMove + const ExtendedMove* extBaseMove = static_cast(basemove); + + if (alwaysReadAll || stream->readFlag()) + { + isBaseMove = false; + + for(U32 i=0; ireadFlag()) + posX[i] = stream->readSignedInt(MaxPositionBits); + else + posX[i] = extBaseMove->posX[i]; + + if(stream->readFlag()) + posY[i] = stream->readSignedInt(MaxPositionBits); + else + posY[i] = extBaseMove->posY[i]; + + if(stream->readFlag()) + posZ[i] = stream->readSignedInt(MaxPositionBits); + else + posZ[i] = extBaseMove->posZ[i]; + + // Rotation + if(stream->readFlag()) + { + crotX[i] = stream->readInt(MaxRotationBits); + rotX[i] = UNCLAMPROT(crotX[i]); + } + else + { + rotX[i] = extBaseMove->rotX[i]; + } + + if(stream->readFlag()) + { + crotY[i] = stream->readInt(MaxRotationBits); + rotY[i] = UNCLAMPROT(crotY[i]); + } + else + { + rotY[i] = extBaseMove->rotY[i]; + } + + if(stream->readFlag()) + { + crotZ[i] = stream->readInt(MaxRotationBits); + rotZ[i] = UNCLAMPROT(crotZ[i]); + } + else + { + rotZ[i] = extBaseMove->rotZ[i]; + } + + if(stream->readFlag()) + { + crotW[i] = stream->readInt(MaxRotationBits); + rotW[i] = UNCLAMPROT(crotW[i]); + } + else + { + rotW[i] = extBaseMove->rotW[i]; + } + } + } + + if(isBaseMove) + { + *this = *extBaseMove; + } +} + +void ExtendedMove::clamp() +{ + // Clamp the values the same as for net traffic so the client matches the server + for(U32 i=0; i MaxMoveQueueSize ) + return false; + + // From MoveList + F32 pitchAdd = MoveManager::mPitchUpSpeed - MoveManager::mPitchDownSpeed; + F32 yawAdd = MoveManager::mYawLeftSpeed - MoveManager::mYawRightSpeed; + F32 rollAdd = MoveManager::mRollRightSpeed - MoveManager::mRollLeftSpeed; + + curMove.pitch = MoveManager::mPitch + pitchAdd; + curMove.yaw = MoveManager::mYaw + yawAdd; + curMove.roll = MoveManager::mRoll + rollAdd; + + MoveManager::mPitch = 0; + MoveManager::mYaw = 0; + MoveManager::mRoll = 0; + + curMove.x = MoveManager::mRightAction - MoveManager::mLeftAction + MoveManager::mXAxis_L; + curMove.y = MoveManager::mForwardAction - MoveManager::mBackwardAction + MoveManager::mYAxis_L; + curMove.z = MoveManager::mUpAction - MoveManager::mDownAction; + + curMove.freeLook = MoveManager::mFreeLook; + curMove.deviceIsKeyboardMouse = MoveManager::mDeviceIsKeyboardMouse; + + for(U32 i = 0; i < MaxTriggerKeys; i++) + { + curMove.trigger[i] = false; + if(MoveManager::mTriggerCount[i] & 1) + curMove.trigger[i] = true; + else if(!(MoveManager::mPrevTriggerCount[i] & 1) && MoveManager::mPrevTriggerCount[i] != MoveManager::mTriggerCount[i]) + curMove.trigger[i] = true; + MoveManager::mPrevTriggerCount[i] = MoveManager::mTriggerCount[i]; + } + + for(U32 i=0; igetControlObject()) + mConnection->getControlObject()->preprocessMove(&curMove); + + curMove.clamp(); // clamp for net traffic + return true; +} + +U32 ExtendedMoveList::getMoves(Move** movePtr,U32* numMoves) +{ + // We don't want to be here + AssertFatal(0, "getMoves() called"); + + numMoves = 0; + + return 0; +} + +U32 ExtendedMoveList::getExtMoves( ExtendedMove** movePtr, U32 *numMoves ) +{ + if (!mConnection->isConnectionToServer()) + { + if (mExtMoveVec.size() > mMoveCredit) + mExtMoveVec.setSize(mMoveCredit); + } + + // From MoveList but converted to use mExtMoveVec + if (mConnection->isConnectionToServer()) + { + // give back moves starting at the last client move... + + AssertFatal(mLastClientMove >= mFirstMoveIndex, "Bad move request"); + AssertFatal(mLastClientMove - mFirstMoveIndex <= mExtMoveVec.size(), "Desynched first and last move."); + *numMoves = mExtMoveVec.size() - mLastClientMove + mFirstMoveIndex; + *movePtr = mExtMoveVec.address() + mLastClientMove - mFirstMoveIndex; + } + else + { + // return the full list + *numMoves = mExtMoveVec.size(); + *movePtr = mExtMoveVec.begin(); + } + + return *numMoves; +} + +void ExtendedMoveList::collectMove() +{ + ExtendedMove mv; + if (mConnection) + { + if(!mConnection->isPlayingBack() && getNextExtMove(mv)) + { + mv.checksum=Move::ChecksumMismatch; + pushMove(mv); + mConnection->recordBlock(GameConnection::BlockTypeMove, sizeof(ExtendedMove), &mv); + } + } + else + { + if(getNextExtMove(mv)) + { + mv.checksum=Move::ChecksumMismatch; + pushMove(mv); + } + } +} + +void ExtendedMoveList::pushMove(const Move &mv) +{ + const ExtendedMove* extMove = dynamic_cast(&mv); + AssertFatal(extMove, "Regular Move struct passed to pushMove()"); + + pushExtMove(*extMove); +} + +void ExtendedMoveList::pushExtMove( const ExtendedMove &mv ) +{ + U32 id = mFirstMoveIndex + mExtMoveVec.size(); + U32 sz = mExtMoveVec.size(); + mExtMoveVec.push_back(mv); + mExtMoveVec[sz].id = id; + mExtMoveVec[sz].sendCount = 0; +} + +void ExtendedMoveList::clearMoves(U32 count) +{ + if (!mConnection->isConnectionToServer()) + { + count = mClamp(count,0,mMoveCredit); + mMoveCredit -= count; + } + + // From MoveList but converted to use mExtMoveVec + if (mConnection->isConnectionToServer()) + { + mLastClientMove += count; + AssertFatal(mLastClientMove >= mFirstMoveIndex, "Bad move request"); + AssertFatal(mLastClientMove - mFirstMoveIndex <= mExtMoveVec.size(), "Desynched first and last move."); + if (!mConnection) + // drop right away if no connection + ackMoves(count); + } + else + { + AssertFatal(count <= mExtMoveVec.size(),"GameConnection: Clearing too many moves"); + for (S32 i=0; iisConnectionToServer(), "Cannot inc move credit on the client."); + + // Game tick increment + mMoveCredit++; + if (mMoveCredit > MaxMoveCount) + mMoveCredit = MaxMoveCount; + + // Clear pending moves for the elapsed time if there + // is no control object. + if ( mConnection->getControlObject() == NULL ) + mExtMoveVec.clear(); +} + +void ExtendedMoveList::clientWriteMovePacket(BitStream *bstream) +{ + AssertFatal(mLastMoveAck == mFirstMoveIndex, "Invalid move index."); + U32 count = mExtMoveVec.size(); + + ExtendedMove* extMove = mExtMoveVec.address(); + U32 start = mLastMoveAck; + U32 offset; + for(offset = 0; offset < count; offset++) + if(extMove[offset].sendCount < MAX_MOVE_PACKET_SENDS) + break; + if(offset == count && count != 0) + offset--; + + start += offset; + count -= offset; + + if (count > MaxMoveCount) + count = MaxMoveCount; + bstream->writeInt(start,32); + bstream->writeInt(count,MoveCountBits); + ExtendedMove* prevExtMove = NULL; + for (int i = 0; i < count; i++) + { + extMove[offset + i].sendCount++; + extMove[offset + i].pack(bstream,prevExtMove); + bstream->writeInt(extMove[offset + i].checksum & (~(0xFFFFFFFF << Move::ChecksumBits)),Move::ChecksumBits); + prevExtMove = &extMove[offset+i]; + } +} + +void ExtendedMoveList::serverReadMovePacket(BitStream *bstream) +{ + // Server side packet read. + U32 start = bstream->readInt(32); + U32 count = bstream->readInt(MoveCountBits); + + ExtendedMove* prevExtMove = NULL; + ExtendedMove prevExtMoveHolder; + + // Skip forward (must be starting up), or over the moves + // we already have. + int skip = mLastMoveAck - start; + if (skip < 0) + { + mLastMoveAck = start; + } + else + { + if (skip > count) + skip = count; + for (int i = 0; i < skip; i++) + { + prevExtMoveHolder.unpack(bstream,prevExtMove); + prevExtMoveHolder.checksum = bstream->readInt(Move::ChecksumBits); + prevExtMove = &prevExtMoveHolder; + S32 idx = mExtMoveVec.size()-skip+i; + if (idx>=0) + { +#ifdef TORQUE_DEBUG_NET_MOVES + if (mExtMoveVec[idx].checksum != prevExtMoveHolder.checksum) + Con::printf("updated checksum on move %i from %i to %i",mExtMoveVec[idx].id,mExtMoveVec[idx].checksum,prevExtMoveHolder.checksum); +#endif + mExtMoveVec[idx].checksum = prevExtMoveHolder.checksum; + } + } + start += skip; + count = count - skip; + } + + // Put the rest on the move list. + int index = mExtMoveVec.size(); + mExtMoveVec.increment(count); + while (index < mExtMoveVec.size()) + { + mExtMoveVec[index].unpack(bstream,prevExtMove); + mExtMoveVec[index].checksum = bstream->readInt(Move::ChecksumBits); + prevExtMove = &mExtMoveVec[index]; + mExtMoveVec[index].id = start++; + index ++; + } + + mLastMoveAck += count; +} + +void ExtendedMoveList::serverWriteMovePacket(BitStream * bstream) +{ +#ifdef TORQUE_DEBUG_NET_MOVES + Con::printf("ack %i minus %i",mLastMoveAck,mExtMoveVec.size()); +#endif + + // acknowledge only those moves that have been ticked + bstream->writeInt(mLastMoveAck - mExtMoveVec.size(),32); +} + +void ExtendedMoveList::clientReadMovePacket(BitStream * bstream) +{ +#ifdef TORQUE_DEBUG_NET_MOVES + Con::printf("pre move ack: %i", mLastMoveAck); +#endif + + mLastMoveAck = bstream->readInt(32); + +#ifdef TORQUE_DEBUG_NET_MOVES + Con::printf("post move ack %i, first move %i, last move %i", mLastMoveAck, mFirstMoveIndex, mLastClientMove); +#endif + + if (mLastMoveAck < mFirstMoveIndex) + mLastMoveAck = mFirstMoveIndex; + + if(mLastMoveAck > mLastClientMove) + mLastClientMove = mLastMoveAck; + while(mFirstMoveIndex < mLastMoveAck) + { + if (mExtMoveVec.size()) + { + mExtMoveVec.pop_front(); + mFirstMoveIndex++; + } + else + { + AssertWarn(1, "Popping off too many moves!"); + mFirstMoveIndex = mLastMoveAck; + } + } +} + +bool ExtendedMoveList::isBacklogged() +{ + if ( !mConnection->isConnectionToServer() ) + return false; + + return mLastClientMove - mFirstMoveIndex == mExtMoveVec.size() && + mExtMoveVec.size() >= MaxMoveCount; +} + +bool ExtendedMoveList::areMovesPending() +{ + return mConnection->isConnectionToServer() ? + mExtMoveVec.size() - mLastClientMove + mFirstMoveIndex : + mExtMoveVec.size(); +} + +void ExtendedMoveList::ackMoves(U32 count) +{ + mLastMoveAck += count; + if(mLastMoveAck > mLastClientMove) + mLastClientMove = mLastMoveAck; + while(mFirstMoveIndex < mLastMoveAck) + { + if (mExtMoveVec.size()) + { + mExtMoveVec.pop_front(); + mFirstMoveIndex++; + } + else + { + AssertWarn(1, "Popping off too many moves!"); + mFirstMoveIndex = mLastMoveAck; + } + } +} diff --git a/Engine/source/T3D/gameBase/extended/extendedMoveList.h b/Engine/source/T3D/gameBase/extended/extendedMoveList.h new file mode 100644 index 0000000000..fc7b891f15 --- /dev/null +++ b/Engine/source/T3D/gameBase/extended/extendedMoveList.h @@ -0,0 +1,55 @@ +#ifndef _EXTENDEDMOVELIST_H_ +#define _EXTENDEDMOVELIST_H_ + +#ifndef _TVECTOR_H_ +#include "core/util/tVector.h" +#endif +#ifndef _MOVELIST_H_ +#include "T3D/gameBase/moveList.h" +#endif + +#include "T3D/gameBase/extended/extendedMove.h" + +class ExtendedMoveList : public MoveList +{ + typedef MoveList Parent; + +public: + + ExtendedMoveList(); + + void clientWriteMovePacket(BitStream *); + void clientReadMovePacket(BitStream *); + + void serverWriteMovePacket(BitStream *); + void serverReadMovePacket(BitStream *); + + void advanceMove(); + void onAdvanceObjects() {} + U32 getMoves(Move** movePtr,U32* numMoves); + U32 getExtMoves( ExtendedMove** movePtr, U32 *numMoves ); + + void collectMove(); + void pushMove( const Move &mv ); + void pushExtMove( const ExtendedMove &mv ); + void clearMoves( U32 count ); + + virtual void reset(); + + bool isBacklogged(); + + bool areMovesPending(); + + void ackMoves( U32 count ); + +protected: + + U32 mMoveCredit; + + Vector mExtMoveVec; + +protected: + bool getNextExtMove( ExtendedMove &curMove ); +}; + +#endif // _EXTENDEDMOVELIST_H_ diff --git a/Engine/source/T3D/gameBase/gameBase.h b/Engine/source/T3D/gameBase/gameBase.h index 68354cdf07..e1a9a1f2f4 100644 --- a/Engine/source/T3D/gameBase/gameBase.h +++ b/Engine/source/T3D/gameBase/gameBase.h @@ -217,7 +217,7 @@ class GameBase : public SceneObject public: GameBase(); - ~GameBase(); + virtual ~GameBase(); enum GameBaseMasks { DataBlockMask = Parent::NextFreeMask << 0, diff --git a/Engine/source/T3D/gameBase/gameConnection.cpp b/Engine/source/T3D/gameBase/gameConnection.cpp index afd1f9e25f..e3f91e1600 100644 --- a/Engine/source/T3D/gameBase/gameConnection.cpp +++ b/Engine/source/T3D/gameBase/gameConnection.cpp @@ -41,6 +41,8 @@ #ifdef TORQUE_HIFI_NET #include "T3D/gameBase/hifi/hifiMoveList.h" +#elif defined TORQUE_EXTENDED_MOVE + #include "T3D/gameBase/extended/extendedMoveList.h" #else #include "T3D/gameBase/std/stdMoveList.h" #endif @@ -175,6 +177,8 @@ GameConnection::GameConnection() #ifdef TORQUE_HIFI_NET mMoveList = new HifiMoveList(); +#elif defined TORQUE_EXTENDED_MOVE + mMoveList = new ExtendedMoveList(); #else mMoveList = new StdMoveList(); #endif diff --git a/Engine/source/T3D/gameBase/gameConnectionEvents.cpp b/Engine/source/T3D/gameBase/gameConnectionEvents.cpp index 37a8167ac5..927814a529 100644 --- a/Engine/source/T3D/gameBase/gameConnectionEvents.cpp +++ b/Engine/source/T3D/gameBase/gameConnectionEvents.cpp @@ -328,9 +328,9 @@ void Sim3DAudioEvent::pack(NetConnection *con, BitStream *bstream) AssertFatal((1.0 - ((q.x * q.x) + (q.y * q.y) + (q.z * q.z))) >= (0.0 - 0.001), "QuatF::normalize() is broken in Sim3DAudioEvent"); - bstream->writeFloat(q.x,SoundRotBits); - bstream->writeFloat(q.y,SoundRotBits); - bstream->writeFloat(q.z,SoundRotBits); + bstream->writeSignedFloat(q.x,SoundRotBits); + bstream->writeSignedFloat(q.y,SoundRotBits); + bstream->writeSignedFloat(q.z,SoundRotBits); bstream->writeFlag(q.w < 0.0); } @@ -352,9 +352,9 @@ void Sim3DAudioEvent::unpack(NetConnection *con, BitStream *bstream) if (bstream->readFlag()) { QuatF q; - q.x = bstream->readFloat(SoundRotBits); - q.y = bstream->readFloat(SoundRotBits); - q.z = bstream->readFloat(SoundRotBits); + q.x = bstream->readSignedFloat(SoundRotBits); + q.y = bstream->readSignedFloat(SoundRotBits); + q.z = bstream->readSignedFloat(SoundRotBits); F32 value = ((q.x * q.x) + (q.y * q.y) + (q.z * q.z)); // #ifdef __linux // Hmm, this should never happen, but it does... diff --git a/Engine/source/T3D/gameBase/moveList.h b/Engine/source/T3D/gameBase/moveList.h index 5b96f7953e..7c68c3a2db 100644 --- a/Engine/source/T3D/gameBase/moveList.h +++ b/Engine/source/T3D/gameBase/moveList.h @@ -76,8 +76,8 @@ class MoveList /// Reset move list back to last acknowledged move. void resetCatchup() { mLastClientMove = mLastMoveAck; } - void collectMove(); - void pushMove( const Move &mv ); + virtual void collectMove(); + virtual void pushMove( const Move &mv ); virtual void clearMoves( U32 count ); virtual void markControlDirty() { mLastClientMove = mLastMoveAck; } @@ -85,15 +85,15 @@ class MoveList void clearMismatch() { mControlMismatch = false; } /// Clear out all moves in the list and reset to initial state. - void reset(); + virtual void reset(); /// If there are no pending moves and the input queue is full, /// then the connection to the server must be clogged. - bool isBacklogged(); + virtual bool isBacklogged(); - bool areMovesPending(); + virtual bool areMovesPending(); - void ackMoves( U32 count ); + virtual void ackMoves( U32 count ); protected: diff --git a/Engine/source/T3D/gameBase/moveManager.cpp b/Engine/source/T3D/gameBase/moveManager.cpp index e9212149bf..a95164ec7e 100644 --- a/Engine/source/T3D/gameBase/moveManager.cpp +++ b/Engine/source/T3D/gameBase/moveManager.cpp @@ -66,20 +66,7 @@ F32 MoveManager::mYAxis_R = 0; U32 MoveManager::mTriggerCount[MaxTriggerKeys] = { 0, }; U32 MoveManager::mPrevTriggerCount[MaxTriggerKeys] = { 0, }; -const Move NullMove = -{ - /*px=*/16, /*py=*/16, /*pz=*/16, - /*pyaw=*/0, /*ppitch=*/0, /*proll=*/0, - /*x=*/0, /*y=*/0,/*z=*/0, - /*yaw=*/0, /*pitch=*/0, /*roll=*/0, - /*id=*/0, - /*sendCount=*/0, - - /*checksum=*/false, - /*deviceIsKeyboardMouse=*/false, - /*freeLook=*/false, - /*triggers=*/{false,false,false,false,false,false} -}; +const Move NullMove; void MoveManager::init() { @@ -161,6 +148,26 @@ void MoveManager::init() } } +Move::Move() +{ + px=16; py=16; pz=16; + pyaw=0; ppitch=0; proll=0; + x=0; y=0; z=0; + yaw=0; pitch=0; roll=0; + id=0; + sendCount=0; + + checksum = false; + deviceIsKeyboardMouse = false; + freeLook = false; + trigger[0] = false; + trigger[1] = false; + trigger[2] = false; + trigger[3] = false; + trigger[4] = false; + trigger[5] = false; +} + static inline F32 clampFloatWrap(F32 val) { return val - F32(S32(val)); @@ -235,6 +242,11 @@ void Move::pack(BitStream *stream, const Move * basemove) if (!basemove) basemove = &NullMove; + packMove(stream, basemove, alwaysWriteAll); +} + +bool Move::packMove(BitStream *stream, const Move* basemove, bool alwaysWriteAll) +{ S32 i; bool triggerDifferent = false; for (i=0; i < MaxTriggerKeys; i++) @@ -272,6 +284,8 @@ void Move::pack(BitStream *stream, const Move * basemove) for(i = 0; i < MaxTriggerKeys; i++) stream->writeFlag(trigger[i]); } + + return (triggerDifferent || somethingDifferent); } void Move::unpack(BitStream *stream, const Move * basemove) @@ -280,7 +294,20 @@ void Move::unpack(BitStream *stream, const Move * basemove) if (!basemove) basemove=&NullMove; - if (alwaysReadAll || stream->readFlag()) + bool readMove = unpackMove(stream, basemove, alwaysReadAll); + if(!readMove) + *this = *basemove; +} + +bool Move::unpackMove(BitStream *stream, const Move* basemove, bool alwaysReadAll) +{ + bool readMove = alwaysReadAll; + if(!readMove) + { + readMove = stream->readFlag(); + } + + if (readMove) { pyaw = stream->readFlag() ? stream->readInt(16) : basemove->pyaw; ppitch = stream->readFlag() ? stream->readInt(16) : basemove->ppitch; @@ -297,6 +324,6 @@ void Move::unpack(BitStream *stream, const Move * basemove) trigger[i] = triggersDiffer ? stream->readFlag() : basemove->trigger[i]; unclamp(); } - else - *this = *basemove; + + return readMove; } diff --git a/Engine/source/T3D/gameBase/moveManager.h b/Engine/source/T3D/gameBase/moveManager.h index 9ee6d111c4..3b8dcbc08c 100644 --- a/Engine/source/T3D/gameBase/moveManager.h +++ b/Engine/source/T3D/gameBase/moveManager.h @@ -51,10 +51,16 @@ struct Move bool freeLook; bool trigger[MaxTriggerKeys]; - void pack(BitStream *stream, const Move * move = NULL); - void unpack(BitStream *stream, const Move * move = NULL); - void clamp(); - void unclamp(); + Move(); + + virtual void pack(BitStream *stream, const Move * move = NULL); + virtual void unpack(BitStream *stream, const Move * move = NULL); + virtual void clamp(); + virtual void unclamp(); + +protected: + bool packMove(BitStream *stream, const Move* basemove, bool alwaysWriteAll); + bool unpackMove(BitStream *stream, const Move* basemove, bool alwaysReadAll); }; extern const Move NullMove; diff --git a/Engine/source/T3D/gameBase/std/stdMoveList.cpp b/Engine/source/T3D/gameBase/std/stdMoveList.cpp index 6b4e11a72f..1fd0ffdfba 100644 --- a/Engine/source/T3D/gameBase/std/stdMoveList.cpp +++ b/Engine/source/T3D/gameBase/std/stdMoveList.cpp @@ -96,7 +96,7 @@ void StdMoveList::clientWriteMovePacket(BitStream *bstream) { move[offset + i].sendCount++; move[offset + i].pack(bstream,prevMove); - bstream->writeInt(move[offset + i].checksum,Move::ChecksumBits); + bstream->writeInt(move[offset + i].checksum & (~(0xFFFFFFFF << Move::ChecksumBits)),Move::ChecksumBits); prevMove = &move[offset+i]; } } diff --git a/Engine/source/T3D/missionArea.cpp b/Engine/source/T3D/missionArea.cpp index b8d4d6f6ba..d11aa91ce2 100644 --- a/Engine/source/T3D/missionArea.cpp +++ b/Engine/source/T3D/missionArea.cpp @@ -52,6 +52,8 @@ ConsoleDocClass( MissionArea, RectI MissionArea::smMissionArea(Point2I(768, 768), Point2I(512, 512)); +MissionArea * MissionArea::smServerObject = NULL; + //------------------------------------------------------------------------------ MissionArea::MissionArea() @@ -79,27 +81,24 @@ void MissionArea::setArea(const RectI & area) MissionArea * MissionArea::getServerObject() { - SimSet * scopeAlwaysSet = Sim::getGhostAlwaysSet(); - for(SimSet::iterator itr = scopeAlwaysSet->begin(); itr != scopeAlwaysSet->end(); itr++) - { - MissionArea * ma = dynamic_cast(*itr); - if(ma) - { - AssertFatal(ma->isServerObject(), "MissionArea::getServerObject: found client object in ghost always set!"); - return(ma); - } - } - return(0); + return smServerObject; } //------------------------------------------------------------------------------ bool MissionArea::onAdd() { - if(isServerObject() && MissionArea::getServerObject()) + if(isServerObject()) { - Con::errorf(ConsoleLogEntry::General, "MissionArea::onAdd - MissionArea already instantiated!"); - return(false); + if(MissionArea::getServerObject()) + { + Con::errorf(ConsoleLogEntry::General, "MissionArea::onAdd - MissionArea already instantiated!"); + return(false); + } + else + { + smServerObject = this; + } } if(!Parent::onAdd()) @@ -109,6 +108,14 @@ bool MissionArea::onAdd() return(true); } +void MissionArea::onRemove() +{ + if (smServerObject == this) + smServerObject = NULL; + + Parent::onRemove(); +} + //------------------------------------------------------------------------------ void MissionArea::inspectPostApply() diff --git a/Engine/source/T3D/missionArea.h b/Engine/source/T3D/missionArea.h index d4ee5e294b..6d1f81b19e 100644 --- a/Engine/source/T3D/missionArea.h +++ b/Engine/source/T3D/missionArea.h @@ -36,6 +36,8 @@ class MissionArea : public NetObject F32 mFlightCeiling; F32 mFlightCeilingRange; + static MissionArea * smServerObject; + public: MissionArea(); @@ -53,6 +55,7 @@ class MissionArea : public NetObject /// @name SimObject Inheritance /// @{ bool onAdd(); + void onRemove(); void inspectPostApply(); diff --git a/Engine/source/T3D/player.cpp b/Engine/source/T3D/player.cpp index 468cb138b0..7133468a38 100644 --- a/Engine/source/T3D/player.cpp +++ b/Engine/source/T3D/player.cpp @@ -252,6 +252,7 @@ PlayerData::PlayerData() shadowProjectionDistance = 14.0f; renderFirstPerson = true; + firstPersonShadows = false; // Used for third person image rendering imageAnimPrefix = StringTable->insert(""); @@ -679,6 +680,9 @@ void PlayerData::initPersistFields() addField( "renderFirstPerson", TypeBool, Offset(renderFirstPerson, PlayerData), "@brief Flag controlling whether to render the player shape in first person view.\n\n" ); + addField( "firstPersonShadows", TypeBool, Offset(firstPersonShadows, PlayerData), + "@brief Forces shadows to be rendered in first person when renderFirstPerson is disabled. Defaults to false.\n\n" ); + addField( "minLookAngle", TypeF32, Offset(minLookAngle, PlayerData), "@brief Lowest angle (in radians) the player can look.\n\n" "@note An angle of zero is straight ahead, with positive up and negative down." ); @@ -1180,7 +1184,8 @@ void PlayerData::packData(BitStream* stream) Parent::packData(stream); stream->writeFlag(renderFirstPerson); - + stream->writeFlag(firstPersonShadows); + stream->write(minLookAngle); stream->write(maxLookAngle); stream->write(maxFreelookAngle); @@ -1361,6 +1366,7 @@ void PlayerData::unpackData(BitStream* stream) Parent::unpackData(stream); renderFirstPerson = stream->readFlag(); + firstPersonShadows = stream->readFlag(); stream->read(&minLookAngle); stream->read(&maxLookAngle); @@ -6947,6 +6953,11 @@ void Player::prepRenderImage( SceneRenderState* state ) GameConnection* connection = GameConnection::getConnectionToServer(); if( connection && connection->getControlObject() == this && connection->isFirstPerson() ) { + // If we're first person and we are not rendering the player + // then disable all shadow rendering... a floating gun shadow sucks. + if ( state->isShadowPass() && !mDataBlock->renderFirstPerson && !mDataBlock->firstPersonShadows ) + return; + renderPlayer = mDataBlock->renderFirstPerson || !state->isDiffusePass(); if( !sRenderMyPlayer ) diff --git a/Engine/source/T3D/player.h b/Engine/source/T3D/player.h index 10046c4c60..86ced6b987 100644 --- a/Engine/source/T3D/player.h +++ b/Engine/source/T3D/player.h @@ -54,6 +54,10 @@ struct PlayerData: public ShapeBaseData { }; bool renderFirstPerson; ///< Render the player shape in first person + /// Render shadows while in first person when + /// renderFirstPerson is disabled. + bool firstPersonShadows; + StringTableEntry imageAnimPrefix; ///< Passed along to mounted images to modify /// animation sequences played in third person. [optional] bool allowImageStateAnimation; ///< When true a new thread is added to the player to allow for diff --git a/Engine/source/T3D/rigidShape.cpp b/Engine/source/T3D/rigidShape.cpp index f81ca8752c..0553a94828 100644 --- a/Engine/source/T3D/rigidShape.cpp +++ b/Engine/source/T3D/rigidShape.cpp @@ -1003,6 +1003,11 @@ void RigidShape::setTransform(const MatrixF& newMat) mContacts.clear(); } +void RigidShape::forceClientTransform() +{ + setMaskBits(ForceMoveMask); +} + //----------------------------------------------------------------------------- @@ -1456,6 +1461,8 @@ U32 RigidShape::packUpdate(NetConnection *con, U32 mask, BitStream *stream) if (stream->writeFlag(mask & PositionMask)) { + stream->writeFlag(mask & ForceMoveMask); + stream->writeCompressedPoint(mRigid.linPosition); mathWrite(*stream, mRigid.angPosition); mathWrite(*stream, mRigid.linMomentum); @@ -1480,6 +1487,10 @@ void RigidShape::unpackUpdate(NetConnection *con, BitStream *stream) if (stream->readFlag()) { + // Check if we need to jump to the given transform + // rather than interpolate to it. + bool forceUpdate = stream->readFlag(); + mPredictionCount = sMaxPredictionTicks; F32 speed = mRigid.linVelocity.len(); mDelta.warpRot[0] = mRigid.angPosition; @@ -1492,7 +1503,7 @@ void RigidShape::unpackUpdate(NetConnection *con, BitStream *stream) mRigid.atRest = stream->readFlag(); mRigid.updateVelocity(); - if (isProperlyAdded()) + if (!forceUpdate && isProperlyAdded()) { // Determine number of ticks to warp based on the average // of the client and server velocities. @@ -1710,3 +1721,12 @@ DefineEngineMethod( RigidShape, freezeSim, void, (bool isFrozen),, { object->freezeSim(isFrozen); } + +DefineEngineMethod( RigidShape, forceClientTransform, void, (),, + "@brief Forces the client to jump to the RigidShape's transform rather then warp to it.\n\n") +{ + if(object->isServerObject()) + { + object->forceClientTransform(); + } +} diff --git a/Engine/source/T3D/rigidShape.h b/Engine/source/T3D/rigidShape.h index 2a05f445ab..180b0d0add 100644 --- a/Engine/source/T3D/rigidShape.h +++ b/Engine/source/T3D/rigidShape.h @@ -152,10 +152,11 @@ class RigidShape: public ShapeBase WheelCollision = BIT(1), }; enum MaskBits { - PositionMask = Parent::NextFreeMask << 0, - EnergyMask = Parent::NextFreeMask << 1, - FreezeMask = Parent::NextFreeMask << 2, - NextFreeMask = Parent::NextFreeMask << 3 + PositionMask = Parent::NextFreeMask << 0, + EnergyMask = Parent::NextFreeMask << 1, + FreezeMask = Parent::NextFreeMask << 2, + ForceMoveMask = Parent::NextFreeMask << 3, + NextFreeMask = Parent::NextFreeMask << 4 }; void updateDustTrail( F32 dt ); @@ -283,6 +284,10 @@ class RigidShape: public ShapeBase /// @param impulse Impulse vector to apply. void applyImpulse(const Point3F &r, const Point3F &impulse); + /// Forces the client to jump to the RigidShape's transform rather + /// then warp to it. + void forceClientTransform(); + void getCameraParameters(F32 *min, F32* max, Point3F* offset, MatrixF* rot); void getCameraTransform(F32* pos, MatrixF* mat); ///@} diff --git a/Engine/source/T3D/shapeBase.cpp b/Engine/source/T3D/shapeBase.cpp index 666f64e321..170a5c07a9 100644 --- a/Engine/source/T3D/shapeBase.cpp +++ b/Engine/source/T3D/shapeBase.cpp @@ -1632,6 +1632,11 @@ F32 ShapeBase::getDamageValue() return mDamage / mDataBlock->maxDamage; } +F32 ShapeBase::getMaxDamage() +{ + return mDataBlock->maxDamage; +} + void ShapeBase::updateDamageLevel() { if (mDamageThread) { @@ -4534,6 +4539,13 @@ DefineEngineMethod( ShapeBase, getDamagePercent, F32, (),, { return object->getDamageValue(); } + +DefineEngineMethod(ShapeBase, getMaxDamage, F32, (),, + "Get the object's maxDamage level.\n" + "@return datablock.maxDamage\n") +{ + return object->getMaxDamage(); +} DefineEngineMethod( ShapeBase, setDamageState, bool, ( const char* state ),, "@brief Set the object's damage state.\n\n" diff --git a/Engine/source/T3D/shapeBase.h b/Engine/source/T3D/shapeBase.h index 96392041a4..af1e0287d8 100644 --- a/Engine/source/T3D/shapeBase.h +++ b/Engine/source/T3D/shapeBase.h @@ -1265,6 +1265,9 @@ class ShapeBase : public GameBase, public ISceneLight /// /// @return Damage factor, between 0.0 - 1.0 F32 getDamageValue(); + + /// Returns the datablock.maxDamage value + F32 getMaxDamage(); /// Returns the rate at which the object regenerates damage F32 getRepairRate() { return mRepairRate; } diff --git a/Engine/source/T3D/tsStatic.cpp b/Engine/source/T3D/tsStatic.cpp index 5200742982..ad7a3164c7 100644 --- a/Engine/source/T3D/tsStatic.cpp +++ b/Engine/source/T3D/tsStatic.cpp @@ -827,6 +827,8 @@ bool TSStatic::buildPolyList(PolyListContext context, AbstractPolyList* polyList return false; else if ( meshType == Bounds ) polyList->addBox( mObjBox ); + else if ( meshType == VisibleMesh ) + mShapeInstance->buildPolyList( polyList, 0 ); else { // Everything else is done from the collision meshes diff --git a/Engine/source/T3D/turret/aiTurretShape.cpp b/Engine/source/T3D/turret/aiTurretShape.cpp index 1f6a15d315..c6dd5ca1f6 100644 --- a/Engine/source/T3D/turret/aiTurretShape.cpp +++ b/Engine/source/T3D/turret/aiTurretShape.cpp @@ -893,7 +893,7 @@ void AITurretShape::_trackTarget(F32 dt) //if (pitch > M_PI_F) // pitch = -(pitch - M_2PI_F); - Point3F rot(-pitch, 0.0f, yaw); + Point3F rot(pitch, 0.0f, -yaw); // If we have a rotation rate make sure we follow it if (mHeadingRate > 0) diff --git a/Engine/source/T3D/turret/turretShape.cpp b/Engine/source/T3D/turret/turretShape.cpp index de86ee1778..59f20a3e14 100644 --- a/Engine/source/T3D/turret/turretShape.cpp +++ b/Engine/source/T3D/turret/turretShape.cpp @@ -824,7 +824,11 @@ void TurretShape::_updateNodes(const Point3F& rot) { MatrixF* mat = &mShapeInstance->mNodeTransforms[node]; Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node]; - mat->set(zRot); + Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node]; + + QuatF qrot(zRot); + qrot *= defaultRot.getQuatF(); + qrot.setMatrix( mat ); mat->setColumn(3, defaultPos); } @@ -834,7 +838,11 @@ void TurretShape::_updateNodes(const Point3F& rot) { MatrixF* mat = &mShapeInstance->mNodeTransforms[node]; Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node]; - mat->set(xRot); + Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node]; + + QuatF qrot(xRot); + qrot *= defaultRot.getQuatF(); + qrot.setMatrix( mat ); mat->setColumn(3, defaultPos); } @@ -846,7 +854,11 @@ void TurretShape::_updateNodes(const Point3F& rot) { MatrixF* mat = &mShapeInstance->mNodeTransforms[node]; Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node]; - mat->set(xRot); + Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node]; + + QuatF qrot(xRot); + qrot *= defaultRot.getQuatF(); + qrot.setMatrix( mat ); mat->setColumn(3, defaultPos); } @@ -855,7 +867,11 @@ void TurretShape::_updateNodes(const Point3F& rot) { MatrixF* mat = &mShapeInstance->mNodeTransforms[node]; Point3F defaultPos = mShapeInstance->getShape()->defaultTranslations[node]; - mat->set(zRot); + Quat16 defaultRot = mShapeInstance->getShape()->defaultRotations[node]; + + QuatF qrot(zRot); + qrot *= defaultRot.getQuatF(); + qrot.setMatrix( mat ); mat->setColumn(3, defaultPos); } } diff --git a/Engine/source/T3D/vehicles/vehicle.cpp b/Engine/source/T3D/vehicles/vehicle.cpp index 9496a81486..f4b58ac616 100644 --- a/Engine/source/T3D/vehicles/vehicle.cpp +++ b/Engine/source/T3D/vehicles/vehicle.cpp @@ -172,6 +172,10 @@ VehicleData::VehicleData() jetEnergyDrain = 0.8f; minJetEnergy = 1; + steeringReturn = 0.0f; + steeringReturnSpeedScale = 0.01f; + powerSteering = false; + for (S32 i = 0; i < Body::MaxSounds; i++) body.sound[i] = 0; @@ -292,6 +296,10 @@ void VehicleData::packData(BitStream* stream) stream->write(jetEnergyDrain); stream->write(minJetEnergy); + stream->write(steeringReturn); + stream->write(steeringReturnSpeedScale); + stream->writeFlag(powerSteering); + stream->writeFlag(cameraRoll); stream->write(cameraLag); stream->write(cameraDecay); @@ -384,6 +392,10 @@ void VehicleData::unpackData(BitStream* stream) stream->read(&jetEnergyDrain); stream->read(&minJetEnergy); + stream->read(&steeringReturn); + stream->read(&steeringReturnSpeedScale); + powerSteering = stream->readFlag(); + cameraRoll = stream->readFlag(); stream->read(&cameraLag); stream->read(&cameraDecay); @@ -462,6 +474,13 @@ void VehicleData::initPersistFields() addField( "minJetEnergy", TypeF32, Offset(minJetEnergy, VehicleData), "Minimum vehicle energy level to begin jetting." ); + addField( "steeringReturn", TypeF32, Offset(steeringReturn, VehicleData), + "Rate at which the vehicle's steering returns to forwards when it is moving." ); + addField( "steeringReturnSpeedScale", TypeF32, Offset(steeringReturnSpeedScale, VehicleData), + "Amount of effect the vehicle's speed has on its rate of steering return." ); + addField( "powerSteering", TypeBool, Offset(powerSteering, VehicleData), + "If true, steering does not auto-centre while the vehicle is being steered by its driver." ); + addField( "massCenter", TypePoint3F, Offset(massCenter, VehicleData), "Defines the vehicle's center of mass (offset from the origin of the model)." ); addField( "massBox", TypePoint3F, Offset(massBox, VehicleData), @@ -1085,6 +1104,22 @@ void Vehicle::updateMove(const Move* move) mSteering.y = 0; } + // Steering return + if(mDataBlock->steeringReturn > 0.0f && + (!mDataBlock->powerSteering || (move->yaw == 0.0f && move->pitch == 0.0f))) + { + Point2F returnAmount(mSteering.x * mDataBlock->steeringReturn * TickSec, + mSteering.y * mDataBlock->steeringReturn * TickSec); + if(mDataBlock->steeringReturnSpeedScale > 0.0f) + { + Point3F vel; + mWorldToObj.mulV(getVelocity(), &vel); + returnAmount += Point2F(mSteering.x * vel.y * mDataBlock->steeringReturnSpeedScale * TickSec, + mSteering.y * vel.y * mDataBlock->steeringReturnSpeedScale * TickSec); + } + mSteering -= returnAmount; + } + // Jetting flag if (move->trigger[3]) { if (!mJetting && getEnergyLevel() >= mDataBlock->minJetEnergy) diff --git a/Engine/source/T3D/vehicles/vehicle.h b/Engine/source/T3D/vehicles/vehicle.h index e8f42acd92..da3b62eeb2 100644 --- a/Engine/source/T3D/vehicles/vehicle.h +++ b/Engine/source/T3D/vehicles/vehicle.h @@ -107,6 +107,10 @@ struct VehicleData: public ShapeBaseData F32 jetEnergyDrain; ///< Energy drain/tick F32 minJetEnergy; + F32 steeringReturn; + F32 steeringReturnSpeedScale; + bool powerSteering; + ParticleEmitterData * dustEmitter; S32 dustID; F32 triggerDustHeight; ///< height vehicle has to be under to kick up dust diff --git a/Engine/source/app/auth.h b/Engine/source/app/auth.h index 2f2098466c..2eb76c1924 100644 --- a/Engine/source/app/auth.h +++ b/Engine/source/app/auth.h @@ -23,10 +23,6 @@ #ifndef _AUTH_H_ #define _AUTH_H_ -#ifndef _EVENT_H_ -#include "platform/event.h" -#endif - /// Formerly contained a certificate, showing that something was valid. class Auth2Certificate { diff --git a/Engine/source/app/mainLoop.cpp b/Engine/source/app/mainLoop.cpp index cb31d6c0b3..0e81030e27 100644 --- a/Engine/source/app/mainLoop.cpp +++ b/Engine/source/app/mainLoop.cpp @@ -291,6 +291,9 @@ void StandardMainLoop::init() tm = new TimeManager; tm->timeEvent.notify(&::processTimeEvent); + // Start up the Input Event Manager + INPUTMGR->start(); + Sampler::init(); // Hook in for UDP notification @@ -307,6 +310,9 @@ void StandardMainLoop::init() void StandardMainLoop::shutdown() { + // Stop the Input Event Manager + INPUTMGR->stop(); + delete tm; preShutdown(); diff --git a/Engine/source/app/net/httpObject.cpp b/Engine/source/app/net/httpObject.cpp index 91287d5ada..c75faed8e2 100644 --- a/Engine/source/app/net/httpObject.cpp +++ b/Engine/source/app/net/httpObject.cpp @@ -23,7 +23,6 @@ #include "app/net/httpObject.h" #include "platform/platform.h" -#include "platform/event.h" #include "core/stream/fileStream.h" #include "console/simBase.h" #include "console/consoleInternal.h" diff --git a/Engine/source/app/net/netTest.cpp b/Engine/source/app/net/netTest.cpp index e9b172a713..81065ce6a2 100644 --- a/Engine/source/app/net/netTest.cpp +++ b/Engine/source/app/net/netTest.cpp @@ -22,7 +22,6 @@ #include "platform/platform.h" #include "console/simBase.h" -#include "platform/event.h" #include "sim/netConnection.h" #include "core/stream/bitStream.h" #include "sim/netObject.h" diff --git a/Engine/source/app/net/serverQuery.cpp b/Engine/source/app/net/serverQuery.cpp index cf3dc8bf87..4cf0df1eb4 100644 --- a/Engine/source/app/net/serverQuery.cpp +++ b/Engine/source/app/net/serverQuery.cpp @@ -96,7 +96,6 @@ #include "app/net/serverQuery.h" #include "platform/platform.h" -#include "platform/event.h" #include "core/dnet.h" #include "core/util/tVector.h" #include "core/stream/bitStream.h" diff --git a/Engine/source/app/net/serverQuery.h b/Engine/source/app/net/serverQuery.h index d59e3c355d..37d33b72e4 100644 --- a/Engine/source/app/net/serverQuery.h +++ b/Engine/source/app/net/serverQuery.h @@ -26,9 +26,6 @@ #ifndef _PLATFORM_H_ #include "platform/platform.h" #endif -#ifndef _EVENT_H_ -#include "platform/event.h" -#endif #ifndef _BITSET_H_ #include "core/bitSet.h" #endif diff --git a/Engine/source/app/net/tcpObject.cpp b/Engine/source/app/net/tcpObject.cpp index 202934fb15..37ee3ccd48 100644 --- a/Engine/source/app/net/tcpObject.cpp +++ b/Engine/source/app/net/tcpObject.cpp @@ -23,7 +23,6 @@ #include "app/net/tcpObject.h" #include "platform/platform.h" -#include "platform/event.h" #include "console/simBase.h" #include "console/consoleInternal.h" #include "core/strings/stringUnit.h" @@ -129,6 +128,7 @@ IMPLEMENT_CALLBACK(TCPObject, onConnectionRequest, void, (const char* address, c "This callback is used when the TCPObject is listening to a port and a client is attempting to connect.\n" "@param address Server address connecting from.\n" "@param ID Connection ID\n" + "@see listen()\n" ); IMPLEMENT_CALLBACK(TCPObject, onLine, void, (const char* line), (line), @@ -424,14 +424,30 @@ DefineEngineMethod(TCPObject, send, void, (const char *data),, DefineEngineMethod(TCPObject, listen, void, (int port),, "@brief Start listening on the specified port for connections.\n\n" + "This method starts a listener which looks for incoming TCP connections to a port. " + "You must overload the onConnectionRequest callback to create a new TCPObject to " + "read, write, or reject the new connection.\n\n" + "@param port Port for this TCPObject to start listening for connections on.\n" "@tsexample\n" - "// Set the port number list\n" - "%portNumber = 80;\n\n" - "// Inform this TCPObject to start listening at the specified port.\n" - "%thisTCPObj.send(%portNumber);\n" + "// Create a listener on port 8080.\n" + "new TCPObject( TCPListener );\n" + "TCPListener.listen( 8080 );\n\n" + + "function TCPListener::onConnectionRequest( %this, %address, %id )\n" + "{\n" + " // Create a new object to manage the connection.\n" + " new TCPObject( TCPClient, %id );\n" + "}\n\n" + + "function TCPClient::onLine( %this, %line )\n" + "{\n" + " // Print the line of text from client.\n" + " echo( %line );\n" + "}\n" + "@endtsexample\n") { object->listen(U32(port)); diff --git a/Engine/source/collision/abstractPolyList.h b/Engine/source/collision/abstractPolyList.h index 092cba4353..9b3b00ef8f 100644 --- a/Engine/source/collision/abstractPolyList.h +++ b/Engine/source/collision/abstractPolyList.h @@ -157,6 +157,11 @@ class AbstractPolyList /// an ID number for that point. virtual U32 addPoint(const Point3F& p) = 0; + /// Adds a point and normal to the poly list, and returns + /// an ID number for them. Normals are ignored for polylists + /// that do not support them. + virtual U32 addPointAndNormal(const Point3F& p, const Point3F& normal) { return addPoint( p ); } + /// Adds a plane to the poly list, and returns /// an ID number for that point. virtual U32 addPlane(const PlaneF& plane) = 0; diff --git a/Engine/source/collision/clippedPolyList.cpp b/Engine/source/collision/clippedPolyList.cpp index 2f83da6649..55bd5598ea 100644 --- a/Engine/source/collision/clippedPolyList.cpp +++ b/Engine/source/collision/clippedPolyList.cpp @@ -74,6 +74,11 @@ bool ClippedPolyList::isEmpty() const //---------------------------------------------------------------------------- U32 ClippedPolyList::addPoint(const Point3F& p) +{ + return addPointAndNormal( p, Point3F::Zero ); +} + +U32 ClippedPolyList::addPointAndNormal(const Point3F& p, const Point3F& normal) { mVertexList.increment(); Vertex& v = mVertexList.last(); @@ -82,6 +87,14 @@ U32 ClippedPolyList::addPoint(const Point3F& p) v.point.z = p.z * mScale.z; mMatrix.mulP(v.point); + mNormalList.increment(); + VectorF& n = mNormalList.last(); + n = normal; + if ( !n.isZero() ) + mMatrix.mulV(n); + + AssertFatal(mNormalList.size() == mVertexList.size(), "Normals count does not match vertex count!"); + // Build the plane mask register U32 mask = 1; register S32 count = mPlaneList.size(); @@ -242,6 +255,13 @@ void ClippedPolyList::end() VectorF vv = v2 - v1; F32 t = -mPlaneList[p].distToPlane(v1) / mDot(mPlaneList[p],vv); + mNormalList.increment(); + VectorF& n1 = mNormalList[mIndexList[i1]]; + VectorF& n2 = mNormalList[mIndexList[i1]]; + VectorF nn = mLerp( n1, n2, t ); + nn.normalizeSafe(); + mNormalList.last() = nn; + mIndexList.push_back/*_noresize*/(mVertexList.size() - 1); Vertex& iv = mVertexList.last(); iv.point.x = v1.x + vv.x * t; @@ -343,12 +363,14 @@ void ClippedPolyList::cullUnusedVerts() if ( !result ) { mVertexList.setSize( i ); + mNormalList.setSize( i ); break; } // Erase unused verts. numDeleted = (k-1) - i + 1; mVertexList.erase( i, numDeleted ); + mNormalList.erase( i, numDeleted ); // Find any references to vertices after those deleted // in the mIndexList and correct with an offset @@ -407,7 +429,7 @@ void ClippedPolyList::generateNormals() { PROFILE_SCOPE( ClippedPolyList_GenerateNormals ); - mNormalList.setSize( mVertexList.size() ); + AssertFatal(mNormalList.size() == mVertexList.size(), "Normals count does not match vertex count!"); U32 i, polyCount; VectorF normal; @@ -418,6 +440,10 @@ void ClippedPolyList::generateNormals() U32 n = 0; for ( ; normalIter != mNormalList.end(); normalIter++, n++ ) { + // Skip normals that already have values. + if ( !normalIter->isZero() ) + continue; + // Average all the face normals which // share this vertex index. indexIter = mIndexList.begin(); diff --git a/Engine/source/collision/clippedPolyList.h b/Engine/source/collision/clippedPolyList.h index c3eb4e5e75..affce34012 100644 --- a/Engine/source/collision/clippedPolyList.h +++ b/Engine/source/collision/clippedPolyList.h @@ -119,6 +119,7 @@ class ClippedPolyList : public AbstractPolyList // AbstractPolyList bool isEmpty() const; U32 addPoint(const Point3F& p); + U32 addPointAndNormal(const Point3F& p, const Point3F& normal); U32 addPlane(const PlaneF& plane); void begin(BaseMatInstance* material,U32 surfaceKey); void plane(U32 v1,U32 v2,U32 v3); diff --git a/Engine/source/collision/depthSortList.cpp b/Engine/source/collision/depthSortList.cpp index 510c38f2a6..175a6fc84b 100644 --- a/Engine/source/collision/depthSortList.cpp +++ b/Engine/source/collision/depthSortList.cpp @@ -181,25 +181,22 @@ void DepthSortList::set(const MatrixF & mat, Point3F & extents) mPlaneList.clear(); mPlaneList.increment(); - mPlaneList.last().set(-1.0f, 0.0f, 0.0f); - mPlaneList.last().d = -mExtent.x; + mPlaneList.last().set(-1.0f, 0.0f, 0.0f, -mExtent.x); + mPlaneList.increment(); - mPlaneList.last().set( 1.0f, 0.0f, 0.0f); - mPlaneList.last().d = -mExtent.x; + mPlaneList.last().set( 1.0f, 0.0f, 0.0f, -mExtent.x); mPlaneList.increment(); - mPlaneList.last().set( 0.0f,-1.0f, 0.0f); - mPlaneList.last().d = 0; + mPlaneList.last().set( 0.0f,-1.0f, 0.0f, 0); + mPlaneList.increment(); - mPlaneList.last().set( 0.0f, 1.0f, 0.0f); - mPlaneList.last().d = -2.0f * mExtent.y; + mPlaneList.last().set( 0.0f, 1.0f, 0.0f, -2.0f * mExtent.y); mPlaneList.increment(); - mPlaneList.last().set( 0.0f, 0.0f,-1.0f); - mPlaneList.last().d = -mExtent.z; + mPlaneList.last().set( 0.0f, 0.0f,-1.0f, -mExtent.z); + mPlaneList.increment(); - mPlaneList.last().set( 0.0f, 0.0f, 1.0f); - mPlaneList.last().d = -mExtent.z; + mPlaneList.last().set( 0.0f, 0.0f, 1.0f, -mExtent.z); } //---------------------------------------------------------------------------- @@ -530,8 +527,8 @@ bool DepthSortList::splitPoly(const Poly & src, Point3F & normal, F32 k, Poly & S32 startSize = mVertexList.size(); - // Assume back and front are degenerate polygons until proven otherwise. - bool backDegen = true, frontDegen = true; + // Assume back and front are degenerate polygons until proven otherwise. + bool backDegen = true, frontDegen = true; U32 bIdx; Point3F * a, * b; @@ -551,8 +548,8 @@ bool DepthSortList::splitPoly(const Poly & src, Point3F & normal, F32 k, Poly & signB = 0; S32 i; - for (i = 0; isize(); j++) { Poly toCut = (*sourceList)[j]; - if(allowclipping) + if(allowclipping) cookieCutter(cutter,toCut,*scraps,partition,partitionVerts); - else - cookieCutter(cutter,toCut,gWorkListJunkBin,partition,partitionVerts); + else + cookieCutter(cutter,toCut,gWorkListJunkBin,partition,partitionVerts); } // project all the new verts onto the cutter's plane @@ -775,14 +772,14 @@ void DepthSortList::depthPartition(const Point3F * sourceVerts, U32 numVerts, Ve for (j=startVert; jclear(); // swap work lists -- scraps become source for next closest poly Vector * tmpListPtr = sourceList; sourceList = scraps; scraps = tmpListPtr; - } + } i++; } } diff --git a/Engine/source/component/componentInterface.cpp b/Engine/source/component/componentInterface.cpp index e489ca0f2c..39bc9d81cb 100644 --- a/Engine/source/component/componentInterface.cpp +++ b/Engine/source/component/componentInterface.cpp @@ -30,11 +30,12 @@ bool ComponentInterfaceCache::add( const char *type, const char *name, const Sim if( ( mInterfaceList.size() == 0 ) || ( enumerate( NULL, type, name, owner ) == 0 ) ) { mInterfaceList.increment(); - // CodeReview [tom, 3/9/2007] Seems silly to keep calling last(), why not cache the var? Yes, I know I am pedantic. - mInterfaceList.last().type = ( type == NULL ? NULL : StringTable->insert( type ) ); - mInterfaceList.last().name = ( name == NULL ? NULL : StringTable->insert( name ) ); - mInterfaceList.last().owner = owner; - mInterfaceList.last().iface = cinterface; + + ComponentInterfaceCache::_InterfaceEntry mEntry = mInterfaceList.last(); + mEntry.type = ( type == NULL ? NULL : StringTable->insert( type ) ); + mEntry.name = ( name == NULL ? NULL : StringTable->insert( name ) ); + mEntry.owner = owner; + mEntry.iface = cinterface; return true; } diff --git a/Engine/source/component/interfaces/IProcessInput.h b/Engine/source/component/interfaces/IProcessInput.h index 3526848c38..9e639f71c2 100644 --- a/Engine/source/component/interfaces/IProcessInput.h +++ b/Engine/source/component/interfaces/IProcessInput.h @@ -23,7 +23,7 @@ #ifndef _I_PROCESSINPUT_H_ #define _I_PROCESSINPUT_H_ -#include "platform/event.h" +#include "platform/input/event.h" // CodeReview : Input can come from a number of places to end up in diff --git a/Engine/source/console/arrayObject.cpp b/Engine/source/console/arrayObject.cpp index 180461cb14..4d9a565f6b 100644 --- a/Engine/source/console/arrayObject.cpp +++ b/Engine/source/console/arrayObject.cpp @@ -55,7 +55,7 @@ ConsoleDocClass( ArrayObject, ); -bool ArrayObject::smIncreasing = false; +bool ArrayObject::smDecreasing = false; bool ArrayObject::smCaseSensitive = false; const char* ArrayObject::smCompareFunction; @@ -65,7 +65,7 @@ S32 QSORT_CALLBACK ArrayObject::_valueCompare( const void* a, const void* b ) ArrayObject::Element *ea = (ArrayObject::Element *) (a); ArrayObject::Element *eb = (ArrayObject::Element *) (b); S32 result = smCaseSensitive ? dStrnatcmp(ea->value, eb->value) : dStrnatcasecmp(ea->value, eb->value); - return ( smIncreasing ? -result : result ); + return ( smDecreasing ? -result : result ); } S32 QSORT_CALLBACK ArrayObject::_valueNumCompare( const void* a, const void* b ) @@ -76,7 +76,7 @@ S32 QSORT_CALLBACK ArrayObject::_valueNumCompare( const void* a, const void* b ) F32 bCol = dAtof(eb->value); F32 result = aCol - bCol; S32 res = result < 0 ? -1 : (result > 0 ? 1 : 0); - return ( smIncreasing ? res : -res ); + return ( smDecreasing ? res : -res ); } S32 QSORT_CALLBACK ArrayObject::_keyCompare( const void* a, const void* b ) @@ -84,7 +84,7 @@ S32 QSORT_CALLBACK ArrayObject::_keyCompare( const void* a, const void* b ) ArrayObject::Element *ea = (ArrayObject::Element *) (a); ArrayObject::Element *eb = (ArrayObject::Element *) (b); S32 result = smCaseSensitive ? dStrnatcmp(ea->key, eb->key) : dStrnatcasecmp(ea->key, eb->key); - return ( smIncreasing ? -result : result ); + return ( smDecreasing ? -result : result ); } S32 QSORT_CALLBACK ArrayObject::_keyNumCompare( const void* a, const void* b ) @@ -95,7 +95,7 @@ S32 QSORT_CALLBACK ArrayObject::_keyNumCompare( const void* a, const void* b ) const char* bCol = eb->key; F32 result = dAtof(aCol) - dAtof(bCol); S32 res = result < 0 ? -1 : (result > 0 ? 1 : 0); - return ( smIncreasing ? res : -res ); + return ( smDecreasing ? res : -res ); } S32 QSORT_CALLBACK ArrayObject::_keyFunctionCompare( const void* a, const void* b ) @@ -110,7 +110,7 @@ S32 QSORT_CALLBACK ArrayObject::_keyFunctionCompare( const void* a, const void* S32 result = dAtoi( Con::execute( 3, argv ) ); S32 res = result < 0 ? -1 : ( result > 0 ? 1 : 0 ); - return ( smIncreasing ? res : -res ); + return ( smDecreasing ? res : -res ); } S32 QSORT_CALLBACK ArrayObject::_valueFunctionCompare( const void* a, const void* b ) @@ -125,7 +125,7 @@ S32 QSORT_CALLBACK ArrayObject::_valueFunctionCompare( const void* a, const void S32 result = dAtoi( Con::execute( 3, argv ) ); S32 res = result < 0 ? -1 : ( result > 0 ? 1 : 0 ); - return ( smIncreasing ? res : -res ); + return ( smDecreasing ? res : -res ); } @@ -472,12 +472,12 @@ void ArrayObject::setValue( const String &value, S32 index ) //----------------------------------------------------------------------------- -void ArrayObject::sort( bool valsort, bool desc, bool numeric ) +void ArrayObject::sort( bool valsort, bool asc, bool numeric ) { if ( mArray.size() <= 1 ) return; - smIncreasing = desc ? false : true; + smDecreasing = asc ? false : true; smCaseSensitive = isCaseSensitive(); if ( numeric ) @@ -498,12 +498,12 @@ void ArrayObject::sort( bool valsort, bool desc, bool numeric ) //----------------------------------------------------------------------------- -void ArrayObject::sort( bool valsort, bool desc, const char* callbackFunctionName ) +void ArrayObject::sort( bool valsort, bool asc, const char* callbackFunctionName ) { if( mArray.size() <= 1 ) return; - smIncreasing = desc ? false : true; + smDecreasing = asc ? false : true; smCompareFunction = callbackFunctionName; if( valsort ) @@ -767,80 +767,80 @@ DefineEngineMethod( ArrayObject, append, bool, ( ArrayObject* target ),, return false; } -DefineEngineMethod( ArrayObject, sort, void, ( bool descending ), ( false ), +DefineEngineMethod( ArrayObject, sort, void, ( bool ascending ), ( false ), "Alpha sorts the array by value\n\n" - "@param descending [optional] True for descending sort, false for ascending sort\n" ) + "@param ascending [optional] True for ascending sort, false for descending sort\n" ) { - object->sort( true, descending, false ); + object->sort( true, ascending, false ); } DefineEngineMethod( ArrayObject, sorta, void, (),, "Alpha sorts the array by value in ascending order" ) { - object->sort( true, false, false ); + object->sort( true, true, false ); } DefineEngineMethod( ArrayObject, sortd, void, (),, "Alpha sorts the array by value in descending order" ) { - object->sort( true, true, false ); + object->sort( true, false, false ); } -DefineEngineMethod( ArrayObject, sortk, void, ( bool descending ), ( false ), +DefineEngineMethod( ArrayObject, sortk, void, ( bool ascending ), ( false ), "Alpha sorts the array by key\n\n" - "@param descending [optional] True for descending sort, false for ascending sort\n" ) + "@param ascending [optional] True for ascending sort, false for descending sort\n" ) { - object->sort( false, descending, false ); + object->sort( false, ascending, false ); } DefineEngineMethod( ArrayObject, sortka, void, (),, "Alpha sorts the array by key in ascending order" ) { - object->sort( false, false, false ); + object->sort( false, true, false ); } DefineEngineMethod( ArrayObject, sortkd, void, (),, "Alpha sorts the array by key in descending order" ) { - object->sort( false, true, false ); + object->sort( false, false, false ); } -DefineEngineMethod( ArrayObject, sortn, void, ( bool descending ), ( false ), +DefineEngineMethod( ArrayObject, sortn, void, ( bool ascending ), ( false ), "Numerically sorts the array by value\n\n" - "@param descending [optional] True for descending sort, false for ascending sort\n" ) + "@param ascending [optional] True for ascending sort, false for descending sort\n" ) { - object->sort( true, descending, true ); + object->sort( true, ascending, true ); } DefineEngineMethod( ArrayObject, sortna, void, (),, "Numerically sorts the array by value in ascending order" ) { - object->sort( true, false, true ); + object->sort( true, true, true ); } DefineEngineMethod( ArrayObject, sortnd, void, (),, "Numerically sorts the array by value in descending order" ) { - object->sort( true, true, true ); + object->sort( true, false, true ); } -DefineEngineMethod( ArrayObject, sortnk, void, ( bool descending ), ( false ), +DefineEngineMethod( ArrayObject, sortnk, void, ( bool ascending ), ( false ), "Numerically sorts the array by key\n\n" - "@param descending [optional] True for descending sort, false for ascending sort\n" ) + "@param ascending [optional] True for ascending sort, false for descending sort\n" ) { - object->sort( false, descending, true ); + object->sort( false, ascending, true ); } DefineEngineMethod( ArrayObject, sortnka, void, (),, "Numerical sorts the array by key in ascending order" ) { - object->sort( false, false, true ); + object->sort( false, true, true ); } DefineEngineMethod( ArrayObject, sortnkd, void, (),, "Numerical sorts the array by key in descending order" ) { - object->sort( false, true, true ); + object->sort( false, false, true ); } DefineEngineMethod( ArrayObject, sortf, void, ( const char* functionName ),, @@ -854,7 +854,7 @@ DefineEngineMethod( ArrayObject, sortf, void, ( const char* functionName ),, "%array.sortf( \"mySortCallback\" );\n" "@endtsexample\n" ) { - object->sort( true, false, functionName ); + object->sort( true, true, functionName ); } DefineEngineMethod( ArrayObject, sortfk, void, ( const char* functionName ),, @@ -862,7 +862,7 @@ DefineEngineMethod( ArrayObject, sortfk, void, ( const char* functionName ),, "@param functionName Name of a function that takes two arguments A and B and returns -1 if A is less, 1 if B is less, and 0 if both are equal." "@see sortf\n" ) { - object->sort( false, false, functionName ); + object->sort( false, true, functionName ); } DefineEngineMethod( ArrayObject, sortfd, void, ( const char* functionName ),, @@ -870,7 +870,7 @@ DefineEngineMethod( ArrayObject, sortfd, void, ( const char* functionName ),, "@param functionName Name of a function that takes two arguments A and B and returns -1 if A is less, 1 if B is less, and 0 if both are equal." "@see sortf\n" ) { - object->sort( true, true, functionName ); + object->sort( true, false, functionName ); } DefineEngineMethod( ArrayObject, sortfkd, void, ( const char* functionName ),, @@ -878,7 +878,7 @@ DefineEngineMethod( ArrayObject, sortfkd, void, ( const char* functionName ),, "@param functionName Name of a function that takes two arguments A and B and returns -1 if A is less, 1 if B is less, and 0 if both are equal." "@see sortf\n" ) { - object->sort( false, true, functionName ); + object->sort( false, false, functionName ); } DefineEngineMethod( ArrayObject, moveFirst, S32, (),, diff --git a/Engine/source/console/arrayObject.h b/Engine/source/console/arrayObject.h index d905467c03..caab6dbd58 100644 --- a/Engine/source/console/arrayObject.h +++ b/Engine/source/console/arrayObject.h @@ -57,7 +57,7 @@ class ArrayObject : public SimObject /// @name Sorting /// @{ - static bool smIncreasing; + static bool smDecreasing; static bool smCaseSensitive; static const char* smCompareFunction; @@ -175,15 +175,15 @@ class ArrayObject : public SimObject /// This sorts the array. /// @param valtest Determines whether sorting by value or key. - /// @param desc Determines if sorting ascending or descending. + /// @param asc Determines if sorting ascending or descending. /// @param numeric Determines if sorting alpha or numeric search. - void sort( bool valtest, bool desc, bool numeric ); + void sort( bool valtest, bool asc, bool numeric ); /// This sorts the array using a script callback. /// @param valtest Determines whether sorting by value or key. - /// @param desc Determines if sorting ascending or descending. + /// @param asc Determines if sorting ascending or descending. /// @param callbackFunctionName Name of the script function. - void sort( bool valtest, bool desc, const char* callbackFunctionName ); + void sort( bool valtest, bool asc, const char* callbackFunctionName ); /// @} diff --git a/Engine/source/console/astNodes.cpp b/Engine/source/console/astNodes.cpp index d055801a0e..11cc44f903 100644 --- a/Engine/source/console/astNodes.cpp +++ b/Engine/source/console/astNodes.cpp @@ -23,7 +23,6 @@ #include "platform/platform.h" #include "console/console.h" #include "console/telnetDebugger.h" -#include "platform/event.h" #include "console/ast.h" #include "core/tAlgorithm.h" diff --git a/Engine/source/console/compiler.cpp b/Engine/source/console/compiler.cpp index b3a9bfb5ff..ba8a0c314e 100644 --- a/Engine/source/console/compiler.cpp +++ b/Engine/source/console/compiler.cpp @@ -23,7 +23,6 @@ #include "platform/platform.h" #include "console/console.h" #include "console/telnetDebugger.h" -#include "platform/event.h" #include "console/ast.h" #include "core/tAlgorithm.h" diff --git a/Engine/source/console/consoleFunctions.cpp b/Engine/source/console/consoleFunctions.cpp index a2a6b11379..537f583baa 100644 --- a/Engine/source/console/consoleFunctions.cpp +++ b/Engine/source/console/consoleFunctions.cpp @@ -30,7 +30,6 @@ #include "core/strings/unicode.h" #include "core/stream/fileStream.h" #include "console/compiler.h" -#include "platform/event.h" #include "platform/platformInput.h" #include "core/util/journal/journal.h" #include "core/util/uuid.h" @@ -1580,13 +1579,13 @@ DefineEngineFunction( gotoWebPage, void, ( const char* address ),, //----------------------------------------------------------------------------- -DefineEngineFunction( displaySplashWindow, bool, (),, +DefineEngineFunction( displaySplashWindow, bool, (const char* path), ("art/gui/splash.bmp"), "Display a startup splash window suitable for showing while the engine still starts up.\n\n" "@note This is currently only implemented on Windows.\n\n" "@return True if the splash window could be successfully initialized.\n\n" "@ingroup Platform" ) { - return Platform::displaySplashWindow(); + return Platform::displaySplashWindow(path); } //----------------------------------------------------------------------------- @@ -2023,8 +2022,10 @@ DefineEngineFunction( exec, bool, ( const char* fileName, bool noCalls, bool jou //} // If we had a DSO, let's check to see if we should be reading from it. - if(compiled && dsoFile != NULL && (scriptFile == NULL|| (scriptModifiedTime - dsoModifiedTime) > Torque::Time(0))) - { + //MGT: fixed bug with dsos not getting recompiled correctly + //Note: Using Nathan Martin's version from the forums since its easier to read and understand + if(compiled && dsoFile != NULL && (scriptFile == NULL|| (dsoModifiedTime >= scriptModifiedTime))) + { //MGT: end compiledStream = FileStream::createAndOpen( nameBuffer, Torque::FS::File::Read ); if (compiledStream) { diff --git a/Engine/source/console/fileSystemFunctions.cpp b/Engine/source/console/fileSystemFunctions.cpp index b4007beb0f..d6e29ecaa9 100644 --- a/Engine/source/console/fileSystemFunctions.cpp +++ b/Engine/source/console/fileSystemFunctions.cpp @@ -27,7 +27,6 @@ #include "console/ast.h" #include "core/stream/fileStream.h" #include "console/compiler.h" -#include "platform/event.h" #include "platform/platformInput.h" #include "torqueConfig.h" #include "core/frameAllocator.h" diff --git a/Engine/source/console/scriptObjects.cpp b/Engine/source/console/scriptObjects.cpp index 2f7869976e..e5916fb64e 100644 --- a/Engine/source/console/scriptObjects.cpp +++ b/Engine/source/console/scriptObjects.cpp @@ -27,6 +27,10 @@ #include "console/simBase.h" #include "console/engineAPI.h" +//----------------------------------------------------------------------------- +// ScriptObject +//----------------------------------------------------------------------------- + IMPLEMENT_CONOBJECT(ScriptObject); ConsoleDocClass( ScriptObject, @@ -83,23 +87,103 @@ void ScriptObject::onRemove() } //----------------------------------------------------------------------------- -// Script group placeholder +// ScriptTickObject //----------------------------------------------------------------------------- -class ScriptGroup : public SimGroup +IMPLEMENT_CONOBJECT(ScriptTickObject); + +ConsoleDocClass( ScriptTickObject, + "@brief A ScriptObject that responds to tick and frame events.\n\n" + + "ScriptTickObject is a ScriptObject that adds callbacks for tick and frame events. Use " + "setProcessTicks() to enable or disable the onInterpolateTick() and onProcessTick() callbacks. " + "The callOnAdvanceTime property determines if the onAdvanceTime() callback is called.\n\n" + + "@see ScriptObject\n" + "@ingroup Console\n" + "@ingroup Scripting" +); + +IMPLEMENT_CALLBACK( ScriptTickObject, onInterpolateTick, void, ( F32 delta ), ( delta ), + "This is called every frame, but only if the object is set to process ticks.\n" + "@param delta The time delta for this frame.\n" +); + +IMPLEMENT_CALLBACK( ScriptTickObject, onProcessTick, void, (), (), + "Called once every 32ms if this object is set to process ticks.\n" +); + +IMPLEMENT_CALLBACK( ScriptTickObject, onAdvanceTime, void, ( F32 timeDelta ), ( timeDelta ), + "This is called every frame regardless if the object is set to process ticks, but only " + "if the callOnAdvanceTime property is set to true.\n" + "@param timeDelta The time delta for this frame.\n" + "@see callOnAdvanceTime\n" +); + +ScriptTickObject::ScriptTickObject() { - typedef SimGroup Parent; - -public: - ScriptGroup(); - bool onAdd(); - void onRemove(); + mCallOnAdvanceTime = false; +} - DECLARE_CONOBJECT(ScriptGroup); +void ScriptTickObject::initPersistFields() +{ + addField("callOnAdvanceTime", TypeBool, Offset(mCallOnAdvanceTime, ScriptTickObject), "Call the onAdvaceTime() callback."); - DECLARE_CALLBACK(void, onAdd, (SimObjectId ID) ); - DECLARE_CALLBACK(void, onRemove, (SimObjectId ID)); -}; + Parent::initPersistFields(); +} + +bool ScriptTickObject::onAdd() +{ + if (!Parent::onAdd()) + return false; + + return true; +} + +void ScriptTickObject::onRemove() +{ + Parent::onRemove(); +} + +void ScriptTickObject::interpolateTick( F32 delta ) +{ + onInterpolateTick_callback(delta); +} + +void ScriptTickObject::processTick() +{ + onProcessTick_callback(); +} + +void ScriptTickObject::advanceTime( F32 timeDelta ) +{ + if(mCallOnAdvanceTime) + { + onAdvanceTime_callback(timeDelta); + } +} + +DefineEngineMethod( ScriptTickObject, setProcessTicks, void, ( bool tick ),, + "@brief Sets this object as either tick processing or not.\n\n" + + "@param tick This object's onInterpolateTick() and onProcessTick() callbacks are called if set to true.\n\n") +{ + object->setProcessTicks(tick); +} + +DefineEngineMethod( ScriptTickObject, isProcessingTicks, bool, ( ),, + "@brief Is this object wanting to receive tick notifications.\n\n" + + "If this object is set to receive tick notifications then its onInterpolateTick() and " + "onProcessTick() callbacks are called.\n" + "@return True if object wants tick notifications\n\n" ) +{ + return object->isProcessingTicks(); +} + +//----------------------------------------------------------------------------- +// ScriptGroup +//----------------------------------------------------------------------------- IMPLEMENT_CONOBJECT(ScriptGroup); @@ -157,7 +241,6 @@ bool ScriptGroup::onAdd() return false; // Call onAdd in script! - //Con::executef(this, "onAdd", Con::getIntArg(getId())); onAdd_callback(getId()); return true; } @@ -165,7 +248,6 @@ bool ScriptGroup::onAdd() void ScriptGroup::onRemove() { // Call onRemove in script! - //Con::executef(this, "onRemove", Con::getIntArg(getId())); onRemove_callback(getId()); Parent::onRemove(); diff --git a/Engine/source/console/scriptObjects.h b/Engine/source/console/scriptObjects.h index 65780b6330..4686a547be 100644 --- a/Engine/source/console/scriptObjects.h +++ b/Engine/source/console/scriptObjects.h @@ -27,8 +27,12 @@ #include "console/consoleInternal.h" #endif +#ifndef _ITICKABLE_H_ +#include "core/iTickable.h" +#endif + //----------------------------------------------------------------------------- -// Script object placeholder +// ScriptObject //----------------------------------------------------------------------------- class ScriptObject : public SimObject @@ -46,4 +50,51 @@ class ScriptObject : public SimObject DECLARE_CALLBACK(void, onRemove, (SimObjectId ID)); }; +//----------------------------------------------------------------------------- +// ScriptTickObject +//----------------------------------------------------------------------------- + +class ScriptTickObject : public ScriptObject, public virtual ITickable +{ + typedef ScriptObject Parent; + +protected: + bool mCallOnAdvanceTime; + +public: + ScriptTickObject(); + static void initPersistFields(); + bool onAdd(); + void onRemove(); + + virtual void interpolateTick( F32 delta ); + virtual void processTick(); + virtual void advanceTime( F32 timeDelta ); + + DECLARE_CONOBJECT(ScriptTickObject); + + DECLARE_CALLBACK(void, onInterpolateTick, (F32 delta) ); + DECLARE_CALLBACK(void, onProcessTick, () ); + DECLARE_CALLBACK(void, onAdvanceTime, (F32 timeDelta) ); +}; + +//----------------------------------------------------------------------------- +// ScriptGroup +//----------------------------------------------------------------------------- + +class ScriptGroup : public SimGroup +{ + typedef SimGroup Parent; + +public: + ScriptGroup(); + bool onAdd(); + void onRemove(); + + DECLARE_CONOBJECT(ScriptGroup); + + DECLARE_CALLBACK(void, onAdd, (SimObjectId ID) ); + DECLARE_CALLBACK(void, onRemove, (SimObjectId ID)); +}; + #endif \ No newline at end of file diff --git a/Engine/source/console/telnetConsole.cpp b/Engine/source/console/telnetConsole.cpp index a44bd31668..2a6e0258ae 100644 --- a/Engine/source/console/telnetConsole.cpp +++ b/Engine/source/console/telnetConsole.cpp @@ -25,7 +25,6 @@ #include "console/engineAPI.h" #include "core/strings/stringFunctions.h" -#include "platform/event.h" #include "core/util/journal/process.h" #include "core/module.h" diff --git a/Engine/source/console/telnetConsole.h b/Engine/source/console/telnetConsole.h index 4313967255..96677942c0 100644 --- a/Engine/source/console/telnetConsole.h +++ b/Engine/source/console/telnetConsole.h @@ -26,9 +26,6 @@ #ifndef _CONSOLE_H_ #include "console/console.h" #endif -#ifndef _EVENT_H_ -#include "platform/event.h" -#endif #include "platform/platformNet.h" /// Telnet admin console. diff --git a/Engine/source/console/telnetDebugger.cpp b/Engine/source/console/telnetDebugger.cpp index 25fdca8493..06b758d9af 100644 --- a/Engine/source/console/telnetDebugger.cpp +++ b/Engine/source/console/telnetDebugger.cpp @@ -25,7 +25,6 @@ #include "core/frameAllocator.h" #include "console/console.h" -#include "platform/event.h" #include "core/stringTable.h" #include "console/consoleInternal.h" #include "console/ast.h" diff --git a/Engine/source/core/bitVector.h b/Engine/source/core/bitVector.h index e1bc6c709c..3cd60108a9 100644 --- a/Engine/source/core/bitVector.h +++ b/Engine/source/core/bitVector.h @@ -56,6 +56,9 @@ class BitVector /// Constructs a bit vector with the desired size. /// @note The resulting vector is not cleared. BitVector( U32 sizeInBits ); + + /// Copy constructor + BitVector( const BitVector &r); /// Destructor. ~BitVector(); @@ -86,6 +89,9 @@ class BitVector /// Copy the content of another bit vector. void copy( const BitVector &from ); + /// Copy the contents of another bit vector + BitVector& operator=( const BitVector &r); + /// @name Mutators /// Note that bits are specified by index, unlike BitSet32. /// @{ @@ -150,6 +156,11 @@ inline BitVector::BitVector( U32 sizeInBits ) setSize( sizeInBits ); } +inline BitVector::BitVector( const BitVector &r ) +{ + copy(r); +} + inline BitVector::~BitVector() { delete [] mBits; @@ -182,6 +193,12 @@ inline void BitVector::copy( const BitVector &from ) dMemcpy( mBits, from.getBits(), getByteSize() ); } +inline BitVector& BitVector::operator=( const BitVector &r) +{ + copy(r); + return *this; +} + inline void BitVector::set() { if (mSize != 0) diff --git a/Engine/source/core/dnet.cpp b/Engine/source/core/dnet.cpp index 6eda3533eb..324a9fcfd8 100644 --- a/Engine/source/core/dnet.cpp +++ b/Engine/source/core/dnet.cpp @@ -79,11 +79,19 @@ void ConnectionProtocol::buildSendPacketHeader(BitStream *stream, S32 packetType stream->writeFlag(true); stream->writeInt(mConnectSequence & 1, 1); - stream->writeInt(mLastSendSeq, 9); - stream->writeInt(mLastSeqRecvd, 9); - stream->writeInt(packetType, 2); - stream->writeInt(ackByteCount, 3); - stream->writeInt(mAckMask, ackByteCount * 8); + stream->writeInt(mLastSendSeq & 0x1FF, 9); + stream->writeInt(mLastSeqRecvd & 0x1FF, 9); + stream->writeInt(packetType & 0x3, 2); + stream->writeInt(ackByteCount & 0x7, 3); + U32 bitmask = ~(0xFFFFFFFF << (ackByteCount*8)); + if(ackByteCount == 4) + { + // Performing a bit shift that is the same size as the variable being shifted + // is undefined in the C/C++ standard. Handle that exception here when + // ackByteCount*8 == 4*8 == 32 + bitmask = 0xFFFFFFFF; + } + stream->writeInt(mAckMask & bitmask, ackByteCount * 8); // if we're resending this header, we can't advance the // sequence recieved (in case this packet drops and the prev one diff --git a/Engine/source/core/dnet.h b/Engine/source/core/dnet.h index 5f35c100d2..56ba7acf65 100644 --- a/Engine/source/core/dnet.h +++ b/Engine/source/core/dnet.h @@ -26,9 +26,6 @@ #ifndef _PLATFORM_H_ #include "platform/platform.h" #endif -#ifndef _EVENT_H_ -#include "platform/event.h" -#endif #include "platform/platformNet.h" diff --git a/Engine/source/core/stream/bitStream.cpp b/Engine/source/core/stream/bitStream.cpp index 6080eee943..4ea46b6f59 100644 --- a/Engine/source/core/stream/bitStream.cpp +++ b/Engine/source/core/stream/bitStream.cpp @@ -336,6 +336,8 @@ S32 BitStream::readInt(S32 bitCount) void BitStream::writeInt(S32 val, S32 bitCount) { + AssertWarn((bitCount == 32) || ((val >> bitCount) == 0), "BitStream::writeInt: value out of range"); + val = convertHostToLEndian(val); writeBits(bitCount, &val); } diff --git a/Engine/source/core/stream/ioHelper.h b/Engine/source/core/stream/ioHelper.h index 1255356d05..ed006aff62 100644 --- a/Engine/source/core/stream/ioHelper.h +++ b/Engine/source/core/stream/ioHelper.h @@ -31,6 +31,18 @@ /// template expansion. namespace IOHelper { + template + inline bool reads(Stream *s,A& a,B& b,C& c,D& d,E& e,F& f,G& g,H& h,I& i,J& j,K& k,L& l,M& m) + { s->read(&a); s->read(&b); s->read(&c); s->read(&d); s->read(&e); s->read(&f); s->read(&g); s->read(&h); s->read(&i); s->read(&j); s->read(&k); s->read(&l); return s->read(&m); } + + template + inline bool reads(Stream *s,A& a,B& b,C& c,D& d,E& e,F& f,G& g,H& h,I& i,J& j,K& k,L& l) + { s->read(&a); s->read(&b); s->read(&c); s->read(&d); s->read(&e); s->read(&f); s->read(&g); s->read(&h); s->read(&i); s->read(&j); s->read(&k); return s->read(&l); } + + template + inline bool reads(Stream *s,A& a,B& b,C& c,D& d,E& e,F& f,G& g,H& h,I& i,J& j,K& k) + { s->read(&a); s->read(&b); s->read(&c); s->read(&d); s->read(&e); s->read(&f); s->read(&g); s->read(&h); s->read(&i); s->read(&j); return s->read(&k); } + template inline bool reads(Stream *s,A& a,B& b,C& c,D& d,E& e,F& f,G& g,H& h,I& i,J& j) { s->read(&a); s->read(&b); s->read(&c); s->read(&d); s->read(&e); s->read(&f); s->read(&g); s->read(&h); s->read(&i); return s->read(&j); } @@ -71,6 +83,18 @@ namespace IOHelper inline bool reads(Stream *s,A& a) { return s->read(&a); } + template + inline bool writes(Stream *s,A& a,B& b,C& c,D& d,E& e,F& f,G& g,H& h,I& i,J& j,K& k,L& l,M& m) + { s->write(a); s->write(b); s->write(c); s->write(d); s->write(e); s->write(f); s->write(g); s->write(h); s->write(i); s->write(j); s->write(k); s->write(l); return s->write(m); } + + template + inline bool writes(Stream *s,A& a,B& b,C& c,D& d,E& e,F& f,G& g,H& h,I& i,J& j,K& k,L& l) + { s->write(a); s->write(b); s->write(c); s->write(d); s->write(e); s->write(f); s->write(g); s->write(h); s->write(i); s->write(j); s->write(k); return s->write(l); } + + template + inline bool writes(Stream *s,A& a,B& b,C& c,D& d,E& e,F& f,G& g,H& h,I& i,J& j,K& k) + { s->write(a); s->write(b); s->write(c); s->write(d); s->write(e); s->write(f); s->write(g); s->write(h); s->write(i); s->write(j); return s->write(k); } + template inline bool writes(Stream *s,A& a,B& b,C& c,D& d,E& e,F& f,G& g,H& h,I& i,J& j) { s->write(a); s->write(b); s->write(c); s->write(d); s->write(e); s->write(f); s->write(g); s->write(h); s->write(i); return s->write(j); } diff --git a/Engine/source/core/util/FastDelegate.h b/Engine/source/core/util/FastDelegate.h index 4ac73c6cb0..b977a6a126 100644 --- a/Engine/source/core/util/FastDelegate.h +++ b/Engine/source/core/util/FastDelegate.h @@ -1613,6 +1613,261 @@ class FastDelegate8 { return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8); } }; +//N=11 +template +class FastDelegate11 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate11 type; + + // Construction and comparison functions + FastDelegate11() { clear(); } + FastDelegate11(const FastDelegate11 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate11 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate11 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate11 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate11 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate11 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate11(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate11(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate11(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8), Param9 p9, Param10 p10, Param11 p11) { + m_Closure.bindstaticfunc(this, &FastDelegate11::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); } +}; + +//N=12 +template +class FastDelegate12 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate12 type; + + // Construction and comparison functions + FastDelegate12() { clear(); } + FastDelegate12(const FastDelegate12 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate12 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate12 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate12 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate12 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate12 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate12(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate12(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate12(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8), Param9 p9, Param10 p10, Param11 p11, Param12 p12) { + m_Closure.bindstaticfunc(this, &FastDelegate12::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,p12); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); } +}; + +//N=13 +template +class FastDelegate13 { +private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType (*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13); + typedef RetType (*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13); + typedef RetType (detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; +public: + // Typedefs to aid generic programming + typedef FastDelegate13 type; + + // Construction and comparison functions + FastDelegate13() { clear(); } + FastDelegate13(const FastDelegate13 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + void operator = (const FastDelegate13 &x) { + m_Closure.CopyFrom(this, x.m_Closure); } + bool operator ==(const FastDelegate13 &x) const { + return m_Closure.IsEqual(x.m_Closure); } + bool operator !=(const FastDelegate13 &x) const { + return !m_Closure.IsEqual(x.m_Closure); } + bool operator <(const FastDelegate13 &x) const { + return m_Closure.IsLess(x.m_Closure); } + bool operator >(const FastDelegate13 &x) const { + return x.m_Closure.IsLess(m_Closure); } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate13(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) ) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Binding to const member functions. + template < class X, class Y > + FastDelegate13(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType (X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate13(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) ) { + bind(function_to_bind); } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) ) { + bind(function_to_bind); } + inline void bind(DesiredRetType (*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8), Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) { + m_Closure.bindstaticfunc(this, &FastDelegate13::InvokeStaticFunction, + function_to_bind); } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11,p12,p13); } + // Implicit conversion to "bool" using the safe_bool idiom +private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; +public: + operator unspecified_bool_type() const { + return empty()? 0: &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; } + inline bool empty() const { + return !m_Closure; } + void clear() { m_Closure.clear();} + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + +private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); } +}; + //////////////////////////////////////////////////////////////////////////////// // Fast Delegates, part 4: @@ -1965,6 +2220,117 @@ class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, *static_cast(this) = x; } }; +//N=11 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11 ) > +// instead of +// FastDelegate11 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11 ) > + // Inherit from FastDelegate11 so that it can be treated just like a FastDelegate11 + : public FastDelegate11 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate11 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=12 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12 ) > +// instead of +// FastDelegate12 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12 ) > + // Inherit from FastDelegate12 so that it can be treated just like a FastDelegate12 + : public FastDelegate12 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate12 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + +//N=13 +// Specialization to allow use of +// FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13 ) > +// instead of +// FastDelegate13 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, R > +template +class FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13 ) > + // Inherit from FastDelegate13 so that it can be treated just like a FastDelegate13 + : public FastDelegate13 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, R > +{ +public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate13 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, Param9, Param10, Param11, Param12, Param13, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13 )) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R (X::* function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13 ) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R (*function_to_bind)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13 )) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; } +}; + #endif //FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX @@ -2097,6 +2463,39 @@ FastDelegate8(x, func); } +//N=11 +template +FastDelegate11 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11)) { + return FastDelegate11(x, func); +} + +template +FastDelegate11 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11) const) { + return FastDelegate11(x, func); +} + +//N=12 +template +FastDelegate12 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12)) { + return FastDelegate12(x, func); +} + +template +FastDelegate12 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12) const) { + return FastDelegate12(x, func); +} + +//N=13 +template +FastDelegate13 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13)) { + return FastDelegate13(x, func); +} + +template +FastDelegate13 MakeDelegate(Y* x, RetType (X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8, Param9 p9, Param10 p10, Param11 p11, Param12 p12, Param13 p13) const) { + return FastDelegate13(x, func); +} + // clean up after ourselves... #undef FASTDLGT_RETTYPE diff --git a/Engine/source/core/util/journal/journal.h b/Engine/source/core/util/journal/journal.h index aefebcd23f..9db84e2f6e 100644 --- a/Engine/source/core/util/journal/journal.h +++ b/Engine/source/core/util/journal/journal.h @@ -73,6 +73,33 @@ class Journal void dispatch() { (*ptr)(); } }; + template + struct FunctorDecl< void(*)(A,B,C,D,E,F,G,H,I,J,K,L,M) >: public Functor { + typedef void(*FuncPtr)(A,B,C,D,E,F,G,H,I,J,K,L,M); + FuncPtr ptr; A a; B b; C c; D d; E e; F f; G g; H h; I i; J j; K k; L l; M m; + FunctorDecl(FuncPtr p): ptr(p) {} + void read(Stream *file) { IOHelper::reads(file,a,b,c,d,e,f,g,h,i,j,k,l,m); } + void dispatch() { (*ptr)(a,b,c,d,e,f,g,h,i,j,k,l,m); } + }; + + template + struct FunctorDecl< void(*)(A,B,C,D,E,F,G,H,I,J,K,L) >: public Functor { + typedef void(*FuncPtr)(A,B,C,D,E,F,G,H,I,J,K,L); + FuncPtr ptr; A a; B b; C c; D d; E e; F f; G g; H h; I i; J j; K k; L l; + FunctorDecl(FuncPtr p): ptr(p) {} + void read(Stream *file) { IOHelper::reads(file,a,b,c,d,e,f,g,h,i,j,k,l); } + void dispatch() { (*ptr)(a,b,c,d,e,f,g,h,i,j,k,l); } + }; + + template + struct FunctorDecl< void(*)(A,B,C,D,E,F,G,H,I,J,K) >: public Functor { + typedef void(*FuncPtr)(A,B,C,D,E,F,G,H,I,J,K); + FuncPtr ptr; A a; B b; C c; D d; E e; F f; G g; H h; I i; J j; K k; + FunctorDecl(FuncPtr p): ptr(p) {} + void read(Stream *file) { IOHelper::reads(file,a,b,c,d,e,f,g,h,i,j,k); } + void dispatch() { (*ptr)(a,b,c,d,e,f,g,h,i,j,k); } + }; + template struct FunctorDecl< void(*)(A,B,C,D,E,F,G,H,I,J) >: public Functor { typedef void(*FuncPtr)(A,B,C,D,E,F,G,H,I,J); @@ -174,6 +201,36 @@ class Journal void dispatch() { (obj->*method)(); } }; + template + struct MethodDecl: public Functor { + typedef T* ObjPtr; + typedef void(T::*MethodPtr)(A,B,C,D,E,F,G,H,I,J,K,L,M); + ObjPtr obj; MethodPtr method; A a; B b; C c; D d; E e; F f; G g; H h; I i; J j; K k; L l; M m; + MethodDecl(ObjPtr o,MethodPtr p): obj(o), method(p) {} + void read(Stream *file) { IOHelper::reads(file,a,b,c,d,e,f,g,h,i,j,k,l,m); } + void dispatch() { (obj->*method)(a,b,c,d,e,f,g,h,i,j,k,l,m); } + }; + + template + struct MethodDecl: public Functor { + typedef T* ObjPtr; + typedef void(T::*MethodPtr)(A,B,C,D,E,F,G,H,I,J,K,L); + ObjPtr obj; MethodPtr method; A a; B b; C c; D d; E e; F f; G g; H h; I i; J j; K k; L l; + MethodDecl(ObjPtr o,MethodPtr p): obj(o), method(p) {} + void read(Stream *file) { IOHelper::reads(file,a,b,c,d,e,f,g,h,i,j,k,l); } + void dispatch() { (obj->*method)(a,b,c,d,e,f,g,h,i,j,k,l); } + }; + + template + struct MethodDecl: public Functor { + typedef T* ObjPtr; + typedef void(T::*MethodPtr)(A,B,C,D,E,F,G,H,I,J,K); + ObjPtr obj; MethodPtr method; A a; B b; C c; D d; E e; F f; G g; H h; I i; J j; K k; + MethodDecl(ObjPtr o,MethodPtr p): obj(o), method(p) {} + void read(Stream *file) { IOHelper::reads(file,a,b,c,d,e,f,g,h,i,j,k); } + void dispatch() { (obj->*method)(a,b,c,d,e,f,g,h,i,j,k); } + }; + template struct MethodDecl: public Functor { typedef T* ObjPtr; @@ -445,6 +502,12 @@ class Journal return value; \ } + template + Method(Func,(Func func,A a,B b,C c,D d,E e,F f, G g, H h, I i, J j, K k, L l, M m),(a,b,c,d,e,f,g,h,i,j,k,l,m)) + template + Method(Func,(Func func,A a,B b,C c,D d,E e,F f, G g, H h, I i, J j, K k, L l),(a,b,c,d,e,f,g,h,i,j,k,l)) + template + Method(Func,(Func func,A a,B b,C c,D d,E e,F f, G g, H h, I i, J j, K k),(a,b,c,d,e,f,g,h,i,j,k)) template Method(Func,(Func func,A a,B b,C c,D d,E e,F f, G g, H h, I i, J j),(a,b,c,d,e,f,g,h,i,j)) template @@ -493,6 +556,12 @@ class Journal return; \ } + template + Method((Func func,A a,B b,C c,D d,E e,F f,G g,H h,I i,J j,K k,L l,M m),(mFile,id,a,b,c,d,e,f,g,h,i,j,k,l,m),(a,b,c,d,e,f,g,h,i,j,k,l,m)) + template + Method((Func func,A a,B b,C c,D d,E e,F f,G g,H h,I i,J j,K k,L l),(mFile,id,a,b,c,d,e,f,g,h,i,j,k,l),(a,b,c,d,e,f,g,h,i,j,k,l)) + template + Method((Func func,A a,B b,C c,D d,E e,F f,G g,H h,I i,J j,K k),(mFile,id,a,b,c,d,e,f,g,h,i,j,k),(a,b,c,d,e,f,g,h,i,j,k)) template Method((Func func,A a,B b,C c,D d,E e,F f,G g,H h,I i,J j),(mFile,id,a,b,c,d,e,f,g,h,i,j),(a,b,c,d,e,f,g,h,i,j)) template @@ -537,6 +606,12 @@ class Journal } + template + Method((Obj* obj,void (Obj::*method)(A,B,C,D,E,F,G,H,I,J,K,L,M),A a,B b,C c,D d,E e,F f,G g,H h,I i,J j,K k,L l,M m),(mFile,id,a,b,c,d,e,f,g,h,i,j,k,l,m),(a,b,c,d,e,f,g,h,i,j,k,l,m)) + template + Method((Obj* obj,void (Obj::*method)(A,B,C,D,E,F,G,H,I,J,K,L),A a,B b,C c,D d,E e,F f,G g,H h,I i,J j,K k,L l),(mFile,id,a,b,c,d,e,f,g,h,i,j,k,l),(a,b,c,d,e,f,g,h,i,j,k,l)) + template + Method((Obj* obj,void (Obj::*method)(A,B,C,D,E,F,G,H,I,J,K),A a,B b,C c,D d,E e,F f,G g,H h,I i,J j,K k),(mFile,id,a,b,c,d,e,f,g,h,i,j,k),(a,b,c,d,e,f,g,h,i,j,k)) template Method((Obj* obj,void (Obj::*method)(A,B,C,D,E,F,G,H,I,J),A a,B b,C c,D d,E e,F f,G g,H h,I i,J j),(mFile,id,a,b,c,d,e,f,g,h,i,j),(a,b,c,d,e,f,g,h,i,j)) template @@ -574,6 +649,12 @@ class Journal return false; \ } + template + Method((A& a,B& b,C& c,D& d,E& e, F& f, G& g, H& h, I& i,J& j,K& k,L& l,M& m),(mFile,a,b,c,d,e,f,g,h,i,j,k,l,m)); + template + Method((A& a,B& b,C& c,D& d,E& e, F& f, G& g, H& h, I& i,J& j,K& k,L& l),(mFile,a,b,c,d,e,f,g,h,i,j,k,l)); + template + Method((A& a,B& b,C& c,D& d,E& e, F& f, G& g, H& h, I& i,J& j,K& k),(mFile,a,b,c,d,e,f,g,h,i,j,k)); template Method((A& a,B& b,C& c,D& d,E& e, F& f, G& g, H& h, I& i,J& j),(mFile,a,b,c,d,e,f,g,h,i,j)); template @@ -608,6 +689,12 @@ class Journal return false; \ } + template + Method((A& a,B& b,C& c,D& d,E& e,F& f,G& g, H& h, I& i, J& j, K& k, L& l, M& m),(mFile,a,b,c,d,e,f,g,h,i,j,k,l,m)); + template + Method((A& a,B& b,C& c,D& d,E& e,F& f,G& g, H& h, I& i, J& j, K& k, L& l),(mFile,a,b,c,d,e,f,g,h,i,j,k,l)); + template + Method((A& a,B& b,C& c,D& d,E& e,F& f,G& g, H& h, I& i, J& j, K& k),(mFile,a,b,c,d,e,f,g,h,i,j,k)); template Method((A& a,B& b,C& c,D& d,E& e,F& f,G& g, H& h, I& i, J& j),(mFile,a,b,c,d,e,f,g,h,i,j)); template diff --git a/Engine/source/core/util/journal/journaledSignal.h b/Engine/source/core/util/journal/journaledSignal.h index 99843fcf50..2c9079bd35 100644 --- a/Engine/source/core/util/journal/journaledSignal.h +++ b/Engine/source/core/util/journal/journaledSignal.h @@ -243,6 +243,75 @@ class JournaledSignal : public Signal +template +class JournaledSignal : public Signal +{ + typedef Signal Parent; + +public: + JournaledSignal() + { + Journal::DeclareFunction((Parent*)this, &Parent::trigger); + } + + ~JournaledSignal() + { + Journal::RemoveFunction((Parent*)this, &Parent::trigger); + } + + void trigger(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k) + { + Journal::Call((Parent*)this, &Parent::trigger, a, b, c, d, e, f, g, h, i, j, k); + } +}; + +/// @copydoc JournaledSignal +template +class JournaledSignal : public Signal +{ + typedef Signal Parent; + +public: + JournaledSignal() + { + Journal::DeclareFunction((Parent*)this, &Parent::trigger); + } + + ~JournaledSignal() + { + Journal::RemoveFunction((Parent*)this, &Parent::trigger); + } + + void trigger(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l) + { + Journal::Call((Parent*)this, &Parent::trigger, a, b, c, d, e, f, g, h, i, j, k, l); + } +}; + +/// @copydoc JournaledSignal +template +class JournaledSignal : public Signal +{ + typedef Signal Parent; + +public: + JournaledSignal() + { + Journal::DeclareFunction((Parent*)this, &Parent::trigger); + } + + ~JournaledSignal() + { + Journal::RemoveFunction((Parent*)this, &Parent::trigger); + } + + void trigger(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m) + { + Journal::Call((Parent*)this, &Parent::trigger, a, b, c, d, e, f, g, h, i, j, k, l, m); + } +}; + //----------------------------------------------------------------------------- // Common event callbacks definitions @@ -325,8 +394,8 @@ typedef JournaledSignal ResizeEvent; /// void event(S32 timeDelta) typedef JournaledSignal TimeManagerEvent; -// void event(U32 deviceInst,F32 fValue, U16 deviceType, U16 objType, U16 ascii, U16 objInst, U8 action, U8 modifier) -typedef JournaledSignal InputEvent; +// void event(U32 deviceInst, F32 fValue, F32 fValue2, F32 fValue3, F32 fValue4, S32 iValue, U16 deviceType, U16 objType, U16 ascii, U16 objInst, U8 action, U8 modifier) +typedef JournaledSignal InputEvent; /// void event(U32 popupGUID, U32 commandID, bool& returnValue) typedef JournaledSignal PopupMenuEvent; diff --git a/Engine/source/core/util/tSignal.h b/Engine/source/core/util/tSignal.h index 1fbbb07584..ea2e679541 100644 --- a/Engine/source/core/util/tSignal.h +++ b/Engine/source/core/util/tSignal.h @@ -463,6 +463,75 @@ class Signal : public SignalBaseT +class Signal : public SignalBaseT +{ + public: + + bool trigger( A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k ) + { + this->mTriggerNext.push_back(NULL); + for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; ) + { + this->mTriggerNext.last() = ptr->next; + if( !this->getDelegate( ptr )( a, b, c, d, e, f, g, h, i, j, k ) ) + { + this->mTriggerNext.pop_back(); + return false; + } + ptr = this->mTriggerNext.last(); + } + this->mTriggerNext.pop_back(); + return true; + } +}; + +template +class Signal : public SignalBaseT +{ + public: + + bool trigger( A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l ) + { + this->mTriggerNext.push_back(NULL); + for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; ) + { + this->mTriggerNext.last() = ptr->next; + if( !this->getDelegate( ptr )( a, b, c, d, e, f, g, h, i, j, k, l ) ) + { + this->mTriggerNext.pop_back(); + return false; + } + ptr = this->mTriggerNext.last(); + } + this->mTriggerNext.pop_back(); + return true; + } +}; + +template +class Signal : public SignalBaseT +{ + public: + + bool trigger( A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m ) + { + this->mTriggerNext.push_back(NULL); + for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; ) + { + this->mTriggerNext.last() = ptr->next; + if( !this->getDelegate( ptr )( a, b, c, d, e, f, g, h, i, j, k, l, m ) ) + { + this->mTriggerNext.pop_back(); + return false; + } + ptr = this->mTriggerNext.last(); + } + this->mTriggerNext.pop_back(); + return true; + } +}; + // Non short-circuit signal implementations template<> @@ -663,4 +732,58 @@ class Signal : public SignalBaseT +class Signal : public SignalBaseT +{ + public: + + void trigger( A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k ) + { + this->mTriggerNext.push_back(NULL); + for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; ) + { + this->mTriggerNext.last() = ptr->next; + this->getDelegate( ptr )( a, b, c, d, e, f, g, h, i, j, k ); + ptr = this->mTriggerNext.last(); + } + this->mTriggerNext.pop_back(); + } +}; + +template +class Signal : public SignalBaseT +{ + public: + + void trigger( A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l ) + { + this->mTriggerNext.push_back(NULL); + for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; ) + { + this->mTriggerNext.last() = ptr->next; + this->getDelegate( ptr )( a, b, c, d, e, f, g, h, i, j, k, l ); + ptr = this->mTriggerNext.last(); + } + this->mTriggerNext.pop_back(); + } +}; + +template +class Signal : public SignalBaseT +{ + public: + + void trigger( A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l, M m ) + { + this->mTriggerNext.push_back(NULL); + for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; ) + { + this->mTriggerNext.last() = ptr->next; + this->getDelegate( ptr )( a, b, c, d, e, f, g, h, i, j, k, l, m ); + ptr = this->mTriggerNext.last(); + } + this->mTriggerNext.pop_back(); + } +}; + #endif // _TSIGNAL_H_ diff --git a/Engine/source/core/util/timeClass.h b/Engine/source/core/util/timeClass.h index af9fe09fae..2e2f725e6f 100644 --- a/Engine/source/core/util/timeClass.h +++ b/Engine/source/core/util/timeClass.h @@ -79,8 +79,8 @@ class Time Time operator+(const Time &time) const; Time operator-(const Time &time) const; S64 operator/(const Time &time) const; - const Time& operator+=(const Time time); - const Time& operator-=(const Time time); + const Time& operator+=(const Time &time); + const Time& operator-=(const Time &time); template Time operator*(T scaler) const { return Time(_time * scaler); } template Time operator/(T scaler) const { return Time(_time / scaler); } @@ -173,13 +173,13 @@ inline S64 Time::operator/(const Time &time) const return S64(_time / time._time); } -inline const Time& Time::operator+=(const Time time) +inline const Time& Time::operator+=(const Time &time) { _time += time._time; return *this; } -inline const Time& Time::operator-=(const Time time) +inline const Time& Time::operator-=(const Time &time) { _time -= time._time; return *this; diff --git a/Engine/source/environment/basicClouds.cpp b/Engine/source/environment/basicClouds.cpp index ac2f459a7b..6f9b286536 100644 --- a/Engine/source/environment/basicClouds.cpp +++ b/Engine/source/environment/basicClouds.cpp @@ -26,6 +26,7 @@ #include "basicClouds.h" #include "gfx/gfxTransformSaver.h" +#include "gfx/gfxTextureManager.h" #include "core/stream/fileStream.h" #include "core/stream/bitStream.h" #include "scene/sceneRenderState.h" @@ -336,7 +337,7 @@ void BasicClouds::_initTexture() mTexture[i].set( mTexName[i], &GFXDefaultStaticDiffuseProfile, "BasicClouds" ); if ( mTexture[i].isNull() ) - mTexture[i].set( "core/art/warnmat", &GFXDefaultStaticDiffuseProfile, "BasicClouds" ); + mTexture[i].set( GFXTextureManager::getWarningTexturePath(), &GFXDefaultStaticDiffuseProfile, "BasicClouds" ); } } diff --git a/Engine/source/environment/cloudLayer.cpp b/Engine/source/environment/cloudLayer.cpp index 7e424bf813..bf99c9312c 100644 --- a/Engine/source/environment/cloudLayer.cpp +++ b/Engine/source/environment/cloudLayer.cpp @@ -26,6 +26,7 @@ #include "cloudLayer.h" #include "gfx/gfxTransformSaver.h" +#include "gfx/gfxTextureManager.h" #include "core/stream/fileStream.h" #include "core/stream/bitStream.h" #include "scene/sceneRenderState.h" @@ -387,7 +388,7 @@ void CloudLayer::_initTexture() mTexture.set( mTextureName, &GFXDefaultStaticDiffuseProfile, "CloudLayer" ); if ( mTexture.isNull() ) - mTexture.set( "core/art/warnmat", &GFXDefaultStaticDiffuseProfile, "CloudLayer" ); + mTexture.set( GFXTextureManager::getWarningTexturePath(), &GFXDefaultStaticDiffuseProfile, "CloudLayer" ); } void CloudLayer::_initBuffers() diff --git a/Engine/source/environment/waterObject.cpp b/Engine/source/environment/waterObject.cpp index 470d27b8aa..51e7377176 100644 --- a/Engine/source/environment/waterObject.cpp +++ b/Engine/source/environment/waterObject.cpp @@ -38,6 +38,7 @@ #include "T3D/gameBase/gameConnection.h" #include "T3D/shapeBase.h" #include "gfx/gfxOcclusionQuery.h" +#include "gfx/gfxTextureManager.h" #include "gfx/sim/cubemapData.h" #include "math/util/matrixSet.h" #include "sfx/sfxAmbience.h" @@ -1152,12 +1153,12 @@ void WaterObject::initTextures() if ( mRippleTexName.isNotEmpty() ) mRippleTex.set( mRippleTexName, &GFXDefaultStaticDiffuseProfile, "WaterObject::mRippleTex" ); if ( mRippleTex.isNull() ) - mRippleTex.set( "core/art/warnmat", &GFXDefaultStaticDiffuseProfile, "WaterObject::mRippleTex" ); + mRippleTex.set( GFXTextureManager::getWarningTexturePath(), &GFXDefaultStaticDiffuseProfile, "WaterObject::mRippleTex" ); if ( mDepthGradientTexName.isNotEmpty() ) mDepthGradientTex.set( mDepthGradientTexName, &GFXDefaultStaticDiffuseProfile, "WaterObject::mDepthGradientTex" ); if ( mDepthGradientTex.isNull() ) - mDepthGradientTex.set( "core/art/warnmat", &GFXDefaultStaticDiffuseProfile, "WaterObject::mDepthGradientTex" ); + mDepthGradientTex.set( GFXTextureManager::getWarningTexturePath(), &GFXDefaultStaticDiffuseProfile, "WaterObject::mDepthGradientTex" ); if ( mNamedDepthGradTex.isRegistered() ) mNamedDepthGradTex.setTexture( mDepthGradientTex ); @@ -1165,7 +1166,7 @@ void WaterObject::initTextures() if ( mFoamTexName.isNotEmpty() ) mFoamTex.set( mFoamTexName, &GFXDefaultStaticDiffuseProfile, "WaterObject::mFoamTex" ); if ( mFoamTex.isNull() ) - mFoamTex.set( "core/art/warnmat", &GFXDefaultStaticDiffuseProfile, "WaterObject::mFoamTex" ); + mFoamTex.set( GFXTextureManager::getWarningTexturePath(), &GFXDefaultStaticDiffuseProfile, "WaterObject::mFoamTex" ); if ( mCubemapName.isNotEmpty() ) Sim::findObject( mCubemapName, mCubemap ); diff --git a/Engine/source/gfx/D3D9/gfxD3D9QueryFence.cpp b/Engine/source/gfx/D3D9/gfxD3D9QueryFence.cpp index 7056e00b26..7a81069e32 100644 --- a/Engine/source/gfx/D3D9/gfxD3D9QueryFence.cpp +++ b/Engine/source/gfx/D3D9/gfxD3D9QueryFence.cpp @@ -66,19 +66,6 @@ GFXFence::FenceStatus GFXD3D9QueryFence::getStatus() const void GFXD3D9QueryFence::block() { PROFILE_SCOPE(GFXD3D9QueryFence_block); - - // Calling block() before issue() is valid, catch this case - if( mQuery == NULL ) - return; - - HRESULT hRes; - while( ( hRes = mQuery->GetData( NULL, 0, D3DGETDATA_FLUSH ) ) == S_FALSE ) - ; - - // Check for D3DERR_DEVICELOST, if we lost the device, the fence will get - // re-created next issue() - if( hRes == D3DERR_DEVICELOST ) - SAFE_RELEASE( mQuery ); } void GFXD3D9QueryFence::zombify() diff --git a/Engine/source/gfx/gfxFontRenderBatcher.cpp b/Engine/source/gfx/gfxFontRenderBatcher.cpp index cecdd52a23..e782268d0a 100644 --- a/Engine/source/gfx/gfxFontRenderBatcher.cpp +++ b/Engine/source/gfx/gfxFontRenderBatcher.cpp @@ -215,12 +215,18 @@ void FontRenderBatcher::queueChar( UTF16 c, S32 ¤tX, GFXVertexColor &curre FontRenderBatcher::SheetMarker & FontRenderBatcher::getSheetMarker( U32 sheetID ) { - // Allocate if it doesn't exist... - if(mSheets.size() <= sheetID || !mSheets[sheetID]) + // Add empty sheets up to and including the requested sheet if necessary + if (mSheets.size() <= sheetID) { - if(sheetID >= mSheets.size()) - mSheets.setSize(sheetID+1); + S32 oldSize = mSheets.size(); + mSheets.setSize( sheetID + 1 ); + for ( S32 i = oldSize; i < mSheets.size(); i++ ) + mSheets[i] = NULL; + } + // Allocate if it doesn't exist... + if (!mSheets[sheetID]) + { S32 size = sizeof( SheetMarker) + mLength * sizeof( CharMarker ); mSheets[sheetID] = (SheetMarker *)mStorage.alloc(size); mSheets[sheetID]->numChars = 0; diff --git a/Engine/source/gfx/gfxTextureManager.cpp b/Engine/source/gfx/gfxTextureManager.cpp index 2c2dd4fe6a..3edd1f7656 100644 --- a/Engine/source/gfx/gfxTextureManager.cpp +++ b/Engine/source/gfx/gfxTextureManager.cpp @@ -41,6 +41,10 @@ S32 GFXTextureManager::smTextureReductionLevel = 0; +String GFXTextureManager::smMissingTexturePath("core/art/missingTexture"); +String GFXTextureManager::smUnavailableTexturePath("core/art/unavailable"); +String GFXTextureManager::smWarningTexturePath("core/art/warnmat"); + GFXTextureManager::EventSignal GFXTextureManager::smEventSignal; static const String sDDSExt( "dds" ); @@ -52,6 +56,19 @@ void GFXTextureManager::init() "video memory usage. It will skip any textures that have been defined " "as not allowing down scaling.\n" "@ingroup GFX\n" ); + + Con::addVariable( "$pref::Video::missingTexturePath", TypeString, &smMissingTexturePath, + "The file path of the texture to display when the requested texture is missing.\n" + "@ingroup GFX\n" ); + + Con::addVariable( "$pref::Video::unavailableTexturePath", TypeString, &smUnavailableTexturePath, + "@brief The file path of the texture to display when the requested texture is unavailable.\n\n" + "Often this texture is used by GUI controls to indicate that the request image is unavailable.\n" + "@ingroup GFX\n" ); + + Con::addVariable( "$pref::Video::warningTexturePath", TypeString, &smWarningTexturePath, + "The file path of the texture used to warn the developer.\n" + "@ingroup GFX\n" ); } GFXTextureManager::GFXTextureManager() diff --git a/Engine/source/gfx/gfxTextureManager.h b/Engine/source/gfx/gfxTextureManager.h index 5ecbd07d5a..dadd9534c1 100644 --- a/Engine/source/gfx/gfxTextureManager.h +++ b/Engine/source/gfx/gfxTextureManager.h @@ -65,6 +65,15 @@ class GFXTextureManager /// Set up some global script interface stuff. static void init(); + /// Provide the path to the texture to use when the requested one is missing + static const String& getMissingTexturePath() { return smMissingTexturePath; } + + /// Provide the path to the texture to use when the requested one is unavailable. + static const String& getUnavailableTexturePath() { return smUnavailableTexturePath; } + + /// Provide the path to the texture used to warn the developer + static const String& getWarningTexturePath() { return smWarningTexturePath; } + /// Update width and height based on available resources. /// /// We provide a simple interface for managing texture memory usage. Specifically, @@ -177,6 +186,16 @@ class GFXTextureManager /// static S32 smTextureReductionLevel; + /// File path to the missing texture + static String smMissingTexturePath; + + /// File path to the unavailable texture. Often used by GUI controls + /// when the requested image is not available. + static String smUnavailableTexturePath; + + /// File path to the warning texture + static String smWarningTexturePath; + GFXTextureObject *mListHead; GFXTextureObject *mListTail; diff --git a/Engine/source/gui/buttons/guiBitmapButtonCtrl.cpp b/Engine/source/gui/buttons/guiBitmapButtonCtrl.cpp index 8c0f452aa7..ce95475f2e 100644 --- a/Engine/source/gui/buttons/guiBitmapButtonCtrl.cpp +++ b/Engine/source/gui/buttons/guiBitmapButtonCtrl.cpp @@ -29,6 +29,7 @@ #include "gui/core/guiCanvas.h" #include "gui/core/guiDefaultControlRender.h" #include "gfx/gfxDrawUtil.h" +#include "gfx/gfxTextureManager.h" ImplementEnumType( GuiBitmapMode, @@ -327,7 +328,7 @@ void GuiBitmapButtonCtrl::setBitmap( const String& name ) if( i == 0 && mTextures[ i ].mTextureNormal.isNull() && mTextures[ i ].mTextureHilight.isNull() && mTextures[ i ].mTextureDepressed.isNull() && mTextures[ i ].mTextureInactive.isNull() ) { Con::warnf( "GuiBitmapButtonCtrl::setBitmap - Unable to load texture: %s", mBitmapName.c_str() ); - this->setBitmap( "core/art/unavailable" ); + this->setBitmap( GFXTextureManager::getUnavailableTexturePath() ); return; } } @@ -372,7 +373,7 @@ void GuiBitmapButtonCtrl::setBitmapHandles(GFXTexHandle normal, GFXTexHandle hig if (mTextures[ i ].mTextureNormal.isNull() && mTextures[ i ].mTextureHilight.isNull() && mTextures[ i ].mTextureDepressed.isNull() && mTextures[ i ].mTextureInactive.isNull()) { Con::warnf("GuiBitmapButtonCtrl::setBitmapHandles() - Invalid texture handles"); - setBitmap("core/art/unavailable"); + setBitmap( GFXTextureManager::getUnavailableTexturePath() ); return; } diff --git a/Engine/source/gui/containers/guiScrollCtrl.cpp b/Engine/source/gui/containers/guiScrollCtrl.cpp index c1c7a93059..c32e9e2a67 100644 --- a/Engine/source/gui/containers/guiScrollCtrl.cpp +++ b/Engine/source/gui/containers/guiScrollCtrl.cpp @@ -26,7 +26,6 @@ #include "console/engineAPI.h" #include "console/console.h" #include "gfx/bitmap/gBitmap.h" -#include "platform/event.h" #include "gui/core/guiDefaultControlRender.h" #include "gfx/gfxDevice.h" #include "gfx/gfxDrawUtil.h" diff --git a/Engine/source/gui/controls/guiMLTextEditCtrl.cpp b/Engine/source/gui/controls/guiMLTextEditCtrl.cpp index 34e17f9f5d..771ae24ad1 100644 --- a/Engine/source/gui/controls/guiMLTextEditCtrl.cpp +++ b/Engine/source/gui/controls/guiMLTextEditCtrl.cpp @@ -24,7 +24,6 @@ #include "gui/containers/guiScrollCtrl.h" #include "gui/core/guiCanvas.h" #include "console/consoleTypes.h" -#include "platform/event.h" #include "core/frameAllocator.h" #include "core/stringBuffer.h" #include "gfx/gfxDrawUtil.h" diff --git a/Engine/source/gui/controls/guiSliderCtrl.cpp b/Engine/source/gui/controls/guiSliderCtrl.cpp index 47362dc9b9..ae62fd9499 100644 --- a/Engine/source/gui/controls/guiSliderCtrl.cpp +++ b/Engine/source/gui/controls/guiSliderCtrl.cpp @@ -26,7 +26,6 @@ #include "gfx/gfxTextureManager.h" #include "gui/controls/guiSliderCtrl.h" #include "gui/core/guiDefaultControlRender.h" -#include "platform/event.h" #include "gfx/primBuilder.h" #include "gfx/gfxDrawUtil.h" #include "sfx/sfxSystem.h" diff --git a/Engine/source/gui/controls/guiTreeViewCtrl.cpp b/Engine/source/gui/controls/guiTreeViewCtrl.cpp index 5e71b71886..7f7035b70e 100644 --- a/Engine/source/gui/controls/guiTreeViewCtrl.cpp +++ b/Engine/source/gui/controls/guiTreeViewCtrl.cpp @@ -30,7 +30,6 @@ #include "console/consoleTypes.h" #include "console/console.h" #include "gui/core/guiTypes.h" -#include "platform/event.h" #include "gfx/gfxDrawUtil.h" #include "gui/controls/guiTextEditCtrl.h" #ifdef TORQUE_TOOLS diff --git a/Engine/source/gui/core/guiArrayCtrl.cpp b/Engine/source/gui/core/guiArrayCtrl.cpp index 67a509e352..bdb002ef71 100644 --- a/Engine/source/gui/core/guiArrayCtrl.cpp +++ b/Engine/source/gui/core/guiArrayCtrl.cpp @@ -25,7 +25,6 @@ #include "console/console.h" #include "console/engineAPI.h" -#include "platform/event.h" #include "gui/containers/guiScrollCtrl.h" #include "gfx/gfxDrawUtil.h" #include "gui/core/guiDefaultControlRender.h" @@ -284,7 +283,8 @@ void GuiArrayCtrl::onRender(Point2I offset, const RectI &updateRect) //now render the header onRenderColumnHeaders(offset, parentOffset, mHeaderDim); - clipRect.point.y = headerClip.point.y + headerClip.extent.y - 1; + clipRect.point.y += headerClip.extent.y; + clipRect.extent.y -= headerClip.extent.y; } offset.y += mHeaderDim.y; } diff --git a/Engine/source/gui/core/guiCanvas.cpp b/Engine/source/gui/core/guiCanvas.cpp index 00a669646e..2d29f1a782 100644 --- a/Engine/source/gui/core/guiCanvas.cpp +++ b/Engine/source/gui/core/guiCanvas.cpp @@ -26,7 +26,6 @@ #include "console/console.h" #include "console/engineAPI.h" #include "platform/profiler.h" -#include "platform/event.h" #include "gfx/gfxDevice.h" #include "gfx/gfxDrawUtil.h" #include "gui/core/guiTypes.h" diff --git a/Engine/source/gui/core/guiCanvas.h b/Engine/source/gui/core/guiCanvas.h index b0d7c2fbdb..04af6d6929 100644 --- a/Engine/source/gui/core/guiCanvas.h +++ b/Engine/source/gui/core/guiCanvas.h @@ -26,9 +26,6 @@ #ifndef _SIMBASE_H_ #include "console/simBase.h" #endif -#ifndef _EVENT_H_ -#include "platform/event.h" -#endif #ifndef _GUICONTROL_H_ #include "gui/core/guiControl.h" #endif diff --git a/Engine/source/gui/core/guiControl.cpp b/Engine/source/gui/core/guiControl.cpp index 2f5f41d993..1485f81d8d 100644 --- a/Engine/source/gui/core/guiControl.cpp +++ b/Engine/source/gui/core/guiControl.cpp @@ -28,7 +28,6 @@ #include "console/consoleInternal.h" #include "console/engineAPI.h" #include "console/codeBlock.h" -#include "platform/event.h" #include "gfx/bitmap/gBitmap.h" #include "sim/actionMap.h" #include "gui/core/guiCanvas.h" diff --git a/Engine/source/gui/core/guiControl.h b/Engine/source/gui/core/guiControl.h index 0e798935fe..51057fd216 100644 --- a/Engine/source/gui/core/guiControl.h +++ b/Engine/source/gui/core/guiControl.h @@ -38,9 +38,6 @@ #ifndef _GUITYPES_H_ #include "gui/core/guiTypes.h" #endif -#ifndef _EVENT_H_ -#include "platform/event.h" -#endif #ifndef _UTIL_DELEGATE_H_ #include "core/util/delegate.h" #endif diff --git a/Engine/source/gui/core/guiTypes.h b/Engine/source/gui/core/guiTypes.h index acb1e743d9..e38a5fbed4 100644 --- a/Engine/source/gui/core/guiTypes.h +++ b/Engine/source/gui/core/guiTypes.h @@ -38,7 +38,7 @@ #include "gfx/gfxDevice.h" -#include "platform/event.h" +#include "platform/input/event.h" class GBitmap; class SFXTrack; diff --git a/Engine/source/gui/utility/guiInputCtrl.h b/Engine/source/gui/utility/guiInputCtrl.h index 77d5d3e6cd..e5769740c6 100644 --- a/Engine/source/gui/utility/guiInputCtrl.h +++ b/Engine/source/gui/utility/guiInputCtrl.h @@ -26,9 +26,6 @@ #ifndef _GUIMOUSEEVENTCTRL_H_ #include "gui/utility/guiMouseEventCtrl.h" #endif -#ifndef _EVENT_H_ - #include "platform/event.h" -#endif /// A control that locks the mouse and reports all keyboard input events diff --git a/Engine/source/gui/utility/guiMouseEventCtrl.h b/Engine/source/gui/utility/guiMouseEventCtrl.h index 3162113b46..0a8bf72577 100644 --- a/Engine/source/gui/utility/guiMouseEventCtrl.h +++ b/Engine/source/gui/utility/guiMouseEventCtrl.h @@ -26,9 +26,6 @@ #ifndef _GUICONTROL_H_ #include "gui/core/guiControl.h" #endif -#ifndef _EVENT_H_ -#include "platform/event.h" -#endif class GuiMouseEventCtrl : public GuiControl diff --git a/Engine/source/gui/worldEditor/guiConvexShapeEditorCtrl.cpp b/Engine/source/gui/worldEditor/guiConvexShapeEditorCtrl.cpp index f0d41f4231..00245376e5 100644 --- a/Engine/source/gui/worldEditor/guiConvexShapeEditorCtrl.cpp +++ b/Engine/source/gui/worldEditor/guiConvexShapeEditorCtrl.cpp @@ -871,10 +871,17 @@ void GuiConvexEditorCtrl::renderScene(const RectI & updateRect) text = "Scale face."; } } + + // Issue a warning in the status bar + // if this convex has an excessive number of surfaces... + if ( mConvexSEL && mConvexSEL->getSurfaces().size() > ConvexShape::smMaxSurfaces ) + { + text = "WARNING: Reduce the number of surfaces on the selected ConvexShape, only the first 100 will be saved!"; + } Con::executef( statusbar, "setInfo", text.c_str() ); - Con::executef( statusbar, "setSelectionObjectsByCount", Con::getIntArg( mConvexSEL == NULL ? 0 : 1 ) ); + Con::executef( statusbar, "setSelectionObjectsByCount", Con::getIntArg( mConvexSEL == NULL ? 0 : 1 ) ); } if ( mActiveTool ) diff --git a/Engine/source/lighting/advanced/advancedLightBinManager.cpp b/Engine/source/lighting/advanced/advancedLightBinManager.cpp index 1aeef56ffb..775c31cc77 100644 --- a/Engine/source/lighting/advanced/advancedLightBinManager.cpp +++ b/Engine/source/lighting/advanced/advancedLightBinManager.cpp @@ -483,7 +483,7 @@ void AdvancedLightBinManager::_setupPerFrameParameters( const SceneRenderState * // Parameters calculated, assign them to the materials LightMatTable::Iterator iter = mLightMaterials.begin(); - for ( ; iter != mLightMaterials.end(); iter++ ) + for ( ; iter != mLightMaterials.end(); ++iter ) { if ( iter->value ) iter->value->setViewParameters( frustum.getNearDist(), diff --git a/Engine/source/materials/processedCustomMaterial.cpp b/Engine/source/materials/processedCustomMaterial.cpp index 3d57e05925..513ead3148 100644 --- a/Engine/source/materials/processedCustomMaterial.cpp +++ b/Engine/source/materials/processedCustomMaterial.cpp @@ -39,6 +39,7 @@ #include "console/simFieldDictionary.h" #include "console/propertyParsing.h" #include "gfx/util/screenspace.h" +#include "scene/reflectionManager.h" ProcessedCustomMaterial::ProcessedCustomMaterial(Material &mat) @@ -347,6 +348,13 @@ void ProcessedCustomMaterial::setTextureStages( SceneRenderState *state, const S case Material::BackBuff: { GFX->setTexture( samplerRegister, sgData.backBuffTex ); + //if ( sgData.reflectTex ) + // GFX->setTexture( samplerRegister, sgData.reflectTex ); + //else + //{ + // GFXTextureObject *refractTex = REFLECTMGR->getRefractTex( true ); + // GFX->setTexture( samplerRegister, refractTex ); + //} break; } case Material::ReflectBuff: diff --git a/Engine/source/materials/processedMaterial.cpp b/Engine/source/materials/processedMaterial.cpp index 3e5d0df402..d7d64ebdeb 100644 --- a/Engine/source/materials/processedMaterial.cpp +++ b/Engine/source/materials/processedMaterial.cpp @@ -30,9 +30,9 @@ #include "materials/materialManager.h" #include "scene/sceneRenderState.h" #include "gfx/gfxPrimitiveBuffer.h" +#include "gfx/gfxTextureManager.h" #include "gfx/sim/cubemapData.h" - RenderPassData::RenderPassData() { reset(); @@ -394,7 +394,7 @@ void ProcessedMaterial::_setStageData() // Load a debug texture to make it clear to the user // that the texture for this stage was missing. - mStages[i].setTex( MFT_DiffuseMap, _createTexture( "core/art/missingTexture", &GFXDefaultStaticDiffuseProfile ) ); + mStages[i].setTex( MFT_DiffuseMap, _createTexture( GFXTextureManager::getMissingTexturePath(), &GFXDefaultStaticDiffuseProfile ) ); } } diff --git a/Engine/source/math/mOrientedBox.cpp b/Engine/source/math/mOrientedBox.cpp index 47037a7cd3..1aa9c178cd 100644 --- a/Engine/source/math/mOrientedBox.cpp +++ b/Engine/source/math/mOrientedBox.cpp @@ -52,7 +52,7 @@ void OrientedBox3F::set( const MatrixF& transform, const Point3F& extents ) mAxes[ ForwardVector ] = transform.getForwardVector(); mAxes[ UpVector ] = transform.getUpVector(); - mHalfExtents = extents; + mHalfExtents = extents * 0.5f; _initPoints(); } diff --git a/Engine/source/math/mathTypes.cpp b/Engine/source/math/mathTypes.cpp index d92f293e1a..cbe1234524 100644 --- a/Engine/source/math/mathTypes.cpp +++ b/Engine/source/math/mathTypes.cpp @@ -55,6 +55,15 @@ IMPLEMENT_STRUCT( Point2F, FIELD( x, x, 1, "X coordinate." ) FIELD( y, y, 1, "Y coordinate." ) +END_IMPLEMENT_STRUCT; +IMPLEMENT_STRUCT( Point3I, + Point3I, MathTypes, + "" ) + + FIELD( x, x, 1, "X coordinate." ) + FIELD( y, y, 1, "Y coordinate." ) + FIELD( z, z, 1, "Z coordinate." ) + END_IMPLEMENT_STRUCT; IMPLEMENT_STRUCT( Point3F, Point3F, MathTypes, @@ -153,6 +162,30 @@ ConsoleSetType( TypePoint2F ) Con::printf("Point2F must be set as { x, y } or \"x y\""); } +//----------------------------------------------------------------------------- +// TypePoint3I +//----------------------------------------------------------------------------- +ConsoleType( Point3I, TypePoint3I, Point3I ) +ImplementConsoleTypeCasters(TypePoint3I, Point3I) + +ConsoleGetType( TypePoint3I ) +{ + Point3I *pt = (Point3I *) dptr; + char* returnBuffer = Con::getReturnBuffer(256); + dSprintf(returnBuffer, 256, "%d %d %d", pt->x, pt->y, pt->z); + return returnBuffer; +} + +ConsoleSetType( TypePoint3I ) +{ + if(argc == 1) + dSscanf(argv[0], "%d %d %d", &((Point3I *) dptr)->x, &((Point3I *) dptr)->y, &((Point3I *) dptr)->z); + else if(argc == 3) + *((Point3I *) dptr) = Point3I(dAtoi(argv[0]), dAtoi(argv[1]), dAtoi(argv[2])); + else + Con::printf("Point3I must be set as { x, y, z } or \"x y z\""); +} + //----------------------------------------------------------------------------- // TypePoint3F //----------------------------------------------------------------------------- diff --git a/Engine/source/math/mathTypes.h b/Engine/source/math/mathTypes.h index c6ff83d7bc..b17329cf86 100644 --- a/Engine/source/math/mathTypes.h +++ b/Engine/source/math/mathTypes.h @@ -33,6 +33,7 @@ void RegisterMathFunctions(void); class Point2I; class Point2F; +class Point3I; class Point3F; class Point4F; class RectI; @@ -49,6 +50,7 @@ DECLARE_SCOPE( MathTypes ); DECLARE_STRUCT( Point2I ); DECLARE_STRUCT( Point2F ); +DECLARE_STRUCT( Point3I ); DECLARE_STRUCT( Point3F ); DECLARE_STRUCT( Point4F ); DECLARE_STRUCT( RectI ); @@ -63,6 +65,7 @@ DECLARE_STRUCT( EaseF ); // Legacy console types. DefineConsoleType( TypePoint2I, Point2I ) DefineConsoleType( TypePoint2F, Point2F ) +DefineConsoleType( TypePoint3I, Point3I ) DefineConsoleType( TypePoint3F, Point3F ) DefineConsoleType( TypePoint4F, Point4F ) DefineConsoleType( TypeRectI, RectI ) diff --git a/Engine/source/math/mathUtils.cpp b/Engine/source/math/mathUtils.cpp index 2540191fb4..87ce194be3 100644 --- a/Engine/source/math/mathUtils.cpp +++ b/Engine/source/math/mathUtils.cpp @@ -109,7 +109,7 @@ F32 segmentSegmentNearest(const Point3F & p1, const Point3F & q1, const Point3F //----------------------------------------------------------------------------- -bool capsuleSphereNearestOverlap(const Point3F & A0, const Point3F A1, F32 radA, const Point3F & B, F32 radB, F32 & t) +bool capsuleSphereNearestOverlap(const Point3F & A0, const Point3F & A1, F32 radA, const Point3F & B, F32 radB, F32 & t) { Point3F V = A1-A0; Point3F A0B = A0-B; @@ -362,7 +362,7 @@ void getVectorFromAngles( VectorF &vec, F32 yawAng, F32 pitchAng ) //----------------------------------------------------------------------------- -void transformBoundingBox(const Box3F &sbox, const MatrixF &mat, const Point3F scale, Box3F &dbox) +void transformBoundingBox(const Box3F &sbox, const MatrixF &mat, const Point3F &scale, Box3F &dbox) { Point3F center; diff --git a/Engine/source/math/mathUtils.h b/Engine/source/math/mathUtils.h index 2d708aaa23..0749e3055e 100644 --- a/Engine/source/math/mathUtils.h +++ b/Engine/source/math/mathUtils.h @@ -163,14 +163,14 @@ namespace MathUtils /// Return capsule-sphere overlap. Returns time of first overlap, where time /// is viewed as a sphere of radius radA moving from point A0 to A1. - bool capsuleSphereNearestOverlap(const Point3F & A0, const Point3F A1, F32 radA, const Point3F & B, F32 radB, F32 & t); + bool capsuleSphereNearestOverlap(const Point3F & A0, const Point3F & A1, F32 radA, const Point3F & B, F32 radB, F32 & t); /// Intersect two line segments (p1,q1) and (p2,q2), returning points on lines (c1 & c2) and line parameters (s,t). /// Based on routine from "Real Time Collision Detection" by Christer Ericson pp 149. F32 segmentSegmentNearest(const Point3F & p1, const Point3F & q1, const Point3F & p2, const Point3F & q2, F32 & s, F32 & t, Point3F & c1, Point3F & c2); /// Transform bounding box making sure to keep original box entirely contained. - void transformBoundingBox(const Box3F &sbox, const MatrixF &mat, const Point3F scale, Box3F &dbox); + void transformBoundingBox(const Box3F &sbox, const MatrixF &mat, const Point3F &scale, Box3F &dbox); bool mProjectWorldToScreen( const Point3F &in, Point3F *out, @@ -283,16 +283,16 @@ namespace MathUtils const Point3F &b, const Point3F &p ); - /// Sort the passed verts ( Point3F ) in a clockwise or counter-clockwise winding order. - /// Verts must be co-planar and non-collinear. - /// - /// @param quadMat Transform matrix from vert space to quad space. - /// @param clockwise Sort clockwise or counter-clockwise - /// @param verts Array of Point3F verts. - /// @param vertMap Output - Array of vert element ids sorted by winding order. - /// @param count Element count of the verts and vertMap arrays which must be allocated prior to this call. - /// - void sortQuadWindingOrder( const MatrixF &quadMat, bool clockwise, const Point3F *verts, U32 *vertMap, U32 count ); + /// Sort the passed verts ( Point3F ) in a clockwise or counter-clockwise winding order. + /// Verts must be co-planar and non-collinear. + /// + /// @param quadMat Transform matrix from vert space to quad space. + /// @param clockwise Sort clockwise or counter-clockwise + /// @param verts Array of Point3F verts. + /// @param vertMap Output - Array of vert element ids sorted by winding order. + /// @param count Element count of the verts and vertMap arrays which must be allocated prior to this call. + /// + void sortQuadWindingOrder( const MatrixF &quadMat, bool clockwise, const Point3F *verts, U32 *vertMap, U32 count ); /// Same as above except we assume that the passed verts ( Point3F ) are already /// transformed into 'quad space'. If this was done correctly and the points diff --git a/Engine/source/platform/input/IInputDevice.h b/Engine/source/platform/input/IInputDevice.h new file mode 100644 index 0000000000..bef65ae994 --- /dev/null +++ b/Engine/source/platform/input/IInputDevice.h @@ -0,0 +1,59 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef _IINPUTDEVICE_H_ +#define _IINPUTDEVICE_H_ + +#include "console/consoleTypes.h" + +class IInputDevice +{ +protected: + /// Device name + char mName[30]; + + /// Device type + U32 mDeviceType; + + /// Is the device enabled + bool mEnabled; + +public: + inline const char* getDeviceName() const + { + return mName; + } + + inline U32 getDeviceType() const + { + return mDeviceType; + } + + inline bool isEnabled() + { + return mEnabled; + } + + virtual bool process() = 0; +}; + +#endif diff --git a/Engine/source/platform/input/event.cpp b/Engine/source/platform/input/event.cpp new file mode 100644 index 0000000000..254aca29d2 --- /dev/null +++ b/Engine/source/platform/input/event.cpp @@ -0,0 +1,548 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "platform/input/event.h" +#include "core/module.h" +#include "core/util/journal/process.h" +#include "core/strings/stringFunctions.h" +#include "core/stringTable.h" +#include "platform/platformInput.h" +#include "math/mQuat.h" + +MODULE_BEGIN( InputEventManager ) + + MODULE_INIT_BEFORE( SIM ) + MODULE_SHUTDOWN_AFTER( SIM ) + + MODULE_INIT + { + ManagedSingleton< InputEventManager >::createSingleton(); + } + + MODULE_SHUTDOWN + { + ManagedSingleton< InputEventManager >::deleteSingleton(); + } + +MODULE_END; + +InputEventManager::InputEventManager() +{ + mNextDeviceTypeCode = INPUT_DEVICE_PLUGIN_DEVICES_START; + mNextDeviceCode = INPUT_DEVICE_PLUGIN_CODES_START; + + buildVirtualMap(); +} + +InputEventManager::~InputEventManager() +{ +} + +U32 InputEventManager::getNextDeviceType() +{ + U32 code = mNextDeviceTypeCode; + ++mNextDeviceTypeCode; + return code; +} + +U32 InputEventManager::getNextDeviceCode() +{ + U32 code = mNextDeviceCode; + ++mNextDeviceCode; + return code; +} + +void InputEventManager::registerDevice(IInputDevice* device) +{ + // Make sure the device is not already registered + for(U32 i=0; i::iterator itr = mDeviceList.begin(); itr != mDeviceList.end(); ++itr) + { + if((*itr)->isEnabled()) + { + const char* deviceName = (*itr)->getDeviceName(); + if(dStrnicmp(name, deviceName, dStrlen(deviceName)) == 0) + { + return true; + } + } + } + + return false; +} + +bool InputEventManager::isRegisteredDevice(U32 type) +{ + for(Vector::iterator itr = mDeviceList.begin(); itr != mDeviceList.end(); ++itr) + { + if((*itr)->isEnabled()) + { + U32 deviceType = (*itr)->getDeviceType(); + if(deviceType == type) + { + return true; + } + } + } + + return false; +} + +bool InputEventManager::isRegisteredDeviceWithAttributes(const char* name, U32& deviceType, U32&nameLen) +{ + for(Vector::iterator itr = mDeviceList.begin(); itr != mDeviceList.end(); ++itr) + { + if((*itr)->isEnabled()) + { + const char* deviceName = (*itr)->getDeviceName(); + S32 length = dStrlen(deviceName); + if(dStrnicmp(name, deviceName, length) == 0) + { + deviceType = (*itr)->getDeviceType(); + nameLen = length; + return true; + } + } + } + + return false; +} + +const char* InputEventManager::getRegisteredDeviceName(U32 type) +{ + for(Vector::iterator itr = mDeviceList.begin(); itr != mDeviceList.end(); ++itr) + { + if((*itr)->isEnabled()) + { + U32 deviceType = (*itr)->getDeviceType(); + if(deviceType == type) + { + return (*itr)->getDeviceName(); + } + } + } + + return NULL; +} + +void InputEventManager::start() +{ + Process::notify(this, &InputEventManager::process, PROCESS_INPUT_ORDER); +} + +void InputEventManager::stop() +{ + Process::remove(this, &InputEventManager::process); +} + +void InputEventManager::process() +{ + // Process each device + for(Vector::iterator itr = mDeviceList.begin(); itr != mDeviceList.end(); ++itr) + { + if((*itr)->isEnabled()) + { + (*itr)->process(); + } + } +} + +// Used for the old virtual map table that was originally in actionMap.cpp +struct CodeMapping +{ + const char* pDescription; + InputEventType type; + InputObjectInstances code; +}; + +CodeMapping gVirtualMap[] = +{ + //-------------------------------------- KEYBOARD EVENTS + // + { "backspace", SI_KEY, KEY_BACKSPACE }, + { "tab", SI_KEY, KEY_TAB }, + + { "return", SI_KEY, KEY_RETURN }, + { "enter", SI_KEY, KEY_RETURN }, + + { "shift", SI_KEY, KEY_SHIFT }, + { "ctrl", SI_KEY, KEY_CONTROL }, + { "alt", SI_KEY, KEY_ALT }, + { "pause", SI_KEY, KEY_PAUSE }, + { "capslock", SI_KEY, KEY_CAPSLOCK }, + + { "escape", SI_KEY, KEY_ESCAPE }, + + { "space", SI_KEY, KEY_SPACE }, + { "pagedown", SI_KEY, KEY_PAGE_DOWN }, + { "pageup", SI_KEY, KEY_PAGE_UP }, + { "end", SI_KEY, KEY_END }, + { "home", SI_KEY, KEY_HOME }, + { "left", SI_KEY, KEY_LEFT }, + { "up", SI_KEY, KEY_UP }, + { "right", SI_KEY, KEY_RIGHT }, + { "down", SI_KEY, KEY_DOWN }, + { "print", SI_KEY, KEY_PRINT }, + { "insert", SI_KEY, KEY_INSERT }, + { "delete", SI_KEY, KEY_DELETE }, + { "help", SI_KEY, KEY_HELP }, + + { "win_lwindow", SI_KEY, KEY_WIN_LWINDOW }, + { "win_rwindow", SI_KEY, KEY_WIN_RWINDOW }, + { "win_apps", SI_KEY, KEY_WIN_APPS }, + + { "cmd", SI_KEY, KEY_ALT }, + { "opt", SI_KEY, KEY_MAC_OPT }, + { "lopt", SI_KEY, KEY_MAC_LOPT }, + { "ropt", SI_KEY, KEY_MAC_ROPT }, + + { "numpad0", SI_KEY, KEY_NUMPAD0 }, + { "numpad1", SI_KEY, KEY_NUMPAD1 }, + { "numpad2", SI_KEY, KEY_NUMPAD2 }, + { "numpad3", SI_KEY, KEY_NUMPAD3 }, + { "numpad4", SI_KEY, KEY_NUMPAD4 }, + { "numpad5", SI_KEY, KEY_NUMPAD5 }, + { "numpad6", SI_KEY, KEY_NUMPAD6 }, + { "numpad7", SI_KEY, KEY_NUMPAD7 }, + { "numpad8", SI_KEY, KEY_NUMPAD8 }, + { "numpad9", SI_KEY, KEY_NUMPAD9 }, + { "numpadmult", SI_KEY, KEY_MULTIPLY }, + { "numpadadd", SI_KEY, KEY_ADD }, + { "numpadsep", SI_KEY, KEY_SEPARATOR }, + { "numpadminus", SI_KEY, KEY_SUBTRACT }, + { "numpaddecimal", SI_KEY, KEY_DECIMAL }, + { "numpaddivide", SI_KEY, KEY_DIVIDE }, + { "numpadenter", SI_KEY, KEY_NUMPADENTER }, + + { "f1", SI_KEY, KEY_F1 }, + { "f2", SI_KEY, KEY_F2 }, + { "f3", SI_KEY, KEY_F3 }, + { "f4", SI_KEY, KEY_F4 }, + { "f5", SI_KEY, KEY_F5 }, + { "f6", SI_KEY, KEY_F6 }, + { "f7", SI_KEY, KEY_F7 }, + { "f8", SI_KEY, KEY_F8 }, + { "f9", SI_KEY, KEY_F9 }, + { "f10", SI_KEY, KEY_F10 }, + { "f11", SI_KEY, KEY_F11 }, + { "f12", SI_KEY, KEY_F12 }, + { "f13", SI_KEY, KEY_F13 }, + { "f14", SI_KEY, KEY_F14 }, + { "f15", SI_KEY, KEY_F15 }, + { "f16", SI_KEY, KEY_F16 }, + { "f17", SI_KEY, KEY_F17 }, + { "f18", SI_KEY, KEY_F18 }, + { "f19", SI_KEY, KEY_F19 }, + { "f20", SI_KEY, KEY_F20 }, + { "f21", SI_KEY, KEY_F21 }, + { "f22", SI_KEY, KEY_F22 }, + { "f23", SI_KEY, KEY_F23 }, + { "f24", SI_KEY, KEY_F24 }, + + { "numlock", SI_KEY, KEY_NUMLOCK }, + { "scrolllock", SI_KEY, KEY_SCROLLLOCK }, + + { "lshift", SI_KEY, KEY_LSHIFT }, + { "rshift", SI_KEY, KEY_RSHIFT }, + { "lcontrol", SI_KEY, KEY_LCONTROL }, + { "rcontrol", SI_KEY, KEY_RCONTROL }, + { "lalt", SI_KEY, KEY_LALT }, + { "ralt", SI_KEY, KEY_RALT }, + { "tilde", SI_KEY, KEY_TILDE }, + + { "minus", SI_KEY, KEY_MINUS }, + { "equals", SI_KEY, KEY_EQUALS }, + { "lbracket", SI_KEY, KEY_LBRACKET }, + { "rbracket", SI_KEY, KEY_RBRACKET }, + { "backslash", SI_KEY, KEY_BACKSLASH }, + { "semicolon", SI_KEY, KEY_SEMICOLON }, + { "apostrophe", SI_KEY, KEY_APOSTROPHE }, + { "comma", SI_KEY, KEY_COMMA }, + { "period", SI_KEY, KEY_PERIOD }, + { "slash", SI_KEY, KEY_SLASH }, + { "lessthan", SI_KEY, KEY_OEM_102 }, + + //-------------------------------------- BUTTON EVENTS + // Joystick/Mouse buttons + { "button0", SI_BUTTON, KEY_BUTTON0 }, + { "button1", SI_BUTTON, KEY_BUTTON1 }, + { "button2", SI_BUTTON, KEY_BUTTON2 }, + { "button3", SI_BUTTON, KEY_BUTTON3 }, + { "button4", SI_BUTTON, KEY_BUTTON4 }, + { "button5", SI_BUTTON, KEY_BUTTON5 }, + { "button6", SI_BUTTON, KEY_BUTTON6 }, + { "button7", SI_BUTTON, KEY_BUTTON7 }, + { "button8", SI_BUTTON, KEY_BUTTON8 }, + { "button9", SI_BUTTON, KEY_BUTTON9 }, + { "button10", SI_BUTTON, KEY_BUTTON10 }, + { "button11", SI_BUTTON, KEY_BUTTON11 }, + { "button12", SI_BUTTON, KEY_BUTTON12 }, + { "button13", SI_BUTTON, KEY_BUTTON13 }, + { "button14", SI_BUTTON, KEY_BUTTON14 }, + { "button15", SI_BUTTON, KEY_BUTTON15 }, + { "button16", SI_BUTTON, KEY_BUTTON16 }, + { "button17", SI_BUTTON, KEY_BUTTON17 }, + { "button18", SI_BUTTON, KEY_BUTTON18 }, + { "button19", SI_BUTTON, KEY_BUTTON19 }, + { "button20", SI_BUTTON, KEY_BUTTON20 }, + { "button21", SI_BUTTON, KEY_BUTTON21 }, + { "button22", SI_BUTTON, KEY_BUTTON22 }, + { "button23", SI_BUTTON, KEY_BUTTON23 }, + { "button24", SI_BUTTON, KEY_BUTTON24 }, + { "button25", SI_BUTTON, KEY_BUTTON25 }, + { "button26", SI_BUTTON, KEY_BUTTON26 }, + { "button27", SI_BUTTON, KEY_BUTTON27 }, + { "button28", SI_BUTTON, KEY_BUTTON28 }, + { "button29", SI_BUTTON, KEY_BUTTON29 }, + { "button30", SI_BUTTON, KEY_BUTTON30 }, + { "button31", SI_BUTTON, KEY_BUTTON31 }, + { "button32", SI_BUTTON, KEY_BUTTON32 }, + { "button33", SI_BUTTON, KEY_BUTTON33 }, + { "button34", SI_BUTTON, KEY_BUTTON34 }, + { "button35", SI_BUTTON, KEY_BUTTON35 }, + { "button36", SI_BUTTON, KEY_BUTTON36 }, + { "button37", SI_BUTTON, KEY_BUTTON37 }, + { "button38", SI_BUTTON, KEY_BUTTON38 }, + { "button39", SI_BUTTON, KEY_BUTTON39 }, + { "button40", SI_BUTTON, KEY_BUTTON40 }, + { "button41", SI_BUTTON, KEY_BUTTON41 }, + { "button42", SI_BUTTON, KEY_BUTTON42 }, + { "button43", SI_BUTTON, KEY_BUTTON43 }, + { "button44", SI_BUTTON, KEY_BUTTON44 }, + { "button45", SI_BUTTON, KEY_BUTTON45 }, + { "button46", SI_BUTTON, KEY_BUTTON46 }, + { "button47", SI_BUTTON, KEY_BUTTON47 }, + + //-------------------------------------- MOVE EVENTS + // Mouse/Joystick axes: + { "xaxis", SI_AXIS, SI_XAXIS }, + { "yaxis", SI_AXIS, SI_YAXIS }, + { "zaxis", SI_AXIS, SI_ZAXIS }, + { "rxaxis", SI_AXIS, SI_RXAXIS }, + { "ryaxis", SI_AXIS, SI_RYAXIS }, + { "rzaxis", SI_AXIS, SI_RZAXIS }, + { "slider", SI_AXIS, SI_SLIDER }, + + //-------------------------------------- POV EVENTS + // Joystick POV: + { "xpov", SI_POV, SI_XPOV }, + { "ypov", SI_POV, SI_YPOV }, + { "upov", SI_POV, SI_UPOV }, + { "dpov", SI_POV, SI_DPOV }, + { "lpov", SI_POV, SI_LPOV }, + { "rpov", SI_POV, SI_RPOV }, + { "xpov2", SI_POV, SI_XPOV2 }, + { "ypov2", SI_POV, SI_YPOV2 }, + { "upov2", SI_POV, SI_UPOV2 }, + { "dpov2", SI_POV, SI_DPOV2 }, + { "lpov2", SI_POV, SI_LPOV2 }, + { "rpov2", SI_POV, SI_RPOV2 }, + +#if defined( TORQUE_OS_WIN32 ) || defined( TORQUE_OS_XENON ) + //-------------------------------------- XINPUT EVENTS + // Controller connect / disconnect: + { "connect", SI_BUTTON, XI_CONNECT }, + + // L & R Thumbsticks: + { "thumblx", SI_AXIS, XI_THUMBLX }, + { "thumbly", SI_AXIS, XI_THUMBLY }, + { "thumbrx", SI_AXIS, XI_THUMBRX }, + { "thumbry", SI_AXIS, XI_THUMBRY }, + + // L & R Triggers: + { "triggerl", SI_AXIS, XI_LEFT_TRIGGER }, + { "triggerr", SI_AXIS, XI_RIGHT_TRIGGER }, + + // DPAD Buttons: + { "dpadu", SI_BUTTON, SI_UPOV }, + { "dpadd", SI_BUTTON, SI_DPOV }, + { "dpadl", SI_BUTTON, SI_LPOV }, + { "dpadr", SI_BUTTON, SI_RPOV }, + + // START & BACK Buttons: + { "btn_start", SI_BUTTON, XI_START }, + { "btn_back", SI_BUTTON, XI_BACK }, + + // L & R Thumbstick Buttons: + { "btn_lt", SI_BUTTON, XI_LEFT_THUMB }, + { "btn_rt", SI_BUTTON, XI_RIGHT_THUMB }, + + // L & R Shoulder Buttons: + { "btn_l", SI_BUTTON, XI_LEFT_SHOULDER }, + { "btn_r", SI_BUTTON, XI_RIGHT_SHOULDER }, + + // Primary buttons: + { "btn_a", SI_BUTTON, XI_A }, + { "btn_b", SI_BUTTON, XI_B }, + { "btn_x", SI_BUTTON, XI_X }, + { "btn_y", SI_BUTTON, XI_Y }, +#endif + + //-------------------------------------- MISCELLANEOUS EVENTS + // + + { "anykey", SI_KEY, KEY_ANYKEY }, + { "nomatch", SI_UNKNOWN, (InputObjectInstances)0xFFFFFFFF } +}; + +void InputEventManager::buildVirtualMap() +{ + char desc[256]; + VirtualMapData* data; + + for (U32 j = 0; gVirtualMap[j].code != 0xFFFFFFFF; j++) + { + // Make sure the description is lower case + desc[0] = 0; + dStrncpy(desc, gVirtualMap[j].pDescription, 255); + dStrlwr(desc); + + data = new VirtualMapData(); + data->type = gVirtualMap[j].type; + data->code = gVirtualMap[j].code; + data->desc = StringTable->insert(desc); + + mVirtualMap.insert(data, desc); + mActionCodeMap.insertUnique(data->code, *data); + } +} + +void InputEventManager::addVirtualMap(const char* description, InputEventType type, InputObjectInstances code) +{ + // Make sure the description is lower case + char desc[256]; + desc[0] = 0; + dStrncpy(desc, description, 255); + dStrlwr(desc); + + VirtualMapData* data = new VirtualMapData(); + data->type = type; + data->code = code; + data->desc = StringTable->insert(desc); + + mVirtualMap.insert(data, desc); + mActionCodeMap.insertUnique(data->code, *data); +} + +InputEventManager::VirtualMapData* InputEventManager::findVirtualMap(const char* description) +{ + char desc[256]; + desc[0] = 0; + dStrncpy(desc, description, 255); + dStrlwr(desc); + + return mVirtualMap.retreive(desc); +} + +const char* InputEventManager::findVirtualMapDescFromCode(U32 code) +{ + HashTable::Iterator itr = mActionCodeMap.find(code); + if(itr != mActionCodeMap.end()) + return itr->value.desc; + + return NULL; +} + +void InputEventManager::buildInputEvent(U32 deviceType, U32 deviceInst, InputEventType objType, InputObjectInstances objInst, InputActionType action, S32 iValue) +{ + InputEventInfo newEvent; + + newEvent.deviceType = deviceType; + newEvent.deviceInst = deviceInst; + newEvent.objType = objType; + newEvent.objInst = objInst; + newEvent.action = action; + newEvent.iValue = iValue; + + newEvent.postToSignal(Input::smInputEvent); +} + +void InputEventManager::buildInputEvent(U32 deviceType, U32 deviceInst, InputEventType objType, InputObjectInstances objInst, InputActionType action, float fValue) +{ + InputEventInfo newEvent; + + newEvent.deviceType = deviceType; + newEvent.deviceInst = deviceInst; + newEvent.objType = objType; + newEvent.objInst = objInst; + newEvent.action = action; + newEvent.fValue = fValue; + + newEvent.postToSignal(Input::smInputEvent); +} + +void InputEventManager::buildInputEvent(U32 deviceType, U32 deviceInst, InputEventType objType, InputObjectInstances objInst, InputActionType action, Point3F& pValue) +{ + InputEventInfo newEvent; + + newEvent.deviceType = deviceType; + newEvent.deviceInst = deviceInst; + newEvent.objType = objType; + newEvent.objInst = objInst; + newEvent.action = action; + newEvent.fValue = pValue.x; + newEvent.fValue2 = pValue.y; + newEvent.fValue3 = pValue.z; + + newEvent.postToSignal(Input::smInputEvent); +} + +void InputEventManager::buildInputEvent(U32 deviceType, U32 deviceInst, InputEventType objType, InputObjectInstances objInst, InputActionType action, QuatF& qValue) +{ + InputEventInfo newEvent; + + newEvent.deviceType = deviceType; + newEvent.deviceInst = deviceInst; + newEvent.objType = objType; + newEvent.objInst = objInst; + newEvent.action = action; + newEvent.fValue = qValue.x; + newEvent.fValue2 = qValue.y; + newEvent.fValue3 = qValue.z; + newEvent.fValue4 = qValue.w; + + newEvent.postToSignal(Input::smInputEvent); +} diff --git a/Engine/source/platform/event.h b/Engine/source/platform/input/event.h similarity index 68% rename from Engine/source/platform/event.h rename to Engine/source/platform/input/event.h index dfe7bc2064..965dc0ac60 100644 --- a/Engine/source/platform/event.h +++ b/Engine/source/platform/input/event.h @@ -30,13 +30,21 @@ #define _EVENT_H_ #include "platform/types.h" +#include "platform/input/IInputDevice.h" #include "core/util/journal/journaledSignal.h" +#include "core/util/tSingleton.h" +#include "core/util/tDictionary.h" +#include "core/tSimpleHashTable.h" + +#define AddInputVirtualMap( description, type, code ) \ + INPUTMGR->addVirtualMap( #description, type, code ); /// @defgroup input_constants Input system constants /// @{ /// Input event constants: -enum InputObjectInstances +typedef U32 InputObjectInstances; +enum InputObjectInstancesEnum { KEY_NULL = 0x000, ///< Invalid KeyCode KEY_BACKSPACE = 0x001, @@ -203,6 +211,22 @@ enum InputObjectInstances KEY_BUTTON29 = 0x011D, KEY_BUTTON30 = 0x011E, KEY_BUTTON31 = 0x011F, + KEY_BUTTON32 = 0x0120, + KEY_BUTTON33 = 0x0121, + KEY_BUTTON34 = 0x0122, + KEY_BUTTON35 = 0x0123, + KEY_BUTTON36 = 0x0124, + KEY_BUTTON37 = 0x0125, + KEY_BUTTON38 = 0x0126, + KEY_BUTTON39 = 0x0127, + KEY_BUTTON40 = 0x0128, + KEY_BUTTON41 = 0x0129, + KEY_BUTTON42 = 0x012A, + KEY_BUTTON43 = 0x012B, + KEY_BUTTON44 = 0x012C, + KEY_BUTTON45 = 0x012D, + KEY_BUTTON46 = 0x012E, + KEY_BUTTON47 = 0x012F, KEY_ANYKEY = 0xfffe, /// Joystick event codes. @@ -250,10 +274,13 @@ enum InputObjectInstances XI_B = 0x318, XI_X = 0x319, XI_Y = 0x320, + + INPUT_DEVICE_PLUGIN_CODES_START = 0x400, }; /// Input device types -enum InputDeviceTypes +typedef U32 InputDeviceTypes; +enum InputDeviceTypesEnum { UnknownDeviceType, MouseDeviceType, @@ -262,7 +289,9 @@ enum InputDeviceTypes GamepadDeviceType, XInputDeviceType, - NUM_INPUT_DEVICE_TYPES + NUM_INPUT_DEVICE_TYPES, + + INPUT_DEVICE_PLUGIN_DEVICES_START = NUM_INPUT_DEVICE_TYPES, }; /// Device Event Action Types @@ -278,17 +307,24 @@ enum InputActionType SI_MOVE = 0x03, /// A key repeat occurred. Happens in between a SI_MAKE and SI_BREAK. - SI_REPEAT = 0x04, + SI_REPEAT = 0x04, + + /// A value of some type. Matched with SI_FLOAT or SI_INT. + SI_VALUE = 0x05, }; ///Device Event Types enum InputEventType { SI_UNKNOWN = 0x01, - SI_BUTTON = 0x02, - SI_POV = 0x03, - SI_AXIS = 0x04, - SI_KEY = 0x0A, + SI_BUTTON = 0x02, // Button press/release + SI_POV = 0x03, // Point of View hat + SI_AXIS = 0x04, // Axis in range -1.0..1.0 + SI_POS = 0x05, // Absolute position value (Point3F) + SI_ROT = 0x06, // Absolute rotation value (QuatF) + SI_INT = 0x07, // Integer value (S32) + SI_FLOAT = 0x08, // Float value (F32) + SI_KEY = 0x0A, // Keyboard key }; /// Wildcard match used by the input system. @@ -356,6 +392,10 @@ struct InputEventInfo { deviceInst = 0; fValue = 0.f; + fValue2 = 0.f; + fValue3 = 0.f; + fValue4 = 0.f; + iValue = 0; deviceType = (InputDeviceTypes)0; objType = (InputEventType)0; ascii = 0; @@ -367,9 +407,18 @@ struct InputEventInfo /// Device instance: joystick0, joystick1, etc U32 deviceInst; - /// Value ranges from -1.0 to 1.0 + /// Value typically ranges from -1.0 to 1.0, but doesn't have to. + /// It depends on the context. F32 fValue; + /// Extended float values (often used for absolute rotation Quat) + F32 fValue2; + F32 fValue3; + F32 fValue4; + + /// Signed integer value + S32 iValue; + /// What was the action? (MAKE/BREAK/MOVE) InputActionType action; InputDeviceTypes deviceType; @@ -384,9 +433,99 @@ struct InputEventInfo inline void postToSignal(InputEvent &ie) { - ie.trigger(deviceInst, fValue, deviceType, objType, ascii, objInst, action, modifier); + ie.trigger(deviceInst, fValue, fValue2, fValue3, fValue4, iValue, deviceType, objType, ascii, objInst, action, modifier); } }; +class Point3F; +class QuatF; + +/// Handles input device plug-ins +class InputEventManager +{ +public: + struct VirtualMapData + { + StringTableEntry desc; + InputEventType type; + InputObjectInstances code; + }; + +public: + InputEventManager(); + virtual ~InputEventManager(); + + /// Get the next device type code + U32 getNextDeviceType(); + + /// Get the next device action code + U32 getNextDeviceCode(); + + void registerDevice(IInputDevice* device); + void unregisterDevice(IInputDevice* device); + + /// Check if the given device name is a registered device. + /// The given name can optionally include an instance number on the end. + bool isRegisteredDevice(const char* name); + + /// Check if the given device type is a registered device. + bool isRegisteredDevice(U32 type); + + /// Same as above but also provides the found device type and actual + // device name length. Used by ActionMap::getDeviceTypeAndInstance() + bool isRegisteredDeviceWithAttributes(const char* name, U32& deviceType, U32&nameLen); + + /// Returns the name of a registered device given its type + const char* getRegisteredDeviceName(U32 type); + + void start(); + void stop(); + + void process(); + + // Add to the virtual map table + void addVirtualMap(const char* description, InputEventType type, InputObjectInstances code); + + // Find a virtual map entry based on the text description + VirtualMapData* findVirtualMap(const char* description); + + // Find a virtual map entry's description based on the action code + const char* findVirtualMapDescFromCode(U32 code); + + /// Build an input event based on a single iValue + void buildInputEvent(U32 deviceType, U32 deviceInst, InputEventType objType, InputObjectInstances objInst, InputActionType action, S32 iValue); + + /// Build an input event based on a single fValue + void buildInputEvent(U32 deviceType, U32 deviceInst, InputEventType objType, InputObjectInstances objInst, InputActionType action, float fValue); + + /// Build an input event based on a Point3F + void buildInputEvent(U32 deviceType, U32 deviceInst, InputEventType objType, InputObjectInstances objInst, InputActionType action, Point3F& pValue); + + /// Build an input event based on a QuatF + void buildInputEvent(U32 deviceType, U32 deviceInst, InputEventType objType, InputObjectInstances objInst, InputActionType action, QuatF& qValue); + +protected: + U32 mNextDeviceTypeCode; + U32 mNextDeviceCode; + + Vector mDeviceList; + + // Holds description to VirtualMapData struct + SimpleHashTable mVirtualMap; + + // Used to look up a description based on a VirtualMapData.code + HashTable mActionCodeMap; + +protected: + void buildVirtualMap(); + +public: + // For ManagedSingleton. + static const char* getSingletonName() { return "InputEventManager"; } +}; + +/// Returns the InputEventManager singleton. +#define INPUTMGR ManagedSingleton::instance() + #endif diff --git a/Engine/source/platform/input/leapMotion/leapMotionConstants.h b/Engine/source/platform/input/leapMotion/leapMotionConstants.h new file mode 100644 index 0000000000..59f6b18e60 --- /dev/null +++ b/Engine/source/platform/input/leapMotion/leapMotionConstants.h @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef _LEAPMOTIONCONSTANTS_H_ +#define _LEAPMOTIONCONSTANTS_H_ + +namespace LeapMotionConstants +{ + enum Constants { + MaxHands = 2, + MaxPointablesPerHand = 5, + }; +} + +#endif // _LEAPMOTIONCONSTANTS_H_ diff --git a/Engine/source/platform/input/leapMotion/leapMotionData.cpp b/Engine/source/platform/input/leapMotion/leapMotionData.cpp new file mode 100644 index 0000000000..83276aa016 --- /dev/null +++ b/Engine/source/platform/input/leapMotion/leapMotionData.cpp @@ -0,0 +1,353 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "platform/input/leapMotion/leapMotionData.h" +#include "platform/input/leapMotion/leapMotionUtil.h" + +LeapMotionDeviceData::LeapMotionDeviceData() +{ + reset(); +} + +void LeapMotionDeviceData::reset() +{ + mDataSet = false; + + mIsValid = false; + + mHasTrackingData = false; + + for(U32 i=0; i 0 || frame.pointables().count() > 0; + + const Leap::HandList hands = frame.hands(); + + // Check if the hand index needs to persist between frames, but only if the + // previous data is valid + if(keepHandIndexPersistent && prevData && prevData->mDataSet && prevData->mIsValid) + { + processPersistentHands(frame.hands(), keepPointableIndexPersistent, prevData); + } + else + { + processHands(frame.hands()); + } + + // Single hand rotation as axis + if(mHandValid[0]) + { + Point2F axis; + LeapMotionUtil::calculateHandAxisRotation(mHandRot[0], maxHandAxisRadius, axis); + + mHandRotAxis[0] = axis.x; + mHandRotAxis[1] = axis.y; + } + else + { + // The first hand is not valid so we reset the axis rotation to none + mHandRotAxis[0] = 0.0f; + mHandRotAxis[1] = 0.0f; + } + + // Store the current sequence number + mSequenceNum = frame.id(); + + mDataSet = true; +} + +void LeapMotionDeviceData::processPersistentHands(const Leap::HandList& hands, bool keepPointableIndexPersistent, LeapMotionDeviceData* prevData) +{ + S32 numHands = hands.count(); + + static S32 handDataIndex[LeapMotionConstants::MaxHands]; + static bool handIndexUsed[LeapMotionConstants::MaxHands]; + static Vector frameHandFound; + + // Clear out our lookup arrays + for(U32 i=0; imHandValid[j] && hand.id() == prevData->mHandID[j]) + { + handDataIndex[j] = i; + frameHandFound[i] = j; + } + } + } + + // Process all hands that were present in the last frame + for(U32 i=0; i framePointableFound; + + // Clear out our lookup arrays + for(U32 i=0; imPointableValid[handIndex][j] && pointable.id() == prevData->mPointableID[handIndex][j]) + { + pointableDataIndex[j] = i; + framePointableFound[i] = j; + } + } + } + + // Process all hand pointables that were present in the last frame + for(U32 i=0; imHandRotAxis[0] || !mDataSet) + { + result |= DIFF_HANDROTAXISX; + } + if(mHandRotAxis[1] != other->mHandRotAxis[1] || !mDataSet) + { + result |= DIFF_HANDROTAXISY; + } + + return result; +} + +U32 LeapMotionDeviceData::compareMeta(LeapMotionDeviceData* other) +{ + S32 result = DIFF_NONE; + + if(mHasTrackingData != other->mHasTrackingData || !mDataSet) + { + result |= METADIFF_FRAME_VALID_DATA; + } + + return result; +} diff --git a/Engine/source/platform/input/leapMotion/leapMotionData.h b/Engine/source/platform/input/leapMotion/leapMotionData.h new file mode 100644 index 0000000000..34e9d6ecf1 --- /dev/null +++ b/Engine/source/platform/input/leapMotion/leapMotionData.h @@ -0,0 +1,113 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef _LEAPMOTIONDATA_H_ +#define _LEAPMOTIONDATA_H_ + +#include "console/consoleTypes.h" +#include "math/mMathFn.h" +#include "math/mMatrix.h" +#include "math/mQuat.h" +#include "platform/input/leapMotion/leapMotionConstants.h" +#include "Leap.h" + +struct LeapMotionDeviceData +{ + enum DataDifferences { + DIFF_NONE = 0, + DIFF_HANDROTAXISX = (1<<1), + DIFF_HANDROTAXISY = (1<<2), + + DIFF_HANDROTAXIS = (DIFF_HANDROTAXISX | DIFF_HANDROTAXISY), + }; + + enum MetaDataDifferences { + METADIFF_NONE = 0, + METADIFF_FRAME_VALID_DATA = (1<<0), + }; + +protected: + void processPersistentHands(const Leap::HandList& hands, bool keepPointableIndexPersistent, LeapMotionDeviceData* prevData); + void processHands(const Leap::HandList& hands); + void processHand(const Leap::Hand& hand, U32 handIndex, bool keepPointableIndexPersistent, LeapMotionDeviceData* prevData); + + void processPersistentHandPointables(const Leap::PointableList& pointables, U32 handIndex, LeapMotionDeviceData* prevData); + void processHandPointables(const Leap::PointableList& pointables, U32 handIndex); + void processHandPointable(const Leap::Pointable& pointable, U32 handIndex, U32 handPointableIndex); + +public: + bool mDataSet; + + // Frame Data Set + bool mIsValid; + bool mHasTrackingData; + + // Hand Data Set + bool mHandValid[LeapMotionConstants::MaxHands]; + S32 mHandID[LeapMotionConstants::MaxHands]; + + // Hand Position + F32 mHandRawPos[LeapMotionConstants::MaxHands][3]; + S32 mHandPos[LeapMotionConstants::MaxHands][3]; + Point3F mHandPosPoint[LeapMotionConstants::MaxHands]; + + // Hand Rotation + MatrixF mHandRot[LeapMotionConstants::MaxHands]; + QuatF mHandRotQuat[LeapMotionConstants::MaxHands]; + + // Hand rotation as axis x, y + F32 mHandRotAxis[2]; + + // Pointable Data Set + bool mPointableValid[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand]; + S32 mPointableID[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand]; + F32 mPointableLength[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand]; + F32 mPointableWidth[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand]; + + // Pointable Position + F32 mPointableRawPos[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand][3]; + S32 mPointablePos[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand][3]; + Point3F mPointablePosPoint[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand]; + + // Pointable Rotation + MatrixF mPointableRot[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand]; + QuatF mPointableRotQuat[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand]; + + // Sequence number from device + U64 mSequenceNum; + + LeapMotionDeviceData(); + + /// Reset device data + void reset(); + + /// Set data based on Leap Motion device data + void setData(const Leap::Frame& frame, LeapMotionDeviceData* prevData, bool keepHandIndexPersistent, bool keepPointableIndexPersistent, const F32& maxHandAxisRadius); + + /// Compare this data and given and return differences + U32 compare(LeapMotionDeviceData* other); + + /// Compare meta data between this and given and return differences + U32 compareMeta(LeapMotionDeviceData* other); +}; + +#endif // _LEAPMOTIONDATA_H_ diff --git a/Engine/source/platform/input/leapMotion/leapMotionDevice.cpp b/Engine/source/platform/input/leapMotion/leapMotionDevice.cpp new file mode 100644 index 0000000000..5e4aef681f --- /dev/null +++ b/Engine/source/platform/input/leapMotion/leapMotionDevice.cpp @@ -0,0 +1,364 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "platform/input/leapMotion/leapMotionDevice.h" +#include "platform/input/leapMotion/leapMotionData.h" +#include "platform/input/leapMotion/leapMotionFrameStore.h" +#include "platform/platformInput.h" +#include "core/module.h" +#include "platform/threads/mutex.h" +#include "console/engineAPI.h" + +MODULE_BEGIN( LeapMotionDevice ) + + MODULE_INIT_AFTER( InputEventManager ) + MODULE_SHUTDOWN_BEFORE( InputEventManager ) + + MODULE_INIT + { + LeapMotionDevice::staticInit(); + ManagedSingleton< LeapMotionDevice >::createSingleton(); + if(LeapMotionDevice::smEnableDevice) + { + LEAPMOTIONDEV->enable(); + } + + // Register the device with the Input Event Manager + INPUTMGR->registerDevice(LEAPMOTIONDEV); + } + + MODULE_SHUTDOWN + { + INPUTMGR->unregisterDevice(LEAPMOTIONDEV); + ManagedSingleton< LeapMotionDevice >::deleteSingleton(); + } + +MODULE_END; + +//----------------------------------------------------------------------------- +// LeapMotionDevice +//----------------------------------------------------------------------------- + +bool LeapMotionDevice::smEnableDevice = true; + +bool LeapMotionDevice::smGenerateIndividualEvents = true; +bool LeapMotionDevice::smKeepHandIndexPersistent = false; +bool LeapMotionDevice::smKeepPointableIndexPersistent = false; + +bool LeapMotionDevice::smGenerateSingleHandRotationAsAxisEvents = false; + +F32 LeapMotionDevice::smMaximumHandAxisAngle = 25.0f; + +bool LeapMotionDevice::smGenerateWholeFrameEvents = false; + +U32 LeapMotionDevice::LM_FRAMEVALIDDATA = 0; +U32 LeapMotionDevice::LM_HAND[LeapMotionConstants::MaxHands] = {0}; +U32 LeapMotionDevice::LM_HANDROT[LeapMotionConstants::MaxHands] = {0}; +U32 LeapMotionDevice::LM_HANDAXISX = 0; +U32 LeapMotionDevice::LM_HANDAXISY = 0; +U32 LeapMotionDevice::LM_HANDPOINTABLE[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand] = {0}; +U32 LeapMotionDevice::LM_HANDPOINTABLEROT[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand] = {0}; +U32 LeapMotionDevice::LM_FRAME = 0; + +LeapMotionDevice::LeapMotionDevice() +{ + // From IInputDevice + dStrcpy(mName, "leapmotion"); + mDeviceType = INPUTMGR->getNextDeviceType(); + + mController = NULL; + mListener = NULL; + mActiveMutex = Mutex::createMutex(); + + // + mEnabled = false; + mActive = false; + + for(U32 i=0; i<2; ++i) + { + mDataBuffer[i] = new LeapMotionDeviceData(); + } + mPrevData = mDataBuffer[0]; + + buildCodeTable(); +} + +LeapMotionDevice::~LeapMotionDevice() +{ + disable(); + + Mutex::destroyMutex(mActiveMutex); +} + +void LeapMotionDevice::staticInit() +{ + Con::addVariable("pref::LeapMotion::EnableDevice", TypeBool, &smEnableDevice, + "@brief If true, the Leap Motion device will be enabled, if present.\n\n" + "@ingroup Game"); + + Con::addVariable("LeapMotion::GenerateIndividualEvents", TypeBool, &smGenerateIndividualEvents, + "@brief Indicates that events for each hand and pointable will be created.\n\n" + "@ingroup Game"); + Con::addVariable("LeapMotion::KeepHandIndexPersistent", TypeBool, &smKeepHandIndexPersistent, + "@brief Indicates that we track hand IDs and will ensure that the same hand will remain at the same index between frames.\n\n" + "@ingroup Game"); + Con::addVariable("LeapMotion::KeepPointableIndexPersistent", TypeBool, &smKeepPointableIndexPersistent, + "@brief Indicates that we track pointable IDs and will ensure that the same pointable will remain at the same index between frames.\n\n" + "@ingroup Game"); + + Con::addVariable("LeapMotion::GenerateSingleHandRotationAsAxisEvents", TypeBool, &smGenerateSingleHandRotationAsAxisEvents, + "@brief If true, broadcast single hand rotation as axis events.\n\n" + "@ingroup Game"); + Con::addVariable("LeapMotion::MaximumHandAxisAngle", TypeF32, &smMaximumHandAxisAngle, + "@brief The maximum hand angle when used as an axis event as measured from a vector pointing straight up (in degrees).\n\n" + "Shoud range from 0 to 90 degrees.\n\n" + "@ingroup Game"); + + Con::addVariable("LeapMotion::GenerateWholeFrameEvents", TypeBool, &smGenerateWholeFrameEvents, + "@brief Indicates that a whole frame event should be generated and frames should be buffered.\n\n" + "@ingroup Game"); +} + +void LeapMotionDevice::buildCodeTable() +{ + // Obtain all of the device codes + LM_FRAMEVALIDDATA = INPUTMGR->getNextDeviceCode(); + + for(U32 i=0; igetNextDeviceCode(); + LM_HANDROT[i] = INPUTMGR->getNextDeviceCode(); + + // Pointables per hand + for(U32 j=0; jgetNextDeviceCode(); + LM_HANDPOINTABLEROT[i][j] = INPUTMGR->getNextDeviceCode(); + } + } + + LM_HANDAXISX = INPUTMGR->getNextDeviceCode(); + LM_HANDAXISY = INPUTMGR->getNextDeviceCode(); + + LM_FRAME = INPUTMGR->getNextDeviceCode(); + + // Build out the virtual map + AddInputVirtualMap( lm_framevaliddata, SI_BUTTON, LM_FRAMEVALIDDATA ); + + char buffer[64]; + for(U32 i=0; iaddVirtualMap( buffer, SI_POS, LM_HAND[i] ); + dSprintf(buffer, 64, "lm_hand%drot", i+1); + INPUTMGR->addVirtualMap( buffer, SI_ROT, LM_HANDROT[i] ); + + // Pointables per hand + for(U32 j=0; jaddVirtualMap( buffer, SI_POS, LM_HANDPOINTABLE[i][j] ); + dSprintf(buffer, 64, "lm_hand%dpoint%drot", i+1, j+1); + INPUTMGR->addVirtualMap( buffer, SI_POS, LM_HANDPOINTABLEROT[i][j] ); + } + } + + AddInputVirtualMap( lm_handaxisx, SI_AXIS, LM_HANDAXISX ); + AddInputVirtualMap( lm_handaxisy, SI_AXIS, LM_HANDAXISY ); + + AddInputVirtualMap( lm_frame, SI_INT, LM_FRAME ); +} + +bool LeapMotionDevice::enable() +{ + // Start off with disabling the device if it is already enabled + disable(); + + // Create the controller to talk with the Leap Motion along with the listener + mListener = new MotionListener(); + mController = new Leap::Controller(*mListener); + + // The device is now enabled but not yet ready to be used + mEnabled = true; + + return false; +} + +void LeapMotionDevice::disable() +{ + if(mController) + { + delete mController; + mController = NULL; + + if(mListener) + { + delete mListener; + mListener = NULL; + } + } + + setActive(false); + mEnabled = false; +} + +bool LeapMotionDevice::getActive() +{ + Mutex::lockMutex(mActiveMutex); + bool active = mActive; + Mutex::unlockMutex(mActiveMutex); + + return active; +} + +void LeapMotionDevice::setActive(bool state) +{ + Mutex::lockMutex(mActiveMutex); + mActive = state; + Mutex::unlockMutex(mActiveMutex); +} + +bool LeapMotionDevice::process() +{ + if(!mEnabled) + return false; + + if(!getActive()) + return false; + + //Con::printf("LeapMotionDevice::process()"); + + //Build the maximum hand axis angle to be passed into the LeapMotionDeviceData::setData() + F32 maxHandAxisRadius = mSin(mDegToRad(smMaximumHandAxisAngle)); + + // Get a frame of data + const Leap::Frame frame = mController->frame(); + + //const Leap::HandList hands = frame.hands(); + //Con::printf("Frame: %lld Hands: %d Fingers: %d Tools: %d", (long long)frame.id(), hands.count(), frame.fingers().count(), frame.tools().count()); + + // Store the current data + LeapMotionDeviceData* currentBuffer = (mPrevData == mDataBuffer[0]) ? mDataBuffer[1] : mDataBuffer[0]; + currentBuffer->setData(frame, mPrevData, smKeepHandIndexPersistent, smKeepPointableIndexPersistent, maxHandAxisRadius); + U32 diff = mPrevData->compare(currentBuffer); + U32 metaDiff = mPrevData->compareMeta(currentBuffer); + + // Update the previous data pointers. We do this here in case someone calls our + // console functions during one of the input events below. + mPrevData = currentBuffer; + + // Send out any meta data + if(metaDiff & LeapMotionDeviceData::METADIFF_FRAME_VALID_DATA) + { + // Frame valid change event + INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_BUTTON, LM_FRAMEVALIDDATA, currentBuffer->mHasTrackingData ? SI_MAKE : SI_BREAK, currentBuffer->mHasTrackingData ? 1.0f : 0.0f); + } + + // Send out any valid data + if(currentBuffer->mDataSet && currentBuffer->mIsValid) + { + // Hands and their pointables + if(smGenerateIndividualEvents) + { + for(U32 i=0; imHandValid[i]) + { + // Send out position + INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_POS, LM_HAND[i], SI_MOVE, currentBuffer->mHandPosPoint[i]); + + // Send out rotation + INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_ROT, LM_HANDROT[i], SI_MOVE, currentBuffer->mHandRotQuat[i]); + + // Pointables for hand + for(U32 j=0; jmPointableValid[i][j]) + { + // Send out position + INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_POS, LM_HANDPOINTABLE[i][j], SI_MOVE, currentBuffer->mPointablePosPoint[i][j]); + + // Send out rotation + INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_ROT, LM_HANDPOINTABLEROT[i][j], SI_MOVE, currentBuffer->mPointableRotQuat[i][j]); + } + } + } + } + } + + // Single Hand as axis rotation + if(smGenerateSingleHandRotationAsAxisEvents && diff & LeapMotionDeviceData::DIFF_HANDROTAXIS) + { + if(diff & LeapMotionDeviceData::DIFF_HANDROTAXISX) + INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_AXIS, LM_HANDAXISX, SI_MOVE, currentBuffer->mHandRotAxis[0]); + if(diff & LeapMotionDeviceData::DIFF_HANDROTAXISY) + INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_AXIS, LM_HANDAXISY, SI_MOVE, currentBuffer->mHandRotAxis[1]); + } + } + + // Send out whole frame event, but only if the special frame group is defined + if(smGenerateWholeFrameEvents && LeapMotionFrameStore::isFrameGroupDefined()) + { + S32 id = LEAPMOTIONFS->generateNewFrame(frame, maxHandAxisRadius); + if(id != 0) + { + INPUTMGR->buildInputEvent(mDeviceType, DEFAULT_MOTION_UNIT, SI_INT, LM_FRAME, SI_VALUE, id); + } + } + + return true; +} + +//----------------------------------------------------------------------------- +// LeapMotionDevice::MotionListener +//----------------------------------------------------------------------------- + +void LeapMotionDevice::MotionListener::onConnect (const Leap::Controller &controller) +{ + LEAPMOTIONDEV->setActive(true); +} + +void LeapMotionDevice::MotionListener::onDisconnect (const Leap::Controller &controller) +{ + LEAPMOTIONDEV->setActive(false); +} +//----------------------------------------------------------------------------- + +DefineEngineFunction(isLeapMotionActive, bool, (),, + "@brief Used to determine if the Leap Motion input device is active\n\n" + + "The Leap Motion input device is considered active when the support library has been " + "loaded and the device has been found.\n\n" + + "@return True if the Leap Motion input device is active.\n" + + "@ingroup Game") +{ + if(!ManagedSingleton::instanceOrNull()) + { + return false; + } + + return LEAPMOTIONDEV->getActive(); +} diff --git a/Engine/source/platform/input/leapMotion/leapMotionDevice.h b/Engine/source/platform/input/leapMotion/leapMotionDevice.h new file mode 100644 index 0000000000..2f1542fdac --- /dev/null +++ b/Engine/source/platform/input/leapMotion/leapMotionDevice.h @@ -0,0 +1,138 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef _LEAPMOTIONDEVICE_H_ +#define _LEAPMOTIONDEVICE_H_ + +#include "platform/input/IInputDevice.h" +#include "platform/input/event.h" +#include "platformWin32/platformWin32.h" +#include "core/util/tSingleton.h" +#include "math/mQuat.h" +#include "platform/input/leapMotion/leapMotionConstants.h" +#include "Leap.h" + +#define DEFAULT_MOTION_UNIT 0 + +struct LeapMotionDeviceData; + +class LeapMotionDevice : public IInputDevice +{ +protected: + class MotionListener : public Leap::Listener + { + public: + MotionListener() {} + virtual ~MotionListener() {} + + virtual void onConnect (const Leap::Controller &controller); + virtual void onDisconnect (const Leap::Controller &controller); + }; + + /// The connection to the Leap Motion + Leap::Controller* mController; + + /// Our Leap Motion listener class + MotionListener* mListener; + + /// Used with the LM listener object + void* mActiveMutex; + + /// Is the Leap Motion active + bool mActive; + + /// Buffer to store data Leap Motion data in a Torque friendly way + LeapMotionDeviceData* mDataBuffer[2]; + + /// Points to the buffers that holds the previously collected data + LeapMotionDeviceData* mPrevData; + +protected: + /// Build out the codes used for controller actions with the + /// Input Event Manager + void buildCodeTable(); + +public: + static bool smEnableDevice; + + // Indicates that events for each hand and pointable will be created + static bool smGenerateIndividualEvents; + + // Indicates that we track hand IDs and will ensure that the same hand + // will remain at the same index between frames. + static bool smKeepHandIndexPersistent; + + // Indicates that we track pointable IDs and will ensure that the same + // pointable will remain at the same index between frames. + static bool smKeepPointableIndexPersistent; + + // Broadcast single hand rotation as axis + static bool smGenerateSingleHandRotationAsAxisEvents; + + // The maximum hand angle when used as an axis event + // as measured from a vector pointing straight up (in degrees) + static F32 smMaximumHandAxisAngle; + + // Indicates that a whole frame event should be generated and frames + // should be buffered. + static bool smGenerateWholeFrameEvents; + + // Frame action codes + static U32 LM_FRAMEVALIDDATA; // SI_BUTTON + + // Hand action codes + static U32 LM_HAND[LeapMotionConstants::MaxHands]; // SI_POS + static U32 LM_HANDROT[LeapMotionConstants::MaxHands]; // SI_ROT + + static U32 LM_HANDAXISX; // SI_AXIS + static U32 LM_HANDAXISY; + + // Pointables action codes + static U32 LM_HANDPOINTABLE[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand]; // SI_POS + static U32 LM_HANDPOINTABLEROT[LeapMotionConstants::MaxHands][LeapMotionConstants::MaxPointablesPerHand]; // SI_ROT + + // Whole frame + static U32 LM_FRAME; // SI_INT + +public: + LeapMotionDevice(); + ~LeapMotionDevice(); + + static void staticInit(); + + bool enable(); + void disable(); + + bool getActive(); + void setActive(bool state); + + bool process(); + +public: + // For ManagedSingleton. + static const char* getSingletonName() { return "LeapMotionDevice"; } +}; + +/// Returns the LeapMotionDevice singleton. +#define LEAPMOTIONDEV ManagedSingleton::instance() + +#endif // _LEAPMOTIONDEVICE_H_ diff --git a/Engine/source/platform/input/leapMotion/leapMotionFrame.cpp b/Engine/source/platform/input/leapMotion/leapMotionFrame.cpp new file mode 100644 index 0000000000..0f1cf672db --- /dev/null +++ b/Engine/source/platform/input/leapMotion/leapMotionFrame.cpp @@ -0,0 +1,497 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "platform/input/leapMotion/leapMotionFrame.h" +#include "platform/input/leapMotion/leapMotionUtil.h" +#include "console/engineAPI.h" +#include "math/mAngAxis.h" +#include "math/mTransform.h" + +U32 LeapMotionFrame::smNextInternalFrameId = 0; + +IMPLEMENT_CONOBJECT(LeapMotionFrame); + +ImplementEnumType( LeapMotionFramePointableType, + "Leap Motion pointable type.\n\n") + { LeapMotionFrame::PT_UNKNOWN, "Unknown", "Unknown pointable type.\n" }, + { LeapMotionFrame::PT_FINGER, "Finger", "Finger pointable type.\n" }, + { LeapMotionFrame::PT_TOOL, "Tool", "Tool pointable type.\n" }, +EndImplementEnumType; + +LeapMotionFrame::LeapMotionFrame() +{ + clear(); +} + +LeapMotionFrame::~LeapMotionFrame() +{ + clear(); +} + + +void LeapMotionFrame::initPersistFields() +{ + Parent::initPersistFields(); +} + +bool LeapMotionFrame::onAdd() +{ + if (!Parent::onAdd()) + return false; + + return true; +} + +void LeapMotionFrame::onRemove() +{ + Parent::onRemove(); +} + +void LeapMotionFrame::clear() +{ + mFrameValid = false; + + mHandCount = 0; + mHandValid.clear(); + mHandId.clear(); + mHandRawPos.clear(); + mHandPos.clear(); + mHandRot.clear(); + mHandRotQuat.clear(); + mHandRotAxis.clear(); + mHandPointablesCount.clear(); + + mPointableCount = 0; + mPointableValid.clear(); + mPointableId.clear(); + mPointableHandIndex.clear(); + mPointableType.clear(); + mPointableRawPos.clear(); + mPointablePos.clear(); + mPointableRot.clear(); + mPointableRotQuat.clear(); + mPointableLength.clear(); + mPointableWidth.clear(); +} + +void LeapMotionFrame::copyFromFrame(const Leap::Frame& frame, const F32& maxHandAxisRadius) +{ + // This also resets all counters + clear(); + + // Retrieve frame information + mFrameValid = frame.isValid(); + mFrameId = frame.id(); + mFrameTimeStamp = frame.timestamp(); + + mFrameInternalId = smNextInternalFrameId; + ++smNextInternalFrameId; + mFrameSimTime = Sim::getCurrentTime(); + mFrameRealTime = Platform::getRealMilliseconds(); + + if(!mFrameValid) + { + return; + } + + // Retrieve hand information + mHandCount = frame.hands().count(); + if(mHandCount > 0) + { + copyFromFrameHands(frame.hands(), maxHandAxisRadius); + } + + // Retrieve pointable information + mPointableCount = frame.pointables().count(); + if(mPointableCount > 0) + { + copyFromFramePointables(frame.pointables()); + } +} + +void LeapMotionFrame::copyFromFrameHands(const Leap::HandList& hands, const F32& maxHandAxisRadius) +{ + // Set up Vectors + mHandValid.increment(mHandCount); + mHandId.increment(mHandCount); + mHandRawPos.increment(mHandCount); + mHandPos.increment(mHandCount); + mHandRot.increment(mHandCount); + mHandRotQuat.increment(mHandCount); + mHandRotAxis.increment(mHandCount); + mHandPointablesCount.increment(mHandCount); + + // Copy data + for(U32 i=0; iisFrameValid(); +} + +DefineEngineMethod( LeapMotionFrame, getFrameInternalId, S32, ( ),, + "@brief Provides the internal ID for this frame.\n\n" + "@return Internal ID of this frame.\n\n") +{ + return object->getFrameInternalId(); +} + +DefineEngineMethod( LeapMotionFrame, getFrameSimTime, S32, ( ),, + "@brief Get the sim time that this frame was generated.\n\n" + "@return Sim time of this frame in milliseconds.\n\n") +{ + return object->getFrameSimTime(); +} + +DefineEngineMethod( LeapMotionFrame, getFrameRealTime, S32, ( ),, + "@brief Get the real time that this frame was generated.\n\n" + "@return Real time of this frame in milliseconds.\n\n") +{ + return object->getFrameRealTime(); +} + +DefineEngineMethod( LeapMotionFrame, getHandCount, S32, ( ),, + "@brief Get the number of hands defined in this frame.\n\n" + "@return The number of defined hands.\n\n") +{ + return object->getHandCount(); +} + +DefineEngineMethod( LeapMotionFrame, getHandValid, bool, ( S32 index ),, + "@brief Check if the requested hand is valid.\n\n" + "@param index The hand index to check.\n" + "@return True if the hand is valid.\n\n") +{ + return object->getHandValid(index); +} + +DefineEngineMethod( LeapMotionFrame, getHandId, S32, ( S32 index ),, + "@brief Get the ID of the requested hand.\n\n" + "@param index The hand index to check.\n" + "@return ID of the requested hand.\n\n") +{ + return object->getHandId(index); +} + +DefineEngineMethod( LeapMotionFrame, getHandRawPos, Point3F, ( S32 index ),, + "@brief Get the raw position of the requested hand.\n\n" + "The raw position is the hand's floating point position converted to " + "Torque 3D coordinates (in millimeters).\n" + "@param index The hand index to check.\n" + "@return Raw position of the requested hand.\n\n") +{ + return object->getHandRawPos(index); +} + +DefineEngineMethod( LeapMotionFrame, getHandPos, Point3I, ( S32 index ),, + "@brief Get the position of the requested hand.\n\n" + "The position is the hand's integer position converted to " + "Torque 3D coordinates (in millimeters).\n" + "@param index The hand index to check.\n" + "@return Integer position of the requested hand (in millimeters).\n\n") +{ + return object->getHandPos(index); +} + +DefineEngineMethod( LeapMotionFrame, getHandRot, AngAxisF, ( S32 index ),, + "@brief Get the rotation of the requested hand.\n\n" + "The Leap Motion hand rotation as converted into the Torque 3D" + "coordinate system.\n" + "@param index The hand index to check.\n" + "@return Rotation of the requested hand.\n\n") +{ + AngAxisF aa(object->getHandRot(index)); + return aa; +} + +DefineEngineMethod( LeapMotionFrame, getHandRawTransform, TransformF, ( S32 index ),, + "@brief Get the raw transform of the requested hand.\n\n" + "@param index The hand index to check.\n" + "@return The raw position and rotation of the requested hand (in Torque 3D coordinates).\n\n") +{ + const Point3F& pos = object->getHandRawPos(index); + const QuatF& qa = object->getHandRotQuat(index); + + AngAxisF aa(qa); + aa.axis.normalize(); + + TransformF trans(pos, aa); + return trans; +} + +DefineEngineMethod( LeapMotionFrame, getHandTransform, TransformF, ( S32 index ),, + "@brief Get the transform of the requested hand.\n\n" + "@param index The hand index to check.\n" + "@return The position and rotation of the requested hand (in Torque 3D coordinates).\n\n") +{ + const Point3I& pos = object->getHandPos(index); + const QuatF& qa = object->getHandRotQuat(index); + + AngAxisF aa(qa); + aa.axis.normalize(); + + TransformF trans; + trans.mPosition = Point3F(pos.x, pos.y, pos.z); + trans.mOrientation = aa; + + return trans; +} + +DefineEngineMethod( LeapMotionFrame, getHandRotAxis, Point2F, ( S32 index ),, + "@brief Get the axis rotation of the requested hand.\n\n" + "This is the axis rotation of the hand as if the hand were a gamepad thumb stick. " + "Imagine a stick coming out the top of the hand and tilting the hand front, back, " + "left and right controls that stick. The values returned along the x and y stick " + "axis are normalized from -1.0 to 1.0 with the maximum hand tilt angle for these " + "values as defined by $LeapMotion::MaximumHandAxisAngle.\n" + "@param index The hand index to check.\n" + "@return Axis rotation of the requested hand.\n\n" + "@see LeapMotion::MaximumHandAxisAngle\n") +{ + return object->getHandRotAxis(index); +} + +DefineEngineMethod( LeapMotionFrame, getHandPointablesCount, S32, ( S32 index ),, + "@brief Get the number of pointables associated with this hand.\n\n" + "@param index The hand index to check.\n" + "@return Number of pointables that belong with this hand.\n\n") +{ + return object->getHandPointablesCount(index); +} + +DefineEngineMethod( LeapMotionFrame, getPointablesCount, S32, ( ),, + "@brief Get the number of pointables defined in this frame.\n\n" + "@return The number of defined pointables.\n\n") +{ + return object->getPointablesCount(); +} + +DefineEngineMethod( LeapMotionFrame, getPointableValid, bool, ( S32 index ),, + "@brief Check if the requested pointable is valid.\n\n" + "@param index The pointable index to check.\n" + "@return True if the pointable is valid.\n\n") +{ + return object->getPointableValid(index); +} + +DefineEngineMethod( LeapMotionFrame, getPointableId, S32, ( S32 index ),, + "@brief Get the ID of the requested pointable.\n\n" + "@param index The pointable index to check.\n" + "@return ID of the requested pointable.\n\n") +{ + return object->getPointableId(index); +} + +DefineEngineMethod( LeapMotionFrame, getPointableHandIndex, S32, ( S32 index ),, + "@brief Get the index of the hand that this pointable belongs to, if any.\n\n" + "@param index The pointable index to check.\n" + "@return Index of the hand this pointable belongs to, or -1 if there is no associated hand.\n\n") +{ + return object->getPointableHandIndex(index); +} + +DefineEngineMethod( LeapMotionFrame, getPointableType, LeapMotionFramePointableType, ( S32 index ),, + "@brief Get the type of the requested pointable.\n\n" + "@param index The pointable index to check.\n" + "@return Type of the requested pointable.\n\n") +{ + return object->getPointableType(index); +} + +DefineEngineMethod( LeapMotionFrame, getPointableRawPos, Point3F, ( S32 index ),, + "@brief Get the raw position of the requested pointable.\n\n" + "The raw position is the pointable's floating point position converted to " + "Torque 3D coordinates (in millimeters).\n" + "@param index The pointable index to check.\n" + "@return Raw position of the requested pointable.\n\n") +{ + return object->getPointableRawPos(index); +} + +DefineEngineMethod( LeapMotionFrame, getPointablePos, Point3I, ( S32 index ),, + "@brief Get the position of the requested pointable.\n\n" + "The position is the pointable's integer position converted to " + "Torque 3D coordinates (in millimeters).\n" + "@param index The pointable index to check.\n" + "@return Integer position of the requested pointable (in millimeters).\n\n") +{ + return object->getPointablePos(index); +} + +DefineEngineMethod( LeapMotionFrame, getPointableRot, AngAxisF, ( S32 index ),, + "@brief Get the rotation of the requested pointable.\n\n" + "The Leap Motion pointable rotation as converted into the Torque 3D" + "coordinate system.\n" + "@param index The pointable index to check.\n" + "@return Rotation of the requested pointable.\n\n") +{ + AngAxisF aa(object->getPointableRot(index)); + return aa; +} + +DefineEngineMethod( LeapMotionFrame, getPointableRawTransform, TransformF, ( S32 index ),, + "@brief Get the raw transform of the requested pointable.\n\n" + "@param index The pointable index to check.\n" + "@return The raw position and rotation of the requested pointable (in Torque 3D coordinates).\n\n") +{ + const Point3F& pos = object->getPointableRawPos(index); + const QuatF& qa = object->getPointableRotQuat(index); + + AngAxisF aa(qa); + aa.axis.normalize(); + + TransformF trans(pos, aa); + return trans; +} + +DefineEngineMethod( LeapMotionFrame, getPointableTransform, TransformF, ( S32 index ),, + "@brief Get the transform of the requested pointable.\n\n" + "@param index The pointable index to check.\n" + "@return The position and rotation of the requested pointable (in Torque 3D coordinates).\n\n") +{ + const Point3I& pos = object->getPointablePos(index); + const QuatF& qa = object->getPointableRotQuat(index); + + AngAxisF aa(qa); + aa.axis.normalize(); + + TransformF trans; + trans.mPosition = Point3F(pos.x, pos.y, pos.z); + trans.mOrientation = aa; + + return trans; +} + +DefineEngineMethod( LeapMotionFrame, getPointableLength, F32, ( S32 index ),, + "@brief Get the length of the requested pointable.\n\n" + "@param index The pointable index to check.\n" + "@return Length of the requested pointable (in millimeters).\n\n") +{ + return object->getPointableLength(index); +} + +DefineEngineMethod( LeapMotionFrame, getPointableWidth, F32, ( S32 index ),, + "@brief Get the width of the requested pointable.\n\n" + "@param index The pointable index to check.\n" + "@return Width of the requested pointable (in millimeters).\n\n") +{ + return object->getPointableWidth(index); +} diff --git a/Engine/source/platform/input/leapMotion/leapMotionFrame.h b/Engine/source/platform/input/leapMotion/leapMotionFrame.h new file mode 100644 index 0000000000..eeefb08430 --- /dev/null +++ b/Engine/source/platform/input/leapMotion/leapMotionFrame.h @@ -0,0 +1,227 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef _LEAPMOTIONFRAME_H_ +#define _LEAPMOTIONFRAME_H_ + +#include "console/simObject.h" +#include "math/mPoint3.h" +#include "math/mMatrix.h" +#include "math/mQuat.h" +#include "Leap.h" + +class LeapMotionFrame : public SimObject +{ + typedef SimObject Parent; + +public: + enum PointableType + { + PT_UNKNOWN = -1, + PT_FINGER = 0, + PT_TOOL, + }; + +protected: + static U32 smNextInternalFrameId; + + // Frame + bool mFrameValid; + U64 mFrameId; + U64 mFrameTimeStamp; + + // Torque 3D frame information + U32 mFrameInternalId; + S32 mFrameSimTime; + S32 mFrameRealTime; + + // Hands + U32 mHandCount; + Vector mHandValid; + Vector mHandId; + Vector mHandRawPos; + Vector mHandPos; + Vector mHandRot; + Vector mHandRotQuat; + Vector mHandRotAxis; + Vector mHandPointablesCount; + + // Pointables + U32 mPointableCount; + Vector mPointableValid; + Vector mPointableId; + Vector mPointableHandIndex; + Vector mPointableType; + Vector mPointableRawPos; + Vector mPointablePos; + Vector mPointableRot; + Vector mPointableRotQuat; + Vector mPointableLength; + Vector mPointableWidth; + +protected: + void copyFromFrameHands(const Leap::HandList& hands, const F32& maxHandAxisRadius); + void copyFromFramePointables(const Leap::PointableList& pointables); + +public: + LeapMotionFrame(); + virtual ~LeapMotionFrame(); + + static void initPersistFields(); + + virtual bool onAdd(); + virtual void onRemove(); + + void clear(); + + /// Copy a Leap Frame into our data structures + void copyFromFrame(const Leap::Frame& frame, const F32& maxHandAxisRadius); + + // Frame + bool isFrameValid() const { return mFrameValid; } + U32 getFrameInternalId() const { return mFrameInternalId; } + S32 getFrameSimTime() const { return mFrameSimTime; } + S32 getFrameRealTime() const { return mFrameRealTime; } + + // Hands + U32 getHandCount() const { return mHandCount; } + bool getHandValid(U32 index) const; + S32 getHandId(U32 index) const; + const Point3F& getHandRawPos(U32 index) const; + const Point3I& getHandPos(U32 index) const; + const MatrixF& getHandRot(U32 index) const; + const QuatF& getHandRotQuat(U32 index) const; + const Point2F& getHandRotAxis(U32 index) const; + U32 getHandPointablesCount(U32 index) const; + + // Pointables + U32 getPointablesCount() const { return mPointableCount; } + bool getPointableValid(U32 index) const; + S32 getPointableId(U32 index) const; + S32 getPointableHandIndex(U32 index) const; + PointableType getPointableType(U32 index) const; + const Point3F& getPointableRawPos(U32 index) const; + const Point3I& getPointablePos(U32 index) const; + const MatrixF& getPointableRot(U32 index) const; + const QuatF& getPointableRotQuat(U32 index) const; + F32 getPointableLength(U32 index) const; + F32 getPointableWidth(U32 index) const; + + DECLARE_CONOBJECT(LeapMotionFrame); +}; + +typedef LeapMotionFrame::PointableType LeapMotionFramePointableType; +DefineEnumType( LeapMotionFramePointableType ); + +//----------------------------------------------------------------------------- + +inline bool LeapMotionFrame::getHandValid(U32 index) const +{ + return (index < mHandCount && mHandValid[index]); +} + +inline S32 LeapMotionFrame::getHandId(U32 index) const +{ + return (index >= mHandCount) ? -1 : mHandId[index]; +} + +inline const Point3F& LeapMotionFrame::getHandRawPos(U32 index) const +{ + return (index >= mHandCount) ? Point3F::Zero : mHandRawPos[index]; +} + +inline const Point3I& LeapMotionFrame::getHandPos(U32 index) const +{ + return (index >= mHandCount) ? Point3I::Zero : mHandPos[index]; +} + +inline const MatrixF& LeapMotionFrame::getHandRot(U32 index) const +{ + return (index >= mHandCount) ? MatrixF::Identity : mHandRot[index]; +} + +inline const QuatF& LeapMotionFrame::getHandRotQuat(U32 index) const +{ + return (index >= mHandCount) ? QuatF::Identity : mHandRotQuat[index]; +} + +inline const Point2F& LeapMotionFrame::getHandRotAxis(U32 index) const +{ + return (index >= mHandCount) ? Point2F::Zero : mHandRotAxis[index]; +} + +inline U32 LeapMotionFrame::getHandPointablesCount(U32 index) const +{ + return (index >= mHandCount) ? 0 : mHandPointablesCount[index]; +} + +inline bool LeapMotionFrame::getPointableValid(U32 index) const +{ + return (index < mPointableCount && mPointableValid[index]); +} + +inline S32 LeapMotionFrame::getPointableId(U32 index) const +{ + return (index >= mPointableCount) ? -1 : mPointableId[index]; +} + +inline S32 LeapMotionFrame::getPointableHandIndex(U32 index) const +{ + return (index >= mPointableCount) ? -1 : mPointableHandIndex[index]; +} + +inline LeapMotionFrame::PointableType LeapMotionFrame::getPointableType(U32 index) const +{ + return (index >= mPointableCount) ? PT_UNKNOWN : mPointableType[index]; +} + +inline const Point3F& LeapMotionFrame::getPointableRawPos(U32 index) const +{ + return (index >= mPointableCount) ? Point3F::Zero : mPointableRawPos[index]; +} + +inline const Point3I& LeapMotionFrame::getPointablePos(U32 index) const +{ + return (index >= mPointableCount) ? Point3I::Zero : mPointablePos[index]; +} + +inline const MatrixF& LeapMotionFrame::getPointableRot(U32 index) const +{ + return (index >= mPointableCount) ? MatrixF::Identity : mPointableRot[index]; +} + +inline const QuatF& LeapMotionFrame::getPointableRotQuat(U32 index) const +{ + return (index >= mPointableCount) ? QuatF::Identity : mPointableRotQuat[index]; +} + +inline F32 LeapMotionFrame::getPointableLength(U32 index) const +{ + return (index >= mPointableCount) ? 0.0f : mPointableLength[index]; +} + +inline F32 LeapMotionFrame::getPointableWidth(U32 index) const +{ + return (index >= mPointableCount) ? 0.0f : mPointableWidth[index]; +} + +#endif // _LEAPMOTIONFRAME_H_ diff --git a/Engine/source/platform/input/leapMotion/leapMotionFrameStore.cpp b/Engine/source/platform/input/leapMotion/leapMotionFrameStore.cpp new file mode 100644 index 0000000000..77f40485d1 --- /dev/null +++ b/Engine/source/platform/input/leapMotion/leapMotionFrameStore.cpp @@ -0,0 +1,106 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "platform/input/leapMotion/leapMotionFrameStore.h" +#include "platform/input/leapMotion/leapMotionFrame.h" +#include "core/module.h" +#include "console/simSet.h" +#include "console/consoleTypes.h" + +MODULE_BEGIN( LeapMotionFrameStore ) + + MODULE_INIT_AFTER( LeapMotionDevice ) + MODULE_INIT_AFTER( Sim ) + MODULE_SHUTDOWN_BEFORE( Sim ) + MODULE_SHUTDOWN_BEFORE( LeapMotionDevice ) + + MODULE_INIT + { + LeapMotionFrameStore::staticInit(); + ManagedSingleton< LeapMotionFrameStore >::createSingleton(); + } + + MODULE_SHUTDOWN + { + ManagedSingleton< LeapMotionFrameStore >::deleteSingleton(); + } + +MODULE_END; + +S32 LeapMotionFrameStore::smMaximumFramesStored = 30; + +SimGroup* LeapMotionFrameStore::smFrameGroup = NULL; + +LeapMotionFrameStore::LeapMotionFrameStore() +{ + // Set up the SimGroup to store our frames + smFrameGroup = new SimGroup(); + smFrameGroup->registerObject("LeapMotionFrameGroup"); + smFrameGroup->setNameChangeAllowed(false); + Sim::getRootGroup()->addObject(smFrameGroup); +} + +LeapMotionFrameStore::~LeapMotionFrameStore() +{ + if(smFrameGroup) + { + smFrameGroup->deleteObject(); + smFrameGroup = NULL; + } +} + +void LeapMotionFrameStore::staticInit() +{ + Con::addVariable("LeapMotion::MaximumFramesStored", TypeS32, &smMaximumFramesStored, + "@brief The maximum number of frames to keep when $LeapMotion::GenerateWholeFrameEvents is true.\n\n" + "@ingroup Game"); +} + +S32 LeapMotionFrameStore::generateNewFrame(const Leap::Frame& frame, const F32& maxHandAxisRadius) +{ + // Make sure our group has been created + if(!smFrameGroup) + return 0; + + // Either create a new frame object or pull one off the end + S32 frameID = 0; + if(smFrameGroup->size() >= smMaximumFramesStored) + { + // Make the last frame the first and update + LeapMotionFrame* frameObj = static_cast(smFrameGroup->last()); + smFrameGroup->bringObjectToFront(frameObj); + frameObj->copyFromFrame(frame, maxHandAxisRadius); + frameID = frameObj->getId(); + } + else + { + // Create a new frame and add it to the front of the list + LeapMotionFrame* frameObj = new LeapMotionFrame(); + frameObj->registerObject(); + smFrameGroup->addObject(frameObj); + smFrameGroup->bringObjectToFront(frameObj); + frameObj->copyFromFrame(frame, maxHandAxisRadius); + frameID = frameObj->getId(); + } + + return frameID; +} diff --git a/Engine/source/platform/input/leapMotion/leapMotionFrameStore.h b/Engine/source/platform/input/leapMotion/leapMotionFrameStore.h new file mode 100644 index 0000000000..8576ad52db --- /dev/null +++ b/Engine/source/platform/input/leapMotion/leapMotionFrameStore.h @@ -0,0 +1,58 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef _LEAPMOTIONFRAMESTORE_H_ +#define _LEAPMOTIONFRAMESTORE_H_ + +#include "platformWin32/platformWin32.h" +#include "Leap.h" + +class SimGroup; + +class LeapMotionFrameStore +{ +public: + // The maximum number of frames to keep + static S32 smMaximumFramesStored; + + static SimGroup* smFrameGroup; + +public: + LeapMotionFrameStore(); + virtual ~LeapMotionFrameStore(); + + static void staticInit(); + + static bool isFrameGroupDefined() { return smFrameGroup != NULL; } + static SimGroup* getFrameGroup() { return smFrameGroup; } + + S32 generateNewFrame(const Leap::Frame& frame, const F32& maxHandAxisRadius); + +public: + // For ManagedSingleton. + static const char* getSingletonName() { return "LeapMotionFrameStore"; } +}; + +/// Returns the LeapMotionFrameStore singleton. +#define LEAPMOTIONFS ManagedSingleton::instance() + +#endif // _LEAPMOTIONFRAMESTORE_H_ diff --git a/Engine/source/platform/input/leapMotion/leapMotionUtil.cpp b/Engine/source/platform/input/leapMotion/leapMotionUtil.cpp new file mode 100644 index 0000000000..12dc42acc5 --- /dev/null +++ b/Engine/source/platform/input/leapMotion/leapMotionUtil.cpp @@ -0,0 +1,109 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#include "platform/input/leapMotion/leapMotionUtil.h" + +namespace LeapMotionUtil +{ + +void convertPosition(const Leap::Vector& inPosition, F32& x, F32& y, F32& z) +{ + // Convert to Torque coordinates. The conversion is: + // + // Motion Torque + // x y z --> x -z y + x = inPosition.x; // x = x + y = -inPosition.z; // y = -z + z = inPosition.y; // z = y; +} + +void convertPosition(const Leap::Vector& inPosition, Point3F& outPosition) +{ + // Convert to Torque coordinates. The conversion is: + // + // Motion Torque + // x y z --> x -z y + outPosition.x = inPosition.x; // x = x + outPosition.y = -inPosition.z; // y = -z + outPosition.z = inPosition.y; // z = y; +} + +void convertHandRotation(const Leap::Hand& hand, MatrixF& outRotation) +{ + // We need to convert from Motion coordinates to + // Torque coordinates. The conversion is: + // + // Motion Torque + // a b c a b c a -c b + // d e f --> -g -h -i --> -g i -h + // g h i d e f d -f e + const Leap::Vector& handToFingers = hand.direction(); + Leap::Vector handFront = -handToFingers; + const Leap::Vector& handDown = hand.palmNormal(); + Leap::Vector handUp = -handDown; + Leap::Vector handRight = handUp.cross(handFront); + + outRotation.setColumn(0, Point4F( handRight.x, -handRight.z, handRight.y, 0.0f)); + outRotation.setColumn(1, Point4F( -handFront.x, handFront.z, -handFront.y, 0.0f)); + outRotation.setColumn(2, Point4F( handUp.x, -handUp.z, handUp.y, 0.0f)); + outRotation.setPosition(Point3F::Zero); +} + +void calculateHandAxisRotation(const MatrixF& handRotation, const F32& maxHandAxisRadius, Point2F& outRotation) +{ + const VectorF& controllerUp = handRotation.getUpVector(); + outRotation.x = controllerUp.x; + outRotation.y = controllerUp.y; + + // Limit the axis angle to that given to us + if(outRotation.len() > maxHandAxisRadius) + { + outRotation.normalize(maxHandAxisRadius); + } + + // Renormalize to the range of 0..1 + if(maxHandAxisRadius != 0.0f) + { + outRotation /= maxHandAxisRadius; + } +} + +void convertPointableRotation(const Leap::Pointable& pointable, MatrixF& outRotation) +{ + // We need to convert from Motion coordinates to + // Torque coordinates. The conversion is: + // + // Motion Torque + // a b c a b c a -c b + // d e f --> -g -h -i --> -g i -h + // g h i d e f d -f e + Leap::Vector pointableFront = -pointable.direction(); + Leap::Vector pointableRight = Leap::Vector::up().cross(pointableFront); + Leap::Vector pointableUp = pointableFront.cross(pointableRight); + + outRotation.setColumn(0, Point4F( pointableRight.x, -pointableRight.z, pointableRight.y, 0.0f)); + outRotation.setColumn(1, Point4F( -pointableFront.x, pointableFront.z, -pointableFront.y, 0.0f)); + outRotation.setColumn(2, Point4F( pointableUp.x, -pointableUp.z, pointableUp.y, 0.0f)); + outRotation.setPosition(Point3F::Zero); +} + +} diff --git a/Engine/source/platform/input/leapMotion/leapMotionUtil.h b/Engine/source/platform/input/leapMotion/leapMotionUtil.h new file mode 100644 index 0000000000..a2eeaed2aa --- /dev/null +++ b/Engine/source/platform/input/leapMotion/leapMotionUtil.h @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2012 GarageGames, LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +//----------------------------------------------------------------------------- + +#ifndef _LEAPMOTIONUTIL_H_ +#define _LEAPMOTIONUTIL_H_ + +#include "math/mPoint3.h" +#include "math/mMatrix.h" +#include "Leap.h" + +namespace LeapMotionUtil +{ + /// Convert from a Leap Motion position to a Torque 3D position + void convertPosition(const Leap::Vector& inPosition, F32& x, F32& y, F32& z); + + /// Convert from a Leap Motion position to a Torque 3D Point3F + void convertPosition(const Leap::Vector& inPosition, Point3F& outPosition); + + /// Convert a Leap Motion hand's rotation to a Torque 3D matrix + void convertHandRotation(const Leap::Hand& hand, MatrixF& outRotation); + + /// Calcualte a hand's rotation as if it were a thumb stick axis + void calculateHandAxisRotation(const MatrixF& handRotation, const F32& maxHandAxisRadius, Point2F& outRotation); + + /// Convert a Leap Motion pointable's rotation to a Torque 3D matrix + void convertPointableRotation(const Leap::Pointable& pointable, MatrixF& outRotation); +} + +#endif diff --git a/Engine/source/platform/platform.cpp b/Engine/source/platform/platform.cpp index fe9b14167c..57032b5314 100644 --- a/Engine/source/platform/platform.cpp +++ b/Engine/source/platform/platform.cpp @@ -27,7 +27,7 @@ #include "console/consoleTypes.h" #include "platform/threads/mutex.h" #include "app/mainLoop.h" -#include "platform/event.h" +#include "platform/input/event.h" #include "platform/typetraits.h" diff --git a/Engine/source/platform/platform.h b/Engine/source/platform/platform.h index 2ae100e0d5..eeda303b99 100644 --- a/Engine/source/platform/platform.h +++ b/Engine/source/platform/platform.h @@ -336,7 +336,7 @@ namespace Platform bool openWebBrowser( const char* webAddress ); // display Splash Window - bool displaySplashWindow( ); + bool displaySplashWindow( String path ); void openFolder( const char* path ); diff --git a/Engine/source/platform/platformInput.h b/Engine/source/platform/platformInput.h index 79f05e8887..6abc459e70 100644 --- a/Engine/source/platform/platformInput.h +++ b/Engine/source/platform/platformInput.h @@ -27,7 +27,7 @@ #include "console/simBase.h" #endif -#include "platform/event.h" +#include "platform/input/event.h" //------------------------------------------------------------------------------ U8 TranslateOSKeyCode( U8 vcode ); diff --git a/Engine/source/platform/platformNet.cpp b/Engine/source/platform/platformNet.cpp index 30dcee4c48..786fcf62d7 100644 --- a/Engine/source/platform/platformNet.cpp +++ b/Engine/source/platform/platformNet.cpp @@ -21,7 +21,6 @@ //----------------------------------------------------------------------------- #include "platform/platformNet.h" -#include "platform/event.h" #include "core/strings/stringFunctions.h" #if defined (TORQUE_OS_WIN32) diff --git a/Engine/source/platformWin32/winConsole.h b/Engine/source/platformWin32/winConsole.h index 4c86bbb34a..3551670424 100644 --- a/Engine/source/platformWin32/winConsole.h +++ b/Engine/source/platformWin32/winConsole.h @@ -27,9 +27,6 @@ #ifndef _CONSOLE_H_ #include "console/console.h" #endif -#ifndef _EVENT_H_ -#include "platform/event.h" -#endif class WinConsole { diff --git a/Engine/source/platformWin32/winDInputDevice.cpp b/Engine/source/platformWin32/winDInputDevice.cpp index 992a881940..759a346436 100644 --- a/Engine/source/platformWin32/winDInputDevice.cpp +++ b/Engine/source/platformWin32/winDInputDevice.cpp @@ -66,7 +66,8 @@ DInputDevice::DInputDevice( const DIDEVICEINSTANCE* dii ) switch ( GET_DIDEVICE_TYPE( mDeviceInstance.dwDevType ) ) { // [rene, 12/09/2008] why do we turn a gamepad into a joystick here? - + + case DI8DEVTYPE_DRIVING: case DI8DEVTYPE_GAMEPAD: case DI8DEVTYPE_JOYSTICK: deviceTypeName = "joystick"; @@ -991,7 +992,7 @@ bool DInputDevice::buildEvent( DWORD offset, S32 newData, S32 oldData ) } if( clearkeys & POV_down) { - newEvent.objInst = ( objInst == 0 ) ? SI_DPOV : SI_DPOV; + newEvent.objInst = ( objInst == 0 ) ? SI_DPOV : SI_DPOV2; _Win32LogPOVInput(newEvent); newEvent.postToSignal(Input::smInputEvent); } @@ -1022,7 +1023,7 @@ bool DInputDevice::buildEvent( DWORD offset, S32 newData, S32 oldData ) } if( setkeys & POV_down) { - newEvent.objInst = ( objInst == 0 ) ? SI_DPOV : SI_DPOV; + newEvent.objInst = ( objInst == 0 ) ? SI_DPOV : SI_DPOV2; _Win32LogPOVInput(newEvent); newEvent.postToSignal(Input::smInputEvent); } diff --git a/Engine/source/platformWin32/winDInputDevice.h b/Engine/source/platformWin32/winDInputDevice.h index 46a9d1a60f..e8cd13e664 100644 --- a/Engine/source/platformWin32/winDInputDevice.h +++ b/Engine/source/platformWin32/winDInputDevice.h @@ -29,9 +29,6 @@ #ifndef _PLATFORMINPUT_H_ #include "platform/platformInput.h" #endif -#ifndef _EVENT_H_ -#include "platform/event.h" -#endif #define DIRECTINPUT_VERSION 0x0800 #include diff --git a/Engine/source/platformWin32/winDirectInput.cpp b/Engine/source/platformWin32/winDirectInput.cpp index 72254c17c0..86bb52bd27 100644 --- a/Engine/source/platformWin32/winDirectInput.cpp +++ b/Engine/source/platformWin32/winDirectInput.cpp @@ -23,7 +23,6 @@ #include "platformWin32/platformWin32.h" #include "platformWin32/winDirectInput.h" #include "platformWin32/winDInputDevice.h" -#include "platform/event.h" #include "console/console.h" #include "console/consoleTypes.h" #include "sim/actionMap.h" diff --git a/Engine/source/platformWin32/winInput.cpp b/Engine/source/platformWin32/winInput.cpp index f6ee3cc024..e4fcdba578 100644 --- a/Engine/source/platformWin32/winInput.cpp +++ b/Engine/source/platformWin32/winInput.cpp @@ -24,7 +24,6 @@ #include "platform/platformInput.h" #include "platformWin32/winDirectInput.h" -#include "platform/event.h" #include "console/console.h" #include "core/util/journal/process.h" #include "windowManager/platformWindowMgr.h" diff --git a/Engine/source/platformWin32/winWindow.cpp b/Engine/source/platformWin32/winWindow.cpp index f2199e8db5..53b3a2b486 100644 --- a/Engine/source/platformWin32/winWindow.cpp +++ b/Engine/source/platformWin32/winWindow.cpp @@ -21,7 +21,6 @@ //----------------------------------------------------------------------------- #include "platform/platform.h" -#include "platform/event.h" #include "platformWin32/platformWin32.h" #include "platformWin32/winConsole.h" #include "platformWin32/winDirectInput.h" diff --git a/Engine/source/platformX86UNIX/threads/semaphore.cpp b/Engine/source/platformX86UNIX/threads/semaphore.cpp index 64e73454f7..63d7510ecd 100644 --- a/Engine/source/platformX86UNIX/threads/semaphore.cpp +++ b/Engine/source/platformX86UNIX/threads/semaphore.cpp @@ -22,25 +22,30 @@ #include "platformX86UNIX/platformX86UNIX.h" #include "platform/threads/semaphore.h" -// Instead of that mess that was here before, lets use the SDL lib to deal -// with the semaphores. - -#include -#include +#include +#include +#include +#include +#include struct PlatformSemaphore { - SDL_sem *semaphore; + sem_t semaphore; + bool initialized; PlatformSemaphore(S32 initialCount) { - semaphore = SDL_CreateSemaphore(initialCount); - AssertFatal(semaphore, "PlatformSemaphore constructor - Failed to create SDL Semaphore."); + initialized = true; + if (sem_init(&semaphore, 0, initialCount) == -1) { + initialized = false; + AssertFatal(0, "PlatformSemaphore constructor - Failed to create Semaphore."); + } } ~PlatformSemaphore() { - SDL_DestroySemaphore(semaphore); + sem_destroy(&semaphore); + initialized = false; } }; @@ -57,28 +62,37 @@ Semaphore::~Semaphore() bool Semaphore::acquire(bool block, S32 timeoutMS) { - AssertFatal(mData && mData->semaphore, "Semaphore::acquire - Invalid semaphore."); + AssertFatal(mData && mData->initialized, "Semaphore::acquire - Invalid semaphore."); if (block) { + //SDL was removed so I do not now if this still holds true or not with OS calls but my guess is they are used underneath SDL anyway // Semaphore acquiring is different from the MacOS/Win realization because SDL_SemWaitTimeout() with "infinite" timeout can be too heavy on some platforms. // (see "man SDL_SemWaitTimeout(3)" for more info) // "man" states to avoid the use of SDL_SemWaitTimeout at all, but at current stage this looks like a valid and working solution, so keeping it this way. // [bank / Feb-2010] if (timeoutMS == -1) { - if (SDL_SemWait(mData->semaphore) < 0) - AssertFatal(false, "Semaphore::acquie - Wait failed."); + if (sem_wait(&mData->semaphore) < 0) + AssertFatal(false, "Semaphore::acquire - Wait failed."); } else { - if (SDL_SemWaitTimeout(mData->semaphore, timeoutMS) < 0) - AssertFatal(false, "Semaphore::acquie - Wait with timeout failed."); + //convert timeoutMS to timespec + timespec ts; + if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { + AssertFatal(false, "Semaphore::acquire - clock_realtime failed."); + } + ts.tv_sec += timeoutMS / 1000; + ts.tv_nsec += (timeoutMS % 1000) * 1000; + + if (sem_timedwait(&mData->semaphore, &ts) < 0) + AssertFatal(false, "Semaphore::acquire - Wait with timeout failed."); } return (true); } else { - int res = SDL_SemTryWait(mData->semaphore); + int res = sem_trywait(&mData->semaphore); return (res == 0); } } @@ -86,5 +100,5 @@ bool Semaphore::acquire(bool block, S32 timeoutMS) void Semaphore::release() { AssertFatal(mData, "Semaphore::releaseSemaphore - Invalid semaphore."); - SDL_SemPost(mData->semaphore); + sem_post(&mData->semaphore); } diff --git a/Engine/source/platformX86UNIX/x86UNIXProcessControl.cpp b/Engine/source/platformX86UNIX/x86UNIXProcessControl.cpp index bbc1032096..db134ad610 100644 --- a/Engine/source/platformX86UNIX/x86UNIXProcessControl.cpp +++ b/Engine/source/platformX86UNIX/x86UNIXProcessControl.cpp @@ -80,7 +80,10 @@ void Cleanup(bool minimal) } StdConsole::destroy(); + +#ifndef TORQUE_DEDICATED SDL_Quit(); +#endif } //----------------------------------------------------------------------------- diff --git a/Engine/source/platformX86UNIX/x86UNIXRedbook.cpp b/Engine/source/platformX86UNIX/x86UNIXRedbook.cpp index cfed8008d8..12a60f068d 100644 --- a/Engine/source/platformX86UNIX/x86UNIXRedbook.cpp +++ b/Engine/source/platformX86UNIX/x86UNIXRedbook.cpp @@ -20,6 +20,8 @@ // IN THE SOFTWARE. //----------------------------------------------------------------------------- +// Not needed on dedicated (SDL is not not linked against when dedicated) +#ifndef TORQUE_DEDICATED #include "console/console.h" #include "platformX86UNIX/platformX86UNIX.h" #include "platform/platformRedBook.h" @@ -453,3 +455,4 @@ void PollRedbookDevices() } #endif // !defined(__FreeBSD__) } +#endif diff --git a/Engine/source/renderInstance/renderOcclusionMgr.cpp b/Engine/source/renderInstance/renderOcclusionMgr.cpp index 4d9d32bfef..4e9839eb58 100644 --- a/Engine/source/renderInstance/renderOcclusionMgr.cpp +++ b/Engine/source/renderInstance/renderOcclusionMgr.cpp @@ -29,7 +29,11 @@ #include "gfx/gfxDrawUtil.h" #include "gfx/gfxTransformSaver.h" #include "math/util/sphereMesh.h" +#include "materials/materialManager.h" +#include "materials/sceneData.h" +#include "math/util/matrixSet.h" #include "gfx/gfxDebugEvent.h" +#include "materials/materialFeatureTypes.h" IMPLEMENT_CONOBJECT(RenderOcclusionMgr); @@ -48,14 +52,14 @@ bool RenderOcclusionMgr::smDebugRender = false; RenderOcclusionMgr::RenderOcclusionMgr() : RenderBinManager(RenderPassManager::RIT_Occluder, 1.0f, 1.0f) { - mOverrideMat = NULL; mSpherePrimCount = 0; + mMatInstance = NULL; } RenderOcclusionMgr::RenderOcclusionMgr(RenderInstType riType, F32 renderOrder, F32 processAddOrder) : RenderBinManager(riType, renderOrder, processAddOrder) { - mOverrideMat = NULL; + delete mMatInstance; } static const Point3F cubePoints[8] = @@ -72,25 +76,33 @@ static const U32 cubeFaces[6][4] = void RenderOcclusionMgr::init() { - GFXStateBlockDesc d; + delete mMatInstance; + + mMaterial = MATMGR->allocateAndRegister( String::EmptyString ); + mMaterial->mDiffuse[0] = ColorF( 1, 0, 1, 1 ); + mMaterial->mEmissive[0] = true; + mMaterial->mAutoGenerated = true; + + mMatInstance = mMaterial->createMatInstance(); + FeatureSet features = MATMGR->getDefaultFeatures(); + features.removeFeature( MFT_Visibility ); + features.removeFeature( MFT_Fog ); + features.removeFeature( MFT_HDROut ); + mMatInstance->init( features, getGFXVertexFormat() ); + GFXStateBlockDesc d; d.setBlend( false ); d.cullDefined = true; d.cullMode = GFXCullCCW; d.setZReadWrite( true, false ); - - mDebugSB = GFX->createStateBlock(d); - d.setColorWrites( false, false, false, false ); - - mNormalSB = GFX->createStateBlock(d); + mRenderSB = GFX->createStateBlock(d); d.setZReadWrite( false, false ); - mTestSB = GFX->createStateBlock(d); mBoxBuff.set( GFX, 36, GFXBufferTypeStatic ); - GFXVertexPC *verts = mBoxBuff.lock(); + GFXVertexP *verts = mBoxBuff.lock(); U32 vertexIndex = 0; U32 idx; @@ -98,32 +110,26 @@ void RenderOcclusionMgr::init() { idx = cubeFaces[i][0]; verts[vertexIndex].point = cubePoints[idx]; - verts[vertexIndex].color.set( 1,0,1,1 ); vertexIndex++; idx = cubeFaces[i][1]; verts[vertexIndex].point = cubePoints[idx]; - verts[vertexIndex].color.set( 1,0,1,1 ); vertexIndex++; idx = cubeFaces[i][3]; verts[vertexIndex].point = cubePoints[idx]; - verts[vertexIndex].color.set( 1,0,1,1 ); vertexIndex++; idx = cubeFaces[i][1]; verts[vertexIndex].point = cubePoints[idx]; - verts[vertexIndex].color.set( 1,0,1,1 ); vertexIndex++; idx = cubeFaces[i][3]; verts[vertexIndex].point = cubePoints[idx]; - verts[vertexIndex].color.set( 1,0,1,1 ); vertexIndex++; idx = cubeFaces[i][2]; verts[vertexIndex].point = cubePoints[idx]; - verts[vertexIndex].color.set( 1,0,1,1 ); vertexIndex++; } @@ -139,15 +145,12 @@ void RenderOcclusionMgr::init() for ( S32 i = 0; i < mSpherePrimCount; i++ ) { verts[vertexIndex].point = sphereMesh->poly[i].pnt[0]; - verts[vertexIndex].color.set( 1,0,1,1 ); vertexIndex++; verts[vertexIndex].point = sphereMesh->poly[i].pnt[1]; - verts[vertexIndex].color.set( 1,0,1,1 ); vertexIndex++; verts[vertexIndex].point = sphereMesh->poly[i].pnt[2]; - verts[vertexIndex].color.set( 1,0,1,1 ); vertexIndex++; } mSphereBuff.unlock(); @@ -177,62 +180,52 @@ void RenderOcclusionMgr::render( SceneRenderState *state ) if ( !mElementList.size() ) return; + GFXTransformSaver saver; + GFXDEBUGEVENT_SCOPE(RenderOcclusionMgr_Render, ColorI::BLUE); - if ( mNormalSB.isNull() ) + if ( mMatInstance == NULL ) init(); - GFX->disableShaders(); - GFX->setupGenericShaders( GFXDevice::GSColor ); + SceneData sgData; + sgData.init( state ); + // Restore transforms + MatrixSet &matrixSet = getRenderPass()->getMatrixSet(); + matrixSet.restoreSceneViewProjection(); - OccluderRenderInst *firstEl = static_cast(mElementList[0].inst); - - if ( firstEl->isSphere ) - GFX->setVertexBuffer( mSphereBuff ); - else - GFX->setVertexBuffer( mBoxBuff ); - - bool wasSphere = firstEl->isSphere; - + // The material is single pass... just setup once here. + mMatInstance->setupPass( state, sgData ); + U32 primCount; for( U32 i=0; i(mElementList[i].inst); - + OccluderRenderInst *ri = static_cast(mElementList[i].inst); AssertFatal( ri->query != NULL, "RenderOcclusionMgr::render, OcclusionRenderInst has NULL GFXOcclusionQuery" ); - if ( ri->isSphere != wasSphere ) - { - if ( ri->isSphere ) - GFX->setVertexBuffer( mSphereBuff ); - else - GFX->setVertexBuffer( mBoxBuff ); - - wasSphere = ri->isSphere; - } + if ( ri->isSphere ) + { + GFX->setVertexBuffer( mSphereBuff ); + primCount = mSpherePrimCount; + } + else + { + GFX->setVertexBuffer( mBoxBuff ); + primCount = 12; + } - GFX->pushWorldMatrix(); - MatrixF xfm( *ri->orientation ); xfm.setPosition( ri->position ); xfm.scale( ri->scale ); - //GFXTransformSaver saver; - GFX->multWorld( xfm ); + matrixSet.setWorld(xfm); + mMatInstance->setTransforms(matrixSet, state); - if ( smDebugRender ) - GFX->setStateBlock( mDebugSB ); - else - GFX->setStateBlock( mNormalSB ); - - ri->query->begin(); - - if ( wasSphere ) - GFX->drawPrimitive( GFXTriangleList, 0, mSpherePrimCount ); - else - GFX->drawPrimitive( GFXTriangleList, 0, 12 ); + if ( !smDebugRender ) + GFX->setStateBlock( mRenderSB ); + ri->query->begin(); + GFX->drawPrimitive( GFXTriangleList, 0, primCount ); ri->query->end(); if ( ri->query2 ) @@ -240,15 +233,11 @@ void RenderOcclusionMgr::render( SceneRenderState *state ) GFX->setStateBlock( mTestSB ); ri->query2->begin(); - - if ( wasSphere ) - GFX->drawPrimitive( GFXTriangleList, 0, mSpherePrimCount ); - else - GFX->drawPrimitive( GFXTriangleList, 0, 12 ); - + GFX->drawPrimitive( GFXTriangleList, 0, primCount ); ri->query2->end(); } + } - GFX->popWorldMatrix(); - } + // Call setup one more time to end the pass. + mMatInstance->setupPass( state, sgData ); } \ No newline at end of file diff --git a/Engine/source/renderInstance/renderOcclusionMgr.h b/Engine/source/renderInstance/renderOcclusionMgr.h index bcdefdffab..41050c38d2 100644 --- a/Engine/source/renderInstance/renderOcclusionMgr.h +++ b/Engine/source/renderInstance/renderOcclusionMgr.h @@ -26,6 +26,10 @@ #include "renderInstance/renderBinManager.h" #endif +class Material; +class BaseMatInstance; + + //************************************************************************** // RenderOcclusionMgr //************************************************************************** @@ -46,15 +50,17 @@ class RenderOcclusionMgr : public RenderBinManager DECLARE_CONOBJECT(RenderOcclusionMgr); protected: - BaseMatInstance* mOverrideMat; - GFXStateBlockRef mNormalSB; + GFXStateBlockRef mRenderSB; GFXStateBlockRef mTestSB; - - GFXStateBlockRef mDebugSB; + + /// The material for rendering occluders. + SimObjectPtr mMaterial; + BaseMatInstance *mMatInstance; + static bool smDebugRender; - GFXVertexBufferHandle mBoxBuff; - GFXVertexBufferHandle mSphereBuff; + GFXVertexBufferHandle mBoxBuff; + GFXVertexBufferHandle mSphereBuff; U32 mSpherePrimCount; }; diff --git a/Engine/source/scene/reflectionManager.cpp b/Engine/source/scene/reflectionManager.cpp index 7ef64f2407..98eaee1200 100644 --- a/Engine/source/scene/reflectionManager.cpp +++ b/Engine/source/scene/reflectionManager.cpp @@ -236,7 +236,7 @@ GFXTexHandle ReflectionManager::allocRenderTarget( const Point2I &size ) avar("%s() - mReflectTex (line %d)", __FUNCTION__, __LINE__) ); } -GFXTextureObject* ReflectionManager::getRefractTex() +GFXTextureObject* ReflectionManager::getRefractTex( bool forceUpdate ) { GFXTarget *target = GFX->getActiveRenderTarget(); GFXFormat targetFormat = target->getFormat(); @@ -261,7 +261,7 @@ GFXTextureObject* ReflectionManager::getRefractTex() mUpdateRefract = true; } - if ( mUpdateRefract ) + if ( forceUpdate || mUpdateRefract ) { target->resolveTo( mRefractTex ); mUpdateRefract = false; diff --git a/Engine/source/scene/reflectionManager.h b/Engine/source/scene/reflectionManager.h index 3d392af752..1fbd46e0e1 100644 --- a/Engine/source/scene/reflectionManager.h +++ b/Engine/source/scene/reflectionManager.h @@ -101,7 +101,7 @@ class ReflectionManager GFXTexHandle allocRenderTarget( const Point2I &size ); - GFXTextureObject* getRefractTex(); + GFXTextureObject* getRefractTex( bool forceUpdate = false ); BaseMatInstance* getReflectionMaterial( BaseMatInstance *inMat ) const; diff --git a/Engine/source/scene/sceneContainer.cpp b/Engine/source/scene/sceneContainer.cpp index 3643fa5db6..27eabbe6c3 100644 --- a/Engine/source/scene/sceneContainer.cpp +++ b/Engine/source/scene/sceneContainer.cpp @@ -1612,7 +1612,8 @@ DefineEngineFunction( containerRayCast, const char*, "@returns A string containing either null, if nothing was struck, or these fields:\n" "
  • The ID of the object that was struck.
  • " "
  • The x, y, z position that it was struck.
  • " - "
  • The x, y, z of the normal of the face that was struck.
" + "
  • The x, y, z of the normal of the face that was struck.
  • " + "
  • The distance between the start point and the position we hit.
  • " "@ingroup Game") { @@ -1633,9 +1634,9 @@ DefineEngineFunction( containerRayCast, const char*, char *returnBuffer = Con::getReturnBuffer(256); if(ret) { - dSprintf(returnBuffer, 256, "%d %g %g %g %g %g %g", + dSprintf(returnBuffer, 256, "%d %g %g %g %g %g %g %g", ret, rinfo.point.x, rinfo.point.y, rinfo.point.z, - rinfo.normal.x, rinfo.normal.y, rinfo.normal.z); + rinfo.normal.x, rinfo.normal.y, rinfo.normal.z, rinfo.distance); } else { diff --git a/Engine/source/scene/zones/scenePolyhedralZone.cpp b/Engine/source/scene/zones/scenePolyhedralZone.cpp index 2fccd09f6a..232a782147 100644 --- a/Engine/source/scene/zones/scenePolyhedralZone.cpp +++ b/Engine/source/scene/zones/scenePolyhedralZone.cpp @@ -73,7 +73,7 @@ void ScenePolyhedralZone::_updateOrientedWorldBox() if( mIsBox ) Parent::_updateOrientedWorldBox(); else - mOrientedWorldBox.set( getTransform(), Point3F( mObjBox.len_x(), mObjBox.len_y(), mObjBox.len_z() ) ); + mOrientedWorldBox.set( getTransform(), mObjBox.getExtents() * getScale() ); } //----------------------------------------------------------------------------- diff --git a/Engine/source/sfx/sfxDescription.cpp b/Engine/source/sfx/sfxDescription.cpp index 4bf06d6224..df46734b6e 100644 --- a/Engine/source/sfx/sfxDescription.cpp +++ b/Engine/source/sfx/sfxDescription.cpp @@ -508,8 +508,8 @@ void SFXDescription::packData( BitStream *stream ) Parent::packData( stream ); stream->writeFloat( mVolume, 6 ); - stream->writeFloat( mPitch, 6 ); - stream->writeFloat( mPriority, 6 ); + stream->write( mPitch ); + stream->write( mPriority ); stream->writeFlag( mIsLooping ); stream->writeFlag( mFadeLoops ); @@ -576,8 +576,8 @@ void SFXDescription::unpackData( BitStream *stream ) Parent::unpackData( stream ); mVolume = stream->readFloat( 6 ); - mPitch = stream->readFloat( 6 ); - mPriority = stream->readFloat( 6 ); + stream->read( &mPitch ); + stream->read( &mPriority ); mIsLooping = stream->readFlag(); mFadeLoops = stream->readFlag(); diff --git a/Engine/source/sim/actionMap.cpp b/Engine/source/sim/actionMap.cpp index 175ee875b0..125225d99e 100644 --- a/Engine/source/sim/actionMap.cpp +++ b/Engine/source/sim/actionMap.cpp @@ -21,7 +21,6 @@ //----------------------------------------------------------------------------- #include "sim/actionMap.h" -#include "platform/event.h" #include "console/console.h" #include "platform/platform.h" #include "platform/platformInput.h" @@ -29,6 +28,8 @@ #include "core/stream/fileStream.h" #include "math/mMathFn.h" #include "console/engineAPI.h" +#include "math/mQuat.h" +#include "math/mAngAxis.h" #define CONST_E 2.7182818284590452353602874f @@ -175,20 +176,12 @@ static inline bool dIsDecentChar(U8 c) return ((U8(0xa0) <= c) || (( U8(0x21) <= c) && (c <= U8(0x7e))) || ((U8(0x91) <= c) && (c <= U8(0x92)))); } -struct CodeMapping -{ - const char* pDescription; - InputEventType type; - InputObjectInstances code; -}; - struct AsciiMapping { const char* pDescription; U16 asciiCode; }; -extern CodeMapping gVirtualMap[]; extern AsciiMapping gAsciiMap[]; //------------------------------------------------------------------------------ @@ -521,14 +514,21 @@ bool ActionMap::createEventDescriptor(const char* pEventString, EventDescriptor* } } // Didn't find an ascii match. Check the virtual map table - for (U32 j = 0; gVirtualMap[j].code != 0xFFFFFFFF; j++) + //for (U32 j = 0; gVirtualMap[j].code != 0xFFFFFFFF; j++) + //{ + // if (dStricmp(pObjectString, gVirtualMap[j].pDescription) == 0) + // { + // pDescriptor->eventType = gVirtualMap[j].type; + // pDescriptor->eventCode = gVirtualMap[j].code; + // return true; + // } + //} + InputEventManager::VirtualMapData* data = INPUTMGR->findVirtualMap(pObjectString); + if(data) { - if (dStricmp(pObjectString, gVirtualMap[j].pDescription) == 0) - { - pDescriptor->eventType = gVirtualMap[j].type; - pDescriptor->eventCode = gVirtualMap[j].code; - return true; - } + pDescriptor->eventType = data->type; + pDescriptor->eventCode = data->code; + return true; } } return false; @@ -900,7 +900,8 @@ const char* ActionMap::buildActionString( const InputEventInfo* event ) bool ActionMap::getDeviceTypeAndInstance(const char *pDeviceName, U32 &deviceType, U32 &deviceInstance) { U32 offset = 0; - + U32 inputMgrDeviceType = 0; + if (dStrnicmp(pDeviceName, "keyboard", dStrlen("keyboard")) == 0) { deviceType = KeyboardDeviceType; @@ -921,6 +922,10 @@ bool ActionMap::getDeviceTypeAndInstance(const char *pDeviceName, U32 &deviceTyp deviceType = GamepadDeviceType; offset = dStrlen("gamepad"); } + else if(INPUTMGR->isRegisteredDeviceWithAttributes(pDeviceName, inputMgrDeviceType, offset)) + { + deviceType = inputMgrDeviceType; + } else { return false; @@ -964,9 +969,18 @@ bool ActionMap::getDeviceName(const U32 deviceType, const U32 deviceInstance, ch dSprintf(buffer, 16, "gamepad%d", deviceInstance); break; - default: - Con::errorf( "ActionMap::getDeviceName: unknown device type specified, %d (inst: %d)", deviceType, deviceInstance); - return false; + default: + { + const char* name = INPUTMGR->getRegisteredDeviceName(deviceType); + if(!name) + { + Con::errorf( "ActionMap::getDeviceName: unknown device type specified, %d (inst: %d)", deviceType, deviceInstance); + return false; + } + + dSprintf(buffer, 16, "%s%d", name, deviceInstance); + break; + } } return true; @@ -1102,11 +1116,17 @@ bool ActionMap::getKeyString(const U32 action, char* buffer) buffer[1] = '\0'; return true; } - for (U32 i = 0; gVirtualMap[i].code != 0xFFFFFFFF; i++) { - if (gVirtualMap[i].code == action) { - dStrcpy(buffer, gVirtualMap[i].pDescription); - return true; - } + //for (U32 i = 0; gVirtualMap[i].code != 0xFFFFFFFF; i++) { + // if (gVirtualMap[i].code == action) { + // dStrcpy(buffer, gVirtualMap[i].pDescription); + // return true; + // } + //} + const char* desc = INPUTMGR->findVirtualMapDescFromCode(action); + if(desc) + { + dStrcpy(buffer, desc); + return true; } } @@ -1297,7 +1317,7 @@ bool ActionMap::processAction(const InputEventInfo* pEvent) if(Platform::checkKeyboardInputExclusion(pEvent)) return false; - static const char *argv[2]; + static const char *argv[5]; if (pEvent->action == SI_MAKE) { const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, pEvent->modifier, pEvent->objInst); @@ -1390,9 +1410,72 @@ bool ActionMap::processAction(const InputEventInfo* pEvent) Con::execute(2, argv); return true; - } + } + else if ( (pEvent->objType == SI_POS || pEvent->objType == SI_FLOAT || pEvent->objType == SI_ROT || pEvent->objType == SI_INT) + && INPUTMGR->isRegisteredDevice(pEvent->deviceType) + ) + { + const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, + pEvent->modifier, pEvent->objInst); + + if( pNode == NULL ) + return false; + + // Ok, we're all set up, call the function. + argv[0] = pNode->consoleFunction; + S32 argc = 1; + + if (pEvent->objType == SI_INT) + { + // Handle the integer as some sort of motion such as a + // single component to an absolute position + argv[1] = Con::getIntArg( pEvent->iValue ); + argc += 1; + } + else if (pEvent->objType == SI_FLOAT) + { + // Handle float as some sort of motion such as a + // single component to an absolute position + argv[1] = Con::getFloatArg( pEvent->fValue ); + argc += 1; + } + else if (pEvent->objType == SI_POS) + { + // Handle Point3F type position + argv[1] = Con::getFloatArg( pEvent->fValue ); + argv[2] = Con::getFloatArg( pEvent->fValue2 ); + argv[3] = Con::getFloatArg( pEvent->fValue3 ); + + argc += 3; + } + else + { + // Handle rotation (QuatF) + QuatF quat(pEvent->fValue, pEvent->fValue2, pEvent->fValue3, pEvent->fValue4); + AngAxisF aa(quat); + aa.axis.normalize(); + argv[1] = Con::getFloatArg( aa.axis.x ); + argv[2] = Con::getFloatArg( aa.axis.y ); + argv[3] = Con::getFloatArg( aa.axis.z ); + argv[4] = Con::getFloatArg( mRadToDeg(aa.angle) ); + + argc += 4; + } + + if (pNode->object) + { + Con::execute(pNode->object, argc, argv); + } + else + { + Con::execute(argc, argv); + } + + return true; + } else if ( pEvent->deviceType == JoystickDeviceType || pEvent->deviceType == GamepadDeviceType + || INPUTMGR->isRegisteredDevice(pEvent->deviceType) ) { // Joystick events... @@ -1449,6 +1532,49 @@ bool ActionMap::processAction(const InputEventInfo* pEvent) { return checkBreakTable(pEvent); } + else if (pEvent->action == SI_VALUE) + { + if ( (pEvent->objType == SI_FLOAT || pEvent->objType == SI_INT) + && INPUTMGR->isRegisteredDevice(pEvent->deviceType) + ) + { + const Node* pNode = findNode(pEvent->deviceType, pEvent->deviceInst, + pEvent->modifier, pEvent->objInst); + + if( pNode == NULL ) + return false; + + // Ok, we're all set up, call the function. + argv[0] = pNode->consoleFunction; + S32 argc = 1; + + if (pEvent->objType == SI_INT) + { + // Handle the integer as some sort of motion such as a + // single component to an absolute position + argv[1] = Con::getIntArg( pEvent->iValue ); + argc += 1; + } + else if (pEvent->objType == SI_FLOAT) + { + // Handle float as some sort of motion such as a + // single component to an absolute position + argv[1] = Con::getFloatArg( pEvent->fValue ); + argc += 1; + } + + if (pNode->object) + { + Con::execute(pNode->object, argc, argv); + } + else + { + Con::execute(argc, argv); + } + + return true; + } + } return false; } @@ -1998,223 +2124,6 @@ DefineEngineMethod( ActionMap, getDeadZone, const char*, ( const char* device, c } //------------------------------------------------------------------------------ -//-------------------------------------- Key code to string mapping -// TODO: Add most obvious aliases... -// -CodeMapping gVirtualMap[] = -{ - //-------------------------------------- KEYBOARD EVENTS - // - { "backspace", SI_KEY, KEY_BACKSPACE }, - { "tab", SI_KEY, KEY_TAB }, - - { "return", SI_KEY, KEY_RETURN }, - { "enter", SI_KEY, KEY_RETURN }, - - { "shift", SI_KEY, KEY_SHIFT }, - { "ctrl", SI_KEY, KEY_CONTROL }, - { "alt", SI_KEY, KEY_ALT }, - { "pause", SI_KEY, KEY_PAUSE }, - { "capslock", SI_KEY, KEY_CAPSLOCK }, - - { "escape", SI_KEY, KEY_ESCAPE }, - - { "space", SI_KEY, KEY_SPACE }, - { "pagedown", SI_KEY, KEY_PAGE_DOWN }, - { "pageup", SI_KEY, KEY_PAGE_UP }, - { "end", SI_KEY, KEY_END }, - { "home", SI_KEY, KEY_HOME }, - { "left", SI_KEY, KEY_LEFT }, - { "up", SI_KEY, KEY_UP }, - { "right", SI_KEY, KEY_RIGHT }, - { "down", SI_KEY, KEY_DOWN }, - { "print", SI_KEY, KEY_PRINT }, - { "insert", SI_KEY, KEY_INSERT }, - { "delete", SI_KEY, KEY_DELETE }, - { "help", SI_KEY, KEY_HELP }, - - { "win_lwindow", SI_KEY, KEY_WIN_LWINDOW }, - { "win_rwindow", SI_KEY, KEY_WIN_RWINDOW }, - { "win_apps", SI_KEY, KEY_WIN_APPS }, - - { "cmd", SI_KEY, KEY_ALT }, - { "opt", SI_KEY, KEY_MAC_OPT }, - { "lopt", SI_KEY, KEY_MAC_LOPT }, - { "ropt", SI_KEY, KEY_MAC_ROPT }, - - { "numpad0", SI_KEY, KEY_NUMPAD0 }, - { "numpad1", SI_KEY, KEY_NUMPAD1 }, - { "numpad2", SI_KEY, KEY_NUMPAD2 }, - { "numpad3", SI_KEY, KEY_NUMPAD3 }, - { "numpad4", SI_KEY, KEY_NUMPAD4 }, - { "numpad5", SI_KEY, KEY_NUMPAD5 }, - { "numpad6", SI_KEY, KEY_NUMPAD6 }, - { "numpad7", SI_KEY, KEY_NUMPAD7 }, - { "numpad8", SI_KEY, KEY_NUMPAD8 }, - { "numpad9", SI_KEY, KEY_NUMPAD9 }, - { "numpadmult", SI_KEY, KEY_MULTIPLY }, - { "numpadadd", SI_KEY, KEY_ADD }, - { "numpadsep", SI_KEY, KEY_SEPARATOR }, - { "numpadminus", SI_KEY, KEY_SUBTRACT }, - { "numpaddecimal", SI_KEY, KEY_DECIMAL }, - { "numpaddivide", SI_KEY, KEY_DIVIDE }, - { "numpadenter", SI_KEY, KEY_NUMPADENTER }, - - { "f1", SI_KEY, KEY_F1 }, - { "f2", SI_KEY, KEY_F2 }, - { "f3", SI_KEY, KEY_F3 }, - { "f4", SI_KEY, KEY_F4 }, - { "f5", SI_KEY, KEY_F5 }, - { "f6", SI_KEY, KEY_F6 }, - { "f7", SI_KEY, KEY_F7 }, - { "f8", SI_KEY, KEY_F8 }, - { "f9", SI_KEY, KEY_F9 }, - { "f10", SI_KEY, KEY_F10 }, - { "f11", SI_KEY, KEY_F11 }, - { "f12", SI_KEY, KEY_F12 }, - { "f13", SI_KEY, KEY_F13 }, - { "f14", SI_KEY, KEY_F14 }, - { "f15", SI_KEY, KEY_F15 }, - { "f16", SI_KEY, KEY_F16 }, - { "f17", SI_KEY, KEY_F17 }, - { "f18", SI_KEY, KEY_F18 }, - { "f19", SI_KEY, KEY_F19 }, - { "f20", SI_KEY, KEY_F20 }, - { "f21", SI_KEY, KEY_F21 }, - { "f22", SI_KEY, KEY_F22 }, - { "f23", SI_KEY, KEY_F23 }, - { "f24", SI_KEY, KEY_F24 }, - - { "numlock", SI_KEY, KEY_NUMLOCK }, - { "scrolllock", SI_KEY, KEY_SCROLLLOCK }, - - { "lshift", SI_KEY, KEY_LSHIFT }, - { "rshift", SI_KEY, KEY_RSHIFT }, - { "lcontrol", SI_KEY, KEY_LCONTROL }, - { "rcontrol", SI_KEY, KEY_RCONTROL }, - { "lalt", SI_KEY, KEY_LALT }, - { "ralt", SI_KEY, KEY_RALT }, - { "tilde", SI_KEY, KEY_TILDE }, - - { "minus", SI_KEY, KEY_MINUS }, - { "equals", SI_KEY, KEY_EQUALS }, - { "lbracket", SI_KEY, KEY_LBRACKET }, - { "rbracket", SI_KEY, KEY_RBRACKET }, - { "backslash", SI_KEY, KEY_BACKSLASH }, - { "semicolon", SI_KEY, KEY_SEMICOLON }, - { "apostrophe", SI_KEY, KEY_APOSTROPHE }, - { "comma", SI_KEY, KEY_COMMA }, - { "period", SI_KEY, KEY_PERIOD }, - { "slash", SI_KEY, KEY_SLASH }, - { "lessthan", SI_KEY, KEY_OEM_102 }, - - //-------------------------------------- BUTTON EVENTS - // Joystick/Mouse buttons - { "button0", SI_BUTTON, KEY_BUTTON0 }, - { "button1", SI_BUTTON, KEY_BUTTON1 }, - { "button2", SI_BUTTON, KEY_BUTTON2 }, - { "button3", SI_BUTTON, KEY_BUTTON3 }, - { "button4", SI_BUTTON, KEY_BUTTON4 }, - { "button5", SI_BUTTON, KEY_BUTTON5 }, - { "button6", SI_BUTTON, KEY_BUTTON6 }, - { "button7", SI_BUTTON, KEY_BUTTON7 }, - { "button8", SI_BUTTON, KEY_BUTTON8 }, - { "button9", SI_BUTTON, KEY_BUTTON9 }, - { "button10", SI_BUTTON, KEY_BUTTON10 }, - { "button11", SI_BUTTON, KEY_BUTTON11 }, - { "button12", SI_BUTTON, KEY_BUTTON12 }, - { "button13", SI_BUTTON, KEY_BUTTON13 }, - { "button14", SI_BUTTON, KEY_BUTTON14 }, - { "button15", SI_BUTTON, KEY_BUTTON15 }, - { "button16", SI_BUTTON, KEY_BUTTON16 }, - { "button17", SI_BUTTON, KEY_BUTTON17 }, - { "button18", SI_BUTTON, KEY_BUTTON18 }, - { "button19", SI_BUTTON, KEY_BUTTON19 }, - { "button20", SI_BUTTON, KEY_BUTTON20 }, - { "button21", SI_BUTTON, KEY_BUTTON21 }, - { "button22", SI_BUTTON, KEY_BUTTON22 }, - { "button23", SI_BUTTON, KEY_BUTTON23 }, - { "button24", SI_BUTTON, KEY_BUTTON24 }, - { "button25", SI_BUTTON, KEY_BUTTON25 }, - { "button26", SI_BUTTON, KEY_BUTTON26 }, - { "button27", SI_BUTTON, KEY_BUTTON27 }, - { "button28", SI_BUTTON, KEY_BUTTON28 }, - { "button29", SI_BUTTON, KEY_BUTTON29 }, - { "button30", SI_BUTTON, KEY_BUTTON30 }, - { "button31", SI_BUTTON, KEY_BUTTON31 }, - - //-------------------------------------- MOVE EVENTS - // Mouse/Joystick axes: - { "xaxis", SI_AXIS, SI_XAXIS }, - { "yaxis", SI_AXIS, SI_YAXIS }, - { "zaxis", SI_AXIS, SI_ZAXIS }, - { "rxaxis", SI_AXIS, SI_RXAXIS }, - { "ryaxis", SI_AXIS, SI_RYAXIS }, - { "rzaxis", SI_AXIS, SI_RZAXIS }, - { "slider", SI_AXIS, SI_SLIDER }, - - //-------------------------------------- POV EVENTS - // Joystick POV: - { "xpov", SI_POV, SI_XPOV }, - { "ypov", SI_POV, SI_YPOV }, - { "upov", SI_POV, SI_UPOV }, - { "dpov", SI_POV, SI_DPOV }, - { "lpov", SI_POV, SI_LPOV }, - { "rpov", SI_POV, SI_RPOV }, - { "xpov2", SI_POV, SI_XPOV2 }, - { "ypov2", SI_POV, SI_YPOV2 }, - { "upov2", SI_POV, SI_UPOV2 }, - { "dpov2", SI_POV, SI_DPOV2 }, - { "lpov2", SI_POV, SI_LPOV2 }, - { "rpov2", SI_POV, SI_RPOV2 }, - -#if defined( TORQUE_OS_WIN32 ) || defined( TORQUE_OS_XENON ) - //-------------------------------------- XINPUT EVENTS - // Controller connect / disconnect: - { "connect", SI_BUTTON, XI_CONNECT }, - - // L & R Thumbsticks: - { "thumblx", SI_AXIS, XI_THUMBLX }, - { "thumbly", SI_AXIS, XI_THUMBLY }, - { "thumbrx", SI_AXIS, XI_THUMBRX }, - { "thumbry", SI_AXIS, XI_THUMBRY }, - - // L & R Triggers: - { "triggerl", SI_AXIS, XI_LEFT_TRIGGER }, - { "triggerr", SI_AXIS, XI_RIGHT_TRIGGER }, - - // DPAD Buttons: - { "dpadu", SI_BUTTON, SI_UPOV }, - { "dpadd", SI_BUTTON, SI_DPOV }, - { "dpadl", SI_BUTTON, SI_LPOV }, - { "dpadr", SI_BUTTON, SI_RPOV }, - - // START & BACK Buttons: - { "btn_start", SI_BUTTON, XI_START }, - { "btn_back", SI_BUTTON, XI_BACK }, - - // L & R Thumbstick Buttons: - { "btn_lt", SI_BUTTON, XI_LEFT_THUMB }, - { "btn_rt", SI_BUTTON, XI_RIGHT_THUMB }, - - // L & R Shoulder Buttons: - { "btn_l", SI_BUTTON, XI_LEFT_SHOULDER }, - { "btn_r", SI_BUTTON, XI_RIGHT_SHOULDER }, - - // Primary buttons: - { "btn_a", SI_BUTTON, XI_A }, - { "btn_b", SI_BUTTON, XI_B }, - { "btn_x", SI_BUTTON, XI_X }, - { "btn_y", SI_BUTTON, XI_Y }, -#endif - - //-------------------------------------- MISCELLANEOUS EVENTS - // - - { "anykey", SI_KEY, KEY_ANYKEY }, - { "nomatch", SI_UNKNOWN, (InputObjectInstances)0xFFFFFFFF } -}; - AsciiMapping gAsciiMap[] = { //--- KEYBOARD EVENTS diff --git a/Engine/source/sim/netConnection.h b/Engine/source/sim/netConnection.h index 914c112740..b220d187ca 100644 --- a/Engine/source/sim/netConnection.h +++ b/Engine/source/sim/netConnection.h @@ -32,9 +32,6 @@ #ifndef _NETSTRINGTABLE_H_ #include "sim/netStringTable.h" #endif -#ifndef _EVENT_H_ -#include "platform/event.h" -#endif #ifndef _DNET_H_ #include "core/dnet.h" #endif diff --git a/Engine/source/sim/netEvent.cpp b/Engine/source/sim/netEvent.cpp index e73a7ed4a7..07b90f6cac 100644 --- a/Engine/source/sim/netEvent.cpp +++ b/Engine/source/sim/netEvent.cpp @@ -243,7 +243,7 @@ void NetConnection::eventWritePacket(BitStream *bstream, PacketNotify *notify) packQueueTail->mNextEvent = ev; packQueueTail = ev; if(!bstream->writeFlag(ev->mSeqCount == prevSeq + 1)) - bstream->writeInt(ev->mSeqCount, 7); + bstream->writeInt(ev->mSeqCount & 0x7F, 7); prevSeq = ev->mSeqCount; diff --git a/Engine/source/sim/netInterface.cpp b/Engine/source/sim/netInterface.cpp index 2ec7cbff7c..226bd0ca31 100644 --- a/Engine/source/sim/netInterface.cpp +++ b/Engine/source/sim/netInterface.cpp @@ -21,7 +21,6 @@ //----------------------------------------------------------------------------- #include "platform/platform.h" -#include "platform/event.h" #include "sim/netConnection.h" #include "sim/netInterface.h" #include "core/stream/bitStream.h" diff --git a/Engine/source/terrain/terrCollision.cpp b/Engine/source/terrain/terrCollision.cpp index 9d6f68ee8f..5ff849f4d9 100644 --- a/Engine/source/terrain/terrCollision.cpp +++ b/Engine/source/terrain/terrCollision.cpp @@ -616,6 +616,7 @@ bool TerrainBlock::castRay(const Point3F &start, const Point3F &end, RayInfo *in // Set intersection point. info->setContactPoint( start, end ); + getTransform().mulP( info->point ); // transform to world coordinates for getGridPos // Set material at contact point. Point2I gridPos = getGridPos( info->point ); diff --git a/Engine/source/terrain/terrMaterial.cpp b/Engine/source/terrain/terrMaterial.cpp index ee166f8c86..86501c640c 100644 --- a/Engine/source/terrain/terrMaterial.cpp +++ b/Engine/source/terrain/terrMaterial.cpp @@ -23,6 +23,7 @@ #include "platform/platform.h" #include "terrain/terrMaterial.h" #include "console/consoleTypes.h" +#include "gfx/gfxTextureManager.h" #include "gfx/bitmap/gBitmap.h" @@ -152,9 +153,9 @@ TerrainMaterial* TerrainMaterial::findOrCreate( const char *nameOrPath ) // fallback here just in case it gets "lost". mat = new TerrainMaterial(); mat->setInternalName( "warning_material" ); - mat->mDiffuseMap = "core/art/warnMat.png"; + mat->mDiffuseMap = GFXTextureManager::getWarningTexturePath(); mat->mDiffuseSize = 500; - mat->mDetailMap = "core/art/warnMat.png"; + mat->mDetailMap = GFXTextureManager::getWarningTexturePath(); mat->mDetailSize = 5; mat->registerObject(); diff --git a/Engine/source/ts/collada/colladaAppMesh.cpp b/Engine/source/ts/collada/colladaAppMesh.cpp index f9c178c61c..1b58140e5c 100644 --- a/Engine/source/ts/collada/colladaAppMesh.cpp +++ b/Engine/source/ts/collada/colladaAppMesh.cpp @@ -463,6 +463,11 @@ S32 ColladaAppMesh::addMaterial(const char* symbol) } } } + else + { + // No Collada material is present for this symbol, so just create an empty one + appMaterials.push_back(new ColladaAppMaterial(symbol)); + } // Add this symbol to the bound list for the mesh boundMaterials.insert(StringTable->insert(symbol), matIndex); diff --git a/Engine/source/ts/tsMesh.cpp b/Engine/source/ts/tsMesh.cpp index 4249efee1c..2a673f624e 100644 --- a/Engine/source/ts/tsMesh.cpp +++ b/Engine/source/ts/tsMesh.cpp @@ -322,9 +322,11 @@ bool TSMesh::buildPolyList( S32 frame, AbstractPolyList *polyList, U32 &surfaceK } else { - base = polyList->addPoint( mVertexData[firstVert].vert() ); + base = polyList->addPointAndNormal( mVertexData[firstVert].vert(), mVertexData[firstVert].normal() ); for ( i = 1; i < vertsPerFrame; i++ ) - polyList->addPoint( mVertexData[ i + firstVert ].vert() ); + { + polyList->addPointAndNormal( mVertexData[ i + firstVert ].vert(), mVertexData[ i + firstVert ].normal() ); + } } } else @@ -348,9 +350,9 @@ bool TSMesh::buildPolyList( S32 frame, AbstractPolyList *polyList, U32 &surfaceK } else { - base = polyList->addPoint( verts[firstVert] ); + base = polyList->addPointAndNormal( verts[firstVert], norms[firstVert] ); for ( i = 1; i < vertsPerFrame; i++ ) - polyList->addPoint( verts[ i + firstVert ] ); + polyList->addPointAndNormal( verts[ i + firstVert ], norms[ i + firstVert ] ); } } } @@ -681,8 +683,8 @@ bool TSMesh::castRay( S32 frame, const Point3F & start, const Point3F & end, Ray pfound = (bool*) ((dsize_t)pfound ^ (dsize_t)&tmpFound ^ (dsize_t)&found); } - bool noCollision = num * endDen * sgn < endNum * den * sgn && num * startDen * sgn < startNum * den * sgn; - if (num * *pden * sgn < *pnum * den * sgn && !noCollision) + bool noCollision = num * endDen < endNum * den && num * startDen < startNum * den; + if (num * *pden < *pnum * den && !noCollision) { *pnum = num; *pden = den; @@ -761,11 +763,11 @@ bool TSMesh::castRayRendered( S32 frame, const Point3F & start, const Point3F & S32 firstVert = vertsPerFrame * frame; - bool found = false; - F32 best_t = F32_MAX; + bool found = false; + F32 best_t = F32_MAX; U32 bestIdx0 = 0, bestIdx1 = 0, bestIdx2 = 0; BaseMatInstance* bestMaterial = NULL; - Point3F dir = end - start; + Point3F dir = end - start; for ( S32 i = 0; i < primitives.size(); i++ ) { @@ -788,22 +790,22 @@ bool TSMesh::castRayRendered( S32 frame, const Point3F & start, const Point3F & idx1 = indices[drawStart + j + 1]; idx2 = indices[drawStart + j + 2]; - F32 cur_t = 0; - Point2F b; + F32 cur_t = 0; + Point2F b; - if(castRayTriangle(start, dir, mVertexData[firstVert + idx0].vert(), + if(castRayTriangle(start, dir, mVertexData[firstVert + idx0].vert(), mVertexData[firstVert + idx1].vert(), mVertexData[firstVert + idx2].vert(), cur_t, b)) - { - if(cur_t < best_t) - { - best_t = cur_t; + { + if(cur_t < best_t) + { + best_t = cur_t; bestIdx0 = idx0; bestIdx1 = idx1; bestIdx2 = idx2; bestMaterial = material; - found = true; - } - } + found = true; + } + } } } else @@ -822,22 +824,22 @@ bool TSMesh::castRayRendered( S32 frame, const Point3F & start, const Point3F & if ( idx0 == idx1 || idx0 == idx2 || idx1 == idx2 ) continue; - F32 cur_t = 0; - Point2F b; + F32 cur_t = 0; + Point2F b; - if(castRayTriangle(start, dir, mVertexData[firstVert + idx0].vert(), + if(castRayTriangle(start, dir, mVertexData[firstVert + idx0].vert(), mVertexData[firstVert + idx1].vert(), mVertexData[firstVert + idx2].vert(), cur_t, b)) - { - if(cur_t < best_t) - { - best_t = cur_t; + { + if(cur_t < best_t) + { + best_t = cur_t; bestIdx0 = firstVert + idx0; bestIdx1 = firstVert + idx1; bestIdx2 = firstVert + idx2; bestMaterial = material; - found = true; - } - } + found = true; + } + } } } } @@ -1924,12 +1926,12 @@ TSMesh* TSMesh::assembleMesh( U32 meshType, bool skip ) } void TSMesh::convertToTris( const TSDrawPrimitive *primitivesIn, - const S32 *indicesIn, - S32 numPrimIn, - S32 &numPrimOut, - S32 &numIndicesOut, - TSDrawPrimitive *primitivesOut, - S32 *indicesOut ) const + const S32 *indicesIn, + S32 numPrimIn, + S32 &numPrimOut, + S32 &numIndicesOut, + TSDrawPrimitive *primitivesOut, + S32 *indicesOut ) const { S32 prevMaterial = -99999; TSDrawPrimitive * newDraw = NULL; @@ -2027,12 +2029,12 @@ void unwindStrip( const S32 * indices, S32 numElements, Vector &triIndices } void TSMesh::convertToSingleStrip( const TSDrawPrimitive *primitivesIn, - const S32 *indicesIn, - S32 numPrimIn, - S32 &numPrimOut, - S32 &numIndicesOut, - TSDrawPrimitive *primitivesOut, - S32 *indicesOut ) const + const S32 *indicesIn, + S32 numPrimIn, + S32 &numPrimOut, + S32 &numIndicesOut, + TSDrawPrimitive *primitivesOut, + S32 *indicesOut ) const { S32 prevMaterial = -99999; TSDrawPrimitive * newDraw = NULL; @@ -2174,12 +2176,12 @@ void TSMesh::convertToSingleStrip( const TSDrawPrimitive *primitivesIn, // this method does none of the converting that the above methods do, except that small strips are converted // to triangle lists... void TSMesh::leaveAsMultipleStrips( const TSDrawPrimitive *primitivesIn, - const S32 *indicesIn, - S32 numPrimIn, - S32 &numPrimOut, - S32 &numIndicesOut, - TSDrawPrimitive *primitivesOut, - S32 *indicesOut ) const + const S32 *indicesIn, + S32 numPrimIn, + S32 &numPrimOut, + S32 &numIndicesOut, + TSDrawPrimitive *primitivesOut, + S32 *indicesOut ) const { S32 prevMaterial = -99999; TSDrawPrimitive * newDraw = NULL; diff --git a/Engine/source/ts/tsShapeInstance.cpp b/Engine/source/ts/tsShapeInstance.cpp index beb1f7e989..a7cebb027d 100644 --- a/Engine/source/ts/tsShapeInstance.cpp +++ b/Engine/source/ts/tsShapeInstance.cpp @@ -194,7 +194,7 @@ void TSShapeInstance::buildInstanceData(TSShape * _shape, bool loadMaterials) animateSubtrees(); // Construct billboards if not done already - if ( loadMaterials && mShapeResource ) + if ( loadMaterials && mShapeResource && GFXDevice::devicePresent() ) mShape->setupBillboardDetails( mShapeResource.getPath().getFullPath() ); } diff --git a/Engine/source/ts/tsThread.cpp b/Engine/source/ts/tsThread.cpp index 7cb543c9e5..2b6b7c4bcd 100644 --- a/Engine/source/ts/tsThread.cpp +++ b/Engine/source/ts/tsThread.cpp @@ -286,13 +286,14 @@ void TSThread::activateTriggers(F32 a, F32 b) S32 bIndex = numTriggers+firstTrigger; // initialized to handle case where pos past all triggers for (i=firstTrigger; itriggers[i].pos; // is a between this trigger and previous one... - if (a>lastPos && a<=shape->triggers[i].pos) + if (a>lastPos && a<=pTrigger) aIndex = i; // is b between this trigger and previous one... - if (b>lastPos && b<=shape->triggers[i].pos) + if (b>lastPos && b<=pTrigger) bIndex = i; - lastPos = shape->triggers[i].pos; + lastPos = pTrigger; } // activate triggers between aIndex and bIndex (depends on direction) @@ -578,16 +579,17 @@ void TSShapeInstance::transitionToSequence(TSThread * thread, S32 seq, F32 pos, setDirty(AllDirtyMask); mGroundThread = NULL; - if (mScaleCurrentlyAnimated && !thread->getSequence()->animatesScale()) + const TSShape::Sequence* mSequence = thread->getSequence(); + if (mScaleCurrentlyAnimated && !mSequence->animatesScale()) checkScaleCurrentlyAnimated(); - else if (!mScaleCurrentlyAnimated && thread->getSequence()->animatesScale()) + else if (!mScaleCurrentlyAnimated && mSequence->animatesScale()) mScaleCurrentlyAnimated=true; mTransitionRotationNodes.overlap(thread->transitionData.oldRotationNodes); - mTransitionRotationNodes.overlap(thread->getSequence()->rotationMatters); + mTransitionRotationNodes.overlap(mSequence->rotationMatters); mTransitionTranslationNodes.overlap(thread->transitionData.oldTranslationNodes); - mTransitionTranslationNodes.overlap(thread->getSequence()->translationMatters); + mTransitionTranslationNodes.overlap(mSequence->translationMatters); mTransitionScaleNodes.overlap(thread->transitionData.oldScaleNodes); mTransitionScaleNodes.overlap(thread->getSequence()->scaleMatters); @@ -620,8 +622,8 @@ void TSShapeInstance::clearTransition(TSThread * thread) S32 i; if (mTransitionThreads.size() != 0) { for (i=0; i::evaluate( F32 t ) } } - AssertFatal( i >= 0 && i < mCount, "CatmullRom::evaluate - Got bad index!" ); + AssertFatal( i < mCount, "CatmullRom::evaluate - Got bad index!" ); F32 t0 = mTimes[i]; F32 t1 = mTimes[i+1]; diff --git a/Engine/source/windowManager/platformInterface.cpp b/Engine/source/windowManager/platformInterface.cpp index 821c6c60d9..ff34d37db1 100644 --- a/Engine/source/windowManager/platformInterface.cpp +++ b/Engine/source/windowManager/platformInterface.cpp @@ -21,7 +21,6 @@ //----------------------------------------------------------------------------- #include "platform/platform.h" -#include "platform/event.h" #include "windowManager/platformWindowMgr.h" #include "gfx/gfxInit.h" #include "gfx/gfxDevice.h" diff --git a/Engine/source/windowManager/win32/win32SplashScreen.cpp b/Engine/source/windowManager/win32/win32SplashScreen.cpp index a63f97b19d..83189dac36 100644 --- a/Engine/source/windowManager/win32/win32SplashScreen.cpp +++ b/Engine/source/windowManager/win32/win32SplashScreen.cpp @@ -22,6 +22,7 @@ #define _WIN32_WINNT 0x0500 #include +#include #include "platform/platform.h" #include "console/console.h" @@ -120,12 +121,20 @@ void CloseSplashWindow(HINSTANCE hinst) } -bool Platform::displaySplashWindow() +bool Platform::displaySplashWindow( String path ) { + if(path.isEmpty()) + return false; - gSplashImage = (HBITMAP) ::LoadImage(0, L"art\\gui\\splash.bmp", +#ifdef UNICODE + const UTF16 *lFileName = path.utf16(); +#else + const UTF8 *lFileName = path.c_str(); +#endif + + gSplashImage = (HBITMAP) ::LoadImage(0, lFileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); - + if (!gSplashImage) return false; diff --git a/Engine/source/windowManager/win32/winDispatch.cpp b/Engine/source/windowManager/win32/winDispatch.cpp index c2440b4274..f49010f0ea 100644 --- a/Engine/source/windowManager/win32/winDispatch.cpp +++ b/Engine/source/windowManager/win32/winDispatch.cpp @@ -31,7 +31,6 @@ #include -#include "platform/event.h" #include "platform/platformInput.h" #include "windowManager/win32/winDispatch.h" #include "windowManager/win32/win32Window.h" diff --git a/Engine/source/windowManager/windowInputGenerator.cpp b/Engine/source/windowManager/windowInputGenerator.cpp index df4a6c9062..ab446382f3 100644 --- a/Engine/source/windowManager/windowInputGenerator.cpp +++ b/Engine/source/windowManager/windowInputGenerator.cpp @@ -310,7 +310,7 @@ void WindowInputGenerator::handleKeyboard( WindowId did, U32 modifier, U32 actio //----------------------------------------------------------------------------- // Raw input //----------------------------------------------------------------------------- -void WindowInputGenerator::handleInputEvent( U32 deviceInst,F32 fValue, U16 deviceType, U16 objType, U16 ascii, U16 objInst, U8 action, U8 modifier ) +void WindowInputGenerator::handleInputEvent( U32 deviceInst, F32 fValue, F32 fValue2, F32 fValue3, F32 fValue4, S32 iValue, U16 deviceType, U16 objType, U16 ascii, U16 objInst, U8 action, U8 modifier ) { // Skip it if we don't have focus. if(!mInputController || !mFocused) @@ -320,6 +320,10 @@ void WindowInputGenerator::handleInputEvent( U32 deviceInst,F32 fValue, U16 devi InputEventInfo event; event.deviceInst = deviceInst; event.fValue = fValue; + event.fValue2 = fValue2; + event.fValue3 = fValue3; + event.fValue4 = fValue4; + event.iValue = iValue; event.deviceType = (InputDeviceTypes)deviceType; event.objType = (InputEventType)objType; event.ascii = ascii; diff --git a/Engine/source/windowManager/windowInputGenerator.h b/Engine/source/windowManager/windowInputGenerator.h index e8a397b1fd..91fff0c613 100644 --- a/Engine/source/windowManager/windowInputGenerator.h +++ b/Engine/source/windowManager/windowInputGenerator.h @@ -58,7 +58,7 @@ class WindowInputGenerator void handleKeyboard (WindowId did, U32 modifier, U32 action, U16 key); void handleCharInput (WindowId did, U32 modifier, U16 key); void handleAppEvent (WindowId did, S32 event); - void handleInputEvent (U32 deviceInst,F32 fValue, U16 deviceType, U16 objType, U16 ascii, U16 objInst, U8 action, U8 modifier); + void handleInputEvent (U32 deviceInst, F32 fValue, F32 fValue2, F32 fValue3, F32 fValue4, S32 iValue, U16 deviceType, U16 objType, U16 ascii, U16 objInst, U8 action, U8 modifier); void generateInputEvent( InputEventInfo &inputEvent ); diff --git a/QtCore4.dll b/QtCore4.dll deleted file mode 100644 index 1c51406227..0000000000 Binary files a/QtCore4.dll and /dev/null differ diff --git a/QtGui4.dll b/QtGui4.dll deleted file mode 100644 index fc41a5ba96..0000000000 Binary files a/QtGui4.dll and /dev/null differ diff --git a/QtNetwork4.dll b/QtNetwork4.dll deleted file mode 100644 index 16b097fb56..0000000000 Binary files a/QtNetwork4.dll and /dev/null differ diff --git a/QtXml4.dll b/QtXml4.dll deleted file mode 100644 index 80dc9aa644..0000000000 Binary files a/QtXml4.dll and /dev/null differ diff --git a/README.md b/README.md index eab875d23a..1fafadc712 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,105 @@ -Torque3D -======== +Torque 3D v2.0 +============== MIT Licensed Open Source version of [Torque 3D](http://www.garagegames.com/products/torque-3d) from [GarageGames](http://www.garagegames.com) More Information ---------------- +* Torque 3D [main repository](https://github.com/GarageGames/Torque3D) * Documentation is in the [Torque3D-Documentation](https://github.com/GarageGames/Torque3D-Documentation) GitHub repo. +* Project Manager is in the [Torque3D-ProjectManager](https://github.com/GarageGames/Torque3D-ProjectManager) GitHub repo. * T3D [Beginner's Forum](http://www.garagegames.com/community/forums/73) * T3D [Professional Forum](http://www.garagegames.com/community/forums/63) +* Torque 3D [FPS Tutorial](http://www.garagegames.com/products/torque-3d/fps#/1-setup/1) +* GarageGames [Store](http://www.garagegames.com/products) * GarageGames [Professional Services](http://services.garagegames.com/) +Creating a New Project Based on a Template +------------------------------------------ + +The templates included with Torque 3D provide a starting point for your project. Once we have created our own project based on a template we may then compile an executable and begin work on our game. The following templates are included in this version of Torque 3D: + +* Empty +* Empty PhysX +* Full +* Full PhysX + +### Using PhysX ### + +If you plan on creating a project based on a template that uses PhysX you will first need to have the PhysX SDK intalled on your computer. Without the PhysX SDK in place the project generation step will fail when using either the *Project Manager* or manual project generation methods. + +PhysX SDK version 2.8.4.6 is required for Torque 3D's PhysX templates. The following steps are used to install this SDK: + +1. In a web browser, go to the [NVidia Support Center](http://supportcenteronline.com/ics/support/default.asp?deptID=1949) +2. If you do not have an account, you will need to register with them to have the support staff create an account for you. +3. If you have an account, login. +4. On the middle of the page, on the right, click on Downloads. +5. On the far right column, under Old downloads, click More. +6. Download the Windows 2.8.4.6 version. +7. Run the installer and follow the steps to install it in the default location. +8. Depending on your operating system version, you may need to reboot after the installation. + +### Using the Project Manager to Create a Project ### + +The *Project Manager* may be used to create a new game project based on one of the templates that are included with Torque 3D. If you are using Torque 3D directly from the [GitHub](https://github.com/GarageGames/Torque3D) repository then you will need to get the *Project Manager* from the [Torque3D-ProjectManager](https://github.com/GarageGames/Torque3D-ProjectManager) repo. + +The following steps use the *Project Manager* to create a new project: + +1. Run the *Project Manager*. +2. Click the *New Project* button. +3. Choose a template from the drop down on the right. +4. Give the project a name. +5. Click the *Create* button to create the project. This will open a new dialog window that shows the progress. +6. When it finishes, click the *Finished* button. +7. You may click on the *Open Folder* button to go to the project's directory. + +### Manually Creating a Project ### + +We may also manually create a project based on a template. The following steps outline how to do this: + +1. Open the *Templates* directory. +2. Right-click on the template you would like to use and choose *Copy*. +3. Go to the *My Projects* directory and paste the template there. +4. Rename the pasted template to the name of your project/game. +5. Go into your project's *game* directory and rename all executables, DLL files and the .torsion file (and maybe .torsion.opt) from the template name to that of your project (these files may not be present at this time). +6. Open the .torsion file in a text editor and replace all references to the template's name with that of your project (you only need to do this if you plan on using Torsion). You will need to also do this with the .torsion.opt if it exists. +7. Open you project's *source/torqueConfig.h* file in a text editor and change the `TORQUE_APP_NAME` define to the name of your project. +8. In your project's *buildFiles/config* directory open each .conf file and find each reference to the template's name and replace it with the name of your project. +9. Open your project's *game/main.cs* file in a text editor and change the `$appName` assignment to the name of your project. +10. Go to your project's directory and double click on the *generateProjects.bat* to create your project's solution files. + +Compiling Torque 3D (Windows) +----------------------------- +If this is the first time you will compile Torque 3D, or if you have added or removed any files to either the standard Torque 3D *Engine/source* directory or your project's *source* directory, you will need to run your project's *generateProjects.bat* file. This will rebuild your project's solution and project files. Now follow these steps to compile Torque 3D: + +1. Navigate to your project's *buildFiles/VisualStudio 2010* directory (or the *2008* directory if that is the version of Visual Studio you are using). +2. Double click on your project's .sln file. This will open Visual Studio. +3. When Visual Studio has fully loaded, press `F7` to start compiling your project. + +Compiling Torque 3D (Linux) +----------------------------- +This version of Torque 3D supports being run as a dedicated server under Linux. As with a Windows build you will need to run your project's *generateProjects.command* file to properly generate the required make file. + +Prior to compiling Torque 3D under Linux, you will need to make sure you have the appropriate libraries and tools installed. The exact packages will depend on which Linux distribution you are using. For example, under Ubuntu you will need: + +* build-essential +* nasm +* git +* php5-cli +* libsdl-dev +* libogg-dev + +With everything in place you may now follow these steps to compile Torque 3D: + +1. Change to you project's *buildFiles/Make_Ded* directory. +2. Enter the `make clean` command. +3. Enter the either the `make debug` or `make release` command depending on the type of build you wish to make. +4. Go to your project's *game* directory. +5. To start your game enter the following command (we'll use the name *MyGame* as the example project name): + `./MyGame -dedicated -mission "levels/Empty Terrain.mis"` + where the argument after the `-mission` switch is the path to the mission to load. + License ------- diff --git a/Templates/Empty PhysX/buildFiles/config/project.conf b/Templates/Empty PhysX/buildFiles/config/project.conf index b6c4bbe63a..a8ea8fa1f8 100644 --- a/Templates/Empty PhysX/buildFiles/config/project.conf +++ b/Templates/Empty PhysX/buildFiles/config/project.conf @@ -6,6 +6,11 @@ // a racing game. $TORQUE_HIFI_NET = false; +// Set this to true to enable the ExtendedMove class. This +// allows the passing of absolute position and rotation input +// device information from the client to the server. +$TORQUE_EXTENDED_MOVE = false; + // Configure Torque 3D Torque3D::beginConfig( "win32", "Empty PhysX" ); diff --git a/Templates/Empty PhysX/game/Empty PhysX.dll b/Templates/Empty PhysX/game/Empty PhysX.dll deleted file mode 100644 index 22f540c0be..0000000000 Binary files a/Templates/Empty PhysX/game/Empty PhysX.dll and /dev/null differ diff --git a/Templates/Empty PhysX/game/Empty PhysX.exe b/Templates/Empty PhysX/game/Empty PhysX.exe deleted file mode 100644 index 65acee6d34..0000000000 Binary files a/Templates/Empty PhysX/game/Empty PhysX.exe and /dev/null differ diff --git a/Templates/Empty PhysX/game/IE Empty PhysX Plugin.dll b/Templates/Empty PhysX/game/IE Empty PhysX Plugin.dll deleted file mode 100644 index e76306356c..0000000000 Binary files a/Templates/Empty PhysX/game/IE Empty PhysX Plugin.dll and /dev/null differ diff --git a/Templates/Empty PhysX/game/NP Empty PhysX Plugin.dll b/Templates/Empty PhysX/game/NP Empty PhysX Plugin.dll deleted file mode 100644 index df7a7efce7..0000000000 Binary files a/Templates/Empty PhysX/game/NP Empty PhysX Plugin.dll and /dev/null differ diff --git a/Templates/Empty PhysX/game/tools/materialEditor/scripts/materialEditor.ed.cs b/Templates/Empty PhysX/game/tools/materialEditor/scripts/materialEditor.ed.cs index 9297eec94c..f4465c281b 100644 --- a/Templates/Empty PhysX/game/tools/materialEditor/scripts/materialEditor.ed.cs +++ b/Templates/Empty PhysX/game/tools/materialEditor/scripts/materialEditor.ed.cs @@ -814,7 +814,7 @@ singleton Material(notDirtyMaterial) MaterialEditorPropertiesWindow-->showFootprintsCheckbox.setValue((%material).showFootprints); MaterialEditorPropertiesWindow-->showDustCheckbox.setValue((%material).showDust); MaterialEditorGui.updateSoundPopup("Footstep", (%material).footstepSoundId, (%material).customFootstepSound); - MaterialEditorGui.updateSoundPopup("Impact", (%material).footstepSoundId, (%material).customFootstepSound); + MaterialEditorGui.updateSoundPopup("Impact", (%material).impactSoundId, (%material).customImpactSound); //layer specific controls are located here %layer = MaterialEditorGui.currentLayer; diff --git a/Templates/Empty/buildFiles/config/project.conf b/Templates/Empty/buildFiles/config/project.conf index a03a244d8b..af9cbfd652 100644 --- a/Templates/Empty/buildFiles/config/project.conf +++ b/Templates/Empty/buildFiles/config/project.conf @@ -6,6 +6,11 @@ // a racing game. $TORQUE_HIFI_NET = false; +// Set this to true to enable the ExtendedMove class. This +// allows the passing of absolute position and rotation input +// device information from the client to the server. +$TORQUE_EXTENDED_MOVE = false; + // Configure Torque 3D Torque3D::beginConfig( "win32", "Empty" ); diff --git a/Templates/Empty/game/Empty.dll b/Templates/Empty/game/Empty.dll deleted file mode 100644 index 64f18b49b8..0000000000 Binary files a/Templates/Empty/game/Empty.dll and /dev/null differ diff --git a/Templates/Empty/game/Empty.exe b/Templates/Empty/game/Empty.exe deleted file mode 100644 index c4add5ef03..0000000000 Binary files a/Templates/Empty/game/Empty.exe and /dev/null differ diff --git a/Templates/Empty/game/IE Empty Plugin.dll b/Templates/Empty/game/IE Empty Plugin.dll deleted file mode 100644 index 1ce1de44bd..0000000000 Binary files a/Templates/Empty/game/IE Empty Plugin.dll and /dev/null differ diff --git a/Templates/Empty/game/NP Empty Plugin.dll b/Templates/Empty/game/NP Empty Plugin.dll deleted file mode 100644 index ac0394092c..0000000000 Binary files a/Templates/Empty/game/NP Empty Plugin.dll and /dev/null differ diff --git a/Templates/Empty/game/tools/materialEditor/scripts/materialEditor.ed.cs b/Templates/Empty/game/tools/materialEditor/scripts/materialEditor.ed.cs index 9297eec94c..f4465c281b 100644 --- a/Templates/Empty/game/tools/materialEditor/scripts/materialEditor.ed.cs +++ b/Templates/Empty/game/tools/materialEditor/scripts/materialEditor.ed.cs @@ -814,7 +814,7 @@ singleton Material(notDirtyMaterial) MaterialEditorPropertiesWindow-->showFootprintsCheckbox.setValue((%material).showFootprints); MaterialEditorPropertiesWindow-->showDustCheckbox.setValue((%material).showDust); MaterialEditorGui.updateSoundPopup("Footstep", (%material).footstepSoundId, (%material).customFootstepSound); - MaterialEditorGui.updateSoundPopup("Impact", (%material).footstepSoundId, (%material).customFootstepSound); + MaterialEditorGui.updateSoundPopup("Impact", (%material).impactSoundId, (%material).customImpactSound); //layer specific controls are located here %layer = MaterialEditorGui.currentLayer; diff --git a/Templates/Full PhysX/buildFiles/config/project.conf b/Templates/Full PhysX/buildFiles/config/project.conf index 18e70cf548..3eb64cfe3e 100644 --- a/Templates/Full PhysX/buildFiles/config/project.conf +++ b/Templates/Full PhysX/buildFiles/config/project.conf @@ -6,6 +6,11 @@ // a racing game. $TORQUE_HIFI_NET = false; +// Set this to true to enable the ExtendedMove class. This +// allows the passing of absolute position and rotation input +// device information from the client to the server. +$TORQUE_EXTENDED_MOVE = false; + // Configure Torque 3D Torque3D::beginConfig( "win32", "Full PhysX" ); diff --git a/Templates/Full PhysX/game/Full PhysX.dll b/Templates/Full PhysX/game/Full PhysX.dll deleted file mode 100644 index 812b648811..0000000000 Binary files a/Templates/Full PhysX/game/Full PhysX.dll and /dev/null differ diff --git a/Templates/Full PhysX/game/Full PhysX.exe b/Templates/Full PhysX/game/Full PhysX.exe deleted file mode 100644 index 608c9f6971..0000000000 Binary files a/Templates/Full PhysX/game/Full PhysX.exe and /dev/null differ diff --git a/Templates/Full PhysX/game/IE Full PhysX Plugin.dll b/Templates/Full PhysX/game/IE Full PhysX Plugin.dll deleted file mode 100644 index 40718bce7e..0000000000 Binary files a/Templates/Full PhysX/game/IE Full PhysX Plugin.dll and /dev/null differ diff --git a/Templates/Full PhysX/game/NP Full PhysX Plugin.dll b/Templates/Full PhysX/game/NP Full PhysX Plugin.dll deleted file mode 100644 index 5713ea96fe..0000000000 Binary files a/Templates/Full PhysX/game/NP Full PhysX Plugin.dll and /dev/null differ diff --git a/Templates/Full PhysX/game/art/datablocks/player.cs b/Templates/Full PhysX/game/art/datablocks/player.cs index 444e25f908..f582c0ef0a 100644 --- a/Templates/Full PhysX/game/art/datablocks/player.cs +++ b/Templates/Full PhysX/game/art/datablocks/player.cs @@ -484,7 +484,7 @@ datablock PlayerData(DefaultPlayerData) computeCRC = false; // Third person shape - shapeFile = "art/shapes/actors/Soldier/soldier_rigged.dae"; + shapeFile = "art/shapes/actors/Soldier/soldier_rigged.DAE"; cameraMaxDist = 3; allowImageStateAnimation = true; diff --git a/Templates/Full PhysX/game/art/datablocks/weapon.cs b/Templates/Full PhysX/game/art/datablocks/weapon.cs index 02d57cf9c3..4afa9409ae 100644 --- a/Templates/Full PhysX/game/art/datablocks/weapon.cs +++ b/Templates/Full PhysX/game/art/datablocks/weapon.cs @@ -28,7 +28,7 @@ datablock SFXProfile(WeaponUseSound) { - filename = "art/sound/weapons/weapon_switch"; + filename = "art/sound/weapons/Weapon_switch"; description = AudioClose3d; preload = true; }; diff --git a/Templates/Full PhysX/game/art/datablocks/weapons/Ryder.cs b/Templates/Full PhysX/game/art/datablocks/weapons/Ryder.cs index 44b8bde63a..a94bfa8d67 100644 --- a/Templates/Full PhysX/game/art/datablocks/weapons/Ryder.cs +++ b/Templates/Full PhysX/game/art/datablocks/weapons/Ryder.cs @@ -26,21 +26,21 @@ datablock SFXProfile(RyderFireSound) { - filename = "art/sound/weapons/wpn_Ryder_fire"; + filename = "art/sound/weapons/wpn_ryder_fire"; description = AudioClose3D; preload = true; }; datablock SFXProfile(RyderReloadSound) { - filename = "art/sound/weapons/wpn_Ryder_reload"; + filename = "art/sound/weapons/wpn_ryder_reload"; description = AudioClose3D; preload = true; }; datablock SFXProfile(RyderSwitchinSound) { - filename = "art/sound/weapons/wpn_Ryder_switchin"; + filename = "art/sound/weapons/wpn_ryder_switchin"; description = AudioClose3D; preload = true; }; diff --git a/Templates/Full PhysX/game/art/gui/playGui.gui b/Templates/Full PhysX/game/art/gui/playGui.gui index a9aab8a8d0..26a7972b0b 100644 --- a/Templates/Full PhysX/game/art/gui/playGui.gui +++ b/Templates/Full PhysX/game/art/gui/playGui.gui @@ -240,57 +240,31 @@ canSaveDynamicFields = "0"; }; }; - new GuiBitmapBorderCtrl(HealthHUD) { + new GuiHealthTextHud() { + fillColor = "0 0 0 0.65"; + frameColor = "0 0 0 1"; + textColor = "1 1 1 1"; + warningColor = "1 0 0 1"; + showFill = "1"; + showFrame = "1"; + showTrueValue = "0"; + showEnergy = "0"; + warnThreshold = "25"; + pulseThreshold = "15"; + pulseRate = "750"; + position = "5 693"; + extent = "72 72"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "top"; + profile = "GuiBigTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; isContainer = "0"; - Profile = "ChatHudBorderProfile"; - HorizSizing = "right"; - VertSizing = "top"; - position = "6 693"; - Extent = "72 72"; - MinExtent = "8 8"; canSave = "1"; - Visible = "1"; - tooltipprofile = "GuiToolTipProfile"; - hovertime = "1000"; canSaveDynamicFields = "0"; - - new GuiBitmapCtrl() { - bitmap = "core/art/gui/images/hudfill.png"; - wrap = "0"; - isContainer = "0"; - Profile = "GuiDefaultProfile"; - HorizSizing = "width"; - VertSizing = "height"; - position = "8 8"; - Extent = "56 56"; - MinExtent = "8 8"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "GuiToolTipProfile"; - hovertime = "1000"; - canSaveDynamicFields = "0"; - }; - new GuiTextCtrl(numericalHealthHUD) { - maxLength = "255"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "0"; - AnchorBottom = "0"; - AnchorLeft = "0"; - AnchorRight = "0"; - isContainer = "0"; - Profile = "NumericHealthProfile"; - HorizSizing = "center"; - VertSizing = "center"; - position = "0 22"; - Extent = "72 32"; - MinExtent = "8 8"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "GuiToolTipProfile"; - hovertime = "1000"; - canSaveDynamicFields = "0"; - }; }; new GuiBitmapCtrl(OOBSign) { bitmap = "art/gui/playHud/missionAreaWarning.png"; diff --git a/Templates/Full PhysX/game/art/shapes/actors/Soldier/soldier_rigged.cs b/Templates/Full PhysX/game/art/shapes/actors/Soldier/soldier_rigged.cs index f966930156..f15fe0265b 100644 --- a/Templates/Full PhysX/game/art/shapes/actors/Soldier/soldier_rigged.cs +++ b/Templates/Full PhysX/game/art/shapes/actors/Soldier/soldier_rigged.cs @@ -22,7 +22,7 @@ singleton TSShapeConstructor(SoldierDAE) { - baseShape = "./soldier_rigged.dae"; + baseShape = "./soldier_rigged.DAE"; loadLights = "0"; unit = "1.0"; upAxis = "DEFAULT"; diff --git a/Templates/Full PhysX/game/scripts/client/client.cs b/Templates/Full PhysX/game/scripts/client/client.cs index 5d5be25d54..eff6c923a6 100644 --- a/Templates/Full PhysX/game/scripts/client/client.cs +++ b/Templates/Full PhysX/game/scripts/client/client.cs @@ -45,26 +45,6 @@ function clientCmdSyncClock(%time) // or when a client joins a game in progress. } -//----------------------------------------------------------------------------- -// Numerical Health Counter -//----------------------------------------------------------------------------- - -function clientCmdSetNumericalHealthHUD(%curHealth) -{ - // Skip if the hud is missing. - if (!isObject(numericalHealthHUD)) - return; - - // The server has sent us our current health, display it on the HUD - numericalHealthHUD.setValue(%curHealth); - - // Ensure the HUD is set to visible while we have health / are alive - if (%curHealth) - HealthHUD.setVisible(true); - else - HealthHUD.setVisible(false); -} - //----------------------------------------------------------------------------- // Damage Direction Indicator //----------------------------------------------------------------------------- diff --git a/Templates/Full PhysX/game/scripts/server/gameCore.cs b/Templates/Full PhysX/game/scripts/server/gameCore.cs index e0d5cb7b3f..ebb2f557dd 100644 --- a/Templates/Full PhysX/game/scripts/server/gameCore.cs +++ b/Templates/Full PhysX/game/scripts/server/gameCore.cs @@ -676,9 +676,6 @@ function sendMsgClientKilled_Default( %msgType, %client, %sourceClient, %damLoc // Clear out the name on the corpse %client.player.setShapeName(""); - // Update the numerical Health HUD - %client.player.updateHealth(); - // Switch the client over to the death cam and unhook the player object. if (isObject(%client.camera) && isObject(%client.player)) { diff --git a/Templates/Full PhysX/game/scripts/server/health.cs b/Templates/Full PhysX/game/scripts/server/health.cs index 34b8acbc88..f56611184b 100644 --- a/Templates/Full PhysX/game/scripts/server/health.cs +++ b/Templates/Full PhysX/game/scripts/server/health.cs @@ -36,9 +36,6 @@ { %col.applyRepair(%this.repairAmount); - // Update the Health GUI while repairing - %this.doHealthUpdate(%col); - %obj.respawn(); if (%col.client) messageClient(%col.client, 'MsgHealthPatchUsed', '\c2Health Patch Applied'); @@ -46,28 +43,6 @@ } } -function HealthPatch::doHealthUpdate(%this, %obj) -{ - // Would be better to add a onRepair() callback to shapeBase.cpp in order to - // prevent any excess/unneccesary schedules from this. But for the time - // being.... - - // This is just a rough timer to update the Health HUD every 250 ms. From - // my tests a large health pack will fully heal a player from 10 health in - // 36 iterations (ie. 9 seconds). If either the scheduling time, the repair - // amount, or the repair rate is changed then the healthTimer counter should - // be changed also. - - if (%obj.healthTimer < 40) // 40 = 10 seconds at 1 iteration per 250 ms. - { - %obj.UpdateHealth(); - %this.schedule(250, doHealthUpdate, %obj); - %obj.healthTimer++; - } - else - %obj.healthTimer = 0; -} - function ShapeBase::tossPatch(%this) { //error("ShapeBase::tossPatch(" SPC %this.client.nameBase SPC ")"); diff --git a/Templates/Full PhysX/game/scripts/server/player.cs b/Templates/Full PhysX/game/scripts/server/player.cs index af7f499d51..d06ae8c657 100644 --- a/Templates/Full PhysX/game/scripts/server/player.cs +++ b/Templates/Full PhysX/game/scripts/server/player.cs @@ -53,12 +53,6 @@ // Default dynamic armor stats %obj.setRechargeRate(%this.rechargeRate); %obj.setRepairRate(0); - - // Set the numerical Health HUD - //%obj.updateHealth(); - - // Calling updateHealth() must be delayed now... for some reason - %obj.schedule(50, "updateHealth"); } function Armor::onRemove(%this, %obj) @@ -227,9 +221,6 @@ %location = "Body"; - // Update the numerical Health HUD - %obj.updateHealth(); - // Deal with client callbacks here because we don't have this // information in the onDamage or onDisable methods %client = %obj.client; @@ -435,23 +426,6 @@ } // ---------------------------------------------------------------------------- -// Numerical Health Counter -// ---------------------------------------------------------------------------- - -function Player::updateHealth(%player) -{ - //echo("\c4Player::updateHealth() -> Player Health changed, updating HUD!"); - - // Calcualte player health - %maxDamage = %player.getDatablock().maxDamage; - %damageLevel = %player.getDamageLevel(); - %curHealth = %maxDamage - %damageLevel; - %curHealth = mceil(%curHealth); - - // Send the player object's current health level to the client, where it - // will Update the numericalHealth HUD. - commandToClient(%player.client, 'setNumericalHealthHUD', %curHealth); -} function Player::setDamageDirection(%player, %sourceObject, %damagePos) { diff --git a/Templates/Full PhysX/game/tools/materialEditor/scripts/materialEditor.ed.cs b/Templates/Full PhysX/game/tools/materialEditor/scripts/materialEditor.ed.cs index 9297eec94c..f4465c281b 100644 --- a/Templates/Full PhysX/game/tools/materialEditor/scripts/materialEditor.ed.cs +++ b/Templates/Full PhysX/game/tools/materialEditor/scripts/materialEditor.ed.cs @@ -814,7 +814,7 @@ singleton Material(notDirtyMaterial) MaterialEditorPropertiesWindow-->showFootprintsCheckbox.setValue((%material).showFootprints); MaterialEditorPropertiesWindow-->showDustCheckbox.setValue((%material).showDust); MaterialEditorGui.updateSoundPopup("Footstep", (%material).footstepSoundId, (%material).customFootstepSound); - MaterialEditorGui.updateSoundPopup("Impact", (%material).footstepSoundId, (%material).customFootstepSound); + MaterialEditorGui.updateSoundPopup("Impact", (%material).impactSoundId, (%material).customImpactSound); //layer specific controls are located here %layer = MaterialEditorGui.currentLayer; diff --git a/Templates/Full/buildFiles/config/project.conf b/Templates/Full/buildFiles/config/project.conf index 46bfe3328e..3ea967451f 100644 --- a/Templates/Full/buildFiles/config/project.conf +++ b/Templates/Full/buildFiles/config/project.conf @@ -6,6 +6,11 @@ // a racing game. $TORQUE_HIFI_NET = false; +// Set this to true to enable the ExtendedMove class. This +// allows the passing of absolute position and rotation input +// device information from the client to the server. +$TORQUE_EXTENDED_MOVE = false; + // Configure Torque 3D Torque3D::beginConfig( "win32", "Full" ); diff --git a/Templates/Full/game/Full.dll b/Templates/Full/game/Full.dll deleted file mode 100644 index 56cf4734f2..0000000000 Binary files a/Templates/Full/game/Full.dll and /dev/null differ diff --git a/Templates/Full/game/Full.exe b/Templates/Full/game/Full.exe deleted file mode 100644 index 1deed13302..0000000000 Binary files a/Templates/Full/game/Full.exe and /dev/null differ diff --git a/Templates/Full/game/IE Full Plugin.dll b/Templates/Full/game/IE Full Plugin.dll deleted file mode 100644 index 6b23a4bc66..0000000000 Binary files a/Templates/Full/game/IE Full Plugin.dll and /dev/null differ diff --git a/Templates/Full/game/NP Full Plugin.dll b/Templates/Full/game/NP Full Plugin.dll deleted file mode 100644 index 93562df11f..0000000000 Binary files a/Templates/Full/game/NP Full Plugin.dll and /dev/null differ diff --git a/Templates/Full/game/art/datablocks/player.cs b/Templates/Full/game/art/datablocks/player.cs index 7eb6cb5158..746c7b3091 100644 --- a/Templates/Full/game/art/datablocks/player.cs +++ b/Templates/Full/game/art/datablocks/player.cs @@ -484,7 +484,7 @@ datablock PlayerData(DefaultPlayerData) computeCRC = false; // Third person shape - shapeFile = "art/shapes/actors/Soldier/soldier_rigged.dae"; + shapeFile = "art/shapes/actors/Soldier/soldier_rigged.DAE"; cameraMaxDist = 3; allowImageStateAnimation = true; diff --git a/Templates/Full/game/art/datablocks/vehicles/cheetahCar.cs b/Templates/Full/game/art/datablocks/vehicles/cheetahCar.cs index 3fa8395464..cb702166f6 100644 --- a/Templates/Full/game/art/datablocks/vehicles/cheetahCar.cs +++ b/Templates/Full/game/art/datablocks/vehicles/cheetahCar.cs @@ -55,7 +55,7 @@ datablock SFXProfile(DirtKickup) fileName = "art/sound/cheetah/softImpact.ogg"; }; -datablock SFXProfile(TurretFireSound) +datablock SFXProfile(CheetahTurretFireSound) { filename = "art/sound/cheetah/turret_firing.wav"; description = BulletFireDesc; @@ -220,7 +220,7 @@ class = "WeaponImage"; stateSequence[3] = "Fire"; stateSequenceRandomFlash[3] = true; // use muzzle flash sequence stateScript[3] = "onFire"; - stateSound[3] = TurretFireSound; + stateSound[3] = CheetahTurretFireSound; stateEmitter[3] = TurretFireSmokeEmitter; stateEmitterTime[3] = 0.025; @@ -274,7 +274,7 @@ datablock WheeledVehicleTire(CheetahCarTire) // forces to move the vehicle. These distortion/spring forces // are what convert wheel angular velocity into forces that // act on the rigid body. - shapeFile = "art/shapes/Cheetah/wheel.dae"; + shapeFile = "art/shapes/Cheetah/wheel.DAE"; staticFriction = 4.2; kineticFriction = "1"; @@ -296,7 +296,7 @@ datablock WheeledVehicleTire(CheetahCarTireRear) // forces to move the vehicle. These distortion/spring forces // are what convert wheel angular velocity into forces that // act on the rigid body. - shapeFile = "art/shapes/Cheetah/wheelBack.dae"; + shapeFile = "art/shapes/Cheetah/wheelBack.DAE"; staticFriction = "7.2"; kineticFriction = "1"; @@ -324,7 +324,7 @@ datablock WheeledVehicleSpring(CheetahCarSpring) datablock WheeledVehicleData(CheetahCar) { category = "Vehicles"; - shapeFile = "art/shapes/Cheetah/Cheetah_Body.dae"; + shapeFile = "art/shapes/Cheetah/Cheetah_Body.DAE"; emap = 1; mountPose[0] = sitting; diff --git a/Templates/Full/game/art/datablocks/weapon.cs b/Templates/Full/game/art/datablocks/weapon.cs index 02d57cf9c3..4afa9409ae 100644 --- a/Templates/Full/game/art/datablocks/weapon.cs +++ b/Templates/Full/game/art/datablocks/weapon.cs @@ -28,7 +28,7 @@ datablock SFXProfile(WeaponUseSound) { - filename = "art/sound/weapons/weapon_switch"; + filename = "art/sound/weapons/Weapon_switch"; description = AudioClose3d; preload = true; }; diff --git a/Templates/Full/game/art/datablocks/weapons/Ryder.cs b/Templates/Full/game/art/datablocks/weapons/Ryder.cs index 44b8bde63a..a94bfa8d67 100644 --- a/Templates/Full/game/art/datablocks/weapons/Ryder.cs +++ b/Templates/Full/game/art/datablocks/weapons/Ryder.cs @@ -26,21 +26,21 @@ datablock SFXProfile(RyderFireSound) { - filename = "art/sound/weapons/wpn_Ryder_fire"; + filename = "art/sound/weapons/wpn_ryder_fire"; description = AudioClose3D; preload = true; }; datablock SFXProfile(RyderReloadSound) { - filename = "art/sound/weapons/wpn_Ryder_reload"; + filename = "art/sound/weapons/wpn_ryder_reload"; description = AudioClose3D; preload = true; }; datablock SFXProfile(RyderSwitchinSound) { - filename = "art/sound/weapons/wpn_Ryder_switchin"; + filename = "art/sound/weapons/wpn_ryder_switchin"; description = AudioClose3D; preload = true; }; diff --git a/Templates/Full/game/art/gui/playGui.gui b/Templates/Full/game/art/gui/playGui.gui index a9aab8a8d0..26a7972b0b 100644 --- a/Templates/Full/game/art/gui/playGui.gui +++ b/Templates/Full/game/art/gui/playGui.gui @@ -240,57 +240,31 @@ canSaveDynamicFields = "0"; }; }; - new GuiBitmapBorderCtrl(HealthHUD) { + new GuiHealthTextHud() { + fillColor = "0 0 0 0.65"; + frameColor = "0 0 0 1"; + textColor = "1 1 1 1"; + warningColor = "1 0 0 1"; + showFill = "1"; + showFrame = "1"; + showTrueValue = "0"; + showEnergy = "0"; + warnThreshold = "25"; + pulseThreshold = "15"; + pulseRate = "750"; + position = "5 693"; + extent = "72 72"; + minExtent = "8 2"; + horizSizing = "right"; + vertSizing = "top"; + profile = "GuiBigTextProfile"; + visible = "1"; + active = "1"; + tooltipProfile = "GuiToolTipProfile"; + hovertime = "1000"; isContainer = "0"; - Profile = "ChatHudBorderProfile"; - HorizSizing = "right"; - VertSizing = "top"; - position = "6 693"; - Extent = "72 72"; - MinExtent = "8 8"; canSave = "1"; - Visible = "1"; - tooltipprofile = "GuiToolTipProfile"; - hovertime = "1000"; canSaveDynamicFields = "0"; - - new GuiBitmapCtrl() { - bitmap = "core/art/gui/images/hudfill.png"; - wrap = "0"; - isContainer = "0"; - Profile = "GuiDefaultProfile"; - HorizSizing = "width"; - VertSizing = "height"; - position = "8 8"; - Extent = "56 56"; - MinExtent = "8 8"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "GuiToolTipProfile"; - hovertime = "1000"; - canSaveDynamicFields = "0"; - }; - new GuiTextCtrl(numericalHealthHUD) { - maxLength = "255"; - Margin = "0 0 0 0"; - Padding = "0 0 0 0"; - AnchorTop = "0"; - AnchorBottom = "0"; - AnchorLeft = "0"; - AnchorRight = "0"; - isContainer = "0"; - Profile = "NumericHealthProfile"; - HorizSizing = "center"; - VertSizing = "center"; - position = "0 22"; - Extent = "72 32"; - MinExtent = "8 8"; - canSave = "1"; - Visible = "1"; - tooltipprofile = "GuiToolTipProfile"; - hovertime = "1000"; - canSaveDynamicFields = "0"; - }; }; new GuiBitmapCtrl(OOBSign) { bitmap = "art/gui/playHud/missionAreaWarning.png"; diff --git a/Templates/Full/game/art/shapes/Cheetah/wheel.cs b/Templates/Full/game/art/shapes/Cheetah/wheel.cs index 22116b8a73..8dfe9786e3 100644 --- a/Templates/Full/game/art/shapes/Cheetah/wheel.cs +++ b/Templates/Full/game/art/shapes/Cheetah/wheel.cs @@ -22,7 +22,7 @@ singleton TSShapeConstructor(WheelDae) { - baseShape = "./wheel.dae"; + baseShape = "./wheel.DAE"; lodType = "TrailingNumber"; neverImport = "null EnvironmentAmbientLight"; matNamePrefix = ""; diff --git a/Templates/Full/game/art/shapes/Cheetah/wheelBack.cs b/Templates/Full/game/art/shapes/Cheetah/wheelBack.cs index 10eab60cf4..16ab71350c 100644 --- a/Templates/Full/game/art/shapes/Cheetah/wheelBack.cs +++ b/Templates/Full/game/art/shapes/Cheetah/wheelBack.cs @@ -22,7 +22,7 @@ singleton TSShapeConstructor(WheelBackDae) { - baseShape = "./wheelBack.dae"; + baseShape = "./wheelBack.DAE"; lodType = "TrailingNumber"; neverImport = "null EnvironmentAmbientLight"; matNamePrefix = ""; diff --git a/Templates/Full/game/art/shapes/actors/Soldier/soldier_rigged.cs b/Templates/Full/game/art/shapes/actors/Soldier/soldier_rigged.cs index f966930156..f15fe0265b 100644 --- a/Templates/Full/game/art/shapes/actors/Soldier/soldier_rigged.cs +++ b/Templates/Full/game/art/shapes/actors/Soldier/soldier_rigged.cs @@ -22,7 +22,7 @@ singleton TSShapeConstructor(SoldierDAE) { - baseShape = "./soldier_rigged.dae"; + baseShape = "./soldier_rigged.DAE"; loadLights = "0"; unit = "1.0"; upAxis = "DEFAULT"; diff --git a/Templates/Full/game/scripts/client/client.cs b/Templates/Full/game/scripts/client/client.cs index 5d5be25d54..eff6c923a6 100644 --- a/Templates/Full/game/scripts/client/client.cs +++ b/Templates/Full/game/scripts/client/client.cs @@ -45,26 +45,6 @@ function clientCmdSyncClock(%time) // or when a client joins a game in progress. } -//----------------------------------------------------------------------------- -// Numerical Health Counter -//----------------------------------------------------------------------------- - -function clientCmdSetNumericalHealthHUD(%curHealth) -{ - // Skip if the hud is missing. - if (!isObject(numericalHealthHUD)) - return; - - // The server has sent us our current health, display it on the HUD - numericalHealthHUD.setValue(%curHealth); - - // Ensure the HUD is set to visible while we have health / are alive - if (%curHealth) - HealthHUD.setVisible(true); - else - HealthHUD.setVisible(false); -} - //----------------------------------------------------------------------------- // Damage Direction Indicator //----------------------------------------------------------------------------- diff --git a/Templates/Full/game/scripts/server/gameCore.cs b/Templates/Full/game/scripts/server/gameCore.cs index e0d5cb7b3f..ebb2f557dd 100644 --- a/Templates/Full/game/scripts/server/gameCore.cs +++ b/Templates/Full/game/scripts/server/gameCore.cs @@ -676,9 +676,6 @@ function sendMsgClientKilled_Default( %msgType, %client, %sourceClient, %damLoc // Clear out the name on the corpse %client.player.setShapeName(""); - // Update the numerical Health HUD - %client.player.updateHealth(); - // Switch the client over to the death cam and unhook the player object. if (isObject(%client.camera) && isObject(%client.player)) { diff --git a/Templates/Full/game/scripts/server/health.cs b/Templates/Full/game/scripts/server/health.cs index 34b8acbc88..f56611184b 100644 --- a/Templates/Full/game/scripts/server/health.cs +++ b/Templates/Full/game/scripts/server/health.cs @@ -36,9 +36,6 @@ { %col.applyRepair(%this.repairAmount); - // Update the Health GUI while repairing - %this.doHealthUpdate(%col); - %obj.respawn(); if (%col.client) messageClient(%col.client, 'MsgHealthPatchUsed', '\c2Health Patch Applied'); @@ -46,28 +43,6 @@ } } -function HealthPatch::doHealthUpdate(%this, %obj) -{ - // Would be better to add a onRepair() callback to shapeBase.cpp in order to - // prevent any excess/unneccesary schedules from this. But for the time - // being.... - - // This is just a rough timer to update the Health HUD every 250 ms. From - // my tests a large health pack will fully heal a player from 10 health in - // 36 iterations (ie. 9 seconds). If either the scheduling time, the repair - // amount, or the repair rate is changed then the healthTimer counter should - // be changed also. - - if (%obj.healthTimer < 40) // 40 = 10 seconds at 1 iteration per 250 ms. - { - %obj.UpdateHealth(); - %this.schedule(250, doHealthUpdate, %obj); - %obj.healthTimer++; - } - else - %obj.healthTimer = 0; -} - function ShapeBase::tossPatch(%this) { //error("ShapeBase::tossPatch(" SPC %this.client.nameBase SPC ")"); diff --git a/Templates/Full/game/scripts/server/player.cs b/Templates/Full/game/scripts/server/player.cs index af7f499d51..d06ae8c657 100644 --- a/Templates/Full/game/scripts/server/player.cs +++ b/Templates/Full/game/scripts/server/player.cs @@ -53,12 +53,6 @@ // Default dynamic armor stats %obj.setRechargeRate(%this.rechargeRate); %obj.setRepairRate(0); - - // Set the numerical Health HUD - //%obj.updateHealth(); - - // Calling updateHealth() must be delayed now... for some reason - %obj.schedule(50, "updateHealth"); } function Armor::onRemove(%this, %obj) @@ -227,9 +221,6 @@ %location = "Body"; - // Update the numerical Health HUD - %obj.updateHealth(); - // Deal with client callbacks here because we don't have this // information in the onDamage or onDisable methods %client = %obj.client; @@ -435,23 +426,6 @@ } // ---------------------------------------------------------------------------- -// Numerical Health Counter -// ---------------------------------------------------------------------------- - -function Player::updateHealth(%player) -{ - //echo("\c4Player::updateHealth() -> Player Health changed, updating HUD!"); - - // Calcualte player health - %maxDamage = %player.getDatablock().maxDamage; - %damageLevel = %player.getDamageLevel(); - %curHealth = %maxDamage - %damageLevel; - %curHealth = mceil(%curHealth); - - // Send the player object's current health level to the client, where it - // will Update the numericalHealth HUD. - commandToClient(%player.client, 'setNumericalHealthHUD', %curHealth); -} function Player::setDamageDirection(%player, %sourceObject, %damagePos) { diff --git a/Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs b/Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs index 9297eec94c..f4465c281b 100644 --- a/Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs +++ b/Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs @@ -814,7 +814,7 @@ singleton Material(notDirtyMaterial) MaterialEditorPropertiesWindow-->showFootprintsCheckbox.setValue((%material).showFootprints); MaterialEditorPropertiesWindow-->showDustCheckbox.setValue((%material).showDust); MaterialEditorGui.updateSoundPopup("Footstep", (%material).footstepSoundId, (%material).customFootstepSound); - MaterialEditorGui.updateSoundPopup("Impact", (%material).footstepSoundId, (%material).customFootstepSound); + MaterialEditorGui.updateSoundPopup("Impact", (%material).impactSoundId, (%material).customImpactSound); //layer specific controls are located here %layer = MaterialEditorGui.currentLayer; diff --git a/Tools/projectGenerator/classes/BuildTarget.php b/Tools/projectGenerator/classes/BuildTarget.php index 8ab458f6cd..fa31f1ae2d 100644 --- a/Tools/projectGenerator/classes/BuildTarget.php +++ b/Tools/projectGenerator/classes/BuildTarget.php @@ -203,6 +203,17 @@ function isSourceFile( $file ) return false; } + + function isResourceFile( $file ) + { + $ext = ".rc"; + $extLen = strlen( $ext ); + $possibleMatch = substr( $file, -$extLen, $extLen ); + if( $possibleMatch == $ext ) + return true; + + return false; + } } ?> diff --git a/Tools/projectGenerator/classes/Generator.php b/Tools/projectGenerator/classes/Generator.php index fde25460d9..586936e3d1 100644 --- a/Tools/projectGenerator/classes/Generator.php +++ b/Tools/projectGenerator/classes/Generator.php @@ -255,10 +255,16 @@ static function addProjectLibDir( $dir ) array_push( self::$project_cur->lib_dirs, $dir ); } - static function addProjectLibInput( $lib ) + static function addProjectLibInput( $lib, $libDebug = null ) { array_push( self::$project_cur->libs, $lib ); + array_push( self::$project_cur->libsDebug, $libDebug != null ? $libDebug : $lib ); } + + static function addProjectIgnoreDefaultLib( $lib ) + { + array_push( self::$project_cur->libsIgnore, $lib ); + } static function includeLib( $lib ) { diff --git a/Tools/projectGenerator/classes/Project.php b/Tools/projectGenerator/classes/Project.php index 6d409aef7a..d94749a78c 100644 --- a/Tools/projectGenerator/classes/Project.php +++ b/Tools/projectGenerator/classes/Project.php @@ -44,6 +44,8 @@ class Project public $disabledWarnings; // Additional warnings to disable public $includes; // Additional include paths public $libs; // Additional libraries to link against + public $libsDebug; // Additional Debug build libraries to link against + public $libsIgnore; // Ignore Specific Default Libraries public $lib_dirs; // Additional library search paths public $lib_includes; // libs to include (generated by modules) public $additionalExePath; // Additional section to inject into executable path @@ -81,6 +83,8 @@ public function Project( $name, $type, $guid = '', $game_dir = 'game', $output_n $this->defines = array(); $this->includes = array(); $this->libs = array(); + $this->libsDebug = array(); + $this->libsIgnore = array(); $this->lib_dirs = array(); $this->lib_includes = array(); $this->outputs = array(); @@ -330,6 +334,8 @@ private function setTemplateParams( $tpl, $output, &$projectFiles ) $tpl->assign_by_ref( 'projDisabledWarnings', $this->disabledWarnings ); $tpl->assign_by_ref( 'projIncludes', $this->includes ); $tpl->assign_by_ref( 'projLibs', $this->libs ); + $tpl->assign_by_ref( 'projLibsDebug',$this->libsDebug); + $tpl->assign_by_ref( 'projLibsIgnore',$this->libsIgnore); $tpl->assign_by_ref( 'projLibDirs', $this->lib_dirs ); $tpl->assign_by_ref( 'projDepend', $this->dependencies ); $tpl->assign_by_ref( 'gameProjectName', $gameProjectName ); diff --git a/Tools/projectGenerator/modules/T3D.inc b/Tools/projectGenerator/modules/T3D.inc index 5ec6be1c5c..26bc8da1d3 100644 --- a/Tools/projectGenerator/modules/T3D.inc +++ b/Tools/projectGenerator/modules/T3D.inc @@ -60,11 +60,17 @@ addEngineSrcDir('T3D/gameBase'); addEngineSrcDir('T3D/turret'); global $TORQUE_HIFI_NET; +global $TORQUE_EXTENDED_MOVE; if ( $TORQUE_HIFI_NET == true ) { addProjectDefines( 'TORQUE_HIFI_NET' ); addEngineSrcDir('T3D/gameBase/hifi'); } +elseif ( $TORQUE_EXTENDED_MOVE == true ) +{ + addProjectDefines( 'TORQUE_EXTENDED_MOVE' ); + addEngineSrcDir('T3D/gameBase/extended'); +} else addEngineSrcDir('T3D/gameBase/std'); diff --git a/Tools/projectGenerator/modules/core.inc b/Tools/projectGenerator/modules/core.inc index 83d982e86b..84cb1c016e 100644 --- a/Tools/projectGenerator/modules/core.inc +++ b/Tools/projectGenerator/modules/core.inc @@ -72,6 +72,7 @@ switch( Generator::$platform ) addEngineSrcDir('platform/threads'); addEngineSrcDir('platform/async'); +addEngineSrcDir('platform/input'); addEngineSrcDir('app'); addEngineSrcDir('app/net'); diff --git a/Tools/projectGenerator/modules/leapMotion.inc b/Tools/projectGenerator/modules/leapMotion.inc new file mode 100644 index 0000000000..06377c681d --- /dev/null +++ b/Tools/projectGenerator/modules/leapMotion.inc @@ -0,0 +1,79 @@ + diff --git a/Tools/projectGenerator/projectGenUtils.inc b/Tools/projectGenerator/projectGenUtils.inc index e5d0664950..b826578276 100644 --- a/Tools/projectGenerator/projectGenUtils.inc +++ b/Tools/projectGenerator/projectGenUtils.inc @@ -305,9 +305,14 @@ function addProjectLibDir( $dir ) Generator::addProjectLibDir( $dir ); } -function addProjectLibInput( $lib_name ) +function addProjectLibInput( $lib_name, $libDebug = null ) { - Generator::addProjectLibInput( $lib_name ); + Generator::addProjectLibInput( $lib_name, $libDebug ); +} + +function addProjectIgnoreDefaultLib( $lib ) +{ + Generator::addProjectIgnoreDefaultLib( $lib ); } function addProjectDependency( $pd ) diff --git a/Tools/projectGenerator/templates/makeApp.tpl b/Tools/projectGenerator/templates/makeApp.tpl index ae08a7c481..29034d10e3 100644 --- a/Tools/projectGenerator/templates/makeApp.tpl +++ b/Tools/projectGenerator/templates/makeApp.tpl @@ -12,7 +12,7 @@ SOURCES := {foreach from=$dirWalk item=file key=key} {/foreach} LDFLAGS := -g -m32 -LDLIBS := -lstdc++ -lm -lSDL -lpthread -lrt +LDLIBS := -lstdc++ -lm -lpthread -lrt {foreach item=def from=$projLibs}LDLIBS += -l{$def} {/foreach} diff --git a/Tools/projectGenerator/templates/makeSo.tpl b/Tools/projectGenerator/templates/makeSo.tpl index 647907e9bd..ca26f8dc00 100644 --- a/Tools/projectGenerator/templates/makeSo.tpl +++ b/Tools/projectGenerator/templates/makeSo.tpl @@ -15,7 +15,7 @@ SOURCES := {foreach from=$dirWalk item=file key=key} {/foreach} LDFLAGS_{$projName} := -g -m32 -shared -LDLIBS_{$projName} := -lstdc++ -lSDL -lpthread +LDLIBS_{$projName} := -lstdc++ -lpthread CFLAGS_{$projName} := -MMD -I. -m32 -mmmx -msse -march=i686 {foreach item=def from=$projIncludes}CFLAGS_{$projName} += -I{$def} diff --git a/Tools/projectGenerator/templates/vc2010_dll_proj.tpl b/Tools/projectGenerator/templates/vc2010_dll_proj.tpl index a59461590b..cd520d0510 100644 --- a/Tools/projectGenerator/templates/vc2010_dll_proj.tpl +++ b/Tools/projectGenerator/templates/vc2010_dll_proj.tpl @@ -95,11 +95,11 @@ {foreach item=def from=$projIncludes}{$def};{/foreach}%(AdditionalIncludeDirectories) - {foreach item=def from=$projLibs}{$def};{/foreach}%(AdditionalDependencies) + {foreach item=def from=$projLibsDebug}{$def};{/foreach}%(AdditionalDependencies) $(OutDir){$projOutName}_DEBUG.dll true {foreach item=def from=$projLibDirs}{$def};{/foreach}{$projectOffset}../Link/VC2010.$(Configuration).$(PlatformName);$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories) - LIBC;LIBCD;%(IgnoreSpecificDefaultLibraries) + LIBC;LIBCD;{foreach item=def from=$projLibsIgnore}{$def};{/foreach}%(IgnoreSpecificDefaultLibraries) {$projModuleDefinitionFile} true $(IntDir)$(ProjectName).pdb @@ -147,11 +147,11 @@ {foreach item=def from=$projIncludes}{$def};{/foreach}%(AdditionalIncludeDirectories) - {foreach item=def from=$projLibs}{$def};{/foreach}%(AdditionalDependencies) + {foreach item=def from=$projLibsDebug}{$def};{/foreach}%(AdditionalDependencies) $(OutDir){$projOutName}_OPTIMIZEDDEBUG.dll true {foreach item=def from=$projLibDirs}{$def};{/foreach}{$projectOffset}../Link/VC2010.$(Configuration).$(PlatformName);%(AdditionalLibraryDirectories) - LIBC;LIBCD;%(IgnoreSpecificDefaultLibraries) + LIBC;LIBCD;{foreach item=def from=$projLibsIgnore}{$def};{/foreach}%(IgnoreSpecificDefaultLibraries) {$projModuleDefinitionFile} true $(IntDir)$(ProjectName).pdb @@ -203,7 +203,7 @@ $(OutDir){$projOutName}.dll true {foreach item=def from=$projLibDirs}{$def};{/foreach}{$projectOffset}../Link/VC2010.$(Configuration).$(PlatformName);$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories) - LIBC;LIBCD;%(IgnoreSpecificDefaultLibraries) + LIBC;LIBCD;{foreach item=def from=$projLibsIgnore}{$def};{/foreach}%(IgnoreSpecificDefaultLibraries) {$projModuleDefinitionFile} false $(IntDir)$(ProjectName).pdb diff --git a/Tools/projectGenerator/templates/vc2010_fileRecurse.tpl b/Tools/projectGenerator/templates/vc2010_fileRecurse.tpl index 837fcd68ed..d8af596041 100644 --- a/Tools/projectGenerator/templates/vc2010_fileRecurse.tpl +++ b/Tools/projectGenerator/templates/vc2010_fileRecurse.tpl @@ -36,6 +36,8 @@ {elseif $projOutput->isSourceFile( $dirWalk->path ) } + {elseif $projOutput->isResourceFile( $dirWalk->path ) } + {else} {/if}{* if path == "*.asm" *} diff --git a/Tools/projectGenerator/templates/vc2010_proj.tpl b/Tools/projectGenerator/templates/vc2010_proj.tpl index 18fa80c984..2067c30120 100644 --- a/Tools/projectGenerator/templates/vc2010_proj.tpl +++ b/Tools/projectGenerator/templates/vc2010_proj.tpl @@ -95,11 +95,11 @@ {foreach item=def from=$projIncludes}{$def};{/foreach}%(AdditionalIncludeDirectories) - {foreach item=def from=$projLibs}{$def};{/foreach}%(AdditionalDependencies) + {foreach item=def from=$projLibsDebug}{$def};{/foreach}%(AdditionalDependencies) $(OutDir){$projOutName}_DEBUG.dll true {foreach item=def from=$projLibDirs}{$def};{/foreach}{$projectOffset}../Link/VC2010.$(Configuration).$(PlatformName);$(DXSDK_DIR)/Lib/x86;%(AdditionalLibraryDirectories) - LIBC;LIBCD;%(IgnoreSpecificDefaultLibraries) + LIBC;LIBCD;{foreach item=def from=$projLibsIgnore}{$def};{/foreach}%(IgnoreSpecificDefaultLibraries) {$projModuleDefinitionFile} true $(IntDir)$(ProjectName).pdb @@ -147,11 +147,11 @@ {foreach item=def from=$projIncludes}{$def};{/foreach}%(AdditionalIncludeDirectories) - {foreach item=def from=$projLibs}{$def};{/foreach}%(AdditionalDependencies) + {foreach item=def from=$projLibsDebug}{$def};{/foreach}%(AdditionalDependencies) $(OutDir){$projOutName}_OPTIMIZEDDEBUG.dll true {foreach item=def from=$projLibDirs}{$def};{/foreach}{$projectOffset}../Link/VC2010.$(Configuration).$(PlatformName);%(AdditionalLibraryDirectories) - LIBC;LIBCD;%(IgnoreSpecificDefaultLibraries) + LIBC;LIBCD;{foreach item=def from=$projLibsIgnore}{$def};{/foreach}%(IgnoreSpecificDefaultLibraries) {$projModuleDefinitionFile} true $(IntDir)$(ProjectName).pdb @@ -203,7 +203,7 @@ $(OutDir){$projOutName}.dll true {foreach item=def from=$projLibDirs}{$def};{/foreach}{$projectOffset}../Link/VC2010.$(Configuration).$(PlatformName);%(AdditionalLibraryDirectories) - LIBC;LIBCD;%(IgnoreSpecificDefaultLibraries) + LIBC;LIBCD;{foreach item=def from=$projLibsIgnore}{$def};{/foreach}%(IgnoreSpecificDefaultLibraries) {$projModuleDefinitionFile} false $(IntDir)$(ProjectName).pdb diff --git a/Tools/projectGenerator/templates/vc2010_shared.tpl b/Tools/projectGenerator/templates/vc2010_shared.tpl index f94cb2c07f..9cd2df58a3 100644 --- a/Tools/projectGenerator/templates/vc2010_shared.tpl +++ b/Tools/projectGenerator/templates/vc2010_shared.tpl @@ -95,11 +95,11 @@ {foreach item=def from=$projIncludes}{$def};{/foreach}%(AdditionalIncludeDirectories) - {foreach item=def from=$projLibs}{$def};{/foreach}%(AdditionalDependencies) + {foreach item=def from=$projLibsDebug}{$def};{/foreach}%(AdditionalDependencies) $(OutDir){$projOutName}_DEBUG.exe true {foreach item=def from=$projLibDirs}{$def};{/foreach}{$projectOffset}../Link/VC2010.$(Configuration).$(PlatformName);%(AdditionalLibraryDirectories) - LIBC;LIBCD;%(IgnoreSpecificDefaultLibraries) + LIBC;LIBCD;{foreach item=def from=$projLibsIgnore}{$def};{/foreach}%(IgnoreSpecificDefaultLibraries) true $(IntDir)$(ProjectName).pdb {if $projSubSystem == 1}Console{else}Windows{/if} @@ -146,11 +146,11 @@ {foreach item=def from=$projIncludes}{$def};{/foreach}%(AdditionalIncludeDirectories) - {foreach item=def from=$projLibs}{$def};{/foreach}%(AdditionalDependencies) + {foreach item=def from=$projLibsDebug}{$def};{/foreach}%(AdditionalDependencies) $(OutDir){$projOutName}_OPTIMIZEDDEBUG.exe true {foreach item=def from=$projLibDirs}{$def};{/foreach}{$projectOffset}../Link/VC2010.$(Configuration).$(PlatformName);%(AdditionalLibraryDirectories) - LIBC;LIBCD;%(IgnoreSpecificDefaultLibraries) + LIBC;LIBCD;{foreach item=def from=$projLibsIgnore}{$def};{/foreach}%(IgnoreSpecificDefaultLibraries) true $(IntDir)$(ProjectName).pdb {if $projSubSystem == 1}Console{else}Windows{/if} @@ -201,7 +201,7 @@ $(OutDir){$projOutName}.exe true {foreach item=def from=$projLibDirs}{$def};{/foreach}{$projectOffset}../Link/VC2010.$(Configuration).$(PlatformName);%(AdditionalLibraryDirectories) - LIBC;LIBCD;%(IgnoreSpecificDefaultLibraries) + LIBC;LIBCD;{foreach item=def from=$projLibsIgnore}{$def};{/foreach}%(IgnoreSpecificDefaultLibraries) false $(IntDir)$(ProjectName).pdb {if $projSubSystem == 1}Console{else}Windows{/if} diff --git a/Tools/projectGenerator/templates/vc2k8_dll_proj.tpl b/Tools/projectGenerator/templates/vc2k8_dll_proj.tpl index b550752d88..f9d02a7eb3 100644 --- a/Tools/projectGenerator/templates/vc2k8_dll_proj.tpl +++ b/Tools/projectGenerator/templates/vc2k8_dll_proj.tpl @@ -78,7 +78,7 @@ /> - +