| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586 |
- //-----------------------------------------------------------------------------
- // 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 "interior/pathedInterior.h"
- #include "core/stream/stream.h"
- #include "console/consoleTypes.h"
- #include "scene/sceneRenderState.h"
- #include "math/mathIO.h"
- #include "core/stream/bitStream.h"
- #include "interior/interior.h"
- #include "scene/simPath.h"
- #include "scene/pathManager.h"
- #include "core/frameAllocator.h"
- #include "scene/sceneManager.h"
- #include "sfx/sfxSystem.h"
- #include "sfx/sfxProfile.h"
- #include "sfx/sfxSource.h"
- #include "core/resourceManager.h"
- IMPLEMENT_CO_NETOBJECT_V1(PathedInterior);
- IMPLEMENT_CO_DATABLOCK_V1(PathedInteriorData);
- ConsoleDocClass( PathedInterior,
- "@brief Legacy interior related class, soon to be deprecated.\n\n"
- "Not intended for game development, for editors or internal use only.\n\n "
- "@internal");
- ConsoleDocClass( PathedInteriorData,
- "@brief Legacy interior related class, soon to be deprecated.\n\n"
- "Not intended for game development, for editors or internal use only.\n\n "
- "@internal");
- //--------------------------------------------------------------------------
- PathedInteriorData::PathedInteriorData()
- {
- for(U32 i = 0; i < MaxSounds; i++)
- sound[i] = NULL;
- }
- void PathedInteriorData::initPersistFields()
- {
- addField("StartSound", TYPEID< SFXProfile >(), Offset(sound[StartSound], PathedInteriorData));
- addField("SustainSound", TYPEID< SFXProfile >(), Offset(sound[SustainSound], PathedInteriorData));
- addField("StopSound", TYPEID< SFXProfile >(), Offset(sound[StopSound], PathedInteriorData));
- Parent::initPersistFields();
- }
- void PathedInteriorData::packData(BitStream *stream)
- {
- for (S32 i = 0; i < MaxSounds; i++)
- {
- if (stream->writeFlag(sound[i]))
- stream->writeRangedU32(packed? SimObjectId(sound[i]):
- sound[i]->getId(),DataBlockObjectIdFirst,DataBlockObjectIdLast);
- }
- Parent::packData(stream);
- }
- void PathedInteriorData::unpackData(BitStream* stream)
- {
- for (S32 i = 0; i < MaxSounds; i++) {
- sound[i] = NULL;
- if (stream->readFlag())
- sound[i] = (SFXProfile*)stream->readRangedU32(DataBlockObjectIdFirst,
- DataBlockObjectIdLast);
- }
- Parent::unpackData(stream);
- }
- bool PathedInteriorData::preload(bool server, String &errorStr)
- {
- if(!Parent::preload(server, errorStr))
- return false;
-
- // Resolve objects transmitted from server
- if (!server)
- {
- for (S32 i = 0; i < MaxSounds; i++)
- if (sound[i])
- Sim::findObject(SimObjectId(sound[i]),sound[i]);
- }
- return true;
- }
- PathedInterior::PathedInterior()
- {
- mNetFlags.set(Ghostable);
- mTypeMask = InteriorObjectType;
- mCurrentPosition = 0;
- mTargetPosition = 0;
- mPathKey = 0xFFFFFFFF;
- mStopped = false;
- mSustainSound = NULL;
- }
- PathedInterior::~PathedInterior()
- {
- //
- }
- PathedInterior *PathedInterior::mClientPathedInteriors = NULL;
- //--------------------------------------------------------------------------
- void PathedInterior::initPersistFields()
- {
- addField("interiorResource", TypeFilename, Offset(mInteriorResName, PathedInterior));
- addField("interiorIndex", TypeS32, Offset(mInteriorResIndex, PathedInterior));
- addField("basePosition", TypeMatrixPosition, Offset(mBaseTransform, PathedInterior));
- addField("baseRotation", TypeMatrixRotation, Offset(mBaseTransform, PathedInterior));
- addField("baseScale", TypePoint3F, Offset(mBaseScale, PathedInterior));
- Parent::initPersistFields();
- }
- //--------------------------------------------------------------------------
- bool PathedInterior::onAdd()
- {
- if(!Parent::onAdd())
- return false;
-
- // Load the interior resource and extract the interior that is us.
- mInteriorRes = ResourceManager::get().load(mInteriorResName);
- if (bool(mInteriorRes) == false)
- return false;
- mInterior = mInteriorRes->getSubObject(mInteriorResIndex);
- if (mInterior == NULL)
- return false;
- // Setup bounding information
- mObjBox = mInterior->getBoundingBox();
- resetWorldBox();
- setScale(mBaseScale);
- setTransform(mBaseTransform);
- if (isClientObject()) {
- mNextClientPI = mClientPathedInteriors;
- mClientPathedInteriors = this;
- mInterior->prepForRendering(mInteriorRes.getPath().getFullPath().c_str());
- // gInteriorLMManager.addInstance(mInterior->getLMHandle(), mLMHandle, NULL, this);
- }
- if(isClientObject())
- {
- Point3F initialPos( 0.0, 0.0, 0.0 );
- mBaseTransform.getColumn(3, &initialPos);
- Point3F pathPos( 0.0, 0.0, 0.0 );
- //gClientPathManager->getPathPosition(mPathKey, 0, pathPos);
- mOffset = initialPos - pathPos;
- //gClientPathManager->getPathPosition(mPathKey, mCurrentPosition, pathPos);
- MatrixF mat = getTransform();
- mat.setColumn(3, pathPos + mOffset);
- setTransform(mat);
- }
- addToScene();
- return true;
- }
- bool PathedInterior::onNewDataBlock( GameBaseData *dptr, bool reload )
- {
- mDataBlock = dynamic_cast<PathedInteriorData*>(dptr);
- if ( isClientObject() )
- {
- SFX_DELETE( mSustainSound );
- if ( mDataBlock->sound[PathedInteriorData::SustainSound] )
- mSustainSound = SFX->createSource( mDataBlock->sound[PathedInteriorData::SustainSound], &getTransform() );
- if ( mSustainSound )
- mSustainSound->play();
- }
- return Parent::onNewDataBlock(dptr,reload);
- }
- void PathedInterior::onRemove()
- {
- if(isClientObject())
- {
- SFX_DELETE( mSustainSound );
- PathedInterior **walk = &mClientPathedInteriors;
- while(*walk)
- {
- if(*walk == this)
- {
- *walk = mNextClientPI;
- break;
- }
- walk = &((*walk)->mNextClientPI);
- }
- /* if(bool(mInteriorRes) && mLMHandle != 0xFFFFFFFF)
- {
- if (mInterior->getLMHandle() != 0xFFFFFFFF)
- gInteriorLMManager.removeInstance(mInterior->getLMHandle(), mLMHandle);
- }*/
- }
- removeFromScene();
- Parent::onRemove();
- }
- //------------------------------------------------------------------------------
- bool PathedInterior::buildPolyList(AbstractPolyList* list, const Box3F& wsBox, const SphereF&)
- {
- if (bool(mInteriorRes) == false)
- return false;
- // Setup collision state data
- list->setTransform(&getTransform(), getScale());
- list->setObject(this);
- return mInterior->buildPolyList(list, wsBox, mWorldToObj, getScale());
- }
- //--------------------------------------------------------------------------
- void PathedInterior::prepRenderImage( SceneRenderState* state )
- {
- if (mPathKey == SimPath::Path::NoPathIndex)
- return;
- /*
- SceneRenderImage* image = new SceneRenderImage;
- image->obj = this;
- state->insertRenderImage(image);
- */
- }
- extern ColorF gInteriorFogColor;
- void PathedInterior::renderObject(SceneRenderState* state)
- {
- }
- void PathedInterior::resolvePathKey()
- {
- if(mPathKey == 0xFFFFFFFF && !isGhost())
- {
- mPathKey = getPathKey();
- Point3F pathPos( 0.0, 0.0, 0.0 );
- Point3F initialPos( 0.0, 0.0, 0.0 );
- mBaseTransform.getColumn(3, &initialPos);
- //gServerPathManager->getPathPosition(mPathKey, 0, pathPos);
- mOffset = initialPos - pathPos;
- }
- }
- //--------------------------------------------------------------------------
- U32 PathedInterior::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
- {
- U32 retMask = Parent::packUpdate(con, mask, stream);
- resolvePathKey();
- if (stream->writeFlag(mask & InitialUpdateMask))
- {
- // Inital update...
- stream->writeString(mInteriorResName);
- stream->write(mInteriorResIndex);
- stream->writeAffineTransform(mBaseTransform);
- mathWrite(*stream, mBaseScale);
- stream->write(mPathKey);
- }
- if(stream->writeFlag((mask & NewPositionMask) && mPathKey != SimPath::Path::NoPathIndex))
- stream->writeInt(S32(mCurrentPosition), gServerPathManager->getPathTimeBits(mPathKey));
- if(stream->writeFlag((mask & NewTargetMask) && mPathKey != SimPath::Path::NoPathIndex))
- {
- if(stream->writeFlag(mTargetPosition < 0))
- {
- stream->writeFlag(mTargetPosition == -1);
- }
- else
- stream->writeInt(S32(mTargetPosition), gServerPathManager->getPathTimeBits(mPathKey));
- }
- return retMask;
- }
- void PathedInterior::unpackUpdate(NetConnection* con, BitStream* stream)
- {
- Parent::unpackUpdate(con, stream);
- MatrixF tempXForm;
- Point3F tempScale;
- if (stream->readFlag())
- {
- // Initial
- mInteriorResName = stream->readSTString();
- stream->read(&mInteriorResIndex);
- stream->readAffineTransform(&tempXForm);
- mathRead(*stream, &tempScale);
- mBaseTransform = tempXForm;
- mBaseScale = tempScale;
- stream->read(&mPathKey);
- }
- if(stream->readFlag())
- {
- Point3F pathPos(0.0f, 0.0f, 0.0f);
- mCurrentPosition = stream->readInt(gClientPathManager->getPathTimeBits(mPathKey));
- if(isProperlyAdded())
- {
- //gClientPathManager->getPathPosition(mPathKey, mCurrentPosition, pathPos);
- MatrixF mat = getTransform();
- mat.setColumn(3, pathPos + mOffset);
- setTransform(mat);
- }
- }
- if(stream->readFlag())
- {
- if(stream->readFlag())
- {
- mTargetPosition = stream->readFlag() ? -1 : -2;
- }
- else
- mTargetPosition = stream->readInt(gClientPathManager->getPathTimeBits(mPathKey));
- }
- }
- void PathedInterior::processTick(const Move* move)
- {
- if(isServerObject())
- {
- S32 timeMs = 32;
- if(mCurrentPosition != mTargetPosition)
- {
- S32 delta;
- if(mTargetPosition == -1)
- delta = timeMs;
- else if(mTargetPosition == -2)
- delta = -timeMs;
- else
- {
- delta = mTargetPosition - (S32)mCurrentPosition;
- if(delta < -timeMs)
- delta = -timeMs;
- else if(delta > timeMs)
- delta = timeMs;
- }
- mCurrentPosition += delta;
- U32 totalTime = gClientPathManager->getPathTotalTime(mPathKey);
- while(mCurrentPosition > totalTime)
- mCurrentPosition -= totalTime;
- while(mCurrentPosition < 0)
- mCurrentPosition += totalTime;
- }
- }
- }
- void PathedInterior::computeNextPathStep(U32 timeDelta)
- {
- S32 timeMs = timeDelta;
- mStopped = false;
- if(mCurrentPosition == mTargetPosition)
- {
- mExtrudedBox = getWorldBox();
- mCurrentVelocity.set(0,0,0);
- }
- else
- {
- S32 delta = 0;
- if(mTargetPosition < 0)
- {
- if(mTargetPosition == -1)
- delta = timeMs;
- else if(mTargetPosition == -2)
- delta = -timeMs;
-
- mCurrentPosition += delta;
- U32 totalTime = gClientPathManager->getPathTotalTime(mPathKey);
-
- while(mCurrentPosition >= totalTime)
- mCurrentPosition -= totalTime;
-
- while(mCurrentPosition < 0)
- mCurrentPosition += totalTime;
- }
- else
- {
- delta = mTargetPosition - (S32)mCurrentPosition;
- if(delta < -timeMs)
- delta = -timeMs;
- else if(delta > timeMs)
- delta = timeMs;
- mCurrentPosition += delta;
- }
- Point3F curPoint;
- Point3F newPoint( 0.0, 0.0, 0.0 );
- MatrixF mat = getTransform();
- mat.getColumn(3, &curPoint);
- //gClientPathManager->getPathPosition(mPathKey, mCurrentPosition, newPoint);
- newPoint += mOffset;
- Point3F displaceDelta = newPoint - curPoint;
- mExtrudedBox = getWorldBox();
- if(displaceDelta.x < 0)
- mExtrudedBox.minExtents.x += displaceDelta.x;
- else
- mExtrudedBox.maxExtents.x += displaceDelta.x;
- if(displaceDelta.y < 0)
- mExtrudedBox.minExtents.y += displaceDelta.y;
- else
- mExtrudedBox.maxExtents.y += displaceDelta.y;
- if(displaceDelta.z < 0)
- mExtrudedBox.minExtents.z += displaceDelta.z;
- else
- mExtrudedBox.maxExtents.z += displaceDelta.z;
- mCurrentVelocity = displaceDelta * 1000 / F32(timeDelta);
- }
- Point3F pos;
- mExtrudedBox.getCenter(&pos);
- MatrixF mat = getTransform();
- mat.setColumn(3, pos);
- if ( mSustainSound )
- {
- mSustainSound->setTransform( mat );
- mSustainSound->setVelocity( getVelocity() );
- }
- }
- Point3F PathedInterior::getVelocity()
- {
- return mCurrentVelocity;
- }
- void PathedInterior::advance(F64 timeDelta)
- {
- if(mStopped)
- return;
- if(mCurrentVelocity.len() == 0)
- {
- // if(mSustainHandle)
- // {
- // alxStop(mSustainHandle);
- // mSustainHandle = 0;
- // }
- return;
- }
- MatrixF mat = getTransform();
- Point3F newPoint;
- mat.getColumn(3, &newPoint);
- newPoint += mCurrentVelocity * timeDelta / 1000.0f;
- //gClientPathManager->getPathPosition(mPathKey, mCurrentPosition, newPoint);
- mat.setColumn(3, newPoint);// + mOffset);
- setTransform(mat);
- setRenderTransform(mat);
- }
- U32 PathedInterior::getPathKey()
- {
- AssertFatal(isServerObject(), "Error, must be a server object to call this...");
- SimGroup* myGroup = getGroup();
- AssertFatal(myGroup != NULL, "No group for this object?");
- for (SimGroup::iterator itr = myGroup->begin(); itr != myGroup->end(); itr++) {
- SimPath::Path* pPath = dynamic_cast<SimPath::Path*>(*itr);
- if (pPath != NULL) {
- U32 pathKey = pPath->getPathIndex();
- AssertFatal(pathKey != SimPath::Path::NoPathIndex, "Error, path must have event over at this point...");
- return pathKey;
- }
- }
- return SimPath::Path::NoPathIndex;
- }
- void PathedInterior::setPathPosition(S32 newPosition)
- {
- resolvePathKey();
- if(newPosition < 0)
- newPosition = 0;
- if(newPosition > S32(gServerPathManager->getPathTotalTime(mPathKey)))
- newPosition = S32(gServerPathManager->getPathTotalTime(mPathKey));
- mCurrentPosition = mTargetPosition = newPosition;
- setMaskBits(NewPositionMask | NewTargetMask);
- }
- void PathedInterior::setTargetPosition(S32 newPosition)
- {
- resolvePathKey();
- if(newPosition < -2)
- newPosition = 0;
- if(newPosition > S32(gServerPathManager->getPathTotalTime(mPathKey)))
- newPosition = gServerPathManager->getPathTotalTime(mPathKey);
- if(mTargetPosition != newPosition)
- {
- mTargetPosition = newPosition;
- setMaskBits(NewTargetMask);
- }
- }
- ConsoleMethod(PathedInterior, setPathPosition, void, 3, 3, "")
- {
- ((PathedInterior *) object)->setPathPosition(dAtoi(argv[2]));
- }
- ConsoleMethod(PathedInterior, setTargetPosition, void, 3, 3, "")
- {
- ((PathedInterior *) object)->setTargetPosition(dAtoi(argv[2]));
- }
- //--------------------------------------------------------------------------
- bool PathedInterior::readPI(Stream& stream)
- {
- mName = stream.readSTString();
- mInteriorResName = stream.readSTString();
- stream.read(&mInteriorResIndex);
- stream.read(&mPathIndex);
- mathRead(stream, &mOffset);
- U32 numTriggers;
- stream.read(&numTriggers);
- mTriggers.setSize(numTriggers);
- for (S32 i = 0; i < mTriggers.size(); i++)
- mTriggers[i] = stream.readSTString();
- return (stream.getStatus() == Stream::Ok);
- }
- bool PathedInterior::writePI(Stream& stream) const
- {
- stream.writeString(mName);
- stream.writeString(mInteriorResName);
- stream.write(mInteriorResIndex);
- stream.write(mPathIndex);
- mathWrite(stream, mOffset);
- stream.write(mTriggers.size());
- for (S32 i = 0; i < mTriggers.size(); i++)
- stream.writeString(mTriggers[i]);
- return (stream.getStatus() == Stream::Ok);
- }
- PathedInterior* PathedInterior::clone() const
- {
- PathedInterior* pClone = new PathedInterior;
-
- pClone->mName = mName;
- pClone->mInteriorResName = mInteriorResName;
- pClone->mInteriorResIndex = mInteriorResIndex;
- pClone->mPathIndex = mPathIndex;
- pClone->mOffset = mOffset;
- return pClone;
- }
|