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