123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- /**
- * @file llhandmotion.cpp
- * @brief Implementation of LLHandMotion class.
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #include "linden_common.h"
- #include "llhandmotion.h"
- #include "llcharacter.h"
- // Constants
- const char* gHandPoseNames[LLHandMotion::NUM_HAND_POSES] =
- {
- "",
- "Hands_Relaxed",
- "Hands_Point",
- "Hands_Fist",
- "Hands_Relaxed_L",
- "Hands_Point_L",
- "Hands_Fist_L",
- "Hands_Relaxed_R",
- "Hands_Point_R",
- "Hands_Fist_R",
- "Hands_Salute_R",
- "Hands_Typing",
- "Hands_Peace_R",
- "Hands_Spread_R"
- };
- constexpr F32 HAND_MORPH_BLEND_TIME = 0.2f;
- LLHandMotion::LLHandMotion(const LLUUID& id)
- : LLMotion(id),
- mCharacter(NULL),
- mLastTime(0.f),
- mCurrentPose(HAND_POSE_RELAXED),
- mNewPose(HAND_POSE_RELAXED)
- {
- mName = "hand_motion";
- // RN: flag hand joint as highest priority for now, until we implement a
- // proper animation track
- mJointSignature[0][LL_HAND_JOINT_NUM] = 0xff;
- mJointSignature[1][LL_HAND_JOINT_NUM] = 0xff;
- mJointSignature[2][LL_HAND_JOINT_NUM] = 0xff;
- }
- //virtual
- bool LLHandMotion::onActivate()
- {
- LLPolyMesh* upperBodyMesh = mCharacter->getUpperBodyMesh();
- if (upperBodyMesh)
- {
- // Note: 0 is the default
- for (S32 i = 1; i < LLHandMotion::NUM_HAND_POSES; ++i)
- {
- mCharacter->setVisualParamWeight(gHandPoseNames[i], 0.f);
- }
- mCharacter->setVisualParamWeight(gHandPoseNames[mCurrentPose], 1.f);
- mCharacter->updateVisualParams();
- }
- return true;
- }
- //virtual
- bool LLHandMotion::onUpdate(F32 time, U8* joint_mask)
- {
- F32 time_delta = time - mLastTime;
- if (time_delta < 0.f)
- {
- time_delta = 0.f;
- llwarns_sparse << "Negative time passed; zeroed." << llendl;
- }
- mLastTime = time;
- eHandPose* req_hand_pose =
- (eHandPose*)mCharacter->getAnimationData("Hand Pose");
- // check to see if requested pose has changed
- if (!req_hand_pose)
- {
- if (mNewPose != HAND_POSE_RELAXED && mNewPose != mCurrentPose)
- {
- // Only set param weight for poses other than the default
- // (HAND_POSE_SPREAD); HAND_POSE_SPREAD is not an animatable
- // morph !
- if (mNewPose != HAND_POSE_SPREAD)
- {
- mCharacter->setVisualParamWeight(gHandPoseNames[mNewPose],
- 0.f);
- }
- // Reset morph weight for current pose back to its full extend or
- // it might be stuck somewhere in the middle if a pose is requested
- // and the old pose is requested again shortly after while still
- // blending to the other pose !
- if (mCurrentPose != HAND_POSE_SPREAD)
- {
- mCharacter->setVisualParamWeight(gHandPoseNames[mCurrentPose],
- 1.f);
- }
- // Update visual params now if we won't blend
- if (mCurrentPose == HAND_POSE_RELAXED)
- {
- mCharacter->updateVisualParams();
- }
- }
- mNewPose = HAND_POSE_RELAXED;
- }
- else
- {
- // Sometimes we seem to get garbage here, with poses that are out of
- // bounds. So check for a valid pose first.
- if (*req_hand_pose >= 0 && *req_hand_pose < NUM_HAND_POSES)
- {
- // This is a new morph we didn't know about before: reset morph
- // weight for both current and new pose back their starting values
- // while still blending.
- if (*req_hand_pose != mNewPose && mNewPose != mCurrentPose)
- {
- if (mNewPose != HAND_POSE_SPREAD)
- {
- mCharacter->setVisualParamWeight(gHandPoseNames[mNewPose],
- 0.f);
- }
- // Reset morph weight for current pose back to its full extend
- // or it might be stuck somewhere in the middle if a pose is
- // requested and the old pose is requested again shortly after
- // while still blending to the other pose !
- if (mCurrentPose != HAND_POSE_SPREAD)
- {
- mCharacter->setVisualParamWeight(gHandPoseNames[mCurrentPose],
- 1.f);
- }
- // Update visual params now if we won't blend
- if (mCurrentPose == *req_hand_pose)
- {
- mCharacter->updateVisualParams();
- }
- }
- mNewPose = *req_hand_pose;
- }
- else
- {
- llwarns << "Invalid requested hand pose index; ignoring new hand pose."
- << llendl;
- mNewPose = mCurrentPose;
- }
- }
- mCharacter->removeAnimationData("Hand Pose");
- mCharacter->removeAnimationData("Hand Pose Priority");
- // If we are still blending...
- if (mCurrentPose != mNewPose)
- {
- LL_DEBUGS("Animation") << "New Hand Pose: " << gHandPoseNames[mNewPose]
- << LL_ENDL;
- F32 incoming_wght = 1.f;
- F32 outgoing_wght = 0.f;
- if (mNewPose != HAND_POSE_SPREAD)
- {
- incoming_wght =
- mCharacter->getVisualParamWeight(gHandPoseNames[mNewPose]);
- incoming_wght += (time_delta / HAND_MORPH_BLEND_TIME);
- incoming_wght = llclamp(incoming_wght, 0.f, 1.f);
- mCharacter->setVisualParamWeight(gHandPoseNames[mNewPose],
- incoming_wght);
- }
- if (mCurrentPose != HAND_POSE_SPREAD)
- {
- outgoing_wght =
- mCharacter->getVisualParamWeight(gHandPoseNames[mCurrentPose]);
- outgoing_wght -= (time_delta / HAND_MORPH_BLEND_TIME);
- outgoing_wght = llclamp(outgoing_wght, 0.f, 1.f);
- mCharacter->setVisualParamWeight(gHandPoseNames[mCurrentPose],
- outgoing_wght);
- }
- mCharacter->updateVisualParams();
- if (incoming_wght == 1.f && outgoing_wght == 0.f)
- {
- mCurrentPose = mNewPose;
- }
- }
- return true;
- }
- std::string LLHandMotion::getHandPoseName(eHandPose pose)
- {
- if ((S32)pose < LLHandMotion::NUM_HAND_POSES && (S32)pose >= 0)
- {
- return std::string(gHandPoseNames[pose]);
- }
- return LLStringUtil::null;
- }
- LLHandMotion::eHandPose LLHandMotion::getHandPose(const std::string& posename)
- {
- for (S32 pose = 0; pose < LLHandMotion::NUM_HAND_POSES; ++pose)
- {
- if (gHandPoseNames[pose] == posename)
- {
- return (eHandPose)pose;
- }
- }
- return (eHandPose)0;
- }
|