aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/lltexturectrl.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/lltexturectrl.cpp
parentREADME.txt (diff)
downloadmeta-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/lltexturectrl.cpp')
-rw-r--r--linden/indra/newview/lltexturectrl.cpp1387
1 files changed, 1387 insertions, 0 deletions
diff --git a/linden/indra/newview/lltexturectrl.cpp b/linden/indra/newview/lltexturectrl.cpp
new file mode 100644
index 0000000..9edd0ad
--- /dev/null
+++ b/linden/indra/newview/lltexturectrl.cpp
@@ -0,0 +1,1387 @@
1/**
2 * @file lltexturectrl.cpp
3 * @author Richard Nelson, James Cook
4 * @brief LLTextureCtrl class implementation including related functions
5 *
6 * Copyright (c) 2002-2007, Linden Research, Inc.
7 *
8 * The source code in this file ("Source Code") is provided by Linden Lab
9 * to you under the terms of the GNU General Public License, version 2.0
10 * ("GPL"), unless you have obtained a separate licensing agreement
11 * ("Other License"), formally executed by you and Linden Lab. Terms of
12 * the GPL can be found in doc/GPL-license.txt in this distribution, or
13 * online at http://secondlife.com/developers/opensource/gplv2
14 *
15 * There are special exceptions to the terms and conditions of the GPL as
16 * it is applied to this Source Code. View the full text of the exception
17 * in the file doc/FLOSS-exception.txt in this software distribution, or
18 * online at http://secondlife.com/developers/opensource/flossexception
19 *
20 * By copying, modifying or distributing this software, you acknowledge
21 * that you have read and understood your obligations described above,
22 * and agree to abide by those obligations.
23 *
24 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
25 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
26 * COMPLETENESS OR PERFORMANCE.
27 */
28
29#include "llviewerprecompiledheaders.h"
30
31#include "lltexturectrl.h"
32
33#include "llagent.h"
34#include "llviewerimagelist.h"
35#include "llcheckboxctrl.h"
36#include "llcombobox.h"
37#include "llbutton.h"
38#include "lldraghandle.h"
39#include "llfocusmgr.h"
40#include "llviewerimage.h"
41#include "llfolderview.h"
42#include "llinventory.h"
43#include "llinventorymodel.h"
44#include "llinventoryview.h"
45#include "lllineeditor.h"
46#include "llui.h"
47#include "llviewerinventory.h"
48#include "llpermissions.h"
49#include "llsaleinfo.h"
50#include "llassetstorage.h"
51#include "lltextbox.h"
52#include "llresizehandle.h"
53#include "llscrollcontainer.h"
54#include "lltoolmgr.h"
55#include "lltoolpipette.h"
56
57#include "lltool.h"
58#include "llviewerwindow.h"
59#include "llviewerobject.h"
60#include "llviewercontrol.h"
61#include "llglheaders.h"
62#include "llvieweruictrlfactory.h"
63
64
65static const S32 CLOSE_BTN_WIDTH = 100;
66const S32 PIPETTE_BTN_WIDTH = 32;
67static const S32 HPAD = 4;
68static const S32 VPAD = 4;
69static const S32 LINE = 16;
70static const S32 SMALL_BTN_WIDTH = 64;
71static const S32 TEX_PICKER_MIN_WIDTH =
72 (HPAD +
73 CLOSE_BTN_WIDTH +
74 HPAD +
75 CLOSE_BTN_WIDTH +
76 HPAD +
77 SMALL_BTN_WIDTH +
78 HPAD +
79 SMALL_BTN_WIDTH +
80 HPAD +
81 30 +
82 RESIZE_HANDLE_WIDTH * 2);
83static const S32 CLEAR_BTN_WIDTH = 50;
84static const S32 TEX_PICKER_MIN_HEIGHT = 290;
85static const S32 FOOTER_HEIGHT = 100;
86static const S32 BORDER_PAD = HPAD;
87static const S32 TEXTURE_INVENTORY_PADDING = 30;
88static const F32 CONTEXT_CONE_IN_ALPHA = 0.0f;
89static const F32 CONTEXT_CONE_OUT_ALPHA = 1.f;
90static const F32 CONTEXT_FADE_TIME = 0.08f;
91
92//static const char CURRENT_IMAGE_NAME[] = "Current Texture";
93//static const char WHITE_IMAGE_NAME[] = "Blank Texture";
94//static const char NO_IMAGE_NAME[] = "None";
95
96//////////////////////////////////////////////////////////////////////////////////////////
97// LLFloaterTexturePicker
98
99class LLFloaterTexturePicker : public LLFloater
100{
101public:
102 LLFloaterTexturePicker(
103 LLTextureCtrl* owner,
104 const LLRect& rect,
105 const std::string& label,
106 PermissionMask immediate_filter_perm_mask,
107 PermissionMask non_immediate_filter_perm_mask,
108 BOOL can_apply_immediately);
109 virtual ~LLFloaterTexturePicker();
110
111 // LLView overrides
112 virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
113 BOOL drop, EDragAndDropType cargo_type, void *cargo_data,
114 EAcceptance *accept,
115 LLString& tooltip_msg);
116 virtual void draw();
117
118 // LLFloater overrides
119 virtual void onClose(bool app_quitting);
120
121 // New functions
122 void setImageID( const LLUUID& image_asset_id);
123 void updateImageStats();
124 const LLUUID& getAssetID() { return mImageAssetID; }
125 const LLUUID& findItemID(const LLUUID& asset_id, BOOL copyable_only);
126 void setCanApplyImmediately(BOOL b);
127
128 void setDirty( BOOL b ) { mIsDirty = b; }
129 BOOL isDirty() { return mIsDirty; }
130 void setActive( BOOL active );
131
132 LLTextureCtrl* getOwner() const { return mOwner; }
133 void setOwner(LLTextureCtrl* owner) { mOwner = owner; }
134
135 void stopUsingPipette();
136 PermissionMask getFilterPermMask();
137 void updateFilterPermMask();
138 void commitIfImmediateSet();
139
140 static void onBtnSetToDefault( void* userdata );
141 static void onBtnSelect( void* userdata );
142 static void onBtnCancel( void* userdata );
143 static void onBtnPipette( void* userdata );
144 //static void onBtnRevert( void* userdata );
145 static void onBtnWhite( void* userdata );
146 static void onBtnNone( void* userdata );
147 static void onBtnClear( void* userdata );
148 static void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action, void* data);
149 static void onShowFolders(LLUICtrl* ctrl, void* userdata);
150 static void onApplyImmediateCheck(LLUICtrl* ctrl, void* userdata);
151 static void onSearchEdit(const LLString& search_string, void* user_data );
152 static void onTextureSelect( const LLTextureEntry& te, void *data );
153
154protected:
155 LLPointer<LLViewerImage> mTexturep;
156 LLTextureCtrl* mOwner;
157
158 LLUUID mImageAssetID; // Currently selected texture
159
160 LLUUID mWhiteImageAssetID;
161 LLUUID mSpecialCurrentImageAssetID; // Used when the asset id has no corresponding texture in the user's inventory.
162 LLUUID mOriginalImageAssetID;
163
164 LLTextBox* mTentativeLabel;
165 LLTextBox* mResolutionLabel;
166
167 LLString mPendingName;
168 BOOL mIsDirty;
169 BOOL mActive;
170
171 LLSearchEditor* mSearchEdit;
172 LLInventoryPanel* mInventoryPanel;
173 PermissionMask mImmediateFilterPermMask;
174 PermissionMask mNonImmediateFilterPermMask;
175 BOOL mCanApplyImmediately;
176 BOOL mNoCopyTextureSelected;
177 F32 mContextConeOpacity;
178};
179
180LLFloaterTexturePicker::LLFloaterTexturePicker(
181 LLTextureCtrl* owner,
182 const LLRect& rect,
183 const std::string& label,
184 PermissionMask immediate_filter_perm_mask,
185 PermissionMask non_immediate_filter_perm_mask,
186 BOOL can_apply_immediately)
187 :
188 LLFloater( "texture picker",
189 rect,
190 LLString( "Pick: " ) + label,
191 TRUE,
192 TEX_PICKER_MIN_WIDTH, TEX_PICKER_MIN_HEIGHT ),
193 mOwner( owner ),
194 mImageAssetID( owner->getImageAssetID() ),
195 mWhiteImageAssetID( gSavedSettings.getString( "UIImgWhiteUUID" ) ),
196 mOriginalImageAssetID(owner->getImageAssetID()),
197 mTentativeLabel(NULL),
198 mResolutionLabel(NULL),
199 mIsDirty( FALSE ),
200 mActive( TRUE ),
201 mSearchEdit(NULL),
202 mImmediateFilterPermMask(immediate_filter_perm_mask),
203 mNonImmediateFilterPermMask(non_immediate_filter_perm_mask),
204 mContextConeOpacity(0.f)
205{
206 gUICtrlFactory->buildFloater(this,"floater_texture_ctrl.xml");
207
208 mTentativeLabel = LLUICtrlFactory::getTextBoxByName(this,"Multiple");
209
210 mResolutionLabel = LLUICtrlFactory::getTextBoxByName(this,"unknown");
211
212
213 childSetAction("Default",LLFloaterTexturePicker::onBtnSetToDefault,this);
214 childSetAction("None", LLFloaterTexturePicker::onBtnNone,this);
215 childSetAction("Blank", LLFloaterTexturePicker::onBtnWhite,this);
216
217
218 childSetCommitCallback("show_folders_check", onShowFolders, this);
219 childSetVisible("show_folders_check", FALSE);
220
221 mSearchEdit = (LLSearchEditor*)getCtrlByNameAndType("inventory search editor", WIDGET_TYPE_SEARCH_EDITOR);
222 mSearchEdit->setSearchCallback(onSearchEdit, this);
223
224 mInventoryPanel = (LLInventoryPanel*)this->getCtrlByNameAndType("inventory panel", WIDGET_TYPE_INVENTORY_PANEL);
225
226 if(mInventoryPanel)
227 {
228 U32 filter_types = 0x0;
229 filter_types |= 0x1 << LLInventoryType::IT_TEXTURE;
230 filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT;
231
232 mInventoryPanel->setAutoSelectOverride(true);
233 mInventoryPanel->setFilterTypes(filter_types);
234 mInventoryPanel->setFilterPermMask(getFilterPermMask());
235 mInventoryPanel->setSelectCallback(onSelectionChange, this);
236 mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
237 mInventoryPanel->setAllowMultiSelect(FALSE);
238 // Commented out to stop opening all folders with textures
239 // mInventoryPanel->openDefaultFolderForType(LLAssetType::AT_TEXTURE);
240
241 // don't put keyboard focus on selected item, because the selection callback
242 // will assume that this was user input
243 mInventoryPanel->setSelection(findItemID(mImageAssetID, FALSE), TAKE_FOCUS_NO);
244 }
245
246 mCanApplyImmediately = can_apply_immediately;
247 mNoCopyTextureSelected = FALSE;
248
249 childSetValue("apply_immediate_check", gSavedSettings.getBOOL("ApplyTextureImmediately"));
250 childSetCommitCallback("apply_immediate_check", onApplyImmediateCheck, this);
251
252 if (!can_apply_immediately)
253 {
254 childSetEnabled("show_folders_check", FALSE);
255 }
256
257 childSetAction("Pipette", LLFloaterTexturePicker::onBtnPipette,this);
258 childSetAction("Cancel", LLFloaterTexturePicker::onBtnCancel,this);
259 childSetAction("Select", LLFloaterTexturePicker::onBtnSelect,this);
260
261 // update permission filter once UI is fully initialized
262 updateFilterPermMask();
263
264 setCanMinimize(FALSE);
265}
266
267LLFloaterTexturePicker::~LLFloaterTexturePicker()
268{
269}
270
271void LLFloaterTexturePicker::setImageID(const LLUUID& image_id)
272{
273 if( mImageAssetID != image_id && mActive)
274 {
275 mNoCopyTextureSelected = FALSE;
276 mIsDirty = TRUE;
277 mImageAssetID = image_id;
278 LLUUID item_id = findItemID(mImageAssetID, FALSE);
279 if (item_id.isNull())
280 {
281 mInventoryPanel->clearSelection();
282 }
283 else
284 {
285 LLInventoryItem* itemp = gInventory.getItem(image_id);
286 if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID()))
287 {
288 // no copy texture
289 childSetValue("apply_immediate_check", FALSE);
290 mNoCopyTextureSelected = TRUE;
291 }
292 mInventoryPanel->setSelection(item_id, TAKE_FOCUS_NO);
293 }
294 }
295}
296
297void LLFloaterTexturePicker::setActive( BOOL active )
298{
299 if (!active && childGetValue("Pipette").asBoolean())
300 {
301 stopUsingPipette();
302 }
303 mActive = active;
304}
305
306void LLFloaterTexturePicker::setCanApplyImmediately(BOOL b)
307{
308 mCanApplyImmediately = b;
309 if (!mCanApplyImmediately)
310 {
311 childSetValue("apply_immediate_check", FALSE);
312 }
313 updateFilterPermMask();
314}
315
316void LLFloaterTexturePicker::stopUsingPipette()
317{
318 if (gToolMgr && gToolMgr->getCurrentTool(gKeyboard->currentMask(TRUE)) == gToolPipette)
319 {
320 gToolMgr->clearTransientTool();
321 }
322}
323
324void LLFloaterTexturePicker::updateImageStats()
325{
326 if (mTexturep.notNull())
327 {
328 //RN: have we received header data for this image?
329 if (mTexturep->getWidth(0) > 0 && mTexturep->getHeight(0) > 0)
330 {
331 std::ostringstream formatted_dims;
332 formatted_dims << llformat("Dimensions: %d x %d", mTexturep->getWidth(0),mTexturep->getHeight(0));
333 mResolutionLabel->setText(formatted_dims.str());
334 }
335 else
336 {
337 mResolutionLabel->setText("Dimensions: unknown");
338 }
339 if (gAgent.isGodlike())
340 {
341 LLString tstring = "Pick: " + mTexturep->getID().getString();
342 setTitle(tstring);
343 }
344 }
345}
346
347// virtual
348BOOL LLFloaterTexturePicker::handleDragAndDrop(
349 S32 x, S32 y, MASK mask,
350 BOOL drop,
351 EDragAndDropType cargo_type, void *cargo_data,
352 EAcceptance *accept,
353 LLString& tooltip_msg)
354{
355 BOOL handled = FALSE;
356
357 if (cargo_type == DAD_TEXTURE)
358 {
359 LLInventoryItem *item = (LLInventoryItem *)cargo_data;
360
361 BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
362 BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
363 BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
364 gAgent.getID());
365
366 PermissionMask item_perm_mask = 0;
367 if (copy) item_perm_mask |= PERM_COPY;
368 if (mod) item_perm_mask |= PERM_MODIFY;
369 if (xfer) item_perm_mask |= PERM_TRANSFER;
370
371 PermissionMask filter_perm_mask = getFilterPermMask();
372 if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask )
373 {
374 if (drop)
375 {
376 setImageID( item->getAssetUUID() );
377 commitIfImmediateSet();
378 }
379
380 *accept = ACCEPT_YES_SINGLE;
381 }
382 else
383 {
384 *accept = ACCEPT_NO;
385 }
386 }
387 else
388 {
389 *accept = ACCEPT_NO;
390 }
391
392 handled = TRUE;
393 lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFloaterTexturePicker " << getName() << llendl;
394
395 return handled;
396}
397
398// virtual
399void LLFloaterTexturePicker::onClose(bool app_quitting)
400{
401 if (mOwner)
402 {
403 mOwner->onFloaterClose();
404 }
405 stopUsingPipette();
406 destroy();
407}
408
409// virtual
410void LLFloaterTexturePicker::draw()
411{
412 if (mOwner)
413 {
414 // draw cone of context pointing back to texture swatch
415 LLRect owner_rect;
416 mOwner->localRectToOtherView(mOwner->getLocalRect(), &owner_rect, this);
417 LLRect local_rect = getLocalRect();
418 if (gFocusMgr.childHasKeyboardFocus(this) && mOwner->isInVisibleChain() && mContextConeOpacity > 0.001f)
419 {
420 LLGLSNoTexture no_texture;
421 LLGLEnable(GL_CULL_FACE);
422 glBegin(GL_QUADS);
423 {
424 glColor4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
425 glVertex2i(owner_rect.mLeft, owner_rect.mTop);
426 glVertex2i(owner_rect.mRight, owner_rect.mTop);
427 glColor4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
428 glVertex2i(local_rect.mRight, local_rect.mTop);
429 glVertex2i(local_rect.mLeft, local_rect.mTop);
430
431 glColor4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
432 glVertex2i(local_rect.mLeft, local_rect.mTop);
433 glVertex2i(local_rect.mLeft, local_rect.mBottom);
434 glColor4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
435 glVertex2i(owner_rect.mLeft, owner_rect.mBottom);
436 glVertex2i(owner_rect.mLeft, owner_rect.mTop);
437
438 glColor4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
439 glVertex2i(local_rect.mRight, local_rect.mBottom);
440 glVertex2i(local_rect.mRight, local_rect.mTop);
441 glColor4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
442 glVertex2i(owner_rect.mRight, owner_rect.mTop);
443 glVertex2i(owner_rect.mRight, owner_rect.mBottom);
444
445
446 glColor4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
447 glVertex2i(local_rect.mLeft, local_rect.mBottom);
448 glVertex2i(local_rect.mRight, local_rect.mBottom);
449 glColor4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
450 glVertex2i(owner_rect.mRight, owner_rect.mBottom);
451 glVertex2i(owner_rect.mLeft, owner_rect.mBottom);
452 }
453 glEnd();
454 }
455 }
456
457 if (gFocusMgr.childHasMouseCapture(mDragHandle))
458 {
459 mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME));
460 }
461 else
462 {
463 mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME));
464 }
465
466 updateImageStats();
467
468 // if we're inactive, gray out "apply immediate" checkbox
469 childSetEnabled("show_folders_check", mActive && mCanApplyImmediately && !mNoCopyTextureSelected);
470 childSetEnabled("Select", mActive);
471 childSetEnabled("Pipette", gToolMgr != NULL && mActive);
472 childSetValue("Pipette", gToolMgr && gToolMgr->getCurrentTool(gKeyboard->currentMask(TRUE)) == gToolPipette);
473
474 //RN: reset search bar to reflect actual search query (all caps, for example)
475 mSearchEdit->setText(mInventoryPanel->getFilterSubString());
476
477 //BOOL allow_copy = FALSE;
478 if( getVisible() && mOwner)
479 {
480 mTexturep = NULL;
481 if(mImageAssetID.notNull())
482 {
483 mTexturep = gImageList.getImage(mImageAssetID, MIPMAP_YES, IMMEDIATE_NO);
484 mTexturep->setBoostLevel(LLViewerImage::BOOST_PREVIEW);
485 }
486
487 if (mTentativeLabel)
488 {
489 mTentativeLabel->setVisible( FALSE );
490 }
491
492 childSetEnabled("Default", mImageAssetID != mOwner->getDefaultImageAssetID());
493 childSetEnabled("Blank", mImageAssetID != mWhiteImageAssetID );
494 childSetEnabled("None", mOwner->getAllowNoTexture() && !mImageAssetID.isNull() );
495
496 LLFloater::draw();
497
498 if( isMinimized() )
499 {
500 return;
501 }
502
503 // Border
504 LLRect border( BORDER_PAD,
505 mRect.getHeight() - LLFLOATER_HEADER_SIZE - BORDER_PAD,
506 ((TEX_PICKER_MIN_WIDTH / 2) - TEXTURE_INVENTORY_PADDING - HPAD) - BORDER_PAD,
507 BORDER_PAD + FOOTER_HEIGHT + (mRect.getHeight() - TEX_PICKER_MIN_HEIGHT));
508 gl_rect_2d( border, LLColor4::black, FALSE );
509
510
511 // Interior
512 LLRect interior = border;
513 interior.stretch( -1 );
514
515 if( mTexturep )
516 {
517 if( mTexturep->getComponents() == 4 )
518 {
519 gl_rect_2d_checkerboard( interior );
520 }
521
522 gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep );
523
524 // Pump the priority
525 mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) );
526
527 // Draw Tentative Label over the image
528 if( mOwner->getTentative() && !mIsDirty )
529 {
530 mTentativeLabel->setVisible( TRUE );
531 drawChild(mTentativeLabel);
532 }
533 }
534 else
535 {
536 gl_rect_2d( interior, LLColor4::grey, TRUE );
537
538 // Draw X
539 gl_draw_x(interior, LLColor4::black );
540 }
541 }
542}
543
544// static
545/*
546void LLFloaterTexturePicker::onSaveAnotherCopyDialog( S32 option, void* userdata )
547{
548 LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
549 if( 0 == option )
550 {
551 self->copyToInventoryFinal();
552 }
553}
554*/
555
556const LLUUID& LLFloaterTexturePicker::findItemID(const LLUUID& asset_id, BOOL copyable_only)
557{
558 LLViewerInventoryCategory::cat_array_t cats;
559 LLViewerInventoryItem::item_array_t items;
560 LLAssetIDMatches asset_id_matches(asset_id);
561 gInventory.collectDescendentsIf(LLUUID::null,
562 cats,
563 items,
564 LLInventoryModel::INCLUDE_TRASH,
565 asset_id_matches);
566
567 if (items.count())
568 {
569 // search for copyable version first
570 for (S32 i = 0; i < items.count(); i++)
571 {
572 LLInventoryItem* itemp = items[i];
573 LLPermissions item_permissions = itemp->getPermissions();
574 if (item_permissions.allowCopyBy(gAgent.getID(), gAgent.getGroupID()))
575 {
576 return itemp->getUUID();
577 }
578 }
579 // otherwise just return first instance, unless copyable requested
580 if (copyable_only)
581 {
582 return LLUUID::null;
583 }
584 else
585 {
586 return items[0]->getUUID();
587 }
588 }
589
590 return LLUUID::null;
591}
592
593PermissionMask LLFloaterTexturePicker::getFilterPermMask()
594{
595 bool apply_immediate = childGetValue("apply_immediate_check").asBoolean();
596 return apply_immediate ? mImmediateFilterPermMask : mNonImmediateFilterPermMask;
597}
598
599void LLFloaterTexturePicker::commitIfImmediateSet()
600{
601 bool apply_immediate = childGetValue("apply_immediate_check").asBoolean();
602 if (!mNoCopyTextureSelected && apply_immediate && mOwner)
603 {
604 mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CHANGE);
605 }
606}
607
608// static
609void LLFloaterTexturePicker::onBtnSetToDefault(void* userdata)
610{
611 LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
612 if (self->mOwner)
613 {
614 self->setImageID( self->mOwner->getDefaultImageAssetID() );
615 }
616 self->commitIfImmediateSet();
617}
618
619// static
620void LLFloaterTexturePicker::onBtnWhite(void* userdata)
621{
622 LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
623 self->setImageID( self->mWhiteImageAssetID );
624 self->commitIfImmediateSet();
625}
626
627
628// static
629void LLFloaterTexturePicker::onBtnNone(void* userdata)
630{
631 LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
632 self->setImageID( LLUUID::null );
633 self->commitIfImmediateSet();
634}
635
636/*
637// static
638void LLFloaterTexturePicker::onBtnRevert(void* userdata)
639{
640 LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
641 self->setImageID( self->mOriginalImageAssetID );
642 // TODO: Change this to tell the owner to cancel. It needs to be
643 // smart enough to restore multi-texture selections.
644 self->mOwner->onFloaterCommit();
645 self->mIsDirty = FALSE;
646}*/
647
648// static
649void LLFloaterTexturePicker::onBtnCancel(void* userdata)
650{
651 LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
652 self->setImageID( self->mOriginalImageAssetID );
653 if (self->mOwner)
654 {
655 self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CANCEL);
656 }
657 self->mIsDirty = FALSE;
658 self->close();
659}
660
661// static
662void LLFloaterTexturePicker::onBtnSelect(void* userdata)
663{
664 LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
665 if (self->mOwner)
666 {
667 self->mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_SELECT);
668 }
669 self->close();
670}
671
672// static
673void LLFloaterTexturePicker::onBtnPipette( void* userdata )
674{
675 LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
676
677 if ( self && gToolMgr)
678 {
679 BOOL pipette_active = self->childGetValue("Pipette").asBoolean();
680 pipette_active = !pipette_active;
681 if (pipette_active)
682 {
683 gToolPipette->setSelectCallback(onTextureSelect, self);
684 gToolMgr->setTransientTool(gToolPipette);
685 }
686 else
687 {
688 gToolMgr->clearTransientTool();
689 }
690 }
691
692}
693
694// static
695void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action, void* data)
696{
697 LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)data;
698 if (items.size())
699 {
700 LLFolderViewItem* first_item = items.front();
701 LLInventoryItem* itemp = gInventory.getItem(first_item->getListener()->getUUID());
702 self->mNoCopyTextureSelected = FALSE;
703 if (itemp)
704 {
705 if (!itemp->getPermissions().allowCopyBy(gAgent.getID()))
706 {
707 self->mNoCopyTextureSelected = TRUE;
708 }
709 self->mImageAssetID = itemp->getAssetUUID();
710 self->mIsDirty = TRUE;
711 if (user_action)
712 {
713 // only commit intentional selections, not implicit ones
714 self->commitIfImmediateSet();
715 }
716 }
717 }
718}
719
720// static
721void LLFloaterTexturePicker::onShowFolders(LLUICtrl* ctrl, void *user_data)
722{
723 LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl;
724 LLFloaterTexturePicker* picker = (LLFloaterTexturePicker*)user_data;
725
726 if (check_box->get())
727 {
728 picker->mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
729 }
730 else
731 {
732 picker->mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NO_FOLDERS);
733 }
734}
735
736// static
737void LLFloaterTexturePicker::onApplyImmediateCheck(LLUICtrl* ctrl, void *user_data)
738{
739 LLFloaterTexturePicker* picker = (LLFloaterTexturePicker*)user_data;
740
741 LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl;
742 gSavedSettings.setBOOL("ApplyTextureImmediately", check_box->get());
743
744 picker->updateFilterPermMask();
745 picker->commitIfImmediateSet();
746}
747
748void LLFloaterTexturePicker::updateFilterPermMask()
749{
750 mInventoryPanel->setFilterPermMask( getFilterPermMask() );
751}
752
753void LLFloaterTexturePicker::onSearchEdit(const LLString& search_string, void* user_data )
754{
755 LLFloaterTexturePicker* picker = (LLFloaterTexturePicker*)user_data;
756
757 std::string filter_text = search_string;
758
759 if (filter_text.empty()&& picker->mInventoryPanel->getFilterSubString().empty())
760 {
761 // current filter and new filter empty, do nothing
762 return;
763 }
764 std::string upper_case_search_string = filter_text;
765 LLString::toUpper(upper_case_search_string);
766
767 picker->mInventoryPanel->setFilterSubString(upper_case_search_string);
768
769 LLFolderView* root_folder = picker->mInventoryPanel->getRootFolder();
770
771 //if (search_string.size())
772 //{
773 // LLSelectFirstFilteredItem filter;
774 // root_folder->applyFunctorRecursively(filter);
775 // //...and scroll to show it
776 // root_folder->scrollToShowSelection();
777 //}
778
779 KEY key = gKeyboard->currentKey();
780
781 if ((key == KEY_RETURN || key == KEY_DOWN) && gKeyboard->currentMask(FALSE) == MASK_NONE)
782 {
783 if (search_string.size())
784 {
785 LLSelectFirstFilteredItem filter;
786 root_folder->applyFunctorRecursively(filter);
787 //...and scroll to show it
788 root_folder->scrollToShowSelection();
789 }
790
791 if (!root_folder->getCurSelectedItem())
792 {
793 LLFolderViewItem* itemp = root_folder->getItemByID(gAgent.getInventoryRootID());
794 if (itemp)
795 {
796 root_folder->setSelection(itemp, FALSE, FALSE);
797 }
798 }
799
800 // move focus to inventory proper
801 root_folder->setFocus(TRUE);
802 root_folder->scrollToShowSelection();
803 }
804}
805
806//static
807void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te, void *data )
808{
809 LLFloaterTexturePicker* self = (LLFloaterTexturePicker*)data;
810
811 LLUUID inventory_item_id = self->findItemID(te.getID(), TRUE);
812 if (self && inventory_item_id.notNull())
813 {
814 gToolPipette->setResult(TRUE, "");
815 self->setImageID(te.getID());
816
817 self->mNoCopyTextureSelected = FALSE;
818 LLInventoryItem* itemp = gInventory.getItem(inventory_item_id);
819
820 if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID()))
821 {
822 // no copy texture
823 self->mNoCopyTextureSelected = TRUE;
824 }
825
826 self->commitIfImmediateSet();
827 }
828 else
829 {
830 gToolPipette->setResult(FALSE, "You do not have a copy this \nof texture in your inventory");
831 }
832}
833
834///////////////////////////////////////////////////////////////////////
835// LLTextureCtrl
836
837LLTextureCtrl::LLTextureCtrl(
838 const std::string& name,
839 const LLRect &rect,
840 const std::string& label,
841 const LLUUID &image_id,
842 const LLUUID &default_image_id,
843 const std::string& default_image_name )
844 :
845 LLUICtrl(name, rect, TRUE, NULL, NULL, FOLLOWS_LEFT | FOLLOWS_TOP),
846 mDragCallback(NULL),
847 mDropCallback(NULL),
848 mOnCancelCallback(NULL),
849 mOnSelectCallback(NULL),
850 mBorderColor( gColors.getColor("DefaultHighlightLight") ),
851 mImageAssetID( image_id ),
852 mDefaultImageAssetID( default_image_id ),
853 mDefaultImageName( default_image_name ),
854 mLabel( label ),
855 mAllowNoTexture( FALSE ),
856 mImmediateFilterPermMask( PERM_NONE ),
857 mNonImmediateFilterPermMask( PERM_NONE ),
858 mCanApplyImmediately( FALSE ),
859 mNeedsRawImageData( FALSE ),
860 mValid( TRUE )
861{
862 mCaption = new LLTextBox( label,
863 LLRect( 0, BTN_HEIGHT_SMALL, mRect.getWidth(), 0 ),
864 NULL,
865 LLFontGL::sSansSerifSmall );
866 mCaption->setFollows( FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_BOTTOM );
867 addChild( mCaption );
868
869 S32 image_top = mRect.getHeight();
870 S32 image_bottom = BTN_HEIGHT_SMALL;
871 S32 image_middle = (image_top + image_bottom) / 2;
872 S32 line_height = llround(LLFontGL::sSansSerifSmall->getLineHeight());
873
874 mTentativeLabel = new LLTextBox( "Multiple",
875 LLRect(
876 0, image_middle + line_height / 2,
877 mRect.getWidth(), image_middle - line_height / 2 ),
878 NULL,
879 LLFontGL::sSansSerifSmall );
880 mTentativeLabel->setHAlign( LLFontGL::HCENTER );
881 mTentativeLabel->setFollowsAll();
882 addChild( mTentativeLabel );
883
884 LLRect border_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
885 border_rect.mBottom += BTN_HEIGHT_SMALL;
886 mBorder = new LLViewBorder("border", border_rect, LLViewBorder::BEVEL_IN);
887 addChild(mBorder);
888
889 setEnabled(TRUE); // for the tooltip
890}
891
892
893LLTextureCtrl::~LLTextureCtrl()
894{
895 closeFloater();
896}
897
898// virtual
899LLXMLNodePtr LLTextureCtrl::getXML(bool save_children) const
900{
901 LLXMLNodePtr node = LLUICtrl::getXML();
902
903 node->createChild("label", TRUE)->setStringValue(getLabel());
904
905 node->createChild("default_image_name", TRUE)->setStringValue(getDefaultImageName());
906
907 node->createChild("allow_no_texture", TRUE)->setBoolValue(mAllowNoTexture);
908
909 node->createChild("can_apply_immediately", TRUE)->setBoolValue(mCanApplyImmediately );
910
911 return node;
912}
913
914LLView* LLTextureCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
915{
916 LLString name("texture_picker");
917 node->getAttributeString("name", name);
918
919 LLRect rect;
920 createRect(node, rect, parent);
921
922 LLString label;
923 node->getAttributeString("label", label);
924
925 LLString image_id("");
926 node->getAttributeString("image", image_id);
927
928 LLString default_image_id("");
929 node->getAttributeString("default_image", default_image_id);
930
931 LLString default_image_name("Default");
932 node->getAttributeString("default_image_name", default_image_name);
933
934 BOOL allow_no_texture = FALSE;
935 node->getAttributeBOOL("allow_no_texture", allow_no_texture);
936
937 BOOL can_apply_immediately = FALSE;
938 node->getAttributeBOOL("can_apply_immediately", can_apply_immediately);
939
940 if (label.empty())
941 {
942 label.assign(node->getValue());
943 }
944
945 LLTextureCtrl* texture_picker = new LLTextureCtrl(
946 name,
947 rect,
948 label,
949 LLUUID(image_id),
950 LLUUID(default_image_id),
951 default_image_name );
952 texture_picker->setAllowNoTexture(allow_no_texture);
953 texture_picker->setCanApplyImmediately(can_apply_immediately);
954
955 texture_picker->initFromXML(node, parent);
956
957 return texture_picker;
958}
959
960void LLTextureCtrl::setCaption(const LLString& caption)
961{
962 mCaption->setText( caption );
963}
964
965void LLTextureCtrl::setCanApplyImmediately(BOOL b)
966{
967 mCanApplyImmediately = b;
968 LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)LLFloater::getFloaterByHandle(mFloaterHandle);
969 if( floaterp )
970 {
971 floaterp->setCanApplyImmediately(b);
972 }
973}
974
975void LLTextureCtrl::setVisible( BOOL visible )
976{
977 if( !visible )
978 {
979 closeFloater();
980 }
981 LLUICtrl::setVisible( visible );
982}
983
984void LLTextureCtrl::setEnabled( BOOL enabled )
985{
986 if( enabled )
987 {
988 setToolTip( "Click to choose a picture" );
989 }
990 else
991 {
992 setToolTip( "" );
993 // *TODO: would be better to keep floater open and show
994 // disabled state.
995 closeFloater();
996 }
997
998 LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)LLFloater::getFloaterByHandle(mFloaterHandle);
999 if( floaterp )
1000 {
1001 floaterp->setActive(enabled);
1002 }
1003
1004 mCaption->setEnabled( enabled );
1005
1006 LLUICtrl::setEnabled( enabled );
1007}
1008
1009void LLTextureCtrl::setValid(BOOL valid )
1010{
1011 mValid = valid;
1012 if (!valid)
1013 {
1014 LLFloaterTexturePicker* pickerp = (LLFloaterTexturePicker*)LLFloater::getFloaterByHandle(mFloaterHandle);
1015 if (pickerp)
1016 {
1017 pickerp->setActive(FALSE);
1018 }
1019 }
1020}
1021
1022
1023// virtual
1024void LLTextureCtrl::clear()
1025{
1026 setImageAssetID(LLUUID::null);
1027}
1028
1029void LLTextureCtrl::setLabel(const LLString& label)
1030{
1031 mLabel = label;
1032 mCaption->setText(label);
1033}
1034
1035void LLTextureCtrl::showPicker(BOOL take_focus)
1036{
1037 LLFloater* floaterp = LLFloater::getFloaterByHandle(mFloaterHandle);
1038
1039 // Show the dialog
1040 if( floaterp )
1041 {
1042 floaterp->open( );
1043 }
1044 else
1045 {
1046 if( !mLastFloaterLeftTop.mX && !mLastFloaterLeftTop.mY )
1047 {
1048 gFloaterView->getNewFloaterPosition(&mLastFloaterLeftTop.mX, &mLastFloaterLeftTop.mY);
1049 }
1050 LLRect rect = gSavedSettings.getRect("TexturePickerRect");
1051 rect.translate( mLastFloaterLeftTop.mX - rect.mLeft, mLastFloaterLeftTop.mY - rect.mTop );
1052
1053 floaterp = new LLFloaterTexturePicker(
1054 this,
1055 rect,
1056 mLabel,
1057 mImmediateFilterPermMask,
1058 mNonImmediateFilterPermMask,
1059 mCanApplyImmediately);
1060 mFloaterHandle = floaterp->getHandle();
1061
1062 gFloaterView->getParentFloater(this)->addDependentFloater(floaterp);
1063 floaterp->open();
1064 }
1065
1066 if (take_focus)
1067 {
1068 floaterp->setFocus(TRUE);
1069 }
1070}
1071
1072
1073void LLTextureCtrl::closeFloater()
1074{
1075 LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)LLFloater::getFloaterByHandle(mFloaterHandle);
1076 if( floaterp )
1077 {
1078 floaterp->setOwner(NULL);
1079 floaterp->close();
1080 }
1081}
1082
1083// Allow us to download textures quickly when floater is shown
1084class LLTextureFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver
1085{
1086public:
1087 virtual void done()
1088 {
1089 // We need to find textures in all folders, so get the main
1090 // background download going.
1091 gInventory.startBackgroundFetch();
1092 gInventory.removeObserver(this);
1093 delete this;
1094 }
1095};
1096
1097BOOL LLTextureCtrl::handleHover(S32 x, S32 y, MASK mask)
1098{
1099 getWindow()->setCursor(UI_CURSOR_HAND);
1100 return TRUE;
1101}
1102
1103
1104BOOL LLTextureCtrl::handleMouseDown(S32 x, S32 y, MASK mask)
1105{
1106 BOOL handled = LLUICtrl::handleMouseDown( x, y , mask );
1107 if( handled )
1108 {
1109 showPicker(FALSE);
1110
1111 //grab textures first...
1112 gInventory.startBackgroundFetch(gInventory.findCategoryUUIDForType(LLAssetType::AT_TEXTURE));
1113 //...then start full inventory fetch.
1114 gInventory.startBackgroundFetch();
1115 }
1116 return handled;
1117}
1118
1119void LLTextureCtrl::onFloaterClose()
1120{
1121 LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)LLFloater::getFloaterByHandle(mFloaterHandle);
1122
1123 if (floaterp)
1124 {
1125 floaterp->setOwner(NULL);
1126 mLastFloaterLeftTop.set( floaterp->getRect().mLeft, floaterp->getRect().mTop );
1127 }
1128
1129 mFloaterHandle.markDead();
1130}
1131
1132void LLTextureCtrl::onFloaterCommit(ETexturePickOp op)
1133{
1134 LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)LLFloater::getFloaterByHandle(mFloaterHandle);
1135
1136 if( floaterp && mEnabled)
1137 {
1138 if( floaterp->isDirty() )
1139 {
1140 setTentative( FALSE );
1141 mImageItemID = floaterp->findItemID(floaterp->getAssetID(), FALSE);
1142 lldebugs << "mImageItemID: " << mImageItemID << llendl;
1143 mImageAssetID = floaterp->getAssetID();
1144 lldebugs << "mImageAssetID: " << mImageAssetID << llendl;
1145 if (op == TEXTURE_SELECT && mOnSelectCallback)
1146 {
1147 mOnSelectCallback(this, mCallbackUserData);
1148 }
1149 else if (op == TEXTURE_CANCEL && mOnCancelCallback)
1150 {
1151 mOnCancelCallback(this, mCallbackUserData);
1152 }
1153 else
1154 {
1155 onCommit();
1156 }
1157 }
1158 }
1159}
1160
1161void LLTextureCtrl::setImageAssetID( const LLUUID& asset_id )
1162{
1163 if( mImageAssetID != asset_id )
1164 {
1165 mImageItemID.setNull();
1166 mImageAssetID = asset_id;
1167 LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)LLFloater::getFloaterByHandle(mFloaterHandle);
1168 if( floaterp && getEnabled() )
1169 {
1170 floaterp->setImageID( asset_id );
1171 floaterp->setDirty( FALSE );
1172 }
1173 }
1174}
1175
1176BOOL LLTextureCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask,
1177 BOOL drop, EDragAndDropType cargo_type, void *cargo_data,
1178 EAcceptance *accept,
1179 LLString& tooltip_msg)
1180{
1181 BOOL handled = FALSE;
1182
1183 // this downcast may be invalid - but if the second test below
1184 // returns true, then the cast was valid, and we can perform
1185 // the third test without problems.
1186 LLInventoryItem* item = (LLInventoryItem*)cargo_data;
1187 if (mEnabled && (cargo_type == DAD_TEXTURE) && allowDrop(item))
1188 {
1189 if (drop)
1190 {
1191 if(doDrop(item))
1192 {
1193 // This removes the 'Multiple' overlay, since
1194 // there is now only one texture selected.
1195 setTentative( FALSE );
1196 onCommit();
1197 }
1198 }
1199
1200 *accept = ACCEPT_YES_SINGLE;
1201 }
1202 else
1203 {
1204 *accept = ACCEPT_NO;
1205 }
1206
1207 handled = TRUE;
1208 lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLTextureCtrl " << getName() << llendl;
1209
1210 return handled;
1211}
1212
1213void LLTextureCtrl::draw()
1214{
1215 if( getVisible() )
1216 {
1217 mBorder->setKeyboardFocusHighlight(hasFocus());
1218
1219 if (mImageAssetID.isNull() || !mValid)
1220 {
1221 mTexturep = NULL;
1222 }
1223 else
1224 {
1225 mTexturep = gImageList.getImage(mImageAssetID, MIPMAP_YES, IMMEDIATE_NO);
1226 mTexturep->setBoostLevel(LLViewerImage::BOOST_PREVIEW);
1227 }
1228
1229 // Border
1230 LLRect border( 0, mRect.getHeight(), mRect.getWidth(), BTN_HEIGHT_SMALL );
1231 gl_rect_2d( border, mBorderColor, FALSE );
1232
1233 // Interior
1234 LLRect interior = border;
1235 interior.stretch( -1 );
1236
1237 if( mTexturep )
1238 {
1239 if( mTexturep->getComponents() == 4 )
1240 {
1241 gl_rect_2d_checkerboard( interior );
1242 }
1243
1244 gl_draw_scaled_image( interior.mLeft, interior.mBottom, interior.getWidth(), interior.getHeight(), mTexturep);
1245 mTexturep->addTextureStats( (F32)(interior.getWidth() * interior.getHeight()) );
1246 }
1247 else
1248 {
1249 gl_rect_2d( interior, LLColor4::grey, TRUE );
1250
1251 // Draw X
1252 gl_draw_x( interior, LLColor4::black );
1253 }
1254
1255 mTentativeLabel->setVisible( !mTexturep.isNull() && mTentative );
1256
1257 LLUICtrl::draw();
1258 }
1259}
1260
1261BOOL LLTextureCtrl::allowDrop(LLInventoryItem* item)
1262{
1263 BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
1264 BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
1265 BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
1266 gAgent.getID());
1267
1268 PermissionMask item_perm_mask = 0;
1269 if (copy) item_perm_mask |= PERM_COPY;
1270 if (mod) item_perm_mask |= PERM_MODIFY;
1271 if (xfer) item_perm_mask |= PERM_TRANSFER;
1272
1273 PermissionMask filter_perm_mask = mCanApplyImmediately ?
1274 mImmediateFilterPermMask : mNonImmediateFilterPermMask;
1275 if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask )
1276 {
1277 if(mDragCallback)
1278 {
1279 return mDragCallback(this, item, mCallbackUserData);
1280 }
1281 else
1282 {
1283 return TRUE;
1284 }
1285 }
1286 else
1287 {
1288 return FALSE;
1289 }
1290}
1291
1292BOOL LLTextureCtrl::doDrop(LLInventoryItem* item)
1293{
1294 // call the callback if it exists.
1295 if(mDropCallback)
1296 {
1297 // if it returns TRUE, we return TRUE, and therefore the
1298 // commit is called above.
1299 return mDropCallback(this, item, mCallbackUserData);
1300 }
1301
1302 // no callback installed, so just set the image ids and carry on.
1303 setImageAssetID( item->getAssetUUID() );
1304 mImageItemID = item->getUUID();
1305 return TRUE;
1306}
1307
1308BOOL LLTextureCtrl::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_parent)
1309{
1310 if( getVisible() && mEnabled && !called_from_parent && ' ' == uni_char )
1311 {
1312 showPicker(TRUE);
1313 return TRUE;
1314 }
1315 return LLUICtrl::handleUnicodeCharHere(uni_char, called_from_parent);
1316}
1317
1318void LLTextureCtrl::setValue( LLSD value )
1319{
1320 setImageAssetID(value.asUUID());
1321}
1322
1323LLSD LLTextureCtrl::getValue() const
1324{
1325 return LLSD(getImageAssetID());
1326}
1327
1328
1329/////////////////////////////////////////////////////////////////////////////////
1330// LLToolTexEyedropper
1331
1332class LLToolTexEyedropper : public LLTool
1333{
1334public:
1335 LLToolTexEyedropper( void (*callback)(const LLUUID& obj_id, const LLUUID& image_id, void* userdata ), void* userdata );
1336 virtual ~LLToolTexEyedropper();
1337 virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
1338 virtual BOOL handleHover(S32 x, S32 y, MASK mask);
1339
1340protected:
1341 void (*mCallback)(const LLUUID& obj_id, const LLUUID& image_id, void* userdata );
1342 void* mCallbackUserData;
1343};
1344
1345
1346LLToolTexEyedropper::LLToolTexEyedropper(
1347 void (*callback)(const LLUUID& obj_id, const LLUUID& image_id, void* userdata ),
1348 void* userdata )
1349 : LLTool("texeyedropper"),
1350 mCallback( callback ),
1351 mCallbackUserData( userdata )
1352{
1353}
1354
1355LLToolTexEyedropper::~LLToolTexEyedropper()
1356{
1357}
1358
1359
1360BOOL LLToolTexEyedropper::handleMouseDown(S32 x, S32 y, MASK mask)
1361{
1362 LLViewerObject* hit_obj = gViewerWindow->lastObjectHit();
1363 if (hit_obj &&
1364 !hit_obj->isAvatar())
1365 {
1366 if( (0 <= gLastHitObjectFace) && (gLastHitObjectFace < hit_obj->getNumTEs()) )
1367 {
1368 LLViewerImage* image = hit_obj->getTEImage( gLastHitObjectFace );
1369 if( image )
1370 {
1371 if( mCallback )
1372 {
1373 mCallback( hit_obj->getID(), image->getID(), mCallbackUserData );
1374 }
1375 }
1376 }
1377 }
1378 return TRUE;
1379}
1380
1381BOOL LLToolTexEyedropper::handleHover(S32 x, S32 y, MASK mask)
1382{
1383 lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolTexEyedropper" << llendl;
1384 gViewerWindow->getWindow()->setCursor(UI_CURSOR_CROSS); // TODO: better cursor
1385 return TRUE;
1386}
1387