PageRenderTime 51ms CodeModel.GetById 1ms app.highlight 46ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llprimitive/lltextureentry.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 634 lines | 522 code | 60 blank | 52 comment | 143 complexity | 76a19f66c9d7c0bc92ed0ebb9806a600 MD5 | raw file
  1/** 
  2 * @file lltextureentry.cpp
  3 * @brief LLTextureEntry base class
  4 *
  5 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#include "linden_common.h"
 28
 29#include "lluuid.h"
 30#include "llmediaentry.h"
 31#include "lltextureentry.h"
 32#include "llsdutil_math.h"
 33#include "v4color.h"
 34
 35const U8 DEFAULT_BUMP_CODE = 0;  // no bump or shininess
 36
 37const LLTextureEntry LLTextureEntry::null;
 38
 39// Some LLSD keys.  Do not change these!
 40#define OBJECT_ID_KEY_STR "object_id"
 41#define TEXTURE_INDEX_KEY_STR "texture_index"
 42#define OBJECT_MEDIA_VERSION_KEY_STR "object_media_version"
 43#define OBJECT_MEDIA_DATA_KEY_STR "object_media_data"
 44#define TEXTURE_MEDIA_DATA_KEY_STR "media_data"
 45
 46/*static*/ const char* LLTextureEntry::OBJECT_ID_KEY = OBJECT_ID_KEY_STR;
 47/*static*/ const char* LLTextureEntry::OBJECT_MEDIA_DATA_KEY = OBJECT_MEDIA_DATA_KEY_STR;
 48/*static*/ const char* LLTextureEntry::MEDIA_VERSION_KEY = OBJECT_MEDIA_VERSION_KEY_STR;
 49/*static*/ const char* LLTextureEntry::TEXTURE_INDEX_KEY = TEXTURE_INDEX_KEY_STR;
 50/*static*/ const char* LLTextureEntry::TEXTURE_MEDIA_DATA_KEY = TEXTURE_MEDIA_DATA_KEY_STR;
 51
 52static const std::string MEDIA_VERSION_STRING_PREFIX = "x-mv:";
 53
 54// static 
 55LLTextureEntry* LLTextureEntry::newTextureEntry()
 56{
 57	return new LLTextureEntry();
 58}
 59
 60//===============================================================
 61LLTextureEntry::LLTextureEntry()
 62  : mMediaEntry(NULL)
 63{
 64	init(LLUUID::null,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE);
 65}
 66
 67LLTextureEntry::LLTextureEntry(const LLUUID& tex_id)
 68  : mMediaEntry(NULL)
 69{
 70	init(tex_id,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE);
 71}
 72
 73LLTextureEntry::LLTextureEntry(const LLTextureEntry &rhs)
 74  : mMediaEntry(NULL)
 75{
 76	mID = rhs.mID;
 77	mScaleS = rhs.mScaleS;
 78	mScaleT = rhs.mScaleT;
 79	mOffsetS = rhs.mOffsetS;
 80	mOffsetT = rhs.mOffsetT;
 81	mRotation = rhs.mRotation;
 82	mColor = rhs.mColor;
 83	mBump = rhs.mBump;
 84	mMediaFlags = rhs.mMediaFlags;
 85	mGlow = rhs.mGlow;
 86	if (rhs.mMediaEntry != NULL) {
 87		// Make a copy
 88		mMediaEntry = new LLMediaEntry(*rhs.mMediaEntry);
 89	}
 90}
 91
 92LLTextureEntry &LLTextureEntry::operator=(const LLTextureEntry &rhs)
 93{
 94	if (this != &rhs)
 95	{
 96		mID = rhs.mID;
 97		mScaleS = rhs.mScaleS;
 98		mScaleT = rhs.mScaleT;
 99		mOffsetS = rhs.mOffsetS;
100		mOffsetT = rhs.mOffsetT;
101		mRotation = rhs.mRotation;
102		mColor = rhs.mColor;
103		mBump = rhs.mBump;
104		mMediaFlags = rhs.mMediaFlags;
105		mGlow = rhs.mGlow;
106		if (mMediaEntry != NULL) {
107			delete mMediaEntry;
108		}
109		if (rhs.mMediaEntry != NULL) {
110			// Make a copy
111			mMediaEntry = new LLMediaEntry(*rhs.mMediaEntry);
112		}
113		else {
114			mMediaEntry = NULL;
115		}
116	}
117
118	return *this;
119}
120
121void LLTextureEntry::init(const LLUUID& tex_id, F32 scale_s, F32 scale_t, F32 offset_s, F32 offset_t, F32 rotation, U8 bump)
122{
123	setID(tex_id);
124
125	mScaleS = scale_s;
126	mScaleT = scale_t;
127	mOffsetS = offset_s;
128	mOffsetT = offset_t;
129	mRotation = rotation;
130	mBump = bump;
131	mMediaFlags = 0x0;
132    mGlow = 0;
133	
134	setColor(LLColor4(1.f, 1.f, 1.f, 1.f));
135	if (mMediaEntry != NULL) {
136	    delete mMediaEntry;
137	}
138	mMediaEntry = NULL;
139}
140
141LLTextureEntry::~LLTextureEntry()
142{
143	if(mMediaEntry)
144	{
145		delete mMediaEntry;
146		mMediaEntry = NULL;
147	}
148}
149
150bool LLTextureEntry::operator!=(const LLTextureEntry &rhs) const
151{
152	if (mID != rhs.mID) return(true);
153	if (mScaleS != rhs.mScaleS) return(true);
154	if (mScaleT != rhs.mScaleT) return(true);
155	if (mOffsetS != rhs.mOffsetS) return(true);
156	if (mOffsetT != rhs.mOffsetT) return(true);
157	if (mRotation != rhs.mRotation) return(true);
158	if (mColor != rhs.mColor) return (true);
159	if (mBump != rhs.mBump) return (true);
160	if (mMediaFlags != rhs.mMediaFlags) return (true);
161	if (mGlow != rhs.mGlow) return (true);
162	return(false);
163}
164
165bool LLTextureEntry::operator==(const LLTextureEntry &rhs) const
166{
167	if (mID != rhs.mID) return(false);
168	if (mScaleS != rhs.mScaleS) return(false);
169	if (mScaleT != rhs.mScaleT) return(false);
170	if (mOffsetS != rhs.mOffsetS) return(false);
171	if (mOffsetT != rhs.mOffsetT) return(false);
172	if (mRotation != rhs.mRotation) return(false);
173	if (mColor != rhs.mColor) return (false);
174	if (mBump != rhs.mBump) return (false);
175	if (mMediaFlags != rhs.mMediaFlags) return false;
176	if (mGlow != rhs.mGlow) return false;
177	return(true);
178}
179
180LLSD LLTextureEntry::asLLSD() const
181{
182	LLSD sd;
183	asLLSD(sd);
184	return sd;
185}
186
187void LLTextureEntry::asLLSD(LLSD& sd) const
188{
189	sd["imageid"] = mID;
190	sd["colors"] = ll_sd_from_color4(mColor);
191	sd["scales"] = mScaleS;
192	sd["scalet"] = mScaleT;
193	sd["offsets"] = mOffsetS;
194	sd["offsett"] = mOffsetT;
195	sd["imagerot"] = mRotation;
196	sd["bump"] = getBumpShiny();
197	sd["fullbright"] = getFullbright();
198	sd["media_flags"] = mMediaFlags;
199	if (hasMedia()) {
200		LLSD mediaData;
201        if (NULL != getMediaData()) {
202            getMediaData()->asLLSD(mediaData);
203        }
204		sd[TEXTURE_MEDIA_DATA_KEY] = mediaData;
205	}
206	sd["glow"] = mGlow;
207}
208
209bool LLTextureEntry::fromLLSD(const LLSD& sd)
210{
211	const char *w, *x;
212	w = "imageid";
213	if (sd.has(w))
214	{
215		setID( sd[w] );
216	} else goto fail;
217	w = "colors";
218	if (sd.has(w))
219	{
220		setColor( ll_color4_from_sd(sd["colors"]) );
221	} else goto fail;
222	w = "scales";
223	x = "scalet";
224	if (sd.has(w) && sd.has(x))
225	{
226		setScale( (F32)sd[w].asReal(), (F32)sd[x].asReal() );
227	} else goto fail;
228	w = "offsets";
229	x = "offsett";
230	if (sd.has(w) && sd.has(x))
231	{
232		setOffset( (F32)sd[w].asReal(), (F32)sd[x].asReal() );
233	} else goto fail;
234	w = "imagerot";
235	if (sd.has(w))
236	{
237		setRotation( (F32)sd[w].asReal() );
238	} else goto fail;
239	w = "bump";
240	if (sd.has(w))
241	{
242		setBumpShiny( sd[w].asInteger() );
243	} else goto fail;
244	w = "fullbright";
245	if (sd.has(w))
246	{
247		setFullbright( sd[w].asInteger() );
248	} else goto fail;
249	w = "media_flags";
250	if (sd.has(w))
251	{
252		setMediaTexGen( sd[w].asInteger() );
253	} else goto fail;
254	// If the "has media" flag doesn't match the fact that 
255	// media data exists, updateMediaData will "fix" it
256	// by either clearing or setting the flag
257	w = TEXTURE_MEDIA_DATA_KEY;
258	if (hasMedia() != sd.has(w))
259	{
260		llwarns << "LLTextureEntry::fromLLSD: media_flags (" << hasMedia() <<
261			") does not match presence of media_data (" << sd.has(w) << ").  Fixing." << llendl;
262	}
263	updateMediaData(sd[w]);
264
265	w = "glow";
266	if (sd.has(w))
267	{
268		setGlow((F32)sd[w].asReal() );
269	}
270
271	return true;
272fail:
273	return false;
274}
275
276// virtual 
277// override this method for each derived class
278LLTextureEntry* LLTextureEntry::newBlank() const
279{
280	return new LLTextureEntry();
281}
282
283// virtual 
284LLTextureEntry* LLTextureEntry::newCopy() const
285{
286	return new LLTextureEntry(*this);
287}
288
289S32 LLTextureEntry::setID(const LLUUID &tex_id)
290{
291	if (mID != tex_id)
292	{
293		mID = tex_id;
294		return TEM_CHANGE_TEXTURE;
295	}
296	return TEM_CHANGE_NONE;
297}
298
299S32 LLTextureEntry::setScale(F32 s, F32 t)
300{
301	S32 retval = 0;
302
303	if (  (mScaleS != s)
304		||(mScaleT != t))
305	{
306		mScaleS = s;
307		mScaleT = t;
308
309		retval = TEM_CHANGE_TEXTURE;
310	}
311	return retval;
312}
313
314S32 LLTextureEntry::setScaleS(F32 s)
315{
316	S32 retval = TEM_CHANGE_NONE;
317	if (mScaleS != s)
318	{
319		mScaleS = s;
320		retval = TEM_CHANGE_TEXTURE;
321	}
322	return retval;
323}
324
325S32 LLTextureEntry::setScaleT(F32 t)
326{
327	S32 retval = TEM_CHANGE_NONE;
328	if (mScaleT != t)
329	{
330		mScaleT = t;
331		retval = TEM_CHANGE_TEXTURE;
332	}
333	return retval;
334}
335
336S32 LLTextureEntry::setColor(const LLColor4 &color)
337{
338	if (mColor != color)
339	{
340		mColor = color;
341		return TEM_CHANGE_COLOR;
342	}
343	return TEM_CHANGE_NONE;
344}
345
346S32 LLTextureEntry::setColor(const LLColor3 &color)
347{
348	if (mColor != color)
349	{
350		// This preserves alpha.
351		mColor.setVec(color);
352		return TEM_CHANGE_COLOR;
353	}
354	return TEM_CHANGE_NONE;
355}
356
357S32 LLTextureEntry::setAlpha(const F32 alpha)
358{
359	if (mColor.mV[VW] != alpha)
360	{
361		mColor.mV[VW] = alpha;
362		return TEM_CHANGE_COLOR;
363	}
364	return TEM_CHANGE_NONE;
365}
366
367S32 LLTextureEntry::setOffset(F32 s, F32 t)
368{
369	S32 retval = 0;
370
371	if (  (mOffsetS != s)
372		||(mOffsetT != t))
373	{
374		mOffsetS = s;
375		mOffsetT = t;
376
377		retval = TEM_CHANGE_TEXTURE;
378	}
379	return retval;
380}
381
382S32 LLTextureEntry::setOffsetS(F32 s)
383{
384	S32 retval = 0;
385	if (mOffsetS != s)
386	{
387		mOffsetS = s;
388		retval = TEM_CHANGE_TEXTURE;
389	}
390	return retval;
391}
392
393S32 LLTextureEntry::setOffsetT(F32 t)
394{
395	S32 retval = 0;
396	if (mOffsetT != t)
397	{
398		mOffsetT = t;
399		retval = TEM_CHANGE_TEXTURE;
400	}
401	return retval;
402}
403
404S32 LLTextureEntry::setRotation(F32 theta)
405{
406	if (mRotation != theta && llfinite(theta))
407	{
408		mRotation = theta;
409		return TEM_CHANGE_TEXTURE;
410	}
411	return TEM_CHANGE_NONE;
412}
413
414S32 LLTextureEntry::setBumpShinyFullbright(U8 bump)
415{
416	if (mBump != bump)
417	{
418		mBump = bump;
419		return TEM_CHANGE_TEXTURE;
420	}
421	return TEM_CHANGE_NONE;
422}
423
424S32 LLTextureEntry::setMediaTexGen(U8 media)
425{
426	S32 result = TEM_CHANGE_NONE;
427	result |= setTexGen(media & TEM_TEX_GEN_MASK);
428	result |= setMediaFlags(media & TEM_MEDIA_MASK);
429	return result;
430}
431
432S32 LLTextureEntry::setBumpmap(U8 bump)
433{
434	bump &= TEM_BUMP_MASK;
435	if (getBumpmap() != bump)
436	{
437		mBump &= ~TEM_BUMP_MASK;
438		mBump |= bump;
439		return TEM_CHANGE_TEXTURE;
440	}
441	return TEM_CHANGE_NONE;
442}
443
444S32 LLTextureEntry::setFullbright(U8 fullbright)
445{
446	fullbright &= TEM_FULLBRIGHT_MASK;
447	if (getFullbright() != fullbright)
448	{
449		mBump &= ~(TEM_FULLBRIGHT_MASK<<TEM_FULLBRIGHT_SHIFT);
450		mBump |= fullbright << TEM_FULLBRIGHT_SHIFT;
451		return TEM_CHANGE_TEXTURE;
452	}
453	return TEM_CHANGE_NONE;
454}
455
456S32 LLTextureEntry::setShiny(U8 shiny)
457{
458	shiny &= TEM_SHINY_MASK;
459	if (getShiny() != shiny)
460	{
461		mBump &= ~(TEM_SHINY_MASK<<TEM_SHINY_SHIFT);
462		mBump |= shiny << TEM_SHINY_SHIFT;
463		return TEM_CHANGE_TEXTURE;
464	}
465	return TEM_CHANGE_NONE;
466}
467
468S32 LLTextureEntry::setBumpShiny(U8 bump_shiny)
469{
470	bump_shiny &= TEM_BUMP_SHINY_MASK;
471	if (getBumpShiny() != bump_shiny)
472	{
473		mBump &= ~TEM_BUMP_SHINY_MASK;
474		mBump |= bump_shiny;
475		return TEM_CHANGE_TEXTURE;
476	}
477	return TEM_CHANGE_NONE;
478}
479
480S32 LLTextureEntry::setMediaFlags(U8 media_flags)
481{
482	media_flags &= TEM_MEDIA_MASK;
483	if (getMediaFlags() != media_flags)
484	{
485		mMediaFlags &= ~TEM_MEDIA_MASK;
486		mMediaFlags |= media_flags;
487        
488		// Special code for media handling
489		if( hasMedia() && mMediaEntry == NULL)
490		{
491			mMediaEntry = new LLMediaEntry;
492		}
493        else if ( ! hasMedia() && mMediaEntry != NULL)
494        {
495            delete mMediaEntry;
496            mMediaEntry = NULL;
497        }
498        
499		return TEM_CHANGE_MEDIA;
500	}
501	return TEM_CHANGE_NONE;
502}
503
504S32 LLTextureEntry::setTexGen(U8 tex_gen)
505{
506	tex_gen &= TEM_TEX_GEN_MASK;
507	if (getTexGen() != tex_gen)
508	{
509		mMediaFlags &= ~TEM_TEX_GEN_MASK;
510		mMediaFlags |= tex_gen;
511		return TEM_CHANGE_TEXTURE;
512	}
513	return TEM_CHANGE_NONE;
514}
515
516S32 LLTextureEntry::setGlow(F32 glow)
517{
518	if (mGlow != glow)
519	{
520		mGlow = glow;
521		return TEM_CHANGE_TEXTURE;
522	}
523	return TEM_CHANGE_NONE;
524}
525
526void LLTextureEntry::setMediaData(const LLMediaEntry &media_entry)
527{
528    mMediaFlags |= MF_HAS_MEDIA;
529    if (NULL != mMediaEntry)
530    {
531        delete mMediaEntry;
532    }
533    mMediaEntry = new LLMediaEntry(media_entry);
534}
535
536bool LLTextureEntry::updateMediaData(const LLSD& media_data)
537{
538	if (media_data.isUndefined())
539	{
540		// clear the media data
541        clearMediaData();
542		return false;
543	}
544	else {
545		mMediaFlags |= MF_HAS_MEDIA;
546		if (mMediaEntry == NULL)
547		{
548			mMediaEntry = new LLMediaEntry;
549		}
550        // *NOTE: this will *clobber* all of the fields in mMediaEntry 
551        // with whatever fields are present (or not present) in media_data!
552 		mMediaEntry->fromLLSD(media_data);
553		return true;
554	}
555}
556
557void LLTextureEntry::clearMediaData()
558{
559    mMediaFlags &= ~MF_HAS_MEDIA;
560    if (mMediaEntry != NULL) {
561        delete mMediaEntry;
562    }
563    mMediaEntry = NULL;
564}    
565
566void LLTextureEntry::mergeIntoMediaData(const LLSD& media_fields)
567{
568    mMediaFlags |= MF_HAS_MEDIA;
569    if (mMediaEntry == NULL)
570    {
571        mMediaEntry = new LLMediaEntry;
572    }
573    // *NOTE: this will *merge* the data in media_fields
574    // with the data in our media entry
575    mMediaEntry->mergeFromLLSD(media_fields);
576}
577
578//static
579std::string LLTextureEntry::touchMediaVersionString(const std::string &in_version, const LLUUID &agent_id)
580{
581    // XXX TODO: make media version string binary (base64-encoded?)
582    // Media "URL" is a representation of a version and the last-touched agent
583    // x-mv:nnnnn/agent-id
584    // where "nnnnn" is version number
585    // *NOTE: not the most efficient code in the world...
586    U32 current_version = getVersionFromMediaVersionString(in_version) + 1;
587    const size_t MAX_VERSION_LEN = 10; // 2^32 fits in 10 decimal digits
588    char buf[MAX_VERSION_LEN+1];
589    snprintf(buf, (int)MAX_VERSION_LEN+1, "%0*u", (int)MAX_VERSION_LEN, current_version);  // added int cast to fix warning/breakage on mac.
590    return MEDIA_VERSION_STRING_PREFIX + buf + "/" + agent_id.asString();
591}
592
593//static
594U32 LLTextureEntry::getVersionFromMediaVersionString(const std::string &version_string)
595{
596    U32 version = 0;
597    if (!version_string.empty()) 
598    {
599        size_t found = version_string.find(MEDIA_VERSION_STRING_PREFIX);
600        if (found != std::string::npos) 
601        {
602            found = version_string.find_first_of("/", found);
603            std::string v = version_string.substr(MEDIA_VERSION_STRING_PREFIX.length(), found);
604            version = strtoul(v.c_str(),NULL,10);
605        }
606    }
607    return version;
608}
609
610//static
611LLUUID LLTextureEntry::getAgentIDFromMediaVersionString(const std::string &version_string)
612{
613    LLUUID id;
614    if (!version_string.empty()) 
615    {
616        size_t found = version_string.find(MEDIA_VERSION_STRING_PREFIX);
617        if (found != std::string::npos) 
618        {
619            found = version_string.find_first_of("/", found);
620            if (found != std::string::npos) 
621            {
622                std::string v = version_string.substr(found + 1);
623                id.set(v);
624            }
625        }
626    }
627    return id;
628}
629
630//static
631bool LLTextureEntry::isMediaVersionString(const std::string &version_string)
632{
633	return std::string::npos != version_string.find(MEDIA_VERSION_STRING_PREFIX);
634}