diff options
Diffstat (limited to 'indra/newview/llviewerobject.cpp')
-rwxr-xr-x[-rw-r--r--] | indra/newview/llviewerobject.cpp | 979 |
1 files changed, 776 insertions, 203 deletions
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index b1a60197a2..a2c0a91ea6 100644..100755 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -29,7 +29,6 @@ #include "llviewerobject.h" #include "llaudioengine.h" -#include "imageids.h" #include "indra_constants.h" #include "llmath.h" #include "llflexibleobject.h" @@ -39,6 +38,7 @@ #include "llfloaterreg.h" #include "llfontgl.h" #include "llframetimer.h" +#include "llhudicon.h" #include "llinventory.h" #include "llinventorydefines.h" #include "llmaterialtable.h" @@ -52,11 +52,11 @@ #include "llxfermanager.h" #include "message.h" #include "object_flags.h" -#include "timing.h" #include "llaudiosourcevo.h" #include "llagent.h" #include "llagentcamera.h" +#include "llagentwearables.h" #include "llbbox.h" #include "llbox.h" #include "llcylinder.h" @@ -100,6 +100,8 @@ #include "lltrans.h" #include "llsdutil.h" #include "llmediaentry.h" +#include "llfloaterperms.h" +#include "llvocache.h" //#define DEBUG_UPDATE_TYPE @@ -112,21 +114,33 @@ BOOL LLViewerObject::sMapDebug = TRUE; LLColor4 LLViewerObject::sEditSelectColor( 1.0f, 1.f, 0.f, 0.3f); // Edit OK LLColor4 LLViewerObject::sNoEditSelectColor( 1.0f, 0.f, 0.f, 0.3f); // Can't edit S32 LLViewerObject::sAxisArrowLength(50); + + BOOL LLViewerObject::sPulseEnabled(FALSE); BOOL LLViewerObject::sUseSharedDrawables(FALSE); // TRUE // sMaxUpdateInterpolationTime must be greater than sPhaseOutUpdateInterpolationTime -F64 LLViewerObject::sMaxUpdateInterpolationTime = 3.0; // For motion interpolation: after X seconds with no updates, don't predict object motion -F64 LLViewerObject::sPhaseOutUpdateInterpolationTime = 2.0; // For motion interpolation: after Y seconds with no updates, taper off motion prediction +F64Seconds LLViewerObject::sMaxUpdateInterpolationTime(3.0); // For motion interpolation: after X seconds with no updates, don't predict object motion +F64Seconds LLViewerObject::sPhaseOutUpdateInterpolationTime(2.0); // For motion interpolation: after Y seconds with no updates, taper off motion prediction + +std::map<std::string, U32> LLViewerObject::sObjectDataMap; +// The maximum size of an object extra parameters binary (packed) block +#define MAX_OBJECT_PARAMS_SIZE 1024 -static LLFastTimer::DeclareTimer FTM_CREATE_OBJECT("Create Object"); +// At 45 Hz collisions seem stable and objects seem +// to settle down at a reasonable rate. +// JC 3/18/2003 + +const F32 PHYSICS_TIMESTEP = 1.f / 45.f; + +static LLTrace::BlockTimerStatHandle FTM_CREATE_OBJECT("Create Object"); // static LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) { LLViewerObject *res = NULL; - LLFastTimer t1(FTM_CREATE_OBJECT); + LL_RECORD_BLOCK_TIME(FTM_CREATE_OBJECT); switch (pcode) { @@ -140,6 +154,7 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco { gAgentAvatarp = new LLVOAvatarSelf(id, pcode, regionp); gAgentAvatarp->initInstance(); + gAgentWearables.setAvatarObject(gAgentAvatarp); } else { @@ -161,13 +176,13 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco case LL_PCODE_LEGACY_GRASS: res = new LLVOGrass(id, pcode, regionp); break; case LL_PCODE_LEGACY_PART_SYS: -// llwarns << "Creating old part sys!" << llendl; +// LL_WARNS() << "Creating old part sys!" << LL_ENDL; // res = new LLVOPart(id, pcode, regionp); break; res = NULL; break; case LL_PCODE_LEGACY_TREE: res = new LLVOTree(id, pcode, regionp); break; case LL_PCODE_TREE_NEW: -// llwarns << "Creating new tree!" << llendl; +// LL_WARNS() << "Creating new tree!" << LL_ENDL; // res = new LLVOTree(id, pcode, regionp); break; res = NULL; break; case LL_VO_SURFACE_PATCH: @@ -187,20 +202,23 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco case LL_VO_WL_SKY: res = new LLVOWLSky(id, pcode, regionp); break; default: - llwarns << "Unknown object pcode " << (S32)pcode << llendl; + LL_WARNS() << "Unknown object pcode " << (S32)pcode << LL_ENDL; res = NULL; break; } return res; } LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp, BOOL is_global) -: LLPrimitive(), +: LLTrace::MemTrackable<LLViewerObject>("LLViewerObject"), + LLPrimitive(), mChildList(), mID(id), mLocalID(0), mTotalCRC(0), mListIndex(-1), mTEImages(NULL), + mTENormalMaps(NULL), + mTESpecularMaps(NULL), mGLName(0), mbCanSelect(TRUE), mFlags(0), @@ -234,7 +252,6 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mOnMap(FALSE), mStatic(FALSE), mNumFaces(0), - mTimeDilation(1.f), mRotTime(0.f), mAngularVelocityRot(), mPreviousRotation(), @@ -321,22 +338,45 @@ void LLViewerObject::deleteTEImages() { delete[] mTEImages; mTEImages = NULL; + + if (mTENormalMaps != NULL) + { + delete[] mTENormalMaps; + mTENormalMaps = NULL; + } + + if (mTESpecularMaps != NULL) + { + delete[] mTESpecularMaps; + mTESpecularMaps = NULL; + } } void LLViewerObject::markDead() { if (!mDead) { - //llinfos << "Marking self " << mLocalID << " as dead." << llendl; + //LL_INFOS() << "Marking self " << mLocalID << " as dead." << LL_ENDL; // Root object of this hierarchy unlinks itself. + LLVOAvatar *av = getAvatarAncestor(); if (getParent()) { ((LLViewerObject *)getParent())->removeChild(this); } + LLUUID mesh_id; + if (av && LLVOAvatar::getRiggedMeshID(this,mesh_id)) + { + // This case is needed for indirectly attached mesh objects. + av->resetJointPositionsOnDetach(mesh_id); + } // Mark itself as dead mDead = TRUE; + if(mRegionp) + { + mRegionp->removeFromCreatedList(getLocalID()); + } gObjectList.cleanupReferences(this); LLViewerObject *childp; @@ -345,7 +385,7 @@ void LLViewerObject::markDead() childp = mChildList.back(); if (childp->getPCode() != LL_PCODE_LEGACY_AVATAR) { - //llinfos << "Marking child " << childp->getLocalID() << " as dead." << llendl; + //LL_INFOS() << "Marking child " << childp->getLocalID() << " as dead." << LL_ENDL; childp->setParent(NULL); // LLViewerObject::markDead 1 childp->markDead(); } @@ -415,17 +455,17 @@ void LLViewerObject::markDead() void LLViewerObject::dump() const { - llinfos << "Type: " << pCodeToString(mPrimitiveCode) << llendl; - llinfos << "Drawable: " << (LLDrawable *)mDrawable << llendl; - llinfos << "Update Age: " << LLFrameTimer::getElapsedSeconds() - mLastMessageUpdateSecs << llendl; - - llinfos << "Parent: " << getParent() << llendl; - llinfos << "ID: " << mID << llendl; - llinfos << "LocalID: " << mLocalID << llendl; - llinfos << "PositionRegion: " << getPositionRegion() << llendl; - llinfos << "PositionAgent: " << getPositionAgent() << llendl; - llinfos << "PositionGlobal: " << getPositionGlobal() << llendl; - llinfos << "Velocity: " << getVelocity() << llendl; + LL_INFOS() << "Type: " << pCodeToString(mPrimitiveCode) << LL_ENDL; + LL_INFOS() << "Drawable: " << (LLDrawable *)mDrawable << LL_ENDL; + LL_INFOS() << "Update Age: " << LLFrameTimer::getElapsedSeconds() - mLastMessageUpdateSecs << LL_ENDL; + + LL_INFOS() << "Parent: " << getParent() << LL_ENDL; + LL_INFOS() << "ID: " << mID << LL_ENDL; + LL_INFOS() << "LocalID: " << mLocalID << LL_ENDL; + LL_INFOS() << "PositionRegion: " << getPositionRegion() << LL_ENDL; + LL_INFOS() << "PositionAgent: " << getPositionAgent() << LL_ENDL; + LL_INFOS() << "PositionGlobal: " << getPositionGlobal() << LL_ENDL; + LL_INFOS() << "Velocity: " << getVelocity() << LL_ENDL; if (mDrawable.notNull() && mDrawable->getNumFaces() && mDrawable->getFace(0)) @@ -433,31 +473,31 @@ void LLViewerObject::dump() const LLFacePool *poolp = mDrawable->getFace(0)->getPool(); if (poolp) { - llinfos << "Pool: " << poolp << llendl; - llinfos << "Pool reference count: " << poolp->mReferences.size() << llendl; + LL_INFOS() << "Pool: " << poolp << LL_ENDL; + LL_INFOS() << "Pool reference count: " << poolp->mReferences.size() << LL_ENDL; } } - //llinfos << "BoxTree Min: " << mDrawable->getBox()->getMin() << llendl; - //llinfos << "BoxTree Max: " << mDrawable->getBox()->getMin() << llendl; + //LL_INFOS() << "BoxTree Min: " << mDrawable->getBox()->getMin() << LL_ENDL; + //LL_INFOS() << "BoxTree Max: " << mDrawable->getBox()->getMin() << LL_ENDL; /* - llinfos << "Velocity: " << getVelocity() << llendl; - llinfos << "AnyOwner: " << permAnyOwner() << " YouOwner: " << permYouOwner() << " Edit: " << mPermEdit << llendl; - llinfos << "UsePhysics: " << flagUsePhysics() << " CanSelect " << mbCanSelect << " UserSelected " << mUserSelected << llendl; - llinfos << "AppAngle: " << mAppAngle << llendl; - llinfos << "PixelArea: " << mPixelArea << llendl; + LL_INFOS() << "Velocity: " << getVelocity() << LL_ENDL; + LL_INFOS() << "AnyOwner: " << permAnyOwner() << " YouOwner: " << permYouOwner() << " Edit: " << mPermEdit << LL_ENDL; + LL_INFOS() << "UsePhysics: " << flagUsePhysics() << " CanSelect " << mbCanSelect << " UserSelected " << mUserSelected << LL_ENDL; + LL_INFOS() << "AppAngle: " << mAppAngle << LL_ENDL; + LL_INFOS() << "PixelArea: " << mPixelArea << LL_ENDL; char buffer[1000]; char *key; for (key = mNameValuePairs.getFirstKey(); key; key = mNameValuePairs.getNextKey() ) { mNameValuePairs[key]->printNameValue(buffer); - llinfos << buffer << llendl; + LL_INFOS() << buffer << LL_ENDL; } for (child_list_t::iterator iter = mChildList.begin(); iter != mChildList.end(); iter++) { LLViewerObject* child = *iter; - llinfos << " child " << child->getID() << llendl; + LL_INFOS() << " child " << child->getID() << LL_ENDL; } */ } @@ -468,7 +508,7 @@ void LLViewerObject::printNameValuePairs() const iter != mNameValuePairs.end(); iter++) { LLNameValue* nv = iter->second; - llinfos << nv->printNameValue() << llendl; + LL_INFOS() << nv->printNameValue() << LL_ENDL; } } @@ -477,10 +517,12 @@ void LLViewerObject::initVOClasses() // Initialized shared class stuff first. LLVOAvatar::initClass(); LLVOTree::initClass(); - llinfos << "Viewer Object size: " << sizeof(LLViewerObject) << llendl; + LL_INFOS() << "Viewer Object size: " << sizeof(LLViewerObject) << LL_ENDL; LLVOGrass::initClass(); LLVOWater::initClass(); LLVOVolume::initClass(); + + initObjectDataMap(); } void LLViewerObject::cleanupVOClasses() @@ -490,6 +532,118 @@ void LLViewerObject::cleanupVOClasses() LLVOTree::cleanupClass(); LLVOAvatar::cleanupClass(); LLVOVolume::cleanupClass(); + + sObjectDataMap.clear(); +} + +//object data map for compressed && !OUT_TERSE_IMPROVED +//static +void LLViewerObject::initObjectDataMap() +{ + U32 count = 0; + + sObjectDataMap["ID"] = count; //full id //LLUUID + count += sizeof(LLUUID); + + sObjectDataMap["LocalID"] = count; //U32 + count += sizeof(U32); + + sObjectDataMap["PCode"] = count; //U8 + count += sizeof(U8); + + sObjectDataMap["State"] = count; //U8 + count += sizeof(U8); + + sObjectDataMap["CRC"] = count; //U32 + count += sizeof(U32); + + sObjectDataMap["Material"] = count; //U8 + count += sizeof(U8); + + sObjectDataMap["ClickAction"] = count; //U8 + count += sizeof(U8); + + sObjectDataMap["Scale"] = count; //LLVector3 + count += sizeof(LLVector3); + + sObjectDataMap["Pos"] = count; //LLVector3 + count += sizeof(LLVector3); + + sObjectDataMap["Rot"] = count; //LLVector3 + count += sizeof(LLVector3); + + sObjectDataMap["SpecialCode"] = count; //U32 + count += sizeof(U32); + + sObjectDataMap["Owner"] = count; //LLUUID + count += sizeof(LLUUID); + + sObjectDataMap["Omega"] = count; //LLVector3, when SpecialCode & 0x80 is set + count += sizeof(LLVector3); + + //ParentID is after Omega if there is Omega, otherwise is after Owner + sObjectDataMap["ParentID"] = count;//U32, when SpecialCode & 0x20 is set + count += sizeof(U32); + + //------- + //The rest items are not included here + //------- +} + +//static +void LLViewerObject::unpackVector3(LLDataPackerBinaryBuffer* dp, LLVector3& value, std::string name) +{ + dp->shift(sObjectDataMap[name]); + dp->unpackVector3(value, name.c_str()); + dp->reset(); +} + +//static +void LLViewerObject::unpackUUID(LLDataPackerBinaryBuffer* dp, LLUUID& value, std::string name) +{ + dp->shift(sObjectDataMap[name]); + dp->unpackUUID(value, name.c_str()); + dp->reset(); +} + +//static +void LLViewerObject::unpackU32(LLDataPackerBinaryBuffer* dp, U32& value, std::string name) +{ + dp->shift(sObjectDataMap[name]); + dp->unpackU32(value, name.c_str()); + dp->reset(); +} + +//static +void LLViewerObject::unpackU8(LLDataPackerBinaryBuffer* dp, U8& value, std::string name) +{ + dp->shift(sObjectDataMap[name]); + dp->unpackU8(value, name.c_str()); + dp->reset(); +} + +//static +U32 LLViewerObject::unpackParentID(LLDataPackerBinaryBuffer* dp, U32& parent_id) +{ + dp->shift(sObjectDataMap["SpecialCode"]); + U32 value; + dp->unpackU32(value, "SpecialCode"); + + parent_id = 0; + if(value & 0x20) + { + S32 offset = sObjectDataMap["ParentID"]; + if(!(value & 0x80)) + { + offset -= sizeof(LLVector3); + } + + dp->shift(offset); + dp->unpackU32(parent_id, "ParentID"); + } + dp->reset(); + + return parent_id; } // Replaces all name value pairs with data from \n delimited list @@ -516,6 +670,17 @@ void LLViewerObject::setNameValueList(const std::string& name_value_list) } } +void LLViewerObject::setSelected(BOOL sel) +{ + mUserSelected = sel; + resetRot(); + + if (!sel) + { + setAllTESelected(false); + } +} + // This method returns true if the object is over land owned by the // agent. bool LLViewerObject::isReturnable() @@ -589,7 +754,7 @@ void LLViewerObject::buildReturnablesForChildrenVO( std::vector<PotentialReturna { if ( !pChild ) { - llerrs<<"child viewerobject is NULL "<<llendl; + LL_ERRS()<<"child viewerobject is NULL "<<LL_ENDL; } constructAndAddReturnable( returnables, pChild, pTargetRegion ); @@ -870,26 +1035,47 @@ U32 LLViewerObject::checkMediaURL(const std::string &media_url) return retval; } +//extract spatial information from object update message +//return parent_id +//static +U32 LLViewerObject::extractSpatialExtents(LLDataPackerBinaryBuffer *dp, LLVector3& pos, LLVector3& scale, LLQuaternion& rot) +{ + U32 parent_id = 0; + LLViewerObject::unpackParentID(dp, parent_id); + + LLViewerObject::unpackVector3(dp, scale, "Scale"); + LLViewerObject::unpackVector3(dp, pos, "Pos"); + + LLVector3 vec; + LLViewerObject::unpackVector3(dp, vec, "Rot"); + rot.unpackFromVector3(vec); + + return parent_id; +} + U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, U32 block_num, const EObjectUpdateType update_type, LLDataPacker *dp) { + LL_DEBUGS_ONCE("SceneLoadTiming") << "Received viewer object data" << LL_ENDL; + U32 retval = 0x0; // If region is removed from the list it is also deleted. if (!LLWorld::instance().isRegionListed(mRegionp)) { - llwarns << "Updating object in an invalid region" << llendl; + LL_WARNS() << "Updating object in an invalid region" << LL_ENDL; return retval; } // Coordinates of objects on simulators are region-local. - U64 region_handle; - mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle); + U64 region_handle = 0; + if(mesgsys != NULL) { + mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle); LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromHandle(region_handle); if(regionp != mRegionp && regionp && mRegionp)//region cross { @@ -902,6 +1088,17 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, } else { + if(regionp != mRegionp) + { + if(mRegionp) + { + mRegionp->removeFromCreatedList(getLocalID()); + } + if(regionp) + { + regionp->addToCreatedList(getLocalID()); + } + } mRegionp = regionp ; } } @@ -911,15 +1108,18 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, U32 x, y; from_region_handle(region_handle, &x, &y); - llerrs << "Object has invalid region " << x << ":" << y << "!" << llendl; + LL_ERRS() << "Object has invalid region " << x << ":" << y << "!" << LL_ENDL; return retval; } + F32 time_dilation = 1.f; + if(mesgsys != NULL) + { U16 time_dilation16; mesgsys->getU16Fast(_PREHASH_RegionData, _PREHASH_TimeDilation, time_dilation16); - F32 time_dilation = ((F32) time_dilation16) / 65535.f; - mTimeDilation = time_dilation; + time_dilation = ((F32) time_dilation16) / 65535.f; mRegionp->setTimeDilation(time_dilation); + } // this will be used to determine if we've really changed position // Use getPosition, not getPositionRegion, since this is what we're comparing directly against. @@ -967,7 +1167,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, case OUT_FULL: { #ifdef DEBUG_UPDATE_TYPE - llinfos << "Full:" << getID() << llendl; + LL_INFOS() << "Full:" << getID() << LL_ENDL; #endif //clear cost and linkset cost mCostStale = true; @@ -1273,7 +1473,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, S32 param_size; dp.unpackU16(param_type, "param_type"); dp.unpackBinaryData(param_block, param_size, "param_data"); - //llinfos << "Param type: " << param_type << ", Size: " << param_size << llendl; + //LL_INFOS() << "Param type: " << param_type << ", Size: " << param_size << LL_ENDL; LLDataPackerBinaryBuffer dp2(param_block, param_size); unpackParameterEntry(param_type, &dp2); } @@ -1295,7 +1495,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, case OUT_TERSE_IMPROVED: { #ifdef DEBUG_UPDATE_TYPE - llinfos << "TI:" << getID() << llendl; + LL_INFOS() << "TI:" << getID() << LL_ENDL; #endif length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ObjectData); mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num); @@ -1472,7 +1672,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, case OUT_TERSE_IMPROVED: { #ifdef DEBUG_UPDATE_TYPE - llinfos << "CompTI:" << getID() << llendl; + LL_INFOS() << "CompTI:" << getID() << LL_ENDL; #endif U8 value; dp->unpackU8(value, "agent"); @@ -1518,7 +1718,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, case OUT_FULL_CACHED: { #ifdef DEBUG_UPDATE_TYPE - llinfos << "CompFull:" << getID() << llendl; + LL_INFOS() << "CompFull:" << getID() << LL_ENDL; #endif mCostStale = true; @@ -1553,6 +1753,8 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, dp->setPassFlags(value); dp->unpackUUID(owner_id, "Owner"); + mOwnerID = owner_id; + if (value & 0x80) { dp->unpackVector3(new_angv, "Omega"); @@ -1626,13 +1828,13 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, retval |= checkMediaURL(media_url); // - // Unpack particle system data + // Unpack particle system data (legacy) // if (value & 0x8) { - unpackParticleSource(*dp, owner_id); + unpackParticleSource(*dp, owner_id, true); } - else + else if (!(value & 0x400)) { deleteParticleSource(); } @@ -1654,7 +1856,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, S32 param_size; dp->unpackU16(param_type, "param_type"); dp->unpackBinaryData(param_block, param_size, "param_data"); - //llinfos << "Param type: " << param_type << ", Size: " << param_size << llendl; + //LL_INFOS() << "Param type: " << param_type << ", Size: " << param_size << LL_ENDL; LLDataPackerBinaryBuffer dp2(param_block, param_size); unpackParameterEntry(param_type, &dp2); } @@ -1692,13 +1894,12 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // Preload these five flags for every object. // Finer shades require the object to be selected, and the selection manager // stores the extended permission info. + if(mesgsys != NULL) + { U32 flags; mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num); - // keep local flags and overwrite remote-controlled flags - mFlags = (mFlags & FLAGS_LOCAL) | flags; - - // ...new objects that should come in selected need to be added to the selected list - mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0); + loadFlags(flags); + } } break; @@ -1726,10 +1927,21 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, { // No parent now, new parent in message -> attach to that parent if possible LLUUID parent_uuid; + + if(mesgsys != NULL) + { LLViewerObjectList::getUUIDFromLocal(parent_uuid, parent_id, mesgsys->getSenderIP(), mesgsys->getSenderPort()); + } + else + { + LLViewerObjectList::getUUIDFromLocal(parent_uuid, + parent_id, + mRegionp->getHost().getAddress(), + mRegionp->getHost().getPort()); + } LLViewerObject *sent_parentp = gObjectList.findObject(parent_uuid); @@ -1739,7 +1951,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, if (sent_parentp && sent_parentp->getParent() == this) { // Try to recover if we attempt to attach a parent to its child - llwarns << "Attempt to attach a parent to it's child: " << this->getID() << " to " << sent_parentp->getID() << llendl; + LL_WARNS() << "Attempt to attach a parent to it's child: " << this->getID() << " to " << sent_parentp->getID() << LL_ENDL; this->removeChild(sent_parentp); sent_parentp->setDrawableParent(NULL); } @@ -1758,7 +1970,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, { if (mDrawable->isDead() || !mDrawable->getVObj()) { - llwarns << "Drawable is dead or no VObj!" << llendl; + LL_WARNS() << "Drawable is dead or no VObj!" << LL_ENDL; sent_parentp->addChild(this); } else @@ -1768,9 +1980,9 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // Bad, we got a cycle somehow. // Kill both the parent and the child, and // set cache misses for both of them. - llwarns << "Attempting to recover from parenting cycle!" << llendl; - llwarns << "Killing " << sent_parentp->getID() << " and " << getID() << llendl; - llwarns << "Adding to cache miss list" << llendl; + LL_WARNS() << "Attempting to recover from parenting cycle!" << LL_ENDL; + LL_WARNS() << "Killing " << sent_parentp->getID() << " and " << getID() << LL_ENDL; + LL_WARNS() << "Adding to cache miss list" << LL_ENDL; setParent(NULL); sent_parentp->setParent(NULL); getRegion()->addCacheMissFull(getLocalID()); @@ -1805,9 +2017,18 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // //parent_id - U32 ip = mesgsys->getSenderIP(); - U32 port = mesgsys->getSenderPort(); + U32 ip, port; + if(mesgsys != NULL) + { + ip = mesgsys->getSenderIP(); + port = mesgsys->getSenderPort(); + } + else + { + ip = mRegionp->getHost().getAddress(); + port = mRegionp->getHost().getPort(); + } gObjectList.orphanize(this, parent_id, ip, port); // Hide particles, icon and HUD @@ -1828,7 +2049,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, //LLViewerObjectList::getUUIDFromLocal(parent_uuid, parent_id, mesgsys->getSenderIP(), mesgsys->getSenderPort() ); //if (parent_uuid != cur_parentp->getID() ) //{ - // llerrs << "Local ID match but UUID mismatch of viewer object" << llendl; + // LL_ERRS() << "Local ID match but UUID mismatch of viewer object" << LL_ENDL; //} } else @@ -1845,10 +2066,21 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, else { LLUUID parent_uuid; + + if(mesgsys != NULL) + { LLViewerObjectList::getUUIDFromLocal(parent_uuid, parent_id, gMessageSystem->getSenderIP(), gMessageSystem->getSenderPort()); + } + else + { + LLViewerObjectList::getUUIDFromLocal(parent_uuid, + parent_id, + mRegionp->getHost().getAddress(), + mRegionp->getHost().getPort()); + } sent_parentp = gObjectList.findObject(parent_uuid); if (isAvatar()) @@ -1869,8 +2101,18 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // // Switching parents, but we don't know the new parent. // - U32 ip = mesgsys->getSenderIP(); - U32 port = mesgsys->getSenderPort(); + U32 ip, port; + + if(mesgsys != NULL) + { + ip = mesgsys->getSenderIP(); + port = mesgsys->getSenderPort(); + } + else + { + ip = mRegionp->getHost().getAddress(); + port = mRegionp->getHost().getPort(); + } // We're an orphan, flag things appropriately. gObjectList.orphanize(this, parent_id, ip, port); @@ -1889,9 +2131,9 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // Bad, we got a cycle somehow. // Kill both the parent and the child, and // set cache misses for both of them. - llwarns << "Attempting to recover from parenting cycle!" << llendl; - llwarns << "Killing " << sent_parentp->getID() << " and " << getID() << llendl; - llwarns << "Adding to cache miss list" << llendl; + LL_WARNS() << "Attempting to recover from parenting cycle!" << LL_ENDL; + LL_WARNS() << "Killing " << sent_parentp->getID() << " and " << getID() << LL_ENDL; + LL_WARNS() << "Adding to cache miss list" << LL_ENDL; setParent(NULL); sent_parentp->setParent(NULL); getRegion()->addCacheMissFull(getLocalID()); @@ -1923,7 +2165,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // This is probably an object flying across a region boundary, the // object probably ISN'T being reparented, but just got an object // update out of order (child update before parent). - //llinfos << "Don't reparent object handoffs!" << llendl; + //LL_INFOS() << "Don't reparent object handoffs!" << LL_ENDL; remove_parent = false; } } @@ -1954,18 +2196,18 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, new_rot.normQuat(); - if (sPingInterpolate) + if (sPingInterpolate && mesgsys != NULL) { LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mesgsys->getSender()); if (cdp) { - F32 ping_delay = 0.5f * mTimeDilation * ( ((F32)cdp->getPingDelay()) * 0.001f + gFrameDTClamped); + F32 ping_delay = 0.5f * time_dilation * ( ((F32)cdp->getPingDelay().valueInUnits<LLUnits::Seconds>()) + gFrameDTClamped); LLVector3 diff = getVelocity() * ping_delay; new_pos_parent += diff; } else { - llwarns << "findCircuit() returned NULL; skipping interpolation" << llendl; + LL_WARNS() << "findCircuit() returned NULL; skipping interpolation" << LL_ENDL; } } @@ -1977,6 +2219,8 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // If we're going to skip this message, why are we // doing all the parenting, etc above? + if(mesgsys != NULL) + { U32 packet_id = mesgsys->getCurrentRecvPacketID(); if (packet_id < mLatestRecvPacketID && mLatestRecvPacketID - packet_id < 65536) @@ -1984,8 +2228,8 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, //skip application of this message, it's old return retval; } - mLatestRecvPacketID = packet_id; + } // Set the change flags for scale if (new_scale != getScale()) @@ -2017,7 +2261,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, } else { - llwarns << "Can not move the object/avatar to an infinite location!" << llendl ; + LL_WARNS() << "Can not move the object/avatar to an infinite location!" << LL_ENDL ; retval |= INVALID_UPDATE ; } @@ -2033,11 +2277,11 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // If we're snapping the position by more than 0.5m, update LLViewerStats::mAgentPositionSnaps if ( asAvatar() && asAvatar()->isSelf() && (mag_sqr > 0.25f) ) { - LLViewerStats::getInstance()->mAgentPositionSnaps.push( diff.length() ); + record(LLStatViewer::AGENT_POSITION_SNAP, LLUnit<F64, LLUnits::Meters>(diff.length())); } } - if ((new_rot != getRotation()) + if ((new_rot.isNotEqualEps(getRotation(), F_ALMOST_ZERO)) || (new_angv != old_angv)) { if (new_rot != mPreviousRotation) @@ -2134,8 +2378,9 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // Don't clear invisibility flag on update if still orphaned! if (mDrawable->isState(LLDrawable::FORCE_INVISIBLE) && !mOrphaned) { -// lldebugs << "Clearing force invisible: " << mID << ":" << getPCodeString() << ":" << getPositionAgent() << llendl; - mDrawable->setState(LLDrawable::CLEAR_INVISIBLE); +// LL_DEBUGS() << "Clearing force invisible: " << mID << ":" << getPCodeString() << ":" << getPositionAgent() << LL_ENDL; + mDrawable->clearState(LLDrawable::FORCE_INVISIBLE); + gPipeline.markRebuild( mDrawable, LLDrawable::REBUILD_ALL, TRUE ); } } @@ -2155,43 +2400,56 @@ BOOL LLViewerObject::isActive() const return TRUE; } +//load flags from cache or from message +void LLViewerObject::loadFlags(U32 flags) +{ + if(flags == (U32)(-1)) + { + return; //invalid + } + + // keep local flags and overwrite remote-controlled flags + mFlags = (mFlags & FLAGS_LOCAL) | flags; + // ...new objects that should come in selected need to be added to the selected list + mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0); + return; +} -void LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLViewerObject::idleUpdate(LLAgent &agent, const F64 &time) { - //static LLFastTimer::DeclareTimer ftm("Viewer Object"); - //LLFastTimer t(ftm); + //static LLTrace::BlockTimerStatHandle ftm("Viewer Object"); + //LL_RECORD_BLOCK_TIME(ftm); if (!mDead) { - // CRO - don't velocity interp linked objects! - // Leviathan - but DO velocity interp joints - if (!mStatic && sVelocityInterpolate && !isSelected()) - { - // calculate dt from last update - F32 dt_raw = (F32)(time - mLastInterpUpdateSecs); - F32 dt = mTimeDilation * dt_raw; + if (!mStatic && sVelocityInterpolate && !isSelected()) + { + // calculate dt from last update + F32 time_dilation = mRegionp ? mRegionp->getTimeDilation() : 1.0f; + F32 dt_raw = ((F64Seconds)time - mLastInterpUpdateSecs).value(); + F32 dt = time_dilation * dt_raw; applyAngularVelocity(dt); if (isAttachment()) - { - mLastInterpUpdateSecs = time; + { + mLastInterpUpdateSecs = (F64Seconds)time; return; + } + else + { // Move object based on it's velocity and rotation + interpolateLinearMotion(time, dt); + } } - else - { // Move object based on it's velocity and rotation - interpolateLinearMotion(time, dt); - } - } - updateDrawable(FALSE); + updateDrawable(FALSE); } } -// Move an object due to idle-time viewer side updates by iterpolating motion -void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) +// Move an object due to idle-time viewer side updates by interpolating motion +void LLViewerObject::interpolateLinearMotion(const F64SecondsImplicit& time, const F32SecondsImplicit& dt_seconds) { // linear motion // PHYSICS_TIMESTEP is used below to correct for the fact that the velocity in object @@ -2202,8 +2460,9 @@ void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) // to see if object is selected, instead of explicitly // zeroing it out - F64 time_since_last_update = time - mLastMessageUpdateSecs; - if (time_since_last_update <= 0.0 || dt <= 0.f) + F32 dt = dt_seconds; + F64Seconds time_since_last_update = time - mLastMessageUpdateSecs; + if (time_since_last_update <= (F64Seconds)0.0 || dt <= 0.f) { return; } @@ -2211,7 +2470,7 @@ void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) LLVector3 accel = getAcceleration(); LLVector3 vel = getVelocity(); - if (sMaxUpdateInterpolationTime <= 0.0) + if (sMaxUpdateInterpolationTime <= (F64Seconds)0.0) { // Old code path ... unbounded, simple interpolation if (!(accel.isExactlyZero() && vel.isExactlyZero())) { @@ -2233,8 +2492,8 @@ void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) LLVector3 new_v = accel * dt; if (time_since_last_update > sPhaseOutUpdateInterpolationTime && - sPhaseOutUpdateInterpolationTime > 0.0) - { // Haven't seen a viewer update in a while, check to see if the ciruit is still active + sPhaseOutUpdateInterpolationTime > (F64Seconds)0.0) + { // Haven't seen a viewer update in a while, check to see if the circuit is still active if (mRegionp) { // The simulator will NOT send updates if the object continues normally on the path // predicted by the velocity and the acceleration (often gravity) sent to the viewer @@ -2243,19 +2502,19 @@ void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) if (cdp) { // Find out how many seconds since last packet arrived on the circuit - F64 time_since_last_packet = LLMessageSystem::getMessageTimeSeconds() - cdp->getLastPacketInTime(); + F64Seconds time_since_last_packet = LLMessageSystem::getMessageTimeSeconds() - cdp->getLastPacketInTime(); if (!cdp->isAlive() || // Circuit is dead or blocked cdp->isBlocked() || // or doesn't seem to be getting any packets (time_since_last_packet > sPhaseOutUpdateInterpolationTime)) { // Start to reduce motion interpolation since we haven't seen a server update in a while - F64 time_since_last_interpolation = time - mLastInterpUpdateSecs; + F64Seconds time_since_last_interpolation = time - mLastInterpUpdateSecs; F64 phase_out = 1.0; if (time_since_last_update > sMaxUpdateInterpolationTime) { // Past the time limit, so stop the object phase_out = 0.0; - //llinfos << "Motion phase out to zero" << llendl; + //LL_INFOS() << "Motion phase out to zero" << LL_ENDL; // Kill angular motion as well. Note - not adding this due to paranoia // about stopping rotation for llTargetOmega objects and not having it restart @@ -2265,13 +2524,13 @@ void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) { // Last update was already phased out a bit phase_out = (sMaxUpdateInterpolationTime - time_since_last_update) / (sMaxUpdateInterpolationTime - time_since_last_interpolation); - //llinfos << "Continuing motion phase out of " << (F32) phase_out << llendl; + //LL_INFOS() << "Continuing motion phase out of " << (F32) phase_out << LL_ENDL; } else { // Phase out from full value phase_out = (sMaxUpdateInterpolationTime - time_since_last_update) / (sMaxUpdateInterpolationTime - sPhaseOutUpdateInterpolationTime); - //llinfos << "Starting motion phase out of " << (F32) phase_out << llendl; + //LL_INFOS() << "Starting motion phase out of " << (F32) phase_out << LL_ENDL; } phase_out = llclamp(phase_out, 0.0, 1.0); @@ -2316,8 +2575,8 @@ void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) if (clip_pos_global != new_pos_global) { // Was clipped, so this means we hit a edge where there is no region to enter - //llinfos << "Hit empty region edge, clipped predicted position to " << mRegionp->getPosRegionFromGlobal(clip_pos_global) - // << " from " << new_pos << llendl; + //LL_INFOS() << "Hit empty region edge, clipped predicted position to " << mRegionp->getPosRegionFromGlobal(clip_pos_global) + // << " from " << new_pos << LL_ENDL; new_pos = mRegionp->getPosRegionFromGlobal(clip_pos_global); // Stop motion and get server update for bouncing on the edge @@ -2326,7 +2585,7 @@ void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) } else { // Let predicted movement cross into another region - //llinfos << "Predicting region crossing to " << new_pos << llendl; + //LL_INFOS() << "Predicting region crossing to " << new_pos << LL_ENDL; } } @@ -2474,7 +2733,8 @@ void LLViewerObject::saveScript( * XXXPAM Investigate not making this copy. Seems unecessary, but I'm unsure about the * interaction with doUpdateInventory() called below. */ - lldebugs << "LLViewerObject::saveScript() " << item->getUUID() << " " << item->getAssetUUID() << llendl; + LL_DEBUGS() << "LLViewerObject::saveScript() " << item->getUUID() << " " << item->getAssetUUID() << LL_ENDL; + LLPointer<LLViewerInventoryItem> task_item = new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(), item->getAssetUUID(), item->getType(), @@ -2505,7 +2765,7 @@ void LLViewerObject::saveScript( void LLViewerObject::moveInventory(const LLUUID& folder_id, const LLUUID& item_id) { - lldebugs << "LLViewerObject::moveInventory " << item_id << llendl; + LL_DEBUGS() << "LLViewerObject::moveInventory " << item_id << LL_ENDL; LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_MoveTaskInventory); msg->nextBlockFast(_PREHASH_AgentData); @@ -2539,8 +2799,8 @@ void LLViewerObject::dirtyInventory() mInventory->clear(); // will deref and delete entries delete mInventory; mInventory = NULL; - mInventoryDirty = TRUE; } + mInventoryDirty = TRUE; } void LLViewerObject::registerInventoryListener(LLVOInventoryListener* listener, void* user_data) @@ -2577,12 +2837,15 @@ void LLViewerObject::clearInventoryListeners() void LLViewerObject::requestInventory() { - mInventoryDirty = FALSE; + if(mInventoryDirty && mInventory && !mInventoryCallbacks.empty()) + { + mInventory->clear(); // will deref and delete entries + delete mInventory; + mInventory = NULL; + mInventoryDirty = FALSE; //since we are going to request it now + } if(mInventory) { - //mInventory->clear() // will deref and delete it - //delete mInventory; - //mInventory = NULL; doInventoryCallback(); } // throw away duplicate requests @@ -2622,12 +2885,12 @@ struct LLFilenameAndTask LLFilenameAndTask() { ++sCount; - lldebugs << "Constructing LLFilenameAndTask: " << sCount << llendl; + LL_DEBUGS() << "Constructing LLFilenameAndTask: " << sCount << LL_ENDL; } ~LLFilenameAndTask() { --sCount; - lldebugs << "Destroying LLFilenameAndTask: " << sCount << llendl; + LL_DEBUGS() << "Destroying LLFilenameAndTask: " << sCount << LL_ENDL; } private: LLFilenameAndTask(const LLFilenameAndTask& rhs); @@ -2647,8 +2910,8 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data) LLViewerObject* object = gObjectList.findObject(task_id); if(!object) { - llwarns << "LLViewerObject::processTaskInv object " - << task_id << " does not exist." << llendl; + LL_WARNS() << "LLViewerObject::processTaskInv object " + << task_id << " does not exist." << LL_ENDL; return; } @@ -2662,7 +2925,7 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data) if(ft->mFilename.empty()) { - lldebugs << "Task has no inventory" << llendl; + LL_DEBUGS() << "Task has no inventory" << LL_ENDL; // mock up some inventory to make a drop target. if(object->mInventory) { @@ -2697,39 +2960,48 @@ void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtS if(ft && (0 == error_code) && (object = gObjectList.findObject(ft->mTaskID))) { - object->loadTaskInvFile(ft->mFilename); + if (object->loadTaskInvFile(ft->mFilename)) + { - LLInventoryObject::object_list_t::iterator it = object->mInventory->begin(); - LLInventoryObject::object_list_t::iterator end = object->mInventory->end(); - std::list<LLUUID>& pending_lst = object->mPendingInventoryItemsIDs; + LLInventoryObject::object_list_t::iterator it = object->mInventory->begin(); + LLInventoryObject::object_list_t::iterator end = object->mInventory->end(); + std::list<LLUUID>& pending_lst = object->mPendingInventoryItemsIDs; - for (; it != end && pending_lst.size(); ++it) - { - LLViewerInventoryItem* item = dynamic_cast<LLViewerInventoryItem*>(it->get()); - if(item && item->getType() != LLAssetType::AT_CATEGORY) + for (; it != end && pending_lst.size(); ++it) { - std::list<LLUUID>::iterator id_it = std::find(pending_lst.begin(), pending_lst.begin(), item->getAssetUUID()); - if (id_it != pending_lst.end()) + LLViewerInventoryItem* item = dynamic_cast<LLViewerInventoryItem*>(it->get()); + if(item && item->getType() != LLAssetType::AT_CATEGORY) { - pending_lst.erase(id_it); + std::list<LLUUID>::iterator id_it = std::find(pending_lst.begin(), pending_lst.begin(), item->getAssetUUID()); + if (id_it != pending_lst.end()) + { + pending_lst.erase(id_it); + } } } } + else + { + // MAINT-2597 - crash when trying to edit a no-mod object + // Somehow get an contents inventory response, but with an invalid stream (possibly 0 size?) + // Stated repro was specific to no-mod objects so failing without user interaction should be safe. + LL_WARNS() << "Trying to load invalid task inventory file. Ignoring file contents." << LL_ENDL; + } } else { // This Occurs When to requests were made, and the first one // has already handled it. - lldebugs << "Problem loading task inventory. Return code: " - << error_code << llendl; + LL_DEBUGS() << "Problem loading task inventory. Return code: " + << error_code << LL_ENDL; } delete ft; } -void LLViewerObject::loadTaskInvFile(const std::string& filename) +BOOL LLViewerObject::loadTaskInvFile(const std::string& filename) { std::string filename_and_local_path = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, filename); - llifstream ifs(filename_and_local_path); + llifstream ifs(filename_and_local_path.c_str()); if(ifs.good()) { char buffer[MAX_STRING]; /* Flawfinder: ignore */ @@ -2762,8 +3034,8 @@ void LLViewerObject::loadTaskInvFile(const std::string& filename) } else { - llwarns << "Unknown token in inventory file '" - << keyword << "'" << llendl; + LL_WARNS() << "Unknown token in inventory file '" + << keyword << "'" << LL_ENDL; } } ifs.close(); @@ -2771,10 +3043,13 @@ void LLViewerObject::loadTaskInvFile(const std::string& filename) } else { - llwarns << "unable to load task inventory: " << filename_and_local_path - << llendl; + LL_WARNS() << "unable to load task inventory: " << filename_and_local_path + << LL_ENDL; + return FALSE; } doInventoryCallback(); + + return TRUE; } void LLViewerObject::doInventoryCallback() @@ -2793,7 +3068,7 @@ void LLViewerObject::doInventoryCallback() } else { - llinfos << "LLViewerObject::doInventoryCallback() deleting bad listener entry." << llendl; + LL_INFOS() << "LLViewerObject::doInventoryCallback() deleting bad listener entry." << LL_ENDL; delete info; mInventoryCallbacks.erase(curiter); } @@ -2941,7 +3216,7 @@ LLInventoryObject* LLViewerObject::getInventoryRoot() LLViewerInventoryItem* LLViewerObject::getInventoryItemByAsset(const LLUUID& asset_id) { if (mInventoryDirty) - llwarns << "Peforming inventory lookup for object " << mID << " that has dirty inventory!" << llendl; + LL_WARNS() << "Peforming inventory lookup for object " << mID << " that has dirty inventory!" << LL_ENDL; LLViewerInventoryItem* rv = NULL; if(mInventory) @@ -3099,8 +3374,17 @@ void LLViewerObject::setLinksetCost(F32 cost) { mLinksetCost = cost; mCostStale = false; - - if (isSelected()) + + BOOL needs_refresh = isSelected(); + child_list_t::iterator iter = mChildList.begin(); + while(iter != mChildList.end() && !needs_refresh) + { + LLViewerObject* child = *iter; + needs_refresh = child->isSelected(); + iter++; + } + + if (needs_refresh) { gFloaterTools->dirty(); } @@ -3266,14 +3550,14 @@ void LLViewerObject::boostTexturePriority(BOOL boost_children /* = TRUE */) S32 tex_count = getNumTEs(); for (i = 0; i < tex_count; i++) { - getTEImage(i)->setBoostLevel(LLViewerTexture::BOOST_SELECTED); + getTEImage(i)->setBoostLevel(LLGLTexture::BOOST_SELECTED); } if (isSculpted() && !isMesh()) { LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); LLUUID sculpt_id = sculpt_params->getSculptTexture(); - LLViewerTextureManager::getFetchedTexture(sculpt_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)->setBoostLevel(LLViewerTexture::BOOST_SELECTED); + LLViewerTextureManager::getFetchedTexture(sculpt_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)->setBoostLevel(LLGLTexture::BOOST_SELECTED); } if (boost_children) @@ -3346,7 +3630,7 @@ void LLViewerObject::addNVPair(const std::string& data) // char splat[MAX_STRING]; // temp->printNameValue(splat); -// llinfos << "addNVPair " << splat << llendl; +// LL_INFOS() << "addNVPair " << splat << LL_ENDL; name_value_map_t::iterator iter = mNameValuePairs.find(nv->mName); if (iter != mNameValuePairs.end()) @@ -3360,7 +3644,7 @@ void LLViewerObject::addNVPair(const std::string& data) else { delete nv; -// llinfos << "Trying to write to Read Only NVPair " << temp->mName << " in addNVPair()" << llendl; +// LL_INFOS() << "Trying to write to Read Only NVPair " << temp->mName << " in addNVPair()" << LL_ENDL; return; } } @@ -3371,7 +3655,7 @@ BOOL LLViewerObject::removeNVPair(const std::string& name) { char* canonical_name = gNVNameTable.addString(name); - lldebugs << "LLViewerObject::removeNVPair(): " << name << llendl; + LL_DEBUGS() << "LLViewerObject::removeNVPair(): " << name << LL_ENDL; name_value_map_t::iterator iter = mNameValuePairs.find(canonical_name); if (iter != mNameValuePairs.end()) @@ -3397,7 +3681,7 @@ BOOL LLViewerObject::removeNVPair(const std::string& name) } else { - lldebugs << "removeNVPair - No region for object" << llendl; + LL_DEBUGS() << "removeNVPair - No region for object" << LL_ENDL; } } return FALSE; @@ -3783,19 +4067,19 @@ LLViewerObject* LLViewerObject::getRootEdit() const } -BOOL LLViewerObject::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, +BOOL LLViewerObject::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, S32 face, BOOL pick_transparent, S32* face_hit, - LLVector3* intersection, + LLVector4a* intersection, LLVector2* tex_coord, - LLVector3* normal, - LLVector3* bi_normal) + LLVector4a* normal, + LLVector4a* tangent) { return false; } -BOOL LLViewerObject::lineSegmentBoundingBox(const LLVector3& start, const LLVector3& end) +BOOL LLViewerObject::lineSegmentBoundingBox(const LLVector4a& start, const LLVector4a& end) { if (mDrawable.isNull() || mDrawable->isDead()) { @@ -3812,11 +4096,7 @@ BOOL LLViewerObject::lineSegmentBoundingBox(const LLVector3& start, const LLVect size.setSub(ext[1], ext[0]); size.mul(0.5f); - LLVector4a starta, enda; - starta.load3(start.mV); - enda.load3(end.mV); - - return LLLineSegmentBoxIntersect(starta, enda, center, size); + return LLLineSegmentBoxIntersect(start, end, center, size); } U8 LLViewerObject::getMediaType() const @@ -3915,25 +4195,39 @@ void LLViewerObject::setNumTEs(const U8 num_tes) { LLPointer<LLViewerTexture> *new_images; new_images = new LLPointer<LLViewerTexture>[num_tes]; + + LLPointer<LLViewerTexture> *new_normmaps; + new_normmaps = new LLPointer<LLViewerTexture>[num_tes]; + + LLPointer<LLViewerTexture> *new_specmaps; + new_specmaps = new LLPointer<LLViewerTexture>[num_tes]; for (i = 0; i < num_tes; i++) { if (i < getNumTEs()) { new_images[i] = mTEImages[i]; + new_normmaps[i] = mTENormalMaps[i]; + new_specmaps[i] = mTESpecularMaps[i]; } else if (getNumTEs()) { new_images[i] = mTEImages[getNumTEs()-1]; + new_normmaps[i] = mTENormalMaps[getNumTEs()-1]; + new_specmaps[i] = mTESpecularMaps[getNumTEs()-1]; } else { new_images[i] = NULL; + new_normmaps[i] = NULL; + new_specmaps[i] = NULL; } } deleteTEImages(); mTEImages = new_images; + mTENormalMaps = new_normmaps; + mTESpecularMaps = new_specmaps; } else { @@ -4012,12 +4306,18 @@ void LLViewerObject::sendTEUpdate() const void LLViewerObject::setTE(const U8 te, const LLTextureEntry &texture_entry) { LLPrimitive::setTE(te, texture_entry); -// This doesn't work, don't get any textures. -// if (mDrawable.notNull() && mDrawable->isVisible()) -// { + const LLUUID& image_id = getTE(te)->getID(); - mTEImages[te] = LLViewerTextureManager::getFetchedTexture(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); -// } + mTEImages[te] = LLViewerTextureManager::getFetchedTexture(image_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + + if (getTE(te)->getMaterialParams().notNull()) + { + const LLUUID& norm_id = getTE(te)->getMaterialParams()->getNormalID(); + mTENormalMaps[te] = LLViewerTextureManager::getFetchedTexture(norm_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + + const LLUUID& spec_id = getTE(te)->getMaterialParams()->getSpecularID(); + mTESpecularMaps[te] = LLViewerTextureManager::getFetchedTexture(spec_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + } } void LLViewerObject::setTEImage(const U8 te, LLViewerTexture *imagep) @@ -4034,15 +4334,15 @@ void LLViewerObject::setTEImage(const U8 te, LLViewerTexture *imagep) } } - -S32 LLViewerObject::setTETextureCore(const U8 te, const LLUUID& uuid, LLHost host) +S32 LLViewerObject::setTETextureCore(const U8 te, LLViewerTexture *image) { + const LLUUID& uuid = image->getID(); S32 retval = 0; if (uuid != getTE(te)->getID() || uuid == LLUUID::null) { retval = LLPrimitive::setTETexture(te, uuid); - mTEImages[te] = LLViewerTextureManager::getFetchedTexture(uuid, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); + mTEImages[te] = image; setChanged(TEXTURE); if (mDrawable.notNull()) { @@ -4052,6 +4352,52 @@ S32 LLViewerObject::setTETextureCore(const U8 te, const LLUUID& uuid, LLHost hos return retval; } +S32 LLViewerObject::setTENormalMapCore(const U8 te, LLViewerTexture *image) +{ + S32 retval = TEM_CHANGE_TEXTURE; + const LLUUID& uuid = image ? image->getID() : LLUUID::null; + if (uuid != getTE(te)->getID() || + uuid == LLUUID::null) + { + LLTextureEntry* tep = getTE(te); + LLMaterial* mat = NULL; + if (tep) + { + mat = tep->getMaterialParams(); + } + + if (mat) + { + mat->setNormalID(uuid); + } + } + changeTENormalMap(te,image); + return retval; +} + +S32 LLViewerObject::setTESpecularMapCore(const U8 te, LLViewerTexture *image) +{ + S32 retval = TEM_CHANGE_TEXTURE; + const LLUUID& uuid = image ? image->getID() : LLUUID::null; + if (uuid != getTE(te)->getID() || + uuid == LLUUID::null) + { + LLTextureEntry* tep = getTE(te); + LLMaterial* mat = NULL; + if (tep) + { + mat = tep->getMaterialParams(); + } + + if (mat) + { + mat->setSpecularID(uuid); + } + } + changeTESpecularMap(te, image); + return retval; +} + //virtual void LLViewerObject::changeTEImage(S32 index, LLViewerTexture* new_image) { @@ -4062,12 +4408,47 @@ void LLViewerObject::changeTEImage(S32 index, LLViewerTexture* new_image) mTEImages[index] = new_image ; } +void LLViewerObject::changeTENormalMap(S32 index, LLViewerTexture* new_image) +{ + if(index < 0 || index >= getNumTEs()) + { + return ; + } + mTENormalMaps[index] = new_image ; + refreshMaterials(); +} + +void LLViewerObject::changeTESpecularMap(S32 index, LLViewerTexture* new_image) +{ + if(index < 0 || index >= getNumTEs()) + { + return ; + } + mTESpecularMaps[index] = new_image ; + refreshMaterials(); +} + S32 LLViewerObject::setTETexture(const U8 te, const LLUUID& uuid) { // Invalid host == get from the agent's sim - return setTETextureCore(te, uuid, LLHost::invalid); + LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture( + uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid); + return setTETextureCore(te,image); +} + +S32 LLViewerObject::setTENormalMap(const U8 te, const LLUUID& uuid) +{ + LLViewerFetchedTexture *image = (uuid == LLUUID::null) ? NULL : LLViewerTextureManager::getFetchedTexture( + uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid); + return setTENormalMapCore(te, image); } +S32 LLViewerObject::setTESpecularMap(const U8 te, const LLUUID& uuid) +{ + LLViewerFetchedTexture *image = (uuid == LLUUID::null) ? NULL : LLViewerTextureManager::getFetchedTexture( + uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid); + return setTESpecularMapCore(te, image); +} S32 LLViewerObject::setTEColor(const U8 te, const LLColor3& color) { @@ -4080,7 +4461,7 @@ S32 LLViewerObject::setTEColor(const U8 te, const LLColor4& color) const LLTextureEntry *tep = getTE(te); if (!tep) { - llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl; + LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; } else if (color != tep->getColor()) { @@ -4100,7 +4481,7 @@ S32 LLViewerObject::setTEBumpmap(const U8 te, const U8 bump) const LLTextureEntry *tep = getTE(te); if (!tep) { - llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl; + LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; } else if (bump != tep->getBumpmap()) { @@ -4121,7 +4502,7 @@ S32 LLViewerObject::setTETexGen(const U8 te, const U8 texgen) const LLTextureEntry *tep = getTE(te); if (!tep) { - llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl; + LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; } else if (texgen != tep->getTexGen()) { @@ -4137,7 +4518,7 @@ S32 LLViewerObject::setTEMediaTexGen(const U8 te, const U8 media) const LLTextureEntry *tep = getTE(te); if (!tep) { - llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl; + LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; } else if (media != tep->getMediaTexGen()) { @@ -4153,7 +4534,7 @@ S32 LLViewerObject::setTEShiny(const U8 te, const U8 shiny) const LLTextureEntry *tep = getTE(te); if (!tep) { - llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl; + LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; } else if (shiny != tep->getShiny()) { @@ -4169,7 +4550,7 @@ S32 LLViewerObject::setTEFullbright(const U8 te, const U8 fullbright) const LLTextureEntry *tep = getTE(te); if (!tep) { - llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl; + LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; } else if (fullbright != tep->getFullbright()) { @@ -4191,7 +4572,7 @@ S32 LLViewerObject::setTEMediaFlags(const U8 te, const U8 media_flags) const LLTextureEntry *tep = getTE(te); if (!tep) { - llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl; + LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; } else if (media_flags != tep->getMediaFlags()) { @@ -4214,7 +4595,7 @@ S32 LLViewerObject::setTEGlow(const U8 te, const F32 glow) const LLTextureEntry *tep = getTE(te); if (!tep) { - llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl; + LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; } else if (glow != tep->getGlow()) { @@ -4228,6 +4609,59 @@ S32 LLViewerObject::setTEGlow(const U8 te, const F32 glow) return retval; } +S32 LLViewerObject::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID) +{ + S32 retval = 0; + const LLTextureEntry *tep = getTE(te); + if (!tep) + { + LL_WARNS("Material") << "No texture entry for te " << (S32)te + << ", object " << mID + << ", material " << pMaterialID + << LL_ENDL; + } + //else if (pMaterialID != tep->getMaterialID()) + { + LL_DEBUGS("Material") << "Changing texture entry for te " << (S32)te + << ", object " << mID + << ", material " << pMaterialID + << LL_ENDL; + retval = LLPrimitive::setTEMaterialID(te, pMaterialID); + refreshMaterials(); + } + return retval; +} + +S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams) +{ + S32 retval = 0; + const LLTextureEntry *tep = getTE(te); + if (!tep) + { + LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; + return 0; + } + + retval = LLPrimitive::setTEMaterialParams(te, pMaterialParams); + LL_DEBUGS("Material") << "Changing material params for te " << (S32)te + << ", object " << mID + << " (" << retval << ")" + << LL_ENDL; + setTENormalMap(te, (pMaterialParams) ? pMaterialParams->getNormalID() : LLUUID::null); + setTESpecularMap(te, (pMaterialParams) ? pMaterialParams->getSpecularID() : LLUUID::null); + + refreshMaterials(); + return retval; +} + +void LLViewerObject::refreshMaterials() +{ + setChanged(TEXTURE); + if (mDrawable.notNull()) + { + gPipeline.markTextured(mDrawable); + } +} S32 LLViewerObject::setTEScale(const U8 te, const F32 s, const F32 t) { @@ -4323,15 +4757,83 @@ LLViewerTexture *LLViewerObject::getTEImage(const U8 face) const } } - llerrs << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << llendl; + LL_ERRS() << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << LL_ENDL; + + return NULL; +} + + +bool LLViewerObject::isImageAlphaBlended(const U8 te) const +{ + LLViewerTexture* image = getTEImage(te); + LLGLenum format = image ? image->getPrimaryFormat() : GL_RGB; + switch (format) + { + case GL_RGBA: + case GL_ALPHA: + { + return true; + } + break; + + case GL_RGB: break; + default: + { + LL_WARNS() << "Unexpected tex format in LLViewerObject::isImageAlphaBlended...returning no alpha." << LL_ENDL; + } + break; + } + + return false; +} +LLViewerTexture *LLViewerObject::getTENormalMap(const U8 face) const +{ + // llassert(mTEImages); + + if (face < getNumTEs()) + { + LLViewerTexture* image = mTENormalMaps[face]; + if (image) + { + return image; + } + else + { + return (LLViewerTexture*)(LLViewerFetchedTexture::sDefaultImagep); + } + } + + LL_ERRS() << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << LL_ENDL; + return NULL; } +LLViewerTexture *LLViewerObject::getTESpecularMap(const U8 face) const +{ + // llassert(mTEImages); + + if (face < getNumTEs()) + { + LLViewerTexture* image = mTESpecularMaps[face]; + if (image) + { + return image; + } + else + { + return (LLViewerTexture*)(LLViewerFetchedTexture::sDefaultImagep); + } + } + + LL_ERRS() << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << LL_ENDL; + + return NULL; +} void LLViewerObject::fitFaceTexture(const U8 face) { - llinfos << "fitFaceTexture not implemented" << llendl; + LL_INFOS() << "fitFaceTexture not implemented" << LL_ENDL; } @@ -4520,6 +5022,22 @@ LLVOAvatar* LLViewerObject::asAvatar() return NULL; } +// If this object is directly or indirectly parented by an avatar, return it. +LLVOAvatar* LLViewerObject::getAvatarAncestor() +{ + LLViewerObject *pobj = (LLViewerObject*) getParent(); + while (pobj) + { + LLVOAvatar *av = pobj->asAvatar(); + if (av) + { + return av; + } + pobj = (LLViewerObject*) pobj->getParent(); + } + return NULL; +} + BOOL LLViewerObject::isParticleSource() const { return !mPartSourcep.isNull() && !mPartSourcep->isDead(); @@ -4580,7 +5098,7 @@ void LLViewerObject::unpackParticleSource(const S32 block_num, const LLUUID& own // We need to be able to deal with a particle source that hasn't changed, but still got an update! if (pss) { -// llinfos << "Making particle system with owner " << owner_id << llendl; +// LL_INFOS() << "Making particle system with owner " << owner_id << LL_ENDL; pss->setOwnerUUID(owner_id); mPartSourcep = pss; LLViewerPartSim::getInstance()->addPartSource(pss); @@ -4604,7 +5122,7 @@ void LLViewerObject::unpackParticleSource(const S32 block_num, const LLUUID& own } } -void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id) +void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id, bool legacy) { if (!mPartSourcep.isNull() && mPartSourcep->isDead()) { @@ -4613,7 +5131,7 @@ void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_ if (mPartSourcep) { // If we've got one already, just update the existing source (or remove it) - if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, dp)) + if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, dp, legacy)) { mPartSourcep->setDead(); mPartSourcep = NULL; @@ -4621,13 +5139,13 @@ void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_ } else { - LLPointer<LLViewerPartSourceScript> pss = LLViewerPartSourceScript::unpackPSS(this, NULL, dp); + LLPointer<LLViewerPartSourceScript> pss = LLViewerPartSourceScript::unpackPSS(this, NULL, dp, legacy); //If the owner is muted, don't create the system if(LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagParticles)) return; // We need to be able to deal with a particle source that hasn't changed, but still got an update! if (pss) { -// llinfos << "Making particle system with owner " << owner_id << llendl; +// LL_INFOS() << "Making particle system with owner " << owner_id << LL_ENDL; pss->setOwnerUUID(owner_id); mPartSourcep = pss; LLViewerPartSim::getInstance()->addPartSource(pss); @@ -4711,7 +5229,7 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow // At least, this appears to be how the scripts work. // The attached sound ID is set to NULL to avoid it playing back when the // object rezzes in on non-looping sounds. - //llinfos << "Clearing attached sound " << mAudioSourcep->getCurrentData()->getID() << llendl; + //LL_INFOS() << "Clearing attached sound " << mAudioSourcep->getCurrentData()->getID() << LL_ENDL; gAudiop->cleanupAudioSource(mAudioSourcep); mAudioSourcep = NULL; } @@ -4726,7 +5244,7 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow && mAudioSourcep && mAudioSourcep->isLoop() && mAudioSourcep->getCurrentData() && mAudioSourcep->getCurrentData()->getID() == audio_uuid) { - //llinfos << "Already playing this sound on a loop, ignoring" << llendl; + //LL_INFOS() << "Already playing this sound on a loop, ignoring" << LL_ENDL; return; } @@ -4740,7 +5258,7 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow if (mAudioSourcep && mAudioSourcep->isMuted() && mAudioSourcep->getCurrentData() && mAudioSourcep->getCurrentData()->getID() == audio_uuid) { - //llinfos << "Already having this sound as muted sound, ignoring" << llendl; + //LL_INFOS() << "Already having this sound as muted sound, ignoring" << LL_ENDL; return; } @@ -4763,7 +5281,7 @@ void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& ow // Play this sound if region maturity permits if( gAgent.canAccessMaturityAtGlobal(this->getPositionGlobal()) ) { - //llinfos << "Playing attached sound " << audio_uuid << llendl; + //LL_INFOS() << "Playing attached sound " << audio_uuid << LL_ENDL; mAudioSourcep->play(audio_uuid); } } @@ -4778,7 +5296,10 @@ LLAudioSource *LLViewerObject::getAudioSource(const LLUUID& owner_id) LLAudioSourceVO *asvop = new LLAudioSourceVO(mID, owner_id, 0.01f, this); mAudioSourcep = asvop; - if(gAudiop) gAudiop->addAudioSource(asvop); + if(gAudiop) + { + gAudiop->addAudioSource(asvop); + } } return mAudioSourcep; @@ -4786,10 +5307,6 @@ LLAudioSource *LLViewerObject::getAudioSource(const LLUUID& owner_id) void LLViewerObject::adjustAudioGain(const F32 gain) { - if (!gAudiop) - { - return; - } if (mAudioSourcep) { mAudioGain = gain; @@ -4846,7 +5363,7 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para } default: { - llinfos << "Unknown param type." << llendl; + LL_INFOS() << "Unknown param type." << LL_ENDL; break; } }; @@ -4984,7 +5501,7 @@ void LLViewerObject::parameterChanged(U16 param_type, LLNetworkData* data, BOOL } else { - llwarns << "Failed to send object extra parameters: " << param_type << llendl; + LL_WARNS() << "Failed to send object extra parameters: " << param_type << LL_ENDL; } } } @@ -5023,6 +5540,28 @@ void LLViewerObject::clearDrawableState(U32 state, BOOL recursive) } } +BOOL LLViewerObject::isDrawableState(U32 state, BOOL recursive) const +{ + BOOL matches = FALSE; + if (mDrawable) + { + matches = mDrawable->isState(state); + } + if (recursive) + { + for (child_list_t::const_iterator iter = mChildList.begin(); + (iter != mChildList.end()) && matches; iter++) + { + LLViewerObject* child = *iter; + matches &= child->isDrawableState(state, recursive); + } + } + + return matches; +} + + + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // RN: these functions assume a 2-level hierarchy //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! @@ -5249,7 +5788,18 @@ void LLViewerObject::setRegion(LLViewerRegion *regionp) { if (!regionp) { - llwarns << "viewer object set region to NULL" << llendl; + LL_WARNS() << "viewer object set region to NULL" << LL_ENDL; + } + if(regionp != mRegionp) + { + if(mRegionp) + { + mRegionp->removeFromCreatedList(getLocalID()); + } + if(regionp) + { + regionp->addToCreatedList(getLocalID()); + } } mLatestRecvPacketID = 0; @@ -5271,10 +5821,10 @@ void LLViewerObject::updateRegion(LLViewerRegion *regionp) // if (regionp) // { // F64 now = LLFrameTimer::getElapsedSeconds(); -// llinfos << "Updating to region " << regionp->getName() +// LL_INFOS() << "Updating to region " << regionp->getName() // << ", ms since last update message: " << (F32)((now - mLastMessageUpdateSecs) * 1000.0) // << ", ms since last interpolation: " << (F32)((now - mLastInterpUpdateSecs) * 1000.0) -// << llendl; +// << LL_ENDL; // } } @@ -5467,6 +6017,11 @@ F32 LLAlphaObject::getPartSize(S32 idx) return 0.f; } +void LLAlphaObject::getBlendFunc(S32 face, U32& src, U32& dst) +{ + +} + // virtual void LLStaticViewerObject::updateDrawable(BOOL force_damped) { @@ -5616,6 +6171,13 @@ void LLViewerObject::resetChildrenPosition(const LLVector3& offset, BOOL simplif return ; } +// virtual +BOOL LLViewerObject::isTempAttachment() const +{ + return (mID.notNull() && (mID == mAttachmentItemID)); +} + + const LLUUID &LLViewerObject::getAttachmentItemID() const { return mAttachmentItemID; @@ -5662,6 +6224,17 @@ const LLUUID &LLViewerObject::extractAttachmentItemID() return getAttachmentItemID(); } +const std::string& LLViewerObject::getAttachmentItemName() +{ + static std::string empty; + LLInventoryItem *item = gInventory.getItem(getAttachmentItemID()); + if (isAttachment() && item) + { + return item->getName(); + } + return empty; +} + //virtual LLVOAvatar* LLViewerObject::getAvatar() const { |