diff options
Diffstat (limited to 'indra')
41 files changed, 1392 insertions, 155 deletions
| diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp index a3d5679f65..89335a20f5 100644 --- a/indra/llcharacter/lljoint.cpp +++ b/indra/llcharacter/lljoint.cpp @@ -881,7 +881,7 @@ void LLJoint::setWorldRotation( const LLQuaternion& rot )  //--------------------------------------------------------------------  const LLVector3& LLJoint::getScale()  { -	return mXform.getScale();	 +    return mXform.getScale();  }  //-------------------------------------------------------------------- diff --git a/indra/llcharacter/llmotioncontroller.h b/indra/llcharacter/llmotioncontroller.h index 72de331694..22357a2c6b 100644 --- a/indra/llcharacter/llmotioncontroller.h +++ b/indra/llcharacter/llmotioncontroller.h @@ -150,10 +150,13 @@ public:  	BOOL isPaused() const { return mPaused; }  	void setTimeStep(F32 step); +    F32 getTimeStep() const { return mTimeStep; }  	void setTimeFactor(F32 time_factor);  	F32 getTimeFactor() const { return mTimeFactor; } +    F32 getAnimTime() const { return mAnimTime; } +      	motion_list_t& getActiveMotions() { return mActiveMotions; }  	void incMotionCounts(S32& num_motions, S32& num_loading_motions, S32& num_loaded_motions, S32& num_active_motions, S32& num_deprecated_motions); diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 7a54d83b3f..8c27ef9961 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1,5 +1,4 @@  /**  -   * @file llvolume.cpp   *   * $LicenseInfo:firstyear=2002&license=viewerlgpl$ diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp index 1ae8a6ac15..f8e11e324e 100644 --- a/indra/llmessage/message_prehash.cpp +++ b/indra/llmessage/message_prehash.cpp @@ -818,6 +818,7 @@ char const* const _PREHASH_StateSave = LLMessageStringTable::getInstance()->getS  char const* const _PREHASH_RoleData = LLMessageStringTable::getInstance()->getString("RoleData");  char const* const _PREHASH_AgentAnimation = LLMessageStringTable::getInstance()->getString("AgentAnimation");  char const* const _PREHASH_AvatarAnimation = LLMessageStringTable::getInstance()->getString("AvatarAnimation"); +char const* const _PREHASH_ObjectAnimation = LLMessageStringTable::getInstance()->getString("ObjectAnimation");  char const* const _PREHASH_LogDwellTime = LLMessageStringTable::getInstance()->getString("LogDwellTime");  char const* const _PREHASH_ParcelGodMarkAsContent = LLMessageStringTable::getInstance()->getString("ParcelGodMarkAsContent");  char const* const _PREHASH_UsePhysics = LLMessageStringTable::getInstance()->getString("UsePhysics"); diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h index 7910fde305..334236fb25 100644 --- a/indra/llmessage/message_prehash.h +++ b/indra/llmessage/message_prehash.h @@ -818,6 +818,7 @@ extern char const* const _PREHASH_StateSave;  extern char const* const _PREHASH_RoleData;  extern char const* const _PREHASH_AgentAnimation;  extern char const* const _PREHASH_AvatarAnimation; +extern char const* const _PREHASH_ObjectAnimation;  extern char const* const _PREHASH_LogDwellTime;  extern char const* const _PREHASH_ParcelGodMarkAsContent;  extern char const* const _PREHASH_UsePhysics; diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index bfa65666b5..c847cf653f 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -1599,6 +1599,8 @@ BOOL LLNetworkData::isValid(U16 param_type, U32 size)  		return (size == 17);  	case PARAMS_LIGHT_IMAGE:  		return (size == 28); +    case PARAMS_EXTENDED_MESH: +        return (size == 4);  	}  	return FALSE; @@ -2026,3 +2028,67 @@ bool LLLightImageParams::fromLLSD(LLSD& sd)  	return false;  } + +//============================================================================ + +LLExtendedMeshParams::LLExtendedMeshParams() +{ +    mType = PARAMS_EXTENDED_MESH; +	mFlags = 0; +} + +BOOL LLExtendedMeshParams::pack(LLDataPacker &dp) const +{ +	dp.packU32(mFlags, "flags"); + +	return TRUE; +} + +BOOL LLExtendedMeshParams::unpack(LLDataPacker &dp) +{ +	dp.unpackU32(mFlags, "flags"); +	 +	return TRUE; +} + +bool LLExtendedMeshParams::operator==(const LLNetworkData& data) const +{ +	if (data.mType != PARAMS_EXTENDED_MESH) +	{ +		return false; +	} +	 +	const LLExtendedMeshParams *param = (const LLExtendedMeshParams*)&data; +	if ( (param->mFlags != mFlags) ) +	{ +		return false; +	} + +	return true; +} + +void LLExtendedMeshParams::copy(const LLNetworkData& data) +{ +	const LLExtendedMeshParams *param = (LLExtendedMeshParams*)&data; +	mFlags = param->mFlags; +} + +LLSD LLExtendedMeshParams::asLLSD() const +{ +	LLSD sd; +	 +	sd["flags"] = LLSD::Integer(mFlags); +		 +	return sd; +} + +bool LLExtendedMeshParams::fromLLSD(LLSD& sd) +{ +	if (sd.has("flags")) +	{ +		setFlags( sd["flags"].asInteger()); +		return true; +	}  +	 +	return false; +} diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 19d9d52817..9216c04229 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -106,6 +106,7 @@ public:  		PARAMS_LIGHT_IMAGE = 0x40,  		PARAMS_RESERVED = 0x50, // Used on server-side  		PARAMS_MESH     = 0x60, +        PARAMS_EXTENDED_MESH = 0x70,  	};  public: @@ -288,6 +289,27 @@ public:  }; +class LLExtendedMeshParams : public LLNetworkData +{ +protected: +	U32 mFlags; +	 +public: +	static const U32 ANIMATED_MESH_ENABLED_FLAG = 0x1 << 0; + +	LLExtendedMeshParams(); +	/*virtual*/ BOOL pack(LLDataPacker &dp) const; +	/*virtual*/ BOOL unpack(LLDataPacker &dp); +	/*virtual*/ bool operator==(const LLNetworkData& data) const; +	/*virtual*/ void copy(const LLNetworkData& data); +	LLSD asLLSD() const; +	operator LLSD() const { return asLLSD(); } +	bool fromLLSD(LLSD& sd); + +	void setFlags(const U32& flags) { mFlags = flags; } +    U32 getFlags() const { return mFlags; } +	 +};  // This code is not naming-standards compliant. Leaving it like this for  // now to make the connection to code in diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b4e930d062..3787a25a9b 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -149,6 +149,7 @@ set(viewer_SOURCE_FILES      llcommunicationchannel.cpp      llcompilequeue.cpp      llconfirmationmanager.cpp +    llcontrolavatar.cpp      llconversationlog.cpp      llconversationloglist.cpp      llconversationloglistitem.cpp @@ -769,6 +770,7 @@ set(viewer_HEADER_FILES      llcommunicationchannel.h      llcompilequeue.h      llconfirmationmanager.h +    llcontrolavatar.h      llconversationlog.h      llconversationloglist.h      llconversationloglistitem.h diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml index ecd7c4bc36..ddd07dba80 100644 --- a/indra/newview/app_settings/logcontrol.xml +++ b/indra/newview/app_settings/logcontrol.xml @@ -50,6 +50,7 @@  						</array>  					<key>tags</key>  						<array> +                          <string>AXON</string>  						<!-- sample entry for debugging specific items	  						     <string>Avatar</string>  						     <string>Inventory</string> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index c544205df0..3e06e7094d 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -2171,6 +2171,17 @@        <key>Value</key>        <string />      </map> +  <key>DebugAnimatedObjects</key> +  <map> +    <key>Comment</key> +    <string>Show info related to animated objects</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>Boolean</string> +    <key>Value</key> +    <integer>0</integer> +  </map>    <key>DebugAvatarAppearanceMessage</key>    <map>      <key>Comment</key> @@ -10382,6 +10393,17 @@  		<key>Value</key>  		<integer>0</integer>  	</map> +	<key>RenderForceVolumeLOD</key> +    <map> +      <key>Comment</key> +      <string>Override for all volume LODs</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>S32</string> +      <key>Value</key> +      <integer>-1</integer> +    </map>  	<key>RenderVolumeLODFactor</key>      <map>        <key>Comment</key> diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index c928cf0601..d58d03d68d 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -880,7 +880,10 @@ void LLWearableHoldingPattern::onAllComplete()  			 ++it)  		{  			LLViewerObject *objectp = *it; -			gAgentAvatarp->addAttachmentOverridesForObject(objectp); +            if (!objectp->isAnimatedObject()) +            { +                gAgentAvatarp->addAttachmentOverridesForObject(objectp); +            }  		}  		// Add new attachments to match those requested. diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 37340a42b6..4ab19b714f 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -594,6 +594,7 @@ static void settings_to_globals()  	LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO");  	LLImageGL::sGlobalUseAnisotropic	= gSavedSettings.getBOOL("RenderAnisotropic");  	LLImageGL::sCompressTextures		= gSavedSettings.getBOOL("RenderCompressTextures"); +	LLVOVolume::sForceLOD				= gSavedSettings.getS32("RenderForceVolumeLOD");  	LLVOVolume::sLODFactor				= gSavedSettings.getF32("RenderVolumeLODFactor");  	LLVOVolume::sDistanceFactor			= 1.f-LLVOVolume::sLODFactor * 0.1f;  	LLVolumeImplFlexible::sUpdateFactor = gSavedSettings.getF32("RenderFlexTimeFactor"); diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp new file mode 100644 index 0000000000..d458e2951b --- /dev/null +++ b/indra/newview/llcontrolavatar.cpp @@ -0,0 +1,366 @@ +/** + * @file llcontrolavatar.cpp + * @brief Implementation for special dummy avatar used to drive rigged meshes. + * + * $LicenseInfo:firstyear=2017&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2017, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llcontrolavatar.h" +#include "llagent.h" //  Get state values from here +#include "llviewerobjectlist.h" +#include "pipeline.h" +#include "llanimationstates.h" +#include "llviewercontrol.h" +#include "llmeshrepository.h" + +LLControlAvatar::LLControlAvatar(const LLUUID& id, const LLPCode pcode, LLViewerRegion* regionp) : +    LLVOAvatar(id, pcode, regionp), +    mPlaying(false), +    mGlobalScale(1.0f), +    mMarkedForDeath(false) +{ +    mIsControlAvatar = true; +    mEnableDefaultMotions = false; +} + +// virtual +LLControlAvatar::~LLControlAvatar() +{ +} + +void LLControlAvatar::matchVolumeTransform() +{ +    { +        LLVolume *volume = mRootVolp->getVolume(); +        if (volume) +        { +            LLUUID mesh_id = volume->getParams().getSculptID(); +            const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(mesh_id, mRootVolp); +            if (skin) +            { +                LLMatrix4 bind_shape = skin->mBindShapeMatrix; +                LL_INFOS("AXON") << "bind_shape is " << bind_shape << LL_ENDL; +            } +        } +    } +     +	setPositionAgent(mRootVolp->getRenderPosition()); +	//slamPosition(); + +    LLQuaternion fix_axes_rot(-F_PI_BY_TWO, LLVector3(0,0,1)); +    LLQuaternion obj_rot = mRootVolp->getRotation(); +    LLQuaternion result_rot = fix_axes_rot * obj_rot; +	setRotation(result_rot); +    mRoot->setWorldRotation(result_rot); +    mRoot->setPosition(mRootVolp->getRenderPosition()); +} + +void LLControlAvatar::setGlobalScale(F32 scale) +{ +    if (scale <= 0.0) +    { +        LL_WARNS() << "invalid global scale " << scale << LL_ENDL; +        return; +    } +    if (scale != mGlobalScale) +    { +        F32 adjust_scale = scale/mGlobalScale; +        LL_INFOS() << "scale " << scale << " adjustment " << adjust_scale << LL_ENDL; +        // AXON - should we be scaling from the pelvis or the root? +        recursiveScaleJoint(mPelvisp,adjust_scale); +        mGlobalScale = scale; +    } +} + +void LLControlAvatar::recursiveScaleJoint(LLJoint* joint, F32 factor) +{ +    joint->setScale(factor * joint->getScale()); +     +	for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin(); +		 iter != joint->mChildren.end(); ++iter) +	{ +		LLJoint* child = *iter; +		recursiveScaleJoint(child, factor); +	} +} + +// Based on LLViewerJointAttachment::setupDrawable(), without the attaching part. +void LLControlAvatar::updateVolumeGeom() +{ +	if (!mRootVolp->mDrawable) +		return; +	if (mRootVolp->mDrawable->isActive()) +	{ +		mRootVolp->mDrawable->makeStatic(FALSE); +	} +	mRootVolp->mDrawable->makeActive(); +	gPipeline.markMoved(mRootVolp->mDrawable); +	gPipeline.markTextured(mRootVolp->mDrawable); // face may need to change draw pool to/from POOL_HUD +	mRootVolp->mDrawable->setState(LLDrawable::USE_BACKLIGHT); + +	LLViewerObject::const_child_list_t& child_list = mRootVolp->getChildren(); +	for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); +		 iter != child_list.end(); ++iter) +	{ +		LLViewerObject* childp = *iter; +		if (childp && childp->mDrawable.notNull()) +		{ +			childp->mDrawable->setState(LLDrawable::USE_BACKLIGHT); +			gPipeline.markTextured(childp->mDrawable); // face may need to change draw pool to/from POOL_HUD +			gPipeline.markMoved(childp->mDrawable); +        } +    } + +    gPipeline.markRebuild(mRootVolp->mDrawable, LLDrawable::REBUILD_ALL, TRUE); +    mRootVolp->markForUpdate(TRUE); + +    // Note that attachment overrides aren't needed here, have already +    // been applied at the time the mControlAvatar was created, in +    // llvovolume.cpp. + +    matchVolumeTransform(); + +    // AXON testing scale + +    // What should the scale be? What we really want is the ratio +    // between the scale at which the object was originally designed +    // and rigged, and the scale to which it has been subsequently +    // modified - for example, if the object has been scaled down by a +    // factor of 2 then we should use 0.5 as the global scale. But we +    // don't have the original scale stored anywhere, just the current +    // scale. Possibilities - 1) remember the original scale +    // somewhere, 2) add another field to let the user specify the +    // global scale, 3) approximate the original scale by looking at +    // the proportions of the skeleton after joint positions have +    // been applied +     +    //LLVector3 obj_scale = obj->getScale(); +    //F32 obj_scale_z = llmax(obj_scale[2],0.1f); +    //setGlobalScale(obj_scale_z/2.0f); // roughly fit avatar height range (2m) into object height +} + +LLControlAvatar *LLControlAvatar::createControlAvatar(LLVOVolume *obj) +{ +    // AXON Lifted from LLPreviewAnimation +	LLControlAvatar *cav = (LLControlAvatar*)gObjectList.createObjectViewer(LL_PCODE_LEGACY_AVATAR, gAgent.getRegion(), CO_FLAG_CONTROL_AVATAR); + +    cav->mRootVolp = obj; +     +	cav->createDrawable(&gPipeline); +	cav->mIsDummy = TRUE; +	cav->mSpecialRenderMode = 1; +	cav->updateJointLODs(); +	cav->updateGeometry(cav->mDrawable); +	cav->hideSkirt(); + +    // Sync up position/rotation with object +    cav->matchVolumeTransform(); + +    return cav; +} + +void LLControlAvatar::markForDeath() +{ +    mMarkedForDeath = true; +} + +// static +void LLControlAvatar::idleUpdate(LLAgent &agent, const F64 &time) +{ +    if (mMarkedForDeath) +    { +        markDead(); +        mMarkedForDeath = false; +    } +    else +    { +        LLVOAvatar::idleUpdate(agent,time); +    } +} + +//virtual +void LLControlAvatar::updateDebugText() +{ +	if (gSavedSettings.getBOOL("DebugAnimatedObjects")) +    { +        S32 total_linkset_count = 0; +        if (mRootVolp) +        { +            total_linkset_count = 1 + mRootVolp->getChildren().size(); +        } +        std::vector<LLVOVolume*> volumes; +        getAnimatedVolumes(volumes); +        S32 animated_volume_count = volumes.size(); +        std::string active_string; +        std::string lod_string; +        S32 total_tris = 0; +        S32 total_verts = 0; +        for (std::vector<LLVOVolume*>::iterator it = volumes.begin(); +             it != volumes.end(); ++it) +        { +            LLVOVolume *volp = *it; +            S32 verts = 0; +            total_tris += volp->getTriangleCount(&verts); +            total_verts += verts; +            lod_string += llformat("%d",volp->getLOD()); +                        if (volp && volp->mDrawable) +            { +                if (volp->mDrawable->isActive()) +                { +                    active_string += "A"; +                } +                else +                { +                    active_string += "S"; +                } +            } +            else +            { +                active_string += "-"; +            } +        } +        addDebugText(llformat("CAV obj %d anim %d active %s", +                              total_linkset_count, animated_volume_count, active_string.c_str())); + +#if 0 +        // AXON - detailed rigged mesh info +        for (std::vector<LLVOVolume*>::iterator it = volumes.begin(); +             it != volumes.end(); ++it) +        { +            LLRiggedVolume *rig_vol = (*it)->getRiggedVolume(); +            if (rig_vol) +            { +                addDebugText(rig_vol->mExtraDebugText); +            } +        } +#endif + +        addDebugText(llformat("lod %s",lod_string.c_str())); +        addDebugText(llformat("tris %d verts %d", total_tris, total_verts)); +        //addDebugText(llformat("anim time %.1f (step %f factor %f)",  +        //                      mMotionController.getAnimTime(), +        //                      mMotionController.getTimeStep(),  +        //                      mMotionController.getTimeFactor())); +         +    } + +    LLVOAvatar::updateDebugText(); +} + +void LLControlAvatar::getAnimatedVolumes(std::vector<LLVOVolume*>& volumes) +{ +    if (!mRootVolp) +    { +        return; +    } + +    volumes.push_back(mRootVolp); +     +	LLViewerObject::const_child_list_t& child_list = mRootVolp->getChildren(); +	for (LLViewerObject::const_child_list_t::const_iterator iter = child_list.begin(); +		 iter != child_list.end(); ++iter) +	{ +		LLViewerObject* childp = *iter; +        LLVOVolume *child_volp = dynamic_cast<LLVOVolume*>(childp); +        if (child_volp && child_volp->isAnimatedObject()) +        { +            volumes.push_back(child_volp); +        } +    } +} + +// This is called after an associated object receives an animation +// message. Combine the signaled animations for all associated objects +// and process any resulting state changes. +void LLControlAvatar::updateAnimations() +{ +    if (!mRootVolp) +    { +        LL_WARNS("AXON") << "No root vol" << LL_ENDL; +        return; +    } + +    std::vector<LLVOVolume*> volumes; +    getAnimatedVolumes(volumes); +     +    // Rebuild mSignaledAnimations from the associated volumes. +	std::map<LLUUID, S32> anims; +    for (std::vector<LLVOVolume*>::iterator vol_it = volumes.begin(); vol_it != volumes.end(); ++vol_it) +    { +        LLVOVolume *volp = *vol_it; +        for (std::map<LLUUID,S32>::iterator anim_it = volp->mObjectSignaledAnimations.begin(); +             anim_it != volp->mObjectSignaledAnimations.end(); +             ++anim_it) +        { +            std::map<LLUUID,S32>::iterator found_anim_it = anims.find(anim_it->first); +            if (found_anim_it != anims.end()) +            { +                // Animation already present, use the larger sequence id +                anims[anim_it->first] = llmax(found_anim_it->second, anim_it->second); +            } +            else +            { +                // Animation not already present, use this sequence id. +                anims[anim_it->first] = anim_it->second; +            } +        } +    } +    mSignaledAnimations = anims; + +    LL_DEBUGS("AXON") << "process animation state changes here" << LL_ENDL; +    processAnimationStateChanges(); +} + +// virtual +LLViewerObject* LLControlAvatar::lineSegmentIntersectRiggedAttachments(const LLVector4a& start, const LLVector4a& end, +									  S32 face, +									  BOOL pick_transparent, +									  BOOL pick_rigged, +									  S32* face_hit, +									  LLVector4a* intersection, +									  LLVector2* tex_coord, +									  LLVector4a* normal, +									  LLVector4a* tangent) +{ +	LLViewerObject* hit = NULL; + +	if (lineSegmentBoundingBox(start, end)) +	{ +		LLVector4a local_end = end; +		LLVector4a local_intersection; + +        if (mRootVolp && +            mRootVolp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent)) +        { +            local_end = local_intersection; +            if (intersection) +            { +                *intersection = local_intersection; +            } +			 +            hit = mRootVolp; +        } +	} +		 +	return hit; +} diff --git a/indra/newview/llcontrolavatar.h b/indra/newview/llcontrolavatar.h new file mode 100644 index 0000000000..a6b77b73ba --- /dev/null +++ b/indra/newview/llcontrolavatar.h @@ -0,0 +1,81 @@ +/** + * @file llcontrolavatar.h + * @brief Special dummy avatar used to drive rigged meshes. + * + * $LicenseInfo:firstyear=2017&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2017, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_CONTROLAVATAR_H +#define LL_CONTROLAVATAR_H + +#include "llvoavatar.h" +#include "llvovolume.h" + +class LLControlAvatar: +    public LLVOAvatar +{ +    LOG_CLASS(LLControlAvatar); + +public: +    LLControlAvatar(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); +	virtual	~LLControlAvatar(); + +    void matchVolumeTransform(); +    void updateVolumeGeom(); +         +    void setGlobalScale(F32 scale); +    void recursiveScaleJoint(LLJoint *joint, F32 factor); +    static LLControlAvatar *createControlAvatar(LLVOVolume *obj); + +    // Delayed kill so we don't make graphics pipeline unhappy calling +    // markDead() inside other graphics pipeline operations. +    void markForDeath(); + +    virtual void idleUpdate(LLAgent &agent, const F64 &time); + +    void getAnimatedVolumes(std::vector<LLVOVolume*>& volumes); +    void updateAnimations();   +     +	virtual LLViewerObject*	lineSegmentIntersectRiggedAttachments( +        const LLVector4a& start, const LLVector4a& end, +        S32 face = -1,                    // which face to check, -1 = ALL_SIDES +        BOOL pick_transparent = FALSE, +        BOOL pick_rigged = FALSE, +        S32* face_hit = NULL,             // which face was hit +        LLVector4a* intersection = NULL,   // return the intersection point +        LLVector2* tex_coord = NULL,      // return the texture coordinates of the intersection point +        LLVector4a* normal = NULL,         // return the surface normal at the intersection point +        LLVector4a* tangent = NULL);     // return the surface tangent at the intersection point + +	virtual void	updateDebugText(); + +    bool mPlaying; + +    F32 mGlobalScale; + +    LLVOVolume *mRootVolp; + +    bool mMarkedForDeath; + +}; + +#endif //LL_CONTROLAVATAR_H diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index f956023358..8001486b53 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -50,6 +50,7 @@  #include "llviewerobjectlist.h"  #include "llviewerwindow.h"  #include "llvocache.h" +#include "llcontrolavatar.h"  const F32 MIN_INTERPOLATE_DISTANCE_SQUARED = 0.001f * 0.001f;  const F32 MAX_INTERPOLATE_DISTANCE_SQUARED = 10.f * 10.f; @@ -550,7 +551,8 @@ void LLDrawable::makeStatic(BOOL warning_enabled)  	if (isState(ACTIVE) &&   		!isState(ACTIVE_CHILD) &&   		!mVObjp->isAttachment() &&  -		!mVObjp->isFlexible()) +		!mVObjp->isFlexible() && +        !mVObjp->isAnimatedObject())  	{  		clearState(ACTIVE | ANIMATED_CHILD); @@ -696,6 +698,11 @@ F32 LLDrawable::updateXform(BOOL undamped)  	mXform.setScale(LLVector3(1,1,1)); //no scale in drawable transforms (IT'S A RULE!)  	mXform.updateMatrix(); +    if (mVObjp && mVObjp->isRootEdit() && mVObjp->getControlAvatar()) +    { +        mVObjp->getControlAvatar()->matchVolumeTransform(); +    } +      	if (mSpatialBridge)  	{  		gPipeline.markMoved(mSpatialBridge, FALSE); diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index b221221f16..869e37e08c 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -467,6 +467,7 @@ void LLDrawPoolAvatar::renderShadow(S32 pass)  	}  	LLVOAvatar *avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get(); +// AXON fix  	if (avatarp->isDead() || avatarp->mIsDummy || avatarp->mDrawable.isNull())  	{  		return; diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index c9f8683e0e..c5fbc1f71b 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -86,6 +86,7 @@ BOOL	LLPanelVolume::postBuild()  {  	// Flexible Objects Parameters  	{ +		childSetCommitCallback("Animated Mesh Checkbox Ctrl", boost::bind(&LLPanelVolume::onCommitAnimatedMeshCheckbox, this, _1, _2), NULL);  		childSetCommitCallback("Flexible1D Checkbox Ctrl", boost::bind(&LLPanelVolume::onCommitIsFlexible, this, _1, _2), NULL);  		childSetCommitCallback("FlexNumSections",onCommitFlexible,this);  		getChild<LLUICtrl>("FlexNumSections")->setValidateBeforeCommit(precommitValidate); @@ -237,6 +238,11 @@ void LLPanelVolume::getState( )  	{  		volobjp = (LLVOVolume *)objectp;  	} +	LLVOVolume *root_volobjp = NULL; +    if (root_objectp && (root_objectp->getPCode() == LL_PCODE_VOLUME)) +    { +        root_volobjp  = (LLVOVolume *)root_objectp; +    }  	if( !objectp )  	{ @@ -260,6 +266,8 @@ void LLPanelVolume::getState( )  	BOOL editable = root_objectp->permModify() && !root_objectp->isPermanentEnforced();  	BOOL single_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME )  		&& LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1; +    BOOL single_root_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ) &&  +        LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() == 1;  	// Select Single Message  	if (single_volume) @@ -347,7 +355,20 @@ void LLPanelVolume::getState( )  		getChildView("Light Focus")->setEnabled(false);  		getChildView("Light Ambiance")->setEnabled(false);  	} -	 + +    // Animated Mesh +	BOOL is_animated_mesh = single_root_volume && root_volobjp && root_volobjp->isAnimatedObject(); +	getChild<LLUICtrl>("Animated Mesh Checkbox Ctrl")->setValue(is_animated_mesh); +    // AXON FIXME CHECK FOR SKIN INFO ALSO +    // WHAT ABOUT isPermanentEnforced? +    // What about linksets with some skinned objects? +    BOOL enabled_animated_object_box = FALSE; +    if (root_volobjp && root_volobjp == volobjp) +    { +        enabled_animated_object_box = single_root_volume && root_volobjp && root_volobjp->canBeAnimatedObject() && editable;  +    } +    getChildView("Animated Mesh Checkbox Ctrl")->setEnabled(enabled_animated_object_box); +  	// Flexible properties  	BOOL is_flexible = volobjp && volobjp->isFlexible();  	getChild<LLUICtrl>("Flexible1D Checkbox Ctrl")->setValue(is_flexible); @@ -587,6 +608,7 @@ void LLPanelVolume::clearCtrls()  	getChildView("Light Radius")->setEnabled(false);  	getChildView("Light Falloff")->setEnabled(false); +    getChildView("Animated Mesh Checkbox Ctrl")->setEnabled(false);  	getChildView("Flexible1D Checkbox Ctrl")->setEnabled(false);  	getChildView("FlexNumSections")->setEnabled(false);  	getChildView("FlexGravity")->setEnabled(false); @@ -899,6 +921,31 @@ void LLPanelVolume::onCommitFlexible( LLUICtrl* ctrl, void* userdata )  	self->refresh();  } +void LLPanelVolume::onCommitAnimatedMeshCheckbox(LLUICtrl *, void*) +{ +	LLViewerObject* objectp = mObject; +	if (!objectp || (objectp->getPCode() != LL_PCODE_VOLUME)) +	{ +		return; +    } +	LLVOVolume *volobjp = (LLVOVolume *)objectp; +	BOOL animated_mesh = getChild<LLUICtrl>("Animated Mesh Checkbox Ctrl")->getValue(); +    U32 flags = volobjp->getExtendedMeshFlags(); +    U32 new_flags = flags; +    if (animated_mesh) +    { +        new_flags |= LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG; +    } +    else +    { +        new_flags &= ~LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG; +    } +    if (new_flags != flags) +    { +        volobjp->setExtendedMeshFlags(new_flags); +    } +} +  void LLPanelVolume::onCommitIsFlexible(LLUICtrl *, void*)  {  	if (mObject->flagObjectPermanent()) diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h index deb6b6f2a6..d85df69b19 100644 --- a/indra/newview/llpanelvolume.h +++ b/indra/newview/llpanelvolume.h @@ -63,6 +63,7 @@ public:  	static void 	onCommitLight(			LLUICtrl* ctrl, void* userdata);  	void 			onCommitIsFlexible(		LLUICtrl* ctrl, void* userdata);  	static void 	onCommitFlexible(		LLUICtrl* ctrl, void* userdata); +    void            onCommitAnimatedMeshCheckbox(LLUICtrl* ctrl, void* userdata);  	static void     onCommitPhysicsParam(       LLUICtrl* ctrl, void* userdata);  	static void 	onCommitMaterial(		LLUICtrl* ctrl, void* userdata); diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 983a7ca1ae..3e8d8883e0 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -46,6 +46,7 @@  #include "llundo.h"  #include "lluuid.h"  #include "llvolume.h" +#include "llcontrolavatar.h"  #include "message.h"  #include "object_flags.h"  #include "llquaternion.h" @@ -6628,7 +6629,10 @@ S32 get_family_count(LLViewerObject *parent)  //-----------------------------------------------------------------------------  // updateSelectionCenter -//----------------------------------------------------------------------------- +// +// FIXME this is a grab bag of functionality only some of which has to do +// with the selection center +// -----------------------------------------------------------------------------  void LLSelectMgr::updateSelectionCenter()  {  	const F32 MOVE_SELECTION_THRESHOLD = 1.f;		//  Movement threshold in meters for updating selection @@ -6646,23 +6650,12 @@ void LLSelectMgr::updateSelectionCenter()  		mSelectionCenterGlobal.clearVec();  		mShowSelection = FALSE;  		mSelectionBBox = LLBBox();  -		mPauseRequest = NULL;  		resetAgentHUDZoom(); -  	}  	else  	{  		mSelectedObjects->mSelectType = getSelectTypeForObject(object); -		if (mSelectedObjects->mSelectType == SELECT_TYPE_ATTACHMENT && isAgentAvatarValid() && object->getParent() != NULL) -		{ -			mPauseRequest = gAgentAvatarp->requestPause(); -		} -		else -		{ -			mPauseRequest = NULL; -		} -  		if (mSelectedObjects->mSelectType != SELECT_TYPE_HUD && isAgentAvatarValid())  		{  			// reset hud ZOOM @@ -6739,6 +6732,59 @@ void LLSelectMgr::updateSelectionCenter()  	{  		gEditMenuHandler = NULL;  	} + +    pauseAssociatedAvatars(); +} + +//----------------------------------------------------------------------------- +// pauseAssociatedAvatars +// +// If the selection includes an attachment or an animated object, the +// associated avatars should pause their animations until they are no +// longer selected. +//----------------------------------------------------------------------------- +void LLSelectMgr::pauseAssociatedAvatars() +{ +    mPauseRequests.clear(); + +    for (LLObjectSelection::iterator iter = mSelectedObjects->begin(); +         iter != mSelectedObjects->end(); iter++) +    { +        LLSelectNode* node = *iter; +        LLViewerObject* object = node->getObject(); +        if (!object) +            continue; +			 +        mSelectedObjects->mSelectType = getSelectTypeForObject(object); + +        if (mSelectedObjects->mSelectType == SELECT_TYPE_ATTACHMENT &&  +            isAgentAvatarValid() && object->getParent() != NULL) +        { +            if (object->isAnimatedObject()) +            { +                // Is an animated object attachment. +                // Pause both the control avatar and the avatar it's attached to. +                if (object->getControlAvatar()) +                { +                    mPauseRequests.push_back(object->getControlAvatar()->requestPause()); +                } +                mPauseRequests.push_back(gAgentAvatarp->requestPause()); +            } +            else +            { +                // Is a regular attachment. Pause the avatar it's attached to. +                mPauseRequests.push_back(gAgentAvatarp->requestPause()); +            } +        } +        else +        { +            if (object && object->isAnimatedObject() && object->getControlAvatar()) +            { +                // Is a non-attached animated object. Pause the control avatar. +                mPauseRequests.push_back(object->getControlAvatar()->requestPause()); +            } +        } +    }  }  void LLSelectMgr::updatePointAt() diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 7ef0032645..fc4b920c51 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -742,6 +742,8 @@ public:  	LLVector3d		getSelectionCenterGlobal() const	{ return mSelectionCenterGlobal; }  	void			updateSelectionCenter(); +    void pauseAssociatedAvatars(); +  	void resetAgentHUDZoom();  	void setAgentHUDZoom(F32 target_zoom, F32 current_zoom);  	void getAgentHUDZoom(F32 &target_zoom, F32 ¤t_zoom) const; @@ -843,7 +845,7 @@ private:  	LLFrameTimer			mEffectsTimer;  	BOOL					mForceSelection; -	LLAnimPauseRequest		mPauseRequest; +    std::vector<LLAnimPauseRequest>	mPauseRequests;  };  // *DEPRECATED: For callbacks or observers, use diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 1a480b1838..dc184e2538 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2386,6 +2386,7 @@ void register_viewer_callbacks(LLMessageSystem* msg)  	msg->setHandlerFuncFast(_PREHASH_NameValuePair,			process_name_value);  	msg->setHandlerFuncFast(_PREHASH_RemoveNameValuePair,	process_remove_name_value);  	msg->setHandlerFuncFast(_PREHASH_AvatarAnimation,		process_avatar_animation); +	msg->setHandlerFuncFast(_PREHASH_ObjectAnimation,		process_object_animation);  	msg->setHandlerFuncFast(_PREHASH_AvatarAppearance,		process_avatar_appearance);  	msg->setHandlerFuncFast(_PREHASH_CameraConstraint,		process_camera_constraint);  	msg->setHandlerFuncFast(_PREHASH_AvatarSitResponse,		process_avatar_sit_response); diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index fc052ae3aa..a06aeb5631 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -1750,8 +1750,7 @@ BOOL LLToolPie::handleRightClickPick()  		gMenuHolder->setObjectSelection(LLSelectMgr::getInstance()->getSelection());  		bool is_other_attachment = (object->isAttachment() && !object->isHUDAttachment() && !object->permYouOwner()); -		if (object->isAvatar()  -			|| is_other_attachment) +		if (object->isAvatar() || is_other_attachment)  		{  			// Find the attachment's avatar  			while( object && object->isAttachment()) diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 7c1921b143..66f5bf3c37 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -208,6 +208,12 @@ static bool handleAnisotropicChanged(const LLSD& newvalue)  	return true;  } +static bool handleForceLODChanged(const LLSD& newvalue) +{ +	LLVOVolume::sForceLOD = (F32) newvalue.asReal(); +	return true; +} +  static bool handleVolumeLODChanged(const LLSD& newvalue)  {  	LLVOVolume::sLODFactor = (F32) newvalue.asReal(); @@ -626,6 +632,7 @@ void settings_setup_listeners()  	gSavedSettings.getControl("RenderAvatarCloth")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));  	gSavedSettings.getControl("WindLightUseAtmosShaders")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));  	gSavedSettings.getControl("RenderGammaFull")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); +	gSavedSettings.getControl("RenderForceVolumeLOD")->getSignal()->connect(boost::bind(&handleForceLODChanged, _2));  	gSavedSettings.getControl("RenderVolumeLODFactor")->getSignal()->connect(boost::bind(&handleVolumeLODChanged, _2));  	gSavedSettings.getControl("RenderAvatarLODFactor")->getSignal()->connect(boost::bind(&handleAvatarLODChanged, _2));  	gSavedSettings.getControl("RenderAvatarPhysicsLODFactor")->getSignal()->connect(boost::bind(&handleAvatarPhysicsLODChanged, _2)); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index c68f6b8a15..f01c67e499 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -1076,6 +1076,10 @@ U32 info_display_from_string(std::string info_display)  	{  		return LLPipeline::RENDER_DEBUG_TEXEL_DENSITY;  	} +	else if ("triangle count" == info_display) +	{ +		return LLPipeline::RENDER_DEBUG_TRIANGLE_COUNT; +	}  	else  	{  		LL_WARNS() << "unrecognized feature name '" << info_display << "'" << LL_ENDL; @@ -6907,7 +6911,7 @@ class LLAttachmentEnableDrop : public view_listener_t  		// Do not enable drop if all faces of object are not enabled  		if (object && LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES ))  		{ -    		S32 attachmentID  = ATTACHMENT_ID_FROM_STATE(object->getState()); +    		S32 attachmentID  = ATTACHMENT_ID_FROM_STATE(object->getAttachmentState());  			attachment = get_if_there(gAgentAvatarp->mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL);  			if (attachment) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 06f868dc08..14846d898f 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -55,6 +55,7 @@  #include "llagentcamera.h"  #include "llcallingcard.h"  #include "llbuycurrencyhtml.h" +#include "llcontrolavatar.h"  #include "llfirstuse.h"  #include "llfloaterbump.h"  #include "llfloaterbuyland.h" @@ -103,6 +104,7 @@  #include "llviewerwindow.h"  #include "llvlmanager.h"  #include "llvoavatarself.h" +#include "llvovolume.h"  #include "llworld.h"  #include "pipeline.h"  #include "llfloaterworldmap.h" @@ -4982,12 +4984,15 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data)  	LLUUID	animation_id;  	LLUUID	uuid;  	S32		anim_sequence_id; -	LLVOAvatar *avatarp; +	LLVOAvatar *avatarp = NULL;  	mesgsys->getUUIDFast(_PREHASH_Sender, _PREHASH_ID, uuid); -	//clear animation flags -	avatarp = (LLVOAvatar *)gObjectList.findObject(uuid); +	LLViewerObject *objp = gObjectList.findObject(uuid); +    if (objp) +    { +        avatarp =  objp->asAvatar(); +    }  	if (!avatarp)  	{ @@ -4999,6 +5004,7 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data)  	S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_AnimationList);  	S32 num_source_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_AnimationSourceList); +	//clear animation flags  	avatarp->mSignaledAnimations.clear();  	if (avatarp->isSelf()) @@ -5069,6 +5075,65 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data)  	}  } +void process_object_animation(LLMessageSystem *mesgsys, void **user_data) +{ +	LLUUID	animation_id; +	LLUUID	uuid; +	S32		anim_sequence_id; +	 +	mesgsys->getUUIDFast(_PREHASH_Sender, _PREHASH_ID, uuid); + +    LLViewerObject *objp = gObjectList.findObject(uuid); +    if (!objp) +    { +		LL_WARNS("Messaging") << "AXON Received animation state for unknown object" << uuid << LL_ENDL; +        return; +    } +     +	LLVOVolume *volp = dynamic_cast<LLVOVolume*>(objp); +    if (!volp) +    { +		LL_WARNS("Messaging") << "AXON Received animation state for non-volume object" << uuid << LL_ENDL; +        return; +    } + +    if (!volp->isAnimatedObject()) +    { +		LL_WARNS("Messaging") << "AXON Received animation state for non-animated object" << uuid << LL_ENDL; +        return; +    } + +    LLControlAvatar *avatarp = volp->getControlAvatar(); +    if (!avatarp) +    { +        LL_WARNS() << "AXON no control avatar, ignoring" << LL_ENDL; +        return; +    } +     +	S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_AnimationList); +	LL_DEBUGS("AXON") << "handle object animation here, num_blocks " << num_blocks << LL_ENDL; + +    if (!avatarp->mPlaying) +    { +        avatarp->mPlaying = true; +		avatarp->updateVolumeGeom(); +    } + +	volp->mObjectSignaledAnimations.clear(); +	 +    for( S32 i = 0; i < num_blocks; i++ ) +    { +        mesgsys->getUUIDFast(_PREHASH_AnimationList, _PREHASH_AnimID, animation_id, i); +        mesgsys->getS32Fast(_PREHASH_AnimationList, _PREHASH_AnimSequenceID, anim_sequence_id, i); +        volp->mObjectSignaledAnimations[animation_id] = anim_sequence_id; +        LL_DEBUGS("AXON") << "got object animation request for object "  +                          << uuid << " animation id " << animation_id << LL_ENDL; +    } + +    avatarp->updateAnimations(); +} + +  void process_avatar_appearance(LLMessageSystem *mesgsys, void **user_data)  {  	LLUUID uuid; diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index b0eaa37541..cef6f79812 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -95,6 +95,7 @@ void process_health_message(LLMessageSystem *mesgsys, void **user_data);  void process_sim_stats(LLMessageSystem *mesgsys, void **user_data);  void process_shooter_agent_hit(LLMessageSystem* msg, void** user_data);  void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data); +void process_object_animation(LLMessageSystem *mesgsys, void **user_data);  void process_avatar_appearance(LLMessageSystem *mesgsys, void **user_data);  void process_camera_constraint(LLMessageSystem *mesgsys, void **user_data);  void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 1d6daed9cc..e2fbac023a 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -60,6 +60,7 @@  #include "llbbox.h"  #include "llbox.h"  #include "llcylinder.h" +#include "llcontrolavatar.h"  #include "lldrawable.h"  #include "llface.h"  #include "llfloaterproperties.h" @@ -138,7 +139,7 @@ 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 *LLViewerObject::createObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp, S32 flags)  {  	LLViewerObject *res = NULL;  	LL_RECORD_BLOCK_TIME(FTM_CREATE_OBJECT); @@ -166,6 +167,12 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco  			}  			res = gAgentAvatarp;  		} +		else if (flags & CO_FLAG_CONTROL_AVATAR) +		{ +            LLControlAvatar *avatar = new LLControlAvatar(id, pcode, regionp); +			avatar->initInstance(); +			res = avatar; +		}  		else  		{  			LLVOAvatar *avatar = new LLVOAvatar(id, pcode, regionp);  @@ -235,6 +242,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe  	mText(),  	mHudText(""),  	mHudTextColor(LLColor4::white), +    mControlAvatar(NULL),  	mLastInterpUpdateSecs(0.f),  	mLastMessageUpdateSecs(0.f),  	mLatestRecvPacketID(0), @@ -259,7 +267,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe  	mRotTime(0.f),  	mAngularVelocityRot(),  	mPreviousRotation(), -	mState(0), +	mAttachmentState(0),  	mMedia(NULL),  	mClickAction(0),  	mObjectCost(0), @@ -363,17 +371,23 @@ void LLViewerObject::markDead()  		//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->resetJointsOnDetach(mesh_id); -		} +        { +            LLVOAvatar *av = getAvatar(); +            if (av && LLVOAvatar::getRiggedMeshID(this,mesh_id)) +            { +                // This case is needed for indirectly attached mesh objects. +                av->removeAttachmentOverridesForObject(mesh_id); +            } +        } +        if (getControlAvatar()) +        { +            unlinkControlAvatar(); +        }  		// Mark itself as dead  		mDead = TRUE; @@ -1378,7 +1392,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,  				U8 state;  				mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num ); -				mState = state; +				mAttachmentState = state;  				// ...new objects that should come in selected need to be added to the selected list  				mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0); @@ -1648,7 +1662,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,  				U8 state;  				mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num ); -				mState = state; +				mAttachmentState = state;  				break;  			} @@ -1671,7 +1685,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,  		U8		state;  		dp->unpackU8(state, "State"); -		mState = state; +		mAttachmentState = state;  		switch(update_type)  		{ @@ -2902,6 +2916,61 @@ void LLViewerObject::fetchInventoryFromServer()  	}  } +LLControlAvatar *LLViewerObject::getControlAvatar() +{ +    return getRootEdit()->mControlAvatar.get(); +} + +LLControlAvatar *LLViewerObject::getControlAvatar() const +{ +    return getRootEdit()->mControlAvatar.get(); +} + +void LLViewerObject::linkControlAvatar() +{ +    if (!getControlAvatar() && isRootEdit()) +    { +        LLVOVolume *volp = dynamic_cast<LLVOVolume*>(this); +        if (!volp) +        { +            LL_WARNS() << "called with null or non-volume object" << LL_ENDL; +            return; +        } +        mControlAvatar = LLControlAvatar::createControlAvatar(volp); +    } +    if (getControlAvatar()) +    { +        getControlAvatar()->addAttachmentOverridesForObject(this); +    } +    else +    { +        LL_WARNS() << "no control avatar found!" << LL_ENDL; +    } +} + +void LLViewerObject::unlinkControlAvatar() +{ +    if (getControlAvatar()) +    { +        getControlAvatar()->removeAttachmentOverridesForObject(this); +    } +    if (isRootEdit()) +    { +        // This will remove the entire linkset from the control avatar +        LLControlAvatar *av = mControlAvatar; +        mControlAvatar = NULL; +        av->markForDeath(); +    } +    // For non-root prims, removing from the linkset will +    // automatically remove the control avatar connection. +} + +// virtual +bool LLViewerObject::isAnimatedObject() const +{ +    return false; +} +  struct LLFilenameAndTask  {  	LLUUID mTaskID; @@ -3857,7 +3926,7 @@ const LLVector3 LLViewerObject::getRenderPosition() const  	if (mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED))  	{  		LLVOAvatar* avatar = getAvatar(); -		if (avatar) +		if (avatar && !getControlAvatar())  		{  			return avatar->getPositionAgent();  		} @@ -5122,6 +5191,7 @@ LLVOAvatar* LLViewerObject::asAvatar()  // If this object is directly or indirectly parented by an avatar, return it.  LLVOAvatar* LLViewerObject::getAvatarAncestor()  { +    LL_ERRS("AXON") << "this method has been targetted for termination. Use getAvatar()." << LL_ENDL;  	LLViewerObject *pobj = (LLViewerObject*) getParent();  	while (pobj)  	{ @@ -5458,6 +5528,11 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para  		  new_block = new LLLightImageParams();  		  break;  	  } +      case LLNetworkData::PARAMS_EXTENDED_MESH: +      { +		  new_block = new LLExtendedMeshParams(); +		  break; +      }  	  default:  	  {  		  LL_INFOS() << "Unknown param type." << LL_ENDL; @@ -6353,6 +6428,10 @@ const std::string& LLViewerObject::getAttachmentItemName() const  //virtual  LLVOAvatar* LLViewerObject::getAvatar() const  { +    if (getControlAvatar()) +    { +        return getControlAvatar(); +    }  	if (isAttachment())  	{  		LLViewerObject* vobj = (LLViewerObject*) getParent(); diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 24fcf0517e..c79ff7bb74 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -47,6 +47,7 @@ class LLAgent;			// TODO: Get rid of this.  class LLAudioSource;  class LLAudioSourceVO;  class LLColor4; +class LLControlAvatar;  class LLDataPacker;  class LLDataPackerBinaryBuffer;  class LLDrawable; @@ -374,7 +375,7 @@ public:  	void sendShapeUpdate(); -	U8 getState()							{ return mState; } +	U8 getAttachmentState()							{ return mAttachmentState; }  	F32 getAppAngle() const					{ return mAppAngle; }  	F32 getPixelArea() const				{ return mPixelArea; } @@ -683,6 +684,21 @@ public:  	static			BOOL		sUseSharedDrawables; +public: +    // Returns mControlAvatar for the edit root prim of this linkset +    LLControlAvatar *getControlAvatar(); +    LLControlAvatar *getControlAvatar() const; + +    // Create or connect to an existing control av as applicable +    void linkControlAvatar(); +    // Remove any reference to control av for this prim +    void unlinkControlAvatar(); + +    virtual bool isAnimatedObject() const; + +protected: +    LLPointer<LLControlAvatar> mControlAvatar; +  protected:  	// delete an item in the inventory, but don't tell the  	// server. This is used internally by remove, update, and @@ -693,8 +709,10 @@ protected:  	// updateInventory.  	void doUpdateInventory(LLPointer<LLViewerInventoryItem>& item, U8 key, bool is_new); +    // Flags for createObject +    static const S32 CO_FLAG_CONTROL_AVATAR = 1 << 1; -	static LLViewerObject *createObject(const LLUUID &id, LLPCode pcode, LLViewerRegion *regionp); +	static LLViewerObject *createObject(const LLUUID &id, LLPCode pcode, LLViewerRegion *regionp, S32 flags = 0);  	BOOL setData(const U8 *datap, const U32 data_size); @@ -782,7 +800,7 @@ protected:  	LLQuaternion	mAngularVelocityRot;		// accumulated rotation from the angular velocity computations  	LLQuaternion	mPreviousRotation; -	U8				mState;	// legacy +	U8				mAttachmentState;	// this encodes the attachment id in a somewhat complex way. 0 if not an attachment.  	LLViewerObjectMedia* mMedia;	// NULL if no media associated  	U8 mClickAction;  	F32 mObjectCost; //resource cost of this object or -1 if unknown diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 8f98d66c0c..1f99119d82 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -1942,12 +1942,12 @@ void LLViewerObjectList::resetObjectBeacons()  	mDebugBeacons.clear();  } -LLViewerObject *LLViewerObjectList::createObjectViewer(const LLPCode pcode, LLViewerRegion *regionp) +LLViewerObject *LLViewerObjectList::createObjectViewer(const LLPCode pcode, LLViewerRegion *regionp, S32 flags)  {  	LLUUID fullid;  	fullid.generate(); -	LLViewerObject *objectp = LLViewerObject::createObject(fullid, pcode, regionp); +	LLViewerObject *objectp = LLViewerObject::createObject(fullid, pcode, regionp, flags);  	if (!objectp)  	{  // 		LL_WARNS() << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) << LL_ENDL; diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h index 94c751acc6..72b2b99004 100644 --- a/indra/newview/llviewerobjectlist.h +++ b/indra/newview/llviewerobjectlist.h @@ -67,7 +67,7 @@ public:  	inline LLViewerObject *getObject(const S32 index);  	inline LLViewerObject *findObject(const LLUUID &id); -	LLViewerObject *createObjectViewer(const LLPCode pcode, LLViewerRegion *regionp); // Create a viewer-side object +	LLViewerObject *createObjectViewer(const LLPCode pcode, LLViewerRegion *regionp, S32 flags = 0); // Create a viewer-side object  	LLViewerObject *createObjectFromCache(const LLPCode pcode, LLViewerRegion *regionp, const LLUUID &uuid, const U32 local_id);  	LLViewerObject *createObject(const LLPCode pcode, LLViewerRegion *regionp,  								 const LLUUID &uuid, const U32 local_id, const LLHost &sender); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index eb37613c95..02ac0a0d34 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -2857,6 +2857,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)  	capabilityNames.append("MeshUploadFlag");	  	capabilityNames.append("NavMeshGenerationStatus");  	capabilityNames.append("NewFileAgentInventory"); +	capabilityNames.append("ObjectAnimation");  	capabilityNames.append("ObjectMedia");  	capabilityNames.append("ObjectMediaNavigate");  	capabilityNames.append("ObjectNavMeshProperties"); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 80c6805ead..eab5206828 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -44,6 +44,7 @@  #include "llavatarnamecache.h"  #include "llavatarpropertiesprocessor.h"  #include "llavatarrendernotifier.h" +#include "llcontrolavatar.h"  #include "llexperiencecache.h"  #include "llphysicsmotion.h"  #include "llviewercontrol.h" @@ -663,7 +664,9 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,  	mLastUpdateRequestCOFVersion(-1),  	mLastUpdateReceivedCOFVersion(-1),  	mCachedMuteListUpdateTime(0), -	mCachedInMuteList(false) +	mCachedInMuteList(false), +    mIsControlAvatar(false), +    mEnableDefaultMotions(true)  {  	LL_DEBUGS("AvatarRender") << "LLVOAvatar Constructor (0x" << this << ") id:" << mID << LL_ENDL; @@ -718,6 +721,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,  	mCurrentGesticulationLevel = 0; +      	mRuthTimer.reset();  	mRuthDebugTimer.reset();  	mDebugExistenceTimer.reset(); @@ -1222,8 +1226,6 @@ const LLVector3 LLVOAvatar::getRenderPosition() const  	{  		return getPosition() * mDrawable->getParent()->getRenderMatrix();  	} -	 -	  }  void LLVOAvatar::updateDrawable(BOOL force_damped) @@ -1240,6 +1242,10 @@ void LLVOAvatar::onShift(const LLVector4a& shift_vector)  void LLVOAvatar::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax)  { +    if (mDrawable.isNull()) +    { +        return; +    }  	if (isImpostor() && !needsImpostorUpdate())  	{  		LLVector3 delta = getRenderPosition() - @@ -1404,13 +1410,29 @@ void LLVOAvatar::renderCollisionVolumes()          static F32 sphere_scale = 1.0f;          static F32 center_dot_scale = 0.05f; -        static LLVector3 CV_COLOR_OCCLUDED(0.0f, 0.0f, 1.0f); -        static LLVector3 CV_COLOR_VISIBLE(0.5f, 0.5f, 1.0f); -        static LLVector3 DOT_COLOR_OCCLUDED(1.0f, 1.0f, 1.0f); -        static LLVector3 DOT_COLOR_VISIBLE(1.0f, 1.0f, 1.0f); +        static LLVector3 BLUE(0.0f, 0.0f, 1.0f); +        static LLVector3 PASTEL_BLUE(0.5f, 0.5f, 1.0f); +        static LLVector3 RED(1.0f, 0.0f, 0.0f); +        static LLVector3 PASTEL_RED(1.0f, 0.5f, 0.5f); +        static LLVector3 WHITE(1.0f, 1.0f, 1.0f); +         -        render_sphere_and_line(begin_pos, end_pos, sphere_scale, CV_COLOR_OCCLUDED, CV_COLOR_VISIBLE); -        render_sphere_and_line(begin_pos, end_pos, center_dot_scale, DOT_COLOR_OCCLUDED, DOT_COLOR_VISIBLE); +        LLVector3 cv_color_occluded; +        LLVector3 cv_color_visible; +        LLVector3 dot_color_occluded(WHITE); +        LLVector3 dot_color_visible(WHITE); +        if (isControlAvatar()) +        { +            cv_color_occluded = RED; +            cv_color_visible = PASTEL_RED; +        } +        else +        { +            cv_color_occluded = BLUE; +            cv_color_visible = PASTEL_BLUE; +        } +        render_sphere_and_line(begin_pos, end_pos, sphere_scale, cv_color_occluded, cv_color_visible); +        render_sphere_and_line(begin_pos, end_pos, center_dot_scale, dot_color_occluded, dot_color_visible);          gGL.popMatrix();      } @@ -1422,9 +1444,6 @@ void LLVOAvatar::renderCollisionVolumes()  		mNameText->lineSegmentIntersect(unused, unused, unused, TRUE);  	} - -	mDebugText.clear(); -	addDebugText(ostr.str());  }  void LLVOAvatar::renderBones() @@ -1595,6 +1614,11 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&  		return FALSE;  	} +    if (isControlAvatar()) +    { +        return FALSE; +    } +      	if (lineSegmentBoundingBox(start, end))  	{  		for (S32 i = 0; i < mNumCollisionVolumes; ++i) @@ -1680,6 +1704,7 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&  	return FALSE;  } +// virtual  LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector4a& start, const LLVector4a& end,  									  S32 face,  									  BOOL pick_transparent, @@ -1796,7 +1821,11 @@ void LLVOAvatar::buildCharacter()  		mAahMorph = getVisualParam( "Express_Open_Mouth" );  	} -	startDefaultMotions(); +    // Currently disabled for control avatars (animated objects), enabled for all others. +    if (mEnableDefaultMotions) +    { +        startDefaultMotions(); +    }  	//-------------------------------------------------------------------------  	// restart any currently active motions @@ -1942,6 +1971,8 @@ void LLVOAvatar::resetSkeleton(bool reset_animations)  //-----------------------------------------------------------------------------  void LLVOAvatar::releaseMeshData()  { +    // AXON what should we be doing here for control avs? Why are +    // dummies treated differently in the first place?  	if (sInstances.size() < AVATAR_RELEASE_THRESHOLD || mIsDummy)  	{  		return; @@ -1962,15 +1993,15 @@ void LLVOAvatar::releaseMeshData()  		LLFace* facep = mDrawable->getFace(0);  		if (facep)  		{ -		facep->setSize(0, 0); -		for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++) -		{ -			facep = mDrawable->getFace(i); +            facep->setSize(0, 0); +            for(S32 i = mNumInitFaces ; i < mDrawable->getNumFaces(); i++) +            { +                facep = mDrawable->getFace(i);  				if (facep)  				{ -			facep->setSize(0, 0); -		} -	} +                    facep->setSize(0, 0); +                } +            }  		}  	} @@ -1994,6 +2025,10 @@ void LLVOAvatar::releaseMeshData()  void LLVOAvatar::restoreMeshData()  {  	llassert(!isSelf()); +    if (mDrawable.isNull()) +    { +        return; +    }  	//LL_INFOS() << "Restoring" << LL_ENDL;  	mMeshValid = TRUE; @@ -2571,13 +2606,16 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update)  		}  	} -	mDrawable->movePartition(); -	 -	//force a move if sitting on an active object -	if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive()) -	{ -		gPipeline.markMoved(mDrawable, TRUE); -	} +    if (mDrawable.notNull()) +    { +        mDrawable->movePartition(); +         +        //force a move if sitting on an active object +        if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive()) +        { +            gPipeline.markMoved(mDrawable, TRUE); +        } +    }  }  void LLVOAvatar::idleUpdateAppearanceAnimation() @@ -2738,7 +2776,8 @@ void LLVOAvatar::idleUpdateLoadingEffect()  																 LLPartData::LL_PART_EMISSIVE_MASK | // LLPartData::LL_PART_FOLLOW_SRC_MASK |  																 LLPartData::LL_PART_TARGET_POS_MASK ); -			if (!isTooComplex()) // do not generate particles for overly-complex avatars +            // AXON skip cloud effects for dummy avs as well +			if (!mIsDummy && !isTooComplex()) // do not generate particles for overly-complex avatars  			{  				setParticleSource(particle_parameters, getID());  			} @@ -3338,8 +3377,7 @@ bool LLVOAvatar::isInMuteList()  void LLVOAvatar::updateDebugText()  { -	// clear debug text -	mDebugText.clear(); +    // Leave mDebugText uncleared here, in case a derived class has added some state first  	if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage"))  	{ @@ -3406,6 +3444,7 @@ void LLVOAvatar::updateDebugText()  			addDebugText(mBakedTextureDebugText);  	} +    // Develop -> Avatar -> Animation Info  	if (LLVOAvatar::sShowAnimationDebug)  	{  		for (LLMotionController::motion_list_t::iterator iter = mMotionController.getActiveMotions().begin(); @@ -3415,8 +3454,27 @@ void LLVOAvatar::updateDebugText()  			if (motionp->getMinPixelArea() < getPixelArea())  			{  				std::string output; -				if (motionp->getName().empty()) +                std::string motion_name = motionp->getName(); +				if (motion_name.empty())  				{ +                    if (isControlAvatar()) +                    { +                        LLControlAvatar *control_av = dynamic_cast<LLControlAvatar*>(this); +                        // Try to get name from inventory of associated object +                        LLVOVolume *volp = control_av->mRootVolp; +                        if (volp) +                        { +                            volp->requestInventory(); // AXON should be a no-op if already requested or fetched? +                            LLViewerInventoryItem* item = volp->getInventoryItemByAsset(motionp->getID()); +                            if (item) +                            { +                                motion_name = item->getName(); +                            } +                        } +                    } +                } +                if (motion_name.empty()) +                {  					output = llformat("%s - %d",  							  gAgent.isGodlikeWithoutAdminMenuFakery() ?  							  motionp->getID().asString().c_str() : @@ -3426,8 +3484,8 @@ void LLVOAvatar::updateDebugText()  				else  				{  					output = llformat("%s - %d", -							  motionp->getName().c_str(), -							  (U32)motionp->getPriority()); +                                      motion_name.c_str(), +                                      (U32)motionp->getPriority());  				}  				addDebugText(output);  			} @@ -3443,8 +3501,7 @@ void LLVOAvatar::updateDebugText()  	{  		setDebugText(mDebugText);  	} -	mDebugText.clear(); - +    mDebugText.clear();  }  //------------------------------------------------------------------------ @@ -3474,7 +3531,9 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)  	//--------------------------------------------------------------------  	bool visually_muted = isVisuallyMuted(); -	if (visible && (!isSelf() || visually_muted) && !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter) +    // AXON FIXME this expression is a crawling horror +	if (mDrawable.notNull() && visible && (!isSelf() || visually_muted) &&  +        !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter)  	{  		const LLVector4a* ext = mDrawable->getSpatialExtents();  		LLVector4a size; @@ -3530,7 +3589,9 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)  	}  	// change animation time quanta based on avatar render load -	if (!isSelf() && !mIsDummy) +    // AXON how should control avs be handled here? +    bool is_pure_dummy = mIsDummy && !isControlAvatar(); +	if (!isSelf() && !is_pure_dummy)  	{  		F32 time_quantum = clamp_rescale((F32)sInstances.size(), 10.f, 35.f, 0.f, 0.25f);  		F32 pixel_area_scale = clamp_rescale(mPixelArea, 100, 5000, 1.f, 0.f); @@ -3652,7 +3713,8 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)  		//--------------------------------------------------------------------  		// Propagate viewer object rotation to root of avatar  		//-------------------------------------------------------------------- -		if (!isAnyAnimationSignaled(AGENT_NO_ROTATE_ANIMS, NUM_AGENT_NO_ROTATE_ANIMS)) +        // AXON - also skip for control avatars +		if (!isControlAvatar() && !isAnyAnimationSignaled(AGENT_NO_ROTATE_ANIMS, NUM_AGENT_NO_ROTATE_ANIMS))  		{  			LLQuaternion iQ;  			LLVector3 upDir( 0.0f, 0.0f, 1.0f ); @@ -4041,7 +4103,7 @@ void LLVOAvatar::updateVisibility()  	if (mIsDummy)  	{ -		visible = TRUE; +		visible = FALSE;  	}  	else if (mDrawable.isNull())  	{ @@ -4190,6 +4252,11 @@ U32 LLVOAvatar::renderSkinned()  		return num_indices;  	} +    if (mDrawable.isNull()) +    { +		return num_indices; +    } +  	LLFace* face = mDrawable->getFace(0);  	bool needs_rebuild = !face || !face->getVertexBuffer() || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY); @@ -4352,11 +4419,12 @@ U32 LLVOAvatar::renderSkinned()  		}  		BOOL first_pass = TRUE; +        bool is_pure_dummy = mIsDummy && !isControlAvatar();  		if (!LLDrawPoolAvatar::sSkipOpaque)  		{  			if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender)  			{ -				if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy) +				if (isTextureVisible(TEX_HEAD_BAKED) || is_pure_dummy)  				{  					LLViewerJoint* head_mesh = getViewerJoint(MESH_ID_HEAD);  					if (head_mesh) @@ -4366,7 +4434,7 @@ U32 LLVOAvatar::renderSkinned()  					first_pass = FALSE;  				}  			} -			if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy) +			if (isTextureVisible(TEX_UPPER_BAKED) || is_pure_dummy)  			{  				LLViewerJoint* upper_mesh = getViewerJoint(MESH_ID_UPPER_BODY);  				if (upper_mesh) @@ -4376,7 +4444,7 @@ U32 LLVOAvatar::renderSkinned()  				first_pass = FALSE;  			} -			if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy) +			if (isTextureVisible(TEX_LOWER_BAKED) || is_pure_dummy)  			{  				LLViewerJoint* lower_mesh = getViewerJoint(MESH_ID_LOWER_BODY);  				if (lower_mesh) @@ -4433,18 +4501,15 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass)  			}  			first_pass = FALSE;  		} -		// Can't test for baked hair being defined, since that won't always be the case (not all viewers send baked hair) -		// TODO: 1.25 will be able to switch this logic back to calling isTextureVisible(); -		if ( (getImage(TEX_HAIR_BAKED, 0) && getImage(TEX_HAIR_BAKED, 0)->getID() != IMG_INVISIBLE) -			|| LLDrawPoolAlpha::sShowDebugAlpha)		 -		{ -			LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR); -			if (hair_mesh) -			{ -				num_indices += hair_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); -			} -			first_pass = FALSE; -		} +		if (isTextureVisible(TEX_HAIR_BAKED)) +        { +            LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR); +            if (hair_mesh) +            { +                num_indices += hair_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); +            } +            first_pass = FALSE; +        }  		if (LLPipeline::sImpostorRender)  		{  			gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); @@ -4484,7 +4549,9 @@ U32 LLVOAvatar::renderRigid()  		gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f);  	} -	if (isTextureVisible(TEX_EYES_BAKED)  || mIsDummy) +    bool is_pure_dummy = mIsDummy && !isControlAvatar(); + +	if (isTextureVisible(TEX_EYES_BAKED)  || is_pure_dummy)  	{  		LLViewerJoint* eyeball_left = getViewerJoint(MESH_ID_EYEBALL_LEFT);  		LLViewerJoint* eyeball_right = getViewerJoint(MESH_ID_EYEBALL_RIGHT); @@ -5034,7 +5101,10 @@ void LLVOAvatar::processAnimationStateChanges()  	else if (mInAir && !mIsSitting)  	{  		stopMotion(ANIM_AGENT_WALK_ADJUST); -		startMotion(ANIM_AGENT_FLY_ADJUST); +        if (mEnableDefaultMotions) +        { +            startMotion(ANIM_AGENT_FLY_ADJUST); +        }  	}  	else  	{ @@ -5044,13 +5114,19 @@ void LLVOAvatar::processAnimationStateChanges()  	if ( isAnyAnimationSignaled(AGENT_GUN_AIM_ANIMS, NUM_AGENT_GUN_AIM_ANIMS) )  	{ -		startMotion(ANIM_AGENT_TARGET); +        if (mEnableDefaultMotions) +        { +            startMotion(ANIM_AGENT_TARGET); +        }  		stopMotion(ANIM_AGENT_BODY_NOISE);  	}  	else  	{  		stopMotion(ANIM_AGENT_TARGET); -		startMotion(ANIM_AGENT_BODY_NOISE); +        if (mEnableDefaultMotions) +        { +            startMotion(ANIM_AGENT_BODY_NOISE); +        }  	}  	// clear all current animations @@ -5521,14 +5597,13 @@ void LLVOAvatar::rebuildAttachmentOverrides()  //-----------------------------------------------------------------------------  void LLVOAvatar::addAttachmentOverridesForObject(LLViewerObject *vo)  { -	LLVOAvatar *av = vo->getAvatarAncestor(); -	if (!av || (av != this)) -	{ +    if (vo->getAvatar() != this) +    {  		LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL;          return; -	} +    } -    LLScopedContextString str("addAttachmentOverridesForObject " + av->getFullname()); +    LLScopedContextString str("addAttachmentOverridesForObject " + vo->getAvatar()->getFullname());  	// Process all children  	LLViewerObject::const_child_list_t& children = vo->getChildren(); @@ -5554,7 +5629,7 @@ void LLVOAvatar::addAttachmentOverridesForObject(LLViewerObject *vo)  	LLUUID currentId = vobj->getVolume()->getParams().getSculptID();						  	const LLMeshSkinInfo*  pSkinData = gMeshRepo.getSkinInfo( currentId, vobj ); -	if ( vobj && vobj->isAttachment() && vobj->isMesh() && pSkinData ) +	if ( vobj && vobj->isMesh() && pSkinData )  	{  		const int bindCnt = pSkinData->mAlternateBindMatrix.size();								          const int jointCnt = pSkinData->mJointNames.size(); @@ -5736,14 +5811,15 @@ void LLVOAvatar::showAttachmentOverrides(bool verbose) const  }  //----------------------------------------------------------------------------- -// resetJointsOnDetach +// removeAttachmentOverridesForObject  //----------------------------------------------------------------------------- -void LLVOAvatar::resetJointsOnDetach(LLViewerObject *vo) +// AXON handle NPC case +void LLVOAvatar::removeAttachmentOverridesForObject(LLViewerObject *vo)  { -	LLVOAvatar *av = vo->getAvatarAncestor(); -	if (!av || (av != this)) +	if (vo->getAvatar() != this)  	{  		LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL; +        return;  	}  	// Process all children @@ -5752,21 +5828,22 @@ void LLVOAvatar::resetJointsOnDetach(LLViewerObject *vo)  		 it != children.end(); ++it)  	{  		LLViewerObject *childp = *it; -		resetJointsOnDetach(childp); +		removeAttachmentOverridesForObject(childp);  	}  	// Process self.  	LLUUID mesh_id;  	if (getRiggedMeshID(vo,mesh_id))  	{ -		resetJointsOnDetach(mesh_id); +		removeAttachmentOverridesForObject(mesh_id);  	}  }  //----------------------------------------------------------------------------- -// resetJointsOnDetach +// removeAttachmentOverridesForObject  //----------------------------------------------------------------------------- -void LLVOAvatar::resetJointsOnDetach(const LLUUID& mesh_id) +// AXON handle NPC case +void LLVOAvatar::removeAttachmentOverridesForObject(const LLUUID& mesh_id)  {	  	//Subsequent joints are relative to pelvis  	avatar_joint_list_t::iterator iter = mSkeleton.begin(); @@ -5844,6 +5921,7 @@ void LLVOAvatar::getGround(const LLVector3 &in_pos_agent, LLVector3 &out_pos_age  	LLVector3d z_vec(0.0f, 0.0f, 1.0f);  	LLVector3d p0_global, p1_global; +    // AXON update for control avs?  	if (mIsDummy)  	{  		outNorm.setVec(z_vec); @@ -5873,6 +5951,7 @@ F32 LLVOAvatar::getTimeDilation()  //-----------------------------------------------------------------------------  F32 LLVOAvatar::getPixelArea() const  { +    // AXON update for control avatars  	if (mIsDummy)  	{  		return 100000.f; @@ -6288,7 +6367,7 @@ void LLVOAvatar::removeChild(LLViewerObject *childp)  LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* viewer_object)  { -	S32 attachmentID = ATTACHMENT_ID_FROM_STATE(viewer_object->getState()); +	S32 attachmentID = ATTACHMENT_ID_FROM_STATE(viewer_object->getAttachmentState());  	// This should never happen unless the server didn't process the attachment point  	// correctly, but putting this check in here to be safe. @@ -6483,7 +6562,7 @@ void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO )  	LLUUID mesh_id;  	if (getRiggedMeshID(pVO, mesh_id))  	{ -		resetJointsOnDetach(mesh_id); +		removeAttachmentOverridesForObject(mesh_id);  		if ( gAgentCamera.cameraCustomizeAvatar() )  		{  			gAgent.unpauseAnimation(); @@ -6644,7 +6723,10 @@ void LLVOAvatar::getOffObject()  	mRoot->setRotation(cur_rotation_world);  	mRoot->getXform()->update(); -	startMotion(ANIM_AGENT_BODY_NOISE); +    if (mEnableDefaultMotions) +    { +        startMotion(ANIM_AGENT_BODY_NOISE); +    }  	if (isSelf())  	{ @@ -6804,6 +6886,7 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color)  BOOL LLVOAvatar::isVisible() const  { +    // AXON should we flag control avs as invisible?  	return mDrawable.notNull()  		&& (!mOrphaned || isSelf())  		&& (mDrawable->isVisible() || mIsDummy); @@ -6812,6 +6895,11 @@ BOOL LLVOAvatar::isVisible() const  // Determine if we have enough avatar data to render  bool LLVOAvatar::getIsCloud() const  { +	if (mIsDummy) +	{ +		return false; +	} +  	return (   ((const_cast<LLVOAvatar*>(this))->visualParamWeightsAreDefault())// Do we have a shape?  			|| (   !isTextureDefined(TEX_LOWER_BAKED)  				|| !isTextureDefined(TEX_UPPER_BAKED) @@ -8776,6 +8864,11 @@ void LLVOAvatar::updateFreezeCounter(S32 counter)  BOOL LLVOAvatar::updateLOD()  { +    if (mDrawable.isNull()) +    { +        return FALSE; +    } +      	if (isImpostor() && 0 != mDrawable->getNumFaces() && mDrawable->getFace(0)->hasGeometry())  	{  		return TRUE; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index bd89d4ef23..8b22024e0a 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -169,7 +169,8 @@ public:  												 LLVector2* tex_coord = NULL,      // return the texture coordinates of the intersection point  												 LLVector4a* normal = NULL,         // return the surface normal at the intersection point  												 LLVector4a* tangent = NULL);     // return the surface tangent at the intersection point -	LLViewerObject*	lineSegmentIntersectRiggedAttachments(const LLVector4a& start, const LLVector4a& end, +	virtual LLViewerObject*	lineSegmentIntersectRiggedAttachments( +                                                 const LLVector4a& start, const LLVector4a& end,  												 S32 face = -1,                    // which face to check, -1 = ALL_SIDES  												 BOOL pick_transparent = FALSE,  												 BOOL pick_rigged = FALSE, @@ -202,8 +203,8 @@ public:  	LLJoint*		        getJoint(S32 num);  	void 					addAttachmentOverridesForObject(LLViewerObject *vo); -	void					resetJointsOnDetach(const LLUUID& mesh_id); -	void					resetJointsOnDetach(LLViewerObject *vo); +	void					removeAttachmentOverridesForObject(const LLUUID& mesh_id); +	void					removeAttachmentOverridesForObject(LLViewerObject *vo);      bool					jointIsRiggedTo(const std::string& joint_name);      bool					jointIsRiggedTo(const std::string& joint_name, const LLViewerObject *vo);  	void					clearAttachmentOverrides(); @@ -233,6 +234,8 @@ public:  public:  	virtual bool 	isSelf() const { return false; } // True if this avatar is for this viewer's agent +	virtual bool 	isControlAvatar() const { return mIsControlAvatar; } // True if this avatar is a control av (no associated user) +  private: //aligned members  	LL_ALIGN_16(LLVector4a	mImpostorExtents[2]); @@ -240,7 +243,7 @@ private: //aligned members  	// Updates  	//--------------------------------------------------------------------  public: -	void			updateDebugText(); +	virtual void	updateDebugText();  	virtual BOOL 	updateCharacter(LLAgent &agent);  	void 			idleUpdateVoiceVisualizer(bool voice_enabled);  	void 			idleUpdateMisc(bool detailed_update); @@ -441,6 +444,13 @@ public:  	VisualMuteSettings		mVisuallyMuteSetting;			// Always or never visually mute this AV  	//-------------------------------------------------------------------- +	// animated object status +	//-------------------------------------------------------------------- +public: +    bool mIsControlAvatar; +    bool mEnableDefaultMotions; + +	//--------------------------------------------------------------------  	// Morph masks  	//--------------------------------------------------------------------  public: diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index d62862dfb8..658000987b 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -2791,7 +2791,7 @@ BOOL LLVOAvatarSelf::needsRenderBeam()  		// don't render selection beam on hud objects  		is_touching_or_grabbing = FALSE;  	} -	return is_touching_or_grabbing || (mState & AGENT_STATE_EDITING && LLSelectMgr::getInstance()->shouldShowSelection()); +	return is_touching_or_grabbing || (getAttachmentState() & AGENT_STATE_EDITING && LLSelectMgr::getInstance()->shouldShowSelection());  }  // static diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index de63a3963c..337f969f3d 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -92,7 +92,8 @@ LLVOGrass::~LLVOGrass()  void LLVOGrass::updateSpecies()  { -	mSpecies = mState; +	// AXON is grass still even supported? This use of state seems odd. +	mSpecies = getAttachmentState();  	if (!sSpeciesTable.count(mSpecies))  	{ diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 90ba814a15..403bff5a9e 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -76,8 +76,13 @@  #include "lldatapacker.h"  #include "llviewershadermgr.h"  #include "llvoavatar.h" +#include "llcontrolavatar.h" +#include "llvoavatarself.h"  #include "llvocache.h"  #include "llmaterialmgr.h" +#include "llanimationstates.h" +#include "llinventorytype.h" +#include "llviewerinventory.h"  const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;  const F32 FORCE_CULL_AREA = 8.f; @@ -86,6 +91,8 @@ U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG = 1;  BOOL gAnimateTextures = TRUE;  //extern BOOL gHideSelectedObjects; +// AXON TEMP +S32 LLVOVolume::sForceLOD = -1;  F32 LLVOVolume::sLODFactor = 1.f;  F32	LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop   F32 LLVOVolume::sDistanceFactor = 1.0f; @@ -1217,16 +1224,24 @@ void LLVOVolume::sculpt()  S32	LLVOVolume::computeLODDetail(F32 distance, F32 radius)  {  	S32	cur_detail; -	if (LLPipeline::sDynamicLOD) -	{ -		// We've got LOD in the profile, and in the twist.  Use radius. -		F32 tan_angle = (LLVOVolume::sLODFactor*radius)/distance; -		cur_detail = LLVolumeLODGroup::getDetailFromTan(ll_round(tan_angle, 0.01f)); -	} -	else -	{ -		cur_detail = llclamp((S32) (sqrtf(radius)*LLVOVolume::sLODFactor*4.f), 0, 3);		 -	} +    // AXON TEMP +    if (LLVOVolume::sForceLOD>=0 && LLVOVolume::sForceLOD<=3) +    { +        cur_detail = LLVOVolume::sForceLOD; +    } +    else +    { +        if (LLPipeline::sDynamicLOD) +        { +            // We've got LOD in the profile, and in the twist.  Use radius. +            F32 tan_angle = (LLVOVolume::sLODFactor*radius)/distance; +            cur_detail = LLVolumeLODGroup::getDetailFromTan(ll_round(tan_angle, 0.01f)); +        } +        else +        { +            cur_detail = llclamp((S32) (sqrtf(radius)*LLVOVolume::sLODFactor*4.f), 0, 3);		 +        } +    }  	return cur_detail;  } @@ -1280,15 +1295,38 @@ BOOL LLVOVolume::calcLOD()  	distance *= F_PI/3.f;  	cur_detail = computeLODDetail(ll_round(distance, 0.01f),  -									ll_round(radius, 0.01f)); +                                  ll_round(radius, 0.01f)); +    if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TRIANGLE_COUNT) && mDrawable->getFace(0)) +    { +        if (isRootEdit() && getChildren().size()>0) +        { +            S32 total_tris = getTriangleCount(); +            LLViewerObject::const_child_list_t& child_list = getChildren(); +            for (LLViewerObject::const_child_list_t::const_iterator iter = child_list.begin(); +                 iter != child_list.end(); ++iter) +            { +                LLViewerObject* childp = *iter; +                LLVOVolume *child_volp = dynamic_cast<LLVOVolume*>(childp); +                if (child_volp) +                { +                    total_tris += child_volp->getTriangleCount(); +                } +            } +            setDebugText(llformat("TRIS %d TOTAL %d", getTriangleCount(), total_tris)); +        } +        else +        { +            setDebugText(llformat("TRIS %d", getTriangleCount())); +        } +	 +    }  	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO) &&  		mDrawable->getFace(0))  	{ -		//setDebugText(llformat("%.2f:%.2f, %d", mDrawable->mDistanceWRTCamera, radius, cur_detail)); - -		setDebugText(llformat("%d", mDrawable->getFace(0)->getTextureIndex())); +        // This is a debug display for LODs. Please don't put the texture index here. +        setDebugText(llformat("%d", cur_detail));  	}  	if (cur_detail != mLOD) @@ -1386,7 +1424,8 @@ void LLVOVolume::updateFaceFlags()  BOOL LLVOVolume::setParent(LLViewerObject* parent)  {  	BOOL ret = FALSE ; -	if (parent != getParent()) +    LLViewerObject *old_parent = (LLViewerObject*) getParent(); +	if (parent != old_parent)  	{  		ret = LLViewerObject::setParent(parent);  		if (ret && mDrawable) @@ -1394,6 +1433,7 @@ BOOL LLVOVolume::setParent(LLViewerObject* parent)  			gPipeline.markMoved(mDrawable);  			gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);  		} +        updateAnimatedObjectState(old_parent, parent);  	}  	return ret ; @@ -3270,6 +3310,176 @@ BOOL LLVOVolume::setIsFlexible(BOOL is_flexible)  }  //---------------------------------------------------------------------------- +// AXON - methods related to extended mesh flags + +U32 LLVOVolume::getExtendedMeshFlags() const +{ +	const LLExtendedMeshParams *param_block =  +        (const LLExtendedMeshParams *)getParameterEntry(LLNetworkData::PARAMS_EXTENDED_MESH); +	if (param_block) +	{ +		return param_block->getFlags(); +	} +	else +	{ +		return 0; +	} +} + +void LLVOVolume::setExtendedMeshFlags(U32 flags) +{ +    U32 curr_flags = getExtendedMeshFlags(); +    if (curr_flags != flags) +    { +        bool in_use = (flags != 0); +        setParameterEntryInUse(LLNetworkData::PARAMS_EXTENDED_MESH, in_use, true); +        LLExtendedMeshParams *param_block =  +            (LLExtendedMeshParams *)getParameterEntry(LLNetworkData::PARAMS_EXTENDED_MESH); +        if (param_block) +        { +            param_block->setFlags(flags); +        } +        parameterChanged(LLNetworkData::PARAMS_EXTENDED_MESH, true); +    } +} + +bool LLVOVolume::canBeAnimatedObject() const +{ +    if (!isMesh()) +    { +        return false; +    } +// AXON remove this check if animated object attachments are allowed +#if 0 +    if (isAttachment()) +    { +        return false; +    } +#endif +	if (!getVolume()) +	{ +		return false; +	} +	const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(getVolume()->getParams().getSculptID(), this); +    if (!skin) +    { +        return false; +    } +    return true; +} + +bool LLVOVolume::isAnimatedObject() const +{ +    LLVOVolume *root_vol = (LLVOVolume*)getRootEdit(); +    bool can_be_animated = canBeAnimatedObject(); +    bool root_can_be_animated = root_vol->canBeAnimatedObject(); +    bool root_is_animated = root_vol->getExtendedMeshFlags() & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG; +    if (can_be_animated && root_can_be_animated && root_is_animated) +    { +        return true; +    } +    return false; +} + +// Make sure animated objects in a linkset are consistent. The rules are: +// Only the root of a linkset can have the animated object flag set +// Only the root of a linkset can have a control avatar (iff the animated object flag is set) +// Only skinned mesh volumes can have the animated object flag set, or a control avatar +bool LLVOVolume::isAnimatedObjectStateConsistent() const +{ +    if (!canBeAnimatedObject()) +    { +        if ((getExtendedMeshFlags() & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG) || +            mControlAvatar.notNull()) +        { +            LL_WARNS("AXON") << "Non animatable object has mesh enabled flag or mControlAvatar. Flags "  +                             << getExtendedMeshFlags() << " cav " << mControlAvatar.get() << LL_ENDL; +            return false; +        } +    } +    if (!isRootEdit()) +    { +        if ((getExtendedMeshFlags() & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG) || +            mControlAvatar.notNull()) +        { +            LL_WARNS("AXON") << "Non root object has mesh enabled flag or mControlAvatar. Flags "  +                             << getExtendedMeshFlags() << " cav " << mControlAvatar.get() << LL_ENDL; +            return false; +        } +    } +    // If we get here, we have a potentially animatable root volume. +    bool is_animation_enabled = getExtendedMeshFlags() & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG; +    bool has_control_avatar = (mControlAvatar.notNull()); +    if (is_animation_enabled != has_control_avatar) +    { +        LL_WARNS("AXON") << "Inconsistent state: animation enabled " << is_animation_enabled +                         << " has control avatar " << has_control_avatar  +                         << " flags " << getExtendedMeshFlags() << " cav " << mControlAvatar.get() << LL_ENDL; +        return false; +    } +    return true; +} + +// Called any time parenting changes for a volume. Update flags and +// control av accordingly.  This is called after parent has been +// changed to new_parent. +void LLVOVolume::updateAnimatedObjectState(LLViewerObject *old_parent, LLViewerObject *new_parent) +{ +    LLVOVolume *old_volp = dynamic_cast<LLVOVolume*>(old_parent); +    LLVOVolume *new_volp = dynamic_cast<LLVOVolume*>(new_parent); + +    // AXON - depending on whether animated objects can be attached, +    // we may want to include or remove the isAvatar() check. +    if (new_parent && !new_parent->isAvatar()) +    { +        // Object should inherit control avatar and animated mesh flag +        // from parent, so clear them out from our own state +        if (getExtendedMeshFlags() & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG) +        { +            setExtendedMeshFlags(getExtendedMeshFlags() & ~LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG); +        } +        if (mControlAvatar.notNull()) +        { +            LLControlAvatar *av = mControlAvatar; +            mControlAvatar = NULL; +            av->markForDeath(); +        } +        // If this succeeds now, it's because the new_parent is an animated object +        if (isAnimatedObject() && getControlAvatar()) +        { +            getControlAvatar()->addAttachmentOverridesForObject(this); +        } +    } +    if (old_volp && old_volp->isAnimatedObject()) +    { +        if (old_volp->getControlAvatar()) +        { +            // We have been removed from an animated object, need to do cleanup. +            old_volp->getControlAvatar()->removeAttachmentOverridesForObject(this); +        } +    } +     +    if (old_volp) +    { +        if (!old_volp->isAnimatedObjectStateConsistent()) +        { +            LL_WARNS("AXON") << "old_volp failed consistency check" << LL_ENDL; +        } +    } +    if (new_volp) +    { +        if (!new_volp->isAnimatedObjectStateConsistent()) +        { +            LL_WARNS("AXON") << "new_volp failed consistency check" << LL_ENDL; +        } +    } +    if (!isAnimatedObjectStateConsistent()) +    { +        LL_WARNS("AXON") << "child object failed consistency check" << LL_ENDL; +    } +} + +//----------------------------------------------------------------------------  void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point)  { @@ -3330,7 +3540,7 @@ void LLVOVolume::updateRadius()  BOOL LLVOVolume::isAttachment() const  { -	return mState != 0 ; +	return mAttachmentState != 0 ;  }  BOOL LLVOVolume::isHUDAttachment() const @@ -3338,7 +3548,7 @@ BOOL LLVOVolume::isHUDAttachment() const  	// *NOTE: we assume hud attachment points are in defined range  	// since this range is constant for backwards compatibility  	// reasons this is probably a reasonable assumption to make -	S32 attachment_id = ATTACHMENT_ID_FROM_STATE(mState); +	S32 attachment_id = ATTACHMENT_ID_FROM_STATE(mAttachmentState);  	return ( attachment_id >= 31 && attachment_id <= 38 );  } @@ -4092,9 +4302,9 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&  bool LLVOVolume::treatAsRigged()  {  	return isSelected() && -			isAttachment() && -			mDrawable.notNull() && -			mDrawable->isState(LLDrawable::RIGGED); +        (isAttachment() || isAnimatedObject()) && +        mDrawable.notNull() && +        mDrawable->isState(LLDrawable::RIGGED);  }  LLRiggedVolume* LLVOVolume::getRiggedVolume() @@ -4187,6 +4397,9 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons  	U32 maxJoints = LLSkinningUtil::getMeshJointCount(skin);      LLSkinningUtil::initSkinningMatrixPalette((LLMatrix4*)mat, maxJoints, skin, avatar); +    S32 rigged_vert_count = 0; +    S32 rigged_face_count = 0; +    LLVector4a box_min, box_max;  	for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)  	{  		const LLVolumeFace& vol_face = volume->getVolumeFace(i); @@ -4208,6 +4421,8 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons  				LL_RECORD_BLOCK_TIME(FTM_SKIN_RIGGED);                  U32 max_joints = LLSkinningUtil::getMaxJointCount(); +                rigged_vert_count += dst_face.mNumVertices; +                rigged_face_count++;  				for (U32 j = 0; j < dst_face.mNumVertices; ++j)  				{  					LLMatrix4a final_mat; @@ -4227,12 +4442,19 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons  				min = pos[0];  				max = pos[1]; +                if (i==0) +                { +                    box_min = min; +                    box_max = max; +                }  				for (U32 j = 1; j < dst_face.mNumVertices; ++j)  				{  					min.setMin(min, pos[j]);  					max.setMax(max, pos[j]);  				} +                box_min.setMin(min,box_min); +                box_max.setMax(max,box_max);  				dst_face.mCenter->setAdd(dst_face.mExtents[0], dst_face.mExtents[1]);  				dst_face.mCenter->mul(0.5f); @@ -4252,6 +4474,10 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons  			}  		}  	} +    mExtraDebugText = llformat("rigged %d/%d - box (%f %f %f) (%f %f %f)", +                               rigged_face_count, rigged_vert_count, +                               box_min[0], box_min[1], box_min[2], +                               box_max[0], box_max[1], box_max[2]);  }  U32 LLVOVolume::getPartitionType() const @@ -4772,11 +4998,35 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)                            vobj->isMesh() &&   						  gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID(), vobj); +            if (vobj->isAnimatedObject()) +            { +                if (!vobj->getControlAvatar()) +                { +                    vobj->linkControlAvatar(); +                } +                if (vobj->getControlAvatar()) +                { +                    pAvatarVO = vobj->getControlAvatar(); +                } +            } +            else +            { +                // Not animated but has a control avatar - probably +                // the checkbox has changed since the last rebuild. +                if (vobj->getControlAvatar()) +                { +                    vobj->unlinkControlAvatar(); +                } +            } +  			bool bake_sunlight = LLPipeline::sBakeSunlight && drawablep->isStatic(); +            // AXON why this variable? Only different from rigged if +            // there are no LLFaces associated with the drawable.  			bool is_rigged = false; -            if (rigged && pAvatarVO) +            // AXON handle NPC case +            if (rigged && pAvatarVO && !vobj->isAnimatedObject())              {                  pAvatarVO->addAttachmentOverridesForObject(vobj);  				if (!LLApp::isExiting() && pAvatarVO->isSelf() && debugLoggingEnabled("AvatarAttachments")) @@ -4802,7 +5052,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  				//sum up face verts and indices  				drawablep->updateFaceSize(i); -				if (rigged)  +				if (rigged || (vobj->getControlAvatar() && vobj->getControlAvatar()->mPlaying))  				{  					if (!facep->isState(LLFace::RIGGED))  					{ //completely reset vertex buffer diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index a331908320..c972d7770e 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -62,6 +62,8 @@ public:  	}  	void update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* src_volume); + +    std::string mExtraDebugText;  };  // Base class for implementations of the volume - Primitive, Flexible Object, etc. @@ -261,10 +263,24 @@ public:  	virtual BOOL isMesh() const;  	virtual BOOL hasLightTexture() const; +      	BOOL isVolumeGlobal() const;  	BOOL canBeFlexible() const;  	BOOL setIsFlexible(BOOL is_flexible); +    // Extended Mesh Properties +    U32 getExtendedMeshFlags() const; +    void setExtendedMeshFlags(U32 flags); +    bool canBeAnimatedObject() const; +    bool isAnimatedObject() const; +    bool isAnimatedObjectStateConsistent() const; +    void updateAnimatedObjectState(LLViewerObject *old_parent, LLViewerObject *new_parent); + +    // AXON For animated objects, we need to track animations requested +    // per-object, then reconcile those to manage the control avatar +    // animation state. +	std::map<LLUUID, S32> 					mObjectSignaledAnimations; // requested state of Animation name/value +      // Functions that deal with media, or media navigation      // Update this object's media data with the given media data array @@ -379,6 +395,7 @@ private:  public:  	static F32 sLODSlopDistanceFactor;// Changing this to zero, effectively disables the LOD transition slop  	static F32 sLODFactor;				// LOD scale factor +	static S32 sForceLOD;				// LOD override  	static F32 sDistanceFactor;			// LOD distance factor  	static LLPointer<LLObjectMediaDataClient> sObjectMediaClient; diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index bba36351d9..4cc4b821bf 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -513,11 +513,11 @@ public:  		RENDER_DEBUG_TEXTURE_AREA		= 0x00000100,  		RENDER_DEBUG_FACE_AREA			= 0x00000200,  		RENDER_DEBUG_PARTICLES			= 0x00000400, -		RENDER_DEBUG_GLOW				= 0x00000800, +		RENDER_DEBUG_GLOW				= 0x00000800, // not used  		RENDER_DEBUG_TEXTURE_ANIM		= 0x00001000,  		RENDER_DEBUG_LIGHTS				= 0x00002000,  		RENDER_DEBUG_BATCH_SIZE			= 0x00004000, -		RENDER_DEBUG_ALPHA_BINS			= 0x00008000, +		RENDER_DEBUG_ALPHA_BINS			= 0x00008000, // not used  		RENDER_DEBUG_RAYCAST            = 0x00010000,  		RENDER_DEBUG_AVATAR_DRAW_INFO	= 0x00020000,  		RENDER_DEBUG_SHADOW_FRUSTA		= 0x00040000, @@ -531,8 +531,9 @@ public:  		RENDER_DEBUG_NORMALS	        = 0x04000000,  		RENDER_DEBUG_LOD_INFO	        = 0x08000000,  		RENDER_DEBUG_RENDER_COMPLEXITY  = 0x10000000, -		RENDER_DEBUG_ATTACHMENT_BYTES	= 0x20000000, -		RENDER_DEBUG_TEXEL_DENSITY		= 0x40000000 +		RENDER_DEBUG_ATTACHMENT_BYTES	= 0x20000000, // not used +		RENDER_DEBUG_TEXEL_DENSITY		= 0x40000000, +		RENDER_DEBUG_TRIANGLE_COUNT		= 0x80000000   	};  public: diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index ed3cc26851..63e2ed4bb9 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -2,7 +2,7 @@  <floater   positioning="cascading"   legacy_header_height="18" - height="590" + height="600"   layout="topleft"   bg_opaque_image="Window_NoTitle_Foreground"   bg_alpha_image="Window_NoTitle_Background" @@ -2131,7 +2131,7 @@ even though the user gets a free copy.          <panel           border="false"           follows="all" -         height="367" +         height="387"           label="Features"           layout="topleft"           left_delta="0" @@ -2169,13 +2169,23 @@ even though the user gets a free copy.                  Edit object features:              </text>              <check_box -             height="19" +             height="15" +             label="Animated Mesh" +             layout="topleft" +             left="10" +             name="Animated Mesh Checkbox Ctrl" +             tool_tip="Allows rigged mesh objects to be animated independently" +             top_pad="10" +             width="121" /> +            <check_box +             height="10"               label="Flexible Path" +             follows="left|top"               layout="topleft"               left="10"               name="Flexible1D Checkbox Ctrl"               tool_tip="Allows object to flex about the Z axis (Client-side only)" -             top_pad="20" +             top_pad="15"               width="121" />              <spinner               follows="left|top" diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 697d27907d..f8b4948697 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2654,6 +2654,16 @@             parameter="lod info" />          </menu_item_check>          <menu_item_check +         label="Triangle Count" +         name="Triangle Count"> +          <menu_item_check.on_check +           function="Advanced.CheckInfoDisplay" +           parameter="triangle count" /> +          <menu_item_check.on_click +           function="Advanced.ToggleInfoDisplay" +           parameter="triangle count" /> +        </menu_item_check> +        <menu_item_check           label="Build Queue"           name="Build Queue">            <menu_item_check.on_check diff --git a/indra/test/test.cpp b/indra/test/test.cpp index 630af2b73b..e42374d56b 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -34,7 +34,6 @@   *   */ -  #include "linden_common.h"  #include "llerrorcontrol.h"  #include "lltut.h" @@ -685,5 +684,4 @@ int main(int argc, char **argv)  	return retval;  	//delete mycallback; -  } | 
