diff options
29 files changed, 722 insertions, 63 deletions
diff --git a/etc/message.xml b/etc/message.xml index 6d8160abb5..b444fe6c11 100755 --- a/etc/message.xml +++ b/etc/message.xml @@ -236,6 +236,14 @@ <boolean>false</boolean> </map> + <key>ObjectAnimation</key> + <map> + <key>flavor</key> + <string>template</string> + <key>trusted-sender</key> + <boolean>false</boolean> + </map> + <key>AvatarAppearance</key> <map> <key>flavor</key> 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/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/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp new file mode 100644 index 0000000000..61055f6f58 --- /dev/null +++ b/indra/newview/llcontrolavatar.cpp @@ -0,0 +1,166 @@ +/** + * @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" + +LLControlAvatar::LLControlAvatar(const LLUUID& id, const LLPCode pcode, LLViewerRegion* regionp) : + LLVOAvatar(id, pcode, regionp), + mPlaying(false), + mGlobalScale(1.0f) +{ + mIsControlAvatar = true; + mEnableDefaultMotions = false; +} + +// virtual +LLControlAvatar::~LLControlAvatar() +{ +} + +void LLControlAvatar::matchVolumeTransform() +{ + setPositionAgent(mVolp->getRenderPosition()); + //slamPosition(); + + LLQuaternion fix_axes_rot(-F_PI_BY_TWO, LLVector3(0,0,1)); + LLQuaternion obj_rot = mVolp->getRotation(); + LLQuaternion result_rot = fix_axes_rot * obj_rot; + setRotation(result_rot); + mRoot->setWorldRotation(result_rot); + mRoot->setPosition(mVolp->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 (!mVolp->mDrawable) + return; + if (mVolp->mDrawable->isActive()) + { + mVolp->mDrawable->makeStatic(FALSE); + } + mVolp->mDrawable->makeActive(); + gPipeline.markMoved(mVolp->mDrawable); + gPipeline.markTextured(mVolp->mDrawable); // face may need to change draw pool to/from POOL_HUD + mVolp->mDrawable->setState(LLDrawable::USE_BACKLIGHT); + + LLViewerObject::const_child_list_t& child_list = mVolp->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(mVolp->mDrawable, LLDrawable::REBUILD_ALL, TRUE); + mVolp->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->mVolp = obj; + + cav->createDrawable(&gPipeline); + cav->mIsDummy = TRUE; + cav->mSpecialRenderMode = 1; + cav->updateJointLODs(); + cav->updateGeometry(cav->mDrawable); + //cav->startMotion(ANIM_AGENT_STAND, 5.0f); + cav->hideSkirt(); + + // Sync up position/rotation with object + cav->matchVolumeTransform(); + + return cav; +} + diff --git a/indra/newview/llcontrolavatar.h b/indra/newview/llcontrolavatar.h new file mode 100644 index 0000000000..f29388e035 --- /dev/null +++ b/indra/newview/llcontrolavatar.h @@ -0,0 +1,56 @@ +/** + * @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); + + bool mPlaying; + + F32 mGlobalScale; + + LLVOVolume *mVolp; +}; + +#endif //LL_CONTROLAVATAR_H 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..f34194db19 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); @@ -347,7 +348,16 @@ void LLPanelVolume::getState( ) getChildView("Light Focus")->setEnabled(false); getChildView("Light Ambiance")->setEnabled(false); } - + + // Animated Mesh + BOOL is_animated_mesh = volobjp && volobjp->getExtendedMeshFlags() & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG; + 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 can_be_animated_object = volobjp && volobjp->canBeAnimatedObject() && editable; + getChildView("Animated Mesh Checkbox Ctrl")->setEnabled(can_be_animated_object); + // Flexible properties BOOL is_flexible = volobjp && volobjp->isFlexible(); getChild<LLUICtrl>("Flexible1D Checkbox Ctrl")->setValue(is_flexible); @@ -587,6 +597,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 +910,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/llstartup.cpp b/indra/newview/llstartup.cpp index 33b6352bf5..0c2fcdaf10 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2384,6 +2384,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/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index c68f6b8a15..eddbe16482 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -6907,7 +6907,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 507087d1ae..ff33fe79fa 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" @@ -4976,12 +4978,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) { @@ -4993,6 +4998,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()) @@ -5063,6 +5069,68 @@ 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->mControlAvatar; + if (!avatarp) + { + LL_WARNS() << "AXON no control avatar, ignoring" << LL_ENDL; + return; + } + + S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_AnimationList); + LL_WARNS() << "AXON handle object animation here, num_blocks " << num_blocks << LL_ENDL; + + if (!avatarp->mPlaying) + { + avatarp->mPlaying = true; + avatarp->updateVolumeGeom(); + } + avatarp->mSignaledAnimations.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); + avatarp->mSignaledAnimations[animation_id] = anim_sequence_id; + LL_INFOS() << "AXON got object animation request for object " + << uuid << " animation id " << animation_id << LL_ENDL; + } + + if (num_blocks >= 0) + { + LL_INFOS() << "AXON process animation state changes here" << LL_ENDL; + avatarp->processAnimationStateChanges(); + } +} + + 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..f1c7cfae0d 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), @@ -369,11 +377,18 @@ void LLViewerObject::markDead() ((LLViewerObject *)getParent())->removeChild(this); } LLUUID mesh_id; + // FIXME AXON - need to do this for control avatars too if (av && LLVOAvatar::getRiggedMeshID(this,mesh_id)) { // This case is needed for indirectly attached mesh objects. av->resetJointsOnDetach(mesh_id); } + if (mControlAvatar) + { + LLControlAvatar *av = mControlAvatar; + mControlAvatar = NULL; + av->markDead(); + } // Mark itself as dead mDead = TRUE; @@ -1378,7 +1393,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 +1663,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, U8 state; mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num ); - mState = state; + mAttachmentState = state; break; } @@ -1671,7 +1686,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, U8 state; dp->unpackU8(state, "State"); - mState = state; + mAttachmentState = state; switch(update_type) { @@ -3857,7 +3872,7 @@ const LLVector3 LLViewerObject::getRenderPosition() const if (mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED)) { LLVOAvatar* avatar = getAvatar(); - if (avatar) + if (avatar && !mControlAvatar) { return avatar->getPositionAgent(); } @@ -3993,6 +4008,10 @@ void LLViewerObject::setPosition(const LLVector3 &pos, BOOL damped) // position caches need to be up to date on root objects updatePositionCaches(); } + if (mControlAvatar) + { + mControlAvatar->matchVolumeTransform(); + } } void LLViewerObject::setPositionGlobal(const LLVector3d &pos_global, BOOL damped) @@ -5458,6 +5477,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 +6377,10 @@ const std::string& LLViewerObject::getAttachmentItemName() const //virtual LLVOAvatar* LLViewerObject::getAvatar() const { + if (mControlAvatar) + { + return mControlAvatar; + } if (isAttachment()) { LLViewerObject* vobj = (LLViewerObject*) getParent(); diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 24fcf0517e..e727567957 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,8 @@ public: static BOOL sUseSharedDrawables; + 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 +696,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 +787,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/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 80c6805ead..beb6f08899 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; @@ -1796,7 +1799,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 +1949,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; @@ -2738,7 +2747,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()); } @@ -3406,6 +3416,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 +3426,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->mVolp; + 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 +3456,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); } @@ -3530,7 +3560,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 +3684,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 +4074,7 @@ void LLVOAvatar::updateVisibility() if (mIsDummy) { - visible = TRUE; + visible = FALSE; } else if (mDrawable.isNull()) { @@ -4352,11 +4385,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 +4400,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 +4410,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 +4467,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 +4515,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 +5067,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 +5080,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,12 +5563,26 @@ void LLVOAvatar::rebuildAttachmentOverrides() //----------------------------------------------------------------------------- void LLVOAvatar::addAttachmentOverridesForObject(LLViewerObject *vo) { - LLVOAvatar *av = vo->getAvatarAncestor(); + bool non_attached_case = false; + // FIXME AXON - will this work if vo has child objects? + if (vo->mControlAvatar) + { + non_attached_case = true; + } + LLVOAvatar *av; + if (non_attached_case) + { + av = vo->mControlAvatar; + } + else + { + av = vo->getAvatarAncestor(); if (!av || (av != this)) { LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL; return; } + } LLScopedContextString str("addAttachmentOverridesForObject " + av->getFullname()); @@ -5554,7 +5610,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->isAttachment()||non_attached_case) && vobj->isMesh() && pSkinData ) { const int bindCnt = pSkinData->mAlternateBindMatrix.size(); const int jointCnt = pSkinData->mJointNames.size(); @@ -5738,6 +5794,7 @@ void LLVOAvatar::showAttachmentOverrides(bool verbose) const //----------------------------------------------------------------------------- // resetJointsOnDetach //----------------------------------------------------------------------------- +// AXON handle NPC case void LLVOAvatar::resetJointsOnDetach(LLViewerObject *vo) { LLVOAvatar *av = vo->getAvatarAncestor(); @@ -5766,6 +5823,7 @@ void LLVOAvatar::resetJointsOnDetach(LLViewerObject *vo) //----------------------------------------------------------------------------- // resetJointsOnDetach //----------------------------------------------------------------------------- +// AXON handle NPC case void LLVOAvatar::resetJointsOnDetach(const LLUUID& mesh_id) { //Subsequent joints are relative to pelvis @@ -5844,6 +5902,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 +5932,7 @@ F32 LLVOAvatar::getTimeDilation() //----------------------------------------------------------------------------- F32 LLVOAvatar::getPixelArea() const { + // AXON update for control avatars if (mIsDummy) { return 100000.f; @@ -6288,7 +6348,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. @@ -6644,7 +6704,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 +6867,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 +6876,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) diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index bd89d4ef23..2b71cfbe61 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -233,6 +233,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 +242,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 +443,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 aa5d82a096..2137bf4eb3 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -2789,7 +2789,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..150769845b 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; @@ -3270,6 +3275,59 @@ 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; + } + const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(getVolume()->getParams().getSculptID(), this); + if (!skin) + { + return false; + } + return true; +} + +bool LLVOVolume::isAnimatedObject() const +{ + return canBeAnimatedObject() && (getExtendedMeshFlags() & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG); +} + +//---------------------------------------------------------------------------- void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point) { @@ -3330,7 +3388,7 @@ void LLVOVolume::updateRadius() BOOL LLVOVolume::isAttachment() const { - return mState != 0 ; + return mAttachmentState != 0 ; } BOOL LLVOVolume::isHUDAttachment() const @@ -3338,7 +3396,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 ); } @@ -4772,10 +4830,30 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) vobj->isMesh() && gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID(), vobj); + bool rigged_non_attachment = !vobj->isAttachment() && + vobj->isMesh() && + gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID(), vobj); + + if (rigged_non_attachment) + { + if (!vobj->mControlAvatar) + { + vobj->mControlAvatar = LLControlAvatar::createControlAvatar(vobj); + vobj->mControlAvatar->addAttachmentOverridesForObject(vobj); + } + if (vobj->mControlAvatar) + { + pAvatarVO = vobj->mControlAvatar; + } + } + 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; + // AXON handle NPC case if (rigged && pAvatarVO) { pAvatarVO->addAttachmentOverridesForObject(vobj); @@ -4802,7 +4880,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) //sum up face verts and indices drawablep->updateFaceSize(i); - if (rigged) + if (rigged || (vobj->mControlAvatar && vobj->mControlAvatar->mPlaying)) { if (!facep->isState(LLFace::RIGGED)) { //completely reset vertex buffer diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index a331908320..75dabd961a 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -261,10 +261,17 @@ 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; + // Functions that deal with media, or media navigation // Update this object's media data with the given media data array 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/scripts/messages/message_template.msg b/scripts/messages/message_template.msg index c56eaae6fe..18264ee59c 100755 --- a/scripts/messages/message_template.msg +++ b/scripts/messages/message_template.msg @@ -8,7 +8,7 @@ version 2.0 // for each type is listed below: // Low: 423 // Medium: 18 -// High: 29 +// High: 30 // PLEASE UPDATE THIS WHEN YOU ADD A NEW MESSAGE! @@ -3571,7 +3571,6 @@ version 2.0 } } - // AvatarAppearance - Update visual params { AvatarAppearance Low 158 Trusted Zerocoded @@ -7286,6 +7285,29 @@ version 2.0 // ************************************************************************* +// Object animation messages +// ************************************************************************* + +// Note this is basically identical to AvatarAnimation. +// Needs to be a different message because existing viewers +// have insufficiently smart handler functions. + +// ObjectAnimation - Update animation state +// simulator --> viewer +{ + ObjectAnimation High 30 Trusted Unencoded + { + Sender Single + { ID LLUUID } + } + { + AnimationList Variable + { AnimID LLUUID } + { AnimSequenceID S32 } + } +} + +// ************************************************************************* // Asset storage messages // ************************************************************************* diff --git a/scripts/messages/message_template.msg.sha1 b/scripts/messages/message_template.msg.sha1 index 5bc06ec042..db87ad5e77 100755 --- a/scripts/messages/message_template.msg.sha1 +++ b/scripts/messages/message_template.msg.sha1 @@ -1 +1 @@ -337f351910b0c8821cb3d447bc6578516a043c80
\ No newline at end of file +55df2c7135733c5da64ef8f01859b83a433a3a09
\ No newline at end of file |