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