diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llfloaterimagepreview.cpp | |
parent | README.txt (diff) | |
download | meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2 meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz |
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/llfloaterimagepreview.cpp')
-rw-r--r-- | linden/indra/newview/llfloaterimagepreview.cpp | 698 |
1 files changed, 698 insertions, 0 deletions
diff --git a/linden/indra/newview/llfloaterimagepreview.cpp b/linden/indra/newview/llfloaterimagepreview.cpp new file mode 100644 index 0000000..c741bdb --- /dev/null +++ b/linden/indra/newview/llfloaterimagepreview.cpp | |||
@@ -0,0 +1,698 @@ | |||
1 | /** | ||
2 | * @file llfloaterimagepreview.cpp | ||
3 | * @brief LLFloaterImagePreview class implementation | ||
4 | * | ||
5 | * Copyright (c) 2004-2007, Linden Research, Inc. | ||
6 | * | ||
7 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
8 | * to you under the terms of the GNU General Public License, version 2.0 | ||
9 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
10 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
11 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
12 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
13 | * | ||
14 | * There are special exceptions to the terms and conditions of the GPL as | ||
15 | * it is applied to this Source Code. View the full text of the exception | ||
16 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
17 | * online at http://secondlife.com/developers/opensource/flossexception | ||
18 | * | ||
19 | * By copying, modifying or distributing this software, you acknowledge | ||
20 | * that you have read and understood your obligations described above, | ||
21 | * and agree to abide by those obligations. | ||
22 | * | ||
23 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
24 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
25 | * COMPLETENESS OR PERFORMANCE. | ||
26 | */ | ||
27 | |||
28 | #include "llviewerprecompiledheaders.h" | ||
29 | |||
30 | #include "llfloaterimagepreview.h" | ||
31 | |||
32 | #include "llimagebmp.h" | ||
33 | #include "llimagetga.h" | ||
34 | #include "llimagejpeg.h" | ||
35 | |||
36 | #include "llagent.h" | ||
37 | #include "llbutton.h" | ||
38 | #include "llcombobox.h" | ||
39 | #include "lldrawable.h" | ||
40 | #include "lldrawpoolavatar.h" | ||
41 | #include "llface.h" | ||
42 | #include "lltextbox.h" | ||
43 | #include "lltoolmgr.h" | ||
44 | #include "llui.h" | ||
45 | #include "llviewercamera.h" | ||
46 | #include "llviewerwindow.h" | ||
47 | #include "llvoavatar.h" | ||
48 | #include "pipeline.h" | ||
49 | #include "viewer.h" | ||
50 | #include "llvieweruictrlfactory.h" | ||
51 | |||
52 | //static | ||
53 | S32 LLFloaterImagePreview::sUploadAmount = 10; | ||
54 | |||
55 | const S32 PREVIEW_BORDER_WIDTH = 2; | ||
56 | const S32 PREVIEW_RESIZE_HANDLE_SIZE = S32(RESIZE_HANDLE_WIDTH * OO_SQRT2) + PREVIEW_BORDER_WIDTH; | ||
57 | const S32 PREVIEW_HPAD = PREVIEW_RESIZE_HANDLE_SIZE; | ||
58 | const S32 PREF_BUTTON_HEIGHT = 16; | ||
59 | const S32 PREVIEW_TEXTURE_HEIGHT = 300; | ||
60 | |||
61 | //----------------------------------------------------------------------------- | ||
62 | // LLFloaterImagePreview() | ||
63 | //----------------------------------------------------------------------------- | ||
64 | LLFloaterImagePreview::LLFloaterImagePreview(const char* filename) : | ||
65 | LLFloaterNameDesc(filename) | ||
66 | { | ||
67 | mLastMouseX = 0; | ||
68 | mLastMouseY = 0; | ||
69 | mGLName = 0; | ||
70 | loadImage(mFilenameAndPath.c_str()); | ||
71 | } | ||
72 | |||
73 | //----------------------------------------------------------------------------- | ||
74 | // postBuild() | ||
75 | //----------------------------------------------------------------------------- | ||
76 | BOOL LLFloaterImagePreview::postBuild() | ||
77 | { | ||
78 | if (!LLFloaterNameDesc::postBuild()) | ||
79 | { | ||
80 | return FALSE; | ||
81 | } | ||
82 | |||
83 | childSetLabelArg("ok_btn", "[AMOUNT]", llformat("%d",sUploadAmount)); | ||
84 | |||
85 | LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo"); | ||
86 | if (iface) | ||
87 | { | ||
88 | iface->selectFirstItem(); | ||
89 | } | ||
90 | childSetCommitCallback("clothing_type_combo", onPreviewTypeCommit, this); | ||
91 | |||
92 | mPreviewRect.set(PREVIEW_HPAD, | ||
93 | PREVIEW_TEXTURE_HEIGHT, | ||
94 | getRect().getWidth() - PREVIEW_HPAD, | ||
95 | PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); | ||
96 | mPreviewImageRect.set(0.f, 1.f, 1.f, 0.f); | ||
97 | |||
98 | childHide("bad_image_text"); | ||
99 | |||
100 | if (mRawImagep.notNull()) | ||
101 | { | ||
102 | mAvatarPreview = new LLImagePreviewAvatar(256, 256); | ||
103 | mAvatarPreview->setPreviewTarget("mPelvis", "mUpperBodyMesh0", mRawImagep, 2.f, FALSE); | ||
104 | } | ||
105 | else | ||
106 | { | ||
107 | mAvatarPreview = NULL; | ||
108 | childShow("bad_image_text"); | ||
109 | childDisable("clothing_type_combo"); | ||
110 | childDisable("ok_btn"); | ||
111 | } | ||
112 | |||
113 | return TRUE; | ||
114 | } | ||
115 | |||
116 | //----------------------------------------------------------------------------- | ||
117 | // LLFloaterImagePreview() | ||
118 | //----------------------------------------------------------------------------- | ||
119 | LLFloaterImagePreview::~LLFloaterImagePreview() | ||
120 | { | ||
121 | mRawImagep = NULL; | ||
122 | delete mAvatarPreview; | ||
123 | if (mGLName) | ||
124 | { | ||
125 | glDeleteTextures(1, &mGLName ); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | //static | ||
130 | //----------------------------------------------------------------------------- | ||
131 | // onPreviewTypeCommit() | ||
132 | //----------------------------------------------------------------------------- | ||
133 | void LLFloaterImagePreview::onPreviewTypeCommit(LLUICtrl* ctrl, void* userdata) | ||
134 | { | ||
135 | LLFloaterImagePreview *fp =(LLFloaterImagePreview *)userdata; | ||
136 | |||
137 | if (!fp->mAvatarPreview) | ||
138 | { | ||
139 | return; | ||
140 | } | ||
141 | |||
142 | S32 which_mode = 0; | ||
143 | |||
144 | LLCtrlSelectionInterface* iface = fp->childGetSelectionInterface("clothing_type_combo"); | ||
145 | if (iface) | ||
146 | { | ||
147 | which_mode = iface->getFirstSelectedIndex(); | ||
148 | } | ||
149 | |||
150 | switch(which_mode) | ||
151 | { | ||
152 | case 0: | ||
153 | break; | ||
154 | case 1: | ||
155 | fp->mAvatarPreview->setPreviewTarget("mSkull", "mHairMesh0", fp->mRawImagep, 0.4f, FALSE); | ||
156 | break; | ||
157 | case 2: | ||
158 | fp->mAvatarPreview->setPreviewTarget("mSkull", "mHeadMesh0", fp->mRawImagep, 0.4f, FALSE); | ||
159 | break; | ||
160 | case 3: | ||
161 | fp->mAvatarPreview->setPreviewTarget("mChest", "mUpperBodyMesh0", fp->mRawImagep, 1.0f, FALSE); | ||
162 | break; | ||
163 | case 4: | ||
164 | fp->mAvatarPreview->setPreviewTarget("mKneeLeft", "mLowerBodyMesh0", fp->mRawImagep, 1.2f, FALSE); | ||
165 | break; | ||
166 | case 5: | ||
167 | fp->mAvatarPreview->setPreviewTarget("mSkull", "mHeadMesh0", fp->mRawImagep, 0.4f, TRUE); | ||
168 | break; | ||
169 | case 6: | ||
170 | fp->mAvatarPreview->setPreviewTarget("mChest", "mUpperBodyMesh0", fp->mRawImagep, 1.2f, TRUE); | ||
171 | break; | ||
172 | case 7: | ||
173 | fp->mAvatarPreview->setPreviewTarget("mKneeLeft", "mLowerBodyMesh0", fp->mRawImagep, 1.2f, TRUE); | ||
174 | break; | ||
175 | case 8: | ||
176 | fp->mAvatarPreview->setPreviewTarget("mKneeLeft", "mSkirtMesh0", fp->mRawImagep, 1.3f, FALSE); | ||
177 | break; | ||
178 | default: | ||
179 | break; | ||
180 | } | ||
181 | fp->mAvatarPreview->refresh(); | ||
182 | //gViewerWindow->requestFastFrame(fp); | ||
183 | } | ||
184 | |||
185 | //----------------------------------------------------------------------------- | ||
186 | // draw() | ||
187 | //----------------------------------------------------------------------------- | ||
188 | void LLFloaterImagePreview::draw() | ||
189 | { | ||
190 | LLFloater::draw(); | ||
191 | LLRect r = getRect(); | ||
192 | |||
193 | if (mRawImagep.notNull()) | ||
194 | { | ||
195 | LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo"); | ||
196 | if (iface && iface->getFirstSelectedIndex() <= 0) | ||
197 | { | ||
198 | gl_rect_2d_checkerboard(mPreviewRect); | ||
199 | LLGLDisable gls_alpha(GL_ALPHA_TEST); | ||
200 | |||
201 | GLenum format_options[4] = { GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA }; | ||
202 | GLenum format = format_options[mRawImagep->getComponents()-1]; | ||
203 | |||
204 | GLenum internal_format_options[4] = { GL_LUMINANCE8, GL_LUMINANCE8_ALPHA8, GL_RGB8, GL_RGBA8 }; | ||
205 | GLenum internal_format = internal_format_options[mRawImagep->getComponents()-1]; | ||
206 | |||
207 | if (mGLName) | ||
208 | { | ||
209 | LLImageGL::bindExternalTexture( mGLName, 0, GL_TEXTURE_2D ); | ||
210 | } | ||
211 | else | ||
212 | { | ||
213 | glGenTextures(1, &mGLName ); | ||
214 | stop_glerror(); | ||
215 | |||
216 | LLImageGL::bindExternalTexture( mGLName, 0, GL_TEXTURE_2D ); | ||
217 | stop_glerror(); | ||
218 | |||
219 | glTexImage2D( | ||
220 | GL_TEXTURE_2D, 0, internal_format, | ||
221 | mRawImagep->getWidth(), mRawImagep->getHeight(), | ||
222 | 0, format, GL_UNSIGNED_BYTE, mRawImagep->getData()); | ||
223 | stop_glerror(); | ||
224 | |||
225 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||
226 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||
227 | |||
228 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||
229 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||
230 | if (mAvatarPreview) | ||
231 | { | ||
232 | mAvatarPreview->setTexture(mGLName); | ||
233 | } | ||
234 | } | ||
235 | |||
236 | glColor3f(1.f, 1.f, 1.f); | ||
237 | glBegin( GL_QUADS ); | ||
238 | { | ||
239 | glTexCoord2f(mPreviewImageRect.mLeft, mPreviewImageRect.mTop); | ||
240 | glVertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT); | ||
241 | glTexCoord2f(mPreviewImageRect.mLeft, mPreviewImageRect.mBottom); | ||
242 | glVertex2i(PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); | ||
243 | glTexCoord2f(mPreviewImageRect.mRight, mPreviewImageRect.mBottom); | ||
244 | glVertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); | ||
245 | glTexCoord2f(mPreviewImageRect.mRight, mPreviewImageRect.mTop); | ||
246 | glVertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT); | ||
247 | } | ||
248 | glEnd(); | ||
249 | |||
250 | LLImageGL::unbindTexture(0, GL_TEXTURE_2D); | ||
251 | |||
252 | stop_glerror(); | ||
253 | } | ||
254 | else | ||
255 | { | ||
256 | if (mAvatarPreview) | ||
257 | { | ||
258 | glColor3f(1.f, 1.f, 1.f); | ||
259 | mAvatarPreview->bindTexture(); | ||
260 | |||
261 | glBegin( GL_QUADS ); | ||
262 | { | ||
263 | glTexCoord2f(0.f, 1.f); | ||
264 | glVertex2i(PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT); | ||
265 | glTexCoord2f(0.f, 0.f); | ||
266 | glVertex2i(PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); | ||
267 | glTexCoord2f(1.f, 0.f); | ||
268 | glVertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_HPAD + PREF_BUTTON_HEIGHT + PREVIEW_HPAD); | ||
269 | glTexCoord2f(1.f, 1.f); | ||
270 | glVertex2i(r.getWidth() - PREVIEW_HPAD, PREVIEW_TEXTURE_HEIGHT); | ||
271 | } | ||
272 | glEnd(); | ||
273 | |||
274 | mAvatarPreview->unbindTexture(); | ||
275 | } | ||
276 | } | ||
277 | } | ||
278 | } | ||
279 | |||
280 | //----------------------------------------------------------------------------- | ||
281 | // loadImage() | ||
282 | //----------------------------------------------------------------------------- | ||
283 | bool LLFloaterImagePreview::loadImage(const char *src_filename) | ||
284 | { | ||
285 | // U32 length = strlen(src_filename); | ||
286 | const char* ext = strrchr(src_filename, '.'); | ||
287 | char error_message[MAX_STRING]; | ||
288 | error_message[0] = '\0'; | ||
289 | |||
290 | U32 codec = IMG_CODEC_INVALID; | ||
291 | LLString temp_str; | ||
292 | if( 0 == strnicmp(ext, ".bmp", 4) ) | ||
293 | { | ||
294 | codec = IMG_CODEC_BMP; | ||
295 | } | ||
296 | else if( 0 == strnicmp(ext, ".tga", 4) ) | ||
297 | { | ||
298 | codec = IMG_CODEC_TGA; | ||
299 | } | ||
300 | else if( 0 == strnicmp(ext, ".jpg", 4) || 0 == strnicmp(ext, ".jpeg", 5)) | ||
301 | { | ||
302 | codec = IMG_CODEC_JPEG; | ||
303 | } | ||
304 | |||
305 | LLPointer<LLImageRaw> raw_image = new LLImageRaw; | ||
306 | |||
307 | switch (codec) | ||
308 | { | ||
309 | case IMG_CODEC_BMP: | ||
310 | { | ||
311 | LLPointer<LLImageBMP> bmp_image = new LLImageBMP; | ||
312 | |||
313 | if (!bmp_image->load(src_filename)) | ||
314 | { | ||
315 | return false; | ||
316 | } | ||
317 | |||
318 | if (!bmp_image->decode(raw_image)) | ||
319 | { | ||
320 | return false; | ||
321 | } | ||
322 | } | ||
323 | break; | ||
324 | case IMG_CODEC_TGA: | ||
325 | { | ||
326 | LLPointer<LLImageTGA> tga_image = new LLImageTGA; | ||
327 | |||
328 | if (!tga_image->load(src_filename)) | ||
329 | { | ||
330 | return false; | ||
331 | } | ||
332 | |||
333 | if (!tga_image->decode(raw_image)) | ||
334 | { | ||
335 | return false; | ||
336 | } | ||
337 | |||
338 | if( (tga_image->getComponents() != 3) && | ||
339 | (tga_image->getComponents() != 4) ) | ||
340 | { | ||
341 | tga_image->setLastError( "Image files with less than 3 or more than 4 components are not supported." ); | ||
342 | return false; | ||
343 | } | ||
344 | } | ||
345 | break; | ||
346 | case IMG_CODEC_JPEG: | ||
347 | { | ||
348 | LLPointer<LLImageJPEG> jpeg_image = new LLImageJPEG; | ||
349 | |||
350 | if (!jpeg_image->load(src_filename)) | ||
351 | { | ||
352 | return false; | ||
353 | } | ||
354 | |||
355 | if (!jpeg_image->decode(raw_image)) | ||
356 | { | ||
357 | return false; | ||
358 | } | ||
359 | } | ||
360 | break; | ||
361 | default: | ||
362 | return false; | ||
363 | } | ||
364 | |||
365 | raw_image->biasedScaleToPowerOfTwo(1024); | ||
366 | mRawImagep = raw_image; | ||
367 | |||
368 | return true; | ||
369 | } | ||
370 | |||
371 | //----------------------------------------------------------------------------- | ||
372 | // handleMouseDown() | ||
373 | //----------------------------------------------------------------------------- | ||
374 | BOOL LLFloaterImagePreview::handleMouseDown(S32 x, S32 y, MASK mask) | ||
375 | { | ||
376 | if (mPreviewRect.pointInRect(x, y)) | ||
377 | { | ||
378 | bringToFront( x, y ); | ||
379 | gViewerWindow->setMouseCapture(this, onMouseCaptureLost); | ||
380 | gViewerWindow->hideCursor(); | ||
381 | mLastMouseX = x; | ||
382 | mLastMouseY = y; | ||
383 | return TRUE; | ||
384 | } | ||
385 | |||
386 | return LLFloater::handleMouseDown(x, y, mask); | ||
387 | } | ||
388 | |||
389 | //----------------------------------------------------------------------------- | ||
390 | // handleMouseUp() | ||
391 | //----------------------------------------------------------------------------- | ||
392 | BOOL LLFloaterImagePreview::handleMouseUp(S32 x, S32 y, MASK mask) | ||
393 | { | ||
394 | gViewerWindow->setMouseCapture(FALSE, NULL); | ||
395 | gViewerWindow->showCursor(); | ||
396 | return LLFloater::handleMouseUp(x, y, mask); | ||
397 | } | ||
398 | |||
399 | //----------------------------------------------------------------------------- | ||
400 | // handleHover() | ||
401 | //----------------------------------------------------------------------------- | ||
402 | BOOL LLFloaterImagePreview::handleHover(S32 x, S32 y, MASK mask) | ||
403 | { | ||
404 | MASK local_mask = mask & ~MASK_ALT; | ||
405 | |||
406 | if (mAvatarPreview && gViewerWindow->hasMouseCapture(this)) | ||
407 | { | ||
408 | if (local_mask == MASK_PAN) | ||
409 | { | ||
410 | // pan here | ||
411 | LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo"); | ||
412 | if (iface && iface->getFirstSelectedIndex() <= 0) | ||
413 | { | ||
414 | mPreviewImageRect.translate((F32)(x - mLastMouseX) * -0.005f * mPreviewImageRect.getWidth(), | ||
415 | (F32)(y - mLastMouseY) * -0.005f * mPreviewImageRect.getHeight()); | ||
416 | } | ||
417 | else | ||
418 | { | ||
419 | mAvatarPreview->pan((F32)(x - mLastMouseX) * -0.005f, (F32)(y - mLastMouseY) * -0.005f); | ||
420 | } | ||
421 | } | ||
422 | else if (local_mask == MASK_ORBIT) | ||
423 | { | ||
424 | F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f; | ||
425 | F32 pitch_radians = (F32)(y - mLastMouseY) * 0.02f; | ||
426 | |||
427 | mAvatarPreview->rotate(yaw_radians, pitch_radians); | ||
428 | } | ||
429 | else | ||
430 | { | ||
431 | LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo"); | ||
432 | if (iface && iface->getFirstSelectedIndex() <= 0) | ||
433 | { | ||
434 | F32 zoom_amt = (F32)(y - mLastMouseY) * -0.002f; | ||
435 | mPreviewImageRect.stretch(zoom_amt); | ||
436 | } | ||
437 | else | ||
438 | { | ||
439 | F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f; | ||
440 | F32 zoom_amt = (F32)(y - mLastMouseY) * 0.02f; | ||
441 | |||
442 | mAvatarPreview->rotate(yaw_radians, 0.f); | ||
443 | mAvatarPreview->zoom(zoom_amt); | ||
444 | } | ||
445 | } | ||
446 | |||
447 | LLCtrlSelectionInterface* iface = childGetSelectionInterface("clothing_type_combo"); | ||
448 | if (iface && iface->getFirstSelectedIndex() <= 0) | ||
449 | { | ||
450 | if (mPreviewImageRect.getWidth() > 1.f) | ||
451 | { | ||
452 | mPreviewImageRect.stretch((1.f - mPreviewImageRect.getWidth()) * 0.5f); | ||
453 | } | ||
454 | else if (mPreviewImageRect.getWidth() < 0.1f) | ||
455 | { | ||
456 | mPreviewImageRect.stretch((0.1f - mPreviewImageRect.getWidth()) * 0.5f); | ||
457 | } | ||
458 | |||
459 | if (mPreviewImageRect.getHeight() > 1.f) | ||
460 | { | ||
461 | mPreviewImageRect.stretch((1.f - mPreviewImageRect.getHeight()) * 0.5f); | ||
462 | } | ||
463 | else if (mPreviewImageRect.getHeight() < 0.1f) | ||
464 | { | ||
465 | mPreviewImageRect.stretch((0.1f - mPreviewImageRect.getHeight()) * 0.5f); | ||
466 | } | ||
467 | |||
468 | if (mPreviewImageRect.mLeft < 0.f) | ||
469 | { | ||
470 | mPreviewImageRect.translate(-mPreviewImageRect.mLeft, 0.f); | ||
471 | } | ||
472 | else if (mPreviewImageRect.mRight > 1.f) | ||
473 | { | ||
474 | mPreviewImageRect.translate(1.f - mPreviewImageRect.mRight, 0.f); | ||
475 | } | ||
476 | |||
477 | if (mPreviewImageRect.mBottom < 0.f) | ||
478 | { | ||
479 | mPreviewImageRect.translate(0.f, -mPreviewImageRect.mBottom); | ||
480 | } | ||
481 | else if (mPreviewImageRect.mTop > 1.f) | ||
482 | { | ||
483 | mPreviewImageRect.translate(0.f, 1.f - mPreviewImageRect.mTop); | ||
484 | } | ||
485 | } | ||
486 | else | ||
487 | { | ||
488 | mAvatarPreview->refresh(); | ||
489 | } | ||
490 | |||
491 | LLUI::setCursorPositionLocal(this, mLastMouseX, mLastMouseY); | ||
492 | //gViewerWindow->requestFastFrame(this); | ||
493 | } | ||
494 | |||
495 | if (!mPreviewRect.pointInRect(x, y) || !mAvatarPreview) | ||
496 | { | ||
497 | return LLFloater::handleHover(x, y, mask); | ||
498 | } | ||
499 | else if (local_mask == MASK_ORBIT) | ||
500 | { | ||
501 | gViewerWindow->setCursor(UI_CURSOR_TOOLCAMERA); | ||
502 | } | ||
503 | else if (local_mask == MASK_PAN) | ||
504 | { | ||
505 | gViewerWindow->setCursor(UI_CURSOR_TOOLPAN); | ||
506 | } | ||
507 | else | ||
508 | { | ||
509 | gViewerWindow->setCursor(UI_CURSOR_TOOLZOOMIN); | ||
510 | } | ||
511 | |||
512 | return TRUE; | ||
513 | } | ||
514 | |||
515 | //----------------------------------------------------------------------------- | ||
516 | // handleScrollWheel() | ||
517 | //----------------------------------------------------------------------------- | ||
518 | BOOL LLFloaterImagePreview::handleScrollWheel(S32 x, S32 y, S32 clicks) | ||
519 | { | ||
520 | if (mPreviewRect.pointInRect(x, y) && mAvatarPreview) | ||
521 | { | ||
522 | mAvatarPreview->zoom((F32)clicks * -0.2f); | ||
523 | mAvatarPreview->refresh(); | ||
524 | //gViewerWindow->requestFastFrame(this); | ||
525 | } | ||
526 | |||
527 | return TRUE; | ||
528 | } | ||
529 | |||
530 | //----------------------------------------------------------------------------- | ||
531 | // onMouseCaptureLost() | ||
532 | //----------------------------------------------------------------------------- | ||
533 | void LLFloaterImagePreview::onMouseCaptureLost(LLMouseHandler* handler) | ||
534 | { | ||
535 | gViewerWindow->showCursor(); | ||
536 | } | ||
537 | |||
538 | |||
539 | //----------------------------------------------------------------------------- | ||
540 | // LLImagePreviewAvatar | ||
541 | //----------------------------------------------------------------------------- | ||
542 | LLImagePreviewAvatar::LLImagePreviewAvatar(S32 width, S32 height) : LLDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE) | ||
543 | { | ||
544 | mNeedsUpdate = TRUE; | ||
545 | mTargetJoint = NULL; | ||
546 | mTargetMesh = NULL; | ||
547 | mCameraDistance = 0.f; | ||
548 | mCameraYaw = 0.f; | ||
549 | mCameraPitch = 0.f; | ||
550 | mCameraZoom = 1.f; | ||
551 | |||
552 | mDummyAvatar = new LLVOAvatar(LLUUID::null, LL_PCODE_LEGACY_AVATAR, gAgent.getRegion()); | ||
553 | mDummyAvatar->createDrawable(&gPipeline); | ||
554 | mDummyAvatar->mIsDummy = TRUE; | ||
555 | mDummyAvatar->mSpecialRenderMode = 2; | ||
556 | mDummyAvatar->setPositionAgent(LLVector3::zero); | ||
557 | mDummyAvatar->slamPosition(); | ||
558 | mDummyAvatar->updateJointLODs(); | ||
559 | mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable); | ||
560 | gPipeline.markVisible(mDummyAvatar->mDrawable); | ||
561 | |||
562 | mTextureName = 0; | ||
563 | } | ||
564 | |||
565 | LLImagePreviewAvatar::~LLImagePreviewAvatar() | ||
566 | { | ||
567 | mDummyAvatar->markDead(); | ||
568 | } | ||
569 | |||
570 | |||
571 | void LLImagePreviewAvatar::setPreviewTarget(const char* joint_name, const char* mesh_name, LLImageRaw* imagep, F32 distance, BOOL male) | ||
572 | { | ||
573 | mTargetJoint = mDummyAvatar->mRoot.findJoint(joint_name); | ||
574 | // clear out existing test mesh | ||
575 | if (mTargetMesh) | ||
576 | { | ||
577 | mTargetMesh->setTestTexture(0); | ||
578 | } | ||
579 | |||
580 | if (male) | ||
581 | { | ||
582 | mDummyAvatar->setVisualParamWeight( "male", 1.f ); | ||
583 | mDummyAvatar->updateVisualParams(); | ||
584 | mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable); | ||
585 | } | ||
586 | else | ||
587 | { | ||
588 | mDummyAvatar->setVisualParamWeight( "male", 0.f ); | ||
589 | mDummyAvatar->updateVisualParams(); | ||
590 | mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable); | ||
591 | } | ||
592 | mDummyAvatar->mRoot.setVisible(FALSE, TRUE); | ||
593 | |||
594 | mTargetMesh = (LLViewerJointMesh*)mDummyAvatar->mRoot.findJoint(mesh_name); | ||
595 | mTargetMesh->setTestTexture(mTextureName); | ||
596 | mTargetMesh->setVisible(TRUE, FALSE); | ||
597 | mCameraDistance = distance; | ||
598 | mCameraZoom = 1.f; | ||
599 | mCameraPitch = 0.f; | ||
600 | mCameraYaw = 0.f; | ||
601 | mCameraOffset.clearVec(); | ||
602 | } | ||
603 | |||
604 | //----------------------------------------------------------------------------- | ||
605 | // update() | ||
606 | //----------------------------------------------------------------------------- | ||
607 | BOOL LLImagePreviewAvatar::render() | ||
608 | { | ||
609 | mNeedsUpdate = FALSE; | ||
610 | LLVOAvatar* avatarp = mDummyAvatar; | ||
611 | |||
612 | glMatrixMode(GL_PROJECTION); | ||
613 | glPushMatrix(); | ||
614 | glLoadIdentity(); | ||
615 | glOrtho(0.0f, mWidth, 0.0f, mHeight, -1.0f, 1.0f); | ||
616 | |||
617 | glMatrixMode(GL_MODELVIEW); | ||
618 | glPushMatrix(); | ||
619 | glLoadIdentity(); | ||
620 | |||
621 | LLGLSUIDefault def; | ||
622 | glColor4f(0.15f, 0.2f, 0.3f, 1.f); | ||
623 | |||
624 | gl_rect_2d_simple( mWidth, mHeight ); | ||
625 | |||
626 | glMatrixMode(GL_PROJECTION); | ||
627 | glPopMatrix(); | ||
628 | |||
629 | glMatrixMode(GL_MODELVIEW); | ||
630 | glPopMatrix(); | ||
631 | |||
632 | LLVector3 target_pos = mTargetJoint->getWorldPosition(); | ||
633 | |||
634 | LLQuaternion camera_rot = LLQuaternion(mCameraPitch, LLVector3::y_axis) * | ||
635 | LLQuaternion(mCameraYaw, LLVector3::z_axis); | ||
636 | |||
637 | LLQuaternion av_rot = avatarp->mPelvisp->getWorldRotation() * camera_rot; | ||
638 | gCamera->setOriginAndLookAt( | ||
639 | target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + mCameraOffset) * av_rot), // camera | ||
640 | LLVector3::z_axis, // up | ||
641 | target_pos + (mCameraOffset * av_rot) ); // point of interest | ||
642 | |||
643 | stop_glerror(); | ||
644 | |||
645 | gCamera->setView(gCamera->getDefaultFOV() / mCameraZoom); | ||
646 | gCamera->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mWidth, mHeight, FALSE); | ||
647 | |||
648 | if (avatarp->mDrawable.notNull()) | ||
649 | { | ||
650 | LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); | ||
651 | // make sure alpha=0 shows avatar material color | ||
652 | LLGLDisable no_blend(GL_BLEND); | ||
653 | |||
654 | LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool(); | ||
655 | |||
656 | gPipeline.unbindAGP(); | ||
657 | avatarPoolp->syncAGP(); | ||
658 | if (avatarPoolp->canUseAGP() && gPipeline.usingAGP()) | ||
659 | { | ||
660 | gPipeline.bindAGP(); | ||
661 | } | ||
662 | avatarPoolp->renderAvatars(avatarp, TRUE); // renders only one avatar (no shaders) | ||
663 | } | ||
664 | |||
665 | return TRUE; | ||
666 | } | ||
667 | |||
668 | //----------------------------------------------------------------------------- | ||
669 | // refresh() | ||
670 | //----------------------------------------------------------------------------- | ||
671 | void LLImagePreviewAvatar::refresh() | ||
672 | { | ||
673 | mNeedsUpdate = TRUE; | ||
674 | } | ||
675 | |||
676 | //----------------------------------------------------------------------------- | ||
677 | // rotate() | ||
678 | //----------------------------------------------------------------------------- | ||
679 | void LLImagePreviewAvatar::rotate(F32 yaw_radians, F32 pitch_radians) | ||
680 | { | ||
681 | mCameraYaw = mCameraYaw + yaw_radians; | ||
682 | |||
683 | mCameraPitch = llclamp(mCameraPitch + pitch_radians, F_PI_BY_TWO * -0.8f, F_PI_BY_TWO * 0.8f); | ||
684 | } | ||
685 | |||
686 | //----------------------------------------------------------------------------- | ||
687 | // zoom() | ||
688 | //----------------------------------------------------------------------------- | ||
689 | void LLImagePreviewAvatar::zoom(F32 zoom_amt) | ||
690 | { | ||
691 | mCameraZoom = llclamp(mCameraZoom + zoom_amt, 1.f, 10.f); | ||
692 | } | ||
693 | |||
694 | void LLImagePreviewAvatar::pan(F32 right, F32 up) | ||
695 | { | ||
696 | mCameraOffset.mV[VY] = llclamp(mCameraOffset.mV[VY] + right * mCameraDistance / mCameraZoom, -1.f, 1.f); | ||
697 | mCameraOffset.mV[VZ] = llclamp(mCameraOffset.mV[VZ] + up * mCameraDistance / mCameraZoom, -1.f, 1.f); | ||
698 | } | ||