diff --git a/Engine/source/T3D/shapeBase.cpp b/Engine/source/T3D/shapeBase.cpp index 0f45cd876..5e8c85f55 100644 --- a/Engine/source/T3D/shapeBase.cpp +++ b/Engine/source/T3D/shapeBase.cpp @@ -5014,3 +5014,11 @@ DefineEngineMethod( ShapeBase, getModelFile, const char *, (),, const char *fieldName = StringTable->insert( String("shapeFile") ); return datablock->getDataField( fieldName, NULL ); } + +ConsoleMethod( ShapeBase, setManualImageState, void, 4, 4, "(int slot, string state)") +{ + int imageSlot = dAtoi(argv[2]); + const char* state = argv[3]; + if (imageSlot >= 0 && imageSlot < ShapeBase::MaxMountedImages) + object->setManualImageState(imageSlot, state); +} \ No newline at end of file diff --git a/Engine/source/T3D/shapeBase.h b/Engine/source/T3D/shapeBase.h index c1a4d9b0d..7eb6a3114 100644 --- a/Engine/source/T3D/shapeBase.h +++ b/Engine/source/T3D/shapeBase.h @@ -62,10 +62,14 @@ #ifndef _DYNAMIC_CONSOLETYPES_H_ #include "console/dynamicTypes.h" #endif +#ifndef _NETCONNECTION_H_ +#include "sim/netConnection.h" +#endif // Need full definition visible for SimObjectPtr #include "T3D/fx/particleEmitter.h" +class ManualImageSetEvent; class GFXCubemap; class TSShapeInstance; class SceneRenderState; @@ -96,6 +100,7 @@ class ShapeBaseConvex : public Convex friend class ShapeBase; friend class Vehicle; friend class RigidShape; + friend class ManualImageSetEvent; protected: ShapeBase* pShapeBase; @@ -1040,12 +1045,6 @@ protected: /// @param imageSlot Image slot id U32 getImageReloadState(U32 imageSlot); - /// Sets the state of the image by state index - /// @param imageSlot Image slot id - /// @param state State id - /// @param force Force image to state or let it finish then change - void setImageState(U32 imageSlot, U32 state, bool force = false); - void updateAnimThread(U32 imageSlot, S32 imageShapeIndex, ShapeBaseImageData::StateData* lastState=NULL); /// Get the animation prefix for the image @@ -1178,7 +1177,13 @@ public: void setTeamId(S32 team); //< ZOD: End addition /// @} - + + /// Sets the state of the image by state index + /// @param imageSlot Image slot id + /// @param state State id + /// @param force Force image to state or let it finish then change + void setImageState(U32 imageSlot, U32 state, bool force = false); + /// @name Name & Skin tags /// @{ void setShapeName(const char*); @@ -1570,6 +1575,8 @@ public: /// @param pos Muzzle point (out) void getMuzzlePoint(U32 imageSlot,Point3F* pos); + bool setManualImageState(U32 imageSlot, const char* state); + /// @} /// @name Transforms @@ -1889,4 +1896,34 @@ inline WaterObject* ShapeBase::getCurrentWaterObject() return mCurrentWaterObject; } +//------------------------------------------------------------------------------ +// Manual shapeBaseImage state change NetEvent +//------------------------------------------------------------------------------ + +class ManualImageSetEvent : public NetEvent +{ + typedef NetEvent Parent; + + void pack(NetConnection*, BitStream*); + void write(NetConnection*, BitStream*){} + void unpack(NetConnection*, BitStream*); + void process(NetConnection*); + +public: + ManualImageSetEvent() { + mBadPacket = false; + mShapeBase = NULL; + mImageSlot = -1; + mState = -1; + }; + ~ManualImageSetEvent() {}; + + bool mBadPacket; + SimObjectPtr mShapeBase; + U32 mImageSlot; + S32 mState; + + DECLARE_CONOBJECT(ManualImageSetEvent); +}; + #endif // _H_SHAPEBASE_ diff --git a/Engine/source/T3D/shapeImage.cpp b/Engine/source/T3D/shapeImage.cpp index c25650c56..66a3c994e 100644 --- a/Engine/source/T3D/shapeImage.cpp +++ b/Engine/source/T3D/shapeImage.cpp @@ -3418,3 +3418,77 @@ void ShapeBase::shakeCamera( U32 imageSlot ) } } } + + bool ShapeBase::setManualImageState(U32 imageSlot, const char* state) + { + if(!isServerObject()) return false; + + MountedImage& image = mMountedImageList[imageSlot]; + S32 stateNum = image.dataBlock->lookupState(state); + if (image.dataBlock && stateNum > 0) { + + // Set the server-side image state + setImageState(imageSlot, stateNum, true); + + // Send the state change over the network + SimGroup* pClientGroup = Sim::getClientGroup(); + for (SimGroup::iterator itr = pClientGroup->begin(); itr != pClientGroup->end(); itr++) { + NetConnection* nc = static_cast(*itr); + if(nc->getGhostIndex(this) == -1) + continue; + + ManualImageSetEvent* imgEvnt = new ManualImageSetEvent; + + imgEvnt->mShapeBase = this; + imgEvnt->mImageSlot = imageSlot; + imgEvnt->mState = stateNum; + + nc->postNetEvent(imgEvnt); + } + return true; + } + return false; + } + + //------------------------------------------------------------------------------ + // Manual shapeBaseImage state change NetEvent + //------------------------------------------------------------------------------ + IMPLEMENT_CO_CLIENTEVENT_V1(ManualImageSetEvent); + + void ManualImageSetEvent::pack(NetConnection* conn, BitStream* stream) + { + if(stream->writeFlag(mShapeBase.isNull() || mImageSlot < 0 || mState < 0)) + return; + + S32 shapeId = conn->getGhostIndex(mShapeBase); + if(stream->writeFlag(shapeId != -1)) + stream->writeInt(shapeId, NetConnection::GhostIdBitSize); + + stream->writeRangedU32(mImageSlot, 0, ShapeBase::MaxMountedImages); + stream->writeInt(mState, 5); + } + + void ManualImageSetEvent::unpack(NetConnection* conn, BitStream* stream) + { + if(mBadPacket = stream->readFlag()) + return; + + if(stream->readFlag()) { + S32 shapeId = stream->readInt(NetConnection::GhostIdBitSize); + mShapeBase = dynamic_cast(conn->resolveGhost(shapeId)); + } + else { + mShapeBase = NULL; + mBadPacket = true; + } + + mImageSlot = stream->readRangedU32(0, ShapeBase::MaxMountedImages); + mState = stream->readInt(5); + } + + void ManualImageSetEvent::process(NetConnection* conn) + { + if(mBadPacket) + return; + mShapeBase->setImageState(mImageSlot, mState, true); + } \ No newline at end of file