aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llwearable.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/llwearable.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 '')
-rw-r--r--linden/indra/newview/llwearable.cpp971
1 files changed, 971 insertions, 0 deletions
diff --git a/linden/indra/newview/llwearable.cpp b/linden/indra/newview/llwearable.cpp
new file mode 100644
index 0000000..62a1d20
--- /dev/null
+++ b/linden/indra/newview/llwearable.cpp
@@ -0,0 +1,971 @@
1/**
2 * @file llwearable.cpp
3 * @brief LLWearable class implementation
4 *
5 * Copyright (c) 2002-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 "imageids.h"
31#include "llassetstorage.h"
32#include "lldbstrings.h"
33#include "lldir.h"
34#include "llquantize.h"
35
36#include "llagent.h"
37#include "llviewerwindow.h"
38#include "llfloatercustomize.h"
39#include "llinventorymodel.h"
40#include "llviewerimagelist.h"
41#include "llviewerinventory.h"
42#include "llvoavatar.h"
43#include "llwearable.h"
44
45//#include "viewer.h"
46//#include "llvfs.h"
47
48// static
49S32 LLWearable::sCurrentDefinitionVersion = 1;
50
51// static
52const char* LLWearable::sTypeName[ WT_COUNT ] =
53{
54 "shape",
55 "skin",
56 "hair",
57 "eyes",
58 "shirt",
59 "pants",
60 "shoes",
61 "socks",
62 "jacket",
63 "gloves",
64 "undershirt",
65 "underpants",
66 "skirt"
67};
68
69// static
70const char* LLWearable::sTypeLabel[ WT_COUNT ] =
71{
72 "Shape",
73 "Skin",
74 "Hair",
75 "Eyes",
76 "Shirt",
77 "Pants",
78 "Shoes",
79 "Socks",
80 "Jacket",
81 "Gloves",
82 "Undershirt",
83 "Underpants",
84 "Skirt"
85};
86
87
88// static
89LLAssetType::EType LLWearable::typeToAssetType(EWearableType wearable_type)
90{
91 switch( wearable_type )
92 {
93 case WT_SHAPE:
94 case WT_SKIN:
95 case WT_HAIR:
96 case WT_EYES:
97 return LLAssetType::AT_BODYPART;
98 case WT_SHIRT:
99 case WT_PANTS:
100 case WT_SHOES:
101 case WT_SOCKS:
102 case WT_JACKET:
103 case WT_GLOVES:
104 case WT_UNDERSHIRT:
105 case WT_UNDERPANTS:
106 case WT_SKIRT:
107 return LLAssetType::AT_CLOTHING;
108 default:
109 return LLAssetType::AT_NONE;
110 }
111}
112
113
114LLWearable::LLWearable(const LLTransactionID& transaction_id) :
115 mDefinitionVersion(LLWearable::sCurrentDefinitionVersion),
116 mType(WT_SHAPE)
117{
118 mTransactionID = transaction_id;
119 mAssetID = mTransactionID.makeAssetID(gAgent.getSecureSessionID());
120}
121
122LLWearable::LLWearable(const LLAssetID& asset_id) :
123 mDefinitionVersion( LLWearable::sCurrentDefinitionVersion ),
124 mType(WT_SHAPE)
125{
126 mAssetID = asset_id;
127 mTransactionID.setNull();
128}
129
130LLWearable::~LLWearable()
131{
132 mVisualParamMap.deleteAllData();
133 mTEMap.deleteAllData();
134}
135
136
137// static
138EWearableType LLWearable::typeNameToType( const LLString& type_name )
139{
140 for( S32 i = 0; i < WT_COUNT; i++ )
141 {
142 if( type_name == LLWearable::sTypeName[ i ] )
143 {
144 return (EWearableType)i;
145 }
146 }
147 return WT_INVALID;
148}
149
150
151const char* terse_F32_to_string( F32 f, char s[MAX_STRING] )
152{
153 char* r = s;
154 S32 len = sprintf( s, "%.2f", f );
155
156 // "1.20" -> "1.2"
157 // "24.00" -> "24."
158 while( '0' == r[len - 1] )
159 {
160 len--;
161 r[len] = '\0';
162 }
163
164 if( '.' == r[len - 1] )
165 {
166 // "24." -> "24"
167 len--;
168 r[len] = '\0';
169 }
170 else
171 if( ('-' == r[0]) && ('0' == r[1]) )
172 {
173 // "-0.59" -> "-.59"
174 r++;
175 r[0] = '-';
176 }
177 else
178 if( '0' == r[0] )
179 {
180 // "0.59" -> ".59"
181 r++;
182 }
183
184 return r;
185}
186
187BOOL LLWearable::exportFile( FILE* file )
188{
189 // header and version
190 if( fprintf( file, "LLWearable version %d\n", mDefinitionVersion ) < 0 )
191 {
192 return FALSE;
193 }
194
195 // name
196 if( fprintf( file, "%s\n", mName.c_str() ) < 0 )
197 {
198 return FALSE;
199 }
200
201 // description
202 if( fprintf( file, "%s\n", mDescription.c_str() ) < 0 )
203 {
204 return FALSE;
205 }
206
207 // permissions
208 if( !mPermissions.exportFile( file ) )
209 {
210 return FALSE;
211 }
212
213 // sale info
214 if( !mSaleInfo.exportFile( file ) )
215 {
216 return FALSE;
217 }
218
219 // wearable type
220 S32 type = (S32)mType;
221 if( fprintf( file, "type %d\n", type ) < 0 )
222 {
223 return FALSE;
224 }
225
226 // parameters
227 S32 num_parameters = mVisualParamMap.getLength();
228 if( fprintf( file, "parameters %d\n", num_parameters ) < 0 )
229 {
230 return FALSE;
231 }
232
233 char s[ MAX_STRING ];
234 for( F32* param_weightp = mVisualParamMap.getFirstData(); param_weightp; param_weightp = mVisualParamMap.getNextData() )
235 {
236 S32 param_id = mVisualParamMap.getCurrentKeyWithoutIncrement();
237 if( fprintf( file, "%d %s\n", param_id, terse_F32_to_string( *param_weightp, s ) ) < 0 )
238 {
239 return FALSE;
240 }
241 }
242
243 // texture entries
244 S32 num_textures = mTEMap.getLength();
245 if( fprintf( file, "textures %d\n", num_textures ) < 0 )
246 {
247 return FALSE;
248 }
249
250 for( LLUUID* image_id = mTEMap.getFirstData(); image_id; image_id = mTEMap.getNextData() )
251 {
252 S32 te = mTEMap.getCurrentKeyWithoutIncrement();
253 char image_id_string[UUID_STR_LENGTH];
254 image_id->toString( image_id_string );
255 if( fprintf( file, "%d %s\n", te, image_id_string) < 0 )
256 {
257 return FALSE;
258 }
259 }
260
261 return TRUE;
262}
263
264
265
266BOOL LLWearable::importFile( FILE* file )
267{
268 char text_buffer[2048];
269 S32 fields_read = 0;
270
271 // read header and version
272 fields_read = fscanf( file, "LLWearable version %d\n", &mDefinitionVersion );
273 if( fields_read != 1 )
274 {
275 // Shouldn't really log the asset id for security reasons, but
276 // we need it in this case.
277 llwarns << "Bad Wearable asset header: " << mAssetID << llendl;
278 //gVFS->dumpMap();
279 return FALSE;
280 }
281
282 if( mDefinitionVersion > LLWearable::sCurrentDefinitionVersion )
283 {
284 llwarns << "Wearable asset has newer version (" << mDefinitionVersion << ") than XML (" << LLWearable::sCurrentDefinitionVersion << ")" << llendl;
285 return FALSE;
286 }
287
288 // name
289 char next_char = fgetc( file );
290 if( '\n' == next_char )
291 {
292 // no name
293 mName = "";
294 }
295 else
296 {
297 ungetc( next_char, file );
298 fields_read = fscanf( file, "%[^\n]", text_buffer );
299 if( (1 != fields_read) || (fgetc( file ) != '\n') )
300 {
301 llwarns << "Bad Wearable asset: early end of file" << llendl;
302 return FALSE;
303 }
304 mName = text_buffer;
305 LLString::truncate(mName, DB_INV_ITEM_NAME_STR_LEN );
306 }
307
308 // description
309 next_char = fgetc( file );
310 if( '\n' == next_char )
311 {
312 // no description
313 mDescription = "";
314 }
315 else
316 {
317 ungetc( next_char, file );
318 fields_read = fscanf( file, "%[^\n]", text_buffer );
319 if( (1 != fields_read) || (fgetc( file ) != '\n') )
320 {
321 llwarns << "Bad Wearable asset: early end of file" << llendl;
322 return FALSE;
323 }
324 mDescription = text_buffer;
325 LLString::truncate(mDescription, DB_INV_ITEM_DESC_STR_LEN );
326 }
327
328 // permissions
329 S32 perm_version;
330 fields_read = fscanf( file, " permissions %d\n", &perm_version );
331 if( (fields_read != 1) || (perm_version != 0) )
332 {
333 llwarns << "Bad Wearable asset: missing permissions" << llendl;
334 return FALSE;
335 }
336 if( !mPermissions.importFile( file ) )
337 {
338 return FALSE;
339 }
340
341 // sale info
342 S32 sale_info_version;
343 fields_read = fscanf( file, " sale_info %d\n", &sale_info_version );
344 if( (fields_read != 1) || (sale_info_version != 0) )
345 {
346 llwarns << "Bad Wearable asset: missing sale_info" << llendl;
347 return FALSE;
348 }
349 // Sale info used to contain next owner perm. It is now in the
350 // permissions. Thus, we read that out, and fix legacy
351 // objects. It's possible this op would fail, but it should pick
352 // up the vast majority of the tasks.
353 BOOL has_perm_mask = FALSE;
354 U32 perm_mask = 0;
355 if( !mSaleInfo.importFile(file, has_perm_mask, perm_mask) )
356 {
357 return FALSE;
358 }
359 if(has_perm_mask)
360 {
361 // fair use fix.
362 if(!(perm_mask & PERM_COPY))
363 {
364 perm_mask |= PERM_TRANSFER;
365 }
366 mPermissions.setMaskNext(perm_mask);
367 }
368
369 // wearable type
370 S32 type = -1;
371 fields_read = fscanf( file, "type %d\n", &type );
372 if( fields_read != 1 )
373 {
374 llwarns << "Bad Wearable asset: bad type" << llendl;
375 return FALSE;
376 }
377 if( 0 <= type && type < WT_COUNT )
378 {
379 mType = (EWearableType)type;
380 }
381 else
382 {
383 llwarns << "Bad Wearable asset: bad type #" << type << llendl;
384 return FALSE;
385 }
386
387
388 // parameters header
389 S32 num_parameters = 0;
390 fields_read = fscanf( file, "parameters %d\n", &num_parameters );
391 if( fields_read != 1 )
392 {
393 llwarns << "Bad Wearable asset: missing parameters block" << llendl;
394 return FALSE;
395 }
396
397 // parameters
398 S32 i;
399 for( i = 0; i < num_parameters; i++ )
400 {
401 S32 param_id = 0;
402 F32 param_weight = 0.f;
403 fields_read = fscanf( file, "%d %f\n", &param_id, &param_weight );
404 if( fields_read != 2 )
405 {
406 llwarns << "Bad Wearable asset: bad parameter, #" << i << llendl;
407 return FALSE;
408 }
409 mVisualParamMap.addData( param_id, new F32(param_weight) );
410 }
411
412 // textures header
413 S32 num_textures = 0;
414 fields_read = fscanf( file, "textures %d\n", &num_textures);
415 if( fields_read != 1 )
416 {
417 llwarns << "Bad Wearable asset: missing textures block" << llendl;
418 return FALSE;
419 }
420
421 // textures
422 for( i = 0; i < num_textures; i++ )
423 {
424 S32 te = 0;
425 fields_read = fscanf( file, "%d %s\n", &te, text_buffer);
426 if( fields_read != 2 )
427 {
428 llwarns << "Bad Wearable asset: bad texture, #" << i << llendl;
429 return FALSE;
430 }
431
432 if( !LLUUID::validate( text_buffer ) )
433 {
434 llwarns << "Bad Wearable asset: bad texture uuid: " << text_buffer << llendl;
435 return FALSE;
436 }
437
438 mTEMap.addData( te, new LLUUID( text_buffer ) );
439 }
440
441 return TRUE;
442}
443
444
445// Avatar parameter and texture definitions can change over time.
446// This function returns true if parameters or textures have been added or removed
447// since this wearable was created.
448BOOL LLWearable::isOldVersion()
449{
450 LLVOAvatar* avatar = gAgent.getAvatarObject();
451 llassert( avatar );
452 if( !avatar )
453 {
454 return FALSE;
455 }
456
457 if( LLWearable::sCurrentDefinitionVersion < mDefinitionVersion )
458 {
459 llwarns << "Wearable asset has newer version (" << mDefinitionVersion << ") than XML (" << LLWearable::sCurrentDefinitionVersion << ")" << llendl;
460 llassert(0);
461 }
462
463 if( LLWearable::sCurrentDefinitionVersion != mDefinitionVersion )
464 {
465 return TRUE;
466 }
467
468 S32 param_count = 0;
469 for( LLViewerVisualParam* param = (LLViewerVisualParam*) avatar->getFirstVisualParam();
470 param;
471 param = (LLViewerVisualParam*) avatar->getNextVisualParam() )
472 {
473 if( (param->getWearableType() == mType) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) )
474 {
475 param_count++;
476 if( !mVisualParamMap.checkKey( param->getID() ) )
477 {
478 return TRUE;
479 }
480 }
481 }
482 if( param_count != mVisualParamMap.getLength() )
483 {
484 return TRUE;
485 }
486
487
488 S32 te_count = 0;
489 for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ )
490 {
491 if( LLVOAvatar::getTEWearableType( te ) == mType )
492 {
493 te_count++;
494 if( !mTEMap.checkKey( te ) )
495 {
496 return TRUE;
497 }
498 }
499 }
500 if( te_count != mTEMap.getLength() )
501 {
502 return TRUE;
503 }
504
505 return FALSE;
506}
507
508// Avatar parameter and texture definitions can change over time.
509// * If parameters or textures have been REMOVED since the wearable was created,
510// they're just ignored, so we consider the wearable clean even though isOldVersion()
511// will return true.
512// * If parameters or textures have been ADDED since the wearable was created,
513// they are taken to have default values, so we consider the wearable clean
514// only if those values are the same as the defaults.
515BOOL LLWearable::isDirty()
516{
517 LLVOAvatar* avatar = gAgent.getAvatarObject();
518 llassert( avatar );
519 if( !avatar )
520 {
521 return FALSE;
522 }
523
524
525 for( LLViewerVisualParam* param = (LLViewerVisualParam*) avatar->getFirstVisualParam();
526 param;
527 param = (LLViewerVisualParam*) avatar->getNextVisualParam() )
528 {
529 if( (param->getWearableType() == mType) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) )
530 {
531 F32* weightp = mVisualParamMap.getIfThere( param->getID() );
532 F32 weight;
533 if( weightp )
534 {
535 weight = llclamp( *weightp, param->getMinWeight(), param->getMaxWeight() );
536 }
537 else
538 {
539 weight = param->getDefaultWeight();
540 }
541
542 U8 a = F32_to_U8( param->getWeight(), param->getMinWeight(), param->getMaxWeight() );
543 U8 b = F32_to_U8( weight, param->getMinWeight(), param->getMaxWeight() );
544 if( a != b )
545 {
546 return TRUE;
547 }
548 }
549 }
550
551 for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ )
552 {
553 if( LLVOAvatar::getTEWearableType( te ) == mType )
554 {
555 LLViewerImage* avatar_image = avatar->getTEImage( te );
556 if( !avatar_image )
557 {
558 llassert( 0 );
559 continue;
560 }
561 LLUUID* mapped_image_id = mTEMap.getIfThere( te );
562 const LLUUID& image_id = mapped_image_id ? *mapped_image_id : LLVOAvatar::getDefaultTEImageID( te );
563 if( avatar_image->getID() != image_id )
564 {
565 return TRUE;
566 }
567 }
568 }
569
570 //if( gFloaterCustomize )
571 //{
572 // if( mDescription != gFloaterCustomize->getWearableDescription( mType ) )
573 // {
574 // return TRUE;
575 // }
576 //}
577
578 return FALSE;
579}
580
581
582void LLWearable::setParamsToDefaults()
583{
584 LLVOAvatar* avatar = gAgent.getAvatarObject();
585 llassert( avatar );
586 if( !avatar )
587 {
588 return;
589 }
590
591 mVisualParamMap.deleteAllData();
592 for( LLVisualParam* param = avatar->getFirstVisualParam(); param; param = avatar->getNextVisualParam() )
593 {
594 if( (((LLViewerVisualParam*)param)->getWearableType() == mType ) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) )
595 {
596 mVisualParamMap.addData( param->getID(), new F32( param->getDefaultWeight() ) );
597 }
598 }
599}
600
601void LLWearable::setTexturesToDefaults()
602{
603 mTEMap.deleteAllData();
604 for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ )
605 {
606 if( LLVOAvatar::getTEWearableType( te ) == mType )
607 {
608 mTEMap.addData( te, new LLUUID( LLVOAvatar::getDefaultTEImageID( te ) ) );
609 }
610 }
611}
612
613// Updates the user's avatar's appearance
614void LLWearable::writeToAvatar( BOOL set_by_user )
615{
616 LLVOAvatar* avatar = gAgent.getAvatarObject();
617 llassert( avatar );
618 if( !avatar )
619 {
620 return;
621 }
622
623 ESex old_sex = avatar->getSex();
624
625 // Pull params
626 for( LLVisualParam* param = avatar->getFirstVisualParam(); param; param = avatar->getNextVisualParam() )
627 {
628 if( (((LLViewerVisualParam*)param)->getWearableType() == mType) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) )
629 {
630 S32 param_id = param->getID();
631 F32* weight = mVisualParamMap.getIfThere( param_id );
632 if( weight )
633 {
634 // only animate with user-originated changes
635 if (set_by_user)
636 {
637 param->setAnimationTarget(*weight, set_by_user);
638 }
639 else
640 {
641 avatar->setVisualParamWeight( param_id, *weight, set_by_user );
642 }
643 }
644 else
645 {
646 // only animate with user-originated changes
647 if (set_by_user)
648 {
649 param->setAnimationTarget(param->getDefaultWeight(), set_by_user);
650 }
651 else
652 {
653 avatar->setVisualParamWeight( param_id, param->getDefaultWeight(), set_by_user );
654 }
655 }
656 }
657 }
658
659 // only interpolate with user-originated changes
660 if (set_by_user)
661 {
662 avatar->startAppearanceAnimation(TRUE, TRUE);
663 }
664
665 // Pull texture entries
666 for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ )
667 {
668 if( LLVOAvatar::getTEWearableType( te ) == mType )
669 {
670 LLUUID* mapped_image_id = mTEMap.getIfThere( te );
671 const LLUUID& image_id = mapped_image_id ? *mapped_image_id : LLVOAvatar::getDefaultTEImageID( te );
672 LLViewerImage* image = gImageList.getImage( image_id );
673 avatar->setLocTexTE( te, image, set_by_user );
674 }
675 }
676
677 avatar->updateVisualParams();
678
679 if( gFloaterCustomize )
680 {
681 LLViewerInventoryItem* item;
682 item = (LLViewerInventoryItem*)gInventory.getItem(gAgent.getWearableItem(mType));
683 U32 perm_mask = PERM_NONE;
684 BOOL is_complete = FALSE;
685 if(item)
686 {
687 perm_mask = item->getPermissions().getMaskOwner();
688 is_complete = item->isComplete();
689 if(!is_complete)
690 {
691 item->fetchFromServer();
692 }
693 }
694 gFloaterCustomize->setWearable(mType, this, perm_mask, is_complete);
695 LLFloaterCustomize::setCurrentWearableType( mType );
696 }
697
698 ESex new_sex = avatar->getSex();
699 if( old_sex != new_sex )
700 {
701 avatar->updateSexDependentLayerSets( set_by_user );
702 }
703
704 avatar->updateMeshTextures();
705
706// if( set_by_user )
707// {
708// gAgent.sendAgentSetAppearance();
709// }
710}
711
712// Updates the user's avatar's appearance, replacing this wearables' parameters and textures with default values.
713// static
714void LLWearable::removeFromAvatar( EWearableType type, BOOL set_by_user )
715{
716 LLVOAvatar* avatar = gAgent.getAvatarObject();
717 llassert( avatar );
718 if( !avatar )
719 {
720 return;
721 }
722
723 // You can't just remove body parts.
724 if( (type == WT_SHAPE) ||
725 (type == WT_SKIN) ||
726 (type == WT_HAIR) ||
727 (type == WT_EYES) )
728 {
729 return;
730 }
731
732 // Pull params
733 for( LLVisualParam* param = avatar->getFirstVisualParam(); param; param = avatar->getNextVisualParam() )
734 {
735 if( (((LLViewerVisualParam*)param)->getWearableType() == type) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) )
736 {
737 S32 param_id = param->getID();
738 avatar->setVisualParamWeight( param_id, param->getDefaultWeight(), set_by_user );
739 }
740 }
741
742 // Pull textures
743 LLViewerImage* image = gImageList.getImage( IMG_DEFAULT_AVATAR );
744 for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ )
745 {
746 if( LLVOAvatar::getTEWearableType( te ) == type )
747 {
748 avatar->setLocTexTE( te, image, set_by_user );
749 }
750 }
751
752 if( gFloaterCustomize )
753 {
754 gFloaterCustomize->setWearable(type, NULL, PERM_ALL, TRUE);
755 }
756
757 avatar->updateVisualParams();
758 avatar->updateMeshTextures();
759
760// if( set_by_user )
761// {
762// gAgent.sendAgentSetAppearance();
763// }
764}
765
766
767
768// Updates asset from the user's avatar
769void LLWearable::readFromAvatar()
770{
771 LLVOAvatar* avatar = gAgent.getAvatarObject();
772 llassert( avatar );
773 if( !avatar )
774 {
775 return;
776 }
777
778 mDefinitionVersion = LLWearable::sCurrentDefinitionVersion;
779
780 mVisualParamMap.deleteAllData();
781 for( LLVisualParam* param = avatar->getFirstVisualParam(); param; param = avatar->getNextVisualParam() )
782 {
783 if( (((LLViewerVisualParam*)param)->getWearableType() == mType) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) )
784 {
785 mVisualParamMap.addData( param->getID(), new F32( param->getWeight() ) );
786 }
787 }
788
789 mTEMap.deleteAllData();
790 for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ )
791 {
792 if( LLVOAvatar::getTEWearableType( te ) == mType )
793 {
794 LLViewerImage* image = avatar->getTEImage( te );
795 if( image )
796 {
797 mTEMap.addData( te, new LLUUID( image->getID() ) );
798 }
799 }
800 }
801
802 //if( gFloaterCustomize )
803 //{
804 // mDescription = gFloaterCustomize->getWearableDescription( mType );
805 //}
806}
807
808// Does not copy mAssetID.
809// Definition version is current: removes obsolete enties and creates default values for new ones.
810void LLWearable::copyDataFrom( LLWearable* src )
811{
812 LLVOAvatar* avatar = gAgent.getAvatarObject();
813 llassert( avatar );
814 if( !avatar )
815 {
816 return;
817 }
818
819 mDefinitionVersion = LLWearable::sCurrentDefinitionVersion;
820
821 mName = src->mName;
822 mDescription = src->mDescription;
823 mPermissions = src->mPermissions;
824 mSaleInfo = src->mSaleInfo;
825 mType = src->mType;
826
827 // Deep copy of mVisualParamMap (copies only those params that are current, filling in defaults where needed)
828 for( LLViewerVisualParam* param = (LLViewerVisualParam*) avatar->getFirstVisualParam();
829 param;
830 param = (LLViewerVisualParam*) avatar->getNextVisualParam() )
831 {
832 if( (param->getWearableType() == mType) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) )
833 {
834 S32 id = param->getID();
835 F32* weightp = src->mVisualParamMap.getIfThere( id );
836 F32 weight = weightp ? *weightp : param->getDefaultWeight();
837 mVisualParamMap.addData( id, new F32( weight ) );
838 }
839 }
840
841 // Deep copy of mTEMap (copies only those tes that are current, filling in defaults where needed)
842 for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ )
843 {
844 if( LLVOAvatar::getTEWearableType( te ) == mType )
845 {
846 LLUUID* mapped_image_id = src->mTEMap.getIfThere( te );
847 const LLUUID& image_id = mapped_image_id ? *mapped_image_id : LLVOAvatar::getDefaultTEImageID( te );
848 mTEMap.addData( te, new LLUUID( image_id ) );
849 }
850 }
851}
852
853struct LLWearableSaveData
854{
855 EWearableType mType;
856};
857
858void LLWearable::saveNewAsset()
859{
860// llinfos << "LLWearable::saveNewAsset() type: " << getTypeName() << llendl;
861 //dump();
862
863 char new_asset_id_string[UUID_STR_LENGTH];
864 mAssetID.toString(new_asset_id_string);
865 char filename[LL_MAX_PATH];
866 sprintf(filename, "%s.wbl", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,new_asset_id_string).c_str());
867 FILE* fp = LLFile::fopen(filename, "wb");
868 BOOL successful_save = FALSE;
869 if(fp && exportFile(fp))
870 {
871 successful_save = TRUE;
872 }
873 if(fp)
874 {
875 fclose(fp);
876 fp = NULL;
877 }
878 if(!successful_save)
879 {
880 char buffer[2*MAX_STRING];
881 sprintf(buffer,
882 "Unable to save '%s' to wearable file.",
883 mName.c_str());
884 llwarns << buffer << llendl;
885
886 LLStringBase<char>::format_map_t args;
887 args["[NAME]"] = mName;
888 gViewerWindow->alertXml("CannotSaveWearableOutOfSpace", args);
889 return;
890 }
891
892 // save it out to database
893 if( gAssetStorage )
894 {
895 LLWearableSaveData* data = new LLWearableSaveData;
896 data->mType = mType;
897 gAssetStorage->storeAssetData(filename, mTransactionID, getAssetType(),
898 &LLWearable::onSaveNewAssetComplete,
899 (void*)data);
900 }
901}
902
903// static
904void LLWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id, void* userdata, S32 status) // StoreAssetData callback (fixed)
905{
906 LLWearableSaveData* data = (LLWearableSaveData*)userdata;
907 const char* type_name = LLWearable::typeToTypeName(data->mType);
908 if(0 == status)
909 {
910 // Success
911 llinfos << "Saved wearable " << type_name << llendl;
912 }
913 else
914 {
915 char buffer[2*MAX_STRING];
916 sprintf(buffer,
917 "Unable to save %s to central asset store.",
918 type_name);
919 llwarns << buffer << " Status: " << status << llendl;
920 LLStringBase<char>::format_map_t args;
921 args["[NAME]"] = type_name;
922 gViewerWindow->alertXml("CannotSaveToAssetStore", args);
923 }
924
925 // Delete temp file
926 char new_asset_id_string[UUID_STR_LENGTH];
927 new_asset_id.toString(new_asset_id_string);
928 char src_filename[LL_MAX_PATH];
929 sprintf(src_filename, "%s.wbl", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,new_asset_id_string).c_str());
930 LLFile::remove(src_filename);
931
932 // delete the context data
933 delete data;
934}
935
936BOOL LLWearable::isMatchedToInventoryItem( LLViewerInventoryItem* item )
937{
938 return
939 ( mName == item->getName() ) &&
940 ( mDescription == item->getDescription() ) &&
941 ( mPermissions == item->getPermissions() ) &&
942 ( mSaleInfo == item->getSaleInfo() );
943}
944
945void LLWearable::dump()
946{
947 llinfos << "wearable " << LLWearable::typeToTypeName( mType ) << llendl;
948 llinfos << " Name: " << mName << llendl;
949 llinfos << " Desc: " << mDescription << llendl;
950 //mPermissions
951 //mSaleInfo
952
953 llinfos << " Params:" << llendl;
954 for( F32* param_weightp = mVisualParamMap.getFirstData();
955 param_weightp;
956 param_weightp = mVisualParamMap.getNextData() )
957 {
958 S32 param_id = mVisualParamMap.getCurrentKeyWithoutIncrement();
959 llinfos << " " << param_id << " " << *param_weightp << llendl;
960 }
961
962 llinfos << " Textures:" << llendl;
963 for( LLUUID* image_id = mTEMap.getFirstData();
964 image_id;
965 image_id = mTEMap.getNextData() )
966 {
967 S32 te = mTEMap.getCurrentKeyWithoutIncrement();
968 llinfos << " " << te << " " << *image_id << llendl;
969 }
970}
971