summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xetc/message.xml8
-rw-r--r--indra/llcharacter/lljoint.cpp2
-rw-r--r--indra/llmessage/message_prehash.cpp1
-rw-r--r--indra/llmessage/message_prehash.h1
-rw-r--r--indra/llprimitive/llprimitive.cpp66
-rw-r--r--indra/llprimitive/llprimitive.h22
-rw-r--r--indra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/llcontrolavatar.cpp166
-rw-r--r--indra/newview/llcontrolavatar.h56
-rw-r--r--indra/newview/lldrawpoolavatar.cpp1
-rw-r--r--indra/newview/llpanelvolume.cpp38
-rw-r--r--indra/newview/llpanelvolume.h1
-rw-r--r--indra/newview/llstartup.cpp1
-rw-r--r--indra/newview/llviewermenu.cpp2
-rw-r--r--indra/newview/llviewermessage.cpp74
-rw-r--r--indra/newview/llviewermessage.h1
-rw-r--r--indra/newview/llviewerobject.cpp40
-rw-r--r--indra/newview/llviewerobject.h11
-rw-r--r--indra/newview/llviewerobjectlist.cpp4
-rw-r--r--indra/newview/llviewerobjectlist.h2
-rw-r--r--indra/newview/llvoavatar.cpp133
-rw-r--r--indra/newview/llvoavatar.h11
-rw-r--r--indra/newview/llvoavatarself.cpp2
-rw-r--r--indra/newview/llvograss.cpp3
-rw-r--r--indra/newview/llvovolume.cpp84
-rw-r--r--indra/newview/llvovolume.h7
-rw-r--r--indra/newview/skins/default/xui/en/floater_tools.xml18
-rwxr-xr-xscripts/messages/message_template.msg26
-rwxr-xr-xscripts/messages/message_template.msg.sha12
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