From 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 Mon Sep 17 00:00:00 2001 From: Jacek Antonelli Date: Fri, 15 Aug 2008 23:44:46 -0500 Subject: Second Life viewer sources 1.13.2.12 --- linden/indra/newview/llfloateranimpreview.cpp | 1158 +++++++++++++++++++++++++ 1 file changed, 1158 insertions(+) create mode 100644 linden/indra/newview/llfloateranimpreview.cpp (limited to 'linden/indra/newview/llfloateranimpreview.cpp') diff --git a/linden/indra/newview/llfloateranimpreview.cpp b/linden/indra/newview/llfloateranimpreview.cpp new file mode 100644 index 0000000..ced7a0e --- /dev/null +++ b/linden/indra/newview/llfloateranimpreview.cpp @@ -0,0 +1,1158 @@ +/** + * @file llfloateranimpreview.cpp + * @brief LLFloaterAnimPreview class implementation + * + * Copyright (c) 2004-2007, Linden Research, Inc. + * + * 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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. + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloateranimpreview.h" + +#include "llbvhloader.h" +#include "lldatapacker.h" +#include "lldir.h" +#include "llvfile.h" +#include "llapr.h" + +#include "llagent.h" +#include "llbbox.h" +#include "llbutton.h" +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "lldrawable.h" +#include "lldrawpoolavatar.h" +#include "llface.h" +#include "llkeyframemotion.h" +#include "lllineeditor.h" +#include "llsliderctrl.h" +#include "llspinctrl.h" +#include "lltextbox.h" +#include "lltoolmgr.h" +#include "llui.h" +#include "llviewercamera.h" +#include "llviewerobjectlist.h" +#include "llviewerwindow.h" +#include "llviewermenu.h" +#include "llvoavatar.h" +#include "pipeline.h" +#include "viewer.h" +#include "llvieweruictrlfactory.h" + +S32 LLFloaterAnimPreview::sUploadAmount = 10; + +const S32 PREVIEW_BORDER_WIDTH = 2; +const S32 PREVIEW_RESIZE_HANDLE_SIZE = S32(RESIZE_HANDLE_WIDTH * OO_SQRT2) + PREVIEW_BORDER_WIDTH; +const S32 PREVIEW_HPAD = PREVIEW_RESIZE_HANDLE_SIZE; +const S32 PREF_BUTTON_HEIGHT = 16; +const S32 PREVIEW_TEXTURE_HEIGHT = 300; + +const F32 PREVIEW_CAMERA_DISTANCE = 4.f; + +const F32 MIN_CAMERA_ZOOM = 0.5f; +const F32 MAX_CAMERA_ZOOM = 10.f; + +//----------------------------------------------------------------------------- +// LLFloaterAnimPreview() +//----------------------------------------------------------------------------- +LLFloaterAnimPreview::LLFloaterAnimPreview(const char* filename) : + LLFloaterNameDesc(filename) +{ + mLastSliderValue = 0.f; + mLastMouseX = 0; + mLastMouseY = 0; + + mIDList["Standing"] = ANIM_AGENT_STAND; + mIDList["Walking"] = ANIM_AGENT_FEMALE_WALK; + mIDList["Sitting"] = ANIM_AGENT_SIT_FEMALE; + mIDList["Flying"] = ANIM_AGENT_HOVER; + + mIDList["[None]"] = LLUUID::null; + mIDList["Aaaaah"] = ANIM_AGENT_EXPRESS_OPEN_MOUTH; + mIDList["Afraid"] = ANIM_AGENT_EXPRESS_AFRAID; + mIDList["Angry"] = ANIM_AGENT_EXPRESS_ANGER; + mIDList["Big Smile"] = ANIM_AGENT_EXPRESS_TOOTHSMILE; + mIDList["Bored"] = ANIM_AGENT_EXPRESS_BORED; + mIDList["Cry"] = ANIM_AGENT_EXPRESS_CRY; + mIDList["Disdain"] = ANIM_AGENT_EXPRESS_DISDAIN; + mIDList["Embarrassed"] = ANIM_AGENT_EXPRESS_EMBARRASSED; + mIDList["Frown"] = ANIM_AGENT_EXPRESS_FROWN; + mIDList["Kiss"] = ANIM_AGENT_EXPRESS_KISS; + mIDList["Laugh"] = ANIM_AGENT_EXPRESS_LAUGH; + mIDList["Plllppt"] = ANIM_AGENT_EXPRESS_TONGUE_OUT; + mIDList["Repulsed"] = ANIM_AGENT_EXPRESS_REPULSED; + mIDList["Sad"] = ANIM_AGENT_EXPRESS_SAD; + mIDList["Shrug"] = ANIM_AGENT_EXPRESS_SHRUG; + mIDList["Smile"] = ANIM_AGENT_EXPRESS_SMILE; + mIDList["Surprise"] = ANIM_AGENT_EXPRESS_SURPRISE; + mIDList["Wink"] = ANIM_AGENT_EXPRESS_WINK; + mIDList["Worry"] = ANIM_AGENT_EXPRESS_WORRY; +} + +//----------------------------------------------------------------------------- +// postBuild() +//----------------------------------------------------------------------------- +BOOL LLFloaterAnimPreview::postBuild() +{ + LLRect r; + LLKeyframeMotion* motionp = NULL; + LLBVHLoader* loaderp = NULL; + + if (!LLFloaterNameDesc::postBuild()) + { + return FALSE; + } + + childSetCommitCallback("name_form", onCommitName, this); + + childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d",sUploadAmount)); + childSetAction("ok_btn", onBtnOK, this); + setDefaultBtn(); + + mPreviewRect.set(PREVIEW_HPAD, + PREVIEW_TEXTURE_HEIGHT, + getRect().getWidth() - PREVIEW_HPAD, + PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); + mPreviewImageRect.set(0.f, 1.f, 1.f, 0.f); + + S32 y = mPreviewRect.mTop + BTN_HEIGHT; + S32 btn_left = PREVIEW_HPAD; + + r.set( btn_left, y, btn_left + 32, y - BTN_HEIGHT ); + mPlayButton = LLViewerUICtrlFactory::getButtonByName(this, "play_btn"); + if (!mPlayButton) + { + mPlayButton = new LLButton("play_btn", LLRect(0,0,0,0)); + } + mPlayButton->setClickedCallback(onBtnPlay); + mPlayButton->setCallbackUserData(this); + + mPlayButton->setImages("button_anim_play.tga", + "button_anim_play_selected.tga"); + mPlayButton->setDisabledImages("",""); + + mPlayButton->setScaleImage(TRUE); + mPlayButton->setFixedBorder(0, 0); + + mStopButton = LLViewerUICtrlFactory::getButtonByName(this, "stop_btn"); + if (!mStopButton) + { + mStopButton = new LLButton("stop_btn", LLRect(0,0,0,0)); + } + mStopButton->setClickedCallback(onBtnStop); + mStopButton->setCallbackUserData(this); + + mStopButton->setImages("button_anim_stop.tga", + "button_anim_stop_selected.tga"); + mStopButton->setDisabledImages("",""); + + mStopButton->setScaleImage(TRUE); + mStopButton->setFixedBorder(0, 0); + + r.set(r.mRight + PREVIEW_HPAD, y, getRect().getWidth() - PREVIEW_HPAD, y - BTN_HEIGHT); + childSetCommitCallback("playback_slider", onSliderMove, this); + + childHide("bad_animation_text"); + + childSetCommitCallback("preview_base_anim", onCommitBaseAnim, this); + childSetValue("preview_base_anim", "Standing"); + + childSetCommitCallback("priority", onCommitPriority, this); + childSetCommitCallback("loop_check", onCommitLoop, this); + childSetCommitCallback("loop_in_point", onCommitLoopIn, this); + childSetValidate("loop_in_point", validateLoopIn); + childSetCommitCallback("loop_out_point", onCommitLoopOut, this); + childSetValidate("loop_out_point", validateLoopOut); + + childSetCommitCallback("hand_pose_combo", onCommitHandPose, this); + + childSetCommitCallback("emote_combo", onCommitEmote, this); + childSetValue("emote_combo", "[None]"); + + childSetCommitCallback("ease_in_time", onCommitEaseIn, this); + childSetValidate("ease_in_time", validateEaseIn); + childSetCommitCallback("ease_out_time", onCommitEaseOut, this); + childSetValidate("ease_out_time", validateEaseOut); + + if (!stricmp(strrchr(mFilename.c_str(), '.'), ".bvh")) + { + // loading a bvh file + + // now load bvh file + S32 file_size; + apr_file_t* fp = ll_apr_file_open(mFilenameAndPath, LL_APR_RB, &file_size); + + if (!fp) + { + llwarns << "Can't open BVH file:" << mFilename << llendl; + } + else + { + char* file_buffer; + + file_buffer = new char[file_size + 1]; + + if (file_size == ll_apr_file_read(fp, file_buffer, file_size)) + { + file_buffer[file_size] = '\0'; + llinfos << "Loading BVH file " << mFilename << llendl; + loaderp = new LLBVHLoader(file_buffer); + } + + apr_file_close(fp); + delete file_buffer; + } + } + + if (loaderp && loaderp->isInitialized() && loaderp->getDuration() <= MAX_ANIM_DURATION) + { + // generate unique id for this motion + mTransactionID.generate(); + mMotionID = mTransactionID.makeAssetID(gAgent.getSecureSessionID()); + + mAnimPreview = new LLPreviewAnimation(256, 256); + + // motion will be returned, but it will be in a load-pending state, as this is a new motion + // this motion will not request an asset transfer until next update, so we have a chance to + // load the keyframe data locally + motionp = (LLKeyframeMotion*)mAnimPreview->getDummyAvatar()->createMotion(mMotionID); + + // create data buffer for keyframe initialization + S32 buffer_size = loaderp->getOutputSize(); + U8* buffer = new U8[buffer_size]; + + LLDataPackerBinaryBuffer dp(buffer, buffer_size); + + // pass animation data through memory buffer + loaderp->serialize(dp); + dp.reset(); + BOOL success = motionp->deserialize(dp); + + delete []buffer; + + if (motionp && success) + { + const LLBBoxLocal &pelvis_bbox = motionp->getPelvisBBox(); + + LLVector3 temp = pelvis_bbox.getCenter(); + // only consider XY? + //temp.mV[VZ] = 0.f; + F32 pelvis_offset = temp.magVec(); + + temp = pelvis_bbox.getExtent(); + //temp.mV[VZ] = 0.f; + F32 pelvis_max_displacement = pelvis_offset + (temp.magVec() * 0.5f) + 1.f; + + F32 camera_zoom = gCamera->getDefaultFOV() / (2.f * atan(pelvis_max_displacement / PREVIEW_CAMERA_DISTANCE)); + + mAnimPreview->setZoom(camera_zoom); + + motionp->setName(childGetValue("name_form").asString()); + mAnimPreview->getDummyAvatar()->startMotion(mMotionID); + childSetMinValue("playback_slider", 0.0); + childSetMaxValue("playback_slider", 1.0); + + childSetValue("loop_check", LLSD(motionp->getLoop())); + childSetValue("loop_in_point", LLSD(motionp->getLoopIn() / motionp->getDuration() * 100.f)); + childSetValue("loop_out_point", LLSD(motionp->getLoopOut() / motionp->getDuration() * 100.f)); + childSetValue("priority", LLSD((F32)motionp->getPriority())); + childSetValue("hand_pose_combo", LLHandMotion::getHandPoseName(motionp->getHandPose())); + childSetValue("ease_in_time", LLSD(motionp->getEaseInDuration())); + childSetValue("ease_out_time", LLSD(motionp->getEaseOutDuration())); + mEnabled = TRUE; + char seconds_string[128]; + sprintf(seconds_string, " - %.2f seconds", motionp->getDuration()); + + setTitle(mFilename + LLString(seconds_string)); + } + else + { + delete mAnimPreview; + mAnimPreview = NULL; + mMotionID.setNull(); + // XUI:translate + childSetValue("bad_animation_text", LLSD("Failed to initialize motion.")); + mEnabled = FALSE; + } + } + else + { + if ( loaderp ) + { + if (loaderp->getDuration() > MAX_ANIM_DURATION) + { + char output_str[256]; + + sprintf(output_str, "Animation file is %.1f seconds in length.\n\nMaximum animation length is %.1f seconds.\n", + loaderp->getDuration(), MAX_ANIM_DURATION); + childSetValue("bad_animation_text", LLSD(output_str)); + } + else + { + char* status = loaderp->getStatus(); + LLString error_string("Unable to read animation file.\n\n"); + error_string += LLString(status); + childSetValue("bad_animation_text", LLSD(error_string)); + } + } + + mEnabled = FALSE; + mMotionID.setNull(); + mAnimPreview = NULL; + } + + refresh(); + + delete loaderp; + + return TRUE; +} + +//----------------------------------------------------------------------------- +// LLFloaterAnimPreview() +//----------------------------------------------------------------------------- +LLFloaterAnimPreview::~LLFloaterAnimPreview() +{ + delete mAnimPreview; + mAnimPreview = NULL; + + mEnabled = FALSE; +} + +//----------------------------------------------------------------------------- +// draw() +//----------------------------------------------------------------------------- +void LLFloaterAnimPreview::draw() +{ + LLFloater::draw(); + LLRect r = getRect(); + + refresh(); + + if (mMotionID.notNull() && mAnimPreview) + { + glColor3f(1.f, 1.f, 1.f); + mAnimPreview->bindTexture(); + + glBegin( GL_QUADS ); + { + glTexCoord2f(0.f, 1.f); + glVertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT); + glTexCoord2f(0.f, 0.f); + glVertex2i(PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); + glTexCoord2f(1.f, 0.f); + glVertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); + glTexCoord2f(1.f, 1.f); + glVertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT); + } + glEnd(); + + mAnimPreview->unbindTexture(); + + LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); + if (!avatarp->areAnimationsPaused()) + { + mAnimPreview->requestUpdate(); + } + } +} + +//----------------------------------------------------------------------------- +// resetMotion() +//----------------------------------------------------------------------------- +void LLFloaterAnimPreview::resetMotion() +{ + LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); + BOOL paused = avatarp->areAnimationsPaused(); + + mPauseRequest = NULL; + + LLUUID anim_id = mIDList[childGetValue("preview_base_anim").asString()]; + avatarp->stopMotion(anim_id, TRUE); + avatarp->stopMotion(mMotionID, TRUE); + avatarp->startMotion(anim_id, 5.f); + avatarp->startMotion(mMotionID); + childSetValue("playback_slider", 0.0); + mLastSliderValue = 0.0f; + + if (paused) + { + mPauseRequest = avatarp->requestPause(); + } +} + +//----------------------------------------------------------------------------- +// handleMouseDown() +//----------------------------------------------------------------------------- +BOOL LLFloaterAnimPreview::handleMouseDown(S32 x, S32 y, MASK mask) +{ + if (mPreviewRect.pointInRect(x, y)) + { + bringToFront( x, y ); + gViewerWindow->setMouseCapture(this, onMouseCaptureLost); + gViewerWindow->hideCursor(); + mLastMouseX = x; + mLastMouseY = y; + return TRUE; + } + + return LLFloater::handleMouseDown(x, y, mask); +} + +//----------------------------------------------------------------------------- +// handleMouseUp() +//----------------------------------------------------------------------------- +BOOL LLFloaterAnimPreview::handleMouseUp(S32 x, S32 y, MASK mask) +{ + gViewerWindow->setMouseCapture(FALSE, NULL); + gViewerWindow->showCursor(); + return LLFloater::handleMouseUp(x, y, mask); +} + +//----------------------------------------------------------------------------- +// handleHover() +//----------------------------------------------------------------------------- +BOOL LLFloaterAnimPreview::handleHover(S32 x, S32 y, MASK mask) +{ + MASK local_mask = mask & ~MASK_ALT; + + if (mAnimPreview && gViewerWindow->hasMouseCapture(this)) + { + if (local_mask == MASK_PAN) + { + // pan here + mAnimPreview->pan((F32)(x - mLastMouseX) * -0.005f, (F32)(y - mLastMouseY) * -0.005f); + } + else if (local_mask == MASK_ORBIT) + { + F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f; + F32 pitch_radians = (F32)(y - mLastMouseY) * 0.02f; + + mAnimPreview->rotate(yaw_radians, pitch_radians); + } + else + { + F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f; + F32 zoom_amt = (F32)(y - mLastMouseY) * 0.02f; + + mAnimPreview->rotate(yaw_radians, 0.f); + mAnimPreview->zoom(zoom_amt); + } + + mAnimPreview->requestUpdate(); + + LLUI::setCursorPositionLocal(this, mLastMouseX, mLastMouseY); + } + + if (!mPreviewRect.pointInRect(x, y) || !mAnimPreview) + { + return LLFloater::handleHover(x, y, mask); + } + else if (local_mask == MASK_ORBIT) + { + gViewerWindow->setCursor(UI_CURSOR_TOOLCAMERA); + } + else if (local_mask == MASK_PAN) + { + gViewerWindow->setCursor(UI_CURSOR_TOOLPAN); + } + else + { + gViewerWindow->setCursor(UI_CURSOR_TOOLZOOMIN); + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// handleScrollWheel() +//----------------------------------------------------------------------------- +BOOL LLFloaterAnimPreview::handleScrollWheel(S32 x, S32 y, S32 clicks) +{ + mAnimPreview->zoom((F32)clicks * -0.2f); + mAnimPreview->requestUpdate(); + + return TRUE; +} + +//----------------------------------------------------------------------------- +// onMouseCaptureLost() +//----------------------------------------------------------------------------- +void LLFloaterAnimPreview::onMouseCaptureLost(LLMouseHandler* handler) +{ + gViewerWindow->showCursor(); +} + +//----------------------------------------------------------------------------- +// onBtnPlay() +//----------------------------------------------------------------------------- +void LLFloaterAnimPreview::onBtnPlay(void* user_data) +{ + LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)user_data; + if (!previewp->mEnabled) return; + + if (previewp->mMotionID.notNull() && previewp->mAnimPreview) + { + LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar(); + + if(!avatarp->isMotionActive(previewp->mMotionID)) + { + previewp->resetMotion(); + previewp->mPauseRequest = NULL; + } + else + { + if (avatarp->areAnimationsPaused()) + { + previewp->mPauseRequest = NULL; + } + else + { + previewp->mPauseRequest = avatarp->requestPause(); + } + } + } +} + +//----------------------------------------------------------------------------- +// onBtnStop() +//----------------------------------------------------------------------------- +void LLFloaterAnimPreview::onBtnStop(void* user_data) +{ + LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)user_data; + if (!previewp->mEnabled) return; + + if (previewp->mMotionID.notNull() && previewp->mAnimPreview) + { + LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar(); + + // is the motion looping and have we passed the loop in point? + if (previewp->childGetValue("loop_check").asBoolean() && + (F32)previewp->childGetValue("loop_in_point").asReal() <= (F32)previewp->childGetValue("playback_slider").asReal() * 100.f) + { + avatarp->stopMotion(previewp->mMotionID, FALSE); + } + else + { + avatarp->stopMotion(previewp->mMotionID, FALSE); + } + } +} + +//----------------------------------------------------------------------------- +// onSliderMove() +//----------------------------------------------------------------------------- +void LLFloaterAnimPreview::onSliderMove(LLUICtrl* ctrl, void*user_data) +{ + LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)user_data; + if (!previewp->mEnabled) return; + + if (previewp->mAnimPreview) + { + LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar(); + LLMotion* motionp = avatarp->findMotion(previewp->mMotionID); + LLMotion* base_motionp = + avatarp->findMotion(previewp->mIDList[previewp->childGetValue("preview_base_anim").asString()]); + + if (motionp && base_motionp) + { + if (!avatarp->isMotionActive(previewp->mMotionID)) + { + previewp->resetMotion(); + } + + previewp->mPauseRequest = avatarp->requestPause(); + F32 original_activation_time = motionp->mActivationTimestamp; + motionp->mActivationTimestamp -= ((F32)previewp->childGetValue("playback_slider").asReal() - previewp->mLastSliderValue) * + motionp->getDuration(); + base_motionp->mActivationTimestamp -= ((F32)previewp->childGetValue("playback_slider").asReal() - previewp->mLastSliderValue) * + base_motionp->getDuration(); + + if (motionp->mSendStopTimestamp != F32_MIN) + { + motionp->mSendStopTimestamp = motionp->mSendStopTimestamp - original_activation_time + motionp->mActivationTimestamp; + } + + if (motionp->mStopTimestamp != F32_MIN) + { + motionp->mStopTimestamp = motionp->mStopTimestamp - original_activation_time + motionp->mActivationTimestamp; + } + previewp->refresh(); + } + } + + previewp->mLastSliderValue = (F32)previewp->childGetValue("playback_slider").asReal(); +} + +//----------------------------------------------------------------------------- +// onCommitBaseAnim() +//----------------------------------------------------------------------------- +void LLFloaterAnimPreview::onCommitBaseAnim(LLUICtrl* ctrl, void* data) +{ + LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; + + if (!previewp->mEnabled) return; + + if (previewp->mAnimPreview) + { + LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar(); + + BOOL paused = avatarp->areAnimationsPaused(); + + // stop all other possible base motions + avatarp->stopMotion(ANIM_AGENT_STAND, TRUE); + avatarp->stopMotion(ANIM_AGENT_WALK, TRUE); + avatarp->stopMotion(ANIM_AGENT_SIT, TRUE); + avatarp->stopMotion(ANIM_AGENT_HOVER, TRUE); + + previewp->resetMotion(); + + if (!paused) + { + previewp->mPauseRequest = NULL; + } + } +} + +//----------------------------------------------------------------------------- +// onCommitLoop() +//----------------------------------------------------------------------------- +void LLFloaterAnimPreview::onCommitLoop(LLUICtrl* ctrl, void* data) +{ + LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; + + if (!previewp->mEnabled) return; + LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar(); + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); + + if (motionp) + { + motionp->setLoop(previewp->childGetValue("loop_check").asBoolean()); + motionp->setLoopIn((F32)previewp->childGetValue("loop_in_point").asReal() * 0.01f * motionp->getDuration()); + motionp->setLoopOut((F32)previewp->childGetValue("loop_out_point").asReal() * 0.01f * motionp->getDuration()); + } +} + +//----------------------------------------------------------------------------- +// onCommitLoopIn() +//----------------------------------------------------------------------------- +void LLFloaterAnimPreview::onCommitLoopIn(LLUICtrl* ctrl, void* data) +{ + LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; + if (!previewp->mEnabled) return; + + LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar(); + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); + + if (motionp) + { + motionp->setLoopIn((F32)previewp->childGetValue("loop_in_point").asReal() / 100.f); + previewp->resetMotion(); + previewp->childSetValue("loop_check", LLSD(TRUE)); + onCommitLoop(ctrl, data); + } +} + +//----------------------------------------------------------------------------- +// onCommitLoopOut() +//----------------------------------------------------------------------------- +void LLFloaterAnimPreview::onCommitLoopOut(LLUICtrl* ctrl, void* data) +{ + LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; + if (!previewp->mEnabled) return; + + LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar(); + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); + + if (motionp) + { + motionp->setLoopOut((F32)previewp->childGetValue("loop_out_point").asReal() * 0.01f * motionp->getDuration()); + previewp->resetMotion(); + previewp->childSetValue("loop_check", LLSD(TRUE)); + onCommitLoop(ctrl, data); + } +} + +//----------------------------------------------------------------------------- +// onCommitName() +//----------------------------------------------------------------------------- +void LLFloaterAnimPreview::onCommitName(LLUICtrl* ctrl, void* data) +{ + LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; + if (!previewp->mEnabled) return; + + LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar(); + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); + + if (motionp) + { + motionp->setName(previewp->childGetValue("name_form").asString()); + } + + LLFloaterNameDesc::doCommit(ctrl, data); +} + +//----------------------------------------------------------------------------- +// onCommitHandPose() +//----------------------------------------------------------------------------- +void LLFloaterAnimPreview::onCommitHandPose(LLUICtrl* ctrl, void* data) +{ + LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; + if (!previewp->mEnabled) return; + + LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar(); + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); + + motionp->setHandPose(LLHandMotion::getHandPose(previewp->childGetValue("hand_pose_combo").asString())); + previewp->resetMotion(); +} + +//----------------------------------------------------------------------------- +// onCommitEmote() +//----------------------------------------------------------------------------- +void LLFloaterAnimPreview::onCommitEmote(LLUICtrl* ctrl, void* data) +{ + LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; + if (!previewp->mEnabled) return; + + LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar(); + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); + + motionp->setEmote(previewp->mIDList[previewp->childGetValue("emote_combo").asString()]); + previewp->resetMotion(); +} + +//----------------------------------------------------------------------------- +// onCommitPriority() +//----------------------------------------------------------------------------- +void LLFloaterAnimPreview::onCommitPriority(LLUICtrl* ctrl, void* data) +{ + LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; + if (!previewp->mEnabled) return; + + LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar(); + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); + + motionp->setPriority(llfloor((F32)previewp->childGetValue("priority").asReal())); +} + +//----------------------------------------------------------------------------- +// onCommitEaseIn() +//----------------------------------------------------------------------------- +void LLFloaterAnimPreview::onCommitEaseIn(LLUICtrl* ctrl, void* data) +{ + LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; + if (!previewp->mEnabled) return; + + LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar(); + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); + + motionp->setEaseIn((F32)previewp->childGetValue("ease_in_time").asReal()); + previewp->resetMotion(); +} + +//----------------------------------------------------------------------------- +// onCommitEaseOut() +//----------------------------------------------------------------------------- +void LLFloaterAnimPreview::onCommitEaseOut(LLUICtrl* ctrl, void* data) +{ + LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; + if (!previewp->mEnabled) return; + + LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar(); + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); + + motionp->setEaseOut((F32)previewp->childGetValue("ease_out_time").asReal()); + previewp->resetMotion(); +} + +//----------------------------------------------------------------------------- +// validateEaseIn() +//----------------------------------------------------------------------------- +BOOL LLFloaterAnimPreview::validateEaseIn(LLUICtrl* spin, void* data) +{ + LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; + + if (!previewp->mEnabled) return FALSE; + + LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar(); + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); + + if (!motionp->getLoop()) + { + F32 new_ease_in = llclamp((F32)previewp->childGetValue("ease_in_time").asReal(), 0.f, motionp->getDuration() - motionp->getEaseOutDuration()); + previewp->childSetValue("ease_in_time", LLSD(new_ease_in)); + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// validateEaseOut() +//----------------------------------------------------------------------------- +BOOL LLFloaterAnimPreview::validateEaseOut(LLUICtrl* spin, void* data) +{ + LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; + + if (!previewp->mEnabled) return FALSE; + + LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar(); + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID); + + if (!motionp->getLoop()) + { + F32 new_ease_out = llclamp((F32)previewp->childGetValue("ease_out_time").asReal(), 0.f, motionp->getDuration() - motionp->getEaseInDuration()); + previewp->childSetValue("ease_out_time", LLSD(new_ease_out)); + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// validateLoopIn() +//----------------------------------------------------------------------------- +BOOL LLFloaterAnimPreview::validateLoopIn(LLUICtrl* ctrl, void* data) +{ + LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; + + if (!previewp->mEnabled) return FALSE; + + F32 loop_in_value = (F32)previewp->childGetValue("loop_in_point").asReal(); + F32 loop_out_value = (F32)previewp->childGetValue("loop_out_point").asReal(); + + if (loop_in_value < 0.f) + { + loop_in_value = 0.f; + } + else if (loop_in_value > 100.f) + { + loop_in_value = 100.f; + } + else if (loop_in_value > loop_out_value) + { + loop_in_value = loop_out_value; + } + + previewp->childSetValue("loop_in_point", LLSD(loop_in_value)); + return TRUE; +} + +//----------------------------------------------------------------------------- +// validateLoopOut() +//----------------------------------------------------------------------------- +BOOL LLFloaterAnimPreview::validateLoopOut(LLUICtrl* spin, void* data) +{ + LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data; + + if (!previewp->mEnabled) return FALSE; + + F32 loop_out_value = (F32)previewp->childGetValue("loop_out_point").asReal(); + F32 loop_in_value = (F32)previewp->childGetValue("loop_in_point").asReal(); + + if (loop_out_value < 0.f) + { + loop_out_value = 0.f; + } + else if (loop_out_value > 100.f) + { + loop_out_value = 100.f; + } + else if (loop_out_value < loop_in_value) + { + loop_out_value = loop_in_value; + } + + previewp->childSetValue("loop_out_point", LLSD(loop_out_value)); + return TRUE; +} + + +//----------------------------------------------------------------------------- +// refresh() +//----------------------------------------------------------------------------- +void LLFloaterAnimPreview::refresh() +{ + if (!mAnimPreview) + { + childShow("bad_animation_text"); + mPlayButton->setEnabled(FALSE); + mStopButton->setEnabled(FALSE); + childDisable("ok_btn"); + } + else + { + childHide("bad_animation_text"); + mPlayButton->setEnabled(TRUE); + LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); + if (avatarp->isMotionActive(mMotionID)) + { + mStopButton->setEnabled(TRUE); + LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(mMotionID); + if (avatarp->areAnimationsPaused()) + { + + mPlayButton->setImages("button_anim_play.tga", + "button_anim_play_selected.tga"); + + } + else + { + if (motionp) + { + F32 fraction_complete; + fraction_complete = motionp->getLastUpdateTime() / motionp->getDuration(); + + childSetValue("playback_slider", fraction_complete); + mLastSliderValue = fraction_complete; + } + mPlayButton->setImages("button_anim_pause.tga", + "button_anim_pause_selected.tga"); + + } + } + else + { + mPauseRequest = avatarp->requestPause(); + mPlayButton->setImages("button_anim_play.tga", + "button_anim_play_selected.tga"); + + mStopButton->setEnabled(FALSE); + } + childEnable("ok_btn"); + mAnimPreview->requestUpdate(); + } +} + +//----------------------------------------------------------------------------- +// onBtnOK() +//----------------------------------------------------------------------------- +void LLFloaterAnimPreview::onBtnOK(void* userdata) +{ + LLFloaterAnimPreview* floaterp = (LLFloaterAnimPreview*)userdata; + if (!floaterp->mEnabled) return; + + if (floaterp->mAnimPreview) + { + LLKeyframeMotion* motionp = (LLKeyframeMotion*)floaterp->mAnimPreview->getDummyAvatar()->findMotion(floaterp->mMotionID); + + S32 file_size = motionp->getFileSize(); + U8* buffer = new U8[file_size]; + + LLDataPackerBinaryBuffer dp(buffer, file_size); + if (motionp->serialize(dp)) + { + LLVFile file(gVFS, motionp->getID(), LLAssetType::AT_ANIMATION, LLVFile::APPEND); + + S32 size = dp.getCurrentSize(); + file.setMaxSize(size); + if (file.write((U8*)buffer, size)) + { + std::string name = floaterp->childGetValue("name_form").asString(); + std::string desc = floaterp->childGetValue("description_form").asString(); + upload_new_resource(floaterp->mTransactionID, // tid + LLAssetType::AT_ANIMATION, + name, + desc, + 0, + LLAssetType::AT_NONE, + LLInventoryType::IT_ANIMATION, + PERM_NONE, + name); + } + else + { + llwarns << "Failure writing animation data." << llendl; + gViewerWindow->alertXml("WriteAnimationFail"); + } + } + + delete [] buffer; + // clear out cache for motion data + floaterp->mAnimPreview->getDummyAvatar()->removeMotion(floaterp->mMotionID); + LLKeyframeDataCache::removeKeyframeData(floaterp->mMotionID); + } + + floaterp->onClose(false); +} + +//----------------------------------------------------------------------------- +// LLPreviewAnimation +//----------------------------------------------------------------------------- +LLPreviewAnimation::LLPreviewAnimation(S32 width, S32 height) : LLDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE) +{ + mNeedsUpdate = TRUE; + mCameraDistance = PREVIEW_CAMERA_DISTANCE; + mCameraYaw = 0.f; + mCameraPitch = 0.f; + mCameraZoom = 1.f; + + mDummyAvatar = (LLVOAvatar*)gObjectList.createObjectViewer(LL_PCODE_LEGACY_AVATAR, gAgent.getRegion()); + mDummyAvatar->createDrawable(&gPipeline); + mDummyAvatar->mIsDummy = TRUE; + mDummyAvatar->mSpecialRenderMode = 1; + mDummyAvatar->setPositionAgent(LLVector3::zero); + mDummyAvatar->slamPosition(); + mDummyAvatar->updateJointLODs(); + mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable); + mDummyAvatar->startMotion(ANIM_AGENT_STAND, 5.f); + mDummyAvatar->mSkirtLOD.setVisible(FALSE, TRUE); + gPipeline.markVisible(mDummyAvatar->mDrawable); + + // stop extraneous animations + mDummyAvatar->stopMotion( ANIM_AGENT_HEAD_ROT, TRUE ); + mDummyAvatar->stopMotion( ANIM_AGENT_EYE, TRUE ); + mDummyAvatar->stopMotion( ANIM_AGENT_BODY_NOISE, TRUE ); + mDummyAvatar->stopMotion( ANIM_AGENT_BREATHE_ROT, TRUE ); +} + +//----------------------------------------------------------------------------- +// LLPreviewAnimation() +//----------------------------------------------------------------------------- +LLPreviewAnimation::~LLPreviewAnimation() +{ + mDummyAvatar->markDead(); +} + +//----------------------------------------------------------------------------- +// update() +//----------------------------------------------------------------------------- +BOOL LLPreviewAnimation::render() +{ + mNeedsUpdate = FALSE; + LLVOAvatar* avatarp = mDummyAvatar; + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0.0f, mWidth, 0.0f, mHeight, -1.0f, 1.0f); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + LLGLSUIDefault def; + LLGLSNoTexture gls_no_texture; + glColor4f(0.15f, 0.2f, 0.3f, 1.f); + + gl_rect_2d_simple( mWidth, mHeight ); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + LLVector3 target_pos = avatarp->mRoot.getWorldPosition(); + + LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) * + LLQuaternion(mCameraYaw, LLVector3::z_axis); + + LLQuaternion av_rot = avatarp->mRoot.getWorldRotation() * camera_rot; + gCamera->setOriginAndLookAt( + target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + mCameraOffset) * av_rot), // camera + LLVector3::z_axis, // up + target_pos + (mCameraOffset * av_rot) ); // point of interest + + gCamera->setView(gCamera->getDefaultFOV() / mCameraZoom); + gCamera->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mWidth, mHeight, FALSE); + + mCameraRelPos = gCamera->getOrigin() - avatarp->mHeadp->getWorldPosition(); + + //avatarp->setAnimationData("LookAtPoint", (void *)&mCameraRelPos); + + //RN: timestep must be zero, because paused animations will never initialize + // av skeleton otherwise + avatarp->setTimeStep(0.f); + if (avatarp->areAnimationsPaused()) + { + avatarp->updateMotion(TRUE); + } + else + { + avatarp->updateMotion(); + } + + avatarp->mRoot.updateWorldMatrixChildren(); + + stop_glerror(); + + LLGLDepthTest gls_depth(GL_TRUE); + + if (avatarp->mDrawable.notNull()) + { + LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool(); + gPipeline.unbindAGP(); + avatarPoolp->syncAGP(); + if (avatarPoolp->canUseAGP() && gPipeline.usingAGP()) + { + gPipeline.bindAGP(); + } + avatarPoolp->renderAvatars(avatarp, TRUE); // renders only one avatar (no shaders) + } + + return TRUE; +} + +//----------------------------------------------------------------------------- +// requestUpdate() +//----------------------------------------------------------------------------- +void LLPreviewAnimation::requestUpdate() +{ + mNeedsUpdate = TRUE; +} + +//----------------------------------------------------------------------------- +// rotate() +//----------------------------------------------------------------------------- +void LLPreviewAnimation::rotate(F32 yaw_radians, F32 pitch_radians) +{ + mCameraYaw = mCameraYaw + yaw_radians; + + mCameraPitch = llclamp(mCameraPitch + pitch_radians, F_PI_BY_TWO * -0.8f, F_PI_BY_TWO * 0.8f); +} + +//----------------------------------------------------------------------------- +// zoom() +//----------------------------------------------------------------------------- +void LLPreviewAnimation::zoom(F32 zoom_delta) +{ + setZoom(mCameraZoom + zoom_delta); +} + +//----------------------------------------------------------------------------- +// setZoom() +//----------------------------------------------------------------------------- +void LLPreviewAnimation::setZoom(F32 zoom_amt) +{ + mCameraZoom = llclamp(zoom_amt, MIN_CAMERA_ZOOM, MAX_CAMERA_ZOOM); +} + +//----------------------------------------------------------------------------- +// pan() +//----------------------------------------------------------------------------- +void LLPreviewAnimation::pan(F32 right, F32 up) +{ + mCameraOffset.mV[VY] = llclamp(mCameraOffset.mV[VY] + right * mCameraDistance / mCameraZoom, -1.f, 1.f); + mCameraOffset.mV[VZ] = llclamp(mCameraOffset.mV[VZ] + up * mCameraDistance / mCameraZoom, -1.f, 1.f); +} + -- cgit v1.1