00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llfloateranimpreview.h"
00035
00036 #include "llbvhloader.h"
00037 #include "lldatapacker.h"
00038 #include "lldir.h"
00039 #include "llvfile.h"
00040 #include "llapr.h"
00041
00042 #include "llagent.h"
00043 #include "llbbox.h"
00044 #include "llbutton.h"
00045 #include "llcheckboxctrl.h"
00046 #include "llcombobox.h"
00047 #include "lldrawable.h"
00048 #include "lldrawpoolavatar.h"
00049 #include "llglimmediate.h"
00050 #include "llface.h"
00051 #include "llkeyframemotion.h"
00052 #include "lllineeditor.h"
00053 #include "llsliderctrl.h"
00054 #include "llspinctrl.h"
00055 #include "lltextbox.h"
00056 #include "lltoolmgr.h"
00057 #include "llui.h"
00058 #include "llviewercamera.h"
00059 #include "llviewerobjectlist.h"
00060 #include "llviewerwindow.h"
00061 #include "llviewermenufile.h"
00062 #include "llvoavatar.h"
00063 #include "pipeline.h"
00064 #include "lluictrlfactory.h"
00065
00066 S32 LLFloaterAnimPreview::sUploadAmount = 10;
00067
00068 const S32 PREVIEW_BORDER_WIDTH = 2;
00069 const S32 PREVIEW_RESIZE_HANDLE_SIZE = S32(RESIZE_HANDLE_WIDTH * OO_SQRT2) + PREVIEW_BORDER_WIDTH;
00070 const S32 PREVIEW_HPAD = PREVIEW_RESIZE_HANDLE_SIZE;
00071 const S32 PREF_BUTTON_HEIGHT = 16;
00072 const S32 PREVIEW_TEXTURE_HEIGHT = 300;
00073
00074 const F32 PREVIEW_CAMERA_DISTANCE = 4.f;
00075
00076 const F32 MIN_CAMERA_ZOOM = 0.5f;
00077 const F32 MAX_CAMERA_ZOOM = 10.f;
00078
00079
00080
00081
00082 LLFloaterAnimPreview::LLFloaterAnimPreview(const char* filename) :
00083 LLFloaterNameDesc(filename)
00084 {
00085 mLastSliderValue = 0.f;
00086 mLastMouseX = 0;
00087 mLastMouseY = 0;
00088
00089 mIDList["Standing"] = ANIM_AGENT_STAND;
00090 mIDList["Walking"] = ANIM_AGENT_FEMALE_WALK;
00091 mIDList["Sitting"] = ANIM_AGENT_SIT_FEMALE;
00092 mIDList["Flying"] = ANIM_AGENT_HOVER;
00093
00094 mIDList["[None]"] = LLUUID::null;
00095 mIDList["Aaaaah"] = ANIM_AGENT_EXPRESS_OPEN_MOUTH;
00096 mIDList["Afraid"] = ANIM_AGENT_EXPRESS_AFRAID;
00097 mIDList["Angry"] = ANIM_AGENT_EXPRESS_ANGER;
00098 mIDList["Big Smile"] = ANIM_AGENT_EXPRESS_TOOTHSMILE;
00099 mIDList["Bored"] = ANIM_AGENT_EXPRESS_BORED;
00100 mIDList["Cry"] = ANIM_AGENT_EXPRESS_CRY;
00101 mIDList["Disdain"] = ANIM_AGENT_EXPRESS_DISDAIN;
00102 mIDList["Embarrassed"] = ANIM_AGENT_EXPRESS_EMBARRASSED;
00103 mIDList["Frown"] = ANIM_AGENT_EXPRESS_FROWN;
00104 mIDList["Kiss"] = ANIM_AGENT_EXPRESS_KISS;
00105 mIDList["Laugh"] = ANIM_AGENT_EXPRESS_LAUGH;
00106 mIDList["Plllppt"] = ANIM_AGENT_EXPRESS_TONGUE_OUT;
00107 mIDList["Repulsed"] = ANIM_AGENT_EXPRESS_REPULSED;
00108 mIDList["Sad"] = ANIM_AGENT_EXPRESS_SAD;
00109 mIDList["Shrug"] = ANIM_AGENT_EXPRESS_SHRUG;
00110 mIDList["Smile"] = ANIM_AGENT_EXPRESS_SMILE;
00111 mIDList["Surprise"] = ANIM_AGENT_EXPRESS_SURPRISE;
00112 mIDList["Wink"] = ANIM_AGENT_EXPRESS_WINK;
00113 mIDList["Worry"] = ANIM_AGENT_EXPRESS_WORRY;
00114 }
00115
00116
00117
00118
00119 void LLFloaterAnimPreview::setAnimCallbacks()
00120 {
00121 childSetCommitCallback("playback_slider", onSliderMove, this);
00122
00123 childSetCommitCallback("preview_base_anim", onCommitBaseAnim, this);
00124 childSetValue("preview_base_anim", "Standing");
00125
00126 childSetCommitCallback("priority", onCommitPriority, this);
00127 childSetCommitCallback("loop_check", onCommitLoop, this);
00128 childSetCommitCallback("loop_in_point", onCommitLoopIn, this);
00129 childSetValidate("loop_in_point", validateLoopIn);
00130 childSetCommitCallback("loop_out_point", onCommitLoopOut, this);
00131 childSetValidate("loop_out_point", validateLoopOut);
00132
00133 childSetCommitCallback("hand_pose_combo", onCommitHandPose, this);
00134
00135 childSetCommitCallback("emote_combo", onCommitEmote, this);
00136 childSetValue("emote_combo", "[None]");
00137
00138 childSetCommitCallback("ease_in_time", onCommitEaseIn, this);
00139 childSetValidate("ease_in_time", validateEaseIn);
00140 childSetCommitCallback("ease_out_time", onCommitEaseOut, this);
00141 childSetValidate("ease_out_time", validateEaseOut);
00142 }
00143
00144
00145
00146
00147 BOOL LLFloaterAnimPreview::postBuild()
00148 {
00149 LLRect r;
00150 LLKeyframeMotion* motionp = NULL;
00151 LLBVHLoader* loaderp = NULL;
00152
00153 if (!LLFloaterNameDesc::postBuild())
00154 {
00155 return FALSE;
00156 }
00157
00158 childSetCommitCallback("name_form", onCommitName, this);
00159
00160 childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d",sUploadAmount));
00161 childSetAction("ok_btn", onBtnOK, this);
00162 setDefaultBtn();
00163
00164 mPreviewRect.set(PREVIEW_HPAD,
00165 PREVIEW_TEXTURE_HEIGHT,
00166 getRect().getWidth() - PREVIEW_HPAD,
00167 PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD);
00168 mPreviewImageRect.set(0.f, 1.f, 1.f, 0.f);
00169
00170 S32 y = mPreviewRect.mTop + BTN_HEIGHT;
00171 S32 btn_left = PREVIEW_HPAD;
00172
00173 r.set( btn_left, y, btn_left + 32, y - BTN_HEIGHT );
00174 mPlayButton = getChild<LLButton>( "play_btn");
00175 if (!mPlayButton)
00176 {
00177 mPlayButton = new LLButton("play_btn", LLRect(0,0,0,0));
00178 }
00179 mPlayButton->setClickedCallback(onBtnPlay);
00180 mPlayButton->setCallbackUserData(this);
00181
00182 mPlayButton->setImages("button_anim_play.tga",
00183 "button_anim_play_selected.tga");
00184 mPlayButton->setDisabledImages("","");
00185
00186 mPlayButton->setScaleImage(TRUE);
00187
00188 mStopButton = getChild<LLButton>( "stop_btn");
00189 if (!mStopButton)
00190 {
00191 mStopButton = new LLButton("stop_btn", LLRect(0,0,0,0));
00192 }
00193 mStopButton->setClickedCallback(onBtnStop);
00194 mStopButton->setCallbackUserData(this);
00195
00196 mStopButton->setImages("button_anim_stop.tga",
00197 "button_anim_stop_selected.tga");
00198 mStopButton->setDisabledImages("","");
00199
00200 mStopButton->setScaleImage(TRUE);
00201
00202 r.set(r.mRight + PREVIEW_HPAD, y, getRect().getWidth() - PREVIEW_HPAD, y - BTN_HEIGHT);
00203
00204
00205 childHide("bad_animation_text");
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 if (!stricmp(strrchr(mFilename.c_str(), '.'), ".bvh"))
00228 {
00229
00230
00231
00232 S32 file_size;
00233 apr_file_t* fp = ll_apr_file_open(mFilenameAndPath, LL_APR_RB, &file_size);
00234
00235 if (!fp)
00236 {
00237 llwarns << "Can't open BVH file:" << mFilename << llendl;
00238 }
00239 else
00240 {
00241 char* file_buffer;
00242
00243 file_buffer = new char[file_size + 1];
00244
00245 if (file_size == ll_apr_file_read(fp, file_buffer, file_size))
00246 {
00247 file_buffer[file_size] = '\0';
00248 llinfos << "Loading BVH file " << mFilename << llendl;
00249 loaderp = new LLBVHLoader(file_buffer);
00250 }
00251
00252 apr_file_close(fp);
00253 delete[] file_buffer;
00254 }
00255 }
00256
00257 if (loaderp && loaderp->isInitialized() && loaderp->getDuration() <= MAX_ANIM_DURATION)
00258 {
00259
00260 mTransactionID.generate();
00261 mMotionID = mTransactionID.makeAssetID(gAgent.getSecureSessionID());
00262
00263 mAnimPreview = new LLPreviewAnimation(256, 256);
00264
00265
00266
00267
00268 motionp = (LLKeyframeMotion*)mAnimPreview->getDummyAvatar()->createMotion(mMotionID);
00269
00270
00271 S32 buffer_size = loaderp->getOutputSize();
00272 U8* buffer = new U8[buffer_size];
00273
00274 LLDataPackerBinaryBuffer dp(buffer, buffer_size);
00275
00276
00277 loaderp->serialize(dp);
00278 dp.reset();
00279 BOOL success = motionp && motionp->deserialize(dp);
00280
00281 delete []buffer;
00282
00283 if (success)
00284 {
00285 setAnimCallbacks() ;
00286
00287 const LLBBoxLocal &pelvis_bbox = motionp->getPelvisBBox();
00288
00289 LLVector3 temp = pelvis_bbox.getCenter();
00290
00291
00292 F32 pelvis_offset = temp.magVec();
00293
00294 temp = pelvis_bbox.getExtent();
00295
00296 F32 pelvis_max_displacement = pelvis_offset + (temp.magVec() * 0.5f) + 1.f;
00297
00298 F32 camera_zoom = LLViewerCamera::getInstance()->getDefaultFOV() / (2.f * atan(pelvis_max_displacement / PREVIEW_CAMERA_DISTANCE));
00299
00300 mAnimPreview->setZoom(camera_zoom);
00301
00302 motionp->setName(childGetValue("name_form").asString());
00303 mAnimPreview->getDummyAvatar()->startMotion(mMotionID);
00304 childSetMinValue("playback_slider", 0.0);
00305 childSetMaxValue("playback_slider", 1.0);
00306
00307 childSetValue("loop_check", LLSD(motionp->getLoop()));
00308 childSetValue("loop_in_point", LLSD(motionp->getLoopIn() / motionp->getDuration() * 100.f));
00309 childSetValue("loop_out_point", LLSD(motionp->getLoopOut() / motionp->getDuration() * 100.f));
00310 childSetValue("priority", LLSD((F32)motionp->getPriority()));
00311 childSetValue("hand_pose_combo", LLHandMotion::getHandPoseName(motionp->getHandPose()));
00312 childSetValue("ease_in_time", LLSD(motionp->getEaseInDuration()));
00313 childSetValue("ease_out_time", LLSD(motionp->getEaseOutDuration()));
00314 setEnabled(TRUE);
00315 char seconds_string[128];
00316 snprintf(seconds_string, sizeof(seconds_string), " - %.2f seconds", motionp->getDuration());
00317
00318 setTitle(mFilename + LLString(seconds_string));
00319 }
00320 else
00321 {
00322 delete mAnimPreview;
00323 mAnimPreview = NULL;
00324 mMotionID.setNull();
00325 childSetValue("bad_animation_text", getString("failed_to_initialize"));
00326 }
00327 }
00328 else
00329 {
00330 if ( loaderp )
00331 {
00332 if (loaderp->getDuration() > MAX_ANIM_DURATION)
00333 {
00334 LLUIString out_str = getString("anim_too_long");
00335 out_str.setArg("[LENGTH]", llformat("%.1f", loaderp->getDuration()));
00336 out_str.setArg("[MAX_LENGTH]", llformat("%.1f", MAX_ANIM_DURATION));
00337 childSetValue("bad_animation_text", out_str.getString());
00338 }
00339 else
00340 {
00341 LLUIString out_str = getString("failed_file_read");
00342 out_str.setArg("[STATUS]", loaderp->getStatus());
00343 childSetValue("bad_animation_text", out_str.getString());
00344 }
00345 }
00346
00347
00348 mMotionID.setNull();
00349 mAnimPreview = NULL;
00350 }
00351
00352 refresh();
00353
00354 delete loaderp;
00355
00356 return TRUE;
00357 }
00358
00359
00360
00361
00362 LLFloaterAnimPreview::~LLFloaterAnimPreview()
00363 {
00364 delete mAnimPreview;
00365 mAnimPreview = NULL;
00366
00367 setEnabled(FALSE);
00368 }
00369
00370
00371
00372
00373 void LLFloaterAnimPreview::draw()
00374 {
00375 LLFloater::draw();
00376 LLRect r = getRect();
00377
00378 refresh();
00379
00380 if (mMotionID.notNull() && mAnimPreview)
00381 {
00382 gGL.color3f(1.f, 1.f, 1.f);
00383 mAnimPreview->bindTexture();
00384
00385 gGL.begin( LLVertexBuffer::QUADS );
00386 {
00387 gGL.texCoord2f(0.f, 1.f);
00388 gGL.vertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT);
00389 gGL.texCoord2f(0.f, 0.f);
00390 gGL.vertex2i(PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD);
00391 gGL.texCoord2f(1.f, 0.f);
00392 gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD);
00393 gGL.texCoord2f(1.f, 1.f);
00394 gGL.vertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT);
00395 }
00396 gGL.end();
00397
00398 mAnimPreview->unbindTexture();
00399
00400 LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar();
00401 if (!avatarp->areAnimationsPaused())
00402 {
00403 mAnimPreview->requestUpdate();
00404 }
00405 }
00406 }
00407
00408
00409
00410
00411 void LLFloaterAnimPreview::resetMotion()
00412 {
00413 LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar();
00414 BOOL paused = avatarp->areAnimationsPaused();
00415
00416 mPauseRequest = NULL;
00417
00418 LLUUID anim_id = mIDList[childGetValue("preview_base_anim").asString()];
00419 avatarp->stopMotion(anim_id, TRUE);
00420 avatarp->stopMotion(mMotionID, TRUE);
00421 avatarp->startMotion(anim_id, 5.f);
00422 avatarp->startMotion(mMotionID);
00423 childSetValue("playback_slider", 0.0);
00424 mLastSliderValue = 0.0f;
00425
00426 if (paused)
00427 {
00428 mPauseRequest = avatarp->requestPause();
00429 }
00430 }
00431
00432
00433
00434
00435 BOOL LLFloaterAnimPreview::handleMouseDown(S32 x, S32 y, MASK mask)
00436 {
00437 if (mPreviewRect.pointInRect(x, y))
00438 {
00439 bringToFront( x, y );
00440 gViewerWindow->setMouseCapture(this);
00441 gViewerWindow->hideCursor();
00442 mLastMouseX = x;
00443 mLastMouseY = y;
00444 return TRUE;
00445 }
00446
00447 return LLFloater::handleMouseDown(x, y, mask);
00448 }
00449
00450
00451
00452
00453 BOOL LLFloaterAnimPreview::handleMouseUp(S32 x, S32 y, MASK mask)
00454 {
00455 gViewerWindow->setMouseCapture(FALSE);
00456 gViewerWindow->showCursor();
00457 return LLFloater::handleMouseUp(x, y, mask);
00458 }
00459
00460
00461
00462
00463 BOOL LLFloaterAnimPreview::handleHover(S32 x, S32 y, MASK mask)
00464 {
00465 MASK local_mask = mask & ~MASK_ALT;
00466
00467 if (mAnimPreview && hasMouseCapture())
00468 {
00469 if (local_mask == MASK_PAN)
00470 {
00471
00472 mAnimPreview->pan((F32)(x - mLastMouseX) * -0.005f, (F32)(y - mLastMouseY) * -0.005f);
00473 }
00474 else if (local_mask == MASK_ORBIT)
00475 {
00476 F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f;
00477 F32 pitch_radians = (F32)(y - mLastMouseY) * 0.02f;
00478
00479 mAnimPreview->rotate(yaw_radians, pitch_radians);
00480 }
00481 else
00482 {
00483 F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f;
00484 F32 zoom_amt = (F32)(y - mLastMouseY) * 0.02f;
00485
00486 mAnimPreview->rotate(yaw_radians, 0.f);
00487 mAnimPreview->zoom(zoom_amt);
00488 }
00489
00490 mAnimPreview->requestUpdate();
00491
00492 LLUI::setCursorPositionLocal(this, mLastMouseX, mLastMouseY);
00493 }
00494
00495 if (!mPreviewRect.pointInRect(x, y) || !mAnimPreview)
00496 {
00497 return LLFloater::handleHover(x, y, mask);
00498 }
00499 else if (local_mask == MASK_ORBIT)
00500 {
00501 gViewerWindow->setCursor(UI_CURSOR_TOOLCAMERA);
00502 }
00503 else if (local_mask == MASK_PAN)
00504 {
00505 gViewerWindow->setCursor(UI_CURSOR_TOOLPAN);
00506 }
00507 else
00508 {
00509 gViewerWindow->setCursor(UI_CURSOR_TOOLZOOMIN);
00510 }
00511
00512 return TRUE;
00513 }
00514
00515
00516
00517
00518 BOOL LLFloaterAnimPreview::handleScrollWheel(S32 x, S32 y, S32 clicks)
00519 {
00520 mAnimPreview->zoom((F32)clicks * -0.2f);
00521 mAnimPreview->requestUpdate();
00522
00523 return TRUE;
00524 }
00525
00526
00527
00528
00529 void LLFloaterAnimPreview::onMouseCaptureLost()
00530 {
00531 gViewerWindow->showCursor();
00532 }
00533
00534
00535
00536
00537 void LLFloaterAnimPreview::onBtnPlay(void* user_data)
00538 {
00539 LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)user_data;
00540 if (!previewp->getEnabled()) return;
00541
00542 if (previewp->mMotionID.notNull() && previewp->mAnimPreview)
00543 {
00544 LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
00545
00546 if(!avatarp->isMotionActive(previewp->mMotionID))
00547 {
00548 previewp->resetMotion();
00549 previewp->mPauseRequest = NULL;
00550 }
00551 else
00552 {
00553 if (avatarp->areAnimationsPaused())
00554 {
00555 previewp->mPauseRequest = NULL;
00556 }
00557 else
00558 {
00559 previewp->mPauseRequest = avatarp->requestPause();
00560 }
00561 }
00562 }
00563 }
00564
00565
00566
00567
00568 void LLFloaterAnimPreview::onBtnStop(void* user_data)
00569 {
00570 LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)user_data;
00571 if (!previewp->getEnabled()) return;
00572
00573 if (previewp->mMotionID.notNull() && previewp->mAnimPreview)
00574 {
00575 LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
00576
00577
00578 if (previewp->childGetValue("loop_check").asBoolean() &&
00579 (F32)previewp->childGetValue("loop_in_point").asReal() <= (F32)previewp->childGetValue("playback_slider").asReal() * 100.f)
00580 {
00581 avatarp->stopMotion(previewp->mMotionID, FALSE);
00582 }
00583 else
00584 {
00585 avatarp->stopMotion(previewp->mMotionID, FALSE);
00586 }
00587 }
00588 }
00589
00590
00591
00592
00593 void LLFloaterAnimPreview::onSliderMove(LLUICtrl* ctrl, void*user_data)
00594 {
00595 LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)user_data;
00596 if (!previewp->getEnabled()) return;
00597
00598 if (previewp->mAnimPreview)
00599 {
00600 LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
00601 LLMotion* motionp = avatarp->findMotion(previewp->mMotionID);
00602 LLMotion* base_motionp =
00603 avatarp->findMotion(previewp->mIDList[previewp->childGetValue("preview_base_anim").asString()]);
00604
00605 if (motionp && base_motionp)
00606 {
00607 if (!avatarp->isMotionActive(previewp->mMotionID))
00608 {
00609 previewp->resetMotion();
00610 }
00611
00612 previewp->mPauseRequest = avatarp->requestPause();
00613 F32 original_activation_time = motionp->mActivationTimestamp;
00614 motionp->mActivationTimestamp -= ((F32)previewp->childGetValue("playback_slider").asReal() - previewp->mLastSliderValue) *
00615 motionp->getDuration();
00616 base_motionp->mActivationTimestamp -= ((F32)previewp->childGetValue("playback_slider").asReal() - previewp->mLastSliderValue) *
00617 base_motionp->getDuration();
00618
00619 if (motionp->mSendStopTimestamp != F32_MIN)
00620 {
00621 motionp->mSendStopTimestamp = motionp->mSendStopTimestamp - original_activation_time + motionp->mActivationTimestamp;
00622 }
00623
00624 if (motionp->mStopTimestamp != F32_MIN)
00625 {
00626 motionp->mStopTimestamp = motionp->mStopTimestamp - original_activation_time + motionp->mActivationTimestamp;
00627 }
00628 previewp->refresh();
00629 }
00630 }
00631
00632 previewp->mLastSliderValue = (F32)previewp->childGetValue("playback_slider").asReal();
00633 }
00634
00635
00636
00637
00638 void LLFloaterAnimPreview::onCommitBaseAnim(LLUICtrl* ctrl, void* data)
00639 {
00640 LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
00641
00642 if (!previewp->getEnabled()) return;
00643
00644 if (previewp->mAnimPreview)
00645 {
00646 LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
00647
00648 BOOL paused = avatarp->areAnimationsPaused();
00649
00650
00651 avatarp->stopMotion(ANIM_AGENT_STAND, TRUE);
00652 avatarp->stopMotion(ANIM_AGENT_WALK, TRUE);
00653 avatarp->stopMotion(ANIM_AGENT_SIT, TRUE);
00654 avatarp->stopMotion(ANIM_AGENT_HOVER, TRUE);
00655
00656 previewp->resetMotion();
00657
00658 if (!paused)
00659 {
00660 previewp->mPauseRequest = NULL;
00661 }
00662 }
00663 }
00664
00665
00666
00667
00668 void LLFloaterAnimPreview::onCommitLoop(LLUICtrl* ctrl, void* data)
00669 {
00670 LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
00671
00672 if (!previewp->getEnabled()) return;
00673 LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
00674 LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID);
00675
00676 if (motionp)
00677 {
00678 motionp->setLoop(previewp->childGetValue("loop_check").asBoolean());
00679 motionp->setLoopIn((F32)previewp->childGetValue("loop_in_point").asReal() * 0.01f * motionp->getDuration());
00680 motionp->setLoopOut((F32)previewp->childGetValue("loop_out_point").asReal() * 0.01f * motionp->getDuration());
00681 }
00682 }
00683
00684
00685
00686
00687 void LLFloaterAnimPreview::onCommitLoopIn(LLUICtrl* ctrl, void* data)
00688 {
00689 LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
00690 if (!previewp->getEnabled()) return;
00691
00692 LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
00693 LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID);
00694
00695 if (motionp)
00696 {
00697 motionp->setLoopIn((F32)previewp->childGetValue("loop_in_point").asReal() / 100.f);
00698 previewp->resetMotion();
00699 previewp->childSetValue("loop_check", LLSD(TRUE));
00700 onCommitLoop(ctrl, data);
00701 }
00702 }
00703
00704
00705
00706
00707 void LLFloaterAnimPreview::onCommitLoopOut(LLUICtrl* ctrl, void* data)
00708 {
00709 LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
00710 if (!previewp->getEnabled()) return;
00711
00712 LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
00713 LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID);
00714
00715 if (motionp)
00716 {
00717 motionp->setLoopOut((F32)previewp->childGetValue("loop_out_point").asReal() * 0.01f * motionp->getDuration());
00718 previewp->resetMotion();
00719 previewp->childSetValue("loop_check", LLSD(TRUE));
00720 onCommitLoop(ctrl, data);
00721 }
00722 }
00723
00724
00725
00726
00727 void LLFloaterAnimPreview::onCommitName(LLUICtrl* ctrl, void* data)
00728 {
00729 LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
00730 if (!previewp->getEnabled()) return;
00731
00732 LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
00733 LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID);
00734
00735 if (motionp)
00736 {
00737 motionp->setName(previewp->childGetValue("name_form").asString());
00738 }
00739
00740 LLFloaterNameDesc::doCommit(ctrl, data);
00741 }
00742
00743
00744
00745
00746 void LLFloaterAnimPreview::onCommitHandPose(LLUICtrl* ctrl, void* data)
00747 {
00748 LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
00749 if (!previewp->getEnabled()) return;
00750
00751 LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
00752 LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID);
00753
00754 motionp->setHandPose(LLHandMotion::getHandPose(previewp->childGetValue("hand_pose_combo").asString()));
00755 previewp->resetMotion();
00756 }
00757
00758
00759
00760
00761 void LLFloaterAnimPreview::onCommitEmote(LLUICtrl* ctrl, void* data)
00762 {
00763 LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
00764 if (!previewp->getEnabled()) return;
00765
00766 LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
00767 LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID);
00768
00769 motionp->setEmote(previewp->mIDList[previewp->childGetValue("emote_combo").asString()]);
00770 previewp->resetMotion();
00771 }
00772
00773
00774
00775
00776 void LLFloaterAnimPreview::onCommitPriority(LLUICtrl* ctrl, void* data)
00777 {
00778 LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
00779 if (!previewp->getEnabled()) return;
00780
00781 LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
00782 LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID);
00783
00784 motionp->setPriority(llfloor((F32)previewp->childGetValue("priority").asReal()));
00785 }
00786
00787
00788
00789
00790 void LLFloaterAnimPreview::onCommitEaseIn(LLUICtrl* ctrl, void* data)
00791 {
00792 LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
00793 if (!previewp->getEnabled()) return;
00794
00795 LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
00796 LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID);
00797
00798 motionp->setEaseIn((F32)previewp->childGetValue("ease_in_time").asReal());
00799 previewp->resetMotion();
00800 }
00801
00802
00803
00804
00805 void LLFloaterAnimPreview::onCommitEaseOut(LLUICtrl* ctrl, void* data)
00806 {
00807 LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
00808 if (!previewp->getEnabled()) return;
00809
00810 LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
00811 LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID);
00812
00813 motionp->setEaseOut((F32)previewp->childGetValue("ease_out_time").asReal());
00814 previewp->resetMotion();
00815 }
00816
00817
00818
00819
00820 BOOL LLFloaterAnimPreview::validateEaseIn(LLUICtrl* spin, void* data)
00821 {
00822 LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
00823
00824 if (!previewp->getEnabled()) return FALSE;
00825
00826 LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
00827 LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID);
00828
00829 if (!motionp->getLoop())
00830 {
00831 F32 new_ease_in = llclamp((F32)previewp->childGetValue("ease_in_time").asReal(), 0.f, motionp->getDuration() - motionp->getEaseOutDuration());
00832 previewp->childSetValue("ease_in_time", LLSD(new_ease_in));
00833 }
00834
00835 return TRUE;
00836 }
00837
00838
00839
00840
00841 BOOL LLFloaterAnimPreview::validateEaseOut(LLUICtrl* spin, void* data)
00842 {
00843 LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
00844
00845 if (!previewp->getEnabled()) return FALSE;
00846
00847 LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar();
00848 LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(previewp->mMotionID);
00849
00850 if (!motionp->getLoop())
00851 {
00852 F32 new_ease_out = llclamp((F32)previewp->childGetValue("ease_out_time").asReal(), 0.f, motionp->getDuration() - motionp->getEaseInDuration());
00853 previewp->childSetValue("ease_out_time", LLSD(new_ease_out));
00854 }
00855
00856 return TRUE;
00857 }
00858
00859
00860
00861
00862 BOOL LLFloaterAnimPreview::validateLoopIn(LLUICtrl* ctrl, void* data)
00863 {
00864 LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
00865
00866 if (!previewp->getEnabled()) return FALSE;
00867
00868 F32 loop_in_value = (F32)previewp->childGetValue("loop_in_point").asReal();
00869 F32 loop_out_value = (F32)previewp->childGetValue("loop_out_point").asReal();
00870
00871 if (loop_in_value < 0.f)
00872 {
00873 loop_in_value = 0.f;
00874 }
00875 else if (loop_in_value > 100.f)
00876 {
00877 loop_in_value = 100.f;
00878 }
00879 else if (loop_in_value > loop_out_value)
00880 {
00881 loop_in_value = loop_out_value;
00882 }
00883
00884 previewp->childSetValue("loop_in_point", LLSD(loop_in_value));
00885 return TRUE;
00886 }
00887
00888
00889
00890
00891 BOOL LLFloaterAnimPreview::validateLoopOut(LLUICtrl* spin, void* data)
00892 {
00893 LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)data;
00894
00895 if (!previewp->getEnabled()) return FALSE;
00896
00897 F32 loop_out_value = (F32)previewp->childGetValue("loop_out_point").asReal();
00898 F32 loop_in_value = (F32)previewp->childGetValue("loop_in_point").asReal();
00899
00900 if (loop_out_value < 0.f)
00901 {
00902 loop_out_value = 0.f;
00903 }
00904 else if (loop_out_value > 100.f)
00905 {
00906 loop_out_value = 100.f;
00907 }
00908 else if (loop_out_value < loop_in_value)
00909 {
00910 loop_out_value = loop_in_value;
00911 }
00912
00913 previewp->childSetValue("loop_out_point", LLSD(loop_out_value));
00914 return TRUE;
00915 }
00916
00917
00918
00919
00920
00921 void LLFloaterAnimPreview::refresh()
00922 {
00923 if (!mAnimPreview)
00924 {
00925 childShow("bad_animation_text");
00926 mPlayButton->setEnabled(FALSE);
00927 mStopButton->setEnabled(FALSE);
00928 childDisable("ok_btn");
00929 }
00930 else
00931 {
00932 childHide("bad_animation_text");
00933 mPlayButton->setEnabled(TRUE);
00934 LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar();
00935 if (avatarp->isMotionActive(mMotionID))
00936 {
00937 mStopButton->setEnabled(TRUE);
00938 LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(mMotionID);
00939 if (avatarp->areAnimationsPaused())
00940 {
00941
00942 mPlayButton->setImages("button_anim_play.tga",
00943 "button_anim_play_selected.tga");
00944
00945 }
00946 else
00947 {
00948 if (motionp)
00949 {
00950 F32 fraction_complete;
00951 fraction_complete = motionp->getLastUpdateTime() / motionp->getDuration();
00952
00953 childSetValue("playback_slider", fraction_complete);
00954 mLastSliderValue = fraction_complete;
00955 }
00956 mPlayButton->setImages("button_anim_pause.tga",
00957 "button_anim_pause_selected.tga");
00958
00959 }
00960 }
00961 else
00962 {
00963 mPauseRequest = avatarp->requestPause();
00964 mPlayButton->setImages("button_anim_play.tga",
00965 "button_anim_play_selected.tga");
00966
00967 mStopButton->setEnabled(FALSE);
00968 }
00969 childEnable("ok_btn");
00970 mAnimPreview->requestUpdate();
00971 }
00972 }
00973
00974
00975
00976
00977 void LLFloaterAnimPreview::onBtnOK(void* userdata)
00978 {
00979 LLFloaterAnimPreview* floaterp = (LLFloaterAnimPreview*)userdata;
00980 if (!floaterp->getEnabled()) return;
00981
00982 if (floaterp->mAnimPreview)
00983 {
00984 LLKeyframeMotion* motionp = (LLKeyframeMotion*)floaterp->mAnimPreview->getDummyAvatar()->findMotion(floaterp->mMotionID);
00985
00986 S32 file_size = motionp->getFileSize();
00987 U8* buffer = new U8[file_size];
00988
00989 LLDataPackerBinaryBuffer dp(buffer, file_size);
00990 if (motionp->serialize(dp))
00991 {
00992 LLVFile file(gVFS, motionp->getID(), LLAssetType::AT_ANIMATION, LLVFile::APPEND);
00993
00994 S32 size = dp.getCurrentSize();
00995 file.setMaxSize(size);
00996 if (file.write((U8*)buffer, size))
00997 {
00998 std::string name = floaterp->childGetValue("name_form").asString();
00999 std::string desc = floaterp->childGetValue("description_form").asString();
01000 upload_new_resource(floaterp->mTransactionID,
01001 LLAssetType::AT_ANIMATION,
01002 name,
01003 desc,
01004 0,
01005 LLAssetType::AT_NONE,
01006 LLInventoryType::IT_ANIMATION,
01007 PERM_NONE,
01008 name);
01009 }
01010 else
01011 {
01012 llwarns << "Failure writing animation data." << llendl;
01013 gViewerWindow->alertXml("WriteAnimationFail");
01014 }
01015 }
01016
01017 delete [] buffer;
01018
01019 floaterp->mAnimPreview->getDummyAvatar()->removeMotion(floaterp->mMotionID);
01020 LLKeyframeDataCache::removeKeyframeData(floaterp->mMotionID);
01021 }
01022
01023 floaterp->close(false);
01024 }
01025
01026
01027
01028
01029 LLPreviewAnimation::LLPreviewAnimation(S32 width, S32 height) : LLDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE)
01030 {
01031 mNeedsUpdate = TRUE;
01032 mCameraDistance = PREVIEW_CAMERA_DISTANCE;
01033 mCameraYaw = 0.f;
01034 mCameraPitch = 0.f;
01035 mCameraZoom = 1.f;
01036
01037 mDummyAvatar = (LLVOAvatar*)gObjectList.createObjectViewer(LL_PCODE_LEGACY_AVATAR, gAgent.getRegion());
01038 mDummyAvatar->createDrawable(&gPipeline);
01039 mDummyAvatar->mIsDummy = TRUE;
01040 mDummyAvatar->mSpecialRenderMode = 1;
01041 mDummyAvatar->setPositionAgent(LLVector3::zero);
01042 mDummyAvatar->slamPosition();
01043 mDummyAvatar->updateJointLODs();
01044 mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable);
01045 mDummyAvatar->startMotion(ANIM_AGENT_STAND, 5.f);
01046 mDummyAvatar->mSkirtLOD.setVisible(FALSE, TRUE);
01047 gPipeline.markVisible(mDummyAvatar->mDrawable, *LLViewerCamera::getInstance());
01048
01049
01050 mDummyAvatar->stopMotion( ANIM_AGENT_HEAD_ROT, TRUE );
01051 mDummyAvatar->stopMotion( ANIM_AGENT_EYE, TRUE );
01052 mDummyAvatar->stopMotion( ANIM_AGENT_BODY_NOISE, TRUE );
01053 mDummyAvatar->stopMotion( ANIM_AGENT_BREATHE_ROT, TRUE );
01054 }
01055
01056
01057
01058
01059 LLPreviewAnimation::~LLPreviewAnimation()
01060 {
01061 mDummyAvatar->markDead();
01062 }
01063
01064
01065
01066
01067 BOOL LLPreviewAnimation::render()
01068 {
01069 mNeedsUpdate = FALSE;
01070 LLVOAvatar* avatarp = mDummyAvatar;
01071
01072 glMatrixMode(GL_PROJECTION);
01073 gGL.pushMatrix();
01074 glLoadIdentity();
01075 glOrtho(0.0f, mWidth, 0.0f, mHeight, -1.0f, 1.0f);
01076
01077 glMatrixMode(GL_MODELVIEW);
01078 gGL.pushMatrix();
01079 glLoadIdentity();
01080
01081 LLGLSUIDefault def;
01082 LLGLSNoTexture gls_no_texture;
01083 gGL.color4f(0.15f, 0.2f, 0.3f, 1.f);
01084
01085 gl_rect_2d_simple( mWidth, mHeight );
01086
01087 glMatrixMode(GL_PROJECTION);
01088 gGL.popMatrix();
01089
01090 glMatrixMode(GL_MODELVIEW);
01091 gGL.popMatrix();
01092
01093 gGL.flush();
01094
01095 LLVector3 target_pos = avatarp->mRoot.getWorldPosition();
01096
01097 LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) *
01098 LLQuaternion(mCameraYaw, LLVector3::z_axis);
01099
01100 LLQuaternion av_rot = avatarp->mRoot.getWorldRotation() * camera_rot;
01101 LLViewerCamera::getInstance()->setOriginAndLookAt(
01102 target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + mCameraOffset) * av_rot),
01103 LLVector3::z_axis,
01104 target_pos + (mCameraOffset * av_rot) );
01105
01106 LLViewerCamera::getInstance()->setView(LLViewerCamera::getInstance()->getDefaultFOV() / mCameraZoom);
01107 LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mWidth, mHeight, FALSE);
01108
01109 mCameraRelPos = LLViewerCamera::getInstance()->getOrigin() - avatarp->mHeadp->getWorldPosition();
01110
01111
01112
01113
01114
01115 avatarp->setTimeStep(0.f);
01116 if (avatarp->areAnimationsPaused())
01117 {
01118 avatarp->updateMotion(TRUE);
01119 }
01120 else
01121 {
01122 avatarp->updateMotion();
01123 }
01124
01125 LLVertexBuffer::unbind();
01126 avatarp->updateLOD();
01127
01128
01129 avatarp->mRoot.updateWorldMatrixChildren();
01130
01131 stop_glerror();
01132
01133 LLGLDepthTest gls_depth(GL_TRUE);
01134
01135 if (avatarp->mDrawable.notNull())
01136 {
01137 LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool();
01138 avatarPoolp->renderAvatars(avatarp);
01139 }
01140
01141 gGL.color4f(1,1,1,1);
01142 return TRUE;
01143 }
01144
01145
01146
01147
01148 void LLPreviewAnimation::requestUpdate()
01149 {
01150 mNeedsUpdate = TRUE;
01151 }
01152
01153
01154
01155
01156 void LLPreviewAnimation::rotate(F32 yaw_radians, F32 pitch_radians)
01157 {
01158 mCameraYaw = mCameraYaw + yaw_radians;
01159
01160 mCameraPitch = llclamp(mCameraPitch + pitch_radians, F_PI_BY_TWO * -0.8f, F_PI_BY_TWO * 0.8f);
01161 }
01162
01163
01164
01165
01166 void LLPreviewAnimation::zoom(F32 zoom_delta)
01167 {
01168 setZoom(mCameraZoom + zoom_delta);
01169 }
01170
01171
01172
01173
01174 void LLPreviewAnimation::setZoom(F32 zoom_amt)
01175 {
01176 mCameraZoom = llclamp(zoom_amt, MIN_CAMERA_ZOOM, MAX_CAMERA_ZOOM);
01177 }
01178
01179
01180
01181
01182 void LLPreviewAnimation::pan(F32 right, F32 up)
01183 {
01184 mCameraOffset.mV[VY] = llclamp(mCameraOffset.mV[VY] + right * mCameraDistance / mCameraZoom, -1.f, 1.f);
01185 mCameraOffset.mV[VZ] = llclamp(mCameraOffset.mV[VZ] + up * mCameraDistance / mCameraZoom, -1.f, 1.f);
01186 }
01187
01188
01189