From bc1df4b1db40f2cff98b4002f3f2d3a723c84be5 Mon Sep 17 00:00:00 2001 From: Bryan O'Sullivan Date: Wed, 9 Sep 2009 20:59:38 +0000 Subject: Fix a whole bunch of compilation warnings reported by gcc 4.4 --- indra/newview/lldrawpoolbump.cpp | 12 ++++++------ indra/newview/llface.cpp | 2 +- indra/newview/llhudeffectlookat.cpp | 4 ++-- indra/newview/llspatialpartition.cpp | 4 ++-- indra/newview/lltoolpie.cpp | 4 ++-- indra/newview/llviewercamera.cpp | 4 ++-- indra/newview/llviewerkeyboard.cpp | 2 +- indra/newview/llviewerobject.cpp | 4 ++-- indra/newview/llvoavatar.cpp | 6 +++--- indra/newview/llvosky.cpp | 4 ++-- indra/newview/llvovolume.cpp | 6 +++--- 11 files changed, 26 insertions(+), 26 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index b11dcc1608..644f1695d4 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -309,8 +309,8 @@ void LLDrawPoolBump::endRenderPass(S32 pass) void LLDrawPoolBump::beginShiny(bool invisible) { LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); - if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)|| - invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) + if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| + (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) { return; } @@ -384,8 +384,8 @@ void LLDrawPoolBump::beginShiny(bool invisible) void LLDrawPoolBump::renderShiny(bool invisible) { LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); - if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)|| - invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) + if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| + (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) { return; } @@ -411,8 +411,8 @@ void LLDrawPoolBump::renderShiny(bool invisible) void LLDrawPoolBump::endShiny(bool invisible) { LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); - if (!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY)|| - invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) + if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))|| + (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY))) { return; } diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 69edccacf0..e179fa866b 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -959,7 +959,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, 0.75f }; - if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || LLPipeline::sRenderBump && tep->getShiny())) + if (getPoolType() != LLDrawPool::POOL_ALPHA && (LLPipeline::sRenderDeferred || (LLPipeline::sRenderBump && tep->getShiny()))) { color.mV[3] = U8 (alpha[tep->getShiny()] * 255); } diff --git a/indra/newview/llhudeffectlookat.cpp b/indra/newview/llhudeffectlookat.cpp index 3a5bec2be0..77461e8f0d 100644 --- a/indra/newview/llhudeffectlookat.cpp +++ b/indra/newview/llhudeffectlookat.cpp @@ -421,8 +421,8 @@ BOOL LLHUDEffectLookAt::setLookAt(ELookAtType target_type, LLViewerObject *objec BOOL lookAtChanged = (target_type != mTargetType) || (object != mTargetObject); // lookat position has moved a certain amount and we haven't just sent an update - lookAtChanged = lookAtChanged || (dist_vec(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE) && - ((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC)); + lookAtChanged = lookAtChanged || ((dist_vec(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE) && + ((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC))); if (lookAtChanged) { diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index f8b824732f..cc3d6a364d 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -1671,9 +1671,9 @@ public: virtual bool earlyFail(LLSpatialGroup* group) { if (mResult || //already found a node, don't check any more - group->mOctreeNode->getParent() && //never occlusion cull the root node + (group->mOctreeNode->getParent() && //never occlusion cull the root node LLPipeline::sUseOcclusion && //ignore occlusion if disabled - group->isState(LLSpatialGroup::OCCLUDED)) + group->isState(LLSpatialGroup::OCCLUDED))) { return true; } diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 986555db49..92c9f3f553 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -189,8 +189,8 @@ BOOL LLToolPie::pickAndShowMenu(BOOL always_show) } // else nothing (fall through to touch) case CLICK_ACTION_PAY: - if (object && object->flagTakesMoney() - || parent && parent->flagTakesMoney()) + if ((object && object->flagTakesMoney()) + || (parent && parent->flagTakesMoney())) { // pay event goes to object actually clicked on mClickActionObject = object; diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index 72d1494d96..b7612d901c 100644 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -759,8 +759,8 @@ BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts) BOOL in_frustum = pointInFrustum(LLVector3(vec)) > 0; - if ( !in_frustum && all_verts || - in_frustum && !all_verts) + if (( !in_frustum && all_verts) || + (in_frustum && !all_verts)) { return !all_verts; } diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 15c814829c..cc3d4ea594 100644 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -683,7 +683,7 @@ BOOL LLViewerKeyboard::bindKey(const S32 mode, const KEY key, const MASK mask, c if (idx >=2 && idx <= 12) { U32 keyidx = ((mask<<16)|key); - (mRemapKeys[mode])[keyidx] = ((0<<16)|KEY_F1+(idx-1)); + (mRemapKeys[mode])[keyidx] = ((0<<16)|(KEY_F1+(idx-1))); return TRUE; } } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 6591cd3b19..8e8f882d75 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -637,8 +637,8 @@ BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp) BOOL ret = mDrawable->mXform.setParent(parentp ? &parentp->mXform : NULL); gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); - if( old_parent != parentp && - old_parent || (parentp && parentp->isActive())) + if( (old_parent != parentp && old_parent) + || (parentp && parentp->isActive())) { // *TODO we should not be relying on setDrawable parent to call markMoved gPipeline.markMoved(mDrawable, FALSE); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 983a580fea..e7f283a11c 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1539,7 +1539,7 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector3& start, const LLVector3& e ) { - if (mIsSelf && !gAgent.needsRenderAvatar() || !LLPipeline::sPickAvatar) + if ((mIsSelf && !gAgent.needsRenderAvatar()) || !LLPipeline::sPickAvatar) { return FALSE; } @@ -9015,9 +9015,9 @@ BOOL LLVOAvatar::updateLOD() LLFace* facep = mDrawable->getFace(0); if (facep->mVertexBuffer.isNull() || - LLVertexBuffer::sEnableVBOs && + (LLVertexBuffer::sEnableVBOs && ((facep->mVertexBuffer->getUsage() == GL_STATIC_DRAW ? TRUE : FALSE) != - (facep->getPool()->getVertexShaderLevel() > 0 ? TRUE : FALSE))) + (facep->getPool()->getVertexShaderLevel() > 0 ? TRUE : FALSE)))) { mDirtyMesh = TRUE; } diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index d4df141477..bbc5daf847 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -1095,10 +1095,10 @@ BOOL LLVOSky::updateSky() mLastTotalAmbient.mV[2] - mTotalAmbient.mV[2]); if ( mForceUpdate - || ((dot_lighting < LIGHT_DIRECTION_THRESHOLD) + || (((dot_lighting < LIGHT_DIRECTION_THRESHOLD) || (delta_color.length() > COLOR_CHANGE_THRESHOLD) || !mInitialized) - && !direction.isExactlyZero()) + && !direction.isExactlyZero())) { mLastLightingDirection = direction; mLastTotalAmbient = mTotalAmbient; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index dd68733d98..6079f02147 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -470,8 +470,8 @@ void LLVOVolume::updateTextures() if (face->mTextureMatrix != NULL) { - if (vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE || - vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE) + if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) || + (vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE)) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, FALSE); } @@ -2387,7 +2387,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { //needs normal + binormal bump_faces.push_back(facep); } - else if (te->getShiny() && LLPipeline::sRenderBump || + else if ((te->getShiny() && LLPipeline::sRenderBump) || !te->getFullbright()) { //needs normal simple_faces.push_back(facep); -- cgit v1.2.3 From acd7d31f3ea161374f2fb32bc50defe43586af8d Mon Sep 17 00:00:00 2001 From: Jiao Li Date: Mon, 28 Sep 2009 06:17:18 +0000 Subject: EXT-735 Login failed if start location wasn't defined by user -- reviewed by oreh --- indra/newview/llpanellogin.cpp | 16 ++++++++++++---- indra/newview/skins/default/xui/en/notifications.xml | 11 +++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 9caa751854..150fd399c6 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -837,14 +837,22 @@ void LLPanelLogin::onClickConnect(void *) std::string first = sInstance->childGetText("first_name_edit"); std::string last = sInstance->childGetText("last_name_edit"); - if (!first.empty() && !last.empty()) + LLComboBox* combo = sInstance->getChild("start_location_combo"); + std::string combo_text = combo->getSimple(); + + if (first.empty() || last.empty()) { - // has both first and last name typed - sInstance->mCallback(0, sInstance->mCallbackData); + LLNotifications::instance().add("MustHaveAccountToLogIn"); + } + else if( (combo_text=="" || combo_text =="") + && LLURLSimString::sInstance.mSimString =="") + { + LLNotifications::instance().add("StartRegionEmpty"); } else { - LLNotifications::instance().add("MustHaveAccountToLogIn"); + // has both first and last name typed + sInstance->mCallback(0, sInstance->mCallbackData); } } } diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 80d501b63e..044194a4ed 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -994,6 +994,17 @@ The object may be out of range or may have been deleted. There was a problem saving a compiled script due to the following reason: [REASON]. Please try re-saving the script later. + +Oops, Your Start Region is not defined. +Please type the Region name in Start Location box or choose My Last Location or My Home as your Start Location. + + + Date: Mon, 28 Sep 2009 17:38:13 +0000 Subject: EXT-1195 Default person and group icons too large for text size - reduce to 18 x 18 --- .../skins/default/textures/icons/Generic_Group.png | Bin 550 -> 3354 bytes .../skins/default/textures/icons/Generic_Person.png | Bin 451 -> 3280 bytes 2 files changed, 0 insertions(+), 0 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/textures/icons/Generic_Group.png b/indra/newview/skins/default/textures/icons/Generic_Group.png index 909334d862..fdd65b49e1 100644 Binary files a/indra/newview/skins/default/textures/icons/Generic_Group.png and b/indra/newview/skins/default/textures/icons/Generic_Group.png differ diff --git a/indra/newview/skins/default/textures/icons/Generic_Person.png b/indra/newview/skins/default/textures/icons/Generic_Person.png index 01618ce2c0..45b491ab59 100644 Binary files a/indra/newview/skins/default/textures/icons/Generic_Person.png and b/indra/newview/skins/default/textures/icons/Generic_Person.png differ -- cgit v1.2.3 From 423cba155adc5ed68a6221001d779b3732cebd27 Mon Sep 17 00:00:00 2001 From: Ramzi Ramey Date: Mon, 28 Sep 2009 18:46:51 +0000 Subject: DEV-39252 fix duplicate name= elements in the EN xui. This breaks localization. --- indra/newview/skins/default/xui/en/floater_about_land.xml | 2 +- indra/newview/skins/default/xui/en/floater_bulk_perms.xml | 4 ++-- indra/newview/skins/default/xui/en/menu_login.xml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml index f11391c5e0..5a285cdcb0 100644 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -1678,7 +1678,7 @@ Only large parcels can be listed in search. height="16" layout="topleft" left="10" - name="at URL:" + name="CurrentURL:" top="49" width="65"> Current URL: diff --git a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml index 897e5da4e8..ef6af28786 100644 --- a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml +++ b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml @@ -200,7 +200,7 @@ layout="topleft" height="16" left="10" - name="Group:" + name="GroupLabel" width="88"> Group: @@ -218,7 +218,7 @@ follows="left|top" height="16" layout="topleft" - name="NextOwnerLabel" + name="AnyoneLabel" left="100" top="110" width="88"> diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index 7a0a78bb50..d3a2b2c66b 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -234,7 +234,7 @@ + name="Critical"> -- cgit v1.2.3 From a744ffcef4add32e8fa9a6ce61deae0c29f649c4 Mon Sep 17 00:00:00 2001 From: Ramzi Ramey Date: Mon, 28 Sep 2009 22:37:51 +0000 Subject: DEV-38453 (part4) Modernize and rearrange the nodes of the localized floater_about.xml; NO CHANGES TO ENGLISH. --- indra/newview/skins/default/xui/da/floater_about.xml | 14 +++++++++++--- indra/newview/skins/default/xui/de/floater_about.xml | 14 +++++++++++--- indra/newview/skins/default/xui/es/floater_about.xml | 14 +++++++++++--- indra/newview/skins/default/xui/fr/floater_about.xml | 14 +++++++++++--- indra/newview/skins/default/xui/it/floater_about.xml | 14 +++++++++++--- indra/newview/skins/default/xui/ja/floater_about.xml | 14 +++++++++++--- indra/newview/skins/default/xui/nl/floater_about.xml | 13 +++++++++++-- indra/newview/skins/default/xui/pl/floater_about.xml | 15 +++++++++++---- indra/newview/skins/default/xui/pt/floater_about.xml | 13 ++++++++++--- 9 files changed, 98 insertions(+), 27 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/da/floater_about.xml b/indra/newview/skins/default/xui/da/floater_about.xml index 6b52da04d0..81d4d3fdfd 100644 --- a/indra/newview/skins/default/xui/da/floater_about.xml +++ b/indra/newview/skins/default/xui/da/floater_about.xml @@ -1,10 +1,19 @@ + + Second Life er gjort muligt for dig af Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les, Michon, Jenelle, Geo, Siz, Shapiro, Pete, Calyle, Selene, Allen, Phoebe, Goldin, Kimmora, Dakota, Slaton, Lindquist, Zoey, Hari, Othello, Rohit, Sheldon, Petra, Viale, Gordon, Kaye, Pink, Ferny, Emerson, Davy, Bri, Chan, Juan, Robert, Terrence, Nathan, Carl and many others. Tak til følgende beboerne for at bidrage til at sikre, at dette er den bedste version til dato: able whitman, Adeon Writer, adonaira aabye, Aeron Kohime, Agathos Frascati, Aimee Trescothick, Aleric Inglewood, Alissa Sabre, Aminom Marvin, Angela Talamasca, Aralara Rajal, Armin Weatherwax, Ashrilyn Hayashida, Athanasius Skytower, Aura Dirval, Barney Boomslang, Biancaluce Robbiani, Biker Offcourse, Borg Capalini, Bulli Schumann, catherine pfeffer, Chalice Yao, Corre Porta, Court Goodman, Cummere Mayo, Dale Innis, Darien Caldwell, Darjeeling Schoonhoven, Daten Thielt, dimentox travanti, Dirk Talamasca, Drew Dwi, Duckless Vandyke, Elanthius Flagstaff, Electro Burnstein, emiley tomsen, Escort DeFarge, Eva Rau, Ezian Ecksol, Fire Centaur, Fluf Fredriksson, Francisco Koolhoven, Frontera Thor, Frungi Stastny, Gally Young, gearsawe stonecutter, Gigs Taggart, Gordon Wendt, Gudmund Shepherd, Gypsy Paz, Harleen Gretzky, Henri Beauchamp, Inma Rau, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Jessicka Graves, Joeseph Albanese, Joshua Philgarlic, Khyota Wulluf, kirstenlee Cinquetti, Latif Khalifa, Lex Neva, Lilibeth Andree, Lisa Lowe, Lunita Savira, Loosey Demonia, lum pfohl, Marcos Fonzarelli, MartinRJ Fayray, Marusame Arai, Matthew Dowd, Maya Remblai, McCabe Maxsted, Meghan Dench, Melchoir Tokhes, Menos Short, Michelle2 Zenovka, Mimika Oh, Minerva Memel, Mm Alder, Ochi Wolfe, Omei Turnbull, Pesho Replacement, Phantom Ninetails, phoenixflames kukulcan, Polo Gufler, prez pessoa, princess niven, Prokofy Neva, Qie Niangao, Rem Beattie, RodneyLee Jessop, Saijanai Kuhn, Seg Baphomet, Sergen Davies, Shirley Marquez, SignpostMarv Martin, Sindy Tsure, Sira Arbizu, Skips Jigsaw, Sougent Harrop, Spritely Pixel, Squirrel Wood, StarSong Bright, Subversive Writer, Sugarcult Dagger, Sylumm Grigorovich, Tammy Nowotny, Tanooki Darkes, Tayra Dagostino, Theoretical Chemistry, Thickbrick Sleaford, valerie rosewood, Vex Streeter, Vixen Heron, Whoops Babii, Winter Ventura, Xiki Luik, Yann Dufaux, Yina Yao, Yukinoroh Kamachi, Zolute Infinity, Zwagoth Klaar + + +I get by with a little help from my friends. --Richard Starkey + + + + 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion APR Copyright (C) 2000-2004 The Apache Software Foundation cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se) @@ -26,10 +35,9 @@ Tak til følgende beboerne for at bidrage til at sikre, at dette er den bedste v Alle rettigheder forbeholdes. Se licenses.txt for detaljer. Voice chat Audio coding: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) - - -I get by with a little help from my friends. --Richard Starkey + + Du er ved [POSITION] diff --git a/indra/newview/skins/default/xui/de/floater_about.xml b/indra/newview/skins/default/xui/de/floater_about.xml index 340b90d802..d36f5a43f6 100644 --- a/indra/newview/skins/default/xui/de/floater_about.xml +++ b/indra/newview/skins/default/xui/de/floater_about.xml @@ -1,10 +1,19 @@ + + Second Life wird Ihnen präsentiert von Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les, Michon, Jenelle, Geo, Siz, Shapiro, Pete, Calyle, Selene, Allen, Phoebe, Goldin, Kimmora, Dakota, Slaton, Lindquist, Zoey, Hari, Othello, Rohit, Sheldon, Petra, Viale, Gordon, Kaye, Pink, Ferny, Emerson, Davy, Bri, Chan, Juan, Robert, Terrence, Nathan, Carl und vielen anderen. Vielen Dank den folgenden Einwohnern, die uns geholfen haben, dies zur bisher besten Version zu machen: able whitman, Adeon Writer, adonaira aabye, Aeron Kohime, Agathos Frascati, Aimee Trescothick, Aleric Inglewood, Alissa Sabre, Aminom Marvin, Angela Talamasca, Aralara Rajal, Armin Weatherwax, Ashrilyn Hayashida, Athanasius Skytower, Aura Dirval, Barney Boomslang, Biancaluce Robbiani, Biker Offcourse, Borg Capalini, Bulli Schumann, catherine pfeffer, Chalice Yao, Corre Porta, Court Goodman, Cummere Mayo, Dale Innis, Darien Caldwell, Darjeeling Schoonhoven, Daten Thielt, dimentox travanti, Dirk Talamasca, Drew Dwi, Duckless Vandyke, Elanthius Flagstaff, Electro Burnstein, emiley tomsen, Escort DeFarge, Eva Rau, Ezian Ecksol, Fire Centaur, Fluf Fredriksson, Francisco Koolhoven, Frontera Thor, Frungi Stastny, Gally Young, gearsawe stonecutter, Gigs Taggart, Gordon Wendt, Gudmund Shepherd, Gypsy Paz, Harleen Gretzky, Henri Beauchamp, Inma Rau, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Jessicka Graves, Joeseph Albanese, Joshua Philgarlic, Khyota Wulluf, kirstenlee Cinquetti, Latif Khalifa, Lex Neva, Lilibeth Andree, Lisa Lowe, Lunita Savira, Loosey Demonia, lum pfohl, Marcos Fonzarelli, MartinRJ Fayray, Marusame Arai, Matthew Dowd, Maya Remblai, McCabe Maxsted, Meghan Dench, Melchoir Tokhes, Menos Short, Michelle2 Zenovka, Mimika Oh, Minerva Memel, Mm Alder, Ochi Wolfe, Omei Turnbull, Pesho Replacement, Phantom Ninetails, phoenixflames kukulcan, Polo Gufler, prez pessoa, princess niven, Prokofy Neva, Qie Niangao, Rem Beattie, RodneyLee Jessop, Saijanai Kuhn, Seg Baphomet, Sergen Davies, Shirley Marquez, SignpostMarv Martin, Sindy Tsure, Sira Arbizu, Skips Jigsaw, Sougent Harrop, Spritely Pixel, Squirrel Wood, StarSong Bright, Subversive Writer, Sugarcult Dagger, Sylumm Grigorovich, Tammy Nowotny, Tanooki Darkes, Tayra Dagostino, Theoretical Chemistry, Thickbrick Sleaford, valerie rosewood, Vex Streeter, Vixen Heron, Whoops Babii, Winter Ventura, Xiki Luik, Yann Dufaux, Yina Yao, Yukinoroh Kamachi, Zolute Infinity, Zwagoth Klaar + + +Um im Geschäftsleben erfolreich zu sein, sei kühn, sei schnell, sei anders. --Henry Marchant + + + + 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion APR Copyright (C) 2000-2004 The Apache Software Foundation cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se) @@ -25,10 +34,9 @@ google-perftools Copyright (c) 2005, Google Inc. Alle Rechte vorbehalten. Details siehe licenses.txt. Voice-Chat-Audiocoding: Polycom(R) Siren14(TM) (ITU-T Empf.G.722.1 Anhang C) - - -Um im Geschäftsleben erfolreich zu sein, sei kühn, sei schnell, sei anders. --Henry Marchant + + Sie befinden sich in [POSITION] diff --git a/indra/newview/skins/default/xui/es/floater_about.xml b/indra/newview/skins/default/xui/es/floater_about.xml index 3e0f6513cc..071d505569 100644 --- a/indra/newview/skins/default/xui/es/floater_about.xml +++ b/indra/newview/skins/default/xui/es/floater_about.xml @@ -1,10 +1,19 @@ + + Le ofrecen Second Life Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les, Michon, Jenelle, Geo, Siz, Shapiro, Pete, Calyle, Selene, Allen, Phoebe, Goldin, Kimmora, Dakota, Slaton, Lindquist, Zoey, Hari, Othello, Rohit, Sheldon, Petra, Viale, Gordon, Kaye, Pink, Ferny, Emerson, Davy, Bri, Chan, Juan, Robert, Terrence, Nathan, Carl, y otros muchos. Gracias a todos estos residentes por contribuir a garantizar que esta es la mejor versión: able whitman, Adeon Writer, adonaira aabye, Aeron Kohime, Agathos Frascati, Aimee Trescothick, Aleric Inglewood, Alissa Sabre, Aminom Marvin, Angela Talamasca, Aralara Rajal, Armin Weatherwax, Ashrilyn Hayashida, Athanasius Skytower, Aura Dirval, Barney Boomslang, Biancaluce Robbiani, Biker Offcourse, Borg Capalini, Bulli Schumann, catherine pfeffer, Chalice Yao, Corre Porta, Court Goodman, Cummere Mayo, Dale Innis, Darien Caldwell, Darjeeling Schoonhoven, Daten Thielt, dimentox travanti, Dirk Talamasca, Drew Dwi, Duckless Vandyke, Elanthius Flagstaff, Electro Burnstein, emiley tomsen, Escort DeFarge, Eva Rau, Ezian Ecksol, Fire Centaur, Fluf Fredriksson, Francisco Koolhoven, Frontera Thor, Frungi Stastny, Gally Young, gearsawe stonecutter, Gigs Taggart, Gordon Wendt, Gudmund Shepherd, Gypsy Paz, Harleen Gretzky, Henri Beauchamp, Inma Rau, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Jessicka Graves, Joeseph Albanese, Joshua Philgarlic, Khyota Wulluf, kirstenlee Cinquetti, Latif Khalifa, Lex Neva, Lilibeth Andree, Lisa Lowe, Lunita Savira, Loosey Demonia, lum pfohl, Marcos Fonzarelli, MartinRJ Fayray, Marusame Arai, Matthew Dowd, Maya Remblai, McCabe Maxsted, Meghan Dench, Melchoir Tokhes, Menos Short, Michelle2 Zenovka, Mimika Oh, Minerva Memel, Mm Alder, Ochi Wolfe, Omei Turnbull, Pesho Replacement, Phantom Ninetails, phoenixflames kukulcan, Polo Gufler, prez pessoa, princess niven, Prokofy Neva, Qie Niangao, Rem Beattie, RodneyLee Jessop, Saijanai Kuhn, Seg Baphomet, Sergen Davies, Shirley Marquez, SignpostMarv Martin, Sindy Tsure, Sira Arbizu, Skips Jigsaw, Sougent Harrop, Spritely Pixel, Squirrel Wood, StarSong Bright, Subversive Writer, Sugarcult Dagger, Sylumm Grigorovich, Tammy Nowotny, Tanooki Darkes, Tayra Dagostino, Theoretical Chemistry, Thickbrick Sleaford, valerie rosewood, Vex Streeter, Vixen Heron, Whoops Babii, Winter Ventura, Xiki Luik, Yann Dufaux, Yina Yao, Yukinoroh Kamachi, Zolute Infinity, Zwagoth Klaar + + + Para tener éxito en los negocios, se atrevido, se el primero, se diferente. (Henry Marchant) + + + + 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion APR Copyright (C) 2000-2004 The Apache Software Foundation cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se) @@ -26,10 +35,9 @@ All rights reserved. See licenses.txt for details. Voice chat Audio coding: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) - - - Para tener éxito en los negocios, se atrevido, se el primero, se diferente. (Henry Marchant) + + Está en [POSITION] diff --git a/indra/newview/skins/default/xui/fr/floater_about.xml b/indra/newview/skins/default/xui/fr/floater_about.xml index e05a6d1596..7b918be075 100644 --- a/indra/newview/skins/default/xui/fr/floater_about.xml +++ b/indra/newview/skins/default/xui/fr/floater_about.xml @@ -1,10 +1,19 @@ + + Second Life existe grâce aux efforts de Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les, Michon, Jenelle, Geo, Siz, Shapiro, Pete, Calyle, Selene, Allen, Phoebe, Goldin, Kimmora, Dakota, Slaton, Lindquist, Zoey, Hari, Othello, Rohit, Sheldon, Petra, Viale, Gordon, Kaye, Pink, Ferny, Emerson, Davy, Bri, Chan, Juan, Robert, Terrence, Nathan, Carl et de nombreuses autres personnes. Tous nos remerciements aux résidents suivants pour avoir testé cette version (la meilleure qui soit jusqu'à présent) : able whitman, Adeon Writer, adonaira aabye, Aeron Kohime, Agathos Frascati, Aimee Trescothick, Aleric Inglewood, Alissa Sabre, Aminom Marvin, Angela Talamasca, Aralara Rajal, Armin Weatherwax, Ashrilyn Hayashida, Athanasius Skytower, Aura Dirval, Barney Boomslang, Biancaluce Robbiani, Biker Offcourse, Borg Capalini, Bulli Schumann, catherine pfeffer, Chalice Yao, Corre Porta, Court Goodman, Cummere Mayo, Dale Innis, Darien Caldwell, Darjeeling Schoonhoven, Daten Thielt, dimentox travanti, Dirk Talamasca, Drew Dwi, Duckless Vandyke, Elanthius Flagstaff, Electro Burnstein, emiley tomsen, Escort DeFarge, Eva Rau, Ezian Ecksol, Fire Centaur, Fluf Fredriksson, Francisco Koolhoven, Frontera Thor, Frungi Stastny, Gally Young, gearsawe stonecutter, Gigs Taggart, Gordon Wendt, Gudmund Shepherd, Gypsy Paz, Harleen Gretzky, Henri Beauchamp, Inma Rau, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Jessicka Graves, Joeseph Albanese, Joshua Philgarlic, Khyota Wulluf, kirstenlee Cinquetti, Latif Khalifa, Lex Neva, Lilibeth Andree, Lisa Lowe, Lunita Savira, Loosey Demonia, lum pfohl, Marcos Fonzarelli, MartinRJ Fayray, Marusame Arai, Matthew Dowd, Maya Remblai, McCabe Maxsted, Meghan Dench, Melchoir Tokhes, Menos Short, Michelle2 Zenovka, Mimika Oh, Minerva Memel, Mm Alder, Ochi Wolfe, Omei Turnbull, Pesho Replacement, Phantom Ninetails, phoenixflames kukulcan, Polo Gufler, prez pessoa, princess niven, Prokofy Neva, Qie Niangao, Rem Beattie, RodneyLee Jessop, Saijanai Kuhn, Seg Baphomet, Sergen Davies, Shirley Marquez, SignpostMarv Martin, Sindy Tsure, Sira Arbizu, Skips Jigsaw, Sougent Harrop, Spritely Pixel, Squirrel Wood, StarSong Bright, Subversive Writer, Sugarcult Dagger, Sylumm Grigorovich, Tammy Nowotny, Tanooki Darkes, Tayra Dagostino, Theoretical Chemistry, Thickbrick Sleaford, valerie rosewood, Vex Streeter, Vixen Heron, Whoops Babii, Winter Ventura, Xiki Luik, Yann Dufaux, Yina Yao, Yukinoroh Kamachi, Zolute Infinity, Zwagoth Klaar + + + Pour réussir dans les affaires, soyez audacieux, créatif et différent. - Henry Marchant + + + + 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion APR Copyright (C) 2000-2004 The Apache Software Foundation cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se) @@ -25,10 +34,9 @@ Tous droits réservés. Voir licenses.txt pour plus de détails. Codage Audio du chat vocal : Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) - - - Pour réussir dans les affaires, soyez audacieux, créatif et différent. - Henry Marchant + + Votre position : [POSITION] diff --git a/indra/newview/skins/default/xui/it/floater_about.xml b/indra/newview/skins/default/xui/it/floater_about.xml index 597208eedb..2c91375930 100644 --- a/indra/newview/skins/default/xui/it/floater_about.xml +++ b/indra/newview/skins/default/xui/it/floater_about.xml @@ -1,10 +1,19 @@ + + Second Life è offerto da Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les, Michon, Jenelle, Geo, Siz, Shapiro, Pete, Calyle, Selene, Allen, Phoebe, Goldin, Kimmora, Dakota, Slaton, Lindquist, Zoey, Hari, Othello, Rohit, Sheldon, Petra, Viale, Gordon, Kaye, Pink, Ferny, Emerson, Davy, Bri, Chan, Juan, Robert, Terrence, Nathan, Carl and many others. Si ringraziano i seguenti residenti per aver contribuito a rendere questa versione la migliore possibile: able whitman, Adeon Writer, adonaira aabye, Aeron Kohime, Agathos Frascati, Aimee Trescothick, Aleric Inglewood, Alissa Sabre, Aminom Marvin, Angela Talamasca, Aralara Rajal, Armin Weatherwax, Ashrilyn Hayashida, Athanasius Skytower, Aura Dirval, Barney Boomslang, Biancaluce Robbiani, Biker Offcourse, Borg Capalini, Bulli Schumann, catherine pfeffer, Chalice Yao, Corre Porta, Court Goodman, Cummere Mayo, Dale Innis, Darien Caldwell, Darjeeling Schoonhoven, Daten Thielt, dimentox travanti, Dirk Talamasca, Drew Dwi, Duckless Vandyke, Elanthius Flagstaff, Electro Burnstein, emiley tomsen, Escort DeFarge, Eva Rau, Ezian Ecksol, Fire Centaur, Fluf Fredriksson, Francisco Koolhoven, Frontera Thor, Frungi Stastny, Gally Young, gearsawe stonecutter, Gigs Taggart, Gordon Wendt, Gudmund Shepherd, Gypsy Paz, Harleen Gretzky, Henri Beauchamp, Inma Rau, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Jessicka Graves, Joeseph Albanese, Joshua Philgarlic, Khyota Wulluf, kirstenlee Cinquetti, Latif Khalifa, Lex Neva, Lilibeth Andree, Lisa Lowe, Lunita Savira, Loosey Demonia, lum pfohl, Marcos Fonzarelli, MartinRJ Fayray, Marusame Arai, Matthew Dowd, Maya Remblai, McCabe Maxsted, Meghan Dench, Melchoir Tokhes, Menos Short, Michelle2 Zenovka, Mimika Oh, Minerva Memel, Mm Alder, Ochi Wolfe, Omei Turnbull, Pesho Replacement, Phantom Ninetails, phoenixflames kukulcan, Polo Gufler, prez pessoa, princess niven, Prokofy Neva, Qie Niangao, Rem Beattie, RodneyLee Jessop, Saijanai Kuhn, Seg Baphomet, Sergen Davies, Shirley Marquez, SignpostMarv Martin, Sindy Tsure, Sira Arbizu, Skips Jigsaw, Sougent Harrop, Spritely Pixel, Squirrel Wood, StarSong Bright, Subversive Writer, Sugarcult Dagger, Sylumm Grigorovich, Tammy Nowotny, Tanooki Darkes, Tayra Dagostino, Theoretical Chemistry, Thickbrick Sleaford, valerie rosewood, Vex Streeter, Vixen Heron, Whoops Babii, Winter Ventura, Xiki Luik, Yann Dufaux, Yina Yao, Yukinoroh Kamachi, Zolute Infinity, Zwagoth Klaar + + + Per avere successo nel business, sii coraggioso, sii il primo, sii differente. --Henry Marchant + + + + 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion APR Copyright (C) 2000-2004 The Apache Software Foundation cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se) @@ -26,10 +35,9 @@ Tutti i diritti riservati. Leggi licenses.txt per maggiori dettagli. Chat vocale Codifica audio: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) - - - Per avere successo nel business, sii coraggioso, sii il primo, sii differente. --Henry Marchant + + Sei a [POSITION] diff --git a/indra/newview/skins/default/xui/ja/floater_about.xml b/indra/newview/skins/default/xui/ja/floater_about.xml index fb12e48c9a..a9b3d81a3b 100644 --- a/indra/newview/skins/default/xui/ja/floater_about.xml +++ b/indra/newview/skins/default/xui/ja/floater_about.xml @@ -1,10 +1,19 @@  + + Second Lifeは、 Philip、Tessa、Andrew、Cory、James、Ben、Char、Charlie、Colin、Dan、Daniel、Doug、Eric、Hamlet、Haney、Eve、Hunter、Ian、Jeff、Jennifer、Jim、John、Lee、Mark、Peter、Phoenix、Richard、Robin、Xenon、Steve、Tanya、Eddie、Avi、Frank、Bruce、Aaron、Alice、Bob、Debra、Eileen、Helen、Janet、Louie、Leviathania、Stefan、Ray、Kevin、Tom、Mikeb、MikeT、Burgess、Elena、Tracy、Bill、Todd、Ryan、Zach、Sarah、Nova、Tim、Stephanie、Michael、Evan、Nicolas、Catherine、Rachelle、Dave、Holly、Bub、Kelly、Magellan、Ramzi、Don、Sabin、Jill、Rheya、Jeska、Torley、Kona、Callum、Charity、Ventrella、Jack、Vektor、Iris、Chris、Nicole、Mick、Reuben、Blue、Babbage、Yedwab、Deana、Lauren、Brent、Pathfinder、Chadrick、Altruima、Jesse、Teeny、Monroe、Icculus、David、Tess、Lizzie、Patsy、Isaac、Lawrence、Cyn、Bo、Gia、Annette、Marius、Tbone、Jonathan、Karen、Ginsu、Satoko、Yuko、Makiko、Thomas、Harry、Seth、Alexei、Brian、Guy、Runitai、Ethan、Data、Cornelius、Kenny、Swiss、Zero、Natria、Wendy、Stephen、Teeple、Thumper、Lucy、Dee、Mia、Liana、Warren、Branka、Aura、beez、Milo、Hermia、Red、Thrax、Joe、Sally、Magenta、Mogura、Paul、Jose、Rejean、Henrik、Lexie、Amber、Logan、Xan、Nora、Morpheus、Donovan、Leyla、MichaelFrancis、Beast、Cube、Bucky、Joshua、Stryfe、Harmony、Teresa、Claudia、Walker、Glenn、Fritz、Fordak、June、Cleopetra、Jean、Ivy、Betsy、Roosevelt、Spike、Ken、Which、Tofu、Chiyo、Rob、Zee、dustin、George、Del、Matthew、Cat、Jacqui、Lightfoot、Adrian、Viola、Alfred、Noel、Irfan、Sunil、Yool、Rika、Jane、Xtreme、Frontier、a2、Neo、Siobhan、Yoz、Justin、Elle、Qarl、Benjamin、Isabel、Gulliver、Everett、Christopher、Izzy、Stephany、Garry、Sejong、Sean、Tobin、Iridium、Meta、Anthony、Jeremy、JP、Jake、Maurice、Madhavi、Leopard、Kyle、Joon、Kari、Bert、Belinda、Jon、Kristi、Bridie、Pramod、KJ、Socrates、Maria、Ivan、Aric、Yamasaki、Adreanne、Jay、MitchK、Ceren、Coco、Durl、Jenny、Periapse、Kartic、Storrs、Lotte、Sandy、Rohn、Colossus、Zen、BigPapi、Brad、Pastrami、Kurz、Mani、Neuro、Jaime、MJ、Rowan、Sgt、Elvis、Gecko、Samuel、Sardonyx、Leo、Bryan、Niko、Soft、Poppy、Rachel、Aki、Angelo、Banzai、Alexa、Sue、CeeLo、Bender、CG、Gillian、Pelle、Nick、Echo、Zara、Christine、Shamiran、Emma、Blake、Keiko、Plexus、Joppa、Sidewinder、Erica、Ashlei、Twilight、Kristen、Brett、Q、Enus、Simon、Bevis、Kraft、Kip、Chandler、Ron、LauraP、Ram、KyleJM、Scouse、Prospero、Melissa、Marty、Nat、Hamilton、Kend、Lordan、Jimmy、Kosmo、Seraph、Green、Ekim、Wiggo、JT、Rome、Doris、Miz、Benoc、Whump、Trinity、Patch、Kate、TJ、Bao、Joohwan、Christy、Sofia、Matias、Cogsworth、Johan、Oreh、Cheah、Angela、Brandy、Mango、Lan、Aleks、Gloria、Heidy、Mitchell、Space、Colton、Bambers、Einstein、Maggie、Malbers、Rose、Winnie、Stella、Milton、Rothman、Niall、Marin、Allison、Katie、Dawn、Katt、Dusty、Kalpana、Judy、Andrea、Ambroff、Infinity、Gail、Rico、Raymond、Yi、William、Christa、M、Teagan、Scout、Molly、Dante、Corr、Dynamike、Usi、Kaylee、Vidtuts、Lil、Danica、Sascha、Kelv、Jacob、Nya、Rodney、Brandon、Elsie、Blondin、Grant、Katrin、Nyx、Gabriel、Locklainn、Claire、Devin、Minerva、Monty、Austin、Bradford、Si、Keira、H、Caitlin、Dita、Makai、Jenn、Ann、Meredith、Clare、Joy、Praveen、Cody、Edmund、Ruthe、Sirena、Gayathri、Spider、FJ、Davidoff、Tian、Jennie、Louise、Oskar、Landon、Noelle、Jarv、Ingrid、Al、Sommer、Doc、Aria、Huin、Gray、Lili、Vir、DJ、Yang、T、Simone、Maestro、Scott、Charlene、Quixote、Amanda、Susan、Zed、Anne、Enkidu、Esbee、Joroan、Katelin、Roxie、Tay、Scarlet、Kevin、Johnny、Wolfgang、Andren、Bob、Howard、Merov、Rand、Ray、Michon、Newell、Galen、Dessie、Les、Michon、Jenelle、Geo、Siz、Shapiro、Pete、Calyle、Selene、Allen、Phoebe、Goldin、Kimmora、Dakota、Slaton、Lindquist、Zoey、Hari、Othello、Rohit、Sheldon、Petra、Viale、Gordon、Kaye、Pink、Ferny、Emerson、Davy、Bri、Chan、Juan、Robert、Terrence、Nathan、Carlと、その他多数の人達によって作成されました。 このバージョンをこれまでで最高のものになるようご協力をいただいた以下の住人の皆様に深く感謝いたします。 able whitman, Adeon Writer, adonaira aabye, Aeron Kohime, Agathos Frascati, Aimee Trescothick, Aleric Inglewood, Alissa Sabre, Aminom Marvin, Angela Talamasca, Aralara Rajal, Armin Weatherwax, Ashrilyn Hayashida, Athanasius Skytower, Aura Dirval, Barney Boomslang, Biancaluce Robbiani, Biker Offcourse, Borg Capalini, Bulli Schumann, catherine pfeffer, Chalice Yao, Corre Porta, Court Goodman, Cummere Mayo, Dale Innis, Darien Caldwell, Darjeeling Schoonhoven, Daten Thielt, dimentox travanti, Dirk Talamasca, Drew Dwi, Duckless Vandyke, Elanthius Flagstaff, Electro Burnstein, emiley tomsen, Escort DeFarge, Eva Rau, Ezian Ecksol, Fire Centaur, Fluf Fredriksson, Francisco Koolhoven, Frontera Thor, Frungi Stastny, Gally Young, gearsawe stonecutter, Gigs Taggart, Gordon Wendt, Gudmund Shepherd, Gypsy Paz, Harleen Gretzky, Henri Beauchamp, Inma Rau, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Jessicka Graves, Joeseph Albanese, Joshua Philgarlic, Khyota Wulluf, kirstenlee Cinquetti, Latif Khalifa, Lex Neva, Lilibeth Andree, Lisa Lowe, Lunita Savira, Loosey Demonia, lum pfohl, Marcos Fonzarelli, MartinRJ Fayray, Marusame Arai, Matthew Dowd, Maya Remblai, McCabe Maxsted, Meghan Dench, Melchoir Tokhes, Menos Short, Michelle2 Zenovka, Mimika Oh, Minerva Memel, Mm Alder, Ochi Wolfe, Omei Turnbull, Pesho Replacement, Phantom Ninetails, phoenixflames kukulcan, Polo Gufler, prez pessoa, princess niven, Prokofy Neva, Qie Niangao, Rem Beattie, RodneyLee Jessop, Saijanai Kuhn, Seg Baphomet, Sergen Davies, Shirley Marquez, SignpostMarv Martin, Sindy Tsure, Sira Arbizu, Skips Jigsaw, Sougent Harrop, Spritely Pixel, Squirrel Wood, StarSong Bright, Subversive Writer, Sugarcult Dagger, Sylumm Grigorovich, Tammy Nowotny, Tanooki Darkes, Tayra Dagostino, Theoretical Chemistry, Thickbrick Sleaford, valerie rosewood, Vex Streeter, Vixen Heron, Whoops Babii, Winter Ventura, Xiki Luik, Yann Dufaux, Yina Yao, Yukinoroh Kamachi, Zolute Infinity, Zwagoth Klaar + + + ビジネスで成功するには、勇気を持って、誰よりも先に、人と違ったことをすることだ。 --Henry Marchant + + + + 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion APR Copyright (C) 2000-2004 The Apache Software Foundation cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se) @@ -25,10 +34,9 @@ 無断転写、複製、転載を禁じます。 詳細はlicenses.txtを参照してください。 Voice chat Audio coding: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) - - - ビジネスで成功するには、勇気を持って、誰よりも先に、人と違ったことをすることだ。 --Henry Marchant + + [POSITION] diff --git a/indra/newview/skins/default/xui/nl/floater_about.xml b/indra/newview/skins/default/xui/nl/floater_about.xml index 4d5d8b1032..9ad947df66 100644 --- a/indra/newview/skins/default/xui/nl/floater_about.xml +++ b/indra/newview/skins/default/xui/nl/floater_about.xml @@ -1,10 +1,19 @@ + + Second Life wordt u aangeboden door Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les, Michon, Jenelle, Geo, Siz, Shapiro, Pete, Calyle, Selene, Allen, Phoebe, Goldin, Kimmora, Dakota, Slaton, Lindquist, Zoey, Hari, Othello, Rohit, Sheldon, Petra, Viale, Gordon, Kaye, Pink, Ferny, Emerson, Davy, Bri, Chan, Juan, Robert, Terrence, Nathan, Carl and many others. Een 'Dank u' voor de volgende bewoners voor het helpen zorgdragen dat dit de beste versie tot nu toe is: able whitman, Adeon Writer, adonaira aabye, Aeron Kohime, Agathos Frascati, Aimee Trescothick, Aleric Inglewood, Alissa Sabre, Aminom Marvin, Angela Talamasca, Aralara Rajal, Armin Weatherwax, Ashrilyn Hayashida, Athanasius Skytower, Aura Dirval, Barney Boomslang, Biancaluce Robbiani, Biker Offcourse, Borg Capalini, Bulli Schumann, catherine pfeffer, Chalice Yao, Corre Porta, Court Goodman, Cummere Mayo, Dale Innis, Darien Caldwell, Darjeeling Schoonhoven, Daten Thielt, dimentox travanti, Dirk Talamasca, Drew Dwi, Duckless Vandyke, Elanthius Flagstaff, Electro Burnstein, emiley tomsen, Escort DeFarge, Eva Rau, Ezian Ecksol, Fire Centaur, Fluf Fredriksson, Francisco Koolhoven, Frontera Thor, Frungi Stastny, Gally Young, gearsawe stonecutter, Gigs Taggart, Gordon Wendt, Gudmund Shepherd, Gypsy Paz, Harleen Gretzky, Henri Beauchamp, Inma Rau, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Jessicka Graves, Joeseph Albanese, Joshua Philgarlic, Khyota Wulluf, kirstenlee Cinquetti, Latif Khalifa, Lex Neva, Lilibeth Andree, Lisa Lowe, Lunita Savira, Loosey Demonia, lum pfohl, Marcos Fonzarelli, MartinRJ Fayray, Marusame Arai, Matthew Dowd, Maya Remblai, McCabe Maxsted, Meghan Dench, Melchoir Tokhes, Menos Short, Michelle2 Zenovka, Mimika Oh, Minerva Memel, Mm Alder, Ochi Wolfe, Omei Turnbull, Pesho Replacement, Phantom Ninetails, phoenixflames kukulcan, Polo Gufler, prez pessoa, princess niven, Prokofy Neva, Qie Niangao, Rem Beattie, RodneyLee Jessop, Saijanai Kuhn, Seg Baphomet, Sergen Davies, Shirley Marquez, SignpostMarv Martin, Sindy Tsure, Sira Arbizu, Skips Jigsaw, Sougent Harrop, Spritely Pixel, Squirrel Wood, StarSong Bright, Subversive Writer, Sugarcult Dagger, Sylumm Grigorovich, Tammy Nowotny, Tanooki Darkes, Tayra Dagostino, Theoretical Chemistry, Thickbrick Sleaford, valerie rosewood, Vex Streeter, Vixen Heron, Whoops Babii, Winter Ventura, Xiki Luik, Yann Dufaux, Yina Yao, Yukinoroh Kamachi, Zolute Infinity, Zwagoth Klaar + + +To be a success in business, be daring, be first, be different. --Henry Marchant + + + + 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion APR Copyright (C) 2000-2004 The Apache Software Foundation cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se) @@ -26,9 +35,9 @@ google-perftools Copyright (c) 2005, Google Inc. All rights reserved. See licenses.txt for details. Voice chat Audio coding: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) - -To be a success in business, be daring, be first, be different. --Henry Marchant + + U bent op [POSITION] diff --git a/indra/newview/skins/default/xui/pl/floater_about.xml b/indra/newview/skins/default/xui/pl/floater_about.xml index bbf8165883..0f100b9d83 100755 --- a/indra/newview/skins/default/xui/pl/floater_about.xml +++ b/indra/newview/skins/default/xui/pl/floater_about.xml @@ -1,10 +1,19 @@ + + Second Life zostało stworzone dla Was przez: Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les, Michon, Jenelle, Geo, Siz, Shapiro, Pete, Calyle, Selene, Allen, Phoebe, Goldin, Kimmora, Dakota, Slaton, Lindquist, Zoey, Hari, Othello, Rohit, Sheldon, Petra, Viale, Gordon, Kaye, Pink, Ferny, Emerson, Davy, Bri, Chan, Juan, Robert, Terrence, Nathan, Carl i wielu innych. Podziękowania dla następujących rezydentów za pomoc w pracy nad obecną wersją Second Life: able whitman, Adeon Writer, adonaira aabye, Aeron Kohime, Agathos Frascati, Aimee Trescothick, Aleric Inglewood, Alissa Sabre, Aminom Marvin, Angela Talamasca, Aralara Rajal, Armin Weatherwax, Ashrilyn Hayashida, Athanasius Skytower, Aura Dirval, Barney Boomslang, Biancaluce Robbiani, Biker Offcourse, Borg Capalini, Bulli Schumann, catherine pfeffer, Chalice Yao, Corre Porta, Court Goodman, Cummere Mayo, Dale Innis, Darien Caldwell, Darjeeling Schoonhoven, Daten Thielt, dimentox travanti, Dirk Talamasca, Drew Dwi, Duckless Vandyke, Elanthius Flagstaff, Electro Burnstein, emiley tomsen, Escort DeFarge, Eva Rau, Ezian Ecksol, Fire Centaur, Fluf Fredriksson, Francisco Koolhoven, Frontera Thor, Frungi Stastny, Gally Young, gearsawe stonecutter, Gigs Taggart, Gordon Wendt, Gudmund Shepherd, Gypsy Paz, Harleen Gretzky, Henri Beauchamp, Inma Rau, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Jessicka Graves, Joeseph Albanese, Joshua Philgarlic, Khyota Wulluf, kirstenlee Cinquetti, Latif Khalifa, Lex Neva, Lilibeth Andree, Lisa Lowe, Lunita Savira, Loosey Demonia, lum pfohl, Marcos Fonzarelli, MartinRJ Fayray, Marusame Arai, Matthew Dowd, Maya Remblai, McCabe Maxsted, Meghan Dench, Melchoir Tokhes, Menos Short, Michelle2 Zenovka, Mimika Oh, Minerva Memel, Mm Alder, Ochi Wolfe, Omei Turnbull, Pesho Replacement, Phantom Ninetails, phoenixflames kukulcan, Polo Gufler, prez pessoa, princess niven, Prokofy Neva, Qie Niangao, Rem Beattie, RodneyLee Jessop, Saijanai Kuhn, Seg Baphomet, Sergen Davies, Shirley Marquez, SignpostMarv Martin, Sindy Tsure, Sira Arbizu, Skips Jigsaw, Sougent Harrop, Spritely Pixel, Squirrel Wood, StarSong Bright, Subversive Writer, Sugarcult Dagger, Sylumm Grigorovich, Tammy Nowotny, Tanooki Darkes, Tayra Dagostino, Theoretical Chemistry, Thickbrick Sleaford, valerie rosewood, Vex Streeter, Vixen Heron, Whoops Babii, Winter Ventura, Xiki Luik, Yann Dufaux, Yina Yao, Yukinoroh Kamachi, Zolute Infinity, Zwagoth Klaar + + + I get by with a little help from my friends. --Richard Starkey + + + + 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion APR Copyright (C) 2000-2004 The Apache Software Foundation cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se) @@ -25,11 +34,9 @@ Wszystkie prawa zastrzeżone. Szczegóły w pliku licenses.txt. Programowanie dźwięku czatu: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) - - Polska wersja klienta: Malwina Dollinger, Magnus Balczo, Identity Euler - - I get by with a little help from my friends. --Richard Starkey + + Położenie: [POSITION] diff --git a/indra/newview/skins/default/xui/pt/floater_about.xml b/indra/newview/skins/default/xui/pt/floater_about.xml index c8c0442d1d..12cc879cbc 100644 --- a/indra/newview/skins/default/xui/pt/floater_about.xml +++ b/indra/newview/skins/default/xui/pt/floater_about.xml @@ -1,10 +1,18 @@ + + Second Life é oferecido a você por Philip, Tessa, Andrew, Cory, James, Ben, Char, Charlie, Colin, Dan, Daniel, Doug, Eric, Hamlet, Haney, Eve, Hunter, Ian, Jeff, Jennifer, Jim, John, Lee, Mark, Peter, Phoenix, Richard, Robin, Xenon, Steve, Tanya, Eddie, Avi, Frank, Bruce, Aaron, Alice, Bob, Debra, Eileen, Helen, Janet, Louie, Leviathania, Stefan, Ray, Kevin, Tom, Mikeb, MikeT, Burgess, Elena, Tracy, Bill, Todd, Ryan, Zach, Sarah, Nova, Tim, Stephanie, Michael, Evan, Nicolas, Catherine, Rachelle, Dave, Holly, Bub, Kelly, Magellan, Ramzi, Don, Sabin, Jill, Rheya, Jeska, Torley, Kona, Callum, Charity, Ventrella, Jack, Vektor, Iris, Chris, Nicole, Mick, Reuben, Blue, Babbage, Yedwab, Deana, Lauren, Brent, Pathfinder, Chadrick, Altruima, Jesse, Teeny, Monroe, Icculus, David, Tess, Lizzie, Patsy, Isaac, Lawrence, Cyn, Bo, Gia, Annette, Marius, Tbone, Jonathan, Karen, Ginsu, Satoko, Yuko, Makiko, Thomas, Harry, Seth, Alexei, Brian, Guy, Runitai, Ethan, Data, Cornelius, Kenny, Swiss, Zero, Natria, Wendy, Stephen, Teeple, Thumper, Lucy, Dee, Mia, Liana, Warren, Branka, Aura, beez, Milo, Hermia, Red, Thrax, Joe, Sally, Magenta, Mogura, Paul, Jose, Rejean, Henrik, Lexie, Amber, Logan, Xan, Nora, Morpheus, Donovan, Leyla, MichaelFrancis, Beast, Cube, Bucky, Joshua, Stryfe, Harmony, Teresa, Claudia, Walker, Glenn, Fritz, Fordak, June, Cleopetra, Jean, Ivy, Betsy, Roosevelt, Spike, Ken, Which, Tofu, Chiyo, Rob, Zee, dustin, George, Del, Matthew, Cat, Jacqui, Lightfoot, Adrian, Viola, Alfred, Noel, Irfan, Sunil, Yool, Rika, Jane, Xtreme, Frontier, a2, Neo, Siobhan, Yoz, Justin, Elle, Qarl, Benjamin, Isabel, Gulliver, Everett, Christopher, Izzy, Stephany, Garry, Sejong, Sean, Tobin, Iridium, Meta, Anthony, Jeremy, JP, Jake, Maurice, Madhavi, Leopard, Kyle, Joon, Kari, Bert, Belinda, Jon, Kristi, Bridie, Pramod, KJ, Socrates, Maria, Ivan, Aric, Yamasaki, Adreanne, Jay, MitchK, Ceren, Coco, Durl, Jenny, Periapse, Kartic, Storrs, Lotte, Sandy, Rohn, Colossus, Zen, BigPapi, Brad, Pastrami, Kurz, Mani, Neuro, Jaime, MJ, Rowan, Sgt, Elvis, Gecko, Samuel, Sardonyx, Leo, Bryan, Niko, Soft, Poppy, Rachel, Aki, Angelo, Banzai, Alexa, Sue, CeeLo, Bender, CG, Gillian, Pelle, Nick, Echo, Zara, Christine, Shamiran, Emma, Blake, Keiko, Plexus, Joppa, Sidewinder, Erica, Ashlei, Twilight, Kristen, Brett, Q, Enus, Simon, Bevis, Kraft, Kip, Chandler, Ron, LauraP, Ram, KyleJM, Scouse, Prospero, Melissa, Marty, Nat, Hamilton, Kend, Lordan, Jimmy, Kosmo, Seraph, Green, Ekim, Wiggo, JT, Rome, Doris, Miz, Benoc, Whump, Trinity, Patch, Kate, TJ, Bao, Joohwan, Christy, Sofia, Matias, Cogsworth, Johan, Oreh, Cheah, Angela, Brandy, Mango, Lan, Aleks, Gloria, Heidy, Mitchell, Space, Colton, Bambers, Einstein, Maggie, Malbers, Rose, Winnie, Stella, Milton, Rothman, Niall, Marin, Allison, Katie, Dawn, Katt, Dusty, Kalpana, Judy, Andrea, Ambroff, Infinity, Gail, Rico, Raymond, Yi, William, Christa, M, Teagan, Scout, Molly, Dante, Corr, Dynamike, Usi, Kaylee, Vidtuts, Lil, Danica, Sascha, Kelv, Jacob, Nya, Rodney, Brandon, Elsie, Blondin, Grant, Katrin, Nyx, Gabriel, Locklainn, Claire, Devin, Minerva, Monty, Austin, Bradford, Si, Keira, H, Caitlin, Dita, Makai, Jenn, Ann, Meredith, Clare, Joy, Praveen, Cody, Edmund, Ruthe, Sirena, Gayathri, Spider, FJ, Davidoff, Tian, Jennie, Louise, Oskar, Landon, Noelle, Jarv, Ingrid, Al, Sommer, Doc, Aria, Huin, Gray, Lili, Vir, DJ, Yang, T, Simone, Maestro, Scott, Charlene, Quixote, Amanda, Susan, Zed, Anne, Enkidu, Esbee, Joroan, Katelin, Roxie, Tay, Scarlet, Kevin, Johnny, Wolfgang, Andren, Bob, Howard, Merov, Rand, Ray, Michon, Newell, Galen, Dessie, Les, Michon, Jenelle, Geo, Siz, Shapiro, Pete, Calyle, Selene, Allen, Phoebe, Goldin, Kimmora, Dakota, Slaton, Lindquist, Zoey, Hari, Othello, Rohit, Sheldon, Petra, Viale, Gordon, Kaye, Pink, Ferny, Emerson, Davy, Bri, Chan, Juan, Robert, Terrence, Nathan, Carl e muitos outros. Obrigado aos seguintes residentes por ajudar a garantir para que esta versão seja ainda melhor: able whitman, Adeon Writer, adonaira aabye, Aeron Kohime, Agathos Frascati, Aimee Trescothick, Aleric Inglewood, Alissa Sabre, Aminom Marvin, Angela Talamasca, Aralara Rajal, Armin Weatherwax, Ashrilyn Hayashida, Athanasius Skytower, Aura Dirval, Barney Boomslang, Biancaluce Robbiani, Biker Offcourse, Borg Capalini, Bulli Schumann, catherine pfeffer, Chalice Yao, Corre Porta, Court Goodman, Cummere Mayo, Dale Innis, Darien Caldwell, Darjeeling Schoonhoven, Daten Thielt, dimentox travanti, Dirk Talamasca, Drew Dwi, Duckless Vandyke, Elanthius Flagstaff, Electro Burnstein, emiley tomsen, Escort DeFarge, Eva Rau, Ezian Ecksol, Fire Centaur, Fluf Fredriksson, Francisco Koolhoven, Frontera Thor, Frungi Stastny, Gally Young, gearsawe stonecutter, Gigs Taggart, Gordon Wendt, Gudmund Shepherd, Gypsy Paz, Harleen Gretzky, Henri Beauchamp, Inma Rau, Irene Muni, Iskar Ariantho, Jacek Antonelli, JB Kraft, Jessicka Graves, Joeseph Albanese, Joshua Philgarlic, Khyota Wulluf, kirstenlee Cinquetti, Latif Khalifa, Lex Neva, Lilibeth Andree, Lisa Lowe, Lunita Savira, Loosey Demonia, lum pfohl, Marcos Fonzarelli, MartinRJ Fayray, Marusame Arai, Matthew Dowd, Maya Remblai, McCabe Maxsted, Meghan Dench, Melchoir Tokhes, Menos Short, Michelle2 Zenovka, Mimika Oh, Minerva Memel, Mm Alder, Ochi Wolfe, Omei Turnbull, Pesho Replacement, Phantom Ninetails, phoenixflames kukulcan, Polo Gufler, prez pessoa, princess niven, Prokofy Neva, Qie Niangao, Rem Beattie, RodneyLee Jessop, Saijanai Kuhn, Seg Baphomet, Sergen Davies, Shirley Marquez, SignpostMarv Martin, Sindy Tsure, Sira Arbizu, Skips Jigsaw, Sougent Harrop, Spritely Pixel, Squirrel Wood, StarSong Bright, Subversive Writer, Sugarcult Dagger, Sylumm Grigorovich, Tammy Nowotny, Tanooki Darkes, Tayra Dagostino, Theoretical Chemistry, Thickbrick Sleaford, valerie rosewood, Vex Streeter, Vixen Heron, Whoops Babii, Winter Ventura, Xiki Luik, Yann Dufaux, Yina Yao, Yukinoroh Kamachi, Zolute Infinity, Zwagoth Klaar + + Para ter sucesso nos negócios, seja ousado, seja o primeiro, seja diferente. --Henry Marchant + + + + 3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion APR Copyright (C) 2000-2004 The Apache Software Foundation cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se) @@ -26,10 +34,9 @@ Todos os direitos reservados. Veja licenças.txt para detalhes. Voice chat Audio coding: Polycom(R) Siren14(TM) (ITU-T Rec. G.722.1 Annex C) - - - Para ter sucesso nos negócios, seja ousado, seja o primeiro, seja diferente. --Henry Marchant + + Você está em [POSITION] -- cgit v1.2.3 From 76dd17168a6ec7f588a862b9575995687cd49b0f Mon Sep 17 00:00:00 2001 From: James Cook Date: Mon, 28 Sep 2009 23:11:18 +0000 Subject: DEV-40528 Viewer 2 floods server with AvatarPropertiesRequest messages causing database load. Icon cache was only being used to provide images more quickly, not to suppress network traffic. Made it suppress network traffic, which may result in stale icons occasionally. Converted online/offline tooltip to use LLAvatarTracker. Will port to viewer-2-qa-1. Reviewed with Richard. --- indra/newview/llavatariconctrl.cpp | 52 ++++++++++++++++++++++++++++---------- indra/newview/llcallingcard.cpp | 6 +++++ indra/newview/llcallingcard.h | 3 +++ 3 files changed, 48 insertions(+), 13 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index a8b1ff6c92..1d5fa9ffa7 100644 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -32,9 +32,10 @@ #include "llviewerprecompiledheaders.h" +#include "llavatariconctrl.h" + #include "llagent.h" #include "llavatarconstants.h" -#include "llavatariconctrl.h" #include "llcallingcard.h" // for LLAvatarTracker #include "llavataractions.h" #include "llimview.h" @@ -139,25 +140,37 @@ void LLAvatarIconCtrl::setValue(const LLSD& value) { if (value.isUUID()) { + LLAvatarPropertiesProcessor* app = + LLAvatarPropertiesProcessor::getInstance(); if (mAvatarId.notNull()) { - LLAvatarPropertiesProcessor::getInstance()->removeObserver(mAvatarId, this); + app->removeObserver(mAvatarId, this); } if (mAvatarId != value.asUUID()) { - LLAvatarPropertiesProcessor::getInstance()->addObserver(value.asUUID(), this); - LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(value.asUUID()); mAvatarId = value.asUUID(); - // Check if cache already contains image_id for that avatar - avatar_image_map_t::iterator it; + // *BUG: This will return stale icons if a user changes their + // profile picture. Also, the online/offline tooltips will be + // out of date. However, otherwise we send too many upstream + // AvatarPropertiesRequest messages. + // + // *TODO: Implement a timeout on the icon cache, perhaps a day?, + // and make the cache update if a user views the full-profile for + // an avatar. - it = sImagesCache.find(mAvatarId); + // Check if cache already contains image_id for that avatar + avatar_image_map_t::iterator it = sImagesCache.find(mAvatarId); if (it != sImagesCache.end()) { updateFromCache(it->second); } + else + { + app->addObserver(value.asUUID(), this); + app->sendAvatarPropertiesRequest(value.asUUID()); + } } } @@ -181,21 +194,34 @@ void LLAvatarIconCtrl::updateFromCache(LLAvatarIconCtrl::LLImagesCacheItem data) LLIconCtrl::setValue("default_profile_picture.j2c"); } - // Update color of status symbol and tool tip - if (data.flags & AVATAR_ONLINE) + // Can only see online status of friends + if (LLAvatarTracker::instance().isBuddy(mAvatarId)) { - mStatusSymbol->setColor(LLColor4::green); - if (mDrawTooltip) + if (LLAvatarTracker::instance().isBuddyOnline(mAvatarId)) { - setToolTip((LLStringExplicit)"Online"); + // Update color of status symbol and tool tip + mStatusSymbol->setColor(LLColor4::green); + if (mDrawTooltip) + { + setToolTip((LLStringExplicit)"Online"); + } + } + else + { + mStatusSymbol->setColor(LLColor4::grey); + if (mDrawTooltip) + { + setToolTip((LLStringExplicit)"Offline"); + } } } else { + // Not a buddy, no information mStatusSymbol->setColor(LLColor4::grey); if (mDrawTooltip) { - setToolTip((LLStringExplicit)"Offline"); + setToolTip((LLStringExplicit)""); } } } diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 7326e39af3..e3440ee779 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -320,6 +320,12 @@ const LLRelationship* LLAvatarTracker::getBuddyInfo(const LLUUID& id) const return get_ptr_in_map(mBuddyInfo, id); } +bool LLAvatarTracker::isBuddy(const LLUUID& id) const +{ + LLRelationship* info = get_ptr_in_map(mBuddyInfo, id); + return (info != NULL); +} + // online status void LLAvatarTracker::setBuddyOnline(const LLUUID& id, bool is_online) { diff --git a/indra/newview/llcallingcard.h b/indra/newview/llcallingcard.h index 113f16de70..228239b5ba 100644 --- a/indra/newview/llcallingcard.h +++ b/indra/newview/llcallingcard.h @@ -125,6 +125,9 @@ public: // get full info const LLRelationship* getBuddyInfo(const LLUUID& id) const; + // Is this person a friend/buddy/calling card holder? + bool isBuddy(const LLUUID& id) const; + // online status void setBuddyOnline(const LLUUID& id, bool is_online); bool isBuddyOnline(const LLUUID& id) const; -- cgit v1.2.3 From 4814ee159a640a9916554c1d069f36ccea76109d Mon Sep 17 00:00:00 2001 From: Erica Olsen Date: Tue, 29 Sep 2009 00:48:25 +0000 Subject: EXT-1199 Small layout tweaks, EXT-927 'Block object by name' dialog is broken --- .../skins/default/xui/en/accordion_parent.xml | 2 +- .../skins/default/xui/en/floater_mute_object.xml | 49 ++++++++++++---------- .../skins/default/xui/en/floater_ui_preview.xml | 18 ++++---- indra/newview/skins/default/xui/en/panel_login.xml | 47 +++++++++------------ .../skins/default/xui/en/widgets/accordion_tab.xml | 10 ++--- .../skins/default/xui/en/widgets/filter_editor.xml | 8 ++-- .../skins/default/xui/en/widgets/scroll_list.xml | 8 ++-- 7 files changed, 69 insertions(+), 73 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/en/accordion_parent.xml b/indra/newview/skins/default/xui/en/accordion_parent.xml index 914a6eddb9..ea34bac0a7 100644 --- a/indra/newview/skins/default/xui/en/accordion_parent.xml +++ b/indra/newview/skins/default/xui/en/accordion_parent.xml @@ -1,5 +1,5 @@ - - Block by name only affects object chat and IM, not sounds. -You must type the object's name exactly. + left="10" + top="25" + name="message"> + Block an object: + top_pad="5" + width="350"> Object name + + * Only blocks object text, not sounds + -- cgit v1.2.3 From 606b381c9fbc43c214afd26fb2e2598eec656b66 Mon Sep 17 00:00:00 2001 From: Steven Bennetts Date: Tue, 29 Sep 2009 19:37:05 +0000 Subject: merge https://svn.aws.productengine.com/secondlife/export-from-ll/viewer-2-0@1830 https://svn.aws.productengine.com/secondlife/pe/stable-2@1839 -> viewer-2.0.0-3 JIRAS: EXT-96 EXT-204 EXT-312 EXT-334 EXT-479 EXT-498 EXT-514 EXT-637 EXT-647 EXT-746 EXT-748 EXT-749 EXT-757 EXT-789 EXT-794 EXT-808 EXT-817 EXT-823 EXT-831 EXT-834 EXT-837 EXT-844 EXT-848 EXT-862 EXT-876 EXT-896 EXT-897 EXT-898 EXT-899 EXT-910 EXT-912 EXT-918 EXT-921 EXT-925 EXT-926 EXT-928 EXT-930 EXT-931 EXT-935 EXT-938 EXT-939 EXT-952 EXT-985 EXT-986 EXT-992 EXT-994 EXT-995 EXT-996 EXT-997 EXT-998 EXT-1001 EXT-1004 EXT-1010 EXT-1012 EXT-1016 EXT-1018 EXT-1020 EXT-1028 EXT-1041 EXT-1044 EXT-1051 EXT-1052 EXT-1061 EXT-1069 EXT-1071 EXT-1074 EXT-1075 EXT-1076 EXT-1078 EXT-1080 EXT-1081 EXT-1082 EXT-1083 EXT-1085 EXT-1092 EXT-1093 EXT-1099 EXT-1100 EXT-1101 EXT-1104 EXT-1106 EXT-1111 EXT-1113 EXT-1114 EXT-1115 EXT-1116 EXT-1118 EXT-1119 EXT-1129 EXT-1132 EXT-1135 EXT-1138 EXT-1142 EXT-1161 EXT-1162 EXT-1178 EXT-1180 * NEW DEVELOPMENT: * EXT-898 - Add dock/undock support for camera and movement controls * Avatar list changes * Bottom bar changes: menu, docking, visibility * Camera changes * Camera & Movement Floaters * Dockable Floaters (LLDockableFloater) * Removed LLListCtrl * Toast / Notification changes: signal / destruction changes, ordering * Nearby chat input should display active voice indicator QA NOTES: * Message Well Window is ready to be tested for regression & matching the spec. * Verify Group List Item L&F * Verify All tabs in People Panel * Verify that Picks behavior is not changed --- indra/newview/CMakeLists.txt | 9 +- indra/newview/app_settings/settings.xml | 50 +- indra/newview/llavataractions.cpp | 59 +++ indra/newview/llavataractions.h | 16 + indra/newview/llavatarlist.cpp | 506 +++++--------------- indra/newview/llavatarlist.h | 89 ++-- indra/newview/llavatarlistitem.cpp | 50 +- indra/newview/llavatarlistitem.h | 18 +- indra/newview/llavatarpropertiesprocessor.cpp | 19 +- indra/newview/llavatarpropertiesprocessor.h | 2 +- indra/newview/llbottomtray.cpp | 78 ++-- indra/newview/llbottomtray.h | 13 +- indra/newview/llchannelmanager.cpp | 126 +++-- indra/newview/llchannelmanager.h | 39 +- indra/newview/llchiclet.cpp | 55 ++- indra/newview/llchiclet.h | 15 +- indra/newview/llexpandabletextbox.cpp | 508 +++++++++++++++++++++ indra/newview/llexpandabletextbox.h | 237 ++++++++++ indra/newview/llfavoritesbar.cpp | 125 ++++- indra/newview/llfavoritesbar.h | 18 +- indra/newview/llfloatercamera.cpp | 91 ++-- indra/newview/llfloatercamera.h | 24 +- indra/newview/llfloaterpreference.cpp | 4 + indra/newview/llgrouplist.cpp | 206 ++++++++- indra/newview/llgrouplist.h | 53 ++- indra/newview/llimfloater.cpp | 416 +++++++++++++++++ indra/newview/llimfloater.h | 112 +++++ indra/newview/llimhandler.cpp | 69 ++- indra/newview/llimpanel.cpp | 316 +------------ indra/newview/llimpanel.h | 64 --- indra/newview/llimview.cpp | 19 +- indra/newview/llimview.h | 3 +- indra/newview/llinventorybridge.cpp | 9 +- indra/newview/lllandmarkactions.cpp | 35 +- indra/newview/lllandmarkactions.h | 14 +- indra/newview/lllocationinputctrl.cpp | 14 +- indra/newview/llmoveview.cpp | 95 +++- indra/newview/llmoveview.h | 12 +- indra/newview/llnearbychat.cpp | 2 +- indra/newview/llnearbychatbar.cpp | 30 ++ indra/newview/llnearbychatbar.h | 2 + indra/newview/llnearbychathandler.cpp | 52 +-- indra/newview/llnearbychathandler.h | 6 +- indra/newview/llnotificationalerthandler.cpp | 53 ++- indra/newview/llnotificationgrouphandler.cpp | 77 ++-- indra/newview/llnotificationhandler.h | 113 +++-- indra/newview/llnotificationmanager.cpp | 26 +- indra/newview/llnotificationmanager.h | 6 +- indra/newview/llnotificationscripthandler.cpp | 135 ++++++ indra/newview/llnotificationtiphandler.cpp | 113 +++++ indra/newview/lloutputmonitorctrl.cpp | 10 +- indra/newview/lloutputmonitorctrl.h | 4 + indra/newview/llpanelavatar.cpp | 3 +- indra/newview/llpanelgroup.cpp | 154 +++++-- indra/newview/llpanelgroup.h | 8 + indra/newview/llpanelgroupgeneral.cpp | 58 +-- indra/newview/llpanelgroupgeneral.h | 1 - indra/newview/llpanelimcontrolpanel.cpp | 3 + indra/newview/llpanelpeople.cpp | 188 +++++--- indra/newview/llpanelpeople.h | 9 +- indra/newview/llpanelpeoplemenus.cpp | 148 ++++++ indra/newview/llpanelpeoplemenus.h | 82 ++++ indra/newview/llpanelpick.cpp | 122 ++++- indra/newview/llpanelpick.h | 21 +- indra/newview/llpanelpicks.cpp | 18 +- indra/newview/llpanelpicks.h | 7 +- indra/newview/llpanelplaceinfo.cpp | 81 ++-- indra/newview/llpanelplaceinfo.h | 8 +- indra/newview/llpanelplaces.cpp | 91 +++- indra/newview/llpanelplaces.h | 3 + indra/newview/llpanelprofile.cpp | 9 - indra/newview/llpanelprofile.h | 7 - indra/newview/llpanelprofileview.cpp | 21 + indra/newview/llpanelprofileview.h | 10 + indra/newview/llpanelteleporthistory.cpp | 245 +++++++--- indra/newview/llpanelteleporthistory.h | 17 +- indra/newview/llrecentpeople.cpp | 19 +- indra/newview/llrecentpeople.h | 4 +- indra/newview/llremoteparcelrequest.cpp | 3 +- indra/newview/llscreenchannel.cpp | 173 +++++-- indra/newview/llscreenchannel.h | 57 ++- indra/newview/llstatusbar.cpp | 40 -- indra/newview/llstatusbar.h | 3 - indra/newview/llsyswellitem.cpp | 11 +- indra/newview/llsyswellitem.h | 6 +- indra/newview/llsyswellwindow.cpp | 400 ++++++++++------ indra/newview/llsyswellwindow.h | 53 ++- indra/newview/lltoast.cpp | 36 +- indra/newview/lltoast.h | 38 +- indra/newview/lltoastimpanel.cpp | 15 +- indra/newview/lltoastimpanel.h | 2 +- indra/newview/lltoastnotifypanel.cpp | 1 + indra/newview/lltooldraganddrop.cpp | 2 + indra/newview/lltooldraganddrop.h | 6 + indra/newview/llviewercontrol.cpp | 37 ++ indra/newview/llviewerfloaterreg.cpp | 2 + indra/newview/llviewermenu.cpp | 1 + indra/newview/llviewermessage.cpp | 1 + indra/newview/llviewerwindow.cpp | 33 +- indra/newview/llviewerwindow.h | 5 + indra/newview/llvoiceclient.cpp | 1 + indra/newview/llvoiceclient.h | 2 +- indra/newview/skins/default/textures/textures.xml | 3 + .../skins/default/xui/en/favorites_bar_button.xml | 10 +- .../skins/default/xui/en/floater_camera.xml | 4 +- .../skins/default/xui/en/floater_im_session.xml | 2 +- .../skins/default/xui/en/floater_moveview.xml | 4 +- .../skins/default/xui/en/floater_sys_well.xml | 33 +- .../skins/default/xui/en/menu_bottomtray.xml | 44 ++ .../skins/default/xui/en/menu_hide_navbar.xml | 20 +- .../xui/en/menu_people_groups_view_sort.xml | 16 + .../skins/default/xui/en/menu_people_nearby.xml | 65 +++ .../xui/en/menu_people_recent_view_sort.xml | 4 +- indra/newview/skins/default/xui/en/menu_viewer.xml | 34 +- .../default/xui/en/panel_avatar_list_item.xml | 2 +- .../skins/default/xui/en/panel_bottomtray.xml | 62 +-- .../default/xui/en/panel_group_info_sidetray.xml | 43 +- .../skins/default/xui/en/panel_group_list_item.xml | 66 +++ .../skins/default/xui/en/panel_instant_message.xml | 12 +- .../skins/default/xui/en/panel_navigation_bar.xml | 1 + .../newview/skins/default/xui/en/panel_people.xml | 8 +- .../skins/default/xui/en/panel_pick_list_item.xml | 2 + indra/newview/skins/default/xui/en/panel_picks.xml | 14 +- .../newview/skins/default/xui/en/panel_profile.xml | 14 +- .../default/xui/en/panel_side_tray_tab_caption.xml | 1 + .../skins/default/xui/en/panel_sys_well_item.xml | 2 +- .../default/xui/en/panel_teleport_history.xml | 120 ++--- .../default/xui/en/panel_teleport_history_item.xml | 65 +++ indra/newview/skins/default/xui/en/strings.xml | 2 +- .../default/xui/en/widgets/expandable_text.xml | 27 ++ .../default/xui/en/widgets/flat_list_view.xml | 3 +- .../newview/skins/default/xui/en/widgets/list.xml | 10 - .../default/xui/en/widgets/location_input.xml | 3 +- .../skins/default/xui/en/widgets/scroll_list.xml | 4 +- 134 files changed, 4970 insertions(+), 2212 deletions(-) create mode 100644 indra/newview/llexpandabletextbox.cpp create mode 100644 indra/newview/llexpandabletextbox.h create mode 100644 indra/newview/llimfloater.cpp create mode 100644 indra/newview/llimfloater.h create mode 100644 indra/newview/llnotificationscripthandler.cpp create mode 100644 indra/newview/llnotificationtiphandler.cpp create mode 100644 indra/newview/llpanelpeoplemenus.cpp create mode 100644 indra/newview/llpanelpeoplemenus.h create mode 100644 indra/newview/skins/default/xui/en/menu_bottomtray.xml create mode 100644 indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml create mode 100644 indra/newview/skins/default/xui/en/menu_people_nearby.xml create mode 100644 indra/newview/skins/default/xui/en/panel_group_list_item.xml create mode 100644 indra/newview/skins/default/xui/en/panel_teleport_history_item.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/expandable_text.xml delete mode 100644 indra/newview/skins/default/xui/en/widgets/list.xml (limited to 'indra/newview') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 8a59b34332..e4e4d8a2fa 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -128,6 +128,7 @@ set(viewer_SOURCE_FILES lleventinfo.cpp lleventnotifier.cpp lleventpoll.cpp + llexpandabletextbox.cpp llface.cpp llfasttimerview.cpp llfavoritesbar.cpp @@ -233,6 +234,7 @@ set(viewer_SOURCE_FILES llhudrender.cpp llhudtext.cpp llhudview.cpp + llimfloater.cpp llimhandler.cpp llimpanel.cpp llimview.cpp @@ -276,8 +278,9 @@ set(viewer_SOURCE_FILES llnetmap.cpp llnotificationalerthandler.cpp llnotificationgrouphandler.cpp - llnotificationinfohandler.cpp llnotificationmanager.cpp + llnotificationscripthandler.cpp + llnotificationtiphandler.cpp llnotify.cpp lloutputmonitorctrl.cpp lloverlaybar.cpp @@ -320,6 +323,7 @@ set(viewer_SOURCE_FILES llpanelmovetip.cpp llpanelobject.cpp llpanelpeople.cpp + llpanelpeoplemenus.cpp llpanelpermissions.cpp llpanelpick.cpp llpanelpicks.cpp @@ -587,6 +591,7 @@ set(viewer_HEADER_FILES lleventinfo.h lleventnotifier.h lleventpoll.h + llexpandabletextbox.h llface.h llfasttimerview.h llfavoritesbar.h @@ -692,6 +697,7 @@ set(viewer_HEADER_FILES llhudrender.h llhudtext.h llhudview.h + llimfloater.h llimpanel.h llimview.h llimcontrolpanel.h @@ -777,6 +783,7 @@ set(viewer_HEADER_FILES llpanelmovetip.h llpanelobject.h llpanelpeople.h + llpanelpeoplemenus.h llpanelpermissions.h llpanelpick.h llpanelpicks.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index c794d7d319..19d503390c 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4884,18 +4884,7 @@ Type S32 Value - 10 - - NavBarMargin - - Comment - Width of notification messages - Persist - 1 - Type - S32 - Value - 60 + 35 OverflowToastHeight @@ -7520,10 +7509,10 @@ Value 1 - ShowCameraAndMoveControls + ShowCameraButton Comment - Show/Hide Camera and Move controls in the bottom tray + Show/Hide Camera button in the bottom tray Persist 1 Type @@ -7531,6 +7520,28 @@ Value 1 + ShowMoveButton + + Comment + Show/Hide Move button in the bottom tray + Persist + 1 + Type + Boolean + Value + 1 + + ShowGestureButton + + Comment + Show/Hide Gesture button in the bottom tray + Persist + 1 + Type + Boolean + Value + 1 + ShowNavbarFavoritesPanel Comment @@ -7553,6 +7564,17 @@ Value 1 + GroupListShowIcons + + Comment + Show/hide group icons in the group list + Persist + 1 + Type + Boolean + Value + 1 + ShowPGSearchAll Comment diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 4819703e72..1676bb1d44 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -43,8 +43,11 @@ #include "llappviewer.h" // for gLastVersionChannel #include "llcachename.h" #include "llcallingcard.h" // for LLAvatarTracker +#include "llgivemoney.h" // foe LLFloaterPay #include "llinventorymodel.h" // for gInventory.findCategoryUUIDForType #include "llimview.h" // for gIMMgr +#include "llmutelist.h" +#include "llrecentpeople.h" #include "llsidetray.h" #include "llviewermessage.h" // for handle_lure #include "llviewerregion.h" @@ -206,6 +209,41 @@ void LLAvatarActions::showProfile(const LLUUID& id) } } +// static +void LLAvatarActions::pay(const LLUUID& id) +{ + LLNotification::Params params("BusyModePay"); + params.functor.function(boost::bind(&LLAvatarActions::handlePay, _1, _2, id)); + + if (gAgent.getBusy()) + { + // warn users of being in busy mode during a transaction + LLNotifications::instance().add(params); + } + else + { + LLNotifications::instance().forceResponse(params, 1); + } +} + +// static +void LLAvatarActions::toggleBlock(const LLUUID& id) +{ + std::string name; + + gCacheName->getFullName(id, name); + LLMute mute(id, name, LLMute::AGENT); + + if (LLMuteList::getInstance()->isMuted(mute.mID, mute.mName)) + { + LLMuteList::getInstance()->remove(mute); + } + else + { + LLMuteList::getInstance()->add(mute); + } +} + //== private methods ======================================================================================== // static @@ -242,6 +280,19 @@ bool LLAvatarActions::handleRemove(const LLSD& notification, const LLSD& respons return false; } +// static +bool LLAvatarActions::handlePay(const LLSD& notification, const LLSD& response, LLUUID avatar_id) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + if (option == 0) + { + gAgent.clearBusy(); + } + + LLFloaterPay::payDirectly(&give_money, avatar_id, /*is_group=*/FALSE); + return false; +} + // static bool LLAvatarActions::callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response) { @@ -290,3 +341,11 @@ bool LLAvatarActions::isFriend(const LLUUID& id) { return ( NULL != LLAvatarTracker::instance().getBuddyInfo(id) ); } + +// static +bool LLAvatarActions::isBlocked(const LLUUID& id) +{ + std::string name; + gCacheName->getFullName(id, name); + return LLMuteList::getInstance()->isMuted(id, name); +} diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h index f3c411e033..e911715c70 100644 --- a/indra/newview/llavataractions.h +++ b/indra/newview/llavataractions.h @@ -76,15 +76,31 @@ public: */ static void showProfile(const LLUUID& id); + /** + * Give money to the avatar. + */ + static void pay(const LLUUID& id); + + /** + * Block/unblock the avatar. + */ + static void toggleBlock(const LLUUID& id); + /** * Return true if avatar with "id" is a friend */ static bool isFriend(const LLUUID& id); + /** + * @return true if the avatar is blocked + */ + static bool isBlocked(const LLUUID& id); + private: static bool callbackAddFriend(const LLSD& notification, const LLSD& response); static bool callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response); static bool handleRemove(const LLSD& notification, const LLSD& response); + static bool handlePay(const LLSD& notification, const LLSD& response, LLUUID avatar_id); // Just request friendship, no dialog. static void requestFriendship(const LLUUID& target_id, const std::string& target_name, const std::string& message); diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 2e64c10bb2..ee14a2ff86 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -37,144 +37,9 @@ // newview #include "llcallingcard.h" // for LLAvatarTracker #include "llcachename.h" -#include "lloutputmonitorctrl.h" #include "llvoiceclient.h" static LLDefaultChildRegistry::Register r("avatar_list"); -static LLDefaultChildRegistry::Register r_tmp("avatar_list_tmp"); - -static const std::string COMMENT_TEXTBOX = "comment_text"; - -LLAvatarList::Params::Params() -: - volume_column_width("volume_column_width", 0) - , online_go_first("online_go_first", true) -{ - draw_heading = true; - draw_stripes = false; - multi_select = false; - column_padding = 0; - search_column = COL_NAME; - sort_column = COL_NAME; -} - -LLAvatarList::LLAvatarList(const Params& p) -: LLScrollListCtrl(p) - , mHaveVolumeColumn(p.volume_column_width > 0) - , mOnlineGoFirst(p.online_go_first) -{ - setCommitOnSelectionChange(TRUE); // there's no such param in LLScrollListCtrl::Params - - // display a context menu appropriate for a list of avatar names - setContextMenu(LLScrollListCtrl::MENU_AVATAR); - - // "volume" column - { - LLScrollListColumn::Params col_params; - col_params.name = "volume"; - col_params.header.label = "Volume"; // *TODO: localize or remove the header - col_params.width.pixel_width = p.volume_column_width; - addColumn(col_params); - } - - // "name" column - { - LLScrollListColumn::Params col_params; - col_params.name = "name"; - col_params.header.label = "Name"; // *TODO: localize or remove the header - col_params.width.dynamic_width = true; - addColumn(col_params); - } - - // "online status" column - { - LLScrollListColumn::Params col_params; - col_params.name = "online"; - col_params.header.label = "Online"; // *TODO: localize or remove the header - col_params.width.pixel_width = 0; // invisible column - addColumn(col_params); - } - - - // invisible "id" column - { - LLScrollListColumn::Params col_params; - col_params.name = "id"; - col_params.header.label = "ID"; // *TODO: localize or remove the header - col_params.width.pixel_width = 0; - addColumn(col_params); - } - - // Primary sort = online status, secondary sort = name - // The corresponding parameters don't work because we create columns dynamically. - sortByColumnIndex(COL_NAME, TRUE); - if (mOnlineGoFirst) - sortByColumnIndex(COL_ONLINE, FALSE); - setSearchColumn(COL_NAME); -} - -// virtual -void LLAvatarList::draw() -{ - LLScrollListCtrl::draw(); - if (mHaveVolumeColumn) - { - updateVolume(); - } -} - -std::vector LLAvatarList::getSelectedIDs() -{ - LLUUID selected_id; - std::vector avatar_ids; - std::vector selected = getAllSelected(); - for(std::vector::iterator itr = selected.begin(); itr != selected.end(); ++itr) - { - avatar_ids.push_back((*itr)->getUUID()); - } - return avatar_ids; -} - -void LLAvatarList::addItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos) -{ - std::string fullname; - - // Populate list item. - LLSD element; - element["id"] = id; - - // Update volume column (if we have one) - { - std::string icon = mHaveVolumeColumn ? getVolumeIcon(id) : ""; - LLSD& volume_column = element["columns"][COL_VOLUME]; - volume_column["column"] = "volume"; - volume_column["type"] = "icon"; - volume_column["value"] = icon; - } - - LLSD& friend_column = element["columns"][COL_NAME]; - friend_column["column"] = "name"; - friend_column["value"] = name; - - LLSD& online_column = element["columns"][COL_ONLINE]; - online_column["column"] = "online"; - online_column["value"] = is_bold ? "1" : "0"; - - LLScrollListItem* new_itemp = addElement(element, pos); - - // Indicate buddy online status. - // (looks like parsing font parameters from LLSD is broken) - if (is_bold) - { - LLScrollListText* name_textp = dynamic_cast(new_itemp->getColumn(COL_NAME)); - if (name_textp) - name_textp->setFontStyle(LLFontGL::BOLD); - else - { - llwarns << "Name column not found" << llendl; - } - } -} static bool findInsensitive(std::string haystack, const std::string& needle_upper) { @@ -182,136 +47,12 @@ static bool findInsensitive(std::string haystack, const std::string& needle_uppe return haystack.find(needle_upper) != std::string::npos; } -BOOL LLAvatarList::update(const std::vector& all_buddies, const std::string& name_filter) -{ - BOOL have_names = TRUE; - - // Save selection. - std::vector selected_ids = getSelectedIDs(); - LLUUID current_id = getCurrentID(); - S32 pos = getScrollPos(); - - std::vector::const_iterator buddy_it = all_buddies.begin(); - deleteAllItems(); - for(; buddy_it != all_buddies.end(); ++buddy_it) - { - std::string name; - const LLUUID& buddy_id = *buddy_it; - have_names &= gCacheName->getFullName(buddy_id, name); - if (name_filter != LLStringUtil::null && !findInsensitive(name, name_filter)) - continue; - addItem(buddy_id, name, LLAvatarTracker::instance().isBuddyOnline(buddy_id)); - } - - // Changed item in place, need to request sort and update columns - // because we might have changed data in a column on which the user - // has already sorted. JC - updateSort(); - - // re-select items - selectMultiple(selected_ids); - setCurrentByID(current_id); -#if 0 - // Restore selection. - if(selected_ids.size() > 0) - { - // only non-null if friends was already found. This may fail, - // but we don't really care here, because refreshUI() will - // clean up the interface. - for(std::vector::iterator itr = selected_ids.begin(); itr != selected_ids.end(); ++itr) - { - setSelectedByValue(*itr, true); - } - } -#endif - setScrollPos(pos); - - updateLineHeight(); - LLRect rect = getRequiredRect(); - - LLSD params; - params["action"] = "size_changes"; - params["width"] = rect.getWidth(); - params["height"] = llmax(rect.getHeight(),20) + 5; - - getParent()->notifyParent(params); - - return have_names; -} -// static -std::string LLAvatarList::getVolumeIcon(const LLUUID& id) -{ - // - // Determine icon appropriate for the current avatar volume. - // - // *TODO: remove this in favor of LLOutputMonitorCtrl - // when ListView widget is implemented - // which is capable of containing arbitrary widgets. - // - static LLOutputMonitorCtrl::Params default_monitor_params(LLUICtrlFactory::getDefaultParams()); - bool muted = gVoiceClient->getIsModeratorMuted(id) || gVoiceClient->getOnMuteList(id); - F32 power = gVoiceClient->getCurrentPower(id); - std::string icon; - - if (muted) - { - icon = default_monitor_params.image_mute.name; - } - else if (power == 0.f) - { - icon = default_monitor_params.image_off.name; - } - else if (power < LLVoiceClient::OVERDRIVEN_POWER_LEVEL) - { - S32 icon_image_idx = llmin(2, llfloor((power / LLVoiceClient::OVERDRIVEN_POWER_LEVEL) * 3.f)); - switch(icon_image_idx) - { - default: - case 0: - icon = default_monitor_params.image_on.name; - break; - case 1: - icon = default_monitor_params.image_level_1.name; - break; - case 2: - icon = default_monitor_params.image_level_2.name; - break; - } - } - else - { - // overdriven - icon = default_monitor_params.image_level_3.name; - } - - return icon; -} - -// Update volume column for all list rows. -void LLAvatarList::updateVolume() -{ - item_list& items = getItemList(); +//comparators +static const LLAvatarItemNameComparator NAME_COMPARATOR; +static const LLFlatListView::ItemReverseComparator REVERSE_NAME_COMPARATOR(NAME_COMPARATOR); - for (item_list::iterator item_it = items.begin(); - item_it != items.end(); - ++item_it) - { - LLScrollListItem* itemp = (*item_it); - LLUUID speaker_id = itemp->getUUID(); - - LLScrollListCell* icon_cell = itemp->getColumn(COL_VOLUME); - if (icon_cell) - icon_cell->setValue(getVolumeIcon(speaker_id)); - } -} - - - - -#include "llavatarlistitem.h" - -LLAvatarListTmp::Params::Params() +LLAvatarList::Params::Params() : volume_column_width("volume_column_width", 0) , online_go_first("online_go_first", true) @@ -320,198 +61,163 @@ volume_column_width("volume_column_width", 0) -LLAvatarListTmp::LLAvatarListTmp(const Params& p) +LLAvatarList::LLAvatarList(const Params& p) : LLFlatListView(p) -, mHaveVolumeColumn(p.volume_column_width > 0) , mOnlineGoFirst(p.online_go_first) +, mContextMenu(NULL) { - LLRect item_list_rect = getLocalRect(); - item_list_rect.stretch( -getBorderWidth()); - - LLTextBox::Params text_p; - text_p.name(COMMENT_TEXTBOX); - text_p.border_visible(false); - text_p.rect(item_list_rect); - text_p.follows.flags(FOLLOWS_ALL); - addChild(LLUICtrlFactory::create(text_p)); -} + setCommitOnSelectionChange(true); -// virtual -void LLAvatarListTmp::draw() -{ - LLFlatListView::draw(); - if (mHaveVolumeColumn) - { - updateVolume(); - } + // Set default sort order. + setComparator(&NAME_COMPARATOR); } -std::vector LLAvatarListTmp::getSelectedIDs() +void LLAvatarList::computeDifference( + const std::vector& vnew_unsorted, + std::vector& vadded, + std::vector& vremoved) { - LLUUID selected_id; - std::vector avatar_ids; + std::vector vcur; + std::vector vnew = vnew_unsorted; - getSelectedUUIDs(avatar_ids); + // Convert LLSDs to LLUUIDs. + { + std::vector vcur_values; + getValues(vcur_values); - return avatar_ids; -} + for (size_t i=0; ishowStatus(true); - item->showInfoBtn(true); - item->showSpeakingIndicator(true); - item->setName(name); - item->setAvatarId(id); + std::sort(vcur.begin(), vcur.end()); + std::sort(vnew.begin(), vnew.end()); - item->childSetVisible("info_btn", false); + std::vector::iterator it; + size_t maxsize = llmax(vcur.size(), vnew.size()); + vadded.resize(maxsize); + vremoved.resize(maxsize); - addItem(item, id, pos); + // what to remove + it = set_difference(vcur.begin(), vcur.end(), vnew.begin(), vnew.end(), vremoved.begin()); + vremoved.erase(it, vremoved.end()); - setCommentVisible(false); + // what to add + it = set_difference(vnew.begin(), vnew.end(), vcur.begin(), vcur.end(), vadded.begin()); + vadded.erase(it, vadded.end()); } -BOOL LLAvatarListTmp::update(const std::vector& all_buddies, const std::string& name_filter) +BOOL LLAvatarList::update(const std::vector& all_buddies, const std::string& name_filter) { BOOL have_names = TRUE; + bool have_filter = name_filter != LLStringUtil::null; // Save selection. - std::vector selected_ids = getSelectedIDs(); + std::vector selected_ids; + getSelectedUUIDs(selected_ids); LLUUID current_id = getSelectedUUID(); - LLRect pos = getScrolledViewRect(); - std::vector::const_iterator buddy_it = all_buddies.begin(); - clear(); - for(; buddy_it != all_buddies.end(); ++buddy_it) + // Determine what to add and what to remove. + std::vector added, removed; + LLAvatarList::computeDifference(all_buddies, added, removed); + + // Handle added items. + for (std::vector::const_iterator it=added.begin(); it != added.end(); it++) { std::string name; - const LLUUID& buddy_id = *buddy_it; + const LLUUID& buddy_id = *it; have_names &= gCacheName->getFullName(buddy_id, name); - if (name_filter != LLStringUtil::null && !findInsensitive(name, name_filter)) - continue; + if (!have_filter || findInsensitive(name, name_filter)) addNewItem(buddy_id, name, LLAvatarTracker::instance().isBuddyOnline(buddy_id)); } + // Handle removed items. + for (std::vector::const_iterator it=removed.begin(); it != removed.end(); it++) + { + removeItemByUUID(*it); + } + + // Handle filter. + if (have_filter) + { + std::vector cur_values; + getValues(cur_values); + + for (std::vector::const_iterator it=cur_values.begin(); it != cur_values.end(); it++) + { + std::string name; + const LLUUID& buddy_id = it->asUUID(); + have_names &= gCacheName->getFullName(buddy_id, name); + if (!findInsensitive(name, name_filter)) + removeItemByUUID(buddy_id); + } + } + // Changed item in place, need to request sort and update columns // because we might have changed data in a column on which the user // has already sorted. JC - // updateSort(); // TODO: implement sorting + sort(); // re-select items // selectMultiple(selected_ids); // TODO: implement in LLFlatListView if need selectItemByUUID(current_id); - scrollToShowRect(pos); - - - setCommentVisible(false); - - return have_names; -} - - -const LLUUID LLAvatarListTmp::getCurrentID() const -{ - return getSelectedUUID(); + // If the name filter is specified and the names are incomplete, + // we need to re-update when the names are complete so that + // the filter can be applied correctly. + // + // Otherwise, if we have no filter then no need to update again + // because the items will update their names. + return !have_filter || have_names; } -void LLAvatarListTmp::setCommentText(const std::string& comment_text) +void LLAvatarList::sortByName() { - getChild(COMMENT_TEXTBOX)->setValue(comment_text); + setComparator(&NAME_COMPARATOR); + sort(); } - ////////////////////////////////////////////////////////////////////////// // PROTECTED SECTION ////////////////////////////////////////////////////////////////////////// - -// virtual overridden -bool LLAvatarListTmp::removeItemPair(item_pair_t* item_pair) +void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos) { - bool removed = LLFlatListView::removeItemPair(item_pair); - setCommentVisible(size() == 0); - return removed; + LLAvatarListItem* item = new LLAvatarListItem(); + item->showStatus(false); + item->showInfoBtn(true); + item->showSpeakingIndicator(true); + item->setName(name); + item->setAvatarId(id); + item->setContextMenu(mContextMenu); + + item->childSetVisible("info_btn", false); + + addItem(item, id, pos); } -////////////////////////////////////////////////////////////////////////// -// PRIVATE SECTION -////////////////////////////////////////////////////////////////////////// -// static -std::string LLAvatarListTmp::getVolumeIcon(const LLUUID& id) -{ - // - // Determine icon appropriate for the current avatar volume. - // - // *TODO: remove this in favor of LLOutputMonitorCtrl - // when ListView widget is implemented - // which is capable of containing arbitrary widgets. - // - static LLOutputMonitorCtrl::Params default_monitor_params(LLUICtrlFactory::getDefaultParams()); - bool muted = gVoiceClient->getIsModeratorMuted(id) || gVoiceClient->getOnMuteList(id); - F32 power = gVoiceClient->getCurrentPower(id); - std::string icon; - if (muted) - { - icon = default_monitor_params.image_mute.name; - } - else if (power == 0.f) - { - icon = default_monitor_params.image_off.name; - } - else if (power < LLVoiceClient::OVERDRIVEN_POWER_LEVEL) - { - S32 icon_image_idx = llmin(2, llfloor((power / LLVoiceClient::OVERDRIVEN_POWER_LEVEL) * 3.f)); - switch(icon_image_idx) - { - default: - case 0: - icon = default_monitor_params.image_on.name; - break; - case 1: - icon = default_monitor_params.image_level_1.name; - break; - case 2: - icon = default_monitor_params.image_level_2.name; - break; - } - } - else +bool LLAvatarItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const +{ + const LLAvatarListItem* avatar_item1 = dynamic_cast(item1); + const LLAvatarListItem* avatar_item2 = dynamic_cast(item2); + + if (!avatar_item1 || !avatar_item2) { - // overdriven - icon = default_monitor_params.image_level_3.name; + llerror("item1 and item2 cannot be null", 0); + return true; } - return icon; + return doCompare(avatar_item1, avatar_item2); } -// Update volume column for all list rows. -void LLAvatarListTmp::updateVolume() +bool LLAvatarItemNameComparator::doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const { - // TODO: implement via Listener - /* - item_list& items = getItemList(); + std::string name1 = avatar_item1->getAvatarName(); + std::string name2 = avatar_item2->getAvatarName(); - for (item_list::iterator item_it = items.begin(); - item_it != items.end(); - ++item_it) - { - LLScrollListItem* itemp = (*item_it); - LLUUID speaker_id = itemp->getUUID(); + LLStringUtil::toUpper(name1); + LLStringUtil::toUpper(name2); - LLScrollListCell* icon_cell = itemp->getColumn(COL_VOLUME); - if (icon_cell) - icon_cell->setValue(getVolumeIcon(speaker_id)); - } - */ + return name1 < name2; } - -void LLAvatarListTmp::setCommentVisible(bool visible) const -{ - getChildView(COMMENT_TEXTBOX)->setVisible(visible); -} - -// EOF diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h index 639ed83ada..8d79e073d2 100644 --- a/indra/newview/llavatarlist.h +++ b/indra/newview/llavatarlist.h @@ -33,88 +33,77 @@ #ifndef LL_LLAVATARLIST_H #define LL_LLAVATARLIST_H -#include +#include "llflatlistview.h" + +#include "llavatarlistitem.h" -// *TODO: derive from ListView when it's ready. -class LLAvatarList : public LLScrollListCtrl +class LLAvatarList : public LLFlatListView { LOG_CLASS(LLAvatarList); public: - struct Params : public LLInitParam::Block + struct Params : public LLInitParam::Block { Optional volume_column_width; Optional online_go_first; Params(); }; - enum EColumnOrder - { - COL_VOLUME, - COL_NAME, - COL_ONLINE, - COL_ID, - }; - LLAvatarList(const Params&); virtual ~LLAvatarList() {} - /*virtual*/ void draw(); - BOOL update(const std::vector& all_buddies, const std::string& name_filter = LLStringUtil::null); + void setContextMenu(LLAvatarListItem::ContextMenu* menu) { mContextMenu = menu; } + + void sortByName(); + protected: - std::vector getSelectedIDs(); - void addItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos = ADD_BOTTOM); + void addNewItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos = ADD_BOTTOM); + void computeDifference( + const std::vector& vnew, + std::vector& vadded, + std::vector& vremoved); private: - static std::string getVolumeIcon(const LLUUID& id); /// determine volume icon from current avatar volume - void updateVolume(); // update volume for all avatars - bool mHaveVolumeColumn; bool mOnlineGoFirst; -}; - -#include "llflatlistview.h" + LLAvatarListItem::ContextMenu* mContextMenu; +}; -class LLAvatarListTmp : public LLFlatListView +/** Abstract comparator for avatar items */ +class LLAvatarItemComparator : public LLFlatListView::ItemComparator { - LOG_CLASS(LLAvatarListTmp); -public: - struct Params : public LLInitParam::Block - { - Optional volume_column_width; - Optional online_go_first; - Params(); - }; - - LLAvatarListTmp(const Params&); - virtual ~LLAvatarListTmp() {} - - /*virtual*/ void draw(); + LOG_CLASS(LLAvatarItemComparator); - BOOL update(const std::vector& all_buddies, - const std::string& name_filter = LLStringUtil::null); +public: + LLAvatarItemComparator() {}; + virtual ~LLAvatarItemComparator() {}; - const LLUUID getCurrentID() const; - void setCommentText( const std::string& comment_text); + virtual bool compare(const LLPanel* item1, const LLPanel* item2) const; protected: - std::vector getSelectedIDs(); - void addNewItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos = ADD_BOTTOM); - /*virtual*/ bool removeItemPair(item_pair_t* item_pair); -private: - static std::string getVolumeIcon(const LLUUID& id); /// determine volume icon from current avatar volume - void updateVolume(); // update volume for all avatars - void setCommentVisible(bool visible) const; + /** + * Returns true if avatar_item1 < avatar_item2, false otherwise + * Implement this method in your particular comparator. + * In Linux a compiler failed to build it using the name "compare", so it was renamed to doCompare + */ + virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const = 0; +}; - bool mHaveVolumeColumn; - bool mOnlineGoFirst; -}; +class LLAvatarItemNameComparator : public LLAvatarItemComparator +{ + LOG_CLASS(LLAvatarItemNameComparator); +public: + LLAvatarItemNameComparator() {}; + virtual ~LLAvatarItemNameComparator() {}; +protected: + virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const; +}; #endif // LL_LLAVATARLIST_H diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp index feae8202bc..665dffc8c6 100644 --- a/indra/newview/llavatarlistitem.cpp +++ b/indra/newview/llavatarlistitem.cpp @@ -48,7 +48,9 @@ LLAvatarListItem::LLAvatarListItem() mAvatarName(NULL), mStatus(NULL), mSpeakingIndicator(NULL), - mInfoBtn(NULL) + mInfoBtn(NULL), + mContextMenu(NULL), + mAvatarId(LLUUID::null) { LLUICtrlFactory::getInstance()->buildPanel(this, "panel_avatar_list_item.xml"); } @@ -114,6 +116,15 @@ void LLAvatarListItem::onMouseLeave(S32 x, S32 y, MASK mask) LLPanel::onMouseLeave(x, y, mask); } +// virtual +BOOL LLAvatarListItem::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + if (mContextMenu) + mContextMenu->show(this, const_cast(mAvatarId), x, y); + + return LLPanel::handleRightMouseDown(x, y, mask); +} + void LLAvatarListItem::setStatus(const std::string& status) { mStatus->setValue(status); @@ -127,13 +138,17 @@ void LLAvatarListItem::setName(const std::string& name) void LLAvatarListItem::setAvatarId(const LLUUID& id) { + mAvatarId = id; mAvatarIcon->setValue(id); mSpeakingIndicator->setSpeakerId(id); + + // Set avatar name. + gCacheName->get(id, FALSE, boost::bind(&LLAvatarListItem::onNameCache, this, _2, _3)); } void LLAvatarListItem::onInfoBtnClick() { - LLFloaterReg::showInstance("inspect_avatar", mAvatarIcon->getValue()); + LLFloaterReg::showInstance("inspect_avatar", mAvatarId); /* TODO fix positioning of inspector localPointToScreen(mXPos, mYPos, &mXPos, &mYPos); @@ -156,6 +171,21 @@ void LLAvatarListItem::onInfoBtnClick() */ } +void LLAvatarListItem::showStatus(bool show_status) +{ + // *HACK: dirty hack until we can determine correct avatar status (EXT-1076). + + if (show_status) + return; + + LLRect name_rect = mAvatarName->getRect(); + LLRect status_rect = mStatus->getRect(); + + mStatus->setVisible(show_status); + name_rect.mRight += (status_rect.mRight - name_rect.mRight); + mAvatarName->setRect(name_rect); +} + void LLAvatarListItem::setValue( const LLSD& value ) { if (!value.isMap()) return;; @@ -163,3 +193,19 @@ void LLAvatarListItem::setValue( const LLSD& value ) childSetVisible("selected_icon", value["selected"]); } +const LLUUID& LLAvatarListItem::getAvatarId() const +{ + return mAvatarId; +} + +const std::string LLAvatarListItem::getAvatarName() const +{ + return mAvatarName->getValue(); +} + +void LLAvatarListItem::onNameCache(const std::string& first_name, const std::string& last_name) +{ + std::string name = first_name + " " + last_name; + mAvatarName->setValue(name); + mAvatarName->setToolTip(name); +} diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h index dc5606e4c2..bde9250e4a 100644 --- a/indra/newview/llavatarlistitem.h +++ b/indra/newview/llavatarlistitem.h @@ -43,32 +43,48 @@ class LLAvatarIconCtrl; class LLAvatarListItem : public LLPanel { public: + class ContextMenu + { + public: + virtual void show(LLView* spawning_view, const LLUUID& id, S32 x, S32 y) = 0; + }; + LLAvatarListItem(); virtual ~LLAvatarListItem() {}; virtual BOOL postBuild(); virtual void onMouseLeave(S32 x, S32 y, MASK mask); virtual void onMouseEnter(S32 x, S32 y, MASK mask); + virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); virtual void setValue(const LLSD& value); void setStatus(const std::string& status); void setName(const std::string& name); void setAvatarId(const LLUUID& id); + + const LLUUID& getAvatarId() const; + const std::string getAvatarName() const; void onInfoBtnClick(); void showSpeakingIndicator(bool show) { mSpeakingIndicator->setVisible(show); } void showInfoBtn(bool show_info_btn) {mInfoBtn->setVisible(show_info_btn); } - void showStatus(bool show_status) {mStatus->setVisible(show_status); } + void showStatus(bool show_status); + void setContextMenu(ContextMenu* menu) { mContextMenu = menu; } private: + void onNameCache(const std::string& first_name, const std::string& last_name); + LLAvatarIconCtrl*mAvatarIcon; LLTextBox* mAvatarName; LLTextBox* mStatus; LLOutputMonitorCtrl* mSpeakingIndicator; LLButton* mInfoBtn; + ContextMenu* mContextMenu; + + LLUUID mAvatarId; }; #endif //LL_LLAVATARLISTITEM_H diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp index edf6e84b68..e568b9c526 100644 --- a/indra/newview/llavatarpropertiesprocessor.cpp +++ b/indra/newview/llavatarpropertiesprocessor.cpp @@ -428,27 +428,10 @@ void LLAvatarPropertiesProcessor::processPickInfoReply(LLMessageSystem* msg, voi msg->getString(_PREHASH_Data, _PREHASH_Desc, pick_data.desc); msg->getUUID(_PREHASH_Data, _PREHASH_SnapshotID, pick_data.snapshot_id); - // "Location text" is actually the owner name, the original - // name that owner gave the parcel, and the location. - msg->getString(_PREHASH_Data, _PREHASH_User, pick_data.location_text); - pick_data.location_text.append(", "); - + msg->getString(_PREHASH_Data, _PREHASH_User, pick_data.user_name); msg->getString(_PREHASH_Data, _PREHASH_OriginalName, pick_data.original_name); - if (!pick_data.original_name.empty()) - { - pick_data.location_text.append(pick_data.original_name); - pick_data.location_text.append(", "); - } - msg->getString(_PREHASH_Data, _PREHASH_SimName, pick_data.sim_name); - pick_data.location_text.append(pick_data.sim_name); - pick_data.location_text.append(" "); - msg->getVector3d(_PREHASH_Data, _PREHASH_PosGlobal, pick_data.pos_global); - S32 region_x = llround((F32)pick_data.pos_global.mdV[VX]) % REGION_WIDTH_UNITS; - S32 region_y = llround((F32)pick_data.pos_global.mdV[VY]) % REGION_WIDTH_UNITS; - S32 region_z = llround((F32)pick_data.pos_global.mdV[VZ]); - pick_data.location_text.append(llformat("(%d, %d, %d)", region_x, region_y, region_z)); msg->getS32(_PREHASH_Data, _PREHASH_SortOrder, pick_data.sort_order); msg->getBOOL(_PREHASH_Data, _PREHASH_Enabled, pick_data.enabled); diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h index 24675c44c0..79d109f1db 100644 --- a/indra/newview/llavatarpropertiesprocessor.h +++ b/indra/newview/llavatarpropertiesprocessor.h @@ -96,7 +96,7 @@ struct LLPickData BOOL enabled; //used only in read requests - std::string location_text; + std::string user_name; std::string original_name; std::string sim_name; diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 06f9a86d8d..46151b469f 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -37,7 +37,7 @@ #include "llchiclet.h" #include "llfloaterreg.h" #include "llflyoutbutton.h" -#include "llimpanel.h" // for LLIMFloater +#include "llimfloater.h" // for LLIMFloater #include "lllayoutstack.h" #include "llnearbychatbar.h" #include "llsplitbutton.h" @@ -59,13 +59,13 @@ LLBottomTray::LLBottomTray(const LLSD&) mChicletPanel = getChild("chiclet_list"); mSysWell = getChild("sys_well"); - mSysWell->setNotificationChicletWindow(LLFloaterReg::getInstance("syswell_window")); + // init mSysWell + // set handler for a Click operation + mSysWell->setClickCallback(boost::bind(&LLSysWellWindow::onChicletClick, LLFloaterReg::getTypedInstance("syswell_window"))); mChicletPanel->setChicletClickedCallback(boost::bind(&LLBottomTray::onChicletClick,this,_1)); - LLSplitButton* presets = getChild("presets"); - presets->setSelectionCallback(LLFloaterCamera::onClickCameraPresets); - + LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("CameraPresets.ChangeView",&LLFloaterCameraPresets::onClickCameraPresets); LLIMMgr::getInstance()->addSessionObserver(this); //this is to fix a crash that occurs because LLBottomTray is a singleton @@ -79,16 +79,15 @@ LLBottomTray::LLBottomTray(const LLSD&) BOOL LLBottomTray::postBuild() { - mCommitCallbackRegistrar.add("ShowCamMoveCtrls.Action", boost::bind(&LLBottomTray::onShowCamMoveCtrlsContextMenuItemClicked, this, _2)); - mEnableCallbackRegistrar.add("ShowCamMoveCtrls.EnableMenuItem", boost::bind(&LLBottomTray::onShowCamMoveCtrlsContextMenuItemEnabled, this, _2)); - - mShowCamMoveCtrlsContextMenu = LLUICtrlFactory::getInstance()->createFromFile("menu_hide_camera_move_controls.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - gMenuHolder->addChild(mShowCamMoveCtrlsContextMenu); + mBottomTrayContextMenu = LLUICtrlFactory::getInstance()->createFromFile("menu_bottomtray.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + gMenuHolder->addChild(mBottomTrayContextMenu); mNearbyChatBar = getChild("chat_bar"); mToolbarStack = getChild("toolbar_stack"); mMovementPanel = getChild("movement_panel"); + mGestureCombo = getChild("Gesture"); mCamPanel = getChild("cam_panel"); + setRightMouseDownCallback(boost::bind(&LLBottomTray::showBottomTrayContextMenu,this, _2, _3,_4)); return TRUE; } @@ -222,54 +221,47 @@ void LLBottomTray::setVisible(BOOL visible) } } -BOOL LLBottomTray::handleRightMouseDown(S32 x, S32 y, MASK mask) +void LLBottomTray::showBottomTrayContextMenu(S32 x, S32 y, MASK mask) { - if (!LLPanel::handleRightMouseDown(x, y, mask)) + // We should show BottomTrayContextMenu in last turn + if (mBottomTrayContextMenu && !LLMenuGL::sMenuContainer->getVisibleMenu()) { - if (mShowCamMoveCtrlsContextMenu) - { - mShowCamMoveCtrlsContextMenu->buildDrawLabels(); - mShowCamMoveCtrlsContextMenu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(this, mShowCamMoveCtrlsContextMenu, x, y); + //there are no other context menu (IM chiclet etc ), so we can show BottomTrayContextMenu + mBottomTrayContextMenu->buildDrawLabels(); + mBottomTrayContextMenu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(this, mBottomTrayContextMenu, x, y); + } - } - - return TRUE; } -bool LLBottomTray::onShowCamMoveCtrlsContextMenuItemEnabled(const LLSD& userdata) +void LLBottomTray::showGestureButton(BOOL visible) { - std::string item = userdata.asString(); - - if (item == "show_camera_move_controls") + if (visible != mGestureCombo->getVisible()) { - return gSavedSettings.getBOOL("ShowCameraAndMoveControls"); - } + LLRect r = mNearbyChatBar->getRect(); - return FALSE; -} - -void LLBottomTray::onShowCamMoveCtrlsContextMenuItemClicked(const LLSD& userdata) -{ - std::string item = userdata.asString(); + mGestureCombo->setVisible(visible); - if (item == "show_camera_move_controls") + if (!visible) { - BOOL state = !gSavedSettings.getBOOL("ShowCameraAndMoveControls"); + LLFloaterReg::hideFloaterInstance("gestures"); + r.mRight -= mGestureCombo->getRect().getWidth(); + } + else + { + r.mRight += mGestureCombo->getRect().getWidth(); + } - showCameraAndMoveControls(state); - gSavedSettings.setBOOL("ShowCameraAndMoveControls", state); + mNearbyChatBar->setRect(r); } } -void LLBottomTray::showCameraAndMoveControls(BOOL visible) +void LLBottomTray::showMoveButton(BOOL visible) { - mCamPanel->setVisible(visible); mMovementPanel->setVisible(visible); +} - if (!visible) - { - LLFloaterReg::hideFloaterInstance("moveview"); - LLFloaterReg::hideFloaterInstance("camera"); - } +void LLBottomTray::showCameraButton(BOOL visible) +{ + mCamPanel->setVisible(visible); } diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index c3c840ede0..b25dec7b92 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -37,6 +37,7 @@ #include "llpanel.h" #include "llimview.h" +#include "llcombobox.h" class LLChicletPanel; class LLLineEditor; @@ -70,9 +71,11 @@ public: virtual void onFocusLost(); virtual void setVisible(BOOL visible); - virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + void showBottomTrayContextMenu(S32 x, S32 y, MASK mask); - void showCameraAndMoveControls(BOOL visible); + void showGestureButton(BOOL visible); + void showMoveButton(BOOL visible); + void showCameraButton(BOOL visible); private: @@ -82,9 +85,6 @@ protected: void onChicletClick(LLUICtrl* ctrl); - bool onShowCamMoveCtrlsContextMenuItemEnabled(const LLSD& userdata); - void onShowCamMoveCtrlsContextMenuItemClicked(const LLSD& userdata); - static void* createNearbyChatBar(void* userdata); /** @@ -97,9 +97,10 @@ protected: LLTalkButton* mTalkBtn; LLNearbyChatBar* mNearbyChatBar; LLLayoutStack* mToolbarStack; - LLMenuGL* mShowCamMoveCtrlsContextMenu; + LLMenuGL* mBottomTrayContextMenu; LLPanel* mMovementPanel; LLPanel* mCamPanel; + LLComboBox* mGestureCombo; }; #endif // LL_LLBOTTOMPANEL_H diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp index a8373491cf..7ae9976338 100644 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -37,6 +37,8 @@ #include "llappviewer.h" #include "llviewercontrol.h" #include "llimview.h" +#include "llbottomtray.h" +#include "llviewerwindow.h" #include @@ -48,12 +50,34 @@ LLChannelManager::LLChannelManager() LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLChannelManager::onLoginCompleted, this)); mChannelList.clear(); mStartUpChannel = NULL; + + if(!gViewerWindow) + { + llerrs << "LLChannelManager::LLChannelManager() - viwer window is not initialized yet" << llendl; + } } //-------------------------------------------------------------------------- LLChannelManager::~LLChannelManager() { - //All channels are being deleted by Parent View + for(std::vector::iterator it = mChannelList.begin(); it != mChannelList.end(); ++it) + { + delete (*it).channel; + } + + mChannelList.clear(); +} + +//-------------------------------------------------------------------------- +LLScreenChannel* LLChannelManager::createNotificationChannel() +{ + // creating params for a channel + LLChannelManager::Params p; + p.id = LLUUID(gSavedSettings.getString("NotificationChannelUUID")); + p.channel_align = CA_RIGHT; + + // Getting a Channel for our notifications + return LLChannelManager::getInstance()->getChannel(p); } //-------------------------------------------------------------------------- @@ -61,20 +85,22 @@ void LLChannelManager::onLoginCompleted() { S32 away_notifications = 0; + // calc a number of all offline notifications for(std::vector::iterator it = mChannelList.begin(); it != mChannelList.end(); ++it) { + // don't calc notifications for Nearby Chat if((*it).channel->getChannelID() == LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))) { continue; } + // don't calc notifications for channels that always show their notifications if(!(*it).channel->getDisplayToastsAlways()) { away_notifications +=(*it).channel->getNumberOfHiddenToasts(); } } - // *TODO: calculate IM notifications away_notifications += gIMMgr->getNumberOfUnreadIM(); if(!away_notifications) @@ -83,11 +109,11 @@ void LLChannelManager::onLoginCompleted() return; } + // create a channel for the StartUp Toast LLChannelManager::Params p; p.id = LLUUID(gSavedSettings.getString("StartUpChannelUUID")); - p.channel_right_bound = getRootView()->getRect().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); - p.channel_width = gSavedSettings.getS32("NotifyBoxWidth"); - mStartUpChannel = createChannel(p); + p.channel_align = CA_RIGHT; + mStartUpChannel = getChannel(p); if(!mStartUpChannel) { @@ -95,8 +121,13 @@ void LLChannelManager::onLoginCompleted() return; } + // init channel's position and size + S32 channel_right_bound = gViewerWindow->getWorldViewRect().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); + S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth"); + mStartUpChannel->init(channel_right_bound - channel_width, channel_right_bound); mStartUpChannel->setShowToasts(true); - static_cast(mStartUpChannel)->setCommitCallback(boost::bind(&LLChannelManager::onStartUpToastClose, this)); + + mStartUpChannel->setCommitCallback(boost::bind(&LLChannelManager::onStartUpToastClose, this)); mStartUpChannel->createStartUpToast(away_notifications, gSavedSettings.getS32("ChannelBottomPanelMargin"), gSavedSettings.getS32("StartUpToastTime")); } @@ -107,76 +138,56 @@ void LLChannelManager::onStartUpToastClose() { mStartUpChannel->setVisible(FALSE); mStartUpChannel->closeStartUpToast(); - getRootView()->removeChild(mStartUpChannel); removeChannelByID(LLUUID(gSavedSettings.getString("StartUpChannelUUID"))); delete mStartUpChannel; mStartUpChannel = NULL; } - // set StartUp Toast Flag + // set StartUp Toast Flag to allow all other channels to show incoming toasts LLScreenChannel::setStartUpToastShown(); - // allow all other channels to show incoming toasts - for(std::vector::iterator it = mChannelList.begin(); it != mChannelList.end(); ++it) - { - (*it).channel->setShowToasts(true); - } - // force NEARBY CHAT CHANNEL to repost all toasts if present - LLScreenChannel* nearby_channel = getChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); + LLScreenChannel* nearby_channel = findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); nearby_channel->loadStoredToastsToChannel(); nearby_channel->setCanStoreToasts(false); } //-------------------------------------------------------------------------- -LLScreenChannel* LLChannelManager::createChannel(LLChannelManager::Params& p) +LLScreenChannel* LLChannelManager::getChannel(LLChannelManager::Params& p) { LLScreenChannel* new_channel = NULL; - if(!p.chiclet) - { - new_channel = getChannelByID(p.id); - } - else - { - new_channel = getChannelByChiclet(p.chiclet); - } + new_channel = findChannelByID(p.id); if(new_channel) return new_channel; new_channel = new LLScreenChannel(p.id); - getRootView()->addChild(new_channel); - new_channel->init(p.channel_right_bound - p.channel_width, p.channel_right_bound); - new_channel->setToastAlignment(p.align); + + if(!new_channel) + { + llerrs << "LLChannelManager::getChannel(LLChannelManager::Params& p) - can't create a channel!" << llendl; + } + else + { + new_channel->setToastAlignment(p.toast_align); + new_channel->setChannelAlignment(p.channel_align); new_channel->setDisplayToastsAlways(p.display_toasts_always); ChannelElem new_elem; new_elem.id = p.id; - new_elem.chiclet = p.chiclet; new_elem.channel = new_channel; - - mChannelList.push_back(new_elem); //TODO: remove chiclet from ScreenChannel? - - return new_channel; -} -//-------------------------------------------------------------------------- -LLScreenChannel* LLChannelManager::getChannelByID(const LLUUID id) -{ - std::vector::iterator it = find(mChannelList.begin(), mChannelList.end(), id); - if(it != mChannelList.end()) - { - return (*it).channel; + mChannelList.push_back(new_elem); } - return NULL; + return new_channel; } //-------------------------------------------------------------------------- -LLScreenChannel* LLChannelManager::getChannelByChiclet(const LLChiclet* chiclet) +LLScreenChannel* LLChannelManager::findChannelByID(const LLUUID id) { - std::vector::iterator it = find(mChannelList.begin(), mChannelList.end(), chiclet); + std::vector::iterator it = find(mChannelList.begin(), mChannelList.end(), id); if(it != mChannelList.end()) { return (*it).channel; @@ -185,22 +196,6 @@ LLScreenChannel* LLChannelManager::getChannelByChiclet(const LLChiclet* chiclet) return NULL; } -//-------------------------------------------------------------------------- -void LLChannelManager::reshape(S32 width, S32 height, BOOL called_from_parent) -{ - for(std::vector::iterator it = mChannelList.begin(); it != mChannelList.end(); ++it) - { - if((*it).channel->getToastAlignment() == NA_CENTRE) - { - LLRect channel_rect = (*it).channel->getRect(); - S32 screen_width = getRootView()->getRect().getWidth(); - channel_rect.setLeftTopAndSize(screen_width/2, channel_rect.mTop, channel_rect.getWidth(), channel_rect.getHeight()); - (*it).channel->setRect(channel_rect); - (*it).channel->showToasts(); - } - } -} - //-------------------------------------------------------------------------- void LLChannelManager::removeChannelByID(const LLUUID id) { @@ -212,18 +207,5 @@ void LLChannelManager::removeChannelByID(const LLUUID id) } //-------------------------------------------------------------------------- -void LLChannelManager::removeChannelByChiclet(const LLChiclet* chiclet) -{ - std::vector::iterator it = find(mChannelList.begin(), mChannelList.end(), chiclet); - if(it != mChannelList.end()) - { - mChannelList.erase(it); - } -} - -//-------------------------------------------------------------------------- - - - diff --git a/indra/newview/llchannelmanager.h b/indra/newview/llchannelmanager.h index e26c96b62e..811fa06d2b 100644 --- a/indra/newview/llchannelmanager.h +++ b/indra/newview/llchannelmanager.h @@ -34,7 +34,6 @@ #define LL_LLCHANNELMANAGER_H -#include "llchiclet.h" #include "llscreenchannel.h" #include "lluuid.h" @@ -48,36 +47,30 @@ namespace LLNotificationsUI * Manager for screen channels. * Responsible for instantiating and retrieving screen channels. */ -class LLChannelManager : public LLUICtrl, public LLSingleton +class LLChannelManager : public LLSingleton { public: - struct Params : public LLInitParam::Block + struct Params { LLUUID id; - LLChiclet* chiclet; - S32 channel_right_bound; - S32 channel_width; bool display_toasts_always; - EToastAlignment align; + EToastAlignment toast_align; + EChannelAlignment channel_align; - Params(): id(LLUUID("")), chiclet(NULL), - channel_right_bound(0), channel_width(0), - display_toasts_always(false), align(NA_BOTTOM) + Params(): id(LLUUID("")), display_toasts_always(false), toast_align(NA_BOTTOM), channel_align(CA_LEFT) {} }; struct ChannelElem { LLUUID id; - LLChiclet* chiclet; LLScreenChannel* channel; - ChannelElem() : id(LLUUID("")), chiclet(NULL), channel(NULL) { } + ChannelElem() : id(LLUUID("")), channel(NULL) { } ChannelElem(const ChannelElem &elem) { id = elem.id; - chiclet = elem.chiclet; channel = elem.channel; } @@ -85,12 +78,6 @@ public: { return (id == id_op); } - - bool operator == (const LLChiclet* chiclet_op) const - { - return (chiclet == chiclet_op); - } - }; LLChannelManager(); @@ -101,17 +88,17 @@ public: // removes a channel intended for the startup toast and allows other channels to show their toasts void onStartUpToastClose(); - //TODO: make protected? in order to be shure that channels are created only by notification handlers - LLScreenChannel* createChannel(LLChannelManager::Params& p); + // creates a new ScreenChannel according to the given parameters or returns existing if present + LLScreenChannel* getChannel(LLChannelManager::Params& p); + + // returns a channel by its ID + LLScreenChannel* findChannelByID(const LLUUID id); - LLScreenChannel* getChannelByID(const LLUUID id); - LLScreenChannel* getChannelByChiclet(const LLChiclet* chiclet); + // creator of the Notification channel, that is used in more than one handler + LLScreenChannel* createNotificationChannel(); // remove channel methods void removeChannelByID(const LLUUID id); - void removeChannelByChiclet(const LLChiclet* chiclet); - - void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); private: diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index a2dc97f7f5..20c44d5b11 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -38,6 +38,7 @@ #include "llgroupactions.h" #include "lliconctrl.h" #include "llimpanel.h" // LLFloaterIMPanel +#include "llimfloater.h" #include "llimview.h" #include "llfloaterreg.h" #include "lllocalcliprect.h" @@ -47,6 +48,7 @@ #include "llvoiceclient.h" #include "llvoicecontrolpanel.h" #include "llgroupmgr.h" +#include "llnotificationmanager.h" static LLDefaultChildRegistry::Register t1("chiclet_panel"); static LLDefaultChildRegistry::Register t2("chiclet_talk"); @@ -84,7 +86,6 @@ LLNotificationChiclet::LLNotificationChiclet(const Params& p) : LLChiclet(p) , mButton(NULL) , mCounterCtrl(NULL) -, mNotificationChicletWindow(NULL) { LLButton::Params button_params = p.button; button_params.rect(p.rect()); @@ -94,6 +95,11 @@ LLNotificationChiclet::LLNotificationChiclet(const Params& p) LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications; mCounterCtrl = LLUICtrlFactory::create(unread_params); addChild(mCounterCtrl); + + // connect counter handlers to the signals + connectCounterUpdatersToSignal("notify"); + connectCounterUpdatersToSignal("groupnotify"); + connectCounterUpdatersToSignal("notifytoast"); } LLNotificationChiclet::~LLNotificationChiclet() @@ -101,6 +107,25 @@ LLNotificationChiclet::~LLNotificationChiclet() } +void LLNotificationChiclet::connectCounterUpdatersToSignal(std::string notification_type) +{ + LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance(); + LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type); + if(n_handler) + { + if(notification_type == "notifytoast") + { + n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::updateUreadIMNotifications, this)); + n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::updateUreadIMNotifications, this)); + } + else + { + n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::incUreadSystemNotifications, this)); + n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::decUreadSystemNotifications, this)); + } + } +} + void LLNotificationChiclet::setCounter(S32 counter) { mCounterCtrl->setCounter(counter); @@ -259,7 +284,8 @@ LLIMP2PChiclet::Params::Params() rect(LLRect(0, 25, 45, 0)); avatar_icon.name("avatar_icon"); - avatar_icon.rect(LLRect(0, 25, 25, 0)); + avatar_icon.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_BOTTOM); + avatar_icon.rect(LLRect(0, 24, 25, 0)); avatar_icon.mouse_opaque(false); unread_notifications.name("unread"); @@ -432,7 +458,7 @@ LLIMGroupChiclet::Params::Params() rect(LLRect(0, 25, 45, 0)); group_icon.name("group_icon"); - group_icon.rect(LLRect(0, 25, 25, 0)); + group_icon.rect(LLRect(0, 24, 25, 0)); unread_notifications.name("unread"); unread_notifications.rect(LLRect(25, 25, 45, 0)); @@ -846,6 +872,27 @@ void LLChicletPanel::removeAll() showScrollButtonsIfNeeded(); } +void LLChicletPanel::scrollToChiclet(const LLChiclet* chiclet) +{ + const LLRect& rect = chiclet->getRect(); + + if (rect.mLeft < 0) + { + scroll(llabs(rect.mLeft)); + showScrollButtonsIfNeeded(); + } + else + { + S32 scrollWidth = mScrollArea->getRect().getWidth(); + + if (rect.mRight > scrollWidth) + { + scroll(-llabs(rect.mRight - scrollWidth)); + showScrollButtonsIfNeeded(); + } + } +} + void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent ) { LLPanel::reshape(width,height,called_from_parent); @@ -861,7 +908,7 @@ void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent ) width, height - scroll_button_rect.getHeight())); mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + SCROLL_BUTTON_PAD, - height + 7, width - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0)); + height, width - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0)); mShowControls = width > mMinWidth; mScrollArea->setVisible(mShowControls); diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 52bd7dbc31..316348cf1d 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -548,9 +548,6 @@ public: /*virtual*/ ~ LLNotificationChiclet(); - // Notification Chiclet Window - void setNotificationChicletWindow(LLFloater* wnd) { mNotificationChicletWindow = wnd; } - // methods for updating a number of unread System or IM notifications void incUreadSystemNotifications() { setCounter(++mUreadSystemNotifications + mUreadIMNotifications); } void decUreadSystemNotifications() { setCounter(--mUreadSystemNotifications + mUreadIMNotifications); } @@ -558,11 +555,12 @@ public: void setToggleState(BOOL toggled); protected: + // connect counter updaters to the corresponding signals + void connectCounterUpdatersToSignal(std::string notification_type); + LLNotificationChiclet(const Params& p); friend class LLUICtrlFactory; - LLFloater* mNotificationChicletWindow; - static S32 mUreadSystemNotifications; static S32 mUreadIMNotifications; @@ -644,6 +642,11 @@ public: */ void removeAll(); + /* + * Scrolls the panel to the specified chiclet + */ + void scrollToChiclet(const LLChiclet* chiclet); + boost::signals2::connection setChicletClickedCallback( const commit_callback_t& cb); @@ -814,6 +817,8 @@ T* LLChicletPanel::createChiclet(const LLUUID& session_id /*= LLUUID::null*/, S3 return NULL; } + scrollToChiclet(chiclet); + chiclet->setSessionId(session_id); return chiclet; diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp new file mode 100644 index 0000000000..131f9ceaf0 --- /dev/null +++ b/indra/newview/llexpandabletextbox.cpp @@ -0,0 +1,508 @@ +/** + * @file llexpandabletextbox.cpp + * @brief LLExpandableTextBox and related class implementations + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llexpandabletextbox.h" + +#include "llscrollcontainer.h" + +static LLDefaultChildRegistry::Register t1("expandable_text"); + +LLExpandableTextBox::LLTextBoxEx::Params::Params() +: expand_textbox("expand_textbox") +{ +} + +LLExpandableTextBox::LLTextBoxEx::LLTextBoxEx(const Params& p) +: LLTextBox(p) +{ + setIsChrome(TRUE); + + LLTextBox::Params params = p.expand_textbox; + mExpandTextBox = LLUICtrlFactory::create(params); + addChild(mExpandTextBox); + + LLRect rc = getLocalRect(); + rc.mRight -= getHPad(); + rc.mLeft = rc.mRight - mExpandTextBox->getTextPixelWidth(); + rc.mTop = mExpandTextBox->getTextPixelHeight(); + mExpandTextBox->setRect(rc); +} + +BOOL LLExpandableTextBox::LLTextBoxEx::handleMouseUp(S32 x, S32 y, MASK mask) +{ + BOOL ret = LLTextBox::handleMouseUp(x, y, mask); + + if(mExpandTextBox->getRect().pointInRect(x, y)) + { + onCommit(); + } + + return ret; +} + +void LLExpandableTextBox::LLTextBoxEx::draw() +{ + // draw text box + LLTextBox::draw(); + // force text box to draw children + LLUICtrl::draw(); +} + +void LLExpandableTextBox::LLTextBoxEx::drawText( S32 x, S32 y, const LLWString &text, const LLColor4& color ) +{ + // *NOTE:dzaporozhan: + // Copy/paste from LLTextBox::drawText in order to modify last + // line width if needed and who "More" link + F32 alpha = getDrawContext().mAlpha; + if (mSegments.size() > 1) + { + // we have Urls (or other multi-styled segments) + drawTextSegments(x, y, text); + } + else if( mLineLengthList.empty() ) + { + // simple case of 1 line of text in one style + mDefaultFont->render(text, 0, (F32)x, (F32)y, color % alpha, + mHAlign, mVAlign, + 0, + mShadowType, + S32_MAX, getRect().getWidth(), NULL, mUseEllipses); + + mExpandTextBox->setVisible(FALSE); + } + else + { + // simple case of multiple lines of text, all in the same style + S32 cur_pos = 0; + for (std::vector::iterator iter = mLineLengthList.begin(); + iter != mLineLengthList.end(); ++iter) + { + S32 line_length = *iter; + S32 line_height = llfloor(mDefaultFont->getLineHeight()) + mLineSpacing; + S32 max_pixels = getRect().getWidth(); + + if(iter + 1 != mLineLengthList.end() + && y - line_height < line_height) + { + max_pixels = getCropTextWidth(); + } + + mDefaultFont->render(text, cur_pos, (F32)x, (F32)y, color % alpha, + mHAlign, mVAlign, + 0, + mShadowType, + line_length, max_pixels, NULL, mUseEllipses ); + + cur_pos += line_length + 1; + + y -= line_height; + if(y < line_height) + { + if( mLineLengthList.end() != iter + 1 ) + { + showExpandText(y); + } + else + { + hideExpandText(); + } + break; + } + } + } +} + +void LLExpandableTextBox::LLTextBoxEx::showExpandText(S32 y) +{ + LLRect rc = mExpandTextBox->getRect(); + rc.mTop = y + mExpandTextBox->getTextPixelHeight(); + rc.mBottom = y; + mExpandTextBox->setRect(rc); + mExpandTextBox->setVisible(TRUE); +} + +void LLExpandableTextBox::LLTextBoxEx::hideExpandText() +{ + mExpandTextBox->setVisible(FALSE); +} + +S32 LLExpandableTextBox::LLTextBoxEx::getCropTextWidth() +{ + return mExpandTextBox->getRect().mLeft - getHPad() * 2; +} + +void LLExpandableTextBox::LLTextBoxEx::drawTextSegments(S32 init_x, S32 init_y, const LLWString &text) +{ + // *NOTE:dzaporozhan: + // Copy/paste from LLTextBox::drawTextSegments in order to modify last + // line width if needed and who "More" link + F32 alpha = getDrawContext().mAlpha; + + const S32 text_len = text.length(); + if (text_len <= 0) + { + return; + } + + S32 cur_line = 0; + S32 num_lines = getLineCount(); + S32 line_start = getLineStart(cur_line); + S32 line_height = llround( mDefaultFont->getLineHeight() ) + mLineSpacing; + F32 text_y = (F32) init_y; + segment_set_t::iterator cur_seg = mSegments.begin(); + + // render a line of text at a time + const LLRect textRect = getLocalRect(); + while((textRect.mBottom <= text_y) && (cur_line < num_lines)) + { + S32 next_start = -1; + S32 line_end = text_len; + + if ((cur_line + 1) < num_lines) + { + next_start = getLineStart(cur_line + 1); + line_end = next_start; + } + if ( text[line_end-1] == '\n' ) + { + --line_end; + } + + // render all segments on this line + F32 text_x = init_x; + S32 seg_start = line_start; + while (seg_start < line_end && cur_seg != mSegments.end()) + { + // move to the next segment (or continue the previous one) + LLTextSegment *cur_segment = *cur_seg; + while (cur_segment->getEnd() <= seg_start) + { + if (++cur_seg == mSegments.end()) + { + return; + } + cur_segment = *cur_seg; + } + + // Draw a segment within the line + S32 clipped_end = llmin( line_end, cur_segment->getEnd() ); + S32 clipped_len = clipped_end - seg_start; + if( clipped_len > 0 ) + { + LLStyleSP style = cur_segment->getStyle(); + if (style && style->isVisible()) + { + // work out the color for the segment + LLColor4 color ; + if (getEnabled()) + { + color = style->isLink() ? mLinkColor.get() : mTextColor.get(); + } + else + { + color = mDisabledColor.get(); + } + color = color % alpha; + + S32 max_pixels = textRect.getWidth(); + + if(cur_line + 1 < num_lines + && text_y - line_height < line_height) + { + max_pixels = getCropTextWidth(); + } + + // render a single line worth for this segment + mDefaultFont->render(text, seg_start, text_x, text_y, color, + mHAlign, mVAlign, 0, mShadowType, clipped_len, + max_pixels, &text_x, mUseEllipses); + } + + seg_start += clipped_len; + } + } + + // move down one line + text_y -= (F32)line_height; + line_start = next_start; + cur_line++; + if(text_y < line_height) + { + if( cur_line < num_lines ) + { + showExpandText((S32)text_y); + } + else + { + hideExpandText(); + } + break; + } + } +} + +S32 LLExpandableTextBox::LLTextBoxEx::getVerticalTextDelta() +{ + S32 text_height = getTextPixelHeight(); + S32 textbox_height = getRect().getHeight(); + + return text_height - textbox_height; +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLExpandableTextBox::Params::Params() +: textbox("textbox") +, scroll("scroll") +, max_height("max_height", 0) +, bg_visible("bg_visible", false) +, expanded_bg_visible("expanded_bg_visible", true) +, bg_color("bg_color", LLColor4::black) +, expanded_bg_color("expanded_bg_color", LLColor4::black) +{ +} + +LLExpandableTextBox::LLExpandableTextBox(const Params& p) +: LLUICtrl(p) +, mMaxHeight(p.max_height) +, mBGVisible(p.bg_visible) +, mExpandedBGVisible(p.expanded_bg_visible) +, mBGColor(p.bg_color) +, mExpandedBGColor(p.expanded_bg_color) +, mExpanded(false) +{ + LLRect rc = getLocalRect(); + + LLScrollContainer::Params scroll_params = p.scroll; + scroll_params.rect(rc); + mScroll = LLUICtrlFactory::create(scroll_params); + addChild(mScroll); + + LLTextBoxEx::Params textbox_params = p.textbox; + textbox_params.rect(rc); + mTextBox = LLUICtrlFactory::create(textbox_params); + mScroll->addChild(mTextBox); + + updateTextBoxRect(); + + mTextBox->setCommitCallback(boost::bind(&LLExpandableTextBox::onExpandClicked, this)); +} + +void LLExpandableTextBox::draw() +{ + if(mBGVisible && !mExpanded) + { + gl_rect_2d(getLocalRect(), mBGColor.get(), TRUE); + } + if(mExpandedBGVisible && mExpanded) + { + gl_rect_2d(getLocalRect(), mExpandedBGColor.get(), TRUE); + } + + collapseIfPosChanged(); + + LLUICtrl::draw(); +} + +void LLExpandableTextBox::collapseIfPosChanged() +{ + if(mExpanded) + { + LLView* parentp = getParent(); + LLRect parent_rect = parentp->getRect(); + parentp->localRectToOtherView(parent_rect, &parent_rect, getRootView()); + + if(parent_rect.mLeft != mParentRect.mLeft + || parent_rect.mTop != mParentRect.mTop) + { + collapseTextBox(); + } + } +} + +void LLExpandableTextBox::onExpandClicked() +{ + expandTextBox(); +} + +void LLExpandableTextBox::updateTextBoxRect() +{ + LLRect rc = getLocalRect(); + + rc.mLeft += mScroll->getBorderWidth(); + rc.mRight -= mScroll->getBorderWidth(); + rc.mTop -= mScroll->getBorderWidth(); + rc.mBottom += mScroll->getBorderWidth(); + + mTextBox->reshape(rc.getWidth(), rc.getHeight()); + mTextBox->setRect(rc); +} + +S32 LLExpandableTextBox::recalculateTextDelta(S32 text_delta) +{ + LLRect expanded_rect = getLocalRect(); + LLView* root_view = getRootView(); + LLRect window_rect = root_view->getRect(); + + LLRect expanded_screen_rect; + localRectToOtherView(expanded_rect, &expanded_screen_rect, root_view); + + // don't allow expanded text box bottom go off screen + if(expanded_screen_rect.mBottom - text_delta < window_rect.mBottom) + { + text_delta = expanded_screen_rect.mBottom - window_rect.mBottom; + } + // show scroll bar if max_height is valid + // and expanded size is greater that max_height + else if(mMaxHeight > 0 && expanded_rect.getHeight() + text_delta > mMaxHeight) + { + text_delta = mMaxHeight - expanded_rect.getHeight(); + } + + return text_delta; +} + +void LLExpandableTextBox::expandTextBox() +{ + S32 text_delta = mTextBox->getVerticalTextDelta(); + text_delta += mTextBox->getVPad() * 2 + mScroll->getBorderWidth() * 2; + // no need to expand + if(text_delta <= 0) + { + return; + } + + saveCollapsedState(); + + LLRect expanded_rect = getLocalRect(); + LLRect expanded_screen_rect; + + S32 updated_text_delta = recalculateTextDelta(text_delta); + // actual expand + expanded_rect.mBottom -= updated_text_delta; + + LLRect text_box_rect = mTextBox->getRect(); + + // check if we need to show scrollbar + if(text_delta != updated_text_delta) + { + static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); + + // disable horizontal scrollbar + text_box_rect.mRight -= scrollbar_size; + // text box size has changed - redo text wrap + mTextBox->setWrappedText(mText, text_box_rect.getWidth()); + // recalculate text delta since text wrap changed text height + text_delta = mTextBox->getVerticalTextDelta() + mTextBox->getVPad() * 2; + } + + // expand text + text_box_rect.mBottom -= text_delta; + mTextBox->reshape(text_box_rect.getWidth(), text_box_rect.getHeight()); + mTextBox->setRect(text_box_rect); + + // expand text box + localRectToOtherView(expanded_rect, &expanded_screen_rect, getParent()); + reshape(expanded_screen_rect.getWidth(), expanded_screen_rect.getHeight(), FALSE); + setRect(expanded_screen_rect); + + setFocus(TRUE); + // this lets us receive top_lost event(needed to collapse text box) + // it also draws text box above all other ui elements + gFocusMgr.setTopCtrl(this); + + mExpanded = true; +} + +void LLExpandableTextBox::collapseTextBox() +{ + if(!mExpanded) + { + return; + } + + mExpanded = false; + + reshape(mCollapsedRect.getWidth(), mCollapsedRect.getHeight(), FALSE); + setRect(mCollapsedRect); + + updateTextBoxRect(); + + mTextBox->setWrappedText(mText); + if(gFocusMgr.getTopCtrl() == this) + { + gFocusMgr.setTopCtrl(NULL); + } +} + +void LLExpandableTextBox::onFocusLost() +{ + collapseTextBox(); + + LLUICtrl::onFocusLost(); +} + +void LLExpandableTextBox::onTopLost() +{ + collapseTextBox(); + + LLUICtrl::onTopLost(); +} + +void LLExpandableTextBox::setValue(const LLSD& value) +{ + collapseTextBox(); + + mText = value.asString(); + mTextBox->setValue(value); +} + +void LLExpandableTextBox::setText(const std::string& str) +{ + collapseTextBox(); + + mText = str; + mTextBox->setText(str); +} + +void LLExpandableTextBox::saveCollapsedState() +{ + mCollapsedRect = getRect(); + + mParentRect = getParent()->getRect(); + // convert parent rect to screen coordinates, + // this will allow to track parent's position change + getParent()->localRectToOtherView(mParentRect, &mParentRect, getRootView()); +} diff --git a/indra/newview/llexpandabletextbox.h b/indra/newview/llexpandabletextbox.h new file mode 100644 index 0000000000..0a5a4c8b75 --- /dev/null +++ b/indra/newview/llexpandabletextbox.h @@ -0,0 +1,237 @@ +/** + * @file llexpandabletextbox.h + * @brief LLExpandableTextBox and related class definitions + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLEXPANDABLETEXTBOX_H +#define LL_LLEXPANDABLETEXTBOX_H + +#include "lltextbox.h" +#include "llscrollcontainer.h" + +/** + * LLExpandableTextBox is a text box control that will show "More" link at end of text + * if text doesn't fit into text box. After pressing "More" the text box will expand to show + * all text. If text is still too big, a scroll bar will appear inside expanded text box. + */ +class LLExpandableTextBox : public LLUICtrl +{ +protected: + + /** + * Extended text box. "More" link will appear at end of text if + * text is too long to fit into text box size. + */ + class LLTextBoxEx : public LLTextBox + { + public: + struct Params : public LLInitParam::Block + { + Optional expand_textbox; + + Params(); + }; + + /** + * Draw text box and "More" link + */ + /*virtual*/ void draw(); + + /** + * Draws simple text(no urls) line by line, will show or hide "More" link + * if needed. + */ + /*virtual*/ void drawText( S32 x, S32 y, const LLWString &text, const LLColor4& color ); + + /** + * Draws segmented text(with urls) line by line. Will show or hide "More" link + * if needed + */ + void drawTextSegments(S32 x, S32 y, const LLWString &text); + + /** + * Returns difference between text box height and text height. + * Value is positive if text height is greater than text box height. + */ + virtual S32 getVerticalTextDelta(); + + /** + * Returns text vertical padding + */ + virtual S32 getVPad() { return mVPad; } + + /** + * Returns text horizontal padding + */ + virtual S32 getHPad() { return mHPad; } + + /** + * Broadcasts "commit" signal if user clicked "More" link + */ + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); + + protected: + + LLTextBoxEx(const Params& p); + friend class LLUICtrlFactory; + + /** + * Shows "More" link + */ + void showExpandText(S32 y); + + /** + * Hides "More" link + */ + void hideExpandText(); + + /** + * Returns cropped line width + */ + S32 getCropTextWidth(); + + private: + + LLTextBox* mExpandTextBox; + }; + +public: + + struct Params : public LLInitParam::Block + { + Optional textbox; + + Optional scroll; + + Optional max_height; + + Optional bg_visible, + expanded_bg_visible; + + Optional bg_color, + expanded_bg_color; + + Params(); + }; + + /** + * Sets text + */ + virtual void setText(const std::string& str); + + /** + * Returns text + */ + virtual std::string getText() const { return mText; } + + /** + * Sets text + */ + /*virtual*/ void setValue(const LLSD& value); + + /** + * Returns text + */ + /*virtual*/ LLSD getValue() const { return mText; } + + /** + * Collapses text box on focus_lost event + */ + /*virtual*/ void onFocusLost(); + + /** + * Collapses text box on top_lost event + */ + /*virtual*/ void onTopLost(); + + /** + * Draws text box, collapses text box if its expanded and its parent's position changed + */ + /*virtual*/ void draw(); + +protected: + + LLExpandableTextBox(const Params& p); + friend class LLUICtrlFactory; + + /** + * Expands text box. + * A scroll bar will appear if expanded height is greater than max_height + */ + virtual void expandTextBox(); + + /** + * Collapses text box. + */ + virtual void collapseTextBox(); + + /** + * Collapses text box if it is expanded and its parent's position changed + */ + virtual void collapseIfPosChanged(); + + /** + * Updates text box rect to avoid horizontal scroll bar + */ + virtual void updateTextBoxRect(); + + /** + * User clicked on "More" link - expand text box + */ + virtual void onExpandClicked(); + + /** + * Saves collapsed text box's states(rect, parent rect...) + */ + virtual void saveCollapsedState(); + + /** + * Recalculate text delta considering min_height and window rect. + */ + virtual S32 recalculateTextDelta(S32 text_delta); + +protected: + + std::string mText; + LLTextBoxEx* mTextBox; + LLScrollContainer* mScroll; + + S32 mMaxHeight; + LLRect mCollapsedRect; + bool mExpanded; + LLRect mParentRect; + + bool mBGVisible; + bool mExpandedBGVisible; + LLUIColor mBGColor; + LLUIColor mExpandedBGColor; +}; + +#endif //LL_LLEXPANDABLETEXTBOX_H diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index ef71e35254..6b18984f88 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -144,6 +144,18 @@ public: void setLandmarkID(const LLUUID& id){ mUrlGetter.setLandmarkID(id); } const LLUUID& getLandmarkId() const { return mUrlGetter.getLandmarkId(); } + void onMouseEnter(S32 x, S32 y, MASK mask) + { + if (LLToolDragAndDrop::getInstance()->hasMouseCapture()) + { + LLUICtrl::onMouseEnter(x, y, mask); + } + else + { + LLButton::onMouseEnter(x, y, mask); + } + } + protected: LLFavoriteLandmarkButton(const LLButton::Params& p) : LLButton(p) {} friend class LLUICtrlFactory; @@ -278,7 +290,8 @@ struct LLFavoritesSort }; LLFavoritesBarCtrl::Params::Params() -: chevron_button_tool_tip("chevron_button_tool_tip") +: chevron_button_tool_tip("chevron_button_tool_tip"), + image_drag_indication("image_drag_indication") { } @@ -287,7 +300,12 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p) mFont(p.font.isProvided() ? p.font() : LLFontGL::getFontSansSerifSmall()), mPopupMenuHandle(), mInventoryItemsPopupMenuHandle(), - mChevronButtonToolTip(p.chevron_button_tool_tip) + mChevronButtonToolTip(p.chevron_button_tool_tip), + mImageDragIndication(p.image_drag_indication), + mShowDragMarker(FALSE), + mLandingTab(NULL), + mLastTab(NULL), + mTabsHighlightEnabled(TRUE) { // Register callback for menus with current registrar (will be parent panel's registrar) LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Favorites.DoToSelected", @@ -321,17 +339,49 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, case DAD_LANDMARK: { + /* + * add a callback to the end drag event. + * the callback will disconnet itself immediately after execution + * this is done because LLToolDragAndDrop is a common tool so it shouldn't + * be overloaded with redundant callbacks. + */ + if (!mEndDragConnection.connected()) + { + mEndDragConnection = LLToolDragAndDrop::getInstance()->setEndDragCallback(boost::bind(&LLFavoritesBarCtrl::onEndDrag, this)); + } + // Copy the item into the favorites folder (if it's not already there). LLInventoryItem *item = (LLInventoryItem *)cargo_data; + if (LLFavoriteLandmarkButton* dest = dynamic_cast(findChildByLocalCoords(x, y))) + { + setLandingTab(dest); + } + /* + * the condition dest == NULL can be satisfied not only in the case + * of dragging to the right from the last tab of the favbar. there is a + * small gap between each tab. if the user drags something exactly there + * then mLandingTab will be set to NULL and the dragged item will be pushed + * to the end of the favorites bar. this is incorrect behavior. that's why + * we need an additional check which excludes the case described previously + * making sure that the mouse pointer is beyond the last tab. + */ + else if (mLastTab && x >= mLastTab->getRect().mRight) + { + setLandingTab(NULL); + } + // check if we are dragging an existing item from the favorites bar if (item && mDragItemId == item->getUUID()) { *accept = ACCEPT_YES_SINGLE; + showDragMarker(TRUE); + if (drop) { handleExistingFavoriteDragAndDrop(x, y); + showDragMarker(FALSE); } } else @@ -343,11 +393,14 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, break; } - *accept = ACCEPT_YES_COPY_SINGLE; + *accept = ACCEPT_YES_COPY_MULTI; + + showDragMarker(TRUE); if (drop) { handleNewFavoriteDragAndDrop(item, favorites_id, x, y); + showDragMarker(FALSE); } } } @@ -361,7 +414,13 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, void LLFavoritesBarCtrl::handleExistingFavoriteDragAndDrop(S32 x, S32 y) { - LLFavoriteLandmarkButton* dest = dynamic_cast(findChildByLocalCoords(x, y)); + LLFavoriteLandmarkButton* dest = dynamic_cast(mLandingTab); + + // there is no need to handle if an item was dragged onto itself + if (dest && dest->getLandmarkId() == mDragItemId) + { + return; + } if (dest) { @@ -381,14 +440,17 @@ void LLFavoritesBarCtrl::handleExistingFavoriteDragAndDrop(S32 x, S32 y) menu->setVisible(FALSE); showDropDownMenu(); } - - mDragItemId = LLUUID::null; - getWindow()->setCursor(UI_CURSOR_ARROW); } void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, const LLUUID& favorites_id, S32 x, S32 y) { - LLFavoriteLandmarkButton* dest = dynamic_cast(findChildByLocalCoords(x, y)); + LLFavoriteLandmarkButton* dest = dynamic_cast(mLandingTab); + + // there is no need to handle if an item was dragged onto itself + if (dest && dest->getLandmarkId() == mDragItemId) + { + return; + } if (dest) { @@ -458,6 +520,30 @@ void LLFavoritesBarCtrl::reshape(S32 width, S32 height, BOOL called_from_parent) LLUICtrl::reshape(width, height, called_from_parent); } +void LLFavoritesBarCtrl::draw() +{ + LLUICtrl::draw(); + + if (mShowDragMarker) + { + S32 w = mImageDragIndication->getWidth() / 2; + S32 h = mImageDragIndication->getHeight() / 2; + + if (mLandingTab) + { + // mouse pointer hovers over an existing tab + LLRect rect = mLandingTab->getRect(); + mImageDragIndication->draw(rect.mLeft - w/2, rect.getHeight(), w, h); + } + else if (mLastTab) + { + // mouse pointer hovers over the favbar empty space (right to the last tab) + LLRect rect = mLastTab->getRect(); + mImageDragIndication->draw(rect.mRight, rect.getHeight(), w, h); + } + } +} + LLXMLNodePtr LLFavoritesBarCtrl::getButtonXMLNode() { LLXMLNodePtr buttonXMLNode = NULL; @@ -628,11 +714,15 @@ void LLFavoritesBarCtrl::createButtons(const LLInventoryModel::item_array_t &ite { S32 curr_x = buttonHGap; // Adding buttons + + LLFavoriteLandmarkButton* fav_btn = NULL; + mLandingTab = mLastTab = NULL; + for(S32 i = mFirstDropDownItem -1, j = 0; i >= 0; i--) { LLViewerInventoryItem* item = items.get(j++); - LLFavoriteLandmarkButton* fav_btn = LLUICtrlFactory::defaultBuilder(buttonXMLNode, this, NULL); + fav_btn = LLUICtrlFactory::defaultBuilder(buttonXMLNode, this, NULL); if (NULL == fav_btn) { llwarns << "Unable to create button for landmark: " << item->getName() << llendl; @@ -657,6 +747,8 @@ void LLFavoritesBarCtrl::createButtons(const LLInventoryModel::item_array_t &ite curr_x += buttonWidth + buttonHGap; } + + mLastTab = fav_btn; } @@ -784,6 +876,7 @@ void LLFavoritesBarCtrl::showDropDownMenu() menu_item->setRightMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonRightClick, this,item->getUUID(),_1,_2,_3,_4)); menu_item->LLUICtrl::setMouseDownCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseDown, this, item->getUUID(), _1, _2, _3, _4)); menu_item->LLUICtrl::setMouseUpCallback(boost::bind(&LLFavoritesBarCtrl::onButtonMouseUp, this, item->getUUID(), _1, _2, _3, _4)); + menu_item->setLandmarkID(item->getUUID()); // Check whether item name wider than menu if (menu_item->getNominalWidth() > max_width) @@ -968,7 +1061,6 @@ void LLFavoritesBarCtrl::pastFromClipboard() const void LLFavoritesBarCtrl::onButtonMouseDown(LLUUID id, LLUICtrl* ctrl, S32 x, S32 y, MASK mask) { mDragItemId = id; - mStartDrag = TRUE; S32 screenX, screenY; localPointToScreen(x, y, &screenX, &screenY); @@ -981,9 +1073,18 @@ void LLFavoritesBarCtrl::onButtonMouseUp(LLUUID id, LLUICtrl* ctrl, S32 x, S32 y mDragItemId = LLUUID::null; } +void LLFavoritesBarCtrl::onEndDrag() +{ + mEndDragConnection.disconnect(); + + showDragMarker(FALSE); + mDragItemId = LLUUID::null; + LLView::getWindow()->setCursor(UI_CURSOR_ARROW); +} + BOOL LLFavoritesBarCtrl::handleHover(S32 x, S32 y, MASK mask) { - if (mDragItemId != LLUUID::null && mStartDrag) + if (mDragItemId != LLUUID::null) { S32 screenX, screenY; localPointToScreen(x, y, &screenX, &screenY); @@ -994,8 +1095,6 @@ BOOL LLFavoritesBarCtrl::handleHover(S32 x, S32 y, MASK mask) DAD_LANDMARK, mDragItemId, LLToolDragAndDrop::SOURCE_LIBRARY); - mStartDrag = FALSE; - return LLToolDragAndDrop::getInstance()->handleHover(x, y, mask); } } diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index 4cd92d1a58..0be8de29a9 100644 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -43,6 +43,7 @@ public: struct Params : public LLInitParam::Block { Optional chevron_button_tool_tip; + Optional image_drag_indication; Params(); }; @@ -65,6 +66,10 @@ public: // LLInventoryObserver observer trigger virtual void changed(U32 mask); virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + virtual void draw(); + + void showDragMarker(BOOL show) { mShowDragMarker = show; } + void setLandingTab(LLUICtrl* tab) { mLandingTab = tab; } protected: void updateButtons(U32 bar_width); @@ -78,6 +83,8 @@ protected: void onButtonMouseDown(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask); void onButtonMouseUp(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask); + void onEndDrag(); + void doToSelected(const LLSD& userdata); BOOL isClipboardPasteable() const; void pastFromClipboard() const; @@ -98,6 +105,7 @@ protected: LLRect mChevronRect; std::string mChevronButtonToolTip; + LLUIImage* mImageDragIndication; private: /* @@ -136,10 +144,16 @@ private: // finds an item by it's UUID in the items array LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id); - BOOL mSkipUpdate; - BOOL mStartDrag; + BOOL mShowDragMarker; + LLUICtrl* mLandingTab; + LLUICtrl* mLastTab; + LLUUID mDragItemId; LLInventoryModel::item_array_t mItems; + + BOOL mTabsHighlightEnabled; + + boost::signals2::connection mEndDragConnection; }; diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp index f4c4f38008..0511ec1063 100644 --- a/indra/newview/llfloatercamera.cpp +++ b/indra/newview/llfloatercamera.cpp @@ -88,7 +88,6 @@ void LLFloaterCamera::update() { ECameraControlMode mode = determineMode(); if (mode != mCurrMode) setMode(mode); - updatePosition(); show_tip(mMode2TipType[mode], this); } @@ -122,48 +121,20 @@ LLFloaterCamera* LLFloaterCamera::findInstance() return LLFloaterReg::findTypedInstance("camera"); } -/*static*/ -void LLFloaterCamera::onClickCameraPresets(LLUICtrl* ctrl, const LLSD& param) -{ - std::string name = param.asString(); - - if ("rear_view" == name) - { - LLFirstTimeTipsManager::showTipsFor(LLFirstTimeTipsManager::FTT_CAMERA_PRESET_REAR, ctrl); - gAgent.switchCameraPreset(CAMERA_PRESET_REAR_VIEW); - } - else if ("group_view" == name) - { - LLFirstTimeTipsManager::showTipsFor(LLFirstTimeTipsManager::FTT_CAMERA_PRESET_GROUP); - gAgent.switchCameraPreset(CAMERA_PRESET_GROUP_VIEW); - } - else if ("front_view" == name) - { - LLFirstTimeTipsManager::showTipsFor(LLFirstTimeTipsManager::FTT_CAMERA_PRESET_FRONT); - gAgent.switchCameraPreset(CAMERA_PRESET_FRONT_VIEW); - } - -} - void LLFloaterCamera::onOpen(const LLSD& key) { - updatePosition(); -} - -void LLFloaterCamera::updatePosition() -{ - LLBottomTray* tray = LLBottomTray::getInstance(); - if (!tray) return; + LLButton *anchor_panel = LLBottomTray::getInstance()->getChild("camera_btn"); - LLButton* camera_button = tray->getChild("camera_btn"); + setDockControl(new LLDockControl( + anchor_panel, this, + getDockTongue(), LLDockControl::TOP)); - //align centers of a button and a floater - S32 x = camera_button->calcScreenRect().getCenterX() - getRect().getWidth()/2; - setOrigin(x, 0); + show_tip(mMode2TipType[mCurrMode], this); } + LLFloaterCamera::LLFloaterCamera(const LLSD& val) -: LLFloater(val), +: LLDockableFloater(NULL, false, val), mCurrMode(CAMERA_CTRL_MODE_ORBIT), mPrevMode(CAMERA_CTRL_MODE_ORBIT) { @@ -187,7 +158,7 @@ BOOL LLFloaterCamera::postBuild() update(); - return TRUE; + return LLDockableFloater::postBuild(); } ECameraControlMode LLFloaterCamera::determineMode() @@ -311,7 +282,8 @@ void LLFloaterCamera::updateState() LLRect controls_rect; if (childGetRect(CONTROLS, controls_rect)) { - static S32 height = controls_rect.getHeight(); + static LLUICachedControl floater_header_size ("UIFloaterHeaderSize", 0); + static S32 height = controls_rect.getHeight() - floater_header_size; S32 newHeight = rect.getHeight(); if (showControls) @@ -330,3 +302,46 @@ void LLFloaterCamera::updateState() } } +//-------------LLFloaterCameraPresets------------------------ + +LLFloaterCameraPresets::LLFloaterCameraPresets(const LLSD& key): +LLDockableFloater(NULL, false, key) +{} + +BOOL LLFloaterCameraPresets::postBuild() +{ + setIsChrome(TRUE); + + //build dockTongue + LLDockableFloater::postBuild(); + + LLButton *anchor_btn = LLBottomTray::getInstance()->getChild("camera_presets_btn"); + + setDockControl(new LLDockControl( + anchor_btn, this, + getDockTongue(), LLDockControl::TOP)); + return TRUE; +} + +/*static*/ +void LLFloaterCameraPresets::onClickCameraPresets(LLUICtrl* ctrl, const LLSD& param) +{ + std::string name = param.asString(); + + if ("rear_view" == name) + { + LLFirstTimeTipsManager::showTipsFor(LLFirstTimeTipsManager::FTT_CAMERA_PRESET_REAR, ctrl); + gAgent.switchCameraPreset(CAMERA_PRESET_REAR_VIEW); + } + else if ("group_view" == name) + { + LLFirstTimeTipsManager::showTipsFor(LLFirstTimeTipsManager::FTT_CAMERA_PRESET_GROUP); + gAgent.switchCameraPreset(CAMERA_PRESET_GROUP_VIEW); + } + else if ("front_view" == name) + { + LLFirstTimeTipsManager::showTipsFor(LLFirstTimeTipsManager::FTT_CAMERA_PRESET_FRONT); + gAgent.switchCameraPreset(CAMERA_PRESET_FRONT_VIEW); + } + +} diff --git a/indra/newview/llfloatercamera.h b/indra/newview/llfloatercamera.h index 1181c443bf..020cae7e82 100644 --- a/indra/newview/llfloatercamera.h +++ b/indra/newview/llfloatercamera.h @@ -33,7 +33,7 @@ #ifndef LLFLOATERCAMERA_H #define LLFLOATERCAMERA_H -#include "llfloater.h" +#include "lldockablefloater.h" #include "llfirsttimetipmanager.h" @@ -51,7 +51,7 @@ enum ECameraControlMode }; class LLFloaterCamera - : public LLFloater + : public LLDockableFloater { friend class LLFloaterReg; @@ -70,14 +70,8 @@ public: static void updateIfNotInAvatarViewMode(); - static void onClickCameraPresets(LLUICtrl* ctrl, const LLSD& param); - virtual void onOpen(const LLSD& key); - // *HACK: due to hard enough to have this control aligned with "Camera" button while resizing - // let update its position in each frame - /*virtual*/ void draw(){updatePosition(); LLFloater::draw();} - LLJoystickCameraRotate* mRotate; LLJoystickCameraZoom* mZoom; LLJoystickCameraTrack* mTrack; @@ -113,9 +107,6 @@ private: void assignButton2Mode(ECameraControlMode mode, const std::string& button_name); void initMode2TipTypeMap(); - /*Updates position of the floater to be center aligned with "Camera" button.*/ - void updatePosition(); - ECameraControlMode mPrevMode; ECameraControlMode mCurrMode; @@ -124,4 +115,15 @@ private: }; +class LLFloaterCameraPresets : public LLDockableFloater +{ + friend class LLFloaterReg; +public: + static void onClickCameraPresets(LLUICtrl* ctrl, const LLSD& param); +private: + LLFloaterCameraPresets(const LLSD&); + ~LLFloaterCameraPresets(){} + /*virtual*/ BOOL postBuild(); + +}; #endif diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index c197c78a41..761b5c9219 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -102,6 +102,7 @@ #include "llboost.h" #include "llviewermedia.h" #include "llpluginclassmedia.h" +#include "llteleporthistorystorage.h" #include @@ -221,6 +222,9 @@ bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response LLSearchHistory::getInstance()->save(); LLSearchComboBox* search_ctrl = LLNavigationBar::getInstance()->getChild("search_combo_box"); search_ctrl->clearHistory(); + + LLTeleportHistoryStorage::getInstance()->purgeItems(); + LLTeleportHistoryStorage::getInstance()->save(); } return false; diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index cddc67cb0a..d3b013237b 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -35,24 +35,53 @@ #include "llgrouplist.h" // libs +#include "llbutton.h" +#include "lliconctrl.h" +#include "lltextbox.h" #include "lltrans.h" // newview #include "llagent.h" +#include "llgroupactions.h" +#include "llviewercontrol.h" // for gSavedSettings static LLDefaultChildRegistry::Register r("group_list"); +S32 LLGroupListItem::sIconWidth = 0; + +class LLGroupComparator : public LLFlatListView::ItemComparator +{ +public: + /** Returns true if item1 < item2, false otherwise */ + /*virtual*/ bool compare(const LLPanel* item1, const LLPanel* item2) const + { + std::string name1 = static_cast(item1)->getGroupName(); + std::string name2 = static_cast(item2)->getGroupName(); + + LLStringUtil::toUpper(name1); + LLStringUtil::toUpper(name2); + + return name1 < name2; + } +}; + +static const LLGroupComparator GROUP_COMPARATOR; LLGroupList::Params::Params() { - // Prevent the active group from being always first in the list. - online_go_first = false; + } LLGroupList::LLGroupList(const Params& p) -: LLAvatarList(p) +: LLFlatListView(p) { + mShowIcons = gSavedSettings.getBOOL("GroupListShowIcons"); + setCommitOnSelectionChange(true); + // TODO: implement context menu // display a context menu appropriate for a list of group names - setContextMenu(LLScrollListCtrl::MENU_GROUP); +// setContextMenu(LLScrollListCtrl::MENU_GROUP); + + // Set default sort order. + setComparator(&GROUP_COMPARATOR); } static bool findInsensitive(std::string haystack, const std::string& needle_upper) @@ -63,36 +92,185 @@ static bool findInsensitive(std::string haystack, const std::string& needle_uppe BOOL LLGroupList::update(const std::string& name_filter) { - LLCtrlListInterface *group_list = getListInterface(); const LLUUID& highlight_id = gAgent.getGroupID(); S32 count = gAgent.mGroups.count(); LLUUID id; - group_list->operateOnAll(LLCtrlListInterface::OP_DELETE); + clear(); for(S32 i = 0; i < count; ++i) { - // *TODO: check powers mask? id = gAgent.mGroups.get(i).mID; const LLGroupData& group_data = gAgent.mGroups.get(i); if (name_filter != LLStringUtil::null && !findInsensitive(group_data.mName, name_filter)) continue; - addItem(id, group_data.mName, highlight_id == id, ADD_BOTTOM); // ADD_SORTED can only sort by first column anyway + addNewItem(id, group_data.mName, group_data.mInsigniaID, highlight_id == id, ADD_BOTTOM); } - // Force sorting the list. - updateSort(); + // Sort the list. + sort(); // add "none" to list at top { std::string loc_none = LLTrans::getString("GroupsNone"); if (name_filter == LLStringUtil::null || findInsensitive(loc_none, name_filter)) - addItem(LLUUID::null, loc_none, highlight_id.isNull(), ADD_TOP); + addNewItem(LLUUID::null, loc_none, LLUUID::null, highlight_id.isNull(), ADD_TOP); + } - // Prevent the "none" item from being sorted. - setNeedsSort(false); + selectItemByUUID(highlight_id); + + return TRUE; +} + +void LLGroupList::toggleIcons() +{ + // Save the new value for new items to use. + mShowIcons = !mShowIcons; + gSavedSettings.setBOOL("GroupListShowIcons", mShowIcons); + + // Show/hide icons for all existing items. + std::vector items; + getItems(items); + for( std::vector::const_iterator it = items.begin(); it != items.end(); it++) + { + static_cast(*it)->setGroupIconVisible(mShowIcons); } +} + +////////////////////////////////////////////////////////////////////////// +// PRIVATE Section +////////////////////////////////////////////////////////////////////////// + +void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, BOOL is_bold, EAddPosition pos) +{ + LLGroupListItem* item = new LLGroupListItem(); + + item->setName(name); + item->setGroupID(id); + item->setGroupIconID(icon_id); +// item->setContextMenu(mContextMenu); + + item->childSetVisible("info_btn", false); + item->setGroupIconVisible(mShowIcons); + + addItem(item, id, pos); + +// setCommentVisible(false); +} + + +/************************************************************************/ +/* LLGroupListItem implementation */ +/************************************************************************/ + +LLGroupListItem::LLGroupListItem() +: LLPanel(), +mGroupIcon(NULL), +mGroupNameBox(NULL), +mInfoBtn(NULL), +//mContextMenu(NULL), //TODO: +mGroupID(LLUUID::null) +{ + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_group_list_item.xml"); + + // Remember group icon width including its padding from the name text box, + // so that we can hide and show the icon again later. + if (!sIconWidth) + { + sIconWidth = mGroupNameBox->getRect().mLeft - mGroupIcon->getRect().mLeft; + } +} + +//virtual +BOOL LLGroupListItem::postBuild() +{ + mGroupIcon = getChild("group_icon"); + mGroupNameBox = getChild("group_name"); + + mInfoBtn = getChild("info_btn"); + mInfoBtn->setClickedCallback(boost::bind(&LLGroupListItem::onInfoBtnClick, this)); - group_list->selectByValue(highlight_id); return TRUE; } + +//virtual +void LLGroupListItem::setValue( const LLSD& value ) +{ + if (!value.isMap()) return; + if (!value.has("selected")) return; + childSetVisible("selected_icon", value["selected"]); +} + +void LLGroupListItem::onMouseEnter(S32 x, S32 y, MASK mask) +{ + childSetVisible("hovered_icon", true); + if (mGroupID.notNull()) // don't show the info button for the "none" group + mInfoBtn->setVisible(true); + + LLPanel::onMouseEnter(x, y, mask); +} + +void LLGroupListItem::onMouseLeave(S32 x, S32 y, MASK mask) +{ + childSetVisible("hovered_icon", false); + mInfoBtn->setVisible(false); + + LLPanel::onMouseLeave(x, y, mask); +} + +void LLGroupListItem::setName(const std::string& name) +{ + mGroupName = name; + mGroupNameBox->setValue(name); + mGroupNameBox->setToolTip(name); +} + +void LLGroupListItem::setGroupID(const LLUUID& group_id) +{ + mGroupID = group_id; + setActive(group_id == gAgent.getGroupID()); +} + +void LLGroupListItem::setGroupIconID(const LLUUID& group_icon_id) +{ + if (group_icon_id.notNull()) + { + mGroupIcon->setValue(group_icon_id); + } +} + +void LLGroupListItem::setGroupIconVisible(bool visible) +{ + // Already done? Then do nothing. + if (mGroupIcon->getVisible() == (BOOL)visible) + return; + + // Show/hide the group icon. + mGroupIcon->setVisible(visible); + + // Move the group name horizontally by icon size + its distance from the group name. + LLRect name_rect = mGroupNameBox->getRect(); + name_rect.mLeft += visible ? sIconWidth : -sIconWidth; + mGroupNameBox->setRect(name_rect); +} + +////////////////////////////////////////////////////////////////////////// +// Private Section +////////////////////////////////////////////////////////////////////////// +void LLGroupListItem::setActive(bool active) +{ + // Active group should be bold. + LLFontDescriptor new_desc(mGroupNameBox->getFont()->getFontDesc()); + + // *NOTE dzaporozhan + // On Windows LLFontGL::NORMAL will not remove LLFontGL::BOLD if font + // is predefined as bold (SansSerifSmallBold, for example) + new_desc.setStyle(active ? LLFontGL::BOLD : LLFontGL::NORMAL); + mGroupNameBox->setFont(LLFontGL::getFont(new_desc)); +} + +void LLGroupListItem::onInfoBtnClick() +{ + LLGroupActions::show(mGroupID); +} +//EOF diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h index e893313f4b..7708b58de6 100644 --- a/indra/newview/llgrouplist.h +++ b/indra/newview/llgrouplist.h @@ -33,22 +33,61 @@ #ifndef LL_LLGROUPLIST_H #define LL_LLGROUPLIST_H -#include +#include "llflatlistview.h" +#include "llpanel.h" -#include "llavatarlist.h" - -// *TODO: derive from ListView when it's ready. -class LLGroupList: public LLAvatarList +class LLGroupList: public LLFlatListView { LOG_CLASS(LLGroupList); public: - struct Params : public LLInitParam::Block + struct Params : public LLInitParam::Block { Params(); }; - LLGroupList(const Params&); + LLGroupList(const Params& p); BOOL update(const std::string& name_filter = LLStringUtil::null); + void toggleIcons(); + bool getIconsVisible() const { return mShowIcons; } + +private: + void addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, BOOL is_bold, EAddPosition pos = ADD_BOTTOM); + + bool mShowIcons; }; +class LLButton; +class LLIconCtrl; +class LLTextBox; + +class LLGroupListItem : public LLPanel +{ +public: + LLGroupListItem(); + /*virtual*/ BOOL postBuild(); + /*virtual*/ void setValue(const LLSD& value); + void onMouseEnter(S32 x, S32 y, MASK mask); + void onMouseLeave(S32 x, S32 y, MASK mask); + + const LLUUID& getGroupID() const { return mGroupID; } + const std::string& getGroupName() const { return mGroupName; } + + void setName(const std::string& name); + void setGroupID(const LLUUID& group_id); + void setGroupIconID(const LLUUID& group_icon_id); + void setGroupIconVisible(bool visible); + +private: + void setActive(bool active); + void onInfoBtnClick(); + + LLTextBox* mGroupNameBox; + LLUUID mGroupID; + LLIconCtrl* mGroupIcon; + LLButton* mInfoBtn; + + std::string mGroupName; + + static S32 sIconWidth; // icon width + padding +}; #endif // LL_LLGROUPLIST_H diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp new file mode 100644 index 0000000000..29102feb64 --- /dev/null +++ b/indra/newview/llimfloater.cpp @@ -0,0 +1,416 @@ +/** + * @file llimfloater.cpp + * @brief LLIMFloater class definition + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llimfloater.h" + +#include "llagent.h" +#include "llappviewer.h" +#include "llbutton.h" +#include "llbottomtray.h" +#include "llchannelmanager.h" +#include "llchiclet.h" +#include "llfloaterreg.h" +#include "llimview.h" +#include "lllineeditor.h" +#include "llpanelimcontrolpanel.h" +#include "llscreenchannel.h" +#include "lltrans.h" +#include "llviewertexteditor.h" +#include "llviewerwindow.h" + + + +LLIMFloater::LLIMFloater(const LLUUID& session_id) + : LLDockableFloater(NULL, session_id), + mControlPanel(NULL), + mSessionID(session_id), + mLastMessageIndex(-1), + mLastFromName(), + mDialog(IM_NOTHING_SPECIAL), + mHistoryEditor(NULL), + mInputEditor(NULL), + mPositioned(false) +{ + LLIMModel::LLIMSession* session = get_if_there(LLIMModel::instance().sSessionsMap, mSessionID, (LLIMModel::LLIMSession*)NULL); + if(session) + { + mDialog = session->mType; + } + + if (mDialog == IM_NOTHING_SPECIAL) + { + mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelIMControl, this); + } + else + { + mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); + } +// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_im_session.xml"); + + gFocusMgr.addFocusChangeCallback(boost::bind(&LLIMFloater::focusChangeCallback, this)); + + mCloseSignal.connect(boost::bind(&LLIMFloater::onClose, this)); +} + +void LLIMFloater::onClose() +{ + LLIMModel::instance().sendLeaveSession(mSessionID, mOtherParticipantUUID); + gIMMgr->removeSession(mSessionID); +} + +/* static */ +void LLIMFloater::newIMCallback(const LLSD& data){ + + if (data["num_unread"].asInteger() > 0) + { + LLUUID session_id = data["session_id"].asUUID(); + + LLIMFloater* floater = LLFloaterReg::findTypedInstance("impanel", session_id); + if (floater == NULL) + { + llwarns << "new_im_callback for non-existent session_id " << session_id << llendl; + return; + } + + // update if visible, otherwise will be updated when opened + if (floater->getVisible()) + { + floater->updateMessages(); + } + } +} + +void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata ) +{ + LLIMFloater* self = (LLIMFloater*) userdata; + self->sendMsg(); +} + +void LLIMFloater::sendMsg() +{ + if (!gAgent.isGodlike() + && (mDialog == IM_NOTHING_SPECIAL) + && mOtherParticipantUUID.isNull()) + { + llinfos << "Cannot send IM to everyone unless you're a god." << llendl; + return; + } + + if (mInputEditor) + { + LLWString text = mInputEditor->getConvertedText(); + if(!text.empty()) + { + // Truncate and convert to UTF8 for transport + std::string utf8_text = wstring_to_utf8str(text); + utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1); + + LLIMModel::sendMessage(utf8_text, + mSessionID, + mOtherParticipantUUID, + mDialog); + + mInputEditor->setText(LLStringUtil::null); + + updateMessages(); + } + } +} + + + +LLIMFloater::~LLIMFloater() +{ +} + +//virtual +BOOL LLIMFloater::postBuild() +{ + LLIMModel::LLIMSession* session = get_if_there(LLIMModel::instance().sSessionsMap, mSessionID, (LLIMModel::LLIMSession*)NULL); + if(session) + { + mOtherParticipantUUID = session->mOtherParticipantID; + mControlPanel->setID(session->mOtherParticipantID); + } + + LLButton* slide_left = getChild("slide_left_btn"); + slide_left->setVisible(mControlPanel->getVisible()); + slide_left->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this)); + + LLButton* slide_right = getChild("slide_right_btn"); + slide_right->setVisible(!mControlPanel->getVisible()); + slide_right->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this)); + + mInputEditor = getChild("chat_editor"); + mInputEditor->setMaxTextLength(1023); + // enable line history support for instant message bar + mInputEditor->setEnableLineHistory(TRUE); + + mInputEditor->setFocusReceivedCallback( onInputEditorFocusReceived, this ); + mInputEditor->setFocusLostCallback( onInputEditorFocusLost, this ); + mInputEditor->setKeystrokeCallback( onInputEditorKeystroke, this ); + mInputEditor->setCommitOnFocusLost( FALSE ); + mInputEditor->setRevertOnEsc( FALSE ); + mInputEditor->setReplaceNewlinesWithSpaces( FALSE ); + + childSetCommitCallback("chat_editor", onSendMsg, this); + + mHistoryEditor = getChild("im_text"); + mHistoryEditor->setParseHTML(TRUE); + + setTitle(LLIMModel::instance().getName(mSessionID)); + setDocked(true); + + return LLDockableFloater::postBuild(); +} + + + +// static +void* LLIMFloater::createPanelIMControl(void* userdata) +{ + LLIMFloater *self = (LLIMFloater*)userdata; + self->mControlPanel = new LLPanelIMControlPanel(); + self->mControlPanel->setXMLFilename("panel_im_control_panel.xml"); + return self->mControlPanel; +} + + +// static +void* LLIMFloater::createPanelGroupControl(void* userdata) +{ + LLIMFloater *self = (LLIMFloater*)userdata; + self->mControlPanel = new LLPanelGroupControlPanel(); + self->mControlPanel->setXMLFilename("panel_group_control_panel.xml"); + return self->mControlPanel; +} + + + +void LLIMFloater::focusChangeCallback() +{ + // hide docked floater if user clicked inside in-world area + if (isDocked() && gFocusMgr.getKeyboardFocus() == NULL) + { + setVisible(false); + } +} + +void LLIMFloater::onSlide() +{ + LLPanel* im_control_panel = getChild("panel_im_control_panel"); + im_control_panel->setVisible(!im_control_panel->getVisible()); + + getChild("slide_left_btn")->setVisible(im_control_panel->getVisible()); + getChild("slide_right_btn")->setVisible(!im_control_panel->getVisible()); +} + +//static +LLIMFloater* LLIMFloater::show(const LLUUID& session_id) +{ + //hide all + LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); + for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); + iter != inst_list.end(); ++iter) + { + LLIMFloater* floater = dynamic_cast(*iter); + if (floater && floater->isDocked()) + { + floater->setVisible(false); + } + } + + LLIMFloater* floater = LLFloaterReg::showTypedInstance("impanel", session_id); + + floater->updateMessages(); + floater->mInputEditor->setFocus(TRUE); + + if (floater->getDockControl() == NULL) + { + LLChiclet* chiclet = + LLBottomTray::getInstance()->getChicletPanel()->findChiclet( + session_id); + if (chiclet == NULL) + { + llerror("Dock chiclet for LLIMFloater doesn't exists", 0); + } + else + { + LLBottomTray::getInstance()->getChicletPanel()->scrollToChiclet(chiclet); + } + + floater->setDockControl(new LLDockControl(chiclet, floater, floater->getDockTongue(), + LLDockControl::TOP, boost::bind(&LLIMFloater::getEnabledRect, floater, _1))); + } + + return floater; +} + +void LLIMFloater::getEnabledRect(LLRect& rect) +{ + rect = gViewerWindow->getWorldViewRect(); +} + +void LLIMFloater::setDocked(bool docked, bool pop_on_undock) +{ + // update notification channel state + LLNotificationsUI::LLScreenChannel* channel = LLNotificationsUI::LLChannelManager::getInstance()-> + findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))); + LLDockableFloater::setDocked(docked, pop_on_undock); + + // update notification channel state + if(channel) + { + channel->updateShowToastsState(); + } +} + +void LLIMFloater::setVisible(BOOL visible) +{ + LLNotificationsUI::LLScreenChannel* channel = LLNotificationsUI::LLChannelManager::getInstance()-> + findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))); + LLDockableFloater::setVisible(visible); + + // update notification channel state + if(channel) + { + channel->updateShowToastsState(); + } +} + +//static +bool LLIMFloater::toggle(const LLUUID& session_id) +{ + LLIMFloater* floater = LLFloaterReg::findTypedInstance("impanel", session_id); + if (floater && floater->getVisible()) + { + // clicking on chiclet to close floater just hides it to maintain existing + // scroll/text entry state + floater->setVisible(false); + return false; + } + else + { + // ensure the list of messages is updated when floater is made visible + show(session_id); + // update number of unread notifications in the SysWell + LLBottomTray::getInstance()->getSysWell()->updateUreadIMNotifications(); + return true; + } +} + +void LLIMFloater::updateMessages() +{ + std::list messages = LLIMModel::instance().getMessages(mSessionID, mLastMessageIndex+1); + std::string agent_name; + + gCacheName->getFullName(gAgentID, agent_name); + + if (messages.size()) + { + LLUIColor divider_color = LLUIColorTable::instance().getColor("LtGray_50"); + LLUIColor chat_color = LLUIColorTable::instance().getColor("IMChatColor"); + + std::ostringstream message; + std::list::const_reverse_iterator iter = messages.rbegin(); + std::list::const_reverse_iterator iter_end = messages.rend(); + for (; iter != iter_end; ++iter) + { + LLSD msg = *iter; + + const bool prepend_newline = true; + std::string from = msg["from"].asString(); + if (from == agent_name) + from = LLTrans::getString("You"); + if (mLastFromName != from) + { + message << from << " ----- " << msg["time"].asString(); + mHistoryEditor->appendColoredText(message.str(), false, + prepend_newline, divider_color); + message.str(""); + mLastFromName = from; + } + + message << msg["message"].asString(); + mHistoryEditor->appendColoredText(message.str(), false, + prepend_newline, chat_color); + message.str(""); + + mLastMessageIndex = msg["index"].asInteger(); + } + + mHistoryEditor->setCursorAndScrollToEnd(); + } +} + +// static +void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata ) +{ + LLIMFloater* self= (LLIMFloater*) userdata; + + //in disconnected state IM input editor should be disabled + self->mInputEditor->setEnabled(!gDisconnected); + + self->mHistoryEditor->setCursorAndScrollToEnd(); +} + +// static +void LLIMFloater::onInputEditorFocusLost(LLFocusableElement* caller, void* userdata) +{ + LLIMFloater* self = (LLIMFloater*) userdata; + self->setTyping(FALSE); +} + +// static +void LLIMFloater::onInputEditorKeystroke(LLLineEditor* caller, void* userdata) +{ + LLIMFloater* self = (LLIMFloater*)userdata; + std::string text = self->mInputEditor->getText(); + if (!text.empty()) + { + self->setTyping(TRUE); + } + else + { + // Deleting all text counts as stopping typing. + self->setTyping(FALSE); + } +} + + +//just a stub for now +void LLIMFloater::setTyping(BOOL typing) +{ +} + diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h new file mode 100644 index 0000000000..276f38e829 --- /dev/null +++ b/indra/newview/llimfloater.h @@ -0,0 +1,112 @@ +/** + * @file llimfloater.h + * @brief LLIMFloater class definition + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_IMFLOATER_H +#define LL_IMFLOATER_H + +#include "lldockablefloater.h" + +class LLLineEditor; +class LLPanelChatControlPanel; +class LLViewerTextEditor; + + +/** + * Individual IM window that appears at the bottom of the screen, + * optionally "docked" to the bottom tray. + */ +class LLIMFloater : public LLDockableFloater +{ +public: + LLIMFloater(const LLUUID& session_id); + + virtual ~LLIMFloater(); + + // LLView overrides + /*virtual*/ BOOL postBuild(); + /*virtual*/ void setVisible(BOOL visible); + + // LLFloater overrides + /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); + + // Make IM conversion visible and update the message history + static LLIMFloater* show(const LLUUID& session_id); + + // Toggle panel specified by session_id + // Returns true iff panel became visible + static bool toggle(const LLUUID& session_id); + + // get new messages from LLIMModel + void updateMessages(); + static void onSendMsg( LLUICtrl*, void*); + void sendMsg(); + + // callback for LLIMModel on new messages + // route to specific floater if it is visible + static void newIMCallback(const LLSD& data); + + // called when docked floater's position has been set by chiclet + void setPositioned(bool b) { mPositioned = b; }; + + // handler for a CLOSE signal + void onClose(); + + +private: + + static void onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata ); + static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); + static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata); + void setTyping(BOOL typing); + void onSlide(); + static void* createPanelIMControl(void* userdata); + static void* createPanelGroupControl(void* userdata); + void focusChangeCallback(); + void getEnabledRect(LLRect& rect); + + LLPanelChatControlPanel* mControlPanel; + LLUUID mSessionID; + S32 mLastMessageIndex; + + // username of last user who added text to this conversation, used to + // suppress duplicate username divider bars + std::string mLastFromName; + + EInstantMessage mDialog; + LLUUID mOtherParticipantUUID; + LLViewerTextEditor* mHistoryEditor; + LLLineEditor* mInputEditor; + bool mPositioned; +}; + + +#endif // LL_IMFLOATER_H diff --git a/indra/newview/llimhandler.cpp b/indra/newview/llimhandler.cpp index a47477c446..46067c081f 100644 --- a/indra/newview/llimhandler.cpp +++ b/indra/newview/llimhandler.cpp @@ -36,29 +36,18 @@ #include "llnotificationhandler.h" #include "llagentdata.h" -#include "llbottomtray.h" -#include "llviewercontrol.h" #include "lltoastimpanel.h" +#include "llviewerwindow.h" using namespace LLNotificationsUI; //-------------------------------------------------------------------------- -LLIMHandler::LLIMHandler() +LLIMHandler::LLIMHandler(e_notification_type type, const LLSD& id) { - - // getting a Chiclet and creating params for a channel - LLBottomTray* tray = LLBottomTray::getInstance(); - mChiclet = tray->getSysWell(); - - LLChannelManager::Params p; - // *TODO: createNotificationChannel method - p.id = LLUUID(gSavedSettings.getString("NotificationChannelUUID")); - p.channel_right_bound = tray->getRect().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); - p.channel_width = gSavedSettings.getS32("NotifyBoxWidth"); + mType = type; // Getting a Channel for our notifications - mChannel = LLChannelManager::getInstance()->createChannel(p); - + mChannel = LLChannelManager::getInstance()->createNotificationChannel(); } //-------------------------------------------------------------------------- @@ -67,12 +56,31 @@ LLIMHandler::~LLIMHandler() } //-------------------------------------------------------------------------- -void LLIMHandler::processNotification(const LLSD& notify) +void LLIMHandler::initChannel() +{ + S32 channel_right_bound = gViewerWindow->getWorldViewRect().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); + S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth"); + mChannel->init(channel_right_bound - channel_width, channel_right_bound); +} + +//-------------------------------------------------------------------------- +bool LLIMHandler::processNotification(const LLSD& notify) { + if(!mChannel) + { + return false; + } + LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); if(!notification) - return; + return false; + + // arrange a channel on a screen + if(!mChannel->getVisible()) + { + initChannel(); + } if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") { @@ -95,40 +103,31 @@ void LLIMHandler::processNotification(const LLSD& notify) LLToastIMPanel* im_box = new LLToastIMPanel(im_p); LLToast::Params p; - p.id = notification->getID(); + p.notif_id = notification->getID(); + p.session_id = im_p.session_id; p.notification = notification; p.panel = im_box; p.can_be_stored = false; - p.on_toast_destroy = boost::bind(&LLIMHandler::onToastDestroy, this, _1); + p.on_delete_toast = boost::bind(&LLIMHandler::onDeleteToast, this, _1); mChannel->addToast(p); - - static_cast(mChiclet)->updateUreadIMNotifications(); + // send a signal to the counter manager; + mNewNotificationSignal(); } else if (notify["sigtype"].asString() == "delete") { mChannel->killToastByNotificationID(notification->getID()); } + return true; } //-------------------------------------------------------------------------- -void LLIMHandler::onToastDestroy(LLToast* toast) -{ - toast->closeFloater(); - static_cast(mChiclet)->updateUreadIMNotifications(); -} - -//-------------------------------------------------------------------------- -void LLIMHandler::onChicletClick(void) +void LLIMHandler::onDeleteToast(LLToast* toast) { + // send a signal to the counter manager + mDelNotificationSignal(); } //-------------------------------------------------------------------------- -void LLIMHandler::onChicletClose(void) -{ -} - -//-------------------------------------------------------------------------- - diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 0efe9b9849..de4faf72f5 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -48,6 +48,7 @@ #include "llbutton.h" #include "llbottomtray.h" #include "llcallingcard.h" +#include "llchannelmanager.h" #include "llchat.h" #include "llchiclet.h" #include "llconsole.h" @@ -81,6 +82,7 @@ #include "llhttpclient.h" #include "llmutelist.h" #include "llstylemap.h" +#include "llappviewer.h" // // Constants @@ -1986,318 +1988,4 @@ bool LLFloaterIMPanel::onConfirmForceCloseError(const LLSD& notification, const } return false; } - - -LLIMFloater::LLIMFloater(const LLUUID& session_id) - : LLDockableFloater(NULL, session_id), - mControlPanel(NULL), - mSessionID(session_id), - mLastMessageIndex(-1), - mLastFromName(), - mDialog(IM_NOTHING_SPECIAL), - mHistoryEditor(NULL), - mInputEditor(NULL), - mPositioned(false) -{ - LLIMModel::LLIMSession* session = get_if_there(LLIMModel::instance().sSessionsMap, mSessionID, (LLIMModel::LLIMSession*)NULL); - if(session) - { - mDialog = session->mType; - } - - if (mDialog == IM_NOTHING_SPECIAL) - { - mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelIMControl, this); - } - else - { - mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); - } -// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_im_session.xml"); -} - -/* static */ -void LLIMFloater::newIMCallback(const LLSD& data){ - - if (data["num_unread"].asInteger() > 0) - { - LLUUID session_id = data["session_id"].asUUID(); - - LLIMFloater* floater = LLFloaterReg::findTypedInstance("impanel", session_id); - if (floater == NULL) - { - llwarns << "new_im_callback for non-existent session_id " << session_id << llendl; - return; - } - - // update if visible, otherwise will be updated when opened - if (floater->getVisible()) - { - floater->updateMessages(); - } - } -} - -void LLIMFloater::onSendMsg( LLUICtrl* ctrl, void* userdata ) -{ - LLIMFloater* self = (LLIMFloater*) userdata; - self->sendMsg(); -} - -void LLIMFloater::sendMsg() -{ - if (!gAgent.isGodlike() - && (mDialog == IM_NOTHING_SPECIAL) - && mOtherParticipantUUID.isNull()) - { - llinfos << "Cannot send IM to everyone unless you're a god." << llendl; - return; - } - - if (mInputEditor) - { - LLWString text = mInputEditor->getConvertedText(); - if(!text.empty()) - { - // Truncate and convert to UTF8 for transport - std::string utf8_text = wstring_to_utf8str(text); - utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1); - - LLIMModel::sendMessage(utf8_text, - mSessionID, - mOtherParticipantUUID, - mDialog); - - mInputEditor->setText(LLStringUtil::null); - - updateMessages(); - } - } -} - - - -LLIMFloater::~LLIMFloater() -{ -} - -//virtual -BOOL LLIMFloater::postBuild() -{ - LLIMModel::LLIMSession* session = get_if_there(LLIMModel::instance().sSessionsMap, mSessionID, (LLIMModel::LLIMSession*)NULL); - if(session) - { - mOtherParticipantUUID = session->mOtherParticipantID; - mControlPanel->setID(session->mOtherParticipantID); - } - - LLButton* slide_left = getChild("slide_left_btn"); - slide_left->setVisible(mControlPanel->getVisible()); - slide_left->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this)); - - LLButton* slide_right = getChild("slide_right_btn"); - slide_right->setVisible(!mControlPanel->getVisible()); - slide_right->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this)); - - mInputEditor = getChild("chat_editor"); - mInputEditor->setMaxTextLength(1023); - // enable line history support for instant message bar - mInputEditor->setEnableLineHistory(TRUE); - - mInputEditor->setFocusReceivedCallback( onInputEditorFocusReceived, this ); - mInputEditor->setFocusLostCallback( onInputEditorFocusLost, this ); - mInputEditor->setKeystrokeCallback( onInputEditorKeystroke, this ); - mInputEditor->setCommitOnFocusLost( FALSE ); - mInputEditor->setRevertOnEsc( FALSE ); - mInputEditor->setReplaceNewlinesWithSpaces( FALSE ); - - childSetCommitCallback("chat_editor", onSendMsg, this); - - mHistoryEditor = getChild("im_text"); - mHistoryEditor->setParseHTML(TRUE); - - setTitle(LLIMModel::instance().getName(mSessionID)); - setDocked(true); - - return LLDockableFloater::postBuild(); -} - - - -// static -void* LLIMFloater::createPanelIMControl(void* userdata) -{ - LLIMFloater *self = (LLIMFloater*)userdata; - self->mControlPanel = new LLPanelIMControlPanel(); - self->mControlPanel->setXMLFilename("panel_im_control_panel.xml"); - return self->mControlPanel; -} - - -// static -void* LLIMFloater::createPanelGroupControl(void* userdata) -{ - LLIMFloater *self = (LLIMFloater*)userdata; - self->mControlPanel = new LLPanelGroupControlPanel(); - self->mControlPanel->setXMLFilename("panel_group_control_panel.xml"); - return self->mControlPanel; -} - -const U32 DOCK_ICON_HEIGHT = 6; - -//virtual -void LLIMFloater::onFocusLost() -{ - // spec says close if docked to bottom tray and user has clicked away - // (hence we are no longer focused) - if (isDocked()) - { - LLIMFloater* floater = LLFloaterReg::getTypedInstance("impanel", mSessionID); - if (floater) - { - floater->setVisible(false); - } - } -} - -void LLIMFloater::onSlide() -{ - LLPanel* im_control_panel = getChild("panel_im_control_panel"); - im_control_panel->setVisible(!im_control_panel->getVisible()); - - getChild("slide_left_btn")->setVisible(im_control_panel->getVisible()); - getChild("slide_right_btn")->setVisible(!im_control_panel->getVisible()); -} - -//static -LLIMFloater* LLIMFloater::show(const LLUUID& session_id) -{ - //hide all - LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel"); - for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); - iter != inst_list.end(); ++iter) - { - LLIMFloater* floater = dynamic_cast(*iter); - if (floater && floater->isDocked()) - { - floater->setVisible(false); - } - } - - LLIMFloater* floater = LLFloaterReg::showTypedInstance("impanel", session_id); - - floater->updateMessages(); - floater->mInputEditor->setFocus(TRUE); - - if (floater->getDockControl() == NULL) - { - LLView* chiclet = - LLBottomTray::getInstance()->getChicletPanel()->findChiclet( - session_id); - if (chiclet == NULL) - { - llerror("Dock chiclet for LLIMFloater doesn't exists", 0); - } - floater->setDockControl(new LLDockControl(chiclet, floater, floater->getDockTongue(), - LLDockControl::TOP, floater->isDocked())); - } - - return floater; -} - -//static -bool LLIMFloater::toggle(const LLUUID& session_id) -{ - LLIMFloater* floater = LLFloaterReg::findTypedInstance("impanel", session_id); - if (floater && floater->getVisible()) - { - // clicking on chiclet to close floater just hides it to maintain existing - // scroll/text entry state - floater->setVisible(false); - return false; - } - else - { - // ensure the list of messages is updated when floater is made visible - show(session_id); - // update number of unread notifications in the SysWell - LLBottomTray::getInstance()->getSysWell()->updateUreadIMNotifications(); - return true; - } -} - -void LLIMFloater::updateMessages() -{ - std::list messages = LLIMModel::instance().getMessages(mSessionID, mLastMessageIndex+1); - - if (messages.size()) - { - LLUIColor divider_color = LLUIColorTable::instance().getColor("LtGray_50"); - LLUIColor chat_color = LLUIColorTable::instance().getColor("IMChatColor"); - - std::ostringstream message; - std::list::const_reverse_iterator iter = messages.rbegin(); - std::list::const_reverse_iterator iter_end = messages.rend(); - for (; iter != iter_end; ++iter) - { - LLSD msg = *iter; - - const bool prepend_newline = true; - std::string from = msg["from"].asString(); - if (mLastFromName != from) - { - message << from << " ----- " << msg["time"].asString(); - mHistoryEditor->appendColoredText(message.str(), false, - prepend_newline, divider_color); - message.str(""); - mLastFromName = from; - } - - message << msg["message"].asString(); - mHistoryEditor->appendColoredText(message.str(), false, - prepend_newline, chat_color); - message.str(""); - - mLastMessageIndex = msg["index"].asInteger(); - } - - mHistoryEditor->setCursorAndScrollToEnd(); - } -} - -// static -void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata ) -{ - LLIMFloater* self= (LLIMFloater*) userdata; - self->mHistoryEditor->setCursorAndScrollToEnd(); -} - -// static -void LLIMFloater::onInputEditorFocusLost(LLFocusableElement* caller, void* userdata) -{ - LLIMFloater* self = (LLIMFloater*) userdata; - self->setTyping(FALSE); -} - -// static -void LLIMFloater::onInputEditorKeystroke(LLLineEditor* caller, void* userdata) -{ - LLIMFloater* self = (LLIMFloater*)userdata; - std::string text = self->mInputEditor->getText(); - if (!text.empty()) - { - self->setTyping(TRUE); - } - else - { - // Deleting all text counts as stopping typing. - self->setTyping(FALSE); - } -} - - -//just a stub for now -void LLIMFloater::setTyping(BOOL typing) -{ -} diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h index 1d69f1567c..dbf5e1cb6a 100644 --- a/indra/newview/llimpanel.h +++ b/indra/newview/llimpanel.h @@ -360,68 +360,4 @@ private: void disableWhileSessionStarting(); }; - -// Individual IM window that appears at the bottom of the screen, -// optionally "docked" to the bottom tray. -class LLIMFloater : public LLDockableFloater -{ -public: - LLIMFloater(const LLUUID& session_id); - - virtual ~LLIMFloater(); - - // LLView overrides - /*virtual*/ BOOL postBuild(); - - // Floater should close when user clicks away to other UI area, - // hence causing focus loss. - /*virtual*/ void onFocusLost(); - - // Make IM conversion visible and update the message history - static LLIMFloater* show(const LLUUID& session_id); - - // Toggle panel specified by session_id - // Returns true iff panel became visible - static bool toggle(const LLUUID& session_id); - - // get new messages from LLIMModel - void updateMessages(); - static void onSendMsg( LLUICtrl*, void*); - void sendMsg(); - - // callback for LLIMModel on new messages - // route to specific floater if it is visible - static void newIMCallback(const LLSD& data); - - // called when docked floater's position has been set by chiclet - void setPositioned(bool b) { mPositioned = b; }; - - - -private: - - static void onInputEditorFocusReceived( LLFocusableElement* caller, void* userdata ); - static void onInputEditorFocusLost(LLFocusableElement* caller, void* userdata); - static void onInputEditorKeystroke(LLLineEditor* caller, void* userdata); - void setTyping(BOOL typing); - void onSlide(); - static void* createPanelIMControl(void* userdata); - static void* createPanelGroupControl(void* userdata); - - LLPanelChatControlPanel* mControlPanel; - LLUUID mSessionID; - S32 mLastMessageIndex; - // username of last user who added text to this conversation, used to - // suppress duplicate username divider bars - std::string mLastFromName; - EInstantMessage mDialog; - LLUUID mOtherParticipantUUID; - LLViewerTextEditor* mHistoryEditor; - LLLineEditor* mInputEditor; - bool mPositioned; -}; - - - - #endif // LL_IMPANEL_H diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 9ef98afe94..3cf78f957b 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -53,6 +53,7 @@ #include "llfloaterchatterbox.h" #include "llavataractions.h" #include "llhttpnode.h" +#include "llimfloater.h" #include "llimpanel.h" #include "llresizebar.h" #include "lltabcontainer.h" @@ -70,6 +71,7 @@ #include "llnotify.h" #include "llviewerregion.h" #include "lltrans.h" +#include "llrecentpeople.h" #include "llfirstuse.h" #include "llagentui.h" @@ -90,6 +92,11 @@ std::map LLIMModel::sSessionsMap; void toast_callback(const LLSD& msg){ + // do not show toast in busy mode + if (gAgent.getBusy()) + { + return; + } //we send notifications to reset counter also if (msg["num_unread"].asInteger()) @@ -101,8 +108,7 @@ void toast_callback(const LLSD& msg){ args["FROM_ID"] = msg["from_id"]; args["SESSION_ID"] = msg["session_id"]; - //LLNotifications::instance().add("IMToast", args, LLSD(), boost::bind(&LLFloaterChatterBox::onOpen, LLFloaterChatterBox::getInstance(), msg["session_id"].asUUID())); - LLNotifications::instance().add("IMToast", args, LLSD(), boost::bind(&LLIMFloater::toggle, msg["session_id"].asUUID())); + LLNotifications::instance().add("IMToast", args, LLSD(), boost::bind(&LLIMFloater::show, msg["session_id"].asUUID())); } } @@ -1345,8 +1351,15 @@ LLUUID LLIMMgr::addSession( // This removes the panel referenced by the uuid, and then restores // internal consistency. The internal pointer is not deleted? Did you mean // a pointer to the corresponding LLIMSession? Session data is cleared now. -void LLIMMgr::removeSession(const LLUUID& session_id) +// Put a copy of UUID to avoid problem when passed reference becames invalid +// if it has been come from the object removed in observer. +void LLIMMgr::removeSession(LLUUID session_id) { + if (mBeingRemovedSessionID == session_id) + { + return; + } + LLFloaterIMPanel* floater = findFloaterBySession(session_id); if(floater) { diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 4eb743b1ac..219af0705d 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -38,7 +38,6 @@ #include "llinstantmessage.h" #include "lluuid.h" #include "llmultifloater.h" -#include "llrecentpeople.h" class LLFloaterChatterBox; class LLUUID; @@ -159,7 +158,7 @@ public: // This removes the panel referenced by the uuid, and then // restores internal consistency. The internal pointer is not // deleted. - void removeSession(const LLUUID& session_id); + void removeSession(LLUUID session_id); void inviteToSession( const LLUUID& session_id, diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 40c5a243cc..e5cf8ccf66 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -3084,8 +3084,15 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) items.push_back(std::string("Landmark Separator")); items.push_back(std::string("Teleport To Landmark")); - hideContextEntries(menu, items, disabled_items); + // Disable "About Landmark" menu item for + // multiple landmarks selected. Only one landmark + // info panel can be shown at a time. + if ((flags & FIRST_SELECTED_ITEM) == 0) + { + disabled_items.push_back(std::string("Teleport To Landmark")); + } + hideContextEntries(menu, items, disabled_items); } // Convenience function for the two functions below. diff --git a/indra/newview/lllandmarkactions.cpp b/indra/newview/lllandmarkactions.cpp index df9aa32d1b..2ad83c76b5 100644 --- a/indra/newview/lllandmarkactions.cpp +++ b/indra/newview/lllandmarkactions.cpp @@ -52,10 +52,10 @@ #include "llinventorymodel.h" #include "llagentui.h" -// Returns true if the given inventory item is a landmark pointing to the current parcel. -// Used to filter inventory items. -class LLIsAgentParcelLandmark : public LLInventoryCollectFunctor + +class LLFetchlLandmarkByAgentPos : public LLInventoryCollectFunctor { + public: /*virtual*/ bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) { @@ -69,8 +69,11 @@ public: LLVector3d landmark_global_pos; if (!landmark->getGlobalPos(landmark_global_pos)) return false; - - return LLViewerParcelMgr::getInstance()->inAgentParcel(landmark_global_pos); + LLVector3d a_pos = gAgent.getPositionGlobal(); + //we have to round off each coordinates to compare positions properly + return llround(a_pos.mdV[VX]) == llround(landmark_global_pos.mdV[VX]) + && llround(a_pos.mdV[VY]) == llround(landmark_global_pos.mdV[VY]) + && llround(a_pos.mdV[VZ]) == llround(landmark_global_pos.mdV[VZ]); } }; @@ -139,24 +142,22 @@ LLInventoryModel::item_array_t LLLandmarkActions::fetchLandmarksByName(std::stri bool LLLandmarkActions::landmarkAlreadyExists() { - // Determine whether there are landmarks pointing to the current parcel. - LLInventoryModel::item_array_t items; - collectParcelLandmark(items); - return !items.empty(); + // Determine whether there are landmarks pointing to the current global agent position. + return findLandmarkForAgentPos() != NULL; } -LLViewerInventoryItem* LLLandmarkActions::findLandmarkForAgentParcel() +LLViewerInventoryItem* LLLandmarkActions::findLandmarkForAgentPos() { // Determine whether there are landmarks pointing to the current parcel. LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; - LLIsAgentParcelLandmark is_current_parcel_landmark; + LLFetchlLandmarkByAgentPos is_current_pos_landmark; gInventory.collectDescendentsIf(gInventory.getRootFolderID(), cats, items, LLInventoryModel::EXCLUDE_TRASH, - is_current_parcel_landmark); + is_current_pos_landmark); if(items.empty()) { @@ -287,13 +288,3 @@ bool LLLandmarkActions::getLandmarkGlobalPos(const LLUUID& landmarkInventoryItem return landmark->getGlobalPos(posGlobal); } - -void LLLandmarkActions::collectParcelLandmark(LLInventoryModel::item_array_t& items){ - LLInventoryModel::cat_array_t cats; - LLIsAgentParcelLandmark is_current_parcel_landmark; - gInventory.collectDescendentsIf(gInventory.getRootFolderID(), - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - is_current_parcel_landmark); -} diff --git a/indra/newview/lllandmarkactions.h b/indra/newview/lllandmarkactions.h index c74072c0f4..ce3ed76090 100644 --- a/indra/newview/lllandmarkactions.h +++ b/indra/newview/lllandmarkactions.h @@ -53,12 +53,12 @@ public: static bool landmarkAlreadyExists(); /** - * @brief Searches landmark for parcel agent is currently in. - * @return Returns landmark for agent parcel or NULL. + * @brief Searches landmark for agent global position. + * @return Returns landmark or NULL. * * *TODO: dzaporozhan: There can be many landmarks for single parcel. */ - static LLViewerInventoryItem* findLandmarkForAgentParcel(); + static LLViewerInventoryItem* findLandmarkForAgentPos(); /** * @brief Checks whether agent has rights to create landmark for current parcel. @@ -77,14 +77,6 @@ public: const std::string& name, const std::string& desc, const LLUUID& folder_id); - - /** - * @brief Trying to find in inventory a landmark of the current parcel. - * Normally items should contain only one item, - * because we can create the only landmark per parcel according to Navigation spec. - */ - static void collectParcelLandmark(LLInventoryModel::item_array_t& items); - /** * @brief Creates SLURL for given global position. */ diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index 1d9220cf3d..9d14a3fbdc 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -419,8 +419,7 @@ void LLLocationInputCtrl::onInfoButtonClicked() void LLLocationInputCtrl::onAddLandmarkButtonClicked() { - LLViewerInventoryItem* landmark = LLLandmarkActions::findLandmarkForAgentParcel(); - + LLViewerInventoryItem* landmark = LLLandmarkActions::findLandmarkForAgentPos(); // Landmark exists, open it for preview and edit if(landmark && landmark->getUUID().notNull()) { @@ -677,15 +676,16 @@ void LLLocationInputCtrl::onLocationContextMenuItemClicked(const LLSD& userdata) } else if (item == std::string("landmark")) { - LLInventoryModel::item_array_t items; - LLLandmarkActions::collectParcelLandmark(items); + LLViewerInventoryItem* landmark = LLLandmarkActions::findLandmarkForAgentPos(); - if(items.empty()) + if(!landmark) { LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", "create_landmark")); - }else{ + } + else + { LLSideTray::getInstance()->showPanel("panel_places", - LLSD().insert("type", "landmark").insert("id",items.get(0)->getUUID())); + LLSD().insert("type", "landmark").insert("id",landmark->getUUID())); } } else if (item == std::string("cut")) diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index 11c8b03f7f..d8f00ec370 100644 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -71,7 +71,7 @@ const std::string BOTTOM_TRAY_BUTTON_NAME = "movement_btn"; // protected LLFloaterMove::LLFloaterMove(const LLSD& key) -: LLFloater(key), +: LLDockableFloater(NULL, false, key), mForwardButton(NULL), mBackwardButton(NULL), mTurnLeftButton(NULL), @@ -79,7 +79,8 @@ LLFloaterMove::LLFloaterMove(const LLSD& key) mMoveUpButton(NULL), mMoveDownButton(NULL), mStopFlyingButton(NULL), - mModeActionsPanel(NULL) + mModeActionsPanel(NULL), + mCurrentMode(MM_WALK) { } @@ -88,6 +89,7 @@ BOOL LLFloaterMove::postBuild() { setIsChrome(TRUE); + LLDockableFloater::postBuild(); mForwardButton = getChild("forward btn"); mForwardButton->setHeldDownDelay(MOVE_BUTTON_DELAY); @@ -134,8 +136,6 @@ BOOL LLFloaterMove::postBuild() initModeTooltips(); - updatePosition(); - initModeButtonMap(); initMovementMode(); @@ -145,6 +145,18 @@ BOOL LLFloaterMove::postBuild() return TRUE; } +// virtual +void LLFloaterMove::setEnabled(BOOL enabled) +{ + //we need to enable/disable only buttons, EXT-1061. + + // is called before postBuild() - use findChild here. + LLPanel *panel_actions = findChild("panel_actions"); + if (panel_actions) panel_actions->setEnabled(enabled); + + showModeButtons(enabled); +} + // static F32 LLFloaterMove::getYawRate( F32 time ) { @@ -266,6 +278,7 @@ void LLFloaterMove::onStopFlyingButtonClick() void LLFloaterMove::setMovementMode(const EMovementMode mode) { + mCurrentMode = mode; gAgent.setFlying(MM_FLY == mode); switch (mode) @@ -401,26 +414,49 @@ void LLFloaterMove::sUpdateFlyingStatus() void LLFloaterMove::showModeButtons(BOOL bShow) { - if (mModeActionsPanel->getVisible() == bShow) + // is called from setEnabled so can be called before postBuild(), check mModeActionsPanel agains to NULL + if (NULL == mModeActionsPanel || mModeActionsPanel->getVisible() == bShow) return; mModeActionsPanel->setVisible(bShow); + if (isDocked()) + { + return; + } + + updateHeight(bShow); +} + +void LLFloaterMove::updateHeight(bool show_mode_buttons) +{ + static bool size_changed = false; + static S32 origin_height = getRect().getHeight(); LLRect rect = getRect(); - static S32 height = mModeActionsPanel->getRect().getHeight(); + static S32 mode_panel_height = mModeActionsPanel->getRect().getHeight(); + S32 newHeight = getRect().getHeight(); - if (!bShow) + + if (!show_mode_buttons && origin_height == newHeight) { - newHeight -= height; + newHeight -= mode_panel_height; + size_changed = true; } - else + else if (show_mode_buttons && origin_height > newHeight) { - newHeight += height; + newHeight += mode_panel_height; + size_changed = true; } + + if (!size_changed) + return; + rect.setLeftTopAndSize(rect.mLeft, rect.mTop, rect.getWidth(), newHeight); reshape(rect.getWidth(), rect.getHeight()); setRect(rect); + size_changed = false; } + //static void LLFloaterMove::enableInstance(BOOL bEnable) { @@ -428,17 +464,42 @@ void LLFloaterMove::enableInstance(BOOL bEnable) if (instance) { instance->setEnabled(bEnable); - instance->showModeButtons(bEnable); } } void LLFloaterMove::onOpen(const LLSD& key) { - updatePosition(); + LLButton *anchor_panel = LLBottomTray::getInstance()->getChild("movement_btn"); + + if (gAgent.getFlying()) + { + setFlyingMode(TRUE); + showModeButtons(FALSE); + } + + if (gAgent.getAvatarObject() && gAgent.getAvatarObject()->isSitting()) + { + setSittingMode(TRUE); + showModeButtons(FALSE); + } + + setDockControl(new LLDockControl( + anchor_panel, this, + getDockTongue(), LLDockControl::TOP)); + + showQuickTips(mCurrentMode); sUpdateFlyingStatus(); } +//virtual +void LLFloaterMove::setDocked(bool docked, bool pop_on_undock/* = true*/) +{ + LLDockableFloater::setDocked(docked, pop_on_undock); + bool show_mode_buttons = isDocked() || !gAgent.getFlying(); + updateHeight(show_mode_buttons); +} + void LLFloaterMove::showQuickTips(const EMovementMode mode) { LLFirstTimeTipsManager::EFirstTimeTipType tipType = LLFirstTimeTipsManager::FTT_MOVE_WALK; @@ -543,6 +604,7 @@ void LLPanelStandStopFlying::setVisible(BOOL visible) if (visible) { updatePosition(); + getParent()->sendChildToFront(this); } LLPanel::setVisible(visible); @@ -600,6 +662,15 @@ void LLPanelStandStopFlying::updatePosition() S32 y = tray->getRect().getHeight(); + LLFloater *move_floater = LLFloaterReg::findInstance("moveview"); + if (move_floater) + { + if (move_floater->isDocked()) + { + y = move_floater->getRect().mBottom + getRect().getHeight(); + } + } + setOrigin(x, y); } diff --git a/indra/newview/llmoveview.h b/indra/newview/llmoveview.h index 6e6af9b693..584c7c494c 100644 --- a/indra/newview/llmoveview.h +++ b/indra/newview/llmoveview.h @@ -34,7 +34,7 @@ #define LL_LLMOVEVIEW_H // Library includes -#include "llfloater.h" +#include "lldockablefloater.h" class LLButton; class LLJoystickAgentTurn; @@ -44,7 +44,7 @@ class LLJoystickAgentSlide; // Classes // class LLFloaterMove -: public LLFloater +: public LLDockableFloater { friend class LLFloaterReg; @@ -54,6 +54,7 @@ private: public: /*virtual*/ BOOL postBuild(); + /*virtual*/ void setEnabled(BOOL enabled); static F32 getYawRate(F32 time); static void setFlyingMode(BOOL fly); void setFlyingModeImpl(BOOL fly); @@ -62,10 +63,7 @@ public: static void setSittingMode(BOOL bSitting); static void enableInstance(BOOL bEnable); /*virtual*/ void onOpen(const LLSD& key); - - // *HACK: due to hard enough to have this control aligned with "Move" button while resizing - // let update its position in each frame - /*virtual*/ void draw(){updatePosition(); LLFloater::draw();} + /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); static void sUpdateFlyingStatus(); @@ -98,6 +96,7 @@ private: void updateButtonsWithMovementMode(const EMovementMode newMode); void updatePosition(); void showModeButtons(BOOL bShow); + void updateHeight(bool show_mode_buttons); public: @@ -117,6 +116,7 @@ private: typedef std::map mode_control_button_map_t; mode_control_button_map_t mModeControlButtonMap; + EMovementMode mCurrentMode; }; diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index 6150d5da37..b53bb586f3 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -482,7 +482,7 @@ BOOL LLNearbyChat::handleRightMouseDown(S32 x, S32 y, MASK mask) void LLNearbyChat::onOpen(const LLSD& key ) { - LLNotificationsUI::LLScreenChannel* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->getChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); + LLNotificationsUI::LLScreenChannel* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); if(chat_channel) { chat_channel->removeToastsFromChannel(); diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index e348189ea9..cec4b9f7c7 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -201,6 +201,35 @@ BOOL LLNearbyChatBar::postBuild() mChatBox->setMaxTextLength(1023); mChatBox->setEnableLineHistory(TRUE); + // TODO: Initialization of the output monitor's params should be done via xml + const S32 MONITOR_RIGHT_PAD = 2; + + LLRect monitor_rect = LLRect(0, 18, 18, 0); + LLRect chatbox_rect = mChatBox->getRect(); + + S32 monitor_height = monitor_rect.getHeight(); + monitor_rect.mLeft = chatbox_rect.getWidth() - monitor_rect.getWidth() - MONITOR_RIGHT_PAD; + monitor_rect.mRight = chatbox_rect.getWidth() - MONITOR_RIGHT_PAD; + monitor_rect.mBottom = (chatbox_rect.getHeight() / 2) - (monitor_height / 2); + monitor_rect.mTop = monitor_rect.mBottom + monitor_height; + + LLOutputMonitorCtrl::Params monitor_params = LLOutputMonitorCtrl::Params(); + monitor_params.name = "output_monitor"; + monitor_params.draw_border(false); + monitor_params.rect(monitor_rect); + monitor_params.auto_update(true); + monitor_params.speaker_id(gAgentID); + + LLView::Follows follows = LLView::Follows(); + follows.flags = FOLLOWS_RIGHT; + monitor_params.follows = follows; + mOutputMonitor = LLUICtrlFactory::create(monitor_params); + mChatBox->addChild(mOutputMonitor); + + // never show "muted" because you can't mute yourself + mOutputMonitor->setIsMuted(false); + mOutputMonitor->setVisible(FALSE); + mTalkBtn = getChild("talk"); // Speak button should be initially disabled because @@ -593,6 +622,7 @@ LLWString LLNearbyChatBar::stripChannelNumber(const LLWString &mesg, S32* channe void LLNearbyChatBar::setPTTState(bool state) { mTalkBtn->setSpeakBtnToggleState(state); + mOutputMonitor->setVisible(state); } void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h index f310740f42..1b71ad69f2 100644 --- a/indra/newview/llnearbychatbar.h +++ b/indra/newview/llnearbychatbar.h @@ -39,6 +39,7 @@ #include "llchat.h" #include "llchiclet.h" #include "llvoiceclient.h" +#include "lloutputmonitorctrl.h" class LLGestureComboBox : public LLComboBox @@ -114,6 +115,7 @@ protected: LLLineEditor* mChatBox; LLTalkButton* mTalkBtn; + LLOutputMonitorCtrl* mOutputMonitor; }; #endif diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index a1912655a3..7eb5d91e53 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -49,23 +49,25 @@ namespace LLNotificationsUI{ LLNearbyChatHandler::LLNearbyChatHandler(e_notification_type type, const LLSD& id) { mType = type; - LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat", LLSD()); - ///////////////////////////////////////////////////// - LLChannelManager::Params p; //TODO: check and correct + LLChannelManager::Params p; p.id = LLUUID(gSavedSettings.getString("NearByChatChannelUUID")); - p.channel_right_bound = nearby_chat->getRect().mRight; - p.channel_width = nearby_chat->getRect().mRight - 16; //HACK: 16 - ? - ///////////////////////////////////////////////////// - // Getting a Channel for our notifications - mChannel = LLChannelManager::getInstance()->createChannel(p); - mChannel->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM | FOLLOWS_TOP); + mChannel = LLChannelManager::getInstance()->getChannel(p); mChannel->setOverflowFormatString("You have %d unread nearby chat messages"); } LLNearbyChatHandler::~LLNearbyChatHandler() { } + +void LLNearbyChatHandler::initChannel() +{ + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat", LLSD()); + S32 channel_right_bound = nearby_chat->getRect().mRight; + S32 channel_width = nearby_chat->getRect().mRight - 16; //HACK: 16 - ? + mChannel->init(channel_right_bound - channel_width, channel_right_bound); +} + void LLNearbyChatHandler::processChat(const LLChat& chat_msg) { if(chat_msg.mMuted == TRUE) @@ -80,6 +82,12 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg) nearby_chat->addMessage(chat_msg); if(nearby_chat->getVisible()) return;//no need in toast if chat is visible + + // arrange a channel on a screen + if(!mChannel->getVisible()) + { + initChannel(); + } LLUUID id; id.generate(); @@ -95,34 +103,14 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg) item->setVisible(true); LLToast::Params p; - p.id = id; + p.notif_id = id; p.panel = item; - p.on_toast_destroy = boost::bind(&LLNearbyChatHandler::onToastDestroy, this, _1); - p.on_mouse_enter = boost::bind(&LLNearbyChatHandler::removeNearbyToastsAndShowChat, this); + p.on_delete_toast = boost::bind(&LLNearbyChatHandler::onDeleteToast, this, _1); mChannel->addToast(p); } -void LLNearbyChatHandler::onToastDestroy(LLToast* toast) +void LLNearbyChatHandler::onDeleteToast(LLToast* toast) { - if(toast) - toast->closeFloater(); -} - -void LLNearbyChatHandler::onChicletClick(void) -{ -} -void LLNearbyChatHandler::onChicletClose(void) -{ -} - -void LLNearbyChatHandler::removeNearbyToastsAndShowChat() -{ - /* - if(mChannel) - mChannel->removeToastsFromChannel(); - - LLFloaterReg::showTypedInstance("nearby_chat", LLSD()); - */ } } diff --git a/indra/newview/llnearbychathandler.h b/indra/newview/llnearbychathandler.h index 8fcd03689d..fb2abac6a4 100644 --- a/indra/newview/llnearbychathandler.h +++ b/indra/newview/llnearbychathandler.h @@ -46,12 +46,10 @@ public: virtual void processChat(const LLChat& chat_msg); - virtual void onToastDestroy(LLToast* toast); - virtual void onChicletClick(void); - virtual void onChicletClose(void); protected: - void removeNearbyToastsAndShowChat(); + virtual void onDeleteToast(LLToast* toast); + virtual void initChannel(); }; } diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp index bd6c6b2308..3893eaa0d4 100644 --- a/indra/newview/llnotificationalerthandler.cpp +++ b/indra/newview/llnotificationalerthandler.cpp @@ -35,8 +35,8 @@ #include "llnotificationhandler.h" #include "lltoastnotifypanel.h" -#include "llbottomtray.h" #include "llviewercontrol.h" +#include "llviewerwindow.h" #include "lltoastalertpanel.h" @@ -47,17 +47,14 @@ LLAlertHandler::LLAlertHandler(e_notification_type type, const LLSD& id) : mIsMo { mType = type; - LLBottomTray* tray = LLBottomTray::getInstance(); LLChannelManager::Params p; p.id = LLUUID(gSavedSettings.getString("AlertChannelUUID")); - p.channel_right_bound = tray->getRect().getWidth() / 2; - p.channel_width = 0; p.display_toasts_always = true; - p.align = NA_CENTRE; + p.toast_align = NA_CENTRE; + p.channel_align = CA_CENTRE; // Getting a Channel for our notifications - mChannel = LLChannelManager::getInstance()->createChannel(p); - mChannel->setFollows(FOLLOWS_BOTTOM | FOLLOWS_TOP); + mChannel = LLChannelManager::getInstance()->getChannel(p); mChannel->setShowToasts(true); } @@ -67,21 +64,42 @@ LLAlertHandler::~LLAlertHandler() } //-------------------------------------------------------------------------- -void LLAlertHandler::processNotification(const LLSD& notify) +void LLAlertHandler::initChannel() { + S32 channel_right_bound = gViewerWindow->getWorldViewRect().getWidth() / 2; + mChannel->init(channel_right_bound, channel_right_bound); +} + +//-------------------------------------------------------------------------- +bool LLAlertHandler::processNotification(const LLSD& notify) +{ + if(!mChannel) + { + return false; + } + LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); + if(!notification) + return false; + + // arrange a channel on a screen + if(!mChannel->getVisible()) + { + initChannel(); + } + if (notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "load") { LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); LLToast::Params p; - p.id = notification->getID(); + p.notif_id = notification->getID(); p.notification = notification; p.panel = dynamic_cast(alert_dialog); p.enable_hide_btn = false; p.can_fade = false; p.is_modal = mIsModal; - p.on_toast_destroy = boost::bind(&LLAlertHandler::onToastDestroy, this, _1); + p.on_delete_toast = boost::bind(&LLAlertHandler::onDeleteToast, this, _1); mChannel->addToast(p); } else if (notify["sigtype"].asString() == "change") @@ -93,25 +111,14 @@ void LLAlertHandler::processNotification(const LLSD& notify) { mChannel->killToastByNotificationID(notification->getID()); } + return true; } //-------------------------------------------------------------------------- -void LLAlertHandler::onToastDestroy(LLToast* toast) -{ - toast->closeFloater(); -} - -//-------------------------------------------------------------------------- -void LLAlertHandler::onChicletClick(void) -{ -} - -//-------------------------------------------------------------------------- -void LLAlertHandler::onChicletClose(void) +void LLAlertHandler::onDeleteToast(LLToast* toast) { } //-------------------------------------------------------------------------- - diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp index 31753efec9..c488d37ea5 100644 --- a/indra/newview/llnotificationgrouphandler.cpp +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -34,11 +34,9 @@ #include "llnotificationhandler.h" #include "lltoastgroupnotifypanel.h" -#include "llbottomtray.h" #include "llgroupactions.h" #include "llviewercontrol.h" -#include "llfloaterreg.h" -#include "llsyswellwindow.h" +#include "llviewerwindow.h" using namespace LLNotificationsUI; @@ -47,16 +45,8 @@ LLGroupHandler::LLGroupHandler(e_notification_type type, const LLSD& id) { mType = type; - // getting a Chiclet and creating params for a channel - LLBottomTray* tray = LLBottomTray::getInstance(); - mChiclet = tray->getSysWell(); - LLChannelManager::Params p; - p.id = LLUUID(gSavedSettings.getString("NotificationChannelUUID")); - p.channel_right_bound = tray->getRect().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); - p.channel_width = gSavedSettings.getS32("NotifyBoxWidth"); - // Getting a Channel for our notifications - mChannel = LLChannelManager::getInstance()->createChannel(p); + mChannel = LLChannelManager::getInstance()->createNotificationChannel(); } //-------------------------------------------------------------------------- @@ -65,52 +55,63 @@ LLGroupHandler::~LLGroupHandler() } //-------------------------------------------------------------------------- -void LLGroupHandler::processNotification(const LLSD& notify) +void LLGroupHandler::initChannel() { + S32 channel_right_bound = gViewerWindow->getWorldViewRect().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); + S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth"); + mChannel->init(channel_right_bound - channel_width, channel_right_bound); +} + +//-------------------------------------------------------------------------- +bool LLGroupHandler::processNotification(const LLSD& notify) +{ + if(!mChannel) + { + return false; + } + LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); + + if(!notification) + return false; + + // arrange a channel on a screen + if(!mChannel->getVisible()) + { + initChannel(); + } + if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") { LLPanel* notify_box = new LLToastGroupNotifyPanel(notification); LLToast::Params p; - p.id = notification->getID(); + p.notif_id = notification->getID(); p.notification = notification; p.panel = notify_box; - p.on_toast_destroy = boost::bind(&LLGroupHandler::onToastDestroy, this, _1); + p.on_delete_toast = boost::bind(&LLGroupHandler::onDeleteToast, this, _1); mChannel->addToast(p); - static_cast(mChiclet)->incUreadSystemNotifications(); - - LLGroupActions::refresh_notices(); + // send a signal to the counter manager + mNewNotificationSignal(); + + LLGroupActions::refresh_notices(); } else if (notify["sigtype"].asString() == "delete") { mChannel->killToastByNotificationID(notification->getID()); } + return true; } //-------------------------------------------------------------------------- -void LLGroupHandler::onToastDestroy(LLToast* toast) -{ - static_cast(mChiclet)->decUreadSystemNotifications(); - - LLToastPanel* panel = dynamic_cast(toast->getPanel()); - LLFloaterReg::getTypedInstance("syswell_window")->removeItemByID(panel->getID()); - - // turning hovering off mannualy because onMouseLeave won't happen if a toast was closed using a keyboard - if(toast->hasFocus()) - mChannel->setHovering(false); - - toast->closeFloater(); -} - -//-------------------------------------------------------------------------- -void LLGroupHandler::onChicletClick(void) +void LLGroupHandler::onDeleteToast(LLToast* toast) { -} + // send a signal to the counter manager + mDelNotificationSignal(); -//-------------------------------------------------------------------------- -void LLGroupHandler::onChicletClose(void) -{ + // send a signal to a listener to let him perform some action + // in this case listener is a SysWellWindow and it will remove a corresponding item from its list + mNotificationIDSignal(toast->getNotificationID()); } //-------------------------------------------------------------------------- diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 6982ab7096..90ff5fbaac 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -65,33 +65,54 @@ typedef enum e_notification_type // LLEventHandler is a base class that specifies a common interface for all // notification handlers. It states, that every handler must react on the follofing // events: -// - destroying of a toast; -// - clicking on a correspondet chiclet; -// - closing of a correspondent chiclet. +// - deleting of a toast; +// - initialization of a corresponding channel; // Also every handler must have the following attributes: // - type of the notification that this handler is responsible to; -// - pointer to a correspondent chiclet; // - pointer to a correspondent screen channel, in which all toasts of the handled notification's // type should be displayed +// This class also provides the following signald: +// - increment counter signal +// - decrement counter signal +// - update counter signal +// - signal, that emits ID of the notification that is being processed // class LLEventHandler { public: virtual ~LLEventHandler() {}; - virtual void onToastDestroy(LLToast* toast)=0; - virtual void onChicletClick(void)=0; - virtual void onChicletClose(void)=0; + // callbacks for counters + typedef boost::function notification_callback_t; + typedef boost::signals2::signal notification_signal_t; + notification_signal_t mNewNotificationSignal; + notification_signal_t mDelNotificationSignal; + boost::signals2::connection setNewNotificationCallback(notification_callback_t cb) { return mNewNotificationSignal.connect(cb); } + boost::signals2::connection setDelNotification(notification_callback_t cb) { return mDelNotificationSignal.connect(cb); } + // callback for notification/toast + typedef boost::function notification_id_callback_t; + typedef boost::signals2::signal notification_id_signal_t; + notification_id_signal_t mNotificationIDSignal; + boost::signals2::connection setNotificationIDCallback(notification_id_callback_t cb) { return mNotificationIDSignal.connect(cb); } + +protected: + virtual void onDeleteToast(LLToast* toast)=0; + + // arrange handler's channel on a screen + // is necessary to unbind a moment of creation of a channel and a moment of positioning of it + // it is useful when positioning depends on positions of other controls, that could not be created + // at the moment, when a handlers creates a channel. + virtual void initChannel()=0; LLScreenChannel* mChannel; - LLChiclet* mChiclet; e_notification_type mType; + }; // LLSysHandler and LLChatHandler are more specific base classes // that divide all notification handlers on to groups: -// - handlers for different system notifications (script dialogs, tips, group notices and alerts); -// - handlers for different messaging notifications (nearby chat, IM chat, group chat etc.) +// - handlers for different system notifications (script dialogs, tips, group notices, alerts and IMs); +// - handlers for different messaging notifications (nearby chat) /** * Handler for system notifications. */ @@ -100,7 +121,7 @@ class LLSysHandler : public LLEventHandler public: virtual ~LLSysHandler() {}; - virtual void processNotification(const LLSD& notify)=0; + virtual bool processNotification(const LLSD& notify)=0; }; /** @@ -116,43 +137,59 @@ public: /** * Handler for IM notifications. - * It manages life time of tip and script notices. + * It manages life time of IMs, group messages. */ class LLIMHandler : public LLSysHandler { public: - LLIMHandler(); + LLIMHandler(e_notification_type type, const LLSD& id); virtual ~LLIMHandler(); // base interface functions - virtual void processNotification(const LLSD& notify); - virtual void onToastDestroy(LLToast* toast); - virtual void onChicletClick(void); - virtual void onChicletClose(void); + virtual bool processNotification(const LLSD& notify); protected: + virtual void onDeleteToast(LLToast* toast); + virtual void initChannel(); }; /** * Handler for system informational notices. - * It manages life time of tip and script notices. + * It manages life time of tip notices. */ -class LLInfoHandler : public LLSysHandler +class LLTipHandler : public LLSysHandler { public: - LLInfoHandler(e_notification_type type, const LLSD& id); - virtual ~LLInfoHandler(); + LLTipHandler(e_notification_type type, const LLSD& id); + virtual ~LLTipHandler(); // base interface functions - virtual void processNotification(const LLSD& notify); - virtual void onToastDestroy(LLToast* toast); - virtual void onChicletClick(void); - virtual void onChicletClose(void); + virtual bool processNotification(const LLSD& notify); - // own handlers - void onStoreToast(LLPanel* info_panel, LLUUID id); - void onRejectToast(LLToast::Params p); protected: + virtual void onDeleteToast(LLToast* toast); + virtual void initChannel(); +}; + +/** + * Handler for system informational notices. + * It manages life time of script notices. + */ +class LLScriptHandler : public LLSysHandler +{ +public: + LLScriptHandler(e_notification_type type, const LLSD& id); + virtual ~LLScriptHandler(); + + // base interface functions + virtual bool processNotification(const LLSD& notify); + +protected: + virtual void onDeleteToast(LLToast* toast); + virtual void initChannel(); + + // own handlers + void onRejectToast(LLUUID& id); }; @@ -164,14 +201,13 @@ class LLGroupHandler : public LLSysHandler public: LLGroupHandler(e_notification_type type, const LLSD& id); virtual ~LLGroupHandler(); - - - virtual void processNotification(const LLSD& notify); - virtual void onToastDestroy(LLToast* toast); - virtual void onChicletClick(void); - virtual void onChicletClose(void); + + // base interface functions + virtual bool processNotification(const LLSD& notify); protected: + virtual void onDeleteToast(LLToast* toast); + virtual void initChannel(); }; /** @@ -185,12 +221,13 @@ public: void setAlertMode(bool is_modal) { mIsModal = is_modal; } - virtual void processNotification(const LLSD& notify); - virtual void onToastDestroy(LLToast* toast); - virtual void onChicletClick(void); - virtual void onChicletClose(void); + // base interface functions + virtual bool processNotification(const LLSD& notify); protected: + virtual void onDeleteToast(LLToast* toast); + virtual void initChannel(); + bool mIsModal; }; diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp index 31266fdecf..81a6b32917 100644 --- a/indra/newview/llnotificationmanager.cpp +++ b/indra/newview/llnotificationmanager.cpp @@ -71,12 +71,13 @@ void LLNotificationManager::init() LLNotifications::instance().getChannel("AlertModal")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); LLNotifications::instance().getChannel("IM Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); - mNotifyHandlers["notify"] = boost::shared_ptr(new LLInfoHandler(NT_NOTIFY, LLSD())); - mNotifyHandlers["notifytip"] = mNotifyHandlers["notify"]; + mNotifyHandlers["notify"] = boost::shared_ptr(new LLScriptHandler(NT_NOTIFY, LLSD())); + mNotifyHandlers["notifytip"] = boost::shared_ptr(new LLTipHandler(NT_NOTIFY, LLSD())); mNotifyHandlers["groupnotify"] = boost::shared_ptr(new LLGroupHandler(NT_GROUPNOTIFY, LLSD())); mNotifyHandlers["alert"] = boost::shared_ptr(new LLAlertHandler(NT_ALERT, LLSD())); - mNotifyHandlers["alertmodal"] = mNotifyHandlers["alert"]; - mNotifyHandlers["notifytoast"] = boost::shared_ptr(new LLIMHandler()); + mNotifyHandlers["alertmodal"] = boost::shared_ptr(new LLAlertHandler(NT_ALERT, LLSD())); + static_cast(mNotifyHandlers["alertmodal"].get())->setAlertMode(true); + mNotifyHandlers["notifytoast"] = boost::shared_ptr(new LLIMHandler(NT_IMCHAT, LLSD())); mNotifyHandlers["nearbychat"] = boost::shared_ptr(new LLNearbyChatHandler(NT_NEARBYCHAT, LLSD())); } @@ -92,17 +93,12 @@ bool LLNotificationManager::onNotification(const LLSD& notify) return false; std::string notification_type = notification->getType(); - handle = dynamic_cast(mNotifyHandlers[notification_type].get()); + handle = static_cast(mNotifyHandlers[notification_type].get()); if(!handle) return false; - if( notification_type == "alertmodal" ) - dynamic_cast(handle)->setAlertMode(true); - - handle->processNotification(notify); - - return true; + return handle->processNotification(notify); } //-------------------------------------------------------------------------- @@ -124,7 +120,15 @@ void LLNotificationManager::onChat(const LLChat& msg,ENotificationType type) } //-------------------------------------------------------------------------- +LLEventHandler* LLNotificationManager::getHandlerForNotification(std::string notification_type) +{ + std::map >::iterator it = mNotifyHandlers.find(notification_type); + if(it != mNotifyHandlers.end()) + return (*it).second.get(); + return NULL; +} +//-------------------------------------------------------------------------- diff --git a/indra/newview/llnotificationmanager.h b/indra/newview/llnotificationmanager.h index 838a00ee11..072fc6f24c 100644 --- a/indra/newview/llnotificationmanager.h +++ b/indra/newview/llnotificationmanager.h @@ -50,7 +50,7 @@ class LLToast; /** * Responsible for registering notification handlers. */ -class LLNotificationManager : public LLUICtrl, public LLSingleton +class LLNotificationManager : public LLSingleton { typedef std::pair eventhandlers; public: @@ -68,6 +68,10 @@ public: // this method reacts on chat notifications and calls an appropriate handler void onChat(const LLChat& msg,ENotificationType type); + // get a handler for a certain type of notification + LLEventHandler* getHandlerForNotification(std::string notification_type); + + private: //TODO (*) std::map > mNotifyHandlers; diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp new file mode 100644 index 0000000000..72855ac0fd --- /dev/null +++ b/indra/newview/llnotificationscripthandler.cpp @@ -0,0 +1,135 @@ +/** + * @file llnotificationscripthandler.cpp + * @brief Notification Handler Class for Simple Notifications and Notification Tips + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + + +#include "llviewerprecompiledheaders.h" // must be first include + +#include "llnotificationhandler.h" +#include "lltoastnotifypanel.h" +#include "llviewercontrol.h" +#include "llviewerwindow.h" + +using namespace LLNotificationsUI; + +//-------------------------------------------------------------------------- +LLScriptHandler::LLScriptHandler(e_notification_type type, const LLSD& id) +{ + mType = type; + + // Getting a Channel for our notifications + mChannel = LLChannelManager::getInstance()->createNotificationChannel(); + mChannel->setControlHovering(true); + mChannel->setOnRejectToastCallback(boost::bind(&LLScriptHandler::onRejectToast, this, _1)); +} + +//-------------------------------------------------------------------------- +LLScriptHandler::~LLScriptHandler() +{ +} + +//-------------------------------------------------------------------------- +void LLScriptHandler::initChannel() +{ + S32 channel_right_bound = gViewerWindow->getWorldViewRect().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); + S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth"); + mChannel->init(channel_right_bound - channel_width, channel_right_bound); +} + +//-------------------------------------------------------------------------- +bool LLScriptHandler::processNotification(const LLSD& notify) +{ + if(!mChannel) + { + return false; + } + + LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); + + if(!notification) + return false; + + // arrange a channel on a screen + if(!mChannel->getVisible()) + { + initChannel(); + } + + if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") + { + LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); + + LLToast::Params p; + p.notif_id = notification->getID(); + p.notification = notification; + p.panel = notify_box; + p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1); + mChannel->addToast(p); + + // send a signal to the counter manager + mNewNotificationSignal(); + + } + else if (notify["sigtype"].asString() == "delete") + { + mChannel->killToastByNotificationID(notification->getID()); + } + return true; +} + +//-------------------------------------------------------------------------- + +void LLScriptHandler::onDeleteToast(LLToast* toast) +{ + // send a signal to the counter manager + mDelNotificationSignal(); + + // send a signal to a listener to let him perform some action + // in this case listener is a SysWellWindow and it will remove a corresponding item from its list + mNotificationIDSignal(toast->getNotificationID()); +} + +//-------------------------------------------------------------------------- +void LLScriptHandler::onRejectToast(LLUUID& id) +{ + LLNotificationPtr notification = LLNotifications::instance().find(id); + + if(notification) + { + LLNotifications::instance().cancel(notification); + } +} + +//-------------------------------------------------------------------------- + + + + diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp new file mode 100644 index 0000000000..740acb6365 --- /dev/null +++ b/indra/newview/llnotificationtiphandler.cpp @@ -0,0 +1,113 @@ +/** + * @file llnotificationtiphandler.cpp + * @brief Notification Handler Class for Notification Tips + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + + +#include "llviewerprecompiledheaders.h" // must be first include + +#include "llnotificationhandler.h" +#include "lltoastnotifypanel.h" +#include "llviewercontrol.h" +#include "llviewerwindow.h" + +using namespace LLNotificationsUI; + + +//-------------------------------------------------------------------------- +LLTipHandler::LLTipHandler(e_notification_type type, const LLSD& id) +{ + mType = type; + + // Getting a Channel for our notifications + mChannel = LLChannelManager::getInstance()->createNotificationChannel(); +} + +//-------------------------------------------------------------------------- +LLTipHandler::~LLTipHandler() +{ +} + +//-------------------------------------------------------------------------- +void LLTipHandler::initChannel() +{ + S32 channel_right_bound = gViewerWindow->getWorldViewRect().mRight - gSavedSettings.getS32("NotificationChannelRightMargin"); + S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth"); + mChannel->init(channel_right_bound - channel_width, channel_right_bound); +} + +//-------------------------------------------------------------------------- +bool LLTipHandler::processNotification(const LLSD& notify) +{ + if(!mChannel) + { + return false; + } + + LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); + + if(!notification) + return false; + + // arrange a channel on a screen + if(!mChannel->getVisible()) + { + initChannel(); + } + + if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") + { + LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); + + LLToast::Params p; + p.notif_id = notification->getID(); + p.notification = notification; + p.panel = notify_box; + p.is_tip = true; + p.can_be_stored = false; + + mChannel->addToast(p); + + } + else if (notify["sigtype"].asString() == "delete") + { + mChannel->killToastByNotificationID(notification->getID()); + } + return true; +} + +//-------------------------------------------------------------------------- +void LLTipHandler::onDeleteToast(LLToast* toast) +{ +} + +//-------------------------------------------------------------------------- + + diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp index 49b48f5a8e..6e1dc6940e 100644 --- a/indra/newview/lloutputmonitorctrl.cpp +++ b/indra/newview/lloutputmonitorctrl.cpp @@ -129,10 +129,10 @@ void LLOutputMonitorCtrl::draw() const F32 LEVEL_1 = LLVoiceClient::OVERDRIVEN_POWER_LEVEL * 2.f / 3.f; const F32 LEVEL_2 = LLVoiceClient::OVERDRIVEN_POWER_LEVEL; - if (getVisible() && mAutoUpdate && !mIsMuted && mSpeakerId.notNull()) + if (mIsParentVisible && getVisible() && mAutoUpdate && !mIsMuted && mSpeakerId.notNull()) { setPower(gVoiceClient->getCurrentPower(mSpeakerId)); - setIsTalking(gVoiceClient->getUserPTTState()); + setIsTalking(gVoiceClient->getIsSpeaking(mSpeakerId)); } LLPointer icon; @@ -220,6 +220,12 @@ void LLOutputMonitorCtrl::draw() gl_rect_2d(0, monh, monw, 0, sColorBound, FALSE); } +void LLOutputMonitorCtrl::handleVisibilityChange(BOOL new_visibility) +{ + mIsParentVisible = new_visibility; + LLView::handleVisibilityChange(new_visibility); +} + void LLOutputMonitorCtrl::setSpeakerId(const LLUUID& speaker_id) { if (speaker_id.isNull()) return; diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h index 7a7b8bc3a1..0e213c4326 100644 --- a/indra/newview/lloutputmonitorctrl.h +++ b/indra/newview/lloutputmonitorctrl.h @@ -72,6 +72,8 @@ public: // llview overrides virtual void draw(); + void handleVisibilityChange(BOOL new_visibility); + void setPower(F32 val); F32 getPower(F32 val) const { return mPower; } @@ -102,6 +104,8 @@ private: F32 mPower; bool mIsMuted; bool mIsTalking; + /** Stores flag whether parent is visible. If not it will not update indicator*/ + bool mIsParentVisible; LLPointer mImageMute; LLPointer mImageOff; LLPointer mImageOn; diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index b7f2f67a9a..649697e091 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -311,7 +311,8 @@ void LLPanelProfileTab::onOpen(const LLSD& key) void LLPanelProfileTab::scrollToTop() { - LLScrollContainer* scrollContainer = getChild("profile_scroll"); + LLScrollContainer* scrollContainer = findChild("profile_scroll"); + if (scrollContainer) scrollContainer->goToTop(); } diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index d1ce6b14ed..490c845c94 100644 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -44,6 +44,9 @@ #include "llfloaterreg.h" #include "llfloater.h" +#include "llagent.h" +#include "llstatusbar.h" // can_afford_transaction() + #include "llsidetraypanelcontainer.h" #include "llpanelgroupnotices.h" @@ -162,15 +165,25 @@ BOOL LLPanelGroup::postBuild() button->setEnabled(false); + button = getChild("btn_join"); + button->setVisible(false); + button->setEnabled(true); + + button = getChild("btn_cancel"); + button->setVisible(false); button->setEnabled(true); + button = getChild("btn_refresh"); button->setClickedCallback(onBtnRefresh, this); button->setVisible(mAllowEdit); getChild("btn_create")->setVisible(false); - childSetCommitCallback("btn_create",boost::bind(&LLPanelGroup::onBtnCreate,this),NULL); childSetCommitCallback("back",boost::bind(&LLPanelGroup::onBackBtnClick,this),NULL); + childSetCommitCallback("btn_create",boost::bind(&LLPanelGroup::onBtnCreate,this),NULL); + childSetCommitCallback("btn_join",boost::bind(&LLPanelGroup::onBtnJoin,this),NULL); + childSetCommitCallback("btn_cancel",boost::bind(&LLPanelGroup::onBtnCancel,this),NULL); + LLPanelGroupTab* panel_general = findChild("group_general_tab_panel"); LLPanelGroupTab* panel_roles = findChild("group_roles_tab_panel"); LLPanelGroupTab* panel_notices = findChild("group_notices_tab_panel"); @@ -181,41 +194,30 @@ BOOL LLPanelGroup::postBuild() if(panel_notices) mTabs.push_back(panel_notices); if(panel_land) mTabs.push_back(panel_land); + if(panel_general) panel_general->setupCtrls(this); return TRUE; } -void LLPanelGroup::reshape(S32 width, S32 height, BOOL called_from_parent ) +void LLPanelGroup::reposButton(const std::string& name) { - LLPanel::reshape(width, height, called_from_parent ); - - LLRect btn_rect; - - LLButton* button = findChild("btn_apply"); - if(button) - { - btn_rect = button->getRect(); - btn_rect.setLeftTopAndSize( btn_rect.mLeft, btn_rect.getHeight() + 2, btn_rect.getWidth(), btn_rect.getHeight()); - button->setRect(btn_rect); - } - - button = findChild("btn_create"); - if(button) - { - btn_rect = button->getRect(); + LLButton* button = findChild(name); + if(!button) + return; + LLRect btn_rect = button->getRect(); btn_rect.setLeftTopAndSize( btn_rect.mLeft, btn_rect.getHeight() + 2, btn_rect.getWidth(), btn_rect.getHeight()); button->setRect(btn_rect); - } +} +void LLPanelGroup::reshape(S32 width, S32 height, BOOL called_from_parent ) +{ + LLPanel::reshape(width, height, called_from_parent ); - button = findChild("btn_refresh"); - if(button) - { - btn_rect = button->getRect(); - btn_rect.setLeftTopAndSize( btn_rect.mLeft, btn_rect.getHeight() + 2, btn_rect.getWidth(), btn_rect.getHeight()); - button->setRect(btn_rect); - } + reposButton("btn_apply"); + reposButton("btn_create"); + reposButton("btn_refresh"); + reposButton("btn_cancel"); } void LLPanelGroup::onBackBtnClick() @@ -247,33 +249,94 @@ void LLPanelGroup::onBtnApply(void* user_data) LLPanelGroup* self = static_cast(user_data); self->apply(); } +void LLPanelGroup::onBtnJoin() +{ + lldebugs << "joining group: " << mID << llendl; + + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mID); + + if (gdatap) + { + S32 cost = gdatap->mMembershipFee; + LLSD args; + args["COST"] = llformat("%d", cost); + LLSD payload; + payload["group_id"] = mID; + + if (can_afford_transaction(cost)) + { + LLNotifications::instance().add("JoinGroupCanAfford", args, payload, LLPanelGroup::joinDlgCB); + } + else + { + LLNotifications::instance().add("JoinGroupCannotAfford", args, payload); + } + } + else + { + llwarns << "LLGroupMgr::getInstance()->getGroupData(" << mID << ") was NULL" << llendl; + } +} +bool LLPanelGroup::joinDlgCB(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + + if (option == 1) + { + // user clicked cancel + return false; + } + + LLGroupMgr::getInstance()->sendGroupMemberJoin(notification["payload"]["group_id"].asUUID()); + return false; +} + +void LLPanelGroup::onBtnCancel() +{ + onBackBtnClick(); +} void LLPanelGroup::changed(LLGroupChange gc) { for(std::vector::iterator it = mTabs.begin();it!=mTabs.end();++it) (*it)->update(gc); - - LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mID); - if(gdatap) - childSetValue("group_name", gdatap->mName); + update(gc); } void LLPanelGroup::notifyObservers() { - for(std::vector::iterator it = mTabs.begin();it!=mTabs.end();++it) - (*it)->update(GC_ALL); + changed(GC_ALL); +} +void LLPanelGroup::update(LLGroupChange gc) +{ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mID); if(gdatap) + { childSetValue("group_name", gdatap->mName); - -} - + LLGroupData agent_gdatap; + bool is_member = gAgent.getGroupData(mID,agent_gdatap); + LLButton* btn_join = getChild("btn_join"); + bool join_btn_visible = !is_member && gdatap->mOpenEnrollment; + btn_join->setVisible(join_btn_visible); + if(join_btn_visible) + { + LLStringUtil::format_map_t string_args; + string_args["[AMOUNT]"] = llformat("%d", gdatap->mMembershipFee); + std::string fee_buff = getString("group_join_btn", string_args); + btn_join->setLabelSelected(fee_buff); + btn_join->setLabelUnselected(fee_buff); + } + } +} void LLPanelGroup::setGroupID(const LLUUID& group_id) { + std::string str_group_id; + group_id.toString(str_group_id); + LLGroupMgr::getInstance()->removeObserver(this); mID = group_id; LLGroupMgr::getInstance()->addObserver(this); @@ -288,6 +351,8 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id) LLButton* button_apply = findChild("btn_apply"); LLButton* button_refresh = findChild("btn_refresh"); LLButton* button_create = findChild("btn_create"); + LLButton* button_join = findChild("btn_join"); + LLButton* button_cancel = findChild("btn_cancel"); bool is_null_group_id = group_id == LLUUID::null; @@ -295,8 +360,11 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id) button_apply->setVisible(!is_null_group_id); if(button_refresh) button_refresh->setVisible(!is_null_group_id); + if(button_create) button_create->setVisible(is_null_group_id); + if(button_cancel) + button_cancel->setVisible(!is_null_group_id); getChild("prepend_founded_by")->setVisible(!is_null_group_id); @@ -307,6 +375,9 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id) if(!tab_general || !tab_roles || !tab_notices || !tab_land) return; + + if(button_join) + button_join->setVisible(false); if(is_null_group_id)//creating new group { @@ -323,6 +394,10 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id) tab_roles->canOpenClose(false); tab_notices->canOpenClose(false); tab_land->canOpenClose(false); + + getChild("group_name")->setVisible(false); + getChild("group_name_editor")->setVisible(true); + } else { @@ -338,6 +413,9 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id) tab_roles->canOpenClose(true); tab_notices->canOpenClose(true); tab_land->canOpenClose(true); + + getChild("group_name")->setVisible(true); + getChild("group_name_editor")->setVisible(false); } } @@ -395,11 +473,9 @@ void LLPanelGroup::draw() void LLPanelGroup::refreshData() { LLGroupMgr::getInstance()->clearGroupData(getID()); - - for(std::vector::iterator it = mTabs.begin();it!=mTabs.end();++it) - (*it)->activate(); - + setGroupID(getID()); + // 5 second timeout childDisable("btn_refresh"); mRefreshTimer.start(); diff --git a/indra/newview/llpanelgroup.h b/indra/newview/llpanelgroup.h index 6db6738d18..f2118a7244 100644 --- a/indra/newview/llpanelgroup.h +++ b/indra/newview/llpanelgroup.h @@ -91,12 +91,20 @@ public: protected: + virtual void update(LLGroupChange gc); + void onBtnCreate(); void onBackBtnClick(); + void onBtnJoin(); + void onBtnCancel(); static void onBtnApply(void*); static void onBtnRefresh(void*); + static bool joinDlgCB(const LLSD& notification, const LLSD& response); + + void reposButton(const std::string& name); + protected: bool apply(LLPanelGroupTab* tab); diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index f3893a104c..d63fd141b0 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -50,7 +50,6 @@ #include "llnamelistctrl.h" #include "llscrolllistitem.h" #include "llspinctrl.h" -#include "llstatusbar.h" // can_afford_transaction() #include "lltextbox.h" #include "lltexteditor.h" #include "lltexturectrl.h" @@ -96,9 +95,6 @@ BOOL LLPanelGroupGeneral::postBuild() { bool recurse = true; - // General info - mGroupNameEditor = getChild("group_name_editor", recurse); - mEditCharter = getChild("charter", recurse); if(mEditCharter) { @@ -194,7 +190,6 @@ BOOL LLPanelGroupGeneral::postBuild() // If the group_id is null, then we are creating a new group if (mGroupID.isNull()) { - mGroupNameEditor->setEnabled(TRUE); mEditCharter->setEnabled(TRUE); mCtrlShowInGroupList->setEnabled(TRUE); @@ -217,6 +212,7 @@ void LLPanelGroupGeneral::setupCtrls(LLPanel* panel_group) mDefaultIconID = mInsignia->getImageAssetID(); } mFounderName = panel_group->getChild("founder_name"); + mGroupNameEditor = panel_group->getChild("group_name_editor"); } // static @@ -297,56 +293,6 @@ void LLPanelGroupGeneral::onClickInfo(void *userdata) } -// static -void LLPanelGroupGeneral::onClickJoin(void *userdata) -{ - LLPanelGroupGeneral *self = (LLPanelGroupGeneral *)userdata; - - if ( !self ) return; - - lldebugs << "joining group: " << self->mGroupID << llendl; - - LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(self->mGroupID); - - if (gdatap) - { - S32 cost = gdatap->mMembershipFee; - LLSD args; - args["COST"] = llformat("%d", cost); - LLSD payload; - payload["group_id"] = self->mGroupID; - - if (can_afford_transaction(cost)) - { - LLNotifications::instance().add("JoinGroupCanAfford", args, payload, LLPanelGroupGeneral::joinDlgCB); - } - else - { - LLNotifications::instance().add("JoinGroupCannotAfford", args, payload); - } - } - else - { - llwarns << "LLGroupMgr::getInstance()->getGroupData(" << self->mGroupID - << ") was NULL" << llendl; - } -} - -// static -bool LLPanelGroupGeneral::joinDlgCB(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotification::getSelectedOption(notification, response); - - if (option == 1) - { - // user clicked cancel - return false; - } - - LLGroupMgr::getInstance()->sendGroupMemberJoin(notification["payload"]["group_id"].asUUID()); - return false; -} - // static void LLPanelGroupGeneral::openProfile(void* data) { @@ -883,6 +829,8 @@ void LLPanelGroupGeneral::reset() mComboActiveTitle->setVisible(false); mInsignia->setImageAssetID(LLUUID::null); + + mInsignia->setEnabled(true); { std::string empty_str = ""; diff --git a/indra/newview/llpanelgroupgeneral.h b/indra/newview/llpanelgroupgeneral.h index b828480a12..7e90e43cf9 100644 --- a/indra/newview/llpanelgroupgeneral.h +++ b/indra/newview/llpanelgroupgeneral.h @@ -79,7 +79,6 @@ private: static void onCommitUserOnly(LLUICtrl* ctrl, void* data); static void onCommitTitle(LLUICtrl* ctrl, void* data); static void onCommitEnrollment(LLUICtrl* ctrl, void* data); - static void onClickJoin(void* userdata); static void onClickInfo(void* userdata); static void onReceiveNotices(LLUICtrl* ctrl, void* data); static void openProfile(void* data); diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index 51cdc5af93..a7590ac1dd 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -82,6 +82,9 @@ void LLPanelIMControlPanel::onShareButtonClicked() void LLPanelIMControlPanel::setID(const LLUUID& avatar_id) { + // Disable "Add friend" button for friends. + childSetEnabled("add_friend_btn", !LLAvatarActions::isFriend(avatar_id)); + getChild("avatar_icon")->setValue(avatar_id); } diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 309a97a9f2..6a41b6feb9 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -42,15 +42,18 @@ #include "llpanelpeople.h" // newview +#include "llaccordionctrltab.h" #include "llagent.h" #include "llavataractions.h" #include "llavatarlist.h" +#include "llavatarlistitem.h" #include "llcallingcard.h" // for LLAvatarTracker #include "llfloateravatarpicker.h" //#include "llfloaterminiinspector.h" #include "llfriendcard.h" #include "llgroupactions.h" #include "llgrouplist.h" +#include "llpanelpeoplemenus.h" #include "llrecentpeople.h" #include "llviewercontrol.h" // for gSavedSettings #include "llviewermenu.h" // for gMenuHolder @@ -68,6 +71,27 @@ static const std::string FRIENDS_TAB_NAME = "friends_panel"; static const std::string GROUP_TAB_NAME = "groups_panel"; static const std::string RECENT_TAB_NAME = "recent_panel"; +/** Comparator for comparing avatar items by last interaction date */ +class LLAvatarItemRecentComparator : public LLAvatarItemComparator +{ +public: + LLAvatarItemRecentComparator() {}; + virtual ~LLAvatarItemRecentComparator() {}; + +protected: + virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const + { + LLRecentPeople& people = LLRecentPeople::instance(); + const LLDate& date1 = people.getDate(avatar_item1->getAvatarId()); + const LLDate& date2 = people.getDate(avatar_item2->getAvatarId()); + + //older comes first + return date1 > date2; + } +}; + +static const LLAvatarItemRecentComparator RECENT_COMPARATOR; + static LLRegisterPanelClassWrapper t_people("panel_people"); //============================================================================= @@ -299,7 +323,7 @@ private: /** * Updates the recent people list (those the agent has recently interacted with). */ -class LLRecentListUpdater : public LLAvatarListUpdater +class LLRecentListUpdater : public LLAvatarListUpdater, public boost::signals2::trackable { LOG_CLASS(LLRecentListUpdater); @@ -398,21 +422,25 @@ LLPanelPeople::~LLPanelPeople() LLView::deleteViewByHandle(mGroupPlusMenuHandle); LLView::deleteViewByHandle(mNearbyViewSortMenuHandle); LLView::deleteViewByHandle(mFriendsViewSortMenuHandle); + LLView::deleteViewByHandle(mGroupsViewSortMenuHandle); LLView::deleteViewByHandle(mRecentViewSortMenuHandle); } -void onAvatarListTmpDoubleClicked(LLAvatarListTmp* list) -{ - LLUUID clicked_id = list->getCurrentID(); - if (clicked_id.isNull()) +void LLPanelPeople::onFriendsAccordionExpandedCollapsed(const LLSD& param, LLAvatarList* avatar_list) +{ + if(!avatar_list) + { + llerrs << "Bad parameter" << llendl; return; + } -#if 0 // SJB: Useful for testing, but not currently functional or to spec - LLAvatarActions::showProfile(clicked_id); -#else // spec says open IM window - LLAvatarActions::startIM(clicked_id); -#endif + bool expanded = param.asBoolean(); + + if(!expanded) + { + avatar_list->resetSelection(); + } } BOOL LLPanelPeople::postBuild() @@ -427,11 +455,22 @@ BOOL LLPanelPeople::postBuild() mOnlineFriendList = getChild(FRIENDS_TAB_NAME)->getChild("avatars_online"); mAllFriendList = getChild(FRIENDS_TAB_NAME)->getChild("avatars_all"); + mOnlineFriendList->setNoItemsCommentText(getString("no_friends_online")); + mAllFriendList->setNoItemsCommentText(getString("no_friends")); mNearbyList = getChild(NEARBY_TAB_NAME)->getChild("avatar_list"); + mNearbyList->setNoItemsCommentText(getString("no_one_near")); + + mRecentList = getChild(RECENT_TAB_NAME)->getChild("avatar_list"); + mRecentList->setNoItemsCommentText(getString("no_people")); - mRecentList = getChild(RECENT_TAB_NAME)->getChild("avatar_list"); mGroupList = getChild("group_list"); + mGroupList->setNoItemsCommentText(getString("no_groups")); + + mNearbyList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu); + mRecentList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu); + + mRecentList->setComparator(&RECENT_COMPARATOR); LLPanel* groups_panel = getChild(GROUP_TAB_NAME); groups_panel->childSetAction("activate_btn", boost::bind(&LLPanelPeople::onActivateButtonClicked, this)); @@ -445,15 +484,24 @@ BOOL LLPanelPeople::postBuild() mOnlineFriendList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mOnlineFriendList)); mAllFriendList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mAllFriendList)); mNearbyList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mNearbyList)); - mRecentList->setDoubleClickCallback(boost::bind(onAvatarListTmpDoubleClicked, mRecentList)); + mRecentList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onAvatarListDoubleClicked, this, mRecentList)); + mOnlineFriendList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mOnlineFriendList)); mAllFriendList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mAllFriendList)); mNearbyList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mNearbyList)); - mRecentList->setCommitCallback(boost::bind(&LLPanelPeople::updateButtons, this)); + mRecentList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mRecentList)); mGroupList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onGroupInfoButtonClicked, this)); mGroupList->setCommitCallback(boost::bind(&LLPanelPeople::updateButtons, this)); + LLAccordionCtrlTab* accordion_tab = getChild("tab_all"); + accordion_tab->setDropDownStateChangedCallback( + boost::bind(&LLPanelPeople::onFriendsAccordionExpandedCollapsed, this, _2, mAllFriendList)); + + accordion_tab = getChild("tab_online"); + accordion_tab->setDropDownStateChangedCallback( + boost::bind(&LLPanelPeople::onFriendsAccordionExpandedCollapsed, this, _2, mOnlineFriendList)); + buttonSetAction("view_profile_btn", boost::bind(&LLPanelPeople::onViewProfileButtonClicked, this)); buttonSetAction("add_friend_btn", boost::bind(&LLPanelPeople::onAddFriendButtonClicked, this)); buttonSetAction("group_info_btn", boost::bind(&LLPanelPeople::onGroupInfoButtonClicked, this)); @@ -466,6 +514,7 @@ BOOL LLPanelPeople::postBuild() getChild(NEARBY_TAB_NAME)->childSetAction("nearby_view_sort_btn",boost::bind(&LLPanelPeople::onNearbyViewSortButtonClicked, this)); getChild(RECENT_TAB_NAME)->childSetAction("recent_viewsort_btn",boost::bind(&LLPanelPeople::onRecentViewSortButtonClicked, this)); getChild(FRIENDS_TAB_NAME)->childSetAction("friends_viewsort_btn",boost::bind(&LLPanelPeople::onFriendsViewSortButtonClicked, this)); + getChild(GROUP_TAB_NAME)->childSetAction("groups_viewsort_btn",boost::bind(&LLPanelPeople::onGroupsViewSortButtonClicked, this)); // Must go after setting commit callback and initializing all pointers to children. mTabContainer->selectTabByName(FRIENDS_TAB_NAME); @@ -476,6 +525,7 @@ BOOL LLPanelPeople::postBuild() registrar.add("People.Group.Plus.Action", boost::bind(&LLPanelPeople::onGroupPlusMenuItemClicked, this, _2)); registrar.add("People.Friends.ViewSort.Action", boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemClicked, this, _2)); registrar.add("People.Nearby.ViewSort.Action", boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemClicked, this, _2)); + registrar.add("People.Groups.ViewSort.Action", boost::bind(&LLPanelPeople::onGroupsViewSortMenuItemClicked, this, _2)); registrar.add("People.Recent.ViewSort.Action", boost::bind(&LLPanelPeople::onRecentViewSortMenuItemClicked, this, _2)); LLMenuGL* plus_menu = LLUICtrlFactory::getInstance()->createFromFile("menu_group_plus.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); @@ -489,6 +539,10 @@ BOOL LLPanelPeople::postBuild() if(friend_view_sort) mFriendsViewSortMenuHandle = friend_view_sort->getHandle(); + LLMenuGL* group_view_sort = LLUICtrlFactory::getInstance()->createFromFile("menu_people_groups_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + if(group_view_sort) + mGroupsViewSortMenuHandle = group_view_sort->getHandle(); + LLMenuGL* recent_view_sort = LLUICtrlFactory::getInstance()->createFromFile("menu_people_recent_view_sort.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); if(recent_view_sort) mRecentViewSortMenuHandle = recent_view_sort->getHandle(); @@ -497,13 +551,28 @@ BOOL LLPanelPeople::postBuild() // Perform initial update. mFriendListUpdater->forceUpdate(); - mRecentListUpdater->forceUpdate(); + mNearbyListUpdater->forceUpdate(); mGroupListUpdater->forceUpdate(); mRecentListUpdater->forceUpdate(); + // call this method in case some list is empty and buttons can be in inconsistent state + updateButtons(); + return TRUE; } +void LLPanelPeople::applyFilterToTab(const std::string& tab_name) +{ + if (tab_name == FRIENDS_TAB_NAME) // this tab has two lists + filterFriendList(); + else if (tab_name == NEARBY_TAB_NAME) + filterNearbyList(); + else if (tab_name == RECENT_TAB_NAME) + filterRecentList(); + else if (tab_name == GROUP_TAB_NAME) + updateGroupList(); +} + bool LLPanelPeople::updateFriendList(U32 changed_mask) { // Refresh names. @@ -570,10 +639,7 @@ bool LLPanelPeople::updateGroupList() return true; // there's no point in further updates bool have_names = mGroupList->update(mFilterSubString); - - if (mGroupList->isEmpty()) - mGroupList->setCommentText(getString("no_groups")); - + updateButtons(); return have_names; } @@ -587,22 +653,15 @@ bool LLPanelPeople::filterFriendList() mOnlineFriendList->update(mOnlineFriendVec, mFilterSubString) & mAllFriendList->update(mAllFriendVec, mFilterSubString); - if (mOnlineFriendVec.size() == 0) - mOnlineFriendList->setCommentText(getString("no_friends_online")); - - if (mAllFriendVec.size() == 0) - mAllFriendList->setCommentText(getString("no_friends")); + updateButtons(); return have_names; } bool LLPanelPeople::filterNearbyList() { bool have_names = mNearbyList->update(mNearbyVec, mFilterSubString); - - if (mNearbyVec.size() == 0) - mNearbyList->setCommentText(getString("no_one_near")); - + updateButtons(); return have_names; } @@ -612,9 +671,11 @@ bool LLPanelPeople::filterRecentList() return true; if (mRecentVec.size() > 0) - return mRecentList->update(mRecentVec, mFilterSubString); - - mRecentList->setCommentText(getString("no_people")); + { + bool updated = mRecentList->update(mRecentVec, mFilterSubString); + updateButtons(); + return updated; + } return true; } @@ -664,12 +725,12 @@ void LLPanelPeople::updateButtons() if (group_tab_active) { - bool item_selected = mGroupList->getFirstSelected() != NULL; + bool item_selected = mGroupList->getSelectedItem() != NULL; bool cur_group_active = true; if (item_selected) { - selected_id = mGroupList->getCurrentID(); + selected_id = mGroupList->getSelectedUUID(); cur_group_active = (gAgent.getGroupID() == selected_id); } @@ -714,20 +775,20 @@ LLUUID LLPanelPeople::getCurrentItemID() const { LLUUID cur_online_friend; - if ((cur_online_friend = mOnlineFriendList->getCurrentID()).notNull()) + if ((cur_online_friend = mOnlineFriendList->getSelectedUUID()).notNull()) return cur_online_friend; - return mAllFriendList->getCurrentID(); + return mAllFriendList->getSelectedUUID(); } if (cur_tab == NEARBY_TAB_NAME) - return mNearbyList->getCurrentID(); + return mNearbyList->getSelectedUUID(); if (cur_tab == RECENT_TAB_NAME) - return mRecentList->getCurrentID(); + return mRecentList->getSelectedUUID(); if (cur_tab == GROUP_TAB_NAME) - return mGroupList->getCurrentID(); + return mGroupList->getSelectedUUID(); llassert(0 && "unknown tab selected"); return LLUUID::null; @@ -785,20 +846,16 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string) LLStringUtil::toUpper(mFilterSubString); LLStringUtil::trimHead(mFilterSubString); - // Apply new filter to all tabs. - filterNearbyList(); - filterFriendList(); - filterRecentList(); - updateGroupList(); - - updateButtons(); + // Apply new filter to current tab. + applyFilterToTab(getActiveTabName()); } void LLPanelPeople::onTabSelected(const LLSD& param) { std::string tab_name = getChild(param.asString())->getName(); mNearbyListUpdater->setActive(tab_name == NEARBY_TAB_NAME); - updateButtons(); + applyFilterToTab(tab_name); + // No need to call updateButtons() because applyFilterToTab() does that. if (GROUP_TAB_NAME == tab_name) mFilterEditor->setLabel(getString("groups_filter_label")); @@ -808,7 +865,7 @@ void LLPanelPeople::onTabSelected(const LLSD& param) void LLPanelPeople::onAvatarListDoubleClicked(LLAvatarList* list) { - LLUUID clicked_id = list->getCurrentID(); + LLUUID clicked_id = list->getSelectedUUID(); if (clicked_id.isNull()) return; @@ -826,9 +883,9 @@ void LLPanelPeople::onAvatarListCommitted(LLAvatarList* list) if (getActiveTabName() == FRIENDS_TAB_NAME) { if (list == mOnlineFriendList) - mAllFriendList->deselectAllItems(TRUE); + mAllFriendList->resetSelection(true); else if (list == mAllFriendList) - mOnlineFriendList->deselectAllItems(TRUE); + mOnlineFriendList->resetSelection(true); else llassert(0 && "commit on unknown friends list"); } @@ -890,7 +947,7 @@ void LLPanelPeople::onImButtonClicked() void LLPanelPeople::onActivateButtonClicked() { - LLGroupActions::activate(mGroupList->getCurrentID()); + LLGroupActions::activate(mGroupList->getSelectedUUID()); } // static @@ -909,7 +966,7 @@ bool LLPanelPeople::onFriendListUpdate(U32 changed_mask) // Update online status in the Recent tab. // *TODO: isn't it too much to update the whole list? - updateRecentList(); +// updateRecentList(); // mantipov: seems online status should be supported by LLAvatarListItem itself. return have_names; } @@ -957,6 +1014,17 @@ void LLPanelPeople::onFriendsViewSortMenuItemClicked(const LLSD& userdata) { } } + +void LLPanelPeople::onGroupsViewSortMenuItemClicked(const LLSD& userdata) +{ + std::string chosen_item = userdata.asString(); + + if (chosen_item == "show_icons") + { + mGroupList->toggleIcons(); + } +} + void LLPanelPeople::onNearbyViewSortMenuItemClicked(const LLSD& userdata) { std::string chosen_item = userdata.asString(); @@ -966,6 +1034,7 @@ void LLPanelPeople::onNearbyViewSortMenuItemClicked(const LLSD& userdata) } else if (chosen_item == "sort_name") { + mNearbyList->sortByName(); } else if (chosen_item == "view_icons") { @@ -978,11 +1047,14 @@ void LLPanelPeople::onRecentViewSortMenuItemClicked(const LLSD& userdata) { std::string chosen_item = userdata.asString(); - if (chosen_item == "sort_most") + if (chosen_item == "sort_recent") { - } + mRecentList->setComparator(&RECENT_COMPARATOR); + mRecentList->sort(); + } else if (chosen_item == "sort_name") { + mRecentList->sortByName(); } else if (chosen_item == "view_icons") { @@ -1008,6 +1080,7 @@ void LLPanelPeople::onMoreButtonClicked() { // *TODO: not implemented yet } + void LLPanelPeople::onFriendsViewSortButtonClicked() { LLMenuGL* menu = (LLMenuGL*)mFriendsViewSortMenuHandle.get(); @@ -1015,6 +1088,15 @@ void LLPanelPeople::onFriendsViewSortButtonClicked() return; showGroupMenu(menu); } + +void LLPanelPeople::onGroupsViewSortButtonClicked() +{ + LLMenuGL* menu = (LLMenuGL*)mGroupsViewSortMenuHandle.get(); + if (!menu) + return; + showGroupMenu(menu); +} + void LLPanelPeople::onRecentViewSortButtonClicked() { LLMenuGL* menu = (LLMenuGL*)mRecentViewSortMenuHandle.get(); @@ -1022,6 +1104,7 @@ void LLPanelPeople::onRecentViewSortButtonClicked() return; showGroupMenu(menu); } + void LLPanelPeople::onNearbyViewSortButtonClicked() { LLMenuGL* menu = (LLMenuGL*)mNearbyViewSortMenuHandle.get(); @@ -1041,4 +1124,3 @@ void LLPanelPeople::onOpen(const LLSD& key) else reSelectedCurrentTab(); } - diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index c0c2f70614..8cd3cc7feb 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -40,7 +40,6 @@ class LLFilterEditor; class LLTabContainer; class LLAvatarList; -class LLAvatarListTmp; class LLGroupList; class LLPanelPeople : public LLPanel @@ -67,6 +66,7 @@ private: bool filterFriendList(); bool filterNearbyList(); bool filterRecentList(); + void applyFilterToTab(const std::string& tab_name); void updateButtons(); const std::string& getActiveTabName() const; LLUUID getCurrentItemID() const; @@ -97,6 +97,7 @@ private: void onRecentViewSortButtonClicked(); void onNearbyViewSortButtonClicked(); void onFriendsViewSortButtonClicked(); + void onGroupsViewSortButtonClicked(); void onAvatarListDoubleClicked(LLAvatarList* list); void onAvatarListCommitted(LLAvatarList* list); void onGroupPlusButtonClicked(); @@ -105,6 +106,7 @@ private: void onFriendsViewSortMenuItemClicked(const LLSD& userdata); void onNearbyViewSortMenuItemClicked(const LLSD& userdata); + void onGroupsViewSortMenuItemClicked(const LLSD& userdata); void onRecentViewSortMenuItemClicked(const LLSD& userdata); // misc callbacks @@ -114,17 +116,20 @@ private: const std::vector& ids, void*); + void onFriendsAccordionExpandedCollapsed(const LLSD& param, LLAvatarList* avatar_list); + LLFilterEditor* mFilterEditor; LLTabContainer* mTabContainer; LLAvatarList* mOnlineFriendList; LLAvatarList* mAllFriendList; LLAvatarList* mNearbyList; - LLAvatarListTmp* mRecentList; + LLAvatarList* mRecentList; LLGroupList* mGroupList; LLHandle mGroupPlusMenuHandle; LLHandle mNearbyViewSortMenuHandle; LLHandle mFriendsViewSortMenuHandle; + LLHandle mGroupsViewSortMenuHandle; LLHandle mRecentViewSortMenuHandle; Updater* mFriendListUpdater; diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp new file mode 100644 index 0000000000..0e88058bb1 --- /dev/null +++ b/indra/newview/llpanelpeoplemenus.cpp @@ -0,0 +1,148 @@ +/** + * @file llpanelpeoplemenus.h + * @brief Menus used by the side tray "People" panel + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +// libs +#include "llmenugl.h" +#include "lluictrlfactory.h" + +#include "llpanelpeoplemenus.h" + +// newview +#include "llagentdata.h" // for gAgentID +#include "llavataractions.h" +#include "llviewermenu.h" // for gMenuHolder + +namespace LLPanelPeopleMenus +{ + +NearbyMenu gNearbyMenu; + +//== ContextMenu ============================================================== + +ContextMenu::ContextMenu() +: mMenu(NULL) +{ +} + +void ContextMenu::show(LLView* spawning_view, const LLUUID& id, S32 x, S32 y) +{ + if (mMenu) + { + //preventing parent (menu holder) from deleting already "dead" context menus on exit + LLView* parent = mMenu->getParent(); + if (parent) + { + parent->removeChild(mMenu); + mMenu->setParent(NULL); + } + delete mMenu; + } + + mID = id; + mMenu = createMenu(); + mMenu->show(x, y); + LLMenuGL::showPopup(spawning_view, mMenu, x, y); +} + +//== NearbyMenu =============================================================== + +LLContextMenu* NearbyMenu::createMenu() +{ + // set up the callbacks for all of the avatar menu items + // (N.B. callbacks don't take const refs as mID is local scope) + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar; + + registrar.add("Avatar.Profile", boost::bind(&LLAvatarActions::showProfile, mID)); + registrar.add("Avatar.AddFriend", boost::bind(&LLAvatarActions::requestFriendshipDialog, mID)); + registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startIM, mID)); + registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startIM, mID)); // *TODO: unimplemented + registrar.add("Avatar.OfferTeleport", boost::bind(&NearbyMenu::offerTeleport, this)); + registrar.add("Avatar.ShowOnMap", boost::bind(&LLAvatarActions::startIM, mID)); // *TODO: unimplemented + registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::startIM, mID)); // *TODO: unimplemented + registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, mID)); + registrar.add("Avatar.BlockUnblock", boost::bind(&LLAvatarActions::toggleBlock, mID)); + + enable_registrar.add("Avatar.EnableItem", boost::bind(&NearbyMenu::enableContextMenuItem, this, _2)); + enable_registrar.add("Avatar.CheckItem", boost::bind(&NearbyMenu::checkContextMenuItem, this, _2)); + + // create the context menu from the XUI + return LLUICtrlFactory::getInstance()->createFromFile( + "menu_people_nearby.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance()); +} + +bool NearbyMenu::enableContextMenuItem(const LLSD& userdata) +{ + std::string item = userdata.asString(); + + if (item == std::string("can_block")) + { + std::string firstname, lastname; + gCacheName->getName(mID, firstname, lastname); + bool is_linden = !LLStringUtil::compareStrings(lastname, "Linden"); + bool is_self = mID == gAgentID; + return !is_self && !is_linden; + } + else if (item == std::string("can_add")) + { + return !LLAvatarActions::isFriend(mID); + } + else if (item == std::string("can_delete")) + { + return LLAvatarActions::isFriend(mID); + } + + return false; +} + +bool NearbyMenu::checkContextMenuItem(const LLSD& userdata) +{ + std::string item = userdata.asString(); + + if (item == std::string("is_blocked")) + { + return LLAvatarActions::isBlocked(mID); + } + + return false; +} + +void NearbyMenu::offerTeleport() +{ + // boost::bind cannot recognize overloaded method LLAvatarActions::offerTeleport(), + // so we have to use a wrapper. + LLAvatarActions::offerTeleport(mID); +} + +} // namespace LLPanelPeopleMenus diff --git a/indra/newview/llpanelpeoplemenus.h b/indra/newview/llpanelpeoplemenus.h new file mode 100644 index 0000000000..0012ac38f8 --- /dev/null +++ b/indra/newview/llpanelpeoplemenus.h @@ -0,0 +1,82 @@ +/** + * @file llpanelpeoplemenus.h + * @brief Menus used by the side tray "People" panel + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPANELPEOPLEMENUS_H +#define LL_LLPANELPEOPLEMENUS_H + +#include "llavatarlistitem.h" + +namespace LLPanelPeopleMenus +{ + +/** + * Base context menu. + */ +class ContextMenu : public LLAvatarListItem::ContextMenu +{ +public: + ContextMenu(); + virtual ~ContextMenu() {} + + /** + * Show the menu at specified coordinates. + * + * @param id either avatar or group id + */ + /*virtual*/ void show(LLView* spawning_view, const LLUUID& id, S32 x, S32 y); + +protected: + + virtual LLContextMenu* createMenu() = 0; + + LLUUID mID; + LLContextMenu* mMenu; +}; + +/** + * Menu used in the nearby people list. + */ +class NearbyMenu : public ContextMenu +{ +public: + /*virtual*/ LLContextMenu* createMenu(); +private: + bool enableContextMenuItem(const LLSD& userdata); + bool checkContextMenuItem(const LLSD& userdata); + void offerTeleport(); +}; + +extern NearbyMenu gNearbyMenu; + +} // namespace LLPanelPeopleMenus + +#endif // LL_LLPANELPEOPLEMENUS_H diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp index 9ae58d1cb6..42185d28e5 100644 --- a/indra/newview/llpanelpick.cpp +++ b/indra/newview/llpanelpick.cpp @@ -64,6 +64,7 @@ #define LABEL_PICK = "Pick" #define LABEL_CHANGES = "Changes" +std::string SET_LOCATION_NOTICE("(will update after save)"); LLPanelPick::LLPanelPick(BOOL edit_mode/* = FALSE */) : LLPanel(), LLAvatarPropertiesObserver(), LLRemoteParcelInfoObserver(), @@ -71,7 +72,8 @@ LLPanelPick::LLPanelPick(BOOL edit_mode/* = FALSE */) mSnapshotCtrl(NULL), mPickId(LLUUID::null), mCreatorId(LLUUID::null), - mDataReceived(FALSE) + mDataReceived(FALSE), + mIsPickNew(false) { if (edit_mode) { @@ -171,7 +173,7 @@ void LLPanelPick::init(LLPickData *pick_data) setPickName(pick_data->name); setPickDesc(pick_data->desc); - setPickLocation(pick_data->location_text); + mSnapshotCtrl->setImageAssetID(pick_data->snapshot_id); //*HACK see reset() where the texture control was set to FALSE @@ -180,27 +182,45 @@ void LLPanelPick::init(LLPickData *pick_data) mPosGlobal = pick_data->pos_global; mSimName = pick_data->sim_name; mParcelId = pick_data->parcel_id; + + setPickLocation(createLocationText(pick_data->user_name, pick_data->original_name, + pick_data->sim_name, pick_data->pos_global)); } -// Fill in some reasonable defaults for a new pick. -void LLPanelPick::createNewPick() +void LLPanelPick::prepareNewPick(const LLVector3d pos_global, + const std::string& name, + const std::string& desc, + const LLUUID& snapshot_id, + const LLUUID& parcel_id) { mPickId.generate(); mCreatorId = gAgent.getID(); - mPosGlobal = gAgent.getPositionGlobal(); + mPosGlobal = pos_global; + setPickName(name); + setPickDesc(desc); + mSnapshotCtrl->setImageAssetID(snapshot_id); + mParcelId = parcel_id; + + setPickLocation(createLocationText(std::string(""), SET_LOCATION_NOTICE, name, pos_global)); + childSetLabelArg(XML_BTN_SAVE, SAVE_BTN_LABEL, std::string("Pick")); + + mIsPickNew = true; +} + +// Fill in some reasonable defaults for a new pick. +void LLPanelPick::prepareNewPick() +{ // Try to fill in the current parcel LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); if (parcel) { - setPickName(parcel->getName()); - setPickDesc(parcel->getDesc()); - mSnapshotCtrl->setImageAssetID(parcel->getSnapshotID()); + prepareNewPick(gAgent.getPositionGlobal(), + parcel->getName(), + parcel->getDesc(), + parcel->getSnapshotID(), + parcel->getID()); } - - sendUpdate(); - - childSetLabelArg(XML_BTN_SAVE, SAVE_BTN_LABEL, std::string("Pick")); } /*virtual*/ void LLPanelPick::processProperties(void* data, EAvatarProcessorType type) @@ -235,6 +255,15 @@ void LLPanelPick::setEditMode( BOOL edit_mode ) deleteAllChildren(); + // *WORKAROUND: for EXT-931. Children are created for both XML_PANEL_EDIT_PICK & XML_PANEL_PICK_INFO files + // The reason is in LLPanel::initPanelXML called from the LLUICtrlFactory::buildPanel(). + // It creates children from the xml file stored while previous initializing in the "mXMLFilename" member + // and then in creates children from the parameters passed from the LLUICtrlFactory::buildPanel(). + // Xml filename is stored after LLPanel::initPanelXML is called (added with export-from-ll/viewer-2-0, r1594 into LLUICtrlFactory::buildPanel & LLUICtrlFactory::buildFloater) + // In case panel creates children from the different xml files they appear from both files. + // So, let clear xml filename related to this instance. + setXMLFilename(""); + if (edit_mode) { LLUICtrlFactory::getInstance()->buildPanel(this, XML_PANEL_EDIT_PICK); @@ -258,6 +287,40 @@ void LLPanelPick::setEditMode( BOOL edit_mode ) updateButtons(); } +////////////////////////////////////////////////////////////////////////// +// PROTECTED AREA +////////////////////////////////////////////////////////////////////////// + +//static +std::string LLPanelPick::createLocationText(const std::string& owner_name, const std::string& original_name, + const std::string& sim_name, const LLVector3d& pos_global) +{ + std::string location_text; + location_text.append(owner_name); + if (!original_name.empty()) + { + if (!location_text.empty()) location_text.append(", "); + location_text.append(original_name); + + } + if (!sim_name.empty()) + { + if (!location_text.empty()) location_text.append(", "); + location_text.append(sim_name); + } + + if (!location_text.empty()) location_text.append(" "); + + if (!pos_global.isNull()) + { + S32 region_x = llround((F32)pos_global.mdV[VX]) % REGION_WIDTH_UNITS; + S32 region_y = llround((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS; + S32 region_z = llround((F32)pos_global.mdV[VZ]); + location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z)); + } + return location_text; +} + void LLPanelPick::setPickName(std::string name) { if (mEditMode) @@ -288,7 +351,7 @@ void LLPanelPick::setPickDesc(std::string desc) mDesc = desc; } -void LLPanelPick::setPickLocation(std::string location) +void LLPanelPick::setPickLocation(const std::string& location) { childSetWrappedText(XML_LOCATION, location); @@ -375,6 +438,12 @@ void LLPanelPick::onClickCancel() { if (!mEditMode) return; + if (mIsPickNew) + { + mBackCb(this, LLSD()); + return; + } + LLUUID pick_id = mPickId; LLUUID creator_id = mCreatorId; reset(); @@ -385,29 +454,34 @@ void LLPanelPick::onClickCancel() void LLPanelPick::onClickSet() { if (!mEditMode) return; - if (!mDataReceived) return; + if (!mIsPickNew && !mDataReceived) return; // Save location for later. mPosGlobal = gAgent.getPositionGlobal(); - S32 region_x = llround((F32)mPosGlobal.mdV[VX]) % REGION_WIDTH_UNITS; - S32 region_y = llround((F32)mPosGlobal.mdV[VY]) % REGION_WIDTH_UNITS; - S32 region_z = llround((F32)mPosGlobal.mdV[VZ]); - - std::string location_text = "(will update after save), "; - location_text.append(mSimName); - location_text.append(llformat(" (%d, %d, %d)", region_x, region_y, region_z)); - - setPickLocation(location_text); + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + if (parcel) + { + mParcelId = parcel->getID(); + mSimName = parcel->getName(); + } + setPickLocation(createLocationText(std::string(""), SET_LOCATION_NOTICE, mSimName, mPosGlobal)); } // static void LLPanelPick::onClickSave() { if (!mEditMode) return; - if (!mDataReceived) return; + if (!mIsPickNew && !mDataReceived) return; sendUpdate(); + + if (mIsPickNew) + { + mBackCb(this, LLSD()); + return; + } + setEditMode(FALSE); } diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h index 2cd4706dfe..7ce58b59af 100644 --- a/indra/newview/llpanelpick.h +++ b/indra/newview/llpanelpick.h @@ -56,9 +56,14 @@ public: /*virtual*/ BOOL postBuild(); - // Create a new pick, including creating an id, giving a sane - // initial position, etc. - void createNewPick(); + // Prepares a new pick, including creating an id, giving a sane + // initial position, etc (saved on clicking Save Pick button - onClickSave callback). + void prepareNewPick(); + void prepareNewPick(const LLVector3d pos_global, + const std::string& name, + const std::string& desc, + const LLUUID& snapshot_id, + const LLUUID& parcel_id); //initializes the panel with data of the pick with id = pick_id //owned by the avatar with id = creator_id @@ -87,9 +92,16 @@ public: protected: + /** + * "Location text" is actually the owner name, the original + * name that owner gave the parcel, and the location. + */ + static std::string createLocationText(const std::string& owner_name, const std::string& original_name, + const std::string& sim_name, const LLVector3d& pos_global); + void setPickName(std::string name); void setPickDesc(std::string desc); - void setPickLocation(std::string location); + void setPickLocation(const std::string& location); std::string getPickName(); std::string getPickDesc(); @@ -120,6 +132,7 @@ protected: BOOL mEditMode; LLTextureCtrl* mSnapshotCtrl; BOOL mDataReceived; + bool mIsPickNew; LLUUID mPickId; LLUUID mCreatorId; diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index d374d24316..93317e613f 100644 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -34,6 +34,7 @@ #include "llagent.h" #include "llavatarconstants.h" +#include "llflatlistview.h" #include "lltexturectrl.h" #include "llviewergenericmessage.h" // send_generic_message #include "llmenugl.h" @@ -45,8 +46,6 @@ #include "llpanelavatar.h" #include "llpanelprofile.h" #include "llpanelpick.h" -#include "llscrollcontainer.h" -#include "lllistctrl.h" static const std::string XML_BTN_NEW = "new_btn"; static const std::string XML_BTN_DELETE = "trash_btn"; @@ -148,7 +147,7 @@ LLPickItem* LLPanelPicks::getSelectedPickItem() BOOL LLPanelPicks::postBuild() { - mPicksList = getChild("picks_list"); + mPicksList = getChild("picks_list"); childSetAction(XML_BTN_DELETE, boost::bind(&LLPanelPicks::onClickDelete, this)); @@ -199,6 +198,11 @@ void LLPanelPicks::onOpen(const LLSD& key) mPopupMenu->setItemVisible("pick_separator", TRUE); } + if(getAvatarId() != key.asUUID()) + { + mPicksList->goToTop(); + } + LLPanelProfileTab::onOpen(key); } @@ -314,7 +318,7 @@ void LLPanelPicks::onClickNew() { buildPickPanel(); mPickPanel->setEditMode(TRUE); - mPickPanel->createNewPick(); + mPickPanel->prepareNewPick(); getProfilePanel()->togglePanel(mPickPanel); } @@ -386,7 +390,6 @@ void LLPickItem::init(LLPickData* pick_data) setPickDesc(pick_data->desc); setSnapshotId(pick_data->snapshot_id); mPosGlobal = pick_data->pos_global; - mLocation = pick_data->location_text; LLTextureCtrl* picture = getChild("picture"); picture->setImageAssetID(pick_data->snapshot_id); @@ -434,11 +437,6 @@ const LLVector3d& LLPickItem::getPosGlobal() return mPosGlobal; } -const std::string& LLPickItem::getLocation() -{ - return mLocation; -} - const std::string LLPickItem::getDescription() { return childGetValue("picture_descr").asString(); diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h index 97e8e607c8..27a21305b3 100644 --- a/indra/newview/llpanelpicks.h +++ b/indra/newview/llpanelpicks.h @@ -48,7 +48,7 @@ class LLPanelPick; class LLAgent; class LLMenuGL; class LLPickItem; -class LLListCtrl; +class LLFlatListView; class LLPanelPicks : public LLPanelProfileTab @@ -107,7 +107,7 @@ private: LLMenuGL* mPopupMenu; LLPanelProfile* mProfilePanel; LLPanelPick* mPickPanel; - LLListCtrl* mPicksList; + LLFlatListView* mPicksList; }; class LLPickItem : public LLPanel, public LLAvatarPropertiesObserver @@ -142,8 +142,6 @@ public: const LLVector3d& getPosGlobal(); - const std::string& getLocation(); - const std::string getDescription(); /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); @@ -167,7 +165,6 @@ protected: bool mNeedData; std::string mPickName; - std::string mLocation; }; #endif // LL_LLPANELPICKS_H diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp index 7a19b8877e..eb269fabe3 100644 --- a/indra/newview/llpanelplaceinfo.cpp +++ b/indra/newview/llpanelplaceinfo.cpp @@ -44,6 +44,7 @@ #include "llqueryflags.h" #include "llbutton.h" +#include "lliconctrl.h" #include "lllineeditor.h" #include "llscrollcontainer.h" #include "lltextbox.h" @@ -55,6 +56,7 @@ #include "llfloaterworldmap.h" #include "llinventorymodel.h" #include "lllandmarkactions.h" +#include "llpanelpick.h" #include "lltexturectrl.h" #include "llviewerinventory.h" #include "llviewerparcelmgr.h" @@ -68,6 +70,7 @@ LLPanelPlaceInfo::LLPanelPlaceInfo() : LLPanel(), mParcelID(), mRequestedID(), + mPosRegion(), mLandmarkID(), mMinHeight(0), mScrollingPanel(NULL), @@ -88,6 +91,8 @@ BOOL LLPanelPlaceInfo::postBuild() mTitle = getChild("panel_title"); mCurrentTitle = mTitle->getText(); + mForSaleIcon = getChild("icon_for_sale"); + // Since this is only used in the directory browser, always // disable the snapshot control. Otherwise clicking on it will // open a texture picker. @@ -251,6 +256,8 @@ void LLPanelPlaceInfo::resetLocation() mParcelID.setNull(); mRequestedID.setNull(); mLandmarkID.setNull(); + mPosRegion.clearVec(); + mForSaleIcon->setVisible(FALSE); std::string not_available = getString("not_available"); mMaturityRatingText->setValue(not_available); mParcelOwner->setValue(not_available); @@ -449,12 +456,27 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data) //update for_sale banner, here we should use DFQ_FOR_SALE instead of PF_FOR_SALE //because we deal with remote parcel response format - bool isForSale = (parcel_data.flags & DFQ_FOR_SALE)? TRUE : FALSE; - getChild("icon_for_sale")->setVisible(isForSale); + bool isForSale = (parcel_data.flags & DFQ_FOR_SALE) && + mInfoType == AGENT ? TRUE : FALSE; + mForSaleIcon->setVisible(isForSale); + + S32 region_x; + S32 region_y; + S32 region_z; - S32 region_x = llround(parcel_data.global_x) % REGION_WIDTH_UNITS; - S32 region_y = llround(parcel_data.global_y) % REGION_WIDTH_UNITS; - S32 region_z = llround(parcel_data.global_z); + // If the region position is zero, grab position from the global + if(mPosRegion.isExactlyZero()) + { + region_x = llround(parcel_data.global_x) % REGION_WIDTH_UNITS; + region_y = llround(parcel_data.global_y) % REGION_WIDTH_UNITS; + region_z = llround(parcel_data.global_z); + } + else + { + region_x = llround(mPosRegion.mV[VX]); + region_y = llround(mPosRegion.mV[VY]); + region_z = llround(mPosRegion.mV[VZ]); + } std::string name = getString("not_available"); if (!parcel_data.sim_name.empty()) @@ -487,15 +509,15 @@ void LLPanelPlaceInfo::displayParcelInfo(const LLUUID& region_id, if (!region) return; + mPosRegion.setVec((F32)fmod(pos_global.mdV[VX], (F64)REGION_WIDTH_METERS), + (F32)fmod(pos_global.mdV[VY], (F64)REGION_WIDTH_METERS), + (F32)pos_global.mdV[VZ]); + LLSD body; std::string url = region->getCapability("RemoteParcelRequest"); if (!url.empty()) { - F32 region_x = (F32)fmod(pos_global.mdV[VX], (F64)REGION_WIDTH_METERS); - F32 region_y = (F32)fmod(pos_global.mdV[VY], (F64)REGION_WIDTH_METERS); - LLVector3 pos_region(region_x, region_y, (F32)pos_global.mdV[VZ]); - - body["location"] = ll_sd_from_vector3(pos_region); + body["location"] = ll_sd_from_vector3(mPosRegion); if (!region_id.isNull()) { body["region_id"] = region_id; @@ -536,20 +558,22 @@ void LLPanelPlaceInfo::displaySelectedParcelInfo(LLParcel* parcel, { case SIM_ACCESS_MATURE: parcel_data.flags = 0x1; + break; case SIM_ACCESS_ADULT: parcel_data.flags = 0x2; + break; default: parcel_data.flags = 0; } parcel_data.desc = parcel->getDesc(); parcel_data.name = parcel->getName(); - parcel_data.sim_name = gAgent.getRegion()->getName(); + parcel_data.sim_name = region->getName(); parcel_data.snapshot_id = parcel->getSnapshotID(); - parcel_data.global_x = pos_global.mdV[0]; - parcel_data.global_y = pos_global.mdV[1]; - parcel_data.global_z = pos_global.mdV[2]; + parcel_data.global_x = pos_global.mdV[VX]; + parcel_data.global_y = pos_global.mdV[VY]; + parcel_data.global_z = pos_global.mdV[VZ]; std::string on = getString("on"); std::string off = getString("off"); @@ -853,30 +877,19 @@ void LLPanelPlaceInfo::createLandmark(const LLUUID& folder_id) folder_id.notNull() ? folder_id : gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK)); } -void LLPanelPlaceInfo::createPick(const LLVector3d& global_pos) +void LLPanelPlaceInfo::createPick(const LLVector3d& pos_global, LLPanelPick* pick_panel) { - LLPickData pick_data; - - pick_data.agent_id = gAgent.getID(); - pick_data.session_id = gAgent.getSessionID(); - pick_data.pick_id = LLUUID::generateNewID(); - pick_data.creator_id = gAgentID; - - //legacy var needs to be deleted - pick_data.top_pick = FALSE; - pick_data.parcel_id = mParcelID; - pick_data.name = mParcelName->getText(); - if (pick_data.name.empty()) + std::string name = mParcelName->getText(); + if (name.empty()) { - pick_data.name = mRegionName->getText(); + name = mRegionName->getText(); } - pick_data.desc = mDescEditor->getText(); - pick_data.snapshot_id = mSnapshotCtrl->getImageAssetID(); - pick_data.pos_global = global_pos; - pick_data.sort_order = 0; - pick_data.enabled = TRUE; - LLAvatarPropertiesProcessor::instance().sendPickInfoUpdate(&pick_data); + pick_panel->prepareNewPick(pos_global, + name, + mDescEditor->getText(), + mSnapshotCtrl->getImageAssetID(), + mParcelID); } // virtual diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h index 32ae4334aa..23a845bc20 100644 --- a/indra/newview/llpanelplaceinfo.h +++ b/indra/newview/llpanelplaceinfo.h @@ -38,15 +38,15 @@ #include "v3dmath.h" #include "lluuid.h" -#include "lliconctrl.h" - #include "llpanelmedia.h" #include "llremoteparcelrequest.h" class LLButton; class LLInventoryItem; class LLLineEditor; +class LLPanelPick; class LLParcel; +class LLIconCtrl; class LLTextBox; class LLTextEditor; class LLTextureCtrl; @@ -88,7 +88,7 @@ public: // Create a pick for the location specified // by global_pos. - void createPick(const LLVector3d& global_pos); + void createPick(const LLVector3d& pos_global, LLPanelPick* pick_panel); BOOL isMediaPanelVisible(); void toggleMediaPanel(BOOL visible); @@ -133,11 +133,13 @@ private: LLUUID mParcelID; LLUUID mRequestedID; LLUUID mLandmarkID; + LLVector3 mPosRegion; std::string mCurrentTitle; S32 mMinHeight; INFO_TYPE mInfoType; LLTextBox* mTitle; + LLIconCtrl* mForSaleIcon; LLTextureCtrl* mSnapshotCtrl; LLTextBox* mRegionName; LLTextBox* mParcelName; diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 11ddc3dd9a..4e070df7eb 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -48,14 +48,15 @@ #include "lluictrlfactory.h" #include "llagent.h" +#include "llavatarpropertiesprocessor.h" #include "llfloaterworldmap.h" #include "llinventorymodel.h" #include "lllandmarkactions.h" #include "lllandmarklist.h" #include "llpanelplaceinfo.h" #include "llpanellandmarks.h" +#include "llpanelpick.h" #include "llpanelteleporthistory.h" -#include "llsidetray.h" #include "llteleporthistorystorage.h" #include "lltoggleablemenu.h" #include "llviewerinventory.h" @@ -72,10 +73,12 @@ static const std::string REMOTE_PLACE_INFO_TYPE = "remote_place"; static const std::string TELEPORT_HISTORY_INFO_TYPE = "teleport_history"; // Helper functions +static bool is_agent_in_selected_parcel(LLParcel* parcel); static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right); static std::string getFullFolderName(const LLViewerInventoryCategory* cat); static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats); static void onSLURLBuilt(std::string& slurl); +static void setAllChildrenVisible(LLView* view, BOOL visible); //Observer classes class LLPlacesParcelObserver : public LLParcelObserver @@ -118,6 +121,7 @@ LLPanelPlaces::LLPanelPlaces() mActivePanel(NULL), mFilterEditor(NULL), mPlaceInfo(NULL), + mPickPanel(NULL), mItem(NULL), mPlaceMenu(NULL), mLandmarkMenu(NULL), @@ -332,6 +336,7 @@ void LLPanelPlaces::onFilterEdit(const std::string& search_string) LLStringUtil::toUpper(mFilterSubString); LLStringUtil::trimHead(mFilterSubString); + if (mActivePanel) mActivePanel->onSearchEdit(mFilterSubString); } } @@ -380,6 +385,7 @@ void LLPanelPlaces::onTeleportButtonClicked() } else { + if (mActivePanel) mActivePanel->onTeleport(); } } @@ -425,6 +431,7 @@ void LLPanelPlaces::onShowOnMapButtonClicked() } else { + if (mActivePanel) mActivePanel->onShowOnMap(); } } @@ -496,10 +503,23 @@ void LLPanelPlaces::onOverflowMenuItemClicked(const LLSD& param) { if (!mPlaceInfo) return; - - mPlaceInfo->createPick(mPosGlobal); - onBackButtonClicked(); + if (mPickPanel == NULL) + { + mPickPanel = new LLPanelPick(); + addChild(mPickPanel); + + mPickPanel->setExitCallback(boost::bind(&LLPanelPlaces::togglePickPanel, this, FALSE)); + } + + togglePickPanel(TRUE); + + LLRect rect = getRect(); + mPickPanel->reshape(rect.getWidth(), rect.getHeight()); + mPickPanel->setRect(rect); + mPickPanel->setEditMode(TRUE); + + mPlaceInfo->createPick(mPosGlobal, mPickPanel); } } @@ -508,6 +528,12 @@ void LLPanelPlaces::onCreateLandmarkButtonClicked(const LLUUID& folder_id) if (!mPlaceInfo) return; + // To prevent creating duplicate landmarks + // disable landmark creating buttons until + // the information on existing landmarks is reloaded. + mCreateLandmarkBtn->setEnabled(FALSE); + mFolderMenuBtn->setEnabled(FALSE); + mPlaceInfo->createLandmark(folder_id); } @@ -544,6 +570,14 @@ void LLPanelPlaces::toggleMediaPanel() onOpen(LLSD().insert("type", AGENT_INFO_TYPE)); } +void LLPanelPlaces::togglePickPanel(BOOL visible) +{ + setAllChildrenVisible(this, !visible); + + if (mPickPanel) + mPickPanel->setVisible(visible); +} + void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible) { if (!mPlaceInfo) @@ -568,16 +602,16 @@ void LLPanelPlaces::changedParcelSelection() if (!mPlaceInfo) return; - mParcel = LLViewerParcelMgr::getInstance()->getFloatingParcelSelection(); + LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance(); + mParcel = parcel_mgr->getFloatingParcelSelection(); LLParcel* parcel = mParcel->getParcel(); - LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion(); + LLViewerRegion* region = parcel_mgr->getSelectionRegion(); if (!region || !parcel) return; // If agent is inside the selected parcel show agent's region, // otherwise show region of agent's selection point. - if (region == gAgent.getRegion() && - parcel->getLocalID() == LLViewerParcelMgr::getInstance()->getAgentParcel()->getLocalID()) + if (is_agent_in_selected_parcel(parcel)) { mPosGlobal = gAgent.getPositionGlobal(); } @@ -629,6 +663,10 @@ void LLPanelPlaces::changedInventory(U32 mask) mActivePanel = dynamic_cast(mTabContainer->getCurrentPanel()); + // Filter applied to show all items. + if (mActivePanel) + mActivePanel->onSearchEdit(mFilterSubString); + // we don't need to monitor inventory changes anymore, // so remove the observer gInventory.removeObserver(mInventoryObserver); @@ -658,7 +696,7 @@ void LLPanelPlaces::updateVerbs() bool is_agent_place_info_visible = mPlaceInfoType == AGENT_INFO_TYPE; bool is_create_landmark_visible = mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE; bool is_media_panel_visible = mPlaceInfo->isMediaPanelVisible(); - + mTeleportBtn->setVisible(!is_create_landmark_visible); mShareBtn->setVisible(!is_create_landmark_visible); mCreateLandmarkBtn->setVisible(is_create_landmark_visible); @@ -679,10 +717,11 @@ void LLPanelPlaces::updateVerbs() else if (is_create_landmark_visible) { // Enable "Create Landmark" only if there is no landmark - // for the current parcel. - bool no_landmark = !LLLandmarkActions::landmarkAlreadyExists(); - mCreateLandmarkBtn->setEnabled(no_landmark); - mFolderMenuBtn->setEnabled(no_landmark); + // for the current parcel and agent is inside it. + bool enable = !LLLandmarkActions::landmarkAlreadyExists() && + is_agent_in_selected_parcel(mParcel->getParcel()); + mCreateLandmarkBtn->setEnabled(enable); + mFolderMenuBtn->setEnabled(enable); } else if (mPlaceInfoType == LANDMARK_INFO_TYPE || mPlaceInfoType == REMOTE_PLACE_INFO_TYPE) { @@ -693,6 +732,7 @@ void LLPanelPlaces::updateVerbs() } else { + if (mActivePanel) mActivePanel->updateVerbs(); } } @@ -822,6 +862,18 @@ void LLPanelPlaces::showLandmarkFoldersMenu() LLMenuGL::showPopup(this, menu, btn_rect.mRight, btn_rect.mTop); } +static bool is_agent_in_selected_parcel(LLParcel* parcel) +{ + LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance(); + + LLViewerRegion* region = parcel_mgr->getSelectionRegion(); + if (!region || !parcel) + return false; + + return region == gAgent.getRegion() && + parcel->getLocalID() == parcel_mgr->getAgentParcel()->getLocalID(); +} + static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right) { return left.second < right.second; @@ -895,3 +947,16 @@ static void onSLURLBuilt(std::string& slurl) LLNotifications::instance().add("CopySLURL", args); } + +static void setAllChildrenVisible(LLView* view, BOOL visible) +{ + const LLView::child_list_t* children = view->getChildList(); + for (LLView::child_list_const_iter_t child_it = children->begin(); child_it != children->end(); ++child_it) + { + LLView* child = *child_it; + if (child->getParent() == view) + { + child->setVisible(visible); + } + } +} diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h index 54bc2b9003..f208e91237 100644 --- a/indra/newview/llpanelplaces.h +++ b/indra/newview/llpanelplaces.h @@ -37,6 +37,7 @@ class LLInventoryItem; class LLFilterEditor; class LLLandmark; +class LLPanelPick; class LLPanelPlaceInfo; class LLPanelPlacesTab; class LLParcelSelection; @@ -77,6 +78,7 @@ private: void onBackButtonClicked(); void toggleMediaPanel(); + void togglePickPanel(BOOL visible); void togglePlaceInfoPanel(BOOL visible); void onAgentParcelChange(); @@ -88,6 +90,7 @@ private: LLPanelPlacesTab* mActivePanel; LLTabContainer* mTabContainer; LLPanelPlaceInfo* mPlaceInfo; + LLPanelPick* mPickPanel; LLToggleableMenu* mPlaceMenu; LLToggleableMenu* mLandmarkMenu; diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index ce01568e99..be28129451 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -104,10 +104,6 @@ void LLPanelProfile::onOpen(const LLSD& key) { getTabCtrl()->getCurrentPanel()->onOpen(getAvatarId()); } - - // Update the avatar name. - gCacheName->get(getAvatarId(), FALSE, - boost::bind(&LLPanelProfile::onAvatarNameCached, this, _1, _2, _3, _4)); } //*TODO redo panel toggling @@ -171,8 +167,3 @@ void LLPanelProfile::setAllChildrenVisible(BOOL visible) } } -void LLPanelProfile::onAvatarNameCached(const LLUUID& id, const std::string& first_name, const std::string& last_name, BOOL is_group) -{ - llassert(getAvatarId() == id); - getChild("user_name", FALSE)->setValue(first_name + " " + last_name); -} diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h index 0864ec1bc3..bb893f257a 100644 --- a/indra/newview/llpanelprofile.h +++ b/indra/newview/llpanelprofile.h @@ -72,13 +72,6 @@ protected: profile_tabs_t& getTabContainer() { return mTabContainer; } private: - // LLCacheName will call this function when avatar name is loaded from server. - // This is required to display names that have not been cached yet. - void onAvatarNameCached( - const LLUUID& id, - const std::string& first_name, - const std::string& last_name, - BOOL is_group); LLTabContainer* mTabCtrl; profile_tabs_t mTabContainer; diff --git a/indra/newview/llpanelprofileview.cpp b/indra/newview/llpanelprofileview.cpp index 0762bbeb87..f1db2416e4 100644 --- a/indra/newview/llpanelprofileview.cpp +++ b/indra/newview/llpanelprofileview.cpp @@ -70,6 +70,10 @@ void LLPanelProfileView::onOpen(const LLSD& key) setAvatarId(id); } + // Update the avatar name. + gCacheName->get(getAvatarId(), FALSE, + boost::bind(&LLPanelProfileView::onAvatarNameCached, this, _1, _2, _3, _4)); + // status should only show if viewer has permission to view online/offline. EXT-453 mStatusText->setVisible(isGrantedToSeeOnlineStatus()); updateOnlineStatus(); @@ -133,4 +137,21 @@ void LLPanelProfileView::updateOnlineStatus() mStatusText->setValue(status); } +void LLPanelProfileView::onAvatarNameCached(const LLUUID& id, const std::string& first_name, const std::string& last_name, BOOL is_group) +{ + llassert(getAvatarId() == id); + getChild("user_name", FALSE)->setValue(first_name + " " + last_name); +} + +void LLPanelProfileView::togglePanel(LLPanel* panel) +{ + LLPanelProfile::togglePanel(panel); + if(FALSE == panel->getVisible()) + { + // LLPanelProfile::togglePanel shows/hides all children, + // we don't want to display online status for non friends, so re-hide it here + mStatusText->setVisible(isGrantedToSeeOnlineStatus()); + } +} + // EOF diff --git a/indra/newview/llpanelprofileview.h b/indra/newview/llpanelprofileview.h index 533ab94cc3..07a6c3a9a0 100644 --- a/indra/newview/llpanelprofileview.h +++ b/indra/newview/llpanelprofileview.h @@ -60,6 +60,8 @@ public: /*virtual*/ BOOL postBuild(); + /*virtual*/ void togglePanel(LLPanel* panel); + protected: void onBackBtnClick(); @@ -67,6 +69,14 @@ protected: void updateOnlineStatus(); private: + // LLCacheName will call this function when avatar name is loaded from server. + // This is required to display names that have not been cached yet. + void onAvatarNameCached( + const LLUUID& id, + const std::string& first_name, + const std::string& last_name, + BOOL is_group); + LLTextBox* mStatusText; }; diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index 1fd7928bfc..f6672d9c8b 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -40,6 +40,83 @@ #include "llteleporthistorystorage.h" #include "llaccordionctrl.h" #include "llaccordionctrltab.h" +#include "llflatlistview.h" +#include "lltextbox.h" + +class LLTeleportHistoryFlatItem : public LLPanel +{ +public: + LLTeleportHistoryFlatItem(S32 index, const std::string ®ion_name); + virtual ~LLTeleportHistoryFlatItem() {}; + + virtual BOOL postBuild(); + + S32 getIndex() { return mIndex; } + + /*virtual*/ void setValue(const LLSD& value); + + void onMouseEnter(S32 x, S32 y, MASK mask); + void onMouseLeave(S32 x, S32 y, MASK mask); +private: + void onInfoBtnClick(); + + LLButton* mInfoBtn; + + S32 mIndex; + std::string mRegionName; +}; + +LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, const std::string ®ion_name) +: LLPanel(), + mIndex(index), + mRegionName(region_name) +{ + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_teleport_history_item.xml"); +} + +//virtual +BOOL LLTeleportHistoryFlatItem::postBuild() +{ + LLTextBox *region = getChild("region"); + region->setValue(mRegionName); + + mInfoBtn = getChild("info_btn"); + mInfoBtn->setClickedCallback(boost::bind(&LLTeleportHistoryFlatItem::onInfoBtnClick, this)); + + return true; +} + +void LLTeleportHistoryFlatItem::setValue(const LLSD& value) +{ + if (!value.isMap()) return;; + if (!value.has("selected")) return; + childSetVisible("selected_icon", value["selected"]); +} + +void LLTeleportHistoryFlatItem::onMouseEnter(S32 x, S32 y, MASK mask) +{ + childSetVisible("hovered_icon", true); + mInfoBtn->setVisible(true); + + LLPanel::onMouseEnter(x, y, mask); +} + +void LLTeleportHistoryFlatItem::onMouseLeave(S32 x, S32 y, MASK mask) +{ + childSetVisible("hovered_icon", false); + mInfoBtn->setVisible(false); + + LLPanel::onMouseLeave(x, y, mask); +} + +void LLTeleportHistoryFlatItem::onInfoBtnClick() +{ + LLSD params; + params["id"] = mIndex; + params["type"] = "teleport_history"; + + LLSideTray::getInstance()->showPanel("panel_places", params); +} // Not yet implemented; need to remove buildPanel() from constructor when we switch //static LLRegisterPanelClassWrapper t_teleport_history("panel_teleport_history"); @@ -48,7 +125,7 @@ LLTeleportHistoryPanel::LLTeleportHistoryPanel() : LLPanelPlacesTab(), mFilterSubString(LLStringUtil::null), mTeleportHistory(NULL), - mHistoryAccordeon(NULL), + mHistoryAccordion(NULL), mLastSelectedScrollList(NULL) { LLUICtrlFactory::getInstance()->buildPanel(this, "panel_teleport_history.xml"); @@ -66,26 +143,25 @@ BOOL LLTeleportHistoryPanel::postBuild() mTeleportHistory->setHistoryChangedCallback(boost::bind(&LLTeleportHistoryPanel::showTeleportHistory, this)); } - mHistoryAccordeon = getChild("history_accordion"); + mHistoryAccordion = getChild("history_accordion"); - if (mHistoryAccordeon) + if (mHistoryAccordion) { - for (child_list_const_iter_t iter = mHistoryAccordeon->beginChild(); iter != mHistoryAccordeon->endChild(); iter++) + for (child_list_const_iter_t iter = mHistoryAccordion->beginChild(); iter != mHistoryAccordion->endChild(); iter++) { if (dynamic_cast(*iter)) { LLAccordionCtrlTab* tab = (LLAccordionCtrlTab*)*iter; mItemContainers.put(tab); - LLScrollListCtrl* sl = getScrollListFromTab(tab); - if (sl) + LLFlatListView* fl = getFlatListViewFromTab(tab); + if (fl) { - sl->setDoubleClickCallback(onDoubleClickItem, this); - sl->setCommitOnSelectionChange(FALSE); - sl->setCommitCallback(boost::bind(&LLTeleportHistoryPanel::handleItemSelect, this, sl)); + fl->setCommitOnSelectionChange(true); + //fl->setDoubleClickCallback(onDoubleClickItem, this); + fl->setCommitCallback(boost::bind(&LLTeleportHistoryPanel::handleItemSelect, this, fl)); } - } } } @@ -109,13 +185,12 @@ void LLTeleportHistoryPanel::onShowOnMap() if (!mLastSelectedScrollList) return; - LLScrollListItem* itemp = mLastSelectedScrollList->getFirstSelected(); + LLTeleportHistoryFlatItem* itemp = dynamic_cast (mLastSelectedScrollList->getSelectedItem()); + if(!itemp) return; - S32 index = itemp->getColumn(LIST_INDEX)->getValue().asInteger(); - - LLVector3d global_pos = mTeleportHistory->getItems()[mTeleportHistory->getItems().size() - 1 - index].mGlobalPos; + LLVector3d global_pos = mTeleportHistory->getItems()[itemp->getIndex()].mGlobalPos; if (!global_pos.isExactlyZero()) { @@ -130,14 +205,12 @@ void LLTeleportHistoryPanel::onTeleport() if (!mLastSelectedScrollList) return; - LLScrollListItem* itemp = mLastSelectedScrollList->getFirstSelected(); + LLTeleportHistoryFlatItem* itemp = dynamic_cast (mLastSelectedScrollList->getSelectedItem()); if(!itemp) return; - S32 index = itemp->getColumn(LIST_INDEX)->getValue().asInteger(); - // teleport to existing item in history, so we don't add it again - mTeleportHistory->goToItem(mTeleportHistory->getItems().size() - 1 - index); + mTeleportHistory->goToItem(itemp->getIndex()); } /* @@ -177,15 +250,15 @@ void LLTeleportHistoryPanel::updateVerbs() return; } - LLScrollListItem* itemp = mLastSelectedScrollList->getFirstSelected(); + LLTeleportHistoryFlatItem* itemp = dynamic_cast (mLastSelectedScrollList->getSelectedItem()); - mTeleportBtn->setEnabled(NULL != itemp && 0 < itemp->getColumn(LIST_INDEX)->getValue().asInteger()); + mTeleportBtn->setEnabled(NULL != itemp && 0 < itemp->getIndex()); mShowOnMapBtn->setEnabled(NULL != itemp); } void LLTeleportHistoryPanel::showTeleportHistory() { - if (!mHistoryAccordeon) + if (!mHistoryAccordion) return; const LLTeleportHistoryStorage::slurl_list_t& hist_items = mTeleportHistory->getItems(); @@ -193,15 +266,17 @@ void LLTeleportHistoryPanel::showTeleportHistory() const U32 seconds_in_day = 24 * 60 * 60; LLDate curr_date = LLDate::now(); - curr_date.secondsSinceEpoch(curr_date.secondsSinceEpoch() + seconds_in_day); - S32 curr_tab = -1; S32 tabs_cnt = mItemContainers.size(); S32 curr_year = 0, curr_month = 0, curr_day = 0; + + curr_date.split(&curr_year, &curr_month, &curr_day); + curr_date.fromYMDHMS(curr_year, curr_month, curr_day); // Set hour, min, and sec to 0 + curr_date.secondsSinceEpoch(curr_date.secondsSinceEpoch() + seconds_in_day); - LLScrollListCtrl *curr_scroll_list = NULL; + LLFlatListView* curr_flat_view = NULL; - S32 index = 0; + S32 index = hist_items.size() - 1; for (LLTeleportHistoryStorage::slurl_list_t::const_reverse_iterator iter = hist_items.rbegin(); iter != hist_items.rend(); ++iter) @@ -219,71 +294,104 @@ void LLTeleportHistoryPanel::showTeleportHistory() { const LLDate &date = (*iter).mDate; - S32 year, month, day; - if (!date.split(&year, &month, &day)) - { - llwarns << "Failed to split date: " << date << llendl; - continue; - } - - if (day != curr_day || month != curr_month || year != curr_year) + if (date < curr_date) { LLAccordionCtrlTab* tab = NULL; - while (curr_tab < tabs_cnt - 1 && (day != curr_day || month != curr_month || year != curr_year)) + while (curr_tab < tabs_cnt - 1 && date < curr_date) { curr_tab++; tab = mItemContainers.get(mItemContainers.size() - 1 - curr_tab); tab->setVisible(false); - + + if (curr_tab <= tabs_cnt - 4) + { curr_date.secondsSinceEpoch(curr_date.secondsSinceEpoch() - seconds_in_day); + } + else if (curr_tab == tabs_cnt - 3) // 6 day and older, low boundary is 1 month + { + curr_date = LLDate::now(); curr_date.split(&curr_year, &curr_month, &curr_day); - } + curr_month--; + if (0 == curr_month) + { + curr_month = 12; + curr_year--; + } + curr_date.fromYMDHMS(curr_year, curr_month, curr_day); + } + else if (curr_tab == tabs_cnt - 2) // 1 month and older, low boundary is 6 months + { + curr_date = LLDate::now(); + curr_date.split(&curr_year, &curr_month, &curr_day); + if (curr_month > 6) + { + curr_month -= 6; + } + else + { + curr_month += 6; + curr_year--; + } + curr_date.fromYMDHMS(curr_year, curr_month, curr_day); + + } + else // 6 months and older + { + curr_date.secondsSinceEpoch(0); + } + } tab->setVisible(true); - curr_scroll_list = getScrollListFromTab(tab); - if (curr_scroll_list) + curr_flat_view = getFlatListViewFromTab(tab); + if (curr_flat_view) { - curr_scroll_list->deleteAllItems(); + curr_flat_view->clear(); } } } - LLSD row; - row["id"] = index; - - if (curr_scroll_list) - { - LLSD& icon_column = row["columns"][LIST_ICON]; - icon_column["column"] = "landmark_icon"; - icon_column["type"] = "icon"; - icon_column["value"] = "inv_item_landmark.tga"; - - LLSD& region_column = row["columns"][LIST_ITEM_TITLE]; - region_column["column"] = "region"; - region_column["type"] = "text"; - region_column["value"] = (*iter).mTitle; - - LLSD& index_column = row["columns"][LIST_INDEX]; - index_column["column"] = "index"; - index_column["type"] = "text"; - index_column["value"] = index; - - index++; - - curr_scroll_list->addElement(row); + if (curr_flat_view) + { + curr_flat_view->addItem(new LLTeleportHistoryFlatItem(index, (*iter).mTitle)); } + + index--; } - mHistoryAccordeon->arrange(); + // Hide empty tabs from current to bottom + for (curr_tab++; curr_tab < tabs_cnt; curr_tab++) + mItemContainers.get(mItemContainers.size() - 1 - curr_tab)->setVisible(false); + + mHistoryAccordion->arrange(); updateVerbs(); } -void LLTeleportHistoryPanel::handleItemSelect(LLScrollListCtrl* sl) +void LLTeleportHistoryPanel::handleItemSelect(LLFlatListView* selected) { - mLastSelectedScrollList = sl; + mLastSelectedScrollList = selected; + + S32 tabs_cnt = mItemContainers.size(); + + for (S32 n = 0; n < tabs_cnt; n++) + { + LLAccordionCtrlTab* tab = mItemContainers.get(n); + + if (!tab->getVisible()) + continue; + + LLFlatListView *flv = getFlatListViewFromTab(tab); + if (!flv) + continue; + + if (flv == selected) + continue; + + flv->resetSelection(true); + } + updateVerbs(); } @@ -303,15 +411,16 @@ void LLTeleportHistoryPanel::onDoubleClickItem(void* user_data) LLSideTray::getInstance()->showPanel("panel_places", key);*/ } -LLScrollListCtrl* LLTeleportHistoryPanel::getScrollListFromTab(LLAccordionCtrlTab *tab) +LLFlatListView* LLTeleportHistoryPanel::getFlatListViewFromTab(LLAccordionCtrlTab *tab) { for (child_list_const_iter_t iter = tab->beginChild(); iter != tab->endChild(); iter++) { - if (dynamic_cast(*iter)) + if (dynamic_cast(*iter)) { - return (LLScrollListCtrl*)*iter; // There should be one scroll list per tab. + return (LLFlatListView*)*iter; // There should be one scroll list per tab. } } return NULL; } + diff --git a/indra/newview/llpanelteleporthistory.h b/indra/newview/llpanelteleporthistory.h index a1c15d087b..66187e69c6 100644 --- a/indra/newview/llpanelteleporthistory.h +++ b/indra/newview/llpanelteleporthistory.h @@ -34,7 +34,6 @@ #define LL_LLPANELTELEPORTHISTORY_H #include "lluictrlfactory.h" -#include "llscrolllistctrl.h" #include "llpanelplacestab.h" #include "llteleporthistory.h" @@ -42,6 +41,7 @@ class LLTeleportHistoryStorage; class LLAccordionCtrl; class LLAccordionCtrlTab; +class LLFlatListView; class LLTeleportHistoryPanel : public LLPanelPlacesTab { @@ -60,19 +60,12 @@ private: static void onDoubleClickItem(void* user_data); void showTeleportHistory(); - void handleItemSelect(LLScrollListCtrl* ); - LLScrollListCtrl* getScrollListFromTab(LLAccordionCtrlTab *); - - enum TELEPORT_HISTORY_COLUMN_ORDER - { - LIST_ICON, - LIST_ITEM_TITLE, - LIST_INDEX - }; + void handleItemSelect(LLFlatListView* ); + LLFlatListView* getFlatListViewFromTab(LLAccordionCtrlTab *); LLTeleportHistoryStorage* mTeleportHistory; - LLAccordionCtrl* mHistoryAccordeon; - LLScrollListCtrl* mLastSelectedScrollList; + LLAccordionCtrl* mHistoryAccordion; + LLFlatListView* mLastSelectedScrollList; std::string mFilterSubString; typedef LLDynamicArray item_containers_t; diff --git a/indra/newview/llrecentpeople.cpp b/indra/newview/llrecentpeople.cpp index 04abe36878..b491c7e109 100644 --- a/indra/newview/llrecentpeople.cpp +++ b/indra/newview/llrecentpeople.cpp @@ -40,27 +40,38 @@ using namespace LLOldEvents; bool LLRecentPeople::add(const LLUUID& id) { - if (contains(id) || id == gAgent.getID()) + if (id == gAgent.getID()) return false; LLDate date_added = LLDate::now(); - mList.insert(std::make_pair(id, date_added)); + + //[] instead of insert to replace existing id->date with new date value + mPeople[id] = date_added; mChangedSignal(); return true; } bool LLRecentPeople::contains(const LLUUID& id) const { - return mList.find(id) != mList.end(); + return mPeople.find(id) != mPeople.end(); } void LLRecentPeople::get(std::vector& result) const { result.clear(); - for (recent_people_t::const_iterator pos = mList.begin(); pos != mList.end(); ++pos) + for (recent_people_t::const_iterator pos = mPeople.begin(); pos != mPeople.end(); ++pos) result.push_back((*pos).first); } +const LLDate& LLRecentPeople::getDate(const LLUUID& id) const +{ + recent_people_t::const_iterator it = mPeople.find(id); + if (it!= mPeople.end()) return (*it).second; + + static LLDate no_date = LLDate(); + return no_date; +} + // virtual bool LLRecentPeople::handleEvent(LLPointer event, const LLSD& userdata) { diff --git a/indra/newview/llrecentpeople.h b/indra/newview/llrecentpeople.h index c18116b4e5..e0f2faaec5 100644 --- a/indra/newview/llrecentpeople.h +++ b/indra/newview/llrecentpeople.h @@ -81,6 +81,8 @@ public: */ void get(std::vector& result) const; + const LLDate& getDate(const LLUUID& id) const; + /** * Set callback to be called when the list changed. * @@ -97,7 +99,7 @@ public: private: typedef std::map recent_people_t; - recent_people_t mList; + recent_people_t mPeople; signal_t mChangedSignal; }; diff --git a/indra/newview/llremoteparcelrequest.cpp b/indra/newview/llremoteparcelrequest.cpp index 1ac0175b83..95e3dd6d78 100644 --- a/indra/newview/llremoteparcelrequest.cpp +++ b/indra/newview/llremoteparcelrequest.cpp @@ -84,7 +84,7 @@ void LLRemoteParcelRequestResponder::error(U32 status, const std::string& reason void LLRemoteParcelInfoProcessor::addObserver(const LLUUID& parcel_id, LLRemoteParcelInfoObserver* observer) { - // Check if the observer is alredy in observsrs list for this UUID + // Check if the observer is already in observers list for this UUID observer_multimap_t::iterator it; it = mObservers.find(parcel_id); @@ -155,7 +155,6 @@ void LLRemoteParcelInfoProcessor::processParcelInfoReply(LLMessageSystem* msg, v for (; oi != end; ++oi) { oi->second->processParcelInfo(parcel_data); - LLRemoteParcelInfoProcessor::getInstance()->removeObserver(parcel_data.parcel_id, oi->second); } } diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 2157f1af74..082bba027f 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -39,9 +39,15 @@ #include "lltoastpanel.h" #include "llviewercontrol.h" +#include "llviewerwindow.h" #include "llfloaterreg.h" #include "lltrans.h" +#include "lldockablefloater.h" +#include "llimpanel.h" +#include "llsyswellwindow.h" +#include "llimfloater.h" + #include using namespace LLNotificationsUI; @@ -53,37 +59,52 @@ LLScreenChannel::LLScreenChannel(LLUUID& id): mOverflowToastPanel(NULL), mStartU mToastAlignment(NA_BOTTOM), mCanStoreToasts(true), mHiddenToastsNum(0), mOverflowToastHidden(false), mIsHovering(false), mControlHovering(false), - mShowToasts(false) + mShowToasts(true) { mID = id; - - setFollows(FOLLOWS_RIGHT | FOLLOWS_BOTTOM | FOLLOWS_TOP); - mOverflowFormatString = LLTrans::getString("OverflowInfoChannelString"); - + mWorldViewRectConnection = gViewerWindow->setOnWorldViewRectUpdated(boost::bind(&LLScreenChannel::updatePositionAndSize, this, _1, _2)); setMouseOpaque( false ); + setVisible(FALSE); } //-------------------------------------------------------------------------- void LLScreenChannel::init(S32 channel_left, S32 channel_right) { - S32 channel_top = getRootView()->getRect().getHeight() - gSavedSettings.getS32("NavBarMargin"); - S32 channel_bottom = getRootView()->getRect().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin"); + S32 channel_top = gViewerWindow->getWorldViewRect().getHeight(); + S32 channel_bottom = gViewerWindow->getWorldViewRect().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin"); setRect(LLRect(channel_left, channel_top, channel_right, channel_bottom)); - + setVisible(TRUE); } //-------------------------------------------------------------------------- LLScreenChannel::~LLScreenChannel() { + mWorldViewRectConnection.disconnect(); } //-------------------------------------------------------------------------- -void LLScreenChannel::reshape(S32 width, S32 height, BOOL called_from_parent) +void LLScreenChannel::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect) { - LLUICtrl::reshape(width, height, called_from_parent); - if(mToastAlignment != NA_CENTRE) - showToasts(); + S32 top_delta = old_world_rect.mTop - new_world_rect.mTop; + S32 right_delta = old_world_rect.mRight - new_world_rect.mRight; + + LLRect this_rect = getRect(); + + this_rect.mTop -= top_delta; + switch(mChannelAlignment) + { + case CA_LEFT : + break; + case CA_CENTRE : + this_rect.setCenterAndSize(new_world_rect.getWidth() / 2, new_world_rect.getHeight() / 2, this_rect.getWidth(), this_rect.getHeight()); + break; + case CA_RIGHT : + this_rect.mLeft -= right_delta; + this_rect.mRight -= right_delta; + } + setRect(this_rect); + redrawToasts(); } //-------------------------------------------------------------------------- @@ -91,12 +112,12 @@ void LLScreenChannel::addToast(LLToast::Params p) { bool store_toast = false, show_toast = false; - show_toast = mShowToasts || p.force_show; + show_toast = mWasStartUpToastShown && (mShowToasts || p.force_show); store_toast = !show_toast && p.can_be_stored && mCanStoreToasts; if(!show_toast && !store_toast) { - mOnRejectToast(p); + mRejectToastSignal(p.notif_id); return; } @@ -104,7 +125,8 @@ void LLScreenChannel::addToast(LLToast::Params p) mOverflowToastHidden = false; - new_toast_elem.toast->setOnFadeCallback(boost::bind(&LLScreenChannel::onToastFade, this, new_toast_elem.toast)); + new_toast_elem.toast->setOnFadeCallback(boost::bind(&LLScreenChannel::onToastFade, this, _1)); + new_toast_elem.toast->setOnToastDestroyedCallback(boost::bind(&LLScreenChannel::onToastDestroyed, this, _1)); if(mControlHovering) { new_toast_elem.toast->setOnToastHoverCallback(boost::bind(&LLScreenChannel::onToastHover, this, _1, _2)); @@ -113,7 +135,7 @@ void LLScreenChannel::addToast(LLToast::Params p) if(show_toast) { mToastList.push_back(new_toast_elem); - showToasts(); + redrawToasts(); } else // store_toast { @@ -122,16 +144,28 @@ void LLScreenChannel::addToast(LLToast::Params p) } } +//-------------------------------------------------------------------------- +void LLScreenChannel::onToastDestroyed(LLToast* toast) +{ + std::vector::iterator it = find(mToastList.begin(), mToastList.end(), static_cast(toast)); + + if(it != mToastList.end()) + { + mToastList.erase(it); + } +} + + //-------------------------------------------------------------------------- void LLScreenChannel::onToastFade(LLToast* toast) { std::vector::iterator it = find(mToastList.begin(), mToastList.end(), static_cast(toast)); - bool destroy_toast = !mCanStoreToasts || !toast->getCanBeStored(); - if(destroy_toast) + bool delete_toast = !mCanStoreToasts || !toast->getCanBeStored(); + if(delete_toast) { mToastList.erase(it); - toast->mOnToastDestroy(toast); + deleteToast(toast); } else { @@ -139,7 +173,22 @@ void LLScreenChannel::onToastFade(LLToast* toast) mToastList.erase(it); } - showToasts(); + redrawToasts(); +} + +//-------------------------------------------------------------------------- +void LLScreenChannel::deleteToast(LLToast* toast) +{ + // send signal to observers about destroying of a toast + toast->mOnDeleteToastSignal(toast); + + // update channel's Hovering state + // turning hovering off mannualy because onMouseLeave won't happen if a toast was closed using a keyboard + if(toast->hasFocus()) + setHovering(false); + + // close the toast + toast->closeFloater(); } //-------------------------------------------------------------------------- @@ -173,11 +222,11 @@ void LLScreenChannel::loadStoredToastsToChannel() } mStoredToastList.clear(); - showToasts(); + redrawToasts(); } //-------------------------------------------------------------------------- -void LLScreenChannel::loadStoredToastByIDToChannel(LLUUID id) +void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id) { std::vector::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), id); @@ -191,11 +240,11 @@ void LLScreenChannel::loadStoredToastByIDToChannel(LLUUID id) mToastList.push_back((*it)); mStoredToastList.erase(it); - showToasts(); + redrawToasts(); } //-------------------------------------------------------------------------- -void LLScreenChannel::removeStoredToastByID(LLUUID id) +void LLScreenChannel::removeStoredToastByNotificationID(LLUUID id) { // *TODO: may be remove this function std::vector::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), id); @@ -205,7 +254,7 @@ void LLScreenChannel::removeStoredToastByID(LLUUID id) LLToast* toast = (*it).toast; mStoredToastList.erase(it); - toast->discardNotification(); + mRejectToastSignal(toast->getNotificationID()); } //-------------------------------------------------------------------------- @@ -223,15 +272,15 @@ void LLScreenChannel::killToastByNotificationID(LLUUID id) // NOTE: if a notification is unresponded this function will be called twice for the same toast. // At first, the notification will be discarded, at second (it will be caused by discarding), // the toast will be destroyed. - if(toast->getIsNotificationUnResponded()) + if(toast->isNotificationValid()) { - toast->discardNotification(); + mRejectToastSignal(toast->getNotificationID()); } else { mToastList.erase(it); - toast->mOnToastDestroy(toast); - showToasts(); + deleteToast(toast); + redrawToasts(); } return; } @@ -243,8 +292,9 @@ void LLScreenChannel::killToastByNotificationID(LLUUID id) { LLToast* toast = (*it).toast; mStoredToastList.erase(it); - toast->discardNotification(); - toast->mOnToastDestroy(toast); + // send signal to a listener to let him perform some action on toast rejecting + mRejectToastSignal(toast->getNotificationID()); + deleteToast(toast); } } @@ -261,12 +311,12 @@ void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel) delete old_panel; toast->insertPanel(panel); toast->resetTimer(); - showToasts(); + redrawToasts(); } } //-------------------------------------------------------------------------- -void LLScreenChannel::showToasts() +void LLScreenChannel::redrawToasts() { if(mToastList.size() == 0 || mIsHovering) return; @@ -487,31 +537,55 @@ void LLScreenChannel::removeToastsFromChannel() hideToastsFromScreen(); for(std::vector::iterator it = mToastList.begin(); it != mToastList.end(); it++) { - // *TODO: ivestigate mOnToastDestroy callback - change name or/and place - (*it).toast->mOnToastDestroy((*it).toast); + deleteToast((*it).toast); } mToastList.clear(); } //-------------------------------------------------------------------------- -void LLScreenChannel::removeAndStoreAllVisibleToasts() +void LLScreenChannel::removeAndStoreAllStorableToasts() { if(mToastList.size() == 0) return; hideToastsFromScreen(); - for(std::vector::iterator it = mToastList.begin(); it != mToastList.end(); it++) + for(std::vector::iterator it = mToastList.begin(); it != mToastList.end();) { if((*it).toast->getCanBeStored()) { mStoredToastList.push_back(*it); mOnStoreToast((*it).toast->getPanel(), (*it).id); (*it).toast->stopTimer(); + it = mToastList.erase(it); } - (*it).toast->setVisible(FALSE); + else + { + ++it; } + } + redrawToasts(); +} - mToastList.clear(); +//-------------------------------------------------------------------------- +void LLScreenChannel::removeToastsBySessionID(LLUUID id) +{ + if(mToastList.size() == 0) + return; + + hideToastsFromScreen(); + for(std::vector::iterator it = mToastList.begin(); it != mToastList.end();) + { + if((*it).toast->getSessionID() == id) + { + deleteToast((*it).toast); + it = mToastList.erase(it); + } + else + { + ++it; + } + } + redrawToasts(); } //-------------------------------------------------------------------------- @@ -546,11 +620,30 @@ void LLScreenChannel::onToastHover(LLToast* toast, bool mouse_enter) } if(!mIsHovering) - showToasts(); + redrawToasts(); } //-------------------------------------------------------------------------- +void LLScreenChannel::updateShowToastsState() +{ + LLFloater* floater = LLDockableFloater::getInstanceHandle().get(); + if(!floater) + { + setShowToasts(true); + return; + } + if(dynamic_cast(floater) || dynamic_cast(floater)) + { + setShowToasts(!(floater->getVisible() && floater->isDocked())); + if (!getShowToasts()) + { + removeAndStoreAllStorableToasts(); + } + + } +} +//-------------------------------------------------------------------------- diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index 746580b574..f1ef6bd64d 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -48,6 +48,12 @@ typedef enum e_notification_toast_alignment NA_BOTTOM, } EToastAlignment; +typedef enum e_channel_alignment +{ + CA_LEFT, + CA_CENTRE, + CA_RIGHT, +} EChannelAlignment; /** * Screen channel manages toasts visibility and positioning on the screen. @@ -60,12 +66,14 @@ public: virtual ~LLScreenChannel(); // Channel's outfit-functions - // classic reshape - void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + // update channel's size and position in the World View + void updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect); // initialization of channel's shape and position void init(S32 channel_left, S32 channel_right); // set allignment of toasts inside a channel - void setToastAlignment(e_notification_toast_alignment align) {mToastAlignment = align;} + void setToastAlignment(EToastAlignment align) {mToastAlignment = align;} + // set allignment of channel inside a world view + void setChannelAlignment(EChannelAlignment align) {mChannelAlignment = align;} // set a template for a string in the OverflowToast void setOverflowFormatString ( std::string str) { mOverflowFormatString = str; } @@ -80,15 +88,17 @@ public: // removes all toasts from a channel void removeToastsFromChannel(); // show all toasts in a channel - void showToasts(); + void redrawToasts(); // void loadStoredToastsToChannel(); - // finds a toast among stored by its ID and throws it on a screen to a channel - void loadStoredToastByIDToChannel(LLUUID id); - // removes a toast from stored finding it by its ID - void removeStoredToastByID(LLUUID id); - // remove all toasts from screen and store them - void removeAndStoreAllVisibleToasts(); + // finds a toast among stored by its Notification ID and throws it on a screen to a channel + void loadStoredToastByNotificationIDToChannel(LLUUID id); + // removes a toast from stored finding it by its Notification ID + void removeStoredToastByNotificationID(LLUUID id); + // removes from channel all toasts that belongs to the certain IM session + void removeToastsBySessionID(LLUUID id); + // remove all storable toasts from screen and store them + void removeAndStoreAllStorableToasts(); // close the Overflow Toast void closeOverflowToastPanel(); // close the StartUp Toast @@ -113,6 +123,8 @@ public: void setShowToasts(bool show) { mShowToasts = show; } // determine whether channel shows toasts or not bool getShowToasts() { return mShowToasts; } + // let a channel update its ShowToast flag + void updateShowToastsState(); // Channel's other interface functions functions // get number of hidden notifications from a channel @@ -124,17 +136,17 @@ public: // get ID of a channel LLUUID getChannelID() { return mID; } - // Channel's callbacks - // callback for storing of faded toasts + // Channel's signals + // signal on storing of faded toasts event typedef boost::function store_tost_callback_t; typedef boost::signals2::signal store_tost_signal_t; store_tost_signal_t mOnStoreToast; boost::signals2::connection setOnStoreToastCallback(store_tost_callback_t cb) { return mOnStoreToast.connect(cb); } - // callback for discarding of a rejected toast - typedef boost::function reject_tost_callback_t; - typedef boost::signals2::signal reject_tost_signal_t; - reject_tost_signal_t mOnRejectToast; - boost::signals2::connection setOnRejectToastCallback(reject_tost_callback_t cb) { return mOnRejectToast.connect(cb); } + // signal on rejecting of a toast event + typedef boost::function reject_tost_callback_t; + typedef boost::signals2::signal reject_tost_signal_t; + reject_tost_signal_t mRejectToastSignal; + boost::signals2::connection setOnRejectToastCallback(reject_tost_callback_t cb) { return mRejectToastSignal.connect(cb); } private: struct ToastElem @@ -142,7 +154,7 @@ private: LLUUID id; LLToast* toast; - ToastElem(LLToast::Params p) : id(p.id) + ToastElem(LLToast::Params p) : id(p.notif_id) { toast = new LLToast(p); } @@ -167,11 +179,14 @@ private: // Channel's handlers void onToastHover(LLToast* toast, bool mouse_enter); void onToastFade(LLToast* toast); + void onToastDestroyed(LLToast* toast); void onOverflowToastHide(); void onStartUpToastHide(); // void storeToast(ToastElem& toast_elem); + // send signal to observers about destroying of a toast, update channel's Hovering state, close the toast + void deleteToast(LLToast* toast); // show-functions depending on allignment of toasts void showToastsBottom(); @@ -194,7 +209,8 @@ private: // controls whether a channel shows toasts or not bool mShowToasts; // - e_notification_toast_alignment mToastAlignment; + EToastAlignment mToastAlignment; + EChannelAlignment mChannelAlignment; // attributes for the Overflow Toast S32 mHiddenToastsNum; @@ -207,6 +223,9 @@ private: // channel's ID LLUUID mID; + // store a connection to prevent futher crash that is caused by sending a signal to a destroyed channel + boost::signals2::connection mWorldViewRectConnection; + std::vector mToastList; std::vector mStoredToastList; std::map mToastEventStack; diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index 40b8445dcf..d7df258750 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -237,9 +237,6 @@ BOOL LLStatusBar::handleRightMouseDown(S32 x, S32 y, MASK mask) BOOL LLStatusBar::postBuild() { - mCommitCallbackRegistrar.add("HideNavbarMenu.Action", boost::bind(&LLStatusBar::onHideNavbarContextMenuItemClicked, this, _2)); - mEnableCallbackRegistrar.add("HideNavbarMenu.EnableMenuItem", boost::bind(&LLStatusBar::onHideNavbarContextMenuItemEnabled, this, _2)); - mHideNavbarContextMenu = LLUICtrlFactory::getInstance()->createFromFile("menu_hide_navbar.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); gMenuHolder->addChild(mHideNavbarContextMenu); @@ -563,43 +560,6 @@ void LLStatusBar::setupDate() } } -bool LLStatusBar::onHideNavbarContextMenuItemEnabled(const LLSD& userdata) -{ - std::string item = userdata.asString(); - - if (item == "show_navbar_navigation_panel") - { - return gSavedSettings.getBOOL("ShowNavbarNavigationPanel"); - } - else if (item == "show_navbar_favorites_panel") - { - return gSavedSettings.getBOOL("ShowNavbarFavoritesPanel"); - } - - return FALSE; -} - -void LLStatusBar::onHideNavbarContextMenuItemClicked(const LLSD& userdata) -{ - std::string item = userdata.asString(); - - if (item == "show_navbar_navigation_panel") - { - BOOL state = !gSavedSettings.getBOOL("ShowNavbarNavigationPanel"); - - LLNavigationBar::getInstance()->showNavigationPanel(state); - gSavedSettings.setBOOL("ShowNavbarNavigationPanel", state); - } - else if (item == "show_navbar_favorites_panel") - { - BOOL state = !gSavedSettings.getBOOL("ShowNavbarFavoritesPanel"); - - LLNavigationBar::getInstance()->showFavoritesPanel(state); - gSavedSettings.setBOOL("ShowNavbarFavoritesPanel", state); - } -} - - void LLStatusBar::onMainMenuRightClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask) { handleRightMouseDown(x, y, mask); diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h index b77db2c525..81a69e9590 100644 --- a/indra/newview/llstatusbar.h +++ b/indra/newview/llstatusbar.h @@ -91,9 +91,6 @@ private: // simple method to setup the part that holds the date void setupDate(); - bool onHideNavbarContextMenuItemEnabled(const LLSD& userdata); - void onHideNavbarContextMenuItemClicked(const LLSD& userdata); - void onMainMenuRightClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask); static void onCommitSearch(LLUICtrl*, void* data); static void onClickSearch(void* data); diff --git a/indra/newview/llsyswellitem.cpp b/indra/newview/llsyswellitem.cpp index 7d9ebc7208..eef8435006 100644 --- a/indra/newview/llsyswellitem.cpp +++ b/indra/newview/llsyswellitem.cpp @@ -40,7 +40,7 @@ #include "lluicolortable.h" //--------------------------------------------------------------------------------- -LLSysWellItem::LLSysWellItem(const Params& p) : LLScrollingPanel(p), +LLSysWellItem::LLSysWellItem(const Params& p) : LLPanel(p), mTitle(NULL), mCloseBtn(NULL), mIcon(NULL) @@ -74,15 +74,6 @@ void LLSysWellItem::onClickCloseBtn() mOnItemClose(this); } -//--------------------------------------------------------------------------------- -void LLSysWellItem::updatePanel(BOOL allow_modify) -{ - S32 parent_width = getParent()->getRect().getWidth(); - S32 panel_height = getRect().getHeight(); - - reshape(parent_width, panel_height, TRUE); -} - //--------------------------------------------------------------------------------- BOOL LLSysWellItem::handleMouseDown(S32 x, S32 y, MASK mask) { diff --git a/indra/newview/llsyswellitem.h b/indra/newview/llsyswellitem.h index b0761f2790..b9b00e972a 100644 --- a/indra/newview/llsyswellitem.h +++ b/indra/newview/llsyswellitem.h @@ -33,14 +33,14 @@ #ifndef LL_LLSYSWELLITEM_H #define LL_LLSYSWELLITEM_H -#include "llscrollingpanellist.h" +#include "llpanel.h" #include "lltextbox.h" #include "llbutton.h" #include "lliconctrl.h" #include -class LLSysWellItem : public LLScrollingPanel +class LLSysWellItem : public LLPanel { public: struct Params : public LLInitParam::Block @@ -54,8 +54,6 @@ public: LLSysWellItem(const Params& p); virtual ~LLSysWellItem(); - void updatePanel(BOOL allow_modify); - // title void setTitle( std::string title ); diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index 98428bf0f7..c1eecf4c12 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -32,6 +32,8 @@ #include "llviewerprecompiledheaders.h" // must be first include +#include "llflatlistview.h" + #include "llsyswellwindow.h" #include "llbottomtray.h" @@ -39,29 +41,101 @@ #include "llviewerwindow.h" #include "llchiclet.h" +#include "lltoastpanel.h" +#include "llnotificationmanager.h" + + +// IM session ID can be the same as Avatar UUID. (See LLIMMgr::computeSessionID) +// Probably notification ID also can be the same as Avatar UUID. +// In case when session ID & notification ID are the same it will be impossible to add both +// appropriate Items into Flat List. +// Functions below are intended to wrap passed LLUUID into LLSD value with different "type". +// Use them anywhere you need to add, get, remove items via the list +inline +LLSD get_notification_value(const LLUUID& notification_id) +{ + return LLSD() + .insert("type", "notification") + .insert("uuid", notification_id); +} + +inline +LLSD get_session_value(const LLUUID& session_id) +{ + return LLSD() + .insert("type", "im_chiclet") + .insert("uuid", session_id); +} + + //--------------------------------------------------------------------------------- LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLDockableFloater(NULL, key), mChannel(NULL), - mScrollContainer(NULL), - mNotificationList(NULL) + mMessageList(NULL), + mSeparator(NULL) { LLIMMgr::getInstance()->addSessionObserver(this); LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLSysWellWindow::findIMChiclet, this, _1)); + + mTypedItemsCount[IT_NOTIFICATION] = 0; + mTypedItemsCount[IT_INSTANT_MESSAGE] = 0; } //--------------------------------------------------------------------------------- BOOL LLSysWellWindow::postBuild() { - mScrollContainer = getChild("notification_list_container"); - mTwinListPanel = getChild("twin_list_panel"); - mNotificationList = getChild("notification_list"); - mIMRowList = getChild("im_row_panel_list"); + mMessageList = getChild("notification_list"); + + // init connections to the list's update events + connectListUpdaterToSignal("notify"); + connectListUpdaterToSignal("groupnotify"); + + // get a corresponding channel + initChannel(); - mScrollContainer->setBorderVisible(FALSE); + LLPanel::Params params; + mSeparator = LLUICtrlFactory::create(params); + LLUICtrlFactory::instance().buildPanel(mSeparator, "panel_separator.xml"); + + LLRect rc = mSeparator->getRect(); + rc.setOriginAndSize(0, 0, mMessageList->getItemsRect().getWidth(), rc.getHeight()); + mSeparator->setRect(rc); + mSeparator->setFollows(FOLLOWS_LEFT | FOLLOWS_RIGHT | FOLLOWS_TOP); + mSeparator->setVisible(FALSE); + + mMessageList->addItem(mSeparator); return LLDockableFloater::postBuild(); } +//--------------------------------------------------------------------------------- +void LLSysWellWindow::connectListUpdaterToSignal(std::string notification_type) +{ + LLNotificationsUI::LLNotificationManager* manager = LLNotificationsUI::LLNotificationManager::getInstance(); + LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type); + if(n_handler) + { + n_handler->setNotificationIDCallback(boost::bind(&LLSysWellWindow::removeItemByID, this, _1)); + } + else + { + llwarns << "LLSysWellWindow::connectListUpdaterToSignal() - could not get a handler for '" << notification_type <<"' type of notifications" << llendl; + } +} + +//--------------------------------------------------------------------------------- +void LLSysWellWindow::onChicletClick() +{ + // 1 - remove StartUp toast and channel if present + if(!LLNotificationsUI::LLScreenChannel::getStartUpToastShown()) + { + LLNotificationsUI::LLChannelManager::getInstance()->onStartUpToastClose(); + } + + // 2 - toggle instance of SysWell's chiclet-window + toggleWindow(); +} + //--------------------------------------------------------------------------------- LLSysWellWindow::~LLSysWellWindow() { @@ -71,57 +145,56 @@ LLSysWellWindow::~LLSysWellWindow() //--------------------------------------------------------------------------------- void LLSysWellWindow::addItem(LLSysWellItem::Params p) { + LLSD value = get_notification_value(p.notification_id); // do not add clones - if( findItemByID(p.notification_id) >= 0 ) + if( mMessageList->getItemByValue(value)) return; LLSysWellItem* new_item = new LLSysWellItem(p); - mNotificationList->addPanel(dynamic_cast(new_item)); + if (mMessageList->addItem(new_item, value, ADD_TOP)) + { + handleItemAdded(IT_NOTIFICATION); + reshapeWindow(); new_item->setOnItemCloseCallback(boost::bind(&LLSysWellWindow::onItemClose, this, _1)); new_item->setOnItemClickCallback(boost::bind(&LLSysWellWindow::onItemClick, this, _1)); + } + else + { + llwarns << "Unable to add Notification into the list, notification ID: " << p.notification_id + << ", title: " << p.title + << llendl; + + new_item->die(); + } } //--------------------------------------------------------------------------------- void LLSysWellWindow::clear() { - // *TODO: fill later + mMessageList->clear(); } //--------------------------------------------------------------------------------- -S32 LLSysWellWindow::findItemByID(const LLUUID& id) +void LLSysWellWindow::removeItemByID(const LLUUID& id) { - const LLScrollingPanelList::panel_list_t list = mNotificationList->getPanelList(); - if(list.size() == 0) - return -1; - - LLScrollingPanelList::panel_list_t::const_iterator it; - S32 index = 0; - for(it = list.begin(); it != list.end(); ++it, ++index) + if(mMessageList->removeItemByValue(get_notification_value(id))) { - if( dynamic_cast(*it)->getID() == id ) - break; + handleItemRemoved(IT_NOTIFICATION); + reshapeWindow(); } - - if(it == list.end()) - return -1; else - return index; - -} - -//--------------------------------------------------------------------------------- -void LLSysWellWindow::removeItemByID(const LLUUID& id) -{ - S32 index = findItemByID(id); - - if(index >= 0) - mNotificationList->removePanel(index); - else - return; + { + llwarns << "Unable to remove notification from the list, ID: " << id + << llendl; + } - reshapeWindow(); + // hide chiclet window if there are no items left + if(isWindowEmpty()) + { + setVisible(FALSE); + } } //--------------------------------------------------------------------------------- @@ -129,7 +202,7 @@ void LLSysWellWindow::onItemClick(LLSysWellItem* item) { LLUUID id = item->getID(); if(mChannel) - mChannel->loadStoredToastByIDToChannel(id); + mChannel->loadStoredToastByNotificationIDToChannel(id); } //--------------------------------------------------------------------------------- @@ -139,9 +212,37 @@ void LLSysWellWindow::onItemClose(LLSysWellItem* item) removeItemByID(id); if(mChannel) mChannel->killToastByNotificationID(id); +} - // hide chiclet window if there are no items left - setVisible(!isWindowEmpty()); +//-------------------------------------------------------------------------- +void LLSysWellWindow::onStoreToast(LLPanel* info_panel, LLUUID id) +{ + LLSysWellItem::Params p; + p.notification_id = id; + p.title = static_cast(info_panel)->getTitle(); + addItem(p); +} + +//--------------------------------------------------------------------------------- +void LLSysWellWindow::initChannel() +{ + LLNotificationsUI::LLScreenChannel* channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID( + LLUUID(gSavedSettings.getString("NotificationChannelUUID"))); + if(channel) + { + mChannel = channel; + mChannel->setOnStoreToastCallback(boost::bind(&LLSysWellWindow::onStoreToast, this, _1, _2)); + } + else + { + llwarns << "LLSysWellWindow::initChannel() - could not get a requested screen channel" << llendl; + } +} + +//--------------------------------------------------------------------------------- +void LLSysWellWindow::getEnabledRect(LLRect& rect) +{ + rect = gViewerWindow->getWorldViewRect(); } //--------------------------------------------------------------------------------- @@ -151,9 +252,26 @@ void LLSysWellWindow::toggleWindow() { setDockControl(new LLDockControl( LLBottomTray::getInstance()->getSysWell(), this, - getDockTongue(), LLDockControl::TOP, isDocked())); + getDockTongue(), LLDockControl::TOP, boost::bind(&LLSysWellWindow::getEnabledRect, this, _1))); + } + + if(!getVisible()) + { + if(mChannel) + { + mChannel->removeAndStoreAllStorableToasts(); + } + if(isWindowEmpty()) + { + return; + } + + setVisible(TRUE); + } + else + { + setVisible(FALSE); } - setVisible(!getVisible()); //set window in foreground setFocus(getVisible()); } @@ -161,15 +279,12 @@ void LLSysWellWindow::toggleWindow() //--------------------------------------------------------------------------------- void LLSysWellWindow::setVisible(BOOL visible) { - // on Show adjust position of SysWell chiclet's window if(visible) { if (LLBottomTray::instanceExists()) { LLBottomTray::getInstance()->getSysWell()->setToggleState(TRUE); } - if(mChannel) - mChannel->removeAndStoreAllVisibleToasts(); } else { @@ -178,86 +293,56 @@ void LLSysWellWindow::setVisible(BOOL visible) LLBottomTray::getInstance()->getSysWell()->setToggleState(FALSE); } } - if(mChannel) - mChannel->setShowToasts(!visible); LLDockableFloater::setVisible(visible); + + // update notification channel state + if(mChannel) + { + mChannel->updateShowToastsState(); + } } //--------------------------------------------------------------------------------- -void LLSysWellWindow::reshapeWindow() +void LLSysWellWindow::setDocked(bool docked, bool pop_on_undock) { - // Get size for scrollbar and floater's header - const LLUICachedControl SCROLLBAR_SIZE("UIScrollbarSize", 0); - const LLUICachedControl HEADER_SIZE("UIFloaterHeaderSize", 0); - - LLRect notif_list_rect = mNotificationList->getRect(); - LLRect im_list_rect = mIMRowList->getRect(); - LLRect panel_rect = mTwinListPanel->getRect(); - - S32 notif_list_height = notif_list_rect.getHeight(); - S32 im_list_height = im_list_rect.getHeight(); + LLDockableFloater::setDocked(docked, pop_on_undock); - S32 new_panel_height = notif_list_height + LLScrollingPanelList::GAP_BETWEEN_PANELS + im_list_height; - S32 new_window_height = new_panel_height + LLScrollingPanelList::GAP_BETWEEN_PANELS + HEADER_SIZE; - - U32 twinListWidth = 0; - - if (new_window_height > MAX_WINDOW_HEIGHT) - { - twinListWidth = MIN_PANELLIST_WIDTH - SCROLLBAR_SIZE; - new_window_height = MAX_WINDOW_HEIGHT; - } - else + // update notification channel state + if(mChannel) { - twinListWidth = MIN_PANELLIST_WIDTH; + mChannel->updateShowToastsState(); } - - reshape(MIN_WINDOW_WIDTH, new_window_height, FALSE); - mTwinListPanel->reshape(twinListWidth, new_panel_height, TRUE); - mNotificationList->reshape(twinListWidth, notif_list_height, TRUE); - mIMRowList->reshape(twinListWidth, im_list_height, TRUE); - - // arrange panel and lists - // move panel - panel_rect.setLeftTopAndSize(1, new_panel_height, twinListWidth, new_panel_height); - mTwinListPanel->setRect(panel_rect); - // move notif list panel - notif_list_rect.setLeftTopAndSize(notif_list_rect.mLeft, new_panel_height, twinListWidth, notif_list_height); - mNotificationList->setRect(notif_list_rect); - // move IM list panel - im_list_rect.setLeftTopAndSize(im_list_rect.mLeft, notif_list_rect.mBottom - LLScrollingPanelList::GAP_BETWEEN_PANELS, twinListWidth, im_list_height); - mIMRowList->setRect(im_list_rect); - - mNotificationList->updatePanels(TRUE); - mIMRowList->updatePanels(TRUE); } //--------------------------------------------------------------------------------- -LLSysWellWindow::RowPanel * LLSysWellWindow::findIMRow(const LLUUID& sessionId) +void LLSysWellWindow::reshapeWindow() { - RowPanel * res = NULL; - const LLScrollingPanelList::panel_list_t &list = mIMRowList->getPanelList(); - if (!list.empty()) + // save difference between floater height and the list height to take it into account while calculating new window height + // it includes height from floater top to list top and from floater bottom and list bottom + static S32 parent_list_delta_height = getRect().getHeight() - mMessageList->getRect().getHeight(); + + S32 notif_list_height = mMessageList->getItemsRect().getHeight() + 2 * mMessageList->getBorderWidth(); + + LLRect curRect = getRect(); + + S32 new_window_height = notif_list_height + parent_list_delta_height; + + if (new_window_height > MAX_WINDOW_HEIGHT) { - for (LLScrollingPanelList::panel_list_t::const_iterator iter = list.begin(); iter != list.end(); ++iter) - { - RowPanel *panel = static_cast (*iter); - if (panel->mChiclet->getSessionId() == sessionId) - { - res = panel; - break; - } - } + new_window_height = MAX_WINDOW_HEIGHT; } - return res; + S32 newY = curRect.mTop + new_window_height - curRect.getHeight(); + curRect.setLeftTopAndSize(curRect.mLeft, newY, MIN_WINDOW_WIDTH, new_window_height); + reshape(curRect.getWidth(), curRect.getHeight(), TRUE); + setRect(curRect); } //--------------------------------------------------------------------------------- LLChiclet* LLSysWellWindow::findIMChiclet(const LLUUID& sessionId) { LLChiclet* res = NULL; - RowPanel* panel = findIMRow(sessionId); + RowPanel* panel = mMessageList->getTypedItemByValue(get_session_value(sessionId)); if (panel != NULL) { res = panel->mChiclet; @@ -270,34 +355,51 @@ LLChiclet* LLSysWellWindow::findIMChiclet(const LLUUID& sessionId) void LLSysWellWindow::addIMRow(const LLUUID& sessionId, S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId) { + RowPanel* item = new RowPanel(this, sessionId, chicletCounter, name, otherParticipantId); + if (mMessageList->insertItemAfter(mSeparator, item, get_session_value(sessionId))) + { + handleItemAdded(IT_INSTANT_MESSAGE); + } + else + { + llwarns << "Unable to add IM Row into the list, sessionID: " << sessionId + << ", name: " << name + << ", other participant ID: " << otherParticipantId + << llendl; - mIMRowList->addPanel(new RowPanel(this, sessionId, chicletCounter, name, otherParticipantId)); + item->die(); + } } //--------------------------------------------------------------------------------- void LLSysWellWindow::delIMRow(const LLUUID& sessionId) { - RowPanel *panel = findIMRow(sessionId); - if (panel != NULL) + if (mMessageList->removeItemByValue(get_session_value(sessionId))) + { + handleItemRemoved(IT_INSTANT_MESSAGE); + } + else { - mIMRowList->removePanel(panel); + llwarns << "Unable to remove IM Row from the list, sessionID: " << sessionId + << llendl; } + // remove all toasts that belong to this session from a screen + if(mChannel) + mChannel->removeToastsBySessionID(sessionId); + // hide chiclet window if there are no items left - setVisible(!isWindowEmpty()); + if(isWindowEmpty()) + { + setVisible(FALSE); + } } //--------------------------------------------------------------------------------- bool LLSysWellWindow::isWindowEmpty() { - if(mIMRowList->getPanelList().size() == 0 && LLBottomTray::getInstance()->getSysWell()->getCounter() == 0) - { - return true; - } - else - { - return false; - } + // keep in mind, mSeparator is always in the list + return mMessageList->size() == 1; } //--------------------------------------------------------------------------------- @@ -305,7 +407,7 @@ bool LLSysWellWindow::isWindowEmpty() void LLSysWellWindow::sessionAdded(const LLUUID& sessionId, const std::string& name, const LLUUID& otherParticipantId) { - if (findIMRow(sessionId) == NULL) + if (mMessageList->getItemByValue(get_session_value(sessionId)) == NULL) { S32 chicletCounter = 0; LLIMModel::LLIMSession* session = get_if_there(LLIMModel::sSessionsMap, @@ -328,10 +430,57 @@ void LLSysWellWindow::sessionRemoved(const LLUUID& sessionId) LLBottomTray::getInstance()->getSysWell()->updateUreadIMNotifications(); } +void LLSysWellWindow::handleItemAdded(EItemType added_item_type) +{ + bool should_be_shown = ++mTypedItemsCount[added_item_type] == 1 && anotherTypeExists(added_item_type); + + if (should_be_shown && !mSeparator->getVisible()) + { + mSeparator->setVisible(TRUE); + + // refresh list to recalculate mSeparator position + mMessageList->reshape(mMessageList->getRect().getWidth(), mMessageList->getRect().getHeight()); + } +} + +void LLSysWellWindow::handleItemRemoved(EItemType removed_item_type) +{ + bool should_be_hidden = --mTypedItemsCount[removed_item_type] == 0; + + if (should_be_hidden && mSeparator->getVisible()) + { + mSeparator->setVisible(FALSE); + + // refresh list to recalculate mSeparator position + mMessageList->reshape(mMessageList->getRect().getWidth(), mMessageList->getRect().getHeight()); + } +} + +bool LLSysWellWindow::anotherTypeExists(EItemType item_type) +{ + bool exists = false; + switch(item_type) + { + case IT_INSTANT_MESSAGE: + if (mTypedItemsCount[IT_NOTIFICATION] > 0) + { + exists = true; + } + break; + case IT_NOTIFICATION: + if (mTypedItemsCount[IT_INSTANT_MESSAGE] > 0) + { + exists = true; + } + break; + } + return exists; +} + //--------------------------------------------------------------------------------- LLSysWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID& sessionId, S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId) : - LLScrollingPanel(LLPanel::Params()), mChiclet(NULL), mParent(parent) + LLPanel(LLPanel::Params()), mChiclet(NULL), mParent(parent) { LLUICtrlFactory::getInstance()->buildPanel(this, "panel_activeim_row.xml", NULL); @@ -373,8 +522,8 @@ LLSysWellWindow::RowPanel::~RowPanel() //--------------------------------------------------------------------------------- void LLSysWellWindow::RowPanel::onClose() { - mParent->mIMRowList->removePanel(this); gIMMgr->removeSession(mChiclet->getSessionId()); + // This row panel will be removed from the list in LLSysWellWindow::sessionRemoved(). } //--------------------------------------------------------------------------------- @@ -400,13 +549,4 @@ BOOL LLSysWellWindow::RowPanel::handleMouseDown(S32 x, S32 y, MASK mask) return LLPanel::handleMouseDown(x, y, mask); } -//--------------------------------------------------------------------------------- -void LLSysWellWindow::RowPanel::updatePanel(BOOL allow_modify) -{ - S32 parent_width = getParent()->getRect().getWidth(); - S32 panel_height = getRect().getHeight(); - - reshape(parent_width, panel_height, TRUE); -} - -//--------------------------------------------------------------------------------- +// EOF diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index d76147b489..37a2690a82 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -44,7 +44,7 @@ #include "boost/shared_ptr.hpp" - +class LLFlatListView; class LLSysWellWindow : public LLDockableFloater, LLIMSessionObserver { @@ -54,36 +54,52 @@ public: BOOL postBuild(); // other interface functions + // check is window empty bool isWindowEmpty(); - // change attributes - void setChannel(LLNotificationsUI::LLScreenChannel* channel) {mChannel = channel;} - // Operating with items void addItem(LLSysWellItem::Params p); void clear( void ); void removeItemByID(const LLUUID& id); - S32 findItemByID(const LLUUID& id); // Operating with outfit virtual void setVisible(BOOL visible); void adjustWindowPosition(); void toggleWindow(); - /*virtua*/BOOL canClose() { return FALSE; } + /*virtual*/ BOOL canClose() { return FALSE; } + /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); // Handlers void onItemClick(LLSysWellItem* item); void onItemClose(LLSysWellItem* item); + void onStoreToast(LLPanel* info_panel, LLUUID id); + void onChicletClick(); // size constants for the window and for its elements static const S32 MAX_WINDOW_HEIGHT = 200; - static const S32 MIN_WINDOW_WIDTH = 320; - static const S32 MIN_PANELLIST_WIDTH = 318; + static const S32 MIN_WINDOW_WIDTH = 318; private: + + typedef enum{ + IT_NOTIFICATION, + IT_INSTANT_MESSAGE + }EItemType; + + // gets a rect valid for SysWellWindow's position on a screen (EXT-1111) + void getEnabledRect(LLRect& rect); + // connect counter and list updaters to the corresponding signals + void connectListUpdaterToSignal(std::string notification_type); + // init Window's channel + void initChannel(); + void handleItemAdded(EItemType added_item_type); + void handleItemRemoved(EItemType removed_item_type); + bool anotherTypeExists(EItemType item_type) ; + + + class RowPanel; void reshapeWindow(); - RowPanel * findIMRow(const LLUUID& sessionId); LLChiclet * findIMChiclet(const LLUUID& sessionId); void addIMRow(const LLUUID& sessionId, S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId); void delIMRow(const LLUUID& sessionId); @@ -93,23 +109,28 @@ private: // pointer to a corresponding channel's instance LLNotificationsUI::LLScreenChannel* mChannel; - LLPanel* mTwinListPanel; - LLScrollContainer* mScrollContainer; - LLScrollingPanelList* mIMRowList; - LLScrollingPanelList* mNotificationList; + LLFlatListView* mMessageList; + + /** + * Special panel which is used as separator of Notifications & IM Rows. + * It is always presents in the list and shown when it is necessary. + * It should be taken into account when reshaping and checking list size + */ + LLPanel* mSeparator; + + typedef std::map typed_items_count_t; + typed_items_count_t mTypedItemsCount; private: /** * Scrolling row panel. */ - class RowPanel: public LLScrollingPanel + class RowPanel: public LLPanel { public: RowPanel(const LLSysWellWindow* parent, const LLUUID& sessionId, S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId); virtual ~RowPanel(); - /*virtual*/ - void updatePanel(BOOL allow_modify); void onMouseEnter(S32 x, S32 y, MASK mask); void onMouseLeave(S32 x, S32 y, MASK mask); BOOL handleMouseDown(S32 x, S32 y, MASK mask); diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index fb7574d68b..97a15759bf 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -44,7 +44,8 @@ using namespace LLNotificationsUI; LLToast::LLToast(LLToast::Params p) : LLFloater(LLSD()), mPanel(p.panel), mTimerValue(p.timer_period), - mID(p.id), + mNotificationID(p.notif_id), + mSessionID(p.session_id), mCanFade(p.can_fade), mCanBeStored(p.can_be_stored), mHideBtnEnabled(p.enable_hide_btn), @@ -73,12 +74,12 @@ LLToast::LLToast(LLToast::Params p) : LLFloater(LLSD()), setFocus(TRUE); } - - if(!p.on_toast_destroy.empty()) - mOnToastDestroy.connect(p.on_toast_destroy); + // init callbacks if present + if(!p.on_delete_toast.empty()) + mOnDeleteToastSignal.connect(p.on_delete_toast); if(!p.on_mouse_enter.empty()) - mOnMousEnter.connect(p.on_mouse_enter); + mOnMouseEnterSignal.connect(p.on_mouse_enter); } //-------------------------------------------------------------------------- @@ -102,6 +103,7 @@ void LLToast::setHideButtonEnabled(bool enabled) //-------------------------------------------------------------------------- LLToast::~LLToast() { + mOnToastDestroyedSignal(this); if(mIsModal) { gFocusMgr.unlockFocus(); @@ -142,7 +144,7 @@ void LLToast::hide() { setVisible(FALSE); mTimer.stop(); - mOnFade(this); + mOnFadeSignal(this); } //-------------------------------------------------------------------------- @@ -160,7 +162,7 @@ void LLToast::tick() { setVisible(FALSE); mTimer.stop(); - mOnFade(this); + mOnFadeSignal(this); } } @@ -223,7 +225,7 @@ void LLToast::setVisible(BOOL show) //-------------------------------------------------------------------------- void LLToast::onMouseEnter(S32 x, S32 y, MASK mask) { - mOnToastHover(this, MOUSE_ENTER); + mOnToastHoverSignal(this, MOUSE_ENTER); setBackgroundOpaque(TRUE); if(mCanFade) @@ -234,13 +236,13 @@ void LLToast::onMouseEnter(S32 x, S32 y, MASK mask) sendChildToFront(mHideBtn); if(mHideBtn && mHideBtn->getEnabled()) mHideBtn->setVisible(TRUE); - mOnMousEnter(this); + mOnMouseEnterSignal(this); } //-------------------------------------------------------------------------- void LLToast::onMouseLeave(S32 x, S32 y, MASK mask) { - mOnToastHover(this, MOUSE_LEAVE); + mOnToastHoverSignal(this, MOUSE_LEAVE); if(mCanFade) { @@ -270,21 +272,11 @@ BOOL LLToast::handleMouseDown(S32 x, S32 y, MASK mask) } //-------------------------------------------------------------------------- -void LLToast::discardNotification() -{ - if(mNotification) - { - mNotification->setIgnored(TRUE); - mNotification->respond(mNotification->getResponseTemplate()); - } -} - -//-------------------------------------------------------------------------- -bool LLToast::getIsNotificationUnResponded() +bool LLToast::isNotificationValid() { if(mNotification) { - return !mNotification->isRespondedTo(); + return !mNotification->isCancelled(); } return false; } diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index 05e63a60c5..9248747c43 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -57,13 +57,14 @@ public: typedef boost::function toast_callback_t; typedef boost::signals2::signal toast_signal_t; - struct Params : public LLInitParam::Block + struct Params { LLPanel* panel; - LLUUID id; //notification or message ID + LLUUID notif_id; //notification ID + LLUUID session_id; //im session ID LLNotificationPtr notification; F32 timer_period; - toast_callback_t on_toast_destroy; + toast_callback_t on_delete_toast; toast_callback_t on_mouse_enter; bool can_fade; bool can_be_stored; @@ -100,8 +101,6 @@ public: void insertPanel(LLPanel* panel); // get toast's panel LLPanel* getPanel() { return mPanel; } - // discard notification - void discardNotification(); // enable/disable Toast's Hide button void setHideButtonEnabled(bool enabled); // initialize and start Toast's timer @@ -120,8 +119,12 @@ public: // get/set Toast's flags or states - // get information whether the notification corresponding to the toast is responded or not - bool getIsNotificationUnResponded(); + // get information whether the notification corresponding to the toast is valid or not + bool isNotificationValid(); + // get toast's Notification ID + const LLUUID getNotificationID() { return mNotificationID;} + // get toast's Session ID + const LLUUID getSessionID() { return mSessionID;} // void setCanFade(bool can_fade); // @@ -132,18 +135,18 @@ public: void setModal(bool modal); - // Registers callbacks for events - toast_signal_t mOnFade; - toast_signal_t mOnMousEnter; - toast_signal_t mOnToastDestroy; - boost::signals2::connection setOnFadeCallback(toast_callback_t cb) { return mOnFade.connect(cb); } - boost::signals2::connection setOnMouseEnterCallback(toast_callback_t cb) { return mOnMousEnter.connect(cb); } - boost::signals2::connection setOnToastDestroyCallback(toast_callback_t cb) { return mOnToastDestroy.connect(cb); } + // Registers signals/callbacks for events + toast_signal_t mOnFadeSignal; + toast_signal_t mOnMouseEnterSignal; + toast_signal_t mOnDeleteToastSignal; + toast_signal_t mOnToastDestroyedSignal; + boost::signals2::connection setOnFadeCallback(toast_callback_t cb) { return mOnFadeSignal.connect(cb); } + boost::signals2::connection setOnToastDestroyedCallback(toast_callback_t cb) { return mOnToastDestroyedSignal.connect(cb); } typedef boost::function toast_hover_check_callback_t; typedef boost::signals2::signal toast_hover_check_signal_t; - toast_hover_check_signal_t mOnToastHover; - boost::signals2::connection setOnToastHoverCallback(toast_hover_check_callback_t cb) { return mOnToastHover.connect(cb); } + toast_hover_check_signal_t mOnToastHoverSignal; + boost::signals2::connection setOnToastHoverCallback(toast_hover_check_callback_t cb) { return mOnToastHoverSignal.connect(cb); } private: @@ -153,7 +156,8 @@ private: // on timer finished function void tick(); - LLUUID mID; + LLUUID mNotificationID; + LLUUID mSessionID; LLNotificationPtr mNotification; LLTimer mTimer; diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp index d401943020..fe1492d937 100644 --- a/indra/newview/lltoastimpanel.cpp +++ b/indra/newview/lltoastimpanel.cpp @@ -44,14 +44,14 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif { LLUICtrlFactory::getInstance()->buildPanel(this, "panel_instant_message.xml"); - mAvatar = getChild("avatar"); + LLIconCtrl* sys_msg_icon = getChild("sys_msg_icon"); + mAvatar = getChild("avatar_icon"); mUserName = getChild("user_name"); mTime = getChild("time_box"); mMessage = getChild("message"); mReplyBtn = getChild("reply"); mMessage->setValue(p.message); - mAvatar->setValue(p.avatar_id); mUserName->setValue(p.from); mTime->setValue(p.time); mSessionID = p.session_id; @@ -60,6 +60,9 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif // if message comes from the system - there shouldn't be a reply btn if(p.from == "Second Life") { + mAvatar->setVisible(FALSE); + sys_msg_icon->setVisible(TRUE); + mReplyBtn->setVisible(FALSE); S32 btn_height = mReplyBtn->getRect().getHeight(); LLRect msg_rect = mMessage->getRect(); @@ -68,6 +71,10 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif } else { + mAvatar->setVisible(TRUE); + sys_msg_icon->setVisible(FALSE); + + mAvatar->setValue(p.avatar_id); mReplyBtn->setClickedCallback(boost::bind(&LLToastIMPanel::onClickReplyBtn, this)); } @@ -88,9 +95,7 @@ LLToastIMPanel::~LLToastIMPanel() //-------------------------------------------------------------------------- void LLToastIMPanel::onClickReplyBtn() { - LLSD response = mNotification->getResponseTemplate(); - response["respondbutton"] = true; - mNotification->respond(response); + mNotification->respond(mNotification->getResponseTemplate()); } //-------------------------------------------------------------------------- diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h index b51ce23364..af21b07a3d 100644 --- a/indra/newview/lltoastimpanel.h +++ b/indra/newview/lltoastimpanel.h @@ -43,7 +43,7 @@ class LLToastIMPanel: public LLToastPanel { public: - struct Params : public LLInitParam::Block + struct Params { LLNotificationPtr notification; LLUUID avatar_id; diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 844c54da6a..9761a45d83 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -171,6 +171,7 @@ LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification) : LLToas params.name("box"); params.rect(LLRect(x, y, getRect().getWidth()-2, mIsTip ? BOTTOM : BTN_TOP+16)); params.max_text_length(MAX_LENGTH); + params.read_only(true); params.default_text(mMessage); params.font(sFont); params.embedded_items(false); diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 08040cfaa5..c3064ffa43 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -54,6 +54,7 @@ #include "llmutelist.h" #include "llnotify.h" #include "llpreviewnotecard.h" +#include "llrecentpeople.h" #include "llselectmgr.h" #include "lltoolmgr.h" #include "lltooltip.h" @@ -646,6 +647,7 @@ void LLToolDragAndDrop::beginMultiDrag( void LLToolDragAndDrop::endDrag() { + mEndDragSignal(); LLSelectMgr::getInstance()->unhighlightAll(); setMouseCapture(FALSE); } diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index c9fef26b58..acf01869e7 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -51,6 +51,8 @@ class LLPickInfo; class LLToolDragAndDrop : public LLTool, public LLSingleton { public: + typedef boost::signals2::signal enddrag_signal_t; + LLToolDragAndDrop(); // overridden from LLTool @@ -87,6 +89,8 @@ public: const LLUUID& getObjectID() const { return mObjectID; } EAcceptance getLastAccept() { return mLastAccept; } + boost::signals2::connection setEndDragCallback( const enddrag_signal_t::slot_type& cb ) { return mEndDragSignal.connect(cb); } + protected: enum EDropTarget { @@ -131,6 +135,8 @@ protected: S32 mCurItemIndex; std::string mToolTipMsg; + enddrag_signal_t mEndDragSignal; + // array of pointers to functions that implement the logic to // dragging and dropping into the simulator. static dragOrDrop3dImpl sDragAndDrop3d[DAD_COUNT][DT_COUNT]; diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index b888560fc7..24f4745c18 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -72,6 +72,8 @@ #include "llvosurfacepatch.h" #include "llvowlsky.h" #include "llrender.h" +#include "llbottomtray.h" +#include "llnavigationbar.h" #ifdef TOGGLE_HACKED_GODLIKE_VIEWER BOOL gHackGodmode = FALSE; @@ -483,6 +485,36 @@ bool toggle_agent_pause(const LLSD& newvalue) return true; } +bool toggle_show_gesture_button(const LLSD& newvalue) +{ + LLBottomTray::getInstance()->showGestureButton(newvalue.asBoolean()); + return true; +} + +bool toggle_show_move_button(const LLSD& newvalue) +{ + LLBottomTray::getInstance()->showMoveButton(newvalue.asBoolean()); + return true; +} + +bool toggle_show_camera_button(const LLSD& newvalue) +{ + LLBottomTray::getInstance()->showCameraButton(newvalue.asBoolean()); + return true; +} + +bool toggle_show_navigation_panel(const LLSD& newvalue) +{ + LLNavigationBar::getInstance()->showNavigationPanel(newvalue.asBoolean()); + return true; +} + +bool toggle_show_favorites_panel(const LLSD& newvalue) +{ + LLNavigationBar::getInstance()->showFavoritesPanel(newvalue.asBoolean()); + return true; +} + //////////////////////////////////////////////////////////////////////////// void settings_setup_listeners() @@ -619,6 +651,11 @@ void settings_setup_listeners() gSavedSettings.getControl("QAMode")->getSignal()->connect(boost::bind(&show_debug_menus)); gSavedSettings.getControl("UseDebugMenus")->getSignal()->connect(boost::bind(&show_debug_menus)); gSavedSettings.getControl("AgentPause")->getSignal()->connect(boost::bind(&toggle_agent_pause, _2)); + gSavedSettings.getControl("ShowGestureButton")->getSignal()->connect(boost::bind(&toggle_show_gesture_button, _2)); + gSavedSettings.getControl("ShowMoveButton")->getSignal()->connect(boost::bind(&toggle_show_move_button, _2)); + gSavedSettings.getControl("ShowCameraButton")->getSignal()->connect(boost::bind(&toggle_show_camera_button, _2)); + gSavedSettings.getControl("ShowNavbarNavigationPanel")->getSignal()->connect(boost::bind(&toggle_show_navigation_panel, _2)); + gSavedSettings.getControl("ShowNavbarFavoritesPanel")->getSignal()->connect(boost::bind(&toggle_show_favorites_panel, _2)); } #if TEST_CACHED_CONTROL diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 441d0ebeaa..51d699c0f7 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -69,6 +69,7 @@ #include "llfloatermediabrowser.h" #include "llfloaterhud.h" #include "llfloaterimagepreview.h" +#include "llimfloater.h" #include "llimpanel.h" #include "llfloaterinspect.h" #include "llfloaterinventory.h" @@ -143,6 +144,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("bumps", "floater_bumps.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("camera_presets", "floater_camera_presets.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("chat", "floater_chat_history.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("nearby_chat", "floater_nearby_chat.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("communicate", "floater_chatterbox.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 9d278e6a6c..a0bd5f301b 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -3830,6 +3830,7 @@ void handle_reset_view() } else { + gAgent.switchCameraPreset(CAMERA_PRESET_REAR_VIEW); reset_view_final( TRUE ); LLFloaterCamera::resetCameraMode(); } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index e37bad6b0e..390e1fe032 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -98,6 +98,7 @@ #include "llnotifications.h" #include "llnotify.h" #include "llpanelgrouplandmoney.h" +#include "llrecentpeople.h" #include "llselectmgr.h" #include "llsidetray.h" #include "llstartup.h" diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 5fd5397970..d23f10f880 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1559,9 +1559,19 @@ void LLViewerWindow::initWorldUI() navbar->showFavoritesPanel(FALSE); } - if (!gSavedSettings.getBOOL("ShowCameraAndMoveControls")) + if (!gSavedSettings.getBOOL("ShowCameraButton")) { - LLBottomTray::getInstance()->showCameraAndMoveControls(FALSE); + LLBottomTray::getInstance()->showCameraButton(FALSE); + } + + if (!gSavedSettings.getBOOL("ShowMoveButton")) + { + LLBottomTray::getInstance()->showMoveButton(FALSE); + } + + if (!gSavedSettings.getBOOL("ShowGestureButton")) + { + LLBottomTray::getInstance()->showGestureButton(FALSE); } getRootView()->addChild(gStatusBar); @@ -1577,13 +1587,6 @@ void LLViewerWindow::initWorldUI() // menu holder appears on top to get first pass at all mouse events getRootView()->sendChildToFront(gMenuHolder); - //Channel Manager - LLNotificationsUI::LLChannelManager* channel_manager = LLNotificationsUI::LLChannelManager::getInstance(); - getRootView()->addChild(channel_manager); - //Notification Manager - LLNotificationsUI::LLNotificationManager* notify_manager = LLNotificationsUI::LLNotificationManager::getInstance(); - getRootView()->addChild(notify_manager); - if ( gHUDView == NULL ) { LLRect hud_rect = full_window; @@ -2859,6 +2862,9 @@ void LLViewerWindow::updateWorldViewRect(bool use_full_window) if (mWorldViewRect != new_world_rect) { + // sending a signal with a new WorldView rect + mOnWorldViewRectUpdated(mWorldViewRect, new_world_rect); + mWorldViewRect = new_world_rect; gResizeScreenTexture = TRUE; LLViewerCamera::getInstance()->setViewHeightInPixels( mWorldViewRect.getHeight() ); @@ -3215,9 +3221,18 @@ LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_trans pickAsync(x, y_from_bot, gKeyboard->currentMask(TRUE), NULL, pick_transparent); // assume that pickAsync put the results in the back of the mPicks list + if(mPicks.size() != 0) + { mLastPick = mPicks.back(); mLastPick.fetchResults(); mPicks.pop_back(); + } + else + { + llwarns << "List of last picks is empty" << llendl; + llwarns << "Using stub pick" << llendl; + mLastPick = LLPickInfo(); + } return mLastPick; } diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index e4f6240fc7..231b857d1f 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -196,6 +196,11 @@ public: typedef boost::signals2::signal bottom_tray_signal_t; bottom_tray_signal_t mOnBottomTrayWidthChanged; boost::signals2::connection setOnBottomTrayWidthChanged(bottom_tray_callback_t cb) { return mOnBottomTrayWidthChanged.connect(cb); } + // signal on update of WorldView rect + typedef boost::function world_rect_callback_t; + typedef boost::signals2::signal world_rect_signal_t; + world_rect_signal_t mOnWorldViewRectUpdated; + boost::signals2::connection setOnWorldViewRectUpdated(world_rect_callback_t cb) { return mOnWorldViewRectUpdated.connect(cb); } // // ACCESSORS diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 2304571cf1..6401389c8f 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -46,6 +46,7 @@ # include "expat/expat.h" #endif #include "llcallbacklist.h" +#include "llcallingcard.h" // for LLFriendObserver #include "llviewerregion.h" #include "llviewernetwork.h" // for gGridChoice #include "llbase64.h" diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index fe99e787da..bddd18dee8 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -42,9 +42,9 @@ class LLVivoxProtocolParser; #include "v3math.h" #include "llframetimer.h" #include "llviewerregion.h" -#include "llcallingcard.h" // for LLFriendObserver #include "m3math.h" // LLMatrix3 +class LLFriendObserver; class LLVoiceClientParticipantObserver { public: diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 8440022844..46c294768d 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -514,6 +514,9 @@ + + + diff --git a/indra/newview/skins/default/xui/en/favorites_bar_button.xml b/indra/newview/skins/default/xui/en/favorites_bar_button.xml index e2f81168fa..dcd85e1f58 100644 --- a/indra/newview/skins/default/xui/en/favorites_bar_button.xml +++ b/indra/newview/skins/default/xui/en/favorites_bar_button.xml @@ -6,9 +6,13 @@ halign="center" height="23" image_disabled="transparent.j2c" - image_disabled_selected="PushButton_Selected" - image_selected="PushButton_Selected" - image_unselected="PushButton_Off" + image_disabled_selected="transparent.j2c" + image_selected="transparent.j2c" + image_unselected="transparent.j2c" + image_hover_selected="PushButton_Selected" + image_hover_unselected="PushButton_Off" + image_pressed="PushButton_Press" + image_pressed_selected="PushButton_Selected_Press" hover_glow_amount="0.15" layout="topleft" left="2" diff --git a/indra/newview/skins/default/xui/en/floater_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml index 1592ed4aa4..0784b88944 100644 --- a/indra/newview/skins/default/xui/en/floater_camera.xml +++ b/indra/newview/skins/default/xui/en/floater_camera.xml @@ -1,5 +1,6 @@ @@ -95,7 +97,7 @@ scale_image="false" tool_tip="Fly Down, Press "C"" top_delta="0" - width="25" /> + width="20" /> - - - - - - diff --git a/indra/newview/skins/default/xui/en/menu_bottomtray.xml b/indra/newview/skins/default/xui/en/menu_bottomtray.xml new file mode 100644 index 0000000000..e98920f8c2 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_bottomtray.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_hide_navbar.xml b/indra/newview/skins/default/xui/en/menu_hide_navbar.xml index 1ad10abbeb..a175b3103f 100644 --- a/indra/newview/skins/default/xui/en/menu_hide_navbar.xml +++ b/indra/newview/skins/default/xui/en/menu_hide_navbar.xml @@ -11,23 +11,23 @@ + name="ShowNavbarNavigationPanel"> + function="ToggleControl" + parameter="ShowNavbarNavigationPanel" /> + function="CheckControl" + parameter="ShowNavbarNavigationPanel" /> + name="ShowNavbarFavoritesPanel"> + function="ToggleControl" + parameter="ShowNavbarFavoritesPanel" /> + function="CheckControl" + parameter="ShowNavbarFavoritesPanel" /> diff --git a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml new file mode 100644 index 0000000000..ec8582f5b5 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_people_nearby.xml b/indra/newview/skins/default/xui/en/menu_people_nearby.xml new file mode 100644 index 0000000000..643336cf6c --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_people_nearby.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml index 88b0528e53..d9606de90d 100644 --- a/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml +++ b/indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml @@ -2,8 +2,8 @@ - - + + diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index b430de2b7b..bc51ba5e6a 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -127,12 +127,14 @@ + + function="World.SetBusy"/> - + + layout="topleft" /> + + + + + + + + + - - - - - - - + diff --git a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml index 311caa4866..c4c8aa24c4 100644 --- a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml @@ -16,7 +16,10 @@ name="want_apply_text"> Do you want to apply these changes? - + + Join (L$[AMOUNT]) + diff --git a/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml b/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml index f25c4bfbba..aa76a61c15 100644 --- a/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml +++ b/indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml @@ -19,4 +19,17 @@ top="4" value="Side Panel" width="255" /> + diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 13a53a4ce3..0f7afcba6e 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -93,7 +93,6 @@ Restore Minimize Tear Off - Edit Dock Undock Show Help diff --git a/indra/newview/tests/llviewerhelputil_test.cpp b/indra/newview/tests/llviewerhelputil_test.cpp new file mode 100644 index 0000000000..40f7d532bc --- /dev/null +++ b/indra/newview/tests/llviewerhelputil_test.cpp @@ -0,0 +1,127 @@ +/** + * @file llviewerhelputil_test.cpp + * @brief LLViewerHelpUtil tests + * @author Tofu Linden + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "../test/lltut.h" + +#include "../llviewerhelputil.h" +#include "llcontrol.h" +#include "llsys.h" + +#include + +//---------------------------------------------------------------------------- +// Implementation of enough of LLControlGroup to support the tests: + +static std::map test_stringvec; + +LLControlGroup::LLControlGroup(const std::string& name) + : LLInstanceTracker(name) +{ +} + +LLControlGroup::~LLControlGroup() +{ +} + +// Implementation of just the LLControlGroup methods we requre +BOOL LLControlGroup::declareString(const std::string& name, + const std::string& initial_val, + const std::string& comment, + BOOL persist) +{ + test_stringvec[name] = initial_val; + return true; +} + +void LLControlGroup::setString(const std::string& name, const std::string& val) +{ + test_stringvec[name] = val; +} + +std::string LLControlGroup::getString(const std::string& name) +{ + return test_stringvec[name]; +} + +//---------------------------------------------------------------------------- + +namespace tut +{ + struct viewerhelputil + { + }; + + typedef test_group viewerhelputil_t; + typedef viewerhelputil_t::object viewerhelputil_object_t; + tut::viewerhelputil_t tut_viewerhelputil("viewerhelputil"); + + template<> template<> + void viewerhelputil_object_t::test<1>() + { + LLOSInfo osinfo; + LLControlGroup cgr("test"); + cgr.declareString("HelpURLFormat", "fooformat", "declared_for_test", FALSE); + cgr.declareString("VersionChannelName", "foochannelname", "declared_for_test", FALSE); + cgr.declareString("Language", "foolanguage", "declared_for_test", FALSE); + std::string topic("test_topic"); + + std::string subresult; + + cgr.setString("HelpURLFormat", "fooformat"); + subresult = LLViewerHelpUtil::buildHelpURL(topic, cgr, osinfo); + ensure_equals("no substitution tags", subresult, "fooformat"); + + cgr.setString("HelpURLFormat", ""); + subresult = LLViewerHelpUtil::buildHelpURL(topic, cgr, osinfo); + ensure_equals("blank substitution format", subresult, ""); + + cgr.setString("HelpURLFormat", "[LANGUAGE]"); + cgr.setString("Language", ""); + subresult = LLViewerHelpUtil::buildHelpURL(topic, cgr, osinfo); + ensure_equals("simple substitution with blank", subresult, ""); + + cgr.setString("HelpURLFormat", "[LANGUAGE]"); + cgr.setString("Language", "Esperanto"); + subresult = LLViewerHelpUtil::buildHelpURL(topic, cgr, osinfo); + ensure_equals("simple substitution", subresult, "Esperanto"); + + cgr.setString("HelpURLFormat", "[XXX]"); + subresult = LLViewerHelpUtil::buildHelpURL(topic, cgr, osinfo); + ensure_equals("unknown substitution", subresult, "[XXX]"); + + cgr.setString("HelpURLFormat", "[LANGUAGE]/[LANGUAGE]"); + cgr.setString("Language", "Esperanto"); + subresult = LLViewerHelpUtil::buildHelpURL(topic, cgr, osinfo); + ensure_equals("multiple substitution", subresult, "Esperanto/Esperanto"); + } + +} -- cgit v1.2.3 From a0596b4d5c0c0aa7a9dfb88ad5d28d28a0c86fa9 Mon Sep 17 00:00:00 2001 From: Ramzi Ramey Date: Wed, 30 Sep 2009 18:15:37 +0000 Subject: DEV-40452 VWR-15527: Correct small errors and linguistic consistency in the LSL editor tooltips - also fixes the specific cases of VWR-3766, VWR-1794 - string changes only, NO CODE changed. - this is needed so that we can begin the Localization round --- indra/newview/skins/default/xui/en/strings.xml | 773 ++++++++++++------------- 1 file changed, 386 insertions(+), 387 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 0f7afcba6e..311bf0503a 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -307,112 +307,115 @@ Sleeps script for [SLEEP_TIME] seconds. float llSin(float theta) -theta in radians +Returns the sine of theta (theta in radians) float llCos(float theta) -theta in radians +Returns the cosine of theta (theta in radians) float llTan(float theta) -theta radians +Returns the tangent of theta (theta in radians) float llAtan2(float y, float x) +Returns the arctangent2 of y, x float llSqrt(float val) -returns 0 and triggers a Math Error for imaginary results +Returns the square root of val, or returns 0 and triggers a Math Error for imaginary results float llPow(float base, float exponent) -returns 0 and triggers Math Error for imaginary results +Returns the base raised to the power exponent, or returns 0 and triggers Math Error for imaginary results integer llAbs(integer val) +Returns the positive version of val float llFabs(float val) +Returns the positive version of val float llFrand(float mag) -returns random number in range [0,mag) +Returns a pseudo random number in the range [0,mag) or (mag,0] integer llFloor(float val) -returns largest integer value <= val +Returns largest integer value <= val integer llCeil(float val) -returns smallest integer value >= val +Returns smallest integer value >= val integer llRound(float val) -returns val rounded to the nearest integer +Returns val rounded to the nearest integer float llVecMag(vector v) -returns the magnitude of v +Returns the magnitude of v vector llVecNorm(vector v) -returns the v normalized +Returns the v normalized float llVecDist(vector v1, vector v2) -returns the 3D distance between v1 and v2 +Returns the 3D distance between v1 and v2 vector llRot2Euler(rotation q) -returns the Euler representation (roll, pitch, yaw) of q +Returns the Euler representation (roll, pitch, yaw) of q rotation llEuler2Rot(vector v) -returns the rotation representation of Euler Angles v +Returns the rotation representation of Euler Angles v rotation llAxes2Rot(vector fwd, vector left, vector up) -returns the rotation defined by the coordinate axes +Returns the rotation defined by the coordinate axes vector llRot2Fwd(rotation q) -returns the forward vector defined by q +Returns the forward vector defined by q vector llRot2Left(rotation q) -returns the left vector defined by q +Returns the left vector defined by q vector llRot2Up(rotation q) -returns the up vector defined by q +Returns the up vector defined by q rotation llRotBetween(vector v1, vector v2) -returns the rotation to rotate v1 to v2 +Returns the rotation to rotate v1 to v2 llWhisper(integer channel, string msg) -whispers msg on channel +Whispers the text of msg on channel llSay(integer channel, string msg) -says msg on channel +Says the text of msg on channel llShout(integer channel, string msg) -shouts msg on channel +Shouts the text of msg on channel integer llListen(integer channel, string name, key id, string msg) -sets a callback for msg on channel from name and id (name, id, and/or msg can be empty) and returns an identifier that can be used to deactivate or remove the listen +Sets a callback for msg on channel from name and id (name, id, and/or msg can be empty) and returns an identifier that can be used to deactivate or remove the listen llListenControl(integer number, integer active) -makes a listen event callback active or inactive +Makes a listen event callback active or inactive llListenRemove(integer number) -removes listen event callback number +Removes listen event callback number llSensor(string name, key id, integer type, float range, float arc) @@ -420,43 +423,43 @@ Performs a single scan for name and id with type (AGENT, ACTIVE, PASSIVE, and/or llSensorRepeat(string name, key id, integer type, float range, float arc, float rate) -sets a callback for name and id with type (AGENT, ACTIVE, PASSIVE, and/or SCRIPTED) within range meters and arc radians of forward vector (name, id, and/or keytype can be empty or 0) and repeats every rate seconds +Sets a callback for name and id with type (AGENT, ACTIVE, PASSIVE, and/or SCRIPTED) within range meters and arc radians of forward vector (name, id, and/or keytype can be empty or 0) and repeats every rate seconds llSensorRemove() -removes sensor +Removes the sensor setup by llSensorRepeat string llDetectedName(integer number) -returns the name of detected object number (returns empty string if number is not valid sensed object) +Returns the name of detected object number (returns empty string if number is not a valid sensed object) key llDetectedKey(integer number) -returns the key of detected object number (returns empty key if number is not valid sensed object) +Returns the key of detected object number (returns empty key if number is not a valid sensed object) key llDetectedOwner(integer number) -returns the key of detected object's owner (returns empty key if number is not valid sensed object) +Returns the key of detected object's owner (returns empty key if number is not a valid sensed object) integer llDetectedType(integer number) -returns the type (AGENT, ACTIVE, PASSIVE, SCRIPTED) of detected object (returns 0 if number is not valid sensed object) +Returns the type (AGENT, ACTIVE, PASSIVE, SCRIPTED) of detected object (returns 0 if number is not a valid sensed object) vector llDetectedPos(integer number) -returns the position of detected object number (returns <0,0,0> if number is not valid sensed object) +Returns the position of detected object number (returns <0,0,0> if number is not a valid sensed object) vector llDetectedVel(integer number) -returns the velocity of detected object number (returns <0,0,0> if number is not valid sensed object) +Returns the velocity of detected object number (returns <0,0,0> if number is not a valid sensed object) vector llDetectedGrab(integer number) -returns the grab offset of the user touching object (returns <0,0,0> if number is not valid sensed object) +Returns the grab offset of the user touching object (returns <0,0,0> if number is not a valid sensed object) rotation llDetectedRot(integer number) -returns the rotation of detected object number (returns <0,0,0,1> if number is not valid sensed object) +Returns the rotation of detected object number (returns <0,0,0,1> if number is not a valid sensed object) integer llDetectedGroup(integer number) @@ -464,127 +467,127 @@ Returns TRUE if detected object is part of same group as owner integer llDetectedLinkNumber(integer number) -returns the link position of the triggered event for touches and collisions only +Returns the link position of the triggered event for touches and collisions only llDie() -deletes the object +Deletes the object -float llGround(vector v) -returns the ground height below the object position + v +float llGround(vector offset) +Returns the ground height below the object position + offset -float llCloud(vector v) -returns the cloud density at the object position + v +float llCloud(vector offset) +Returns the cloud density at the object position + offset -vector llWind(vector v) -returns the wind velocity at the object position + v +vector llWind(vector offset) +Returns the wind velocity at the object position + offset llSetStatus(integer status, integer value) -sets status (STATUS_PHYSICS, STATUS_PHANTOM, STATUS_BLOCK_GRAB, STATUS_ROTATE_X, STATUS_ROTATE_Y, and/or STATUS_ROTATE_Z) to value +Sets status (STATUS_PHYSICS, STATUS_PHANTOM, STATUS_BLOCK_GRAB, STATUS_ROTATE_X, STATUS_ROTATE_Y, and/or STATUS_ROTATE_Z) to value integer llGetStatus(integer status) -gets value of status (STATUS_PHYSICS, STATUS_PHANTOM, STATUS_BLOCK_GRAB, STATUS_ROTATE_X, STATUS_ROTATE_Y, and/or STATUS_ROTATE_Z) +Returns value of status (STATUS_PHYSICS, STATUS_PHANTOM, STATUS_BLOCK_GRAB, STATUS_ROTATE_X, STATUS_ROTATE_Y, and/or STATUS_ROTATE_Z) llSetScale(vector scale) -sets the scale +Sets the scale of the prim vector llGetScale() -gets the scale +Returns the scale of the prim llSetColor(vector color, integer face) -sets the color +Sets the color on face of the prim float llGetAlpha(integer face) -gets the alpha +Returns the alpha of face llSetAlpha(float alpha, integer face) -sets the alpha +Sets the alpha on face vector llGetColor(integer face) -gets the color +Returns the color on face llSetTexture(string texture, integer face) -sets the texture of face +Sets the texture of face or ALL_SIDES -llScaleTexture(float scales, float scalet, integer face) -sets the texture s, t scales for the chosen face +llScaleTexture(float u, float v, integer face) +Sets the texture u & v scales for the chosen face or ALL_SIDES -llOffsetTexture(float offsets, float offsett, integer face) -sets the texture s, t offsets for the chosen face +llOffsetTexture(float u, float v, integer face) +Sets the texture u & v offsets for the chosen face or ALL_SIDES llRotateTexture(float rotation, integer face) -sets the texture rotation for the chosen face +Sets the texture rotation for the chosen face string llGetTexture(integer face) -gets the texture of face (if it's a texture in the object inventory, otherwise the key in a string) +Returns a string that is the texture on face (the inventory name if it is a texture in the prim's inventory, otherwise the key) llSetPos(vector pos) -sets the position (if the script isn't physical) +Moves the object or prim towards pos without using physics (if the script isn't physical) vector llGetPos() -gets the position (if the script isn't physical) +Returns the position of the task in region coordinates vector llGetLocalPos() -gets the position relative to the root (if the script isn't physical) +Returns the position relative to the root llSetRot(rotation rot) -sets the rotation (if the script isn't physical) +Sets the rotation rotation llGetRot() -gets the rotation (if the script isn't physical) +Returns the rotation relative to the region's axes rotation llGetLocalRot() -gets the rotation local to the root (if the script isn't physical) +Returns the rotation local to the root llSetForce(vector force, integer local) -sets force on object, in local coords if local == TRUE (if the script is physical) +Applies force to the object (if the script is physical), in local coords if local == TRUE vector llGetForce() -gets the force (if the script is physical) +Returns the force (if the script is physical) integer llTarget(vector position, float range) -set positions within range of position as a target and return an ID for the target +Sets positions within range of position as a target and return an ID for the target llTargetRemove(integer number) -removes target number +Removes positional target number registered with llTarget integer llRotTarget(rotation rot, float error) -set rotations with error of rot as a rotational target and return an ID for the rotational target +Set rotations with error of rot as a rotational target and return an ID for the rotational target llRotTargetRemove(integer number) -removes rotational target number +Removes rotational target number registered with llRotTarget llMoveToTarget(vector target, float tau) -critically damp to target in tau seconds (if the script is physical) +Critically damps to target in tau seconds (if the script is physical) llStopMoveToTarget() @@ -592,83 +595,83 @@ Stops critically damped motion llApplyImpulse(vector force, integer local) -applies impulse to object, in local coords if local == TRUE (if the script is physical) +Applies impulse to object (if the script is physical), in local coords if local == TRUE llApplyRotationalImpulse(vector force, integer local) -applies rotational impulse to object, in local coords if local == TRUE (if the script is physical) +Applies rotational impulse to object (if the script is physical), in local coords if local == TRUE llSetTorque(vector torque, integer local) -sets the torque of object, in local coords if local == TRUE (if the script is physical) +Sets the torque of object (if the script is physical), in local coords if local == TRUE vector llGetTorque() -gets the torque (if the script is physical) +Returns the torque (if the script is physical) llSetForceAndTorque(vector force, vector torque, integer local) -sets the force and torque of object, in local coords if local == TRUE (if the script is physical) +Sets the force and torque of object (if the script is physical), in local coords if local == TRUE vector llGetVel() -gets the velocity +Returns the velocity of the object vector llGetAccel() -gets the acceleration +Returns the acceleration of the object relative to the region's axes vector llGetOmega() -gets the omega +Returns the rotation velocity in radians per second float llGetTimeOfDay() -gets the time in seconds since [SECOND_LIFE] server midnight (or since server up-time; whichever is smaller) +Returns the time in seconds since [SECOND_LIFE] server midnight or since region up-time, whichever is smaller float llGetWallclock() -gets the time in seconds since midnight +Returns the time in seconds since midnight California Pacific time (PST/PDT) float llGetTime() -gets the time in seconds since creation +Returns the time in seconds since the last region reset, script reset, or call to either llResetTime or llGetAndResetTime llResetTime() -sets the time to zero +Sets the script timer to zero float llGetAndResetTime() -gets the time in seconds since creation and sets the time to zero +Returns the script time in seconds and then resets the script timer to zero llSound(string sound, float volume, integer queue, integer loop) -plays sound at volume and whether it should loop or not +Plays sound at volume and whether it should loop or not llPlaySound(string sound, float volume) -plays attached sound once at volume (0.0 - 1.0) +Plays attached sound once at volume (0.0 - 1.0) llLoopSound(string sound, float volume) -plays attached sound looping indefinitely at volume (0.0 - 1.0) +Plays attached sound looping indefinitely at volume (0.0 - 1.0) llLoopSoundMaster(string sound, float volume) -plays attached sound looping at volume (0.0 - 1.0), declares it a sync master +Plays attached sound looping at volume (0.0 - 1.0), declares it a sync master llLoopSoundSlave(string sound, float volume) -plays attached sound looping at volume (0.0 - 1.0), synced to most audible sync master +Plays attached sound looping at volume (0.0 - 1.0), synced to most audible sync master llPlaySoundSlave(string sound, float volume) -plays attached sound once at volume (0.0 - 1.0), synced to next loop of most audible sync master +Plays attached sound once at volume (0.0 - 1.0), synced to next loop of most audible sync master llTriggerSound(string sound, float volume) -plays sound at volume (0.0 - 1.0), centered at but not attached to object +Plays sound at volume (0.0 - 1.0), centered at but not attached to object llStopSound() @@ -676,143 +679,143 @@ Stops currently attached sound llPreloadSound(string sound) -preloads a sound on viewers within range +Preloads a sound on viewers within range string llGetSubString(string src, integer start, integer end) -returns the indicated substring +Returns the indicated substring string llDeleteSubString(string src, integer start, integer end) -removes the indicated substring and returns the result +Removes the indicated substring and returns the result string llInsertString(string dst, integer position, string src) -inserts src into dst at position and returns the result +Returns a destination string dst with the string src inserted starting at position pos string llToUpper(string src) -convert src to all upper case and returns the result +Returns a string that is src with all upper-case characters string llToLower(string src) -convert src to all lower case and returns the result +Returns a string that is src with all lower-case characters llGiveMoney(key destination, integer amount) -transfer amount of money from script owner to destination +Transfers amount of L$ from script owner to destination llMakeExplosion(integer particles, float scale, float vel, float lifetime, float arc, string texture, vector offset) -Make a round explosion of particles +Makes a round explosion of particles llMakeFountain(integer particles, float scale, float vel, float lifetime, float arc, integer bounce, string texture, vector offset, float bounce_offset) -Make a fountain of particles +Makes a fountain of particles llMakeSmoke(integer particles, float scale, float vel, float lifetime, float arc, string texture, vector offset) -Make smoke like particles +Makes smoke like particles llMakeFire(integer particles, float scale, float vel, float lifetime, float arc, string texture, vector offset) -Make fire like particles +Makes fire like particles llRezObject(string inventory, vector pos, vector vel, rotation rot, integer param) -Instanciate owners inventory object at pos with velocity vel and rotation rot with start parameter param +Instantiates owner's inventory object at pos with velocity vel and rotation rot with start parameter param -llLookAt(vector target, F32 strength, F32 damping) -Cause object name to point it's forward axis towards target +llLookAt(vector target, float strength, float damping) +Causes object to point its up axis (positive z) towards target, while keeping its forward axis (positive x) below the horizon llStopLookAt() -Stop causing object name to point at a target +Stops causing object to point at a target llSetTimerEvent(float sec) -Cause the timer event to be triggered every sec seconds +Causes the timer event to be triggered a maximum of once every sec seconds llSleep(float sec) -Put script to sleep for sec seconds +Puts the script to sleep for sec seconds float llGetMass() -Get the mass of task name that script is attached to +Returns the mass of object that the script is attached to llCollisionFilter(string name, key id, integer accept) -if accept == TRUE, only accept collisions with objects name and id (either is optional), otherwise with objects not name or id +Sets the collision filter, exclusively or inclusively. If accept == TRUE, only accept collisions with objects name and id (either is optional), otherwise with objects not name or id llTakeControls(integer controls, integer accept, integer pass_on) -Take controls from agent task has permissions for. If (accept == (controls & input)), send input to task. If pass_on send to agent also. +Allows for intercepting keyboard and mouse clicks from the agent the script has permissions for llReleaseControls() -Stop taking inputs +Stops taking inputs that were taken with llTakeControls -llAttachToAvatar(integer attachment) -Attach to avatar task has permissions for at point attachment +llAttachToAvatar(integer attach_point) +Attaches the object to the avatar who has granted permission to the script llDetachFromAvatar() -Drop off of avatar +Detaches object from avatar llTakeCamera(key avatar) -Move avatar's viewpoint to task +Moves avatar's viewpoint to task llReleaseCamera(key avatar) -Return camera to agent +Returns camera to agent avatar key llGetOwner() -Returns the owner of the task +Returns the object owner's UUID llInstantMessage(key user, string message) -IMs message to the user +Sends the specified string as an Instant Message to the user llEmail(string address, string subject, string message) -Sends email to address with subject and message +Sends an email to address with the subject and message llGetNextEmail(string address, string subject) -Get the next waiting email with appropriate address and/or subject (if blank they are ignored) +Gets the next waiting email that comes from address, with specified subject key llGetKey() -Get the key for the task the script is attached to +Returns the key of the prim the script is attached to llSetBuoyancy(float buoyancy) -Set the tasks buoyancy (0 is none, < 1.0 sinks, 1.0 floats, > 1.0 rises) +Sets the buoyancy of the task or object (0 is disabled, < 1.0 sinks, 1.0 floats, > 1.0 rises) llSetHoverHeight(float height, integer water, float tau) -Critically damps to a height (either above ground level or above the higher of land and water if water == TRUE) +Critically damps to a height above the ground (or water) in tau seconds llStopHover() -Stop hovering to a height +Stops hovering to a height llMinEventDelay(float delay) -Set the minimum time between events being handled +Sets the minimum time between events being handled llSoundPreload(string sound) -preloads a sound on viewers within range +Preloads a sound on viewers within range -llRotLookAt(rotation target, F32 strength, F32 damping) -Cause object name to point it's forward axis towards target +llRotLookAt(rotation target, float strength, float damping) +Causes object name to point its forward axis towards target integer llStringLength(string str) @@ -820,84 +823,83 @@ Returns the length of string llStartAnimation(string anim) -Start animation anim for agent that owns object +Starts animation anim for agent that granted PERMISSION_TRIGGER_ANIMATION if the permission has not been revoked llStopAnimation(string anim) -Stop animation anim for agent that owns object +Stops animation anim for agent that granted permission llPointAt(vector pos) -Make agent that owns object point at pos +Makes agent that owns object point at pos llStopPointAt() -Stop agent that owns object pointing +Stops pointing agent that owns object llTargetOmega(vector axis, float spinrate, float gain) -Attempt to spin at spinrate with strength gain +Rotates the object around axis at spinrate with strength gain integer llGetStartParameter() -Get's the start paramter passed to llRezObject +Returns an integer that is the script start/rez parameter llGodLikeRezObject(key inventory, vector pos) -rez directly off of a UUID if owner has dog-bit set +Rezzes directly off of UUID if owner is in God Mode llRequestPermissions(key agent, integer perm) -ask agent to allow the script to do perm (NB: Debit, ownership, link, joint, and permission requests can only go to the task's owner) +Asks the agent for permission to run certain classes of functions key llGetPermissionsKey() -Return agent that permissions are enabled for. NULL_KEY if not enabled +Returns the key of the avatar that last granted permissions to the script integer llGetPermissions() -return what permissions have been enabled +Returns an integer bitfield with the permissions that have been granted integer llGetLinkNumber() -Returns what number in a link set the script is attached to (0 means no link, 1 the root, 2 for first child, etc) +Returns the link number of the prim containing the script (0 means not linked, 1 the prim is the root, 2 the prim is the first child, etc) llSetLinkColor(integer linknumber, vector color, integer face) -If a task exists in the link chain at linknumber, set face to color +Sets face to color if a task exists in the link chain at linknumber llCreateLink(key target, integer parent) -Attempt to link task script is attached to and target (requires permission PERMISSION_CHANGE_LINKS be set). If parent == TRUE, task script is attached to is the root +Attempts to link the script's object with the target (requires that PERMISSION_CHANGE_LINKS be granted). If parent == TRUE, then the script's object becomes the root llBreakLink(integer linknum) -Delinks the task with the given link number (requires permission PERMISSION_CHANGE_LINKS be set) +Delinks the prim with the given link number in a linked object set (requires that PERMISSION_CHANGE_LINKS be granted) llBreakAllLinks() -Delinks all tasks in the link set (requires permission PERMISSION_CHANGE_LINKS be set) +Delinks all prims in the link set (requires that PERMISSION_CHANGE_LINKS be granted) -key llGetLinkKey(integer linknum) -Get the key of linknumber in link set +key llGetLinkKey(integer linknumber) +Returns the key of the linked prim linknumber -string llGetLinkName(integer linknum) -Get the name of linknumber in link set +string llGetLinkName(integer linknumber) +Returns the name of linknumber in a link set integer llGetInventoryNumber(integer type) -Get the number of items of a given type in the task's inventory. -Valid types: INVENTORY_TEXTURE, INVENTORY_SOUND, INVENTORY_OBJECT, INVENTORY_SCRIPT, INVENTORY_CLOTHING, INVENTORY_BODYPART, INVENTORY_NOTECARD, INVENTORY_LANDMARK, INVENTORY_ALL +Returns the number of items of a given type (INVENTORY_* flag) in the prim's inventory string llGetInventoryName(integer type, integer number) -Get the name of the inventory item number of type +Returns the name of the inventory item number of a given type llSetScriptState(string name, integer run) -Control the state of a script name. +Sets the running state of the specified script float llGetEnergy() @@ -905,56 +907,55 @@ Returns how much energy is in the object as a percentage of maximum llGiveInventory(key destination, string inventory) -Give inventory to destination +Gives inventory to destination -llRemoveInventory(string inventory) -Remove the named inventory item +llRemoveInventory(string item) +Removes the named inventory item llSetText(string text, vector color, float alpha) -Set text floating over object +Displays text that hovers over the prim with specific color and translucency specified with alpha -float llWater(vector v) -returns the water height below the object position + v +float llWater(vector offset) +Returns the water height below the object position + offset llPassTouches(integer pass) -if pass == TRUE, touches are passed from children on to parents (default is FALSE) +If pass == TRUE, touches are passed from children on to parents key llRequestAgentData(key id, integer data) -Requests data about agent id. When data is available the dataserver event will be raised +Requests data about agent id. When data is available the dataserver event will be raised. key llRequestInventoryData(string name) -Requests data from object's inventory object. When data is available the dataserver event will be raised +Requests data from object's inventory object. When data is available the dataserver event will be raised. llSetDamage(float damage) -Sets the amount of damage that will be done to an object that this task hits. Task will be killed. +Sets the amount of damage that will be done when this object hits an avatar. llTeleportAgentHome(key id) -Teleports agent on owner's land to agent's home location +Teleports avatar on the owner's land to their home location without any warning -llModifyLand(integer action, integer size) -Modify land with action (LAND_LEVEL, LAND_RAISE, LAND_LOWER, LAND_SMOOTH, LAND_NOISE, LAND_REVERT) -on size (LAND_SMALL_BRUSH, LAND_MEDIUM_BRUSH, LAND_LARGE_BRUSH) +llModifyLand(integer action, integer brush) +Modifies land using the specified action on the specified brush size of land llCollisionSound(string impact_sound, float impact_volume) -Suppress default collision sounds, replace default impact sounds with impact_sound (empty string to just suppress) +Suppresses default collision sounds, replaces default impact sounds with impact_sound at the volume impact_volume llCollisionSprite(string impact_sprite) -Suppress default collision sprites, replace default impact sprite with impact_sprite (empty string to just suppress) +Suppresses default collision sprites, replaces default impact sprite with impact_sprite (use an empty string to just suppress) string llGetAnimation(key id) -Get the currently playing locomotion animation for avatar id +Returns the name of the currently playing locomotion animation for avatar id llResetScript() @@ -962,12 +963,7 @@ Resets the script llMessageLinked(integer linknum, integer num, string str, key id) -Sends num, str, and id to members of the link set -(LINK_ROOT sends to root task in a linked set, -LINK_SET sends to all tasks, -LINK_ALL_OTHERS to all other tasks, -LINK_ALL_CHILDREN to all children, -LINK_THIS to the task the script it is in) +Allows scripts in the same object to communicate. Triggers a link_message event with the same parameters num, str, and id in all scripts in the prim(s) described by linknum. llPushObject(key id, vector impulse, vector ang_impulse, integer local) @@ -975,19 +971,19 @@ Applies impulse and ang_impulse to object id llPassCollisions(integer pass) -if pass == TRUE, collisions are passed from children on to parents (default is FALSE) +If pass == TRUE, collisions are passed from children on to parents (default is FALSE) -llGetScriptName() -Returns the script name +string llGetScriptName() +Returns the name of the script that this function is used in integer llGetNumberOfSides() -Returns the number of sides +Returns the number of faces (or sides) of the prim rotation llAxisAngle2Rot(vector axis, float angle) -Returns the rotation generated angle about axis +Returns the rotation that is a generated angle about axis vector llRot2Axis(rotation rot) @@ -1011,19 +1007,19 @@ Returns angle between rotation a and b key llGetInventoryKey(string name) -Returns the key of the inventory name +Returns the key that is the UUID of the inventory name llAllowInventoryDrop(integer add) -If add == TRUE, users without permissions can still drop inventory items onto task +If add == TRUE, users without modify permissions can still drop inventory items onto a prim vector llGetSunDirection() -Returns the sun direction on the simulator +Returns a normalized vector of the direction of the sun in the region -vector llGetTextureOffset(integer side) -Returns the texture offset of side in the x and y components of a vector +vector llGetTextureOffset(integer face) +Returns the texture offset of face in the x and y components of a vector vector llGetTextureScale(integer side) @@ -1035,55 +1031,57 @@ Returns the texture rotation of side integer llSubStringIndex(string source, string pattern) -Finds index in source where pattern first appears (returns -1 if not found) +Returns an integer that is the index in source where pattern first appears. +(Returns -1 if not found) key llGetOwnerKey(key id) -Find the owner of id +Returns the owner of object id vector llGetCenterOfMass() -Get the object's center of mass +Returns the prim's center of mass (unless called from the root prim, where it returns the object's center of mass) list llListSort(list src, integer stride, integer ascending) -Sort the list into blocks of stride in ascending order if ascending == TRUE. Note that sort only works between same types. +Sorts the list into blocks of stride, in ascending order if ascending == TRUE. +The sort order is affected by type. integer llGetListLength(list src) -Get the number of elements in the list +Returns the number of elements in the list integer llList2Integer(list src, integer index) -Copy the integer at index in the list +Copies the integer at index in the list float llList2Float(list src, integer index) -Copy the float at index in the list +Copies the float at index in the list string llList2String(list src, integer index) -Copy the string at index in the list +Copies the string at index in the list key llList2Key(list src, integer index) -Copy the key at index in the list +Copies the key at index in the list vector llList2Vector(list src, integer index) -Copy the vector at index in the list +Copies the vector at index in the list rotation llList2Rot(list src, integer index) -Copy the rotation at index in the list +Copies the rotation at index in the list list llList2List(list src, integer start, integer end) -Copy the slice of the list from start to end +Copies the slice of the list from start to end list llDeleteSubList(list src, integer start, integer end) -Remove the slice from the list and return the remainder +Removes the slice from start to end and returns the remainder of the list integer llGetListEntryType(list src, integer index) @@ -1092,11 +1090,11 @@ Returns the type of the index entry in the list string llList2CSV(list src) -Create a string of comma separated values from list +Creates a string of comma separated values from list list llCSV2List(string src) -Create a list from a string of comma separated values +Creates a list from a string of comma separated values list llListRandomize(list src, integer stride) @@ -1104,80 +1102,83 @@ Returns a randomized list of blocks of size stride list llList2ListStrided(list src, integer start, integer end, integer stride) -Copy the strided slice of the list from start to end +Copies the strided slice of the list from start to end vector llGetRegionCorner() -Returns a vector with the south west corner x,y position of the region the object is in +Returns a vector in meters that is the global location of the south-west corner of the region which the object is in list llListInsertList(list dest, list src, integer start) -Inserts src into dest at position start +Returns a list that contains all the elements from dest but with the elements from src inserted at position start integer llListFindList(list src, list test) -Returns the start of the first instance of test in src, -1 if not found +Returns the index of the first instance of test in src. +(Returns -1 if not found) string llGetObjectName() -Returns the name of the object script is attached to +Returns the name of the prim which the script is attached to llSetObjectName(string name) -Sets the objects name +Sets the prim's name to the name parameter string llGetDate() -Gets the date as YYYY-MM-DD +Returns the current date in the UTC time zone in the format YYYY-MM-DD integer llEdgeOfWorld(vector pos, vector dir) -Checks to see whether the border hit by dir from pos is the edge of the world (has no neighboring simulator) +Checks to see whether the border hit by dir from pos is the edge of the world (has no neighboring region) integer llGetAgentInfo(key id) -Gets information about agent ID. -Returns AGENT_FLYING, AGENT_ATTACHMENTS, AGENT_SCRIPTED, AGENT_SITTING, AGENT_ON_OBJECT, AGENT_MOUSELOOK, AGENT_AWAY, AGENT_BUSY, AGENT_TYPING, AGENT_CROUCHING, AGENT_ALWAYS_RUN, AGENT_WALKING, AGENT_IN_AIR and/or AGENT_AUTOPILOT. +Returns an integer bitfield containing the agent information about id. +Returns AGENT_FLYING, AGENT_ATTACHMENTS, AGENT_SCRIPTED, AGENT_SITTING, AGENT_ON_OBJECT, AGENT_MOUSELOOK, AGENT_AWAY, AGENT_BUSY, AGENT_TYPING, AGENT_CROUCHING, AGENT_ALWAYS_RUN, AGENT_WALKING and/or AGENT_IN_AIR. llAdjustSoundVolume(float volume) -adjusts volume of attached sound (0.0 - 1.0) +Adjusts volume of attached sound (0.0 - 1.0) llSetSoundQueueing(integer queue) -determines whether attached sound calls wait for the current sound to finish (0 = no [default], nonzero = yes) +Sets whether attached sounds wait for the current sound to finish (If queue == TRUE then queuing is enabled, if FALSE queuing is disabled [default]) llSetSoundRadius(float radius) -establishes a hard cut-off radius for audibility of scripted sounds (both attached and triggered) +Establishes a hard cut-off radius for audibility of scripted sounds (both attached and triggered) string llKey2Name(key id) -Returns the name of the object key, iff the object is in the current simulator, otherwise the empty string +Returns the name of the prim or avatar specified by id. +(The id must be a valid rezzed prim or avatar key in the current simulator, otherwise an empty string is returned.) llSetTextureAnim(integer mode, integer face, integer sizex, integer sizey, float start, float length, float rate) -Animate the texture on the specified face/faces +Animates the texture on the specified face/faces -llTriggerSoundLimited(string sound, float volume, vector tne, vector bsw) -plays sound at volume (0.0 - 1.0), centered at but not attached to object, limited to AABB defined by vectors top-north-east and bottom-south-west +llTriggerSoundLimited(string sound, float volume, vector top_north_east, vector bottom_south_west) +Plays sound at volume (0.0 - 1.0), centered at but not attached to object, limited to the box defined by vectors top_north_east and bottom_south_west -llEjectFromLand(key pest) -Ejects pest from land that you own +llEjectFromLand(key avatar) +Ejects avatar from the parcel list llParseString2List(string src, list separators, list spacers) -Breaks src into a list, discarding separators, keeping spacers (separators and spacers must be lists of strings, maximum of 8 each) +Breaks src into a list, discarding separators, keeping spacers +(separators and spacers must be lists of strings, maximum of 8 each) integer llOverMyLand(key id) -Returns TRUE if id is over land owner of object owns, FALSE otherwise +Returns TRUE if id is over land owned by the script owner, otherwise FALSE key llGetLandOwnerAt(vector pos) -Returns the key of the land owner, NULL_KEY if public +Returns the key of the land owner, returns NULL_KEY if public key llGetNotecardLine(string name, integer line) @@ -1185,131 +1186,130 @@ Returns line line of notecard name via the dataserver event vector llGetAgentSize(key id) -If the agent is in the same sim as the object, returns the size of the avatar +If the avatar is in the same region, returns the size of the bounding box of the requested avatar by id, otherwise returns ZERO_VECTOR integer llSameGroup(key id) -Returns TRUE if ID is in the same sim and has the same active group, otherwise FALSE +Returns TRUE if avatar id is in the same region and has the same active group, otherwise FALSE key llUnSit(key id) -If agent identified by id is sitting on the object the script is attached to or is over land owned by the objects owner, the agent is forced to stand up +If avatar identified by id is sitting on the object the script is attached to or is over land owned by the object's owner, the avatar is forced to stand up -vector llGroundSlope(vector v) -returns the ground slope below the object position + v +vector llGroundSlope(vector offset) +Returns the ground slope below the object position + offset -vector llGroundNormal(vector v) -returns the ground normal below the object position + v +vector llGroundNormal(vector offset) +Returns the ground normal below the object position + offset -vector llGroundCountour(vector v) -returns the ground contour below the object position + v +vector llGroundCountour(vector offset) +Returns the ground contour direction below the object position + offset integer llGetAttached() -returns the object attachment point or 0 if not attached +Returns the object's attachment point, or 0 if not attached integer llGetFreeMemory() -returns the available heap space for the current script +Returns the number of free bytes of memory the script can use string llGetRegionName() -returns the current region name +Returns the current region name float llGetRegionTimeDilation() -returns the current time dilation as a float between 0 and 1 +Returns the current time dilation as a float between 0.0 (full dilation) and 1.0 (no dilation) float llGetRegionFPS() -returns the mean region frames per second +Returns the mean region frames per second llParticleSystem(list rules) -Creates a particle system based on rules. Empty list removes particle system from object. +Creates a particle system based on rules. An empty list removes the particle system. List format is [ rule1, data1, rule2, data2 . . . rulen, datan ] llGroundRepel(float height, integer water, float tau) -Critically damps to height if within height*0.5 of level (either above ground level or above the higher of land and water if water == TRUE) +Critically damps to height if within height*0.5 of level (either above ground level, or above the higher of land and water if water == TRUE) -llGiveInventoryList(key destination, string category, list inventory) -Give inventory to destination in a new category +llGiveInventoryList(key target, string folder, list inventory) +Gives inventory items to target, creating a new folder to put them in llSetVehicleType(integer type) -sets vehicle to one of the default types +Sets the vehicle to one of the default types llSetVehicleFloatParam(integer param, float value) -sets the specified vehicle float parameter +Sets the specified vehicle float parameter llSetVehicleVectorParam(integer param, vector vec) -sets the specified vehicle vector parameter +Sets the specified vehicle vector parameter llSetVehicleVectorParam(integer param, rotation rot) -sets the specified vehicle rotation parameter +Sets the specified vehicle rotation parameter llSetVehicleFlags(integer flags) -sets the enabled bits in 'flags' +Sets the enabled bits in 'flags' llRemoveVehicleFlags(integer flags) -removes the enabled bits in 'flags' +Removes the enabled bits in 'flags' llSitTarget(vector offset, rotation rot) -Set the sit location for this object (if offset == <0,0,0> clear it) +Sets the sit location for the prim. If offset == <0,0,0> then the sit target is removed. key llAvatarOnSitTarget() -If an avatar is sitting on the sit target, return the avatar's key, NULL_KEY otherwise +If an avatar is seated on the sit target, returns the avatar's key, otherwise NULL_KEY llAddToLandPassList(key avatar, float hours) -Add avatar to the land pass list for hours +Adds avatar to the land pass list for hours, or indefinitely if hours is 0 llSetTouchText(string text) -Displays text in pie menu that acts as a touch +Displays text rather than the default 'Touch' in the pie menu llSetSitText(string text) -Displays text rather than sit in pie menu +Displays text rather than the default 'Sit Here' in the pie menu llSetCameraEyeOffset(vector offset) -Sets the camera eye offset used in this object if an avatar sits on it +Sets the camera eye offset for avatars that sit on the object llSetCameraAtOffset(vector offset) -Sets the camera at offset used in this object if an avatar sits on it +Sets the point the camera is looking at to offset for avatars that sit on the object string llDumpList2String(list src, string separator) -Write the list out in a single string using separator between values +Returns the list in a single string, using separator between the entries integer llScriptDanger(vector pos) -Returns true if pos is over public land, sandbox land, land that doesn't allow everyone to edit and build, or land that doesn't allow outside scripts +Returns TRUE if pos is over public land, sandbox land, land that doesn't allow everyone to edit and build, or land that doesn't allow outside scripts llDialog(key avatar, string message, list buttons, integer chat_channel -Shows a dialog box on the avatar's screen with the message. -Up to 12 strings in the list form buttons. -If a button is clicked, the name is chatted on chat_channel. +Shows a dialog box on the avatar's screen with a message and up to 12 buttons. +If a button is pressed, the avatar says the text of the button label on chat_channel. llVolumeDetect(integer detect) -If detect = TRUE, object becomes phantom but triggers collision_start and collision_end events when other objects start and stop interpenetrating. -Must be applied to the root object. +If detect = TRUE, object works much like Phantom, but triggers collision_start and collision_end events when other objects start and stop interpenetrating. +Must be applied to the root prim. llResetOtherScript(string name) @@ -1317,110 +1317,107 @@ Resets script name integer llGetScriptState(string name) -Resets TRUE if script name is running +Returns TRUE if the script name is running -Deprecated. Please use llRemoteLoadScriptPin instead. +DEPRECATED! Please use llRemoteLoadScriptPin instead. llSetRemoteScriptAccessPin(integer pin) -If pin is set to a non-zero number, the task will accept remote script loads via llRemoteLoadScriptPin if it passes in the correct pin. -Othersise, llRemoteLoadScriptPin is ignored. +If pin is set to a non-zero number, allows a prim to have scripts remotely loaded via llRemoteLoadScriptPin when it passes in the correct pin. Otherwise, llRemoteLoadScriptPin is ignored. llRemoteLoadScriptPin(key target, string name, integer pin, integer running, integer start_param) -If the owner of the object this script is attached can modify target, -they are in the same region, and the matching pin is used, -copy script name onto target, -if running == TRUE, start the script with param. +Copies script name onto target, if the owner of this scripted object can modify target and is in the same region, and the matching pin is used. +If running == TRUE, starts the script with start_param llOpenRemoteDataChannel() -Creates a channel to listen for XML-RPC calls. Will trigger a remote_data event with channel id once it is available. +Creates a channel to listen for XML-RPC calls, and will trigger a remote_data event with channel id once it is available key llSendRemoteData(key channel, string dest, integer idata, string sdata) -Send an XML-RPC request to dest through channel with payload of channel (in a string), integer idata and string sdata. -A message identifier key is returned. -An XML-RPC reply will trigger a remote_data event and reference the message id. -The message_id is returned. +Sends an XML-RPC request to dest through channel with payload of channel (in a string), integer idata and string sdata. +Returns a key that is the message_id for the resulting remote_data events. llRemoteDataReply(key channel, key message_id, string sdata, integer idata) -Send an XML-RPC reply to message_id on channel with payload of string sdata and integer idata +Sends an XML-RPC reply to message_id on channel with payload of string sdata and integer idata llCloseRemoteDataChannel(key channel) -Closes XML-RPC channel. +Closes XML-RPC channel string llMD5String(string src, integer nonce) -Performs a RSA Data Security, Inc. MD5 Message-Digest Algorithm on string with nonce. Returns a 32 character hex string. +Returns a string of 32 hex characters that is a RSA Data Security, Inc. MD5 Message-Digest Algorithm of src with nonce llSetPrimitiveParams(list rules) -Set primitive parameters based on rules. +Sets the prim's parameters according to rules string llStringToBase64(string str) -Converts a string to the Base 64 representation of the string. +Converts a string to the Base64 representation of the string string llBase64ToString(string str) -Converts a Base 64 string to a conventional string. If the conversion creates any unprintable characters, they are converted to spaces. +Converts a Base64 string to a conventional string. +If the conversion creates any unprintable characters, they are converted to spaces. string llXorBase64Strings(string s1, string s2) -DEPRECATED! Please use llXorBase64StringsCorrect instead!! Incorrectly performs an exclusive or on two Base 64 strings and returns a Base 64 string. s2 repeats if it is shorter than s1. Retained for backwards compatability. +DEPRECATED! Please use llXorBase64StringsCorrect instead. +Incorrectly performs an exclusive or on two Base64 strings and returns a Base64 string. s2 repeats if it is shorter than s1. Retained for backwards compatability. llRemoteDataSetRegion() -If an object using remote data channels changes regions, you must call this function to reregister the remote data channels. -You do not need to make this call if you don't change regions. +DEPRECATED! Please use llOpenRemoteDataChannel instead. +If an object using remote data channels changes regions, you must call this function to reregister the remote data channels. This call is not needed if the prim does not change regions. float llLog10(float val) -Returns the base 10 log of val if val > 0, otherwise returns 0. +Returns the base 10 logarithm of val. Returns zero if val <= 0. float llLog(float val) -Returns the base e log of val if val > 0, otherwise returns 0. +Returns the natural logarithm of val. Returns zero if val <= 0. list llGetAnimationList(key id) -Gets a list of all playing animations for avatar id +Returns a list of keys of playing animations for avatar described by id llSetParcelMusicURL(string url) -Sets the streaming audio URL for the parcel object is on +Sets the streaming audio URL for the parcel which the object is on vector llGetRootPosition() -Gets the global position of the root object of the object script is attached to +Returns the position (in region coordinates) of the root prim of the object which the script is attached to rotation llGetRootRotation() -Gets the global rotation of the root object of the object script is attached to +Returns the rotation (relative to the region) of the root prim of the object which the script is attached to string llGetObjectDesc() -Returns the description of the object the script is attached to +Returns the description of the prim the script is attached to llSetObjectDesc(string name) -Sets the object's description +Sets the prim's description key llGetCreator() -Returns the creator of the object +Returns a key for the creator of the prim string llGetTimestamp() -Gets the timestamp in the format: YYYY-MM-DDThh:mm:ss.ff..fZ +Returns the timestamp in the UTC time zone in the format: YYYY-MM-DDThh:mm:ss.ff..fZ llSetLinkAlpha(integer linknumber, float alpha, integer face) -If a prim exists in the link chain at linknumber, set face to alpha +If a prim exists in the link chain at linknumber, sets face to alpha integer llGetNumberOfPrims() @@ -1428,11 +1425,11 @@ Returns the number of prims in a link set the script is attached to key llGetNumberOfNotecardLines(string name) -Returns number of lines in notecard 'name' via the dataserver event (cast return value to integer) +Returns number of lines in notecard name via the dataserver event (cast return value to integer) list llGetBoundingBox(key object) -Returns the bounding box around an object (including any linked prims) relative to the root prim, in a list: [ (vector) min_corner, (vector) max_corner ] +Returns the bounding box around the object (including any linked prims) relative to its root prim, in a list in the format [ (vector) min_corner, (vector) max_corner ] vector llGetGeometricCenter() @@ -1440,142 +1437,143 @@ Returns the geometric center of the linked set the script is attached to. list llGetPrimitiveParams(list params) -Gets primitive parameters specified in the params list. +Returns the primitive parameters specified in the params list. string llIntegerToBase64(integer number) -Big endian encode of of integer as a Base64 string. +Returns a string that is a Base64 big endian encode of number integer llBase64ToInteger(string str) -Big endian decode of a Base64 string into an integer. +Returns an integer that is the str Base64 decoded as a big endian integer float llGetGMTclock() -Gets the time in seconds since midnight in GMT +Returns the time in seconds since midnight GMT string llGetSimulatorHostname() -Gets the hostname of the machine script is running on (same as string in viewer Help dialog) +Returns the hostname of the machine which the script is running on (same as string in viewer Help dialog) llSetLocalRot(rotation rot) -sets the rotation of a child prim relative to the root prim +Sets the rotation of a child prim relative to the root prim list llParseStringKeepNulls(string src, list separators, list spacers) -Breaks src into a list, discarding separators, keeping spacers (separators and spacers must be lists of strings, maximum of 8 each), keeping any null values generated. +Breaks src into a list, discarding separators, keeping spacers, keeping any null values generated. +(separators and spacers must be lists of strings, maximum of 8 each) llRezAtRoot(string inventory, vector pos, vector vel, rotation rot, integer param) -Instantiate owner's inventory object at pos with velocity vel and rotation rot with start parameter param. -The last selected root object's location will be set to pos +Instantiates owner's inventory object rotated to rot with its root at pos, moving at vel, using param as the start parameter integer llGetObjectPermMask(integer mask) -Returns the requested permission mask for the root object the task is attached to. +Returns the requested permission mask for the root object the task is attached to llSetObjectPermMask(integer mask, integer value) -Sets the given permission mask to the new value on the root object the task is attached to. +Sets the given permission mask to the new value on the root object the task is attached to integer llGetInventoryPermMask(string item, integer mask) -Returns the requested permission mask for the inventory item. +Returns the requested permission mask for the inventory item llSetInventoryPermMask(string item, integer mask, integer value) -Sets the given permission mask to the new value on the inventory item. +Sets the given permission mask to the new value on the inventory item key llGetInventoryCreator(string item) -Returns the key for the creator of the inventory item. +Returns a key for the creator of the inventory item llOwnerSay(string msg) -says msg to owner only (if owner in sim) +Says msg to owner only. (Owner must be in the same region.) key llRequestSimulatorData(string simulator, integer data) -Requests data about simulator. When data is available the dataserver event will be raised +Requests data about simulator. When data is available the dataserver event will be raised. llForceMouselook(integer mouselook) -If mouselook is TRUE any avatar that sits on this object is forced into mouselook mode +If mouselook is TRUE, any avatar that sits upon the prim will be forced into mouselook mode float llGetObjectMass(key id) -Get the mass of the object with key id +Returns the mass of the avatar or object in the region list llListReplaceList(list dest, list src, integer start, integer end) -Replaces start through end of dest with src. +Returns a list that is dest with start through end removed and src inserted at start -llLoadURL(key avatar_id, string message, string url) -Shows dialog to avatar avatar_id offering to load web page at URL. If user clicks yes, launches their web browser. +llLoadURL(key avatar, string message, string url) +Shows a dialog to avatar offering to load the web page at url with a message. +If user clicks yes, launches the page in their web browser. llParcelMediaCommandList(list command) -Sends a list of commands, some with arguments, to a parcel. +Sends a list of commands, some with arguments, to a parcel to control the playback of movies and other media list llParcelMediaQuery(list query) -Sends a list of queries, returns a list of results. +Returns a list containing results of the sent query integer llModPow(integer a, integer b, integer c) -Returns a raised to the b power, mod c. ( (a**b)%c ). b is capped at 0xFFFF (16 bits). +Returns a raised to the b power, mod c. ( (a**b)%c ) +b is capped at 0xFFFF (16 bits). integer llGetInventoryType(string name) -Returns the type of the inventory name +Returns the type of the inventory item name llSetPayPrice(integer price, list quick_pay_buttons) -Sets the default amount when someone chooses to pay this object. +Sets the default amount on the dialog that appears when someone chooses to pay this prim vector llGetCameraPos() -Gets current camera position for agent task has permissions for. +Returns the current camera position for the agent the task has permissions for rotation llGetCameraRot() -Gets current camera orientation for agent task has permissions for. +Returns the current camera orientation for the agent the task has permissions for llSetPrimURL(string url) -Updates the URL for the web page shown on the sides of the object. +Updates the URL for the web page shown on the sides of the object llRefreshPrimURL() -Reloads the web page shown on the sides of the object. +Reloads the web page shown on the sides of the object string llEscapeURL(string url) -Returns and escaped/encoded version of url, replacing spaces with %20 etc. +Returns an escaped/encoded version of url, replacing spaces with %20 etc. string llUnescapeURL(string url) -Returns and unescaped/unencoded version of url, replacing %20 with spaces etc. +Returns an unescaped/ unencoded version of url, replacing %20 with spaces etc. llMapDestination(string simname, vector pos, vector look_at) -Opens world map centered on region with pos highlighted. +Opens the World Map centered on the region simname with pos highlighted. (NOTE: look_at currently does nothing.) Only works for scripts attached to avatar, or during touch events. -(NOTE: look_at currently does nothing) llAddToLandBanList(key avatar, float hours) -Add avatar to the land ban list for hours +Adds avatar to the land ban list for hours, or indefinitely if hours is 0 llRemoveFromLandPassList(key avatar) -Remove avatar from the land pass list +Removes avatar from the land pass list llRemoveFromLandBanList(key avatar) -Remove avatar from the land ban list +Removes avatar from the land ban list llSetCameraParams(list rules) @@ -1584,155 +1582,156 @@ List format is [ rule1, data1, rule2, data2 . . . rulen, datan ] llClearCameraParams() -Resets all camera parameters to default values and turns off scripted camera control. +Resets all camera parameters to default values and turns off scripted camera control -float llListStatistics(integer operation, list l) -Perform statistical aggregate functions on list l using LIST_STAT_* operations. +float llListStatistics(integer operation, list src) +Performs statistical aggregate functions on list src using LIST_STAT_* operations integer llGetUnixTime() -Get the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC from the system clock. +Returns the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC from the system clock integer llGetParcelFlags(vector pos) -Get the parcel flags (PARCEL_FLAG_*) for the parcel including the point pos. +Returns a mask of the parcel flags (PARCEL_FLAG_*) for the parcel that includes the point pos integer llGetRegionFlags() -Get the region flags (REGION_FLAG_*) for the region the object is in. +Returns the region flags (REGION_FLAG_*) for the region the object is in string llXorBase64StringsCorrect(string s1, string s2) -Correctly performs an exclusive or on two Base 64 strings and returns a Base 64 string. s2 repeats if it is shorter than s1. +Correctly performs an exclusive or on two Base64 strings and returns a Base64 string. +s2 repeats if it is shorter than s1. llHTTPRequest(string url, list parameters, string body) -Send an HTTP request. +Sends an HTTP request to the specified url with the body of the request and parameters llResetLandBanList() -Removes all residents from the land ban list. +Removes all residents from the land ban list llResetLandPassList() -Removes all residents from the land access/pass list. +Removes all residents from the land access/pass list integer llGetObjectPrimCount(key object_id) -Returns the total number of prims for an object. +Returns the total number of prims for an object in the region list llGetParcelPrimOwners(vector pos) -Returns a list of all residents who own objects on the parcel and the number of objects they own. +Returns a list of all residents who own objects on the parcel at pos and with individual prim counts. Requires owner-like permissions for the parcel. integer llGetParcelPrimCount(vector pos, integer category, integer sim_wide) -Gets the number of prims on the parcel of the given category. -Categories: PARCEL_COUNT_TOTAL, _OWNER, _GROUP, _OTHER, _SELECTED, _TEMP. +Returns the number of prims on the parcel at pos of the given category. +Categories: PARCEL_COUNT_TOTAL, _OWNER, _GROUP, _OTHER, _SELECTED, _TEMP integer llGetParcelMaxPrims(vector pos, integer sim_wide) -Gets the maximum number of prims allowed on the parcel at pos. +Returns the maximum number of prims allowed on the parcel at pos list llGetParcelDetails(vector pos, list params) -Gets the parcel details specified in params for the parcel at pos. +Returns the parcel details specified in params for the parcel at pos. Params is one or more of: PARCEL_DETAILS_NAME, _DESC, _OWNER, _GROUP, _AREA llSetLinkPrimitiveParams(integer linknumber, list rules) -Set primitive parameters for linknumber based on rules. +Sets primitive parameters for linknumber based on rules -llSetLinkTexture(integer link_pos, string texture, integer face) -Sets the texture of face for link_pos +llSetLinkTexture(integer linknumber, string texture, integer face) +Sets the texture of face for a task that exists in the link chain at linknumber string llStringTrim(string src, integer trim_type) -Trim leading and/or trailing spaces from a string. -Uses trim_type of STRING_TRIM, STRING_TRIM_HEAD or STRING_TRIM_TAIL. +Trims the leading and/or trailing white spaces from a string. +trim_type can be STRING_TRIM, STRING_TRIM_HEAD or STRING_TRIM_TAIL. llRegionSay(integer channel, string msg) -broadcasts msg to entire region on channel (not 0.) +Broadcasts msg on channel (not 0) that can be heard anywhere in the region by a script listening on channel list llGetObjectDetails(key id, list params) -Gets the object details specified in params for the object with key id. -Details are OBJECT_NAME, _DESC, _POS, _ROT, _VELOCITY, _OWNER, _GROUP, _CREATOR. +Returns the object details specified in params for the object with key id. +Params are OBJECT_NAME, _DESC, _POS, _ROT, _VELOCITY, _OWNER, _GROUP, _CREATOR llSetClickAction(integer action) -Sets the action performed when a prim is clicked upon. +Sets the action performed when a prim is clicked upon -int llGetRegionAgentCount() -returns the number of agents in a region +integer llGetRegionAgentCount() +Returns the number of avatars in the region llTextBox(key avatar, string message, integer chat_channel -Shows a dialog box on the avatar's screen with the message. -A text box asks for input, and if entered the text is chatted on chat_channel. +Shows a dialog box on the avatar's screen with the message. +It contains a text box for input, and if entered that text is chatted on chat_channel. -string llGetAgentLanguage(key id) -Gets the agents preferred language.. +string llGetAgentLanguage(key avatar) +Returns the language code of the preferred interface language of the avatar -vector llDetectedTouchUV(integer number) -returns the u and v coordinates in the first two components of a vector, for a triggered touch event +vector llDetectedTouchUV(integer index) +Returns the u and v coordinates in the first two components of a vector, for the texture coordinates where the prim was touched in a triggered touch event -integer llDetectedTouchFace(integer number) -returns the index of the face on the object for a triggered touch event +integer llDetectedTouchFace(integer index) +Returns the index of the face where the avatar clicked in a triggered touch event -vector llDetectedTouchPos(integer number) -returns the position touched for a triggered touch event +vector llDetectedTouchPos(integer index) +Returns the position where the object was touched in a triggered touch event -vector llDetectedTouchNormal(integer number) -returns the surface normal for a triggered touch event +vector llDetectedTouchNormal(integer index) +Returns the surface normal for a triggered touch event -vector llDetectedTouchBinormal(integer number) -returns the surface binormal for a triggered touch event +vector llDetectedTouchBinormal(integer index) +Returns the surface binormal for a triggered touch event -vector llDetectedTouchST(integer number) -returns the s and t coordinates in the first two components of a vector, for a triggered touch event +vector llDetectedTouchST(integer index) +Returns the s and t coordinates in the first two components of a vector, for the surface coordinates where the prim was touched in a triggered touch event -string llSHA1String(string sr) -Performs a SHA1 security Hash. Returns a 40 character hex string. +string llSHA1String(string src) +Returns a string of 40 hex characters that is the SHA1 security Hash of src integer llGetFreeURLs() -returns the available urls for the current script +Returns the number of available URLs for the current script key llRequestURL() -Requests one HTTP:// url for use by this object -Triggers an http_server event with results. +Requests one HTTP:// url for use by this object. +An http_request event is triggered with the results. key llRequestSecureURL() -Requests one HTTPS:// (SSL) url for use by this object -Triggers an http_server event with results. +Requests one HTTPS:// (SSL) url for use by this object. +An http_request event is triggered with the results. llReleaseURL(string url) -Releases the specified URL, it will no longer be usable. +Releases the specified URL, it will no longer be usable -llHTTPResponse(key id, integer status, string body) -Responds to request id with status and body. +llHTTPResponse(key request_id, integer status, string body) +Responds to request_id with status and body -string llGetHTTPHeader(key id, string header) -Get the value for header for request id. +string llGetHTTPHeader(key request_id, string header) +Returns the value for header for request_id -- cgit v1.2.3 From 706b67622a0581f58560e06d9ce1ca2722b31f9b Mon Sep 17 00:00:00 2001 From: Ramzi Ramey Date: Wed, 30 Sep 2009 18:17:32 +0000 Subject: DEV-39781 VWR-15246: LSL compiler typo in the tooltip for 'attach' - edited 2 words in the file --- indra/newview/app_settings/keywords.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/app_settings/keywords.ini b/indra/newview/app_settings/keywords.ini index eaf5213985..a6abde36e3 100644 --- a/indra/newview/app_settings/keywords.ini +++ b/indra/newview/app_settings/keywords.ini @@ -40,7 +40,7 @@ not_at_rot_target not_at_rot_target():Result of LLRotTarget library function cal money money(key id, integer amount):Triggered when L$ is given to task email email(string time, string address, string subj, string message, integer num_left):Triggered when task receives email run_time_permissions run_time_permissions(integer perm):Triggered when an agent grants run time permissions to task -attach attach(key id):Triggered when an agent attaches or detaches from agent +attach attach(key id):Triggered when task attaches or detaches from agent dataserver dataserver(key queryid, string data):Triggered when task receives asynchronous data moving_start moving_start():Triggered when task begins moving moving_end moving_end():Triggered when task stops moving -- cgit v1.2.3 From 6519828508cd0f9feee8154a6412c474bea046de Mon Sep 17 00:00:00 2001 From: Ramzi Ramey Date: Wed, 30 Sep 2009 21:59:50 +0000 Subject: DEV-14830 add'l fix Copy-paste caused duplicate control and widget names in the script errors checkbox & radio buttons; Need to fix this before code is written for it. Need a unique name= for localization --- indra/newview/skins/default/xui/en/panel_preferences_advanced.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml index 8f710545d5..06ecfdc995 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml @@ -261,17 +261,17 @@ My Avatar: label="Show script errors" layout="topleft" left="30" - name="first_person_avatar_visible" + name="show_script_errors" width="256" top_pad="10"/> Date: Thu, 1 Oct 2009 00:23:26 +0000 Subject: DEV-40702 update viewer2 vivox sdk to v3 --- indra/newview/viewer_manifest.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index e85fddbc99..aa6a144247 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -248,10 +248,12 @@ class WindowsManifest(ViewerManifest): # Vivox runtimes if self.prefix(src="vivox-runtime/i686-win32", dst=""): self.path("SLVoice.exe") - self.path("alut.dll") + self.path("libsndfile-1.dll") + self.path("zlib1.dll") self.path("vivoxsdk.dll") + self.path("vivoxplatform.dll") self.path("ortp.dll") - self.path("wrap_oal.dll") + self.path("vivoxoal.dll") self.end_prefix() # pull in the crash logger and updater from other projects @@ -461,10 +463,11 @@ class DarwinManifest(ViewerManifest): self.path("zh-Hans.lproj") # SLVoice and vivox lols - self.path("vivox-runtime/universal-darwin/libalut.dylib", "libalut.dylib") - self.path("vivox-runtime/universal-darwin/libopenal.dylib", "libopenal.dylib") + self.path("vivox-runtime/universal-darwin/libsndfile.dylib", "libsndfile.dylib") + self.path("vivox-runtime/universal-darwin/libvivoxoal.dylib", "libvivoxoal.dylib") self.path("vivox-runtime/universal-darwin/libortp.dylib", "libortp.dylib") self.path("vivox-runtime/universal-darwin/libvivoxsdk.dylib", "libvivoxsdk.dylib") + self.path("vivox-runtime/universal-darwin/libvivoxplatform.dylib", "libvivoxplatform.dylib") self.path("vivox-runtime/universal-darwin/SLVoice", "SLVoice") # need to get the kdu dll from any of the build directories as well @@ -715,7 +718,10 @@ class Linux_i686Manifest(LinuxManifest): self.end_prefix() if self.prefix(src="vivox-runtime/i686-linux", dst="lib"): self.path("libortp.so") + self.path("libsndfile.so.1") + self.path("libvivoxoal.so.1") self.path("libvivoxsdk.so") + self.path("libvivoxplatform.so") self.end_prefix("lib") class Linux_x86_64Manifest(LinuxManifest): -- cgit v1.2.3 From 8135ddac021d3ea1aba2100f862bdb58eff33d07 Mon Sep 17 00:00:00 2001 From: Ramzi Ramey Date: Thu, 1 Oct 2009 02:02:31 +0000 Subject: L10N: typo and inconsistency in a tooltip of panel_login.xml --- indra/newview/skins/default/xui/en/panel_login.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml index e7fb3fa208..f2a7dc11c7 100644 --- a/indra/newview/skins/default/xui/en/panel_login.xml +++ b/indra/newview/skins/default/xui/en/panel_login.xml @@ -52,7 +52,7 @@ max_length="31" name="first_name_edit" select_on_focus="true" - tool_tip="Second Life First Name" + tool_tip="[SECOND_LIFE] First Name" top_pad="2" width="120" /> Date: Thu, 1 Oct 2009 02:35:53 +0000 Subject: svn merge -r 134922:134973 svn+ssh://svn.lindenlab.com/svn/linden/branches/media-on-a-prim/moap-7 Merging branches/media-on-a-prim/moap-7 down to viewer-2.0. --- indra/newview/CMakeLists.txt | 18 +- indra/newview/app_settings/keywords.ini | 43 +- indra/newview/app_settings/settings.xml | 80 ++- indra/newview/lldrawable.cpp | 24 + indra/newview/lldrawable.h | 6 +- indra/newview/llface.cpp | 22 +- indra/newview/llface.h | 1 + indra/newview/llfloatermediabrowser.cpp | 5 +- indra/newview/llfloatermediasettings.cpp | 249 +++++++ indra/newview/llfloatermediasettings.h | 81 +++ indra/newview/llfloaterpreference.cpp | 4 +- indra/newview/llfloatertools.cpp | 683 +++++++++++++++++-- indra/newview/llfloatertools.h | 19 +- indra/newview/llfloaterurlentry.cpp | 34 +- indra/newview/llfloaterurlentry.h | 4 +- indra/newview/llfloaterwhitelistentry.cpp | 97 +++ indra/newview/llfloaterwhitelistentry.h | 56 ++ indra/newview/llmediactrl.cpp | 162 +++-- indra/newview/llmediactrl.h | 20 +- indra/newview/llpanelcontents.cpp | 15 +- indra/newview/llpanelcontents.h | 18 +- indra/newview/llpanelface.cpp | 69 +- indra/newview/llpanelface.h | 9 +- indra/newview/llpanellandmedia.cpp | 11 +- indra/newview/llpanellandmedia.h | 9 - indra/newview/llpanellogin.cpp | 1 + indra/newview/llpanelmediasettingsgeneral.cpp | 409 +++++++++++ indra/newview/llpanelmediasettingsgeneral.h | 89 +++ indra/newview/llpanelmediasettingspermissions.cpp | 223 ++++++ indra/newview/llpanelmediasettingspermissions.h | 71 ++ indra/newview/llpanelmediasettingssecurity.cpp | 233 +++++++ indra/newview/llpanelmediasettingssecurity.h | 64 ++ indra/newview/llselectmgr.cpp | 101 ++- indra/newview/llselectmgr.h | 4 +- indra/newview/llspatialpartition.cpp | 5 + indra/newview/llspatialpartition.h | 1 + indra/newview/lltool.cpp | 16 +- indra/newview/lltoolpie.cpp | 95 ++- indra/newview/lltoolpie.h | 9 + indra/newview/llviewerfloaterreg.cpp | 4 + indra/newview/llviewermedia.cpp | 747 +++++++++++++++++---- indra/newview/llviewermedia.h | 96 ++- indra/newview/llviewermediafocus.cpp | 41 +- indra/newview/llviewermediafocus.h | 4 + indra/newview/llviewerobject.cpp | 107 ++- indra/newview/llviewerobject.h | 16 +- indra/newview/llviewerparcelmedia.cpp | 17 +- indra/newview/llviewerregion.cpp | 2 + indra/newview/llviewertexture.cpp | 465 +++++++++++-- indra/newview/llviewertexture.h | 68 +- indra/newview/llvovolume.cpp | 418 +++++++++++- indra/newview/llvovolume.h | 29 +- .../default/xui/en/floater_media_settings.xml | 20 + .../newview/skins/default/xui/en/floater_tools.xml | 249 +++++-- .../default/xui/en/floater_whitelist_entry.xml | 24 + .../newview/skins/default/xui/en/notifications.xml | 41 ++ indra/newview/skins/default/xui/en/panel_login.xml | 3 +- .../xui/en/panel_media_settings_general.xml | 199 ++++++ .../xui/en/panel_media_settings_permissions.xml | 49 ++ .../xui/en/panel_media_settings_security.xml | 56 ++ indra/newview/skins/default/xui/en/strings.xml | 18 +- indra/newview/viewer_manifest.py | 17 +- 62 files changed, 5128 insertions(+), 622 deletions(-) create mode 100644 indra/newview/llfloatermediasettings.cpp create mode 100644 indra/newview/llfloatermediasettings.h create mode 100644 indra/newview/llfloaterwhitelistentry.cpp create mode 100644 indra/newview/llfloaterwhitelistentry.h create mode 100644 indra/newview/llpanelmediasettingsgeneral.cpp create mode 100644 indra/newview/llpanelmediasettingsgeneral.h create mode 100644 indra/newview/llpanelmediasettingspermissions.cpp create mode 100644 indra/newview/llpanelmediasettingspermissions.h create mode 100644 indra/newview/llpanelmediasettingssecurity.cpp create mode 100644 indra/newview/llpanelmediasettingssecurity.h create mode 100644 indra/newview/skins/default/xui/en/floater_media_settings.xml create mode 100644 indra/newview/skins/default/xui/en/floater_whitelist_entry.xml create mode 100644 indra/newview/skins/default/xui/en/panel_media_settings_general.xml create mode 100644 indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml create mode 100644 indra/newview/skins/default/xui/en/panel_media_settings_security.xml (limited to 'indra/newview') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b74f67e72e..b217a5b781 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -171,6 +171,7 @@ set(viewer_SOURCE_FILES llfloaterhardwaresettings.cpp llfloaterhelpbrowser.cpp llfloatermediabrowser.cpp + llfloatermediasettings.cpp llfloaterhud.cpp llfloaterimagepreview.cpp llfloaterinspect.cpp @@ -207,6 +208,7 @@ set(viewer_SOURCE_FILES llfloaterurlentry.cpp llfloatervoicedevicesettings.cpp llfloaterwater.cpp + llfloaterwhitelistentry.cpp llfloaterwindlight.cpp llfloaterworldmap.cpp llfoldertype.cpp @@ -259,6 +261,9 @@ set(viewer_SOURCE_FILES llmanipscale.cpp llmaniptranslate.cpp llmapresponders.cpp + llmediactrl.cpp + llmediadataresponder.cpp + llmediadatafetcher.cpp llmediaremotectrl.cpp llmemoryview.cpp llmenucommands.cpp @@ -320,6 +325,9 @@ set(viewer_SOURCE_FILES llpanelmediahud.cpp llpanelmeprofile.cpp llpanelmovetip.cpp + llpanelmediasettingsgeneral.cpp + llpanelmediasettingssecurity.cpp + llpanelmediasettingspermissions.cpp llpanelobject.cpp llpanelpeople.cpp llpanelpeoplemenus.cpp @@ -491,7 +499,6 @@ set(viewer_SOURCE_FILES llwearabledictionary.cpp llwearablelist.cpp llweb.cpp - llmediactrl.cpp llwind.cpp llwlanimator.cpp llwldaycycle.cpp @@ -635,6 +642,7 @@ set(viewer_HEADER_FILES llfloaterhardwaresettings.h llfloaterhelpbrowser.h llfloatermediabrowser.h + llfloatermediasettings.h llfloaterhud.h llfloaterimagepreview.h llfloaterinspect.h @@ -671,6 +679,7 @@ set(viewer_HEADER_FILES llfloaterurlentry.h llfloatervoicedevicesettings.h llfloaterwater.h + llfloaterwhitelistentry.h llfloaterwindlight.h llfloaterworldmap.h llfoldertype.h @@ -723,6 +732,8 @@ set(viewer_HEADER_FILES llmanipscale.h llmaniptranslate.h llmapresponders.h + llmediadataresponder.h + llmediadatafetcher.h llmediaremotectrl.h llmemoryview.h llmenucommands.h @@ -781,6 +792,9 @@ set(viewer_HEADER_FILES llpanelmediahud.h llpanelmeprofile.h llpanelmovetip.h + llpanelmediasettingsgeneral.h + llpanelmediasettingssecurity.h + llpanelmediasettingspermissions.h llpanelobject.h llpanelpeople.h llpanelpeoplemenus.h @@ -1566,7 +1580,7 @@ if (WINDOWS) -E copy_if_different ${BUILT_SLPLUGIN} - ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} COMMENT "Copying SLPlugin executable to the runtime folder." ) diff --git a/indra/newview/app_settings/keywords.ini b/indra/newview/app_settings/keywords.ini index a6abde36e3..5d52158298 100644 --- a/indra/newview/app_settings/keywords.ini +++ b/indra/newview/app_settings/keywords.ini @@ -47,7 +47,7 @@ moving_end moving_end():Triggered when task stops moving on_rez on_rez(integer start_param):Triggered when task is rezed in from inventory or another task object_rez object_rez(key id):Triggered when task rezes in another task link_message link_message(integer sender_num, integer num, string str, key id):Triggered when task receives a link message via LLMessageLinked library function call -changed changed( integer change ):Triggered various event change the task:(test change with CHANGED_INVENTORY, CHANGED_COLOR, CHANGED_SHAPE, CHANGED_SCALE, CHANGED_TEXTURE, CHANGED_LINK, CHANGED_ALLOWED_DROP, CHANGED_OWNER, CHANGED_REGION, CHANGED_TELEPORT) +changed changed( integer change ):Triggered various event change the task:(test change with CHANGED_INVENTORY, CHANGED_COLOR, CHANGED_SHAPE, CHANGED_SCALE, CHANGED_TEXTURE, CHANGED_LINK, CHANGED_ALLOWED_DROP, CHANGED_OWNER, CHANGED_REGION, CHANGED_TELEPORT, CHANGED_REGION_START, CHANGED_MEDIA) remote_data remote_data(integer event_type, key channel, key message_id, string sender,integer idata, string sdata):Triggered by various XML-RPC calls (event_type will be one of REMOTE_DATA_CHANNEL, REMOTE_DATA_REQUEST, REMOTE_DATA_REPLY) http_response http_response(key request_id, integer status, list metadata, string body):Triggered when task receives a response to one of its llHTTPRequests http_request http_request(key id, string method, string body):Triggered when task receives an http request against a public URL @@ -320,6 +320,7 @@ CHANGED_OWNER Parameter of changed event handler used to indicate change to tas CHANGED_REGION Parameter of changed event handler used to indicate the region has changed CHANGED_TELEPORT Parameter of changed event handler used to indicate teleport has completed CHANGED_REGION_START Parameter of changed event handler used to indicate the region has been restarted +CHANGED_MEDIA Parameter of changed event handler used to indicate that media has changed on a face of the task TYPE_INTEGER Indicates that the list entry is holding an integer TYPE_FLOAT Indicates that the list entry is holding an float @@ -513,6 +514,46 @@ TOUCH_INVALID_TEXCOORD Value returned by llDetectedTouchUV() and llDetectedTouc TOUCH_INVALID_VECTOR Value returned by llDetectedTouchPos(), llDetectedTouchNormal(), and llDetectedTouchBinormal() when the touch position is not valid. TOUCH_INVALID_FACE Value returned by llDetectedTouchFace() when the touch position is not valid. +PRIM_MEDIA_ALT_IMAGE_ENABLE Used with ll{Get,Set}PrimMediaParams to enable the default alt image for media +PRIM_MEDIA_CONTROLS Used with ll{Get,Set}PrimMediaParams to determine the controls shown for media +PRIM_MEDIA_CURRENT_URL Used with ll{Get,Set}PrimMediaParams to navigate/access the current URL +PRIM_MEDIA_HOME_URL Used with ll{Get,Set}PrimMediaParams to access the home URL +PRIM_MEDIA_AUTO_LOOP Used with ll{Get,Set}PrimMediaParams to determine if media should auto-loop (if applicable) +PRIM_MEDIA_AUTO_PLAY Used with ll{Get,Set}PrimMediaParams to determine if media should start playing as soon as it is created +PRIM_MEDIA_AUTO_SCALE Used with ll{Get,Set}PrimMediaParams to determine if media should scale to fit the face it is on +PRIM_MEDIA_AUTO_ZOOM Used with ll{Get,Set}PrimMediaParams to determine if the user would zoom in when viewing media +PRIM_MEDIA_FIRST_CLICK_INTERACT Used with ll{Get,Set}PrimMediaParams to determine whether the user interacts with media or not when she first clicks it (versus selection) +PRIM_MEDIA_WIDTH_PIXELS Used with ll{Get,Set}PrimMediaParams to access the media's width in pixels +PRIM_MEDIA_HEIGHT_PIXELS Used with ll{Get,Set}PrimMediaParams to access the media's height in pixels +PRIM_MEDIA_WHITELIST_ENABLE Used with ll{Get,Set}PrimMediaParams to determine if the domain whitelist is enabled +PRIM_MEDIA_WHITELIST Used with ll{Get,Set}PrimMediaParams to access the media's list of allowable URL prefixes to navigate to +PRIM_MEDIA_PERMS_INTERACT Used with ll{Get,Set}PrimMediaParams to determine the permissions for who can interact with the media +PRIM_MEDIA_PERMS_CONTROL Used with ll{Get,Set}PrimMediaParams to determine the permissions for who has controls +PRIM_MEDIA_PARAM_MAX The value of the largest media param + +PRIM_MEDIA_CONTROLS_STANDARD Used with ll{Get,Set}PrimMediaParams, a PRIM_MEDIA_CONTROLS value meaning "standard controls" +PRIM_MEDIA_CONTROLS_MINI Used with ll{Get,Set}PrimMediaParams, a PRIM_MEDIA_CONTROLS value meaning "mini controls" + +PRIM_MEDIA_PERM_NONE Used with ll{Get,Set}PrimMediaParams, a PRIM_MEDIA_PERMS_INTERACT or PRIM_MEDIA_PERMS_CONTROL bit, no permissions +PRIM_MEDIA_PERM_OWNER Used with ll{Get,Set}PrimMediaParams, a PRIM_MEDIA_PERMS_INTERACT or PRIM_MEDIA_PERMS_CONTROL bit, owner permissions +PRIM_MEDIA_PERM_GROUP Used with ll{Get,Set}PrimMediaParams, a PRIM_MEDIA_PERMS_INTERACT or PRIM_MEDIA_PERMS_CONTROL bit, group permissions +PRIM_MEDIA_PERM_ANYONE Used with ll{Get,Set}PrimMediaParams, a PRIM_MEDIA_PERMS_INTERACT or PRIM_MEDIA_PERMS_CONTROL bit, anyone has permissions + +PRIM_MEDIA_MAX_URL_LENGTH Used with ll{Get,Set}PrimMediaParams, the maximum length of PRIM_MEDIA_CURRENT_URL or PRIM_MEDIA_HOME_URL +PRIM_MEDIA_MAX_WHITELIST_SIZE Used with ll{Get,Set}PrimMediaParams, the maximum length, in bytes, of PRIM_MEDIA_WHITELIST +PRIM_MEDIA_MAX_WHITELIST_COUNT Used with ll{Get,Set}PrimMediaParams, the maximum number of items allowed in PRIM_MEDIA_WHITELIST +PRIM_MEDIA_MAX_WIDTH_PIXELS Used with ll{Get,Set}PrimMediaParams, the maximum width allowed in PRIM_MEDIA_WIDTH_PIXELS +PRIM_MEDIA_MAX_HEIGHT_PIXELS Used with ll{Get,Set}PrimMediaParams, the maximum width allowed in PRIM_MEDIA_HEIGHT_PIXELS + +STATUS_OK Result of function call was success +STATUS_MALFORMED_PARAMS Function was called with malformed params +STATUS_TYPE_MISMATCH Argument(s) passed to function had a type mismatch +STATUS_BOUNDS_ERROR Argument(s) passed to function had a bounds error +STATUS_NOT_FOUND Object or other item was not found +STATUS_NOT_SUPPORTED Feature not supported +STATUS_INTERNAL_ERROR An internal error occurred +STATUS_WHITELIST_FAILED URL failed to pass whitelist + # string constants [word .1, .3, .5] NULL_KEY Indicates an empty key diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 8cbe6d20c6..99b662a63f 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -3994,6 +3994,17 @@ Value 0 + LastMediaSettingsTab + + Comment + Last selected tab in media settings window + Persist + 1 + Type + S32 + Value + 0 + LastRunVersion Comment @@ -4455,7 +4466,7 @@ Type Boolean Value - 0 + 1 MemoryLogFrequency @@ -5216,6 +5227,51 @@ Value 1 + + PluginInstancesCPULimit + + Comment + Amount of total plugin CPU usage before inworld plugins start getting turned down to "slideshow" priority. Set to 0 to disable this check. + Persist + 1 + Type + F32 + Value + 0.0 + + PluginInstancesLow + + Comment + Limit on the number of inworld media plugins that will run at "low" priority + Persist + 1 + Type + U32 + Value + 4 + + PluginInstancesNormal + + Comment + Limit on the number of inworld media plugins that will run at "normal" priority + Persist + 1 + Type + U32 + Value + 4 + + PluginInstancesTotal + + Comment + Hard limit on the number of plugins that will be instantiated at once + Persist + 1 + Type + U32 + Value + 16 + PrecachingDelay Comment @@ -5238,6 +5294,28 @@ Value 13 + PrimMediaFetchQueueDelay + + Comment + Timer delay for fetching media from the queue (in seconds). + Persist + 1 + Type + F32 + Value + 1.0 + + PrimMediaRetryTimerDelay + + Comment + Timer delay for retrying on media queries (in seconds). + Persist + 1 + Type + F32 + Value + 5.0 + ProbeHardwareOnStartup Comment diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 4cf12a1533..069155c255 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -960,6 +960,30 @@ LLSpatialPartition* LLDrawable::getSpatialPartition() return retval; } +const S32 MIN_VIS_FRAME_RANGE = 2 ; //two frames:the current one and the last one. +//static +S32 LLDrawable::getMinVisFrameRange() +{ + return MIN_VIS_FRAME_RANGE ; +} + +BOOL LLDrawable::isRecentlyVisible() const +{ + //currently visible or visible in the previous frame. + BOOL vis = isVisible() || (sCurVisible - mVisible < MIN_VIS_FRAME_RANGE) ; + + if(!vis) + { + LLSpatialGroup* group = getSpatialGroup(); + if (group && group->isRecentlyVisible()) + { + mVisible = sCurVisible; + vis = TRUE ; + } + } + + return vis ; +} BOOL LLDrawable::isVisible() const { diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index 986440397b..5a10b688da 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -78,7 +78,8 @@ public: BOOL isLight() const; - BOOL isVisible() const; + BOOL isVisible() const; + BOOL isRecentlyVisible() const; virtual void setVisible(LLCamera& camera_in, std::vector* results = NULL, BOOL for_select = FALSE); @@ -278,7 +279,8 @@ public: S32 mQuietCount; static S32 getCurrentFrame() { return sCurVisible; } - + static S32 getMinVisFrameRange(); + void setSpatialBridge(LLSpatialBridge* bridge) { mSpatialBridge = (LLDrawable*) bridge; } LLSpatialBridge* getSpatialBridge() { return (LLSpatialBridge*) (LLDrawable*) mSpatialBridge; } diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index fc5b27dd1b..a5b0b05603 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -270,16 +270,34 @@ void LLFace::setTexture(LLViewerTexture* tex) { mTexture->removeFace(this) ; removeAtlas() ; - } + } mTexture = tex ; - + if(mTexture.notNull()) { mTexture->addFace(this) ; } } +void LLFace::switchTexture(LLViewerTexture* new_texture) +{ + if(mTexture == new_texture) + { + return ; + } + + if(!new_texture) + { + llerrs << "Can not switch to a null texture." << llendl ; + } + new_texture->addTextureStats(mTexture->getMaxVirtualSize()) ; + + getViewerObject()->changeTEImage(mTEOffset, new_texture) ; + setTexture(new_texture) ; + gPipeline.markTextured(getDrawable()); +} + void LLFace::setTEOffset(const S32 te_offset) { mTEOffset = te_offset; diff --git a/indra/newview/llface.h b/indra/newview/llface.h index cafad5706c..f6ffefcb7c 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -89,6 +89,7 @@ public: U16 getGeomIndex() const { return mGeomIndex; } // index into draw pool U16 getGeomStart() const { return mGeomIndex; } // index into draw pool void setTexture(LLViewerTexture* tex) ; + void switchTexture(LLViewerTexture* new_texture); LLXformMatrix* getXform() const { return mXform; } BOOL hasGeometry() const { return mGeomCount > 0; } LLVector3 getPositionAgent() const; diff --git a/indra/newview/llfloatermediabrowser.cpp b/indra/newview/llfloatermediabrowser.cpp index c7ec4bd585..9b7f3305e5 100644 --- a/indra/newview/llfloatermediabrowser.cpp +++ b/indra/newview/llfloatermediabrowser.cpp @@ -146,7 +146,10 @@ void LLFloaterMediaBrowser::buildURLHistory() } // initialize URL history in the plugin - mBrowser->getMediaPlugin()->initializeUrlHistory(browser_history); + if(mBrowser && mBrowser->getMediaPlugin()) + { + mBrowser->getMediaPlugin()->initializeUrlHistory(browser_history); + } } std::string LLFloaterMediaBrowser::getSupportURL() diff --git a/indra/newview/llfloatermediasettings.cpp b/indra/newview/llfloatermediasettings.cpp new file mode 100644 index 0000000000..811cc26efb --- /dev/null +++ b/indra/newview/llfloatermediasettings.cpp @@ -0,0 +1,249 @@ +/** + * @file llfloatermediasettings.cpp + * @brief Tabbed dialog for media settings - class implementation + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterreg.h" +#include "llfloatermediasettings.h" +#include "llpanelmediasettingsgeneral.h" +#include "llpanelmediasettingssecurity.h" +#include "llpanelmediasettingspermissions.h" +#include "llviewercontrol.h" +#include "lluictrlfactory.h" +#include "llbutton.h" +#include "llselectmgr.h" + +LLFloaterMediaSettings* LLFloaterMediaSettings::sInstance = NULL; + +//////////////////////////////////////////////////////////////////////////////// +// +LLFloaterMediaSettings::LLFloaterMediaSettings(const LLSD& key) + : LLFloater(key), + mTabContainer(NULL), + mPanelMediaSettingsGeneral(NULL), + mPanelMediaSettingsSecurity(NULL), + mPanelMediaSettingsPermissions(NULL), + mWaitingToClose( false ) +{ +// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_media_settings.xml"); +} + +//////////////////////////////////////////////////////////////////////////////// +// +LLFloaterMediaSettings::~LLFloaterMediaSettings() +{ + if ( mPanelMediaSettingsGeneral ) + { + delete mPanelMediaSettingsGeneral; + mPanelMediaSettingsGeneral = NULL; + } + + if ( mPanelMediaSettingsSecurity ) + { + delete mPanelMediaSettingsSecurity; + mPanelMediaSettingsSecurity = NULL; + } + + if ( mPanelMediaSettingsPermissions ) + { + delete mPanelMediaSettingsPermissions; + mPanelMediaSettingsPermissions = NULL; + } + + sInstance = NULL; +} + +//////////////////////////////////////////////////////////////////////////////// +// +BOOL LLFloaterMediaSettings::postBuild() +{ + mCloseSignal.connect(boost::bind(&LLFloaterMediaSettings::onClose, this)); + + mApplyBtn = getChild("Apply"); + mApplyBtn->setClickedCallback(onBtnApply, this); + + mCancelBtn = getChild("Cancel"); + mCancelBtn->setClickedCallback(onBtnCancel, this); + + mOKBtn = getChild("OK"); + mOKBtn->setClickedCallback(onBtnOK, this); + + mTabContainer = getChild( "tab_container" ); + + mPanelMediaSettingsGeneral = new LLPanelMediaSettingsGeneral(); + mTabContainer->addTabPanel( + LLTabContainer::TabPanelParams(). + panel(mPanelMediaSettingsGeneral)); + mPanelMediaSettingsGeneral->setParent( this ); + + // note that "permissions" tab is really "Controls" tab - refs to 'perms' and + // 'permissions' not changed to 'controls' since we don't want to change + // shared files in server code and keeping everything the same seemed best. + mPanelMediaSettingsPermissions = new LLPanelMediaSettingsPermissions(); + mTabContainer->addTabPanel( + LLTabContainer::TabPanelParams(). + panel(mPanelMediaSettingsPermissions)); + + mPanelMediaSettingsSecurity = new LLPanelMediaSettingsSecurity(); + mTabContainer->addTabPanel( + LLTabContainer::TabPanelParams(). + panel(mPanelMediaSettingsSecurity)); + + // restore the last tab viewed from persistance variable storage + if (!mTabContainer->selectTab(gSavedSettings.getS32("LastMediaSettingsTab"))) + { + mTabContainer->selectFirstTab(); + }; + + sInstance = this; + + return TRUE; +} + +//static +LLFloaterMediaSettings* LLFloaterMediaSettings::getInstance() +{ + if ( !sInstance ) + { + sInstance = (LLFloaterReg::getTypedInstance("media_settings")); + } + + return sInstance; +} + +//static +void LLFloaterMediaSettings::apply() +{ + + LLSD settings; + sInstance->mPanelMediaSettingsGeneral->getValues( settings ); + sInstance->mPanelMediaSettingsSecurity->getValues( settings ); + sInstance->mPanelMediaSettingsPermissions->getValues( settings ); + LLSelectMgr::getInstance()->selectionSetMedia( LLTextureEntry::MF_HAS_MEDIA ); + LLSelectMgr::getInstance()->selectionSetMediaData(settings); +} + +//////////////////////////////////////////////////////////////////////////////// +void LLFloaterMediaSettings::onClose() +{ + if(mPanelMediaSettingsGeneral) + { + mPanelMediaSettingsGeneral->onClose(); + } + LLFloaterReg::hideInstance("whitelist_entry"); +} + +//////////////////////////////////////////////////////////////////////////////// +//static +void LLFloaterMediaSettings::initValues( const LLSD& media_settings ) +{ + sInstance->clearValues(); + // update all panels with values from simulator + sInstance->mPanelMediaSettingsGeneral-> + initValues( sInstance->mPanelMediaSettingsGeneral, media_settings ); + + sInstance->mPanelMediaSettingsSecurity-> + initValues( sInstance->mPanelMediaSettingsSecurity, media_settings ); + + sInstance->mPanelMediaSettingsPermissions-> + initValues( sInstance->mPanelMediaSettingsPermissions, media_settings ); + +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFloaterMediaSettings::commitFields() +{ + if (hasFocus()) + { + LLUICtrl* cur_focus = dynamic_cast(gFocusMgr.getKeyboardFocus()); + if (cur_focus->acceptsTextInput()) + { + cur_focus->onCommit(); + }; + }; +} + +//////////////////////////////////////////////////////////////////////////////// +//static +void LLFloaterMediaSettings::clearValues() +{ + // clean up all panels before updating + sInstance->mPanelMediaSettingsGeneral->clearValues(sInstance->mPanelMediaSettingsGeneral); + sInstance->mPanelMediaSettingsSecurity->clearValues(sInstance->mPanelMediaSettingsSecurity); + sInstance->mPanelMediaSettingsPermissions->clearValues(sInstance->mPanelMediaSettingsPermissions); +} + + +//////////////////////////////////////////////////////////////////////////////// +// static +void LLFloaterMediaSettings::onBtnOK( void* userdata ) +{ + sInstance->commitFields(); + + sInstance->apply(); + + sInstance->closeFloater(); +} + +//////////////////////////////////////////////////////////////////////////////// +// static +void LLFloaterMediaSettings::onBtnApply( void* userdata ) +{ + sInstance->commitFields(); + + sInstance->apply(); +} + +//////////////////////////////////////////////////////////////////////////////// +// static +void LLFloaterMediaSettings::onBtnCancel( void* userdata ) +{ + sInstance->closeFloater(); +} + +//////////////////////////////////////////////////////////////////////////////// +// static +void LLFloaterMediaSettings::onTabChanged(void* user_data, bool from_click) +{ + LLTabContainer* self = (LLTabContainer*)user_data; + gSavedSettings.setS32("LastMediaSettingsTab", self->getCurrentPanelIndex()); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLFloaterMediaSettings::enableOkApplyBtns( bool enable ) +{ + setCtrlsEnabled( enable ); + childSetEnabled( "OK", enable ); + childSetEnabled( "Apply", enable ); +} diff --git a/indra/newview/llfloatermediasettings.h b/indra/newview/llfloatermediasettings.h new file mode 100644 index 0000000000..b95c590346 --- /dev/null +++ b/indra/newview/llfloatermediasettings.h @@ -0,0 +1,81 @@ +/** + * @file llfloatermediasettings.cpp + * @brief Tabbed dialog for media settings - class definition + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERMEDIASETTINGS_H +#define LL_LLFLOATERMEDIASETTINGS_H + +#include "llfloater.h" +#include "lltabcontainer.h" + +class LLPanelMediaSettingsGeneral; +class LLPanelMediaSettingsSecurity; +class LLPanelMediaSettingsPermissions; + +class LLFloaterMediaSettings : + public LLFloater +{ +public: + LLFloaterMediaSettings(const LLSD& key); + ~LLFloaterMediaSettings(); + + virtual BOOL postBuild(); + static LLFloaterMediaSettings* getInstance(); + static void apply(); + static void initValues( const LLSD& media_settings ); + static void clearValues(); + void enableOkApplyBtns( bool enable ); + LLPanelMediaSettingsSecurity* getPanelSecurity(){return mPanelMediaSettingsSecurity;}; + +protected: + LLButton *mOKBtn; + LLButton *mCancelBtn; + LLButton *mApplyBtn; + + LLTabContainer *mTabContainer; + LLPanelMediaSettingsGeneral* mPanelMediaSettingsGeneral; + LLPanelMediaSettingsSecurity* mPanelMediaSettingsSecurity; + LLPanelMediaSettingsPermissions* mPanelMediaSettingsPermissions; + + void onClose(); + static void onBtnOK(void*); + static void onBtnCancel(void*); + static void onBtnApply(void*); + static void onTabChanged(void* user_data, bool from_click); + void commitFields(); + + static LLFloaterMediaSettings* sInstance; + +private: + bool mWaitingToClose; +}; + +#endif // LL_LLFLOATERMEDIASETTINGS_H diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 761b5c9219..57c043a1e0 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -195,8 +195,8 @@ void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator); viewer_media_t get_web_media() { - viewer_media_t media_source = LLViewerMedia::newMediaImpl("", LLUUID::null, 0, 0, 0, 0, "text/html"); - + viewer_media_t media_source = LLViewerMedia::newMediaImpl(LLUUID::null); + media_source->initializeMedia("text/html"); return media_source; } diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index f334344279..7dc29379e4 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -44,9 +44,11 @@ #include "llcombobox.h" #include "lldraghandle.h" #include "llfloaterbuildoptions.h" +#include "llfloatermediasettings.h" #include "llfloateropenobject.h" #include "llfloaterreg.h" #include "llfocusmgr.h" +#include "llmediaentry.h" #include "llmenugl.h" #include "llpanelcontents.h" #include "llpanelface.h" @@ -97,7 +99,7 @@ const std::string PANEL_NAMES[LLFloaterTools::PANEL_COUNT] = }; // Local prototypes -void commit_select_component(LLUICtrl *ctrl, void *data); +void commit_select_component(void *data); void click_show_more(void*); void click_popup_info(void*); void click_popup_done(void*); @@ -105,15 +107,14 @@ void click_popup_minimize(void*); void click_popup_rotate_left(void*); void click_popup_rotate_reset(void*); void click_popup_rotate_right(void*); -void commit_slider_dozer_size(LLUICtrl *, void*); -void commit_slider_dozer_force(LLUICtrl *, void*); +void commit_slider_dozer_force(LLUICtrl *); void click_apply_to_selection(void*); -void commit_radio_group_focus(LLUICtrl* ctrl, void* data); -void commit_radio_group_move(LLUICtrl* ctrl, void* data); -void commit_radio_group_edit(LLUICtrl* ctrl, void* data); -void commit_radio_group_land(LLUICtrl* ctrl, void* data); -void commit_grid_mode(LLUICtrl *, void*); -void commit_slider_zoom(LLUICtrl *, void*); +void commit_radio_group_focus(LLUICtrl* ctrl); +void commit_radio_group_move(LLUICtrl* ctrl); +void commit_radio_group_edit(LLUICtrl* ctrl); +void commit_radio_group_land(LLUICtrl* ctrl); +void commit_grid_mode(LLUICtrl *); +void commit_slider_zoom(LLUICtrl *ctrl); //static @@ -210,43 +211,28 @@ BOOL LLFloaterTools::postBuild() getDragHandle()->setEnabled( !gSavedSettings.getBOOL("ToolboxAutoMove") ); LLRect rect; - mBtnFocus = getChild("button focus");//btn; - childSetAction("button focus",LLFloaterTools::setEditTool, (void*)LLToolCamera::getInstance()); - mBtnMove = getChild("button move"); - childSetAction("button move",LLFloaterTools::setEditTool, (void*)LLToolGrab::getInstance()); - mBtnEdit = getChild("button edit"); - childSetAction("button edit",LLFloaterTools::setEditTool, (void*)LLToolCompTranslate::getInstance()); - mBtnCreate = getChild("button create"); - childSetAction("button create",LLFloaterTools::setEditTool, (void*)LLToolCompCreate::getInstance()); - mBtnLand = getChild("button land" ); - childSetAction("button land",LLFloaterTools::setEditTool, (void*)LLToolSelectLand::getInstance()); - mTextStatus = getChild("text status"); - - childSetCommitCallback("slider zoom",commit_slider_zoom,this); - - mRadioGroupFocus = getChild("focus_radio_group"); - childSetCommitCallback("focus_radio_group", commit_radio_group_focus, this); - - mRadioGroupMove = getChild("move_radio_group"); - childSetCommitCallback("move_radio_group", commit_radio_group_move, this); - - mRadioGroupEdit = getChild("edit_radio_group"); - childSetCommitCallback("edit_radio_group", commit_radio_group_edit, this); - - mCheckSelectIndividual = getChild("checkbox edit linked parts"); + mBtnFocus = getChild("button focus");//btn; + mBtnMove = getChild("button move"); + mBtnEdit = getChild("button edit"); + mBtnCreate = getChild("button create"); + mBtnLand = getChild("button land" ); + mTextStatus = getChild("text status"); + mRadioGroupFocus = getChild("focus_radio_group"); + mRadioGroupMove = getChild("move_radio_group"); + mRadioGroupEdit = getChild("edit_radio_group"); + mBtnGridOptions = getChild("Options..."); + + mCheckSelectIndividual = getChild("checkbox edit linked parts"); childSetValue("checkbox edit linked parts",(BOOL)gSavedSettings.getBOOL("EditLinkedParts")); - childSetCommitCallback("checkbox edit linked parts",commit_select_component,this); - mCheckSnapToGrid = getChild("checkbox snap to grid"); + mCheckSnapToGrid = getChild("checkbox snap to grid"); childSetValue("checkbox snap to grid",(BOOL)gSavedSettings.getBOOL("SnapEnabled")); - mBtnGridOptions = getChild("Options..."); - childSetAction("Options...",onClickGridOptions, this); - mCheckStretchUniform = getChild("checkbox uniform"); + mCheckStretchUniform = getChild("checkbox uniform"); childSetValue("checkbox uniform",(BOOL)gSavedSettings.getBOOL("ScaleUniform")); - mCheckStretchTexture = getChild("checkbox stretch textures"); + mCheckStretchTexture = getChild("checkbox stretch textures"); childSetValue("checkbox stretch textures",(BOOL)gSavedSettings.getBOOL("ScaleStretchTextures")); - mTextGridMode = getChild("text ruler mode"); - mComboGridMode = getChild("combobox grid mode"); - childSetCommitCallback("combobox grid mode",commit_grid_mode, this); + mTextGridMode = getChild("text ruler mode"); + mComboGridMode = getChild("combobox grid mode"); + // // Create Buttons // @@ -271,18 +257,11 @@ BOOL LLFloaterTools::postBuild() mCheckCopyRotates = getChild("checkbox copy rotates"); childSetValue("checkbox copy rotates",(BOOL)gSavedSettings.getBOOL("CreateToolCopyRotates")); - mRadioGroupLand = getChild("land_radio_group"); - childSetCommitCallback("land_radio_group", commit_radio_group_land, this); - - mBtnApplyToSelection = getChild("button apply to selection"); - childSetAction("button apply to selection",click_apply_to_selection, (void*)0); - - mSliderDozerSize = getChild("slider brush size"); - childSetCommitCallback("slider brush size", commit_slider_dozer_size, (void*)0); + mRadioGroupLand = getChild("land_radio_group"); + mBtnApplyToSelection = getChild("button apply to selection"); + mSliderDozerSize = getChild("slider brush size"); childSetValue( "slider brush size", gSavedSettings.getF32("LandBrushSize")); - - mSliderDozerForce = getChild("slider force"); - childSetCommitCallback("slider force",commit_slider_dozer_force, (void*)0); + mSliderDozerForce = getChild("slider force"); // the setting stores the actual force multiplier, but the slider is logarithmic, so we convert here childSetValue( "slider force", log10(gSavedSettings.getF32("LandBrushForce"))); @@ -369,6 +348,22 @@ LLFloaterTools::LLFloaterTools(const LLSD& key) mFactoryMap["land info panel"] = LLCallbackMap(createPanelLandInfo, this);//LLPanelLandInfo //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this,"floater_tools.xml",FALSE); + mCommitCallbackRegistrar.add("BuildTool.setTool", boost::bind(&LLFloaterTools::setTool,this, _2)); + mCommitCallbackRegistrar.add("BuildTool.commitZoom", boost::bind(&commit_slider_zoom, _1)); + mCommitCallbackRegistrar.add("BuildTool.commitRadioFocus", boost::bind(&commit_radio_group_focus, _1)); + mCommitCallbackRegistrar.add("BuildTool.commitRadioMove", boost::bind(&commit_radio_group_move,_1)); + mCommitCallbackRegistrar.add("BuildTool.commitRadioEdit", boost::bind(&commit_radio_group_edit,_1)); + + mCommitCallbackRegistrar.add("BuildTool.selectComponent", boost::bind(&commit_select_component, this)); + mCommitCallbackRegistrar.add("BuildTool.gridOptions", boost::bind(&LLFloaterTools::onClickGridOptions,this)); + mCommitCallbackRegistrar.add("BuildTool.applyToSelection", boost::bind(&click_apply_to_selection, this)); + mCommitCallbackRegistrar.add("BuildTool.gridMode", boost::bind(&commit_grid_mode,_1)); + mCommitCallbackRegistrar.add("BuildTool.commitRadioLand", boost::bind(&commit_radio_group_land,_1)); + mCommitCallbackRegistrar.add("BuildTool.LandBrushForce", boost::bind(&commit_slider_dozer_force,_1)); + mCommitCallbackRegistrar.add("BuildTool.AddMedia", boost::bind(&LLFloaterTools::onClickBtnAddMedia,this)); + mCommitCallbackRegistrar.add("BuildTool.DeleteMedia", boost::bind(&LLFloaterTools::onClickBtnDeleteMedia,this)); + mCommitCallbackRegistrar.add("BuildTool.EditMedia", boost::bind(&LLFloaterTools::onClickBtnEditMedia,this)); + } LLFloaterTools::~LLFloaterTools() @@ -427,6 +422,7 @@ void LLFloaterTools::refresh() mPanelObject->refresh(); mPanelVolume->refresh(); mPanelFace->refresh(); + refreshMedia(); mPanelContents->refresh(); mPanelLandInfo->refresh(); } @@ -756,6 +752,7 @@ void LLFloaterTools::onClose() LLToolMgr::getInstance()->getCurrentToolset()->selectFirstTool(); //gMenuBarView->setItemVisible("BuildTools", FALSE); + LLFloaterReg::hideInstance("media_settings"); } void click_popup_info(void*) @@ -767,7 +764,7 @@ void click_popup_done(void*) handle_reset_view(); } -void commit_radio_group_move(LLUICtrl* ctrl, void* data) +void commit_radio_group_move(LLUICtrl* ctrl) { LLRadioGroup* group = (LLRadioGroup*)ctrl; std::string selected = group->getValue().asString(); @@ -788,7 +785,7 @@ void commit_radio_group_move(LLUICtrl* ctrl, void* data) } } -void commit_radio_group_focus(LLUICtrl* ctrl, void* data) +void commit_radio_group_focus(LLUICtrl* ctrl) { LLRadioGroup* group = (LLRadioGroup*)ctrl; std::string selected = group->getValue().asString(); @@ -812,7 +809,7 @@ void commit_radio_group_focus(LLUICtrl* ctrl, void* data) } } -void commit_slider_zoom(LLUICtrl *ctrl, void*) +void commit_slider_zoom(LLUICtrl *ctrl) { // renormalize value, since max "volume" level is 0.5 for some reason F32 zoom_level = (F32)ctrl->getValue().asReal() * 2.f; // / 0.5f; @@ -837,26 +834,19 @@ void click_popup_rotate_right(void*) dialog_refresh_all(); } - -void commit_slider_dozer_size(LLUICtrl *ctrl, void*) -{ - F32 size = (F32)ctrl->getValue().asReal(); - gSavedSettings.setF32("LandBrushSize", size); -} - -void commit_slider_dozer_force(LLUICtrl *ctrl, void*) +void commit_slider_dozer_force(LLUICtrl *ctrl) { // the slider is logarithmic, so we exponentiate to get the actual force multiplier F32 dozer_force = pow(10.f, (F32)ctrl->getValue().asReal()); gSavedSettings.setF32("LandBrushForce", dozer_force); } -void click_apply_to_selection(void* user) +void click_apply_to_selection(void*) { LLToolBrushLand::getInstance()->modifyLandInSelectionGlobal(); } -void commit_radio_group_edit(LLUICtrl *ctrl, void *data) +void commit_radio_group_edit(LLUICtrl *ctrl) { S32 show_owners = gSavedSettings.getBOOL("ShowParcelOwners"); @@ -881,7 +871,7 @@ void commit_radio_group_edit(LLUICtrl *ctrl, void *data) gSavedSettings.setBOOL("ShowParcelOwners", show_owners); } -void commit_radio_group_land(LLUICtrl* ctrl, void* data) +void commit_radio_group_land(LLUICtrl* ctrl) { LLRadioGroup* group = (LLRadioGroup*)ctrl; std::string selected = group->getValue().asString(); @@ -909,7 +899,7 @@ void commit_radio_group_land(LLUICtrl* ctrl, void* data) } } -void commit_select_component(LLUICtrl *ctrl, void *data) +void commit_select_component(void *data) { LLFloaterTools* floaterp = (LLFloaterTools*)data; @@ -933,7 +923,7 @@ void commit_select_component(LLUICtrl *ctrl, void *data) } } -void commit_grid_mode(LLUICtrl *ctrl, void *data) +void commit_grid_mode(LLUICtrl *ctrl) { LLComboBox* combo = (LLComboBox*)ctrl; @@ -948,10 +938,9 @@ void LLFloaterTools::setObjectType( LLPCode pcode ) gFocusMgr.setMouseCapture(NULL); } -// static -void LLFloaterTools::onClickGridOptions(void* data) + +void LLFloaterTools::onClickGridOptions() { - //LLFloaterTools* floaterp = (LLFloaterTools*)data; LLFloaterReg::showInstance("build_options"); // RN: this makes grid options dependent on build tools window //floaterp->addDependentFloater(LLFloaterBuildOptions::getInstance(), FALSE); @@ -964,8 +953,558 @@ void LLFloaterTools::setEditTool(void* tool_pointer) LLToolMgr::getInstance()->getCurrentToolset()->selectTool( tool ); } +void LLFloaterTools::setTool(const LLSD& user_data) +{ + std::string control_name = user_data.asString(); + if(control_name == "Focus") + LLToolMgr::getInstance()->getCurrentToolset()->selectTool((LLTool *) LLToolCamera::getInstance() ); + else if (control_name == "Move" ) + LLToolMgr::getInstance()->getCurrentToolset()->selectTool( (LLTool *)LLToolGrab::getInstance() ); + else if (control_name == "Edit" ) + LLToolMgr::getInstance()->getCurrentToolset()->selectTool( (LLTool *) LLToolCompTranslate::getInstance()); + else if (control_name == "Create" ) + LLToolMgr::getInstance()->getCurrentToolset()->selectTool( (LLTool *) LLToolCompCreate::getInstance()); + else if (control_name == "Land" ) + LLToolMgr::getInstance()->getCurrentToolset()->selectTool( (LLTool *) LLToolSelectLand::getInstance()); + else + llwarns<<" no parameter name "<setCurrentToolset(gBasicToolset); LLFloater::onFocusReceived(); } + +// Media stuff +void LLFloaterTools::refreshMedia() +{ + getMediaState(); + LLFloaterMediaSettings::getInstance(); + LLFloaterMediaSettings::initValues(mMediaSettings ); +} + + + +void LLFloaterTools::getMediaState() +{ + LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + + if( !objectp ) + { + childSetEnabled("media_tex", FALSE); + childSetEnabled("add_media", FALSE); + childSetEnabled("delete_media", FALSE); + childSetEnabled("edit_media", FALSE); + updateMediaSettings(); + return; + } + + bool editable = gAgent.isGodlike() || (objectp->permModify() && objectp->getPCode() == LL_PCODE_VOLUME); + + // Media settings + U8 has_media = (U8)0; + struct media_functor : public LLSelectedTEGetFunctor + { + U8 get(LLViewerObject* object, S32 face) + { + return (object->getTE(face)->getMediaTexGen()); + } + } func; + bool identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, has_media ); + + // update UI depending on whether "object" (prim or face) has media + // and whether or not you are allowed to edit it. + bool bool_has_media = (has_media & LLTextureEntry::MF_HAS_MEDIA); + childSetEnabled("media_tex", bool_has_media & editable); + childSetEnabled( "edit_media", bool_has_media & editable ); + childSetEnabled( "delete_media", bool_has_media & editable ); + childSetEnabled( "add_media", ( ! bool_has_media ) & editable ); + + // load values for media settings + updateMediaSettings(); + + // if identical is set, all faces are same + if ( identical ) + { + // TODO: display a list of all media on the face - use 'identical' flag + }; +} + + +////////////////////////////////////////////////////////////////////////////// +// called when a user wants to add media to a prim or prim face +void LLFloaterTools::onClickBtnAddMedia() +{ + // check for the edit tool and now many faces are selected + LLTool *tool = LLToolMgr::getInstance()->getCurrentTool(); + if((tool != LLToolFace::getInstance()) || LLSelectMgr::getInstance()->getSelection()->isMultipleTESelected()) + { + LLNotifications::instance().add("MultipleFacesSelected",LLSD(), LLSD(), multipleFacesSelectedConfirm); + + } + else + { + onClickBtnEditMedia(); + } + +} + +// static +bool LLFloaterTools::multipleFacesSelectedConfirm(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + switch( option ) + { + case 0: // "Yes" + gFloaterTools->onClickBtnEditMedia(); + break; + case 1: // "No" + default: + break; + } + return false; +} + +////////////////////////////////////////////////////////////////////////////// +// called when a user wants to edit existing media settings on a prim or prim face +// TODO: test if there is media on the item and only allow editing if present +void LLFloaterTools::onClickBtnEditMedia() +{ + refreshMedia(); + LLFloaterReg::showInstance("media_settings"); +} + +////////////////////////////////////////////////////////////////////////////// +// called when a user wants to delete media from a prim or prim face +void LLFloaterTools::onClickBtnDeleteMedia() +{ + LLNotifications::instance().add("DeleteMedia", LLSD(), LLSD(), deleteMediaConfirm); +} + + +// static +bool LLFloaterTools::deleteMediaConfirm(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + switch( option ) + { + case 0: // "Yes" + LLSelectMgr::getInstance()->selectionSetMedia( 0 ); + if(LLFloaterReg::instanceVisible("media_settings")) + { + LLFloaterReg::hideInstance("media_settings"); + } + break; + + case 1: // "No" + default: + break; + } + return false; +} + +////////////////////////////////////////////////////////////////////////////// +// +void LLFloaterTools::updateMediaSettings() +{ + bool identical( false ); + std::string base_key( "" ); + std::string value_str( "" ); + int value_int = 0; + bool value_bool = false; + LLObjectSelectionHandle selected_objects =LLSelectMgr::getInstance()->getSelection(); + // TODO: (CP) refactor this using something clever or boost or both !! + + LLMediaEntry default_media_data; + + // controls + U8 value_u8 = default_media_data.getControls(); + struct functor_getter_controls : public LLSelectedTEGetFunctor< U8 > + { + U8 get( LLViewerObject* object, S32 face ) + { + if ( object ) + if ( object->getTE(face) ) + if ( object->getTE(face)->getMediaData() ) + return object->getTE(face)->getMediaData()->getControls(); + LLMediaEntry default_media_data; + return default_media_data.getControls(); + }; + + } func_controls; + identical = selected_objects->getSelectedTEValue( &func_controls, value_u8 ); + base_key = std::string( LLMediaEntry::CONTROLS_KEY ); + mMediaSettings[ base_key ] = value_u8; + mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; + + // First click (formerly left click) + value_bool = default_media_data.getFirstClickInteract(); + struct functor_getter_first_click : public LLSelectedTEGetFunctor< bool > + { + bool get( LLViewerObject* object, S32 face ) + { + if ( object ) + if ( object->getTE(face) ) + if ( object->getTE(face)->getMediaData() ) + return object->getTE(face)->getMediaData()->getFirstClickInteract(); + LLMediaEntry default_media_data; + return default_media_data.getFirstClickInteract(); + }; + + } func_first_click; + identical = selected_objects->getSelectedTEValue( &func_first_click, value_bool ); + base_key = std::string( LLMediaEntry::FIRST_CLICK_INTERACT_KEY ); + mMediaSettings[ base_key ] = value_bool; + mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; + + // Home URL + value_str = default_media_data.getHomeURL(); + struct functor_getter_home_url : public LLSelectedTEGetFunctor< std::string > + { + std::string get( LLViewerObject* object, S32 face ) + { + if ( object ) + if ( object->getTE(face) ) + if ( object->getTE(face)->getMediaData() ) + return object->getTE(face)->getMediaData()->getHomeURL(); + LLMediaEntry default_media_data; + return default_media_data.getHomeURL(); + }; + + } func_home_url; + identical = selected_objects->getSelectedTEValue( &func_home_url, value_str ); + base_key = std::string( LLMediaEntry::HOME_URL_KEY ); + mMediaSettings[ base_key ] = value_str; + mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; + llwarns<<"Angela debug : home url string == "< + { + std::string get( LLViewerObject* object, S32 face ) + { + if ( object ) + if ( object->getTE(face) ) + if ( object->getTE(face)->getMediaData() ) + return object->getTE(face)->getMediaData()->getCurrentURL(); + LLMediaEntry default_media_data; + return default_media_data.getCurrentURL(); + }; + + } func_current_url; + identical = selected_objects->getSelectedTEValue( &func_current_url, value_str ); + base_key = std::string( LLMediaEntry::CURRENT_URL_KEY ); + mMediaSettings[ base_key ] = value_str; + mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; + + // Auto zoom + value_bool = default_media_data.getAutoZoom(); + struct functor_getter_auto_zoom : public LLSelectedTEGetFunctor< bool > + { + bool get( LLViewerObject* object, S32 face ) + { + if ( object ) + if ( object->getTE(face) ) + if ( object->getTE(face)->getMediaData() ) + return object->getTE(face)->getMediaData()->getAutoZoom(); + LLMediaEntry default_media_data; + return default_media_data.getAutoZoom(); + }; + + } func_auto_zoom; + identical = selected_objects->getSelectedTEValue( &func_auto_zoom, value_bool ); + base_key = std::string( LLMediaEntry::AUTO_ZOOM_KEY ); + mMediaSettings[ base_key ] = value_bool; + mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; + + // Auto play + value_bool = default_media_data.getAutoPlay(); + struct functor_getter_auto_play : public LLSelectedTEGetFunctor< bool > + { + bool get( LLViewerObject* object, S32 face ) + { + if ( object ) + if ( object->getTE(face) ) + if ( object->getTE(face)->getMediaData() ) + return object->getTE(face)->getMediaData()->getAutoPlay(); + LLMediaEntry default_media_data; + return default_media_data.getAutoPlay(); + }; + + } func_auto_play; + identical = selected_objects->getSelectedTEValue( &func_auto_play, value_bool ); + base_key = std::string( LLMediaEntry::AUTO_PLAY_KEY ); + mMediaSettings[ base_key ] = value_bool; + mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; + + // Auto scale + value_bool = default_media_data.getAutoScale(); + struct functor_getter_auto_scale : public LLSelectedTEGetFunctor< bool > + { + bool get( LLViewerObject* object, S32 face ) + { + if ( object ) + if ( object->getTE(face) ) + if ( object->getTE(face)->getMediaData() ) + return object->getTE(face)->getMediaData()->getAutoScale(); + LLMediaEntry default_media_data; + return default_media_data.getAutoScale();; + }; + + } func_auto_scale; + identical = selected_objects->getSelectedTEValue( &func_auto_scale, value_bool ); + base_key = std::string( LLMediaEntry::AUTO_SCALE_KEY ); + mMediaSettings[ base_key ] = value_bool; + mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; + + // Auto loop + value_bool = default_media_data.getAutoLoop(); + struct functor_getter_auto_loop : public LLSelectedTEGetFunctor< bool > + { + bool get( LLViewerObject* object, S32 face ) + { + if ( object ) + if ( object->getTE(face) ) + if ( object->getTE(face)->getMediaData() ) + return object->getTE(face)->getMediaData()->getAutoLoop(); + LLMediaEntry default_media_data; + return default_media_data.getAutoLoop(); + }; + + } func_auto_loop; + identical = selected_objects->getSelectedTEValue( &func_auto_loop, value_bool ); + base_key = std::string( LLMediaEntry::AUTO_LOOP_KEY ); + mMediaSettings[ base_key ] = value_bool; + mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; + + // width pixels (if not auto scaled) + value_int = default_media_data.getWidthPixels(); + struct functor_getter_width_pixels : public LLSelectedTEGetFunctor< int > + { + int get( LLViewerObject* object, S32 face ) + { + if ( object ) + if ( object->getTE(face) ) + if ( object->getTE(face)->getMediaData() ) + return object->getTE(face)->getMediaData()->getWidthPixels(); + LLMediaEntry default_media_data; + return default_media_data.getWidthPixels(); + }; + + } func_width_pixels; + identical = selected_objects->getSelectedTEValue( &func_width_pixels, value_int ); + base_key = std::string( LLMediaEntry::WIDTH_PIXELS_KEY ); + mMediaSettings[ base_key ] = value_int; + mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; + + // height pixels (if not auto scaled) + value_int = default_media_data.getHeightPixels(); + struct functor_getter_height_pixels : public LLSelectedTEGetFunctor< int > + { + int get( LLViewerObject* object, S32 face ) + { + if ( object ) + if ( object->getTE(face) ) + if ( object->getTE(face)->getMediaData() ) + return object->getTE(face)->getMediaData()->getHeightPixels(); + LLMediaEntry default_media_data; + return default_media_data.getHeightPixels(); + }; + + } func_height_pixels; + identical = selected_objects->getSelectedTEValue( &func_height_pixels, value_int ); + base_key = std::string( LLMediaEntry::HEIGHT_PIXELS_KEY ); + mMediaSettings[ base_key ] = value_int; + mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; + + // Enable Alt image + value_bool = default_media_data.getAltImageEnable(); + struct functor_getter_enable_alt_image : public LLSelectedTEGetFunctor< bool > + { + bool get( LLViewerObject* object, S32 face ) + { + if ( object ) + if ( object->getTE(face) ) + if ( object->getTE(face)->getMediaData() ) + return object->getTE(face)->getMediaData()->getAltImageEnable(); + LLMediaEntry default_media_data; + return default_media_data.getAltImageEnable(); + }; + + } func_enable_alt_image; + identical = selected_objects->getSelectedTEValue( &func_enable_alt_image, value_bool ); + base_key = std::string( LLMediaEntry::ALT_IMAGE_ENABLE_KEY ); + mMediaSettings[ base_key ] = value_bool; + mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; + + // Perms - owner interact + value_bool = 0 != ( default_media_data.getPermsInteract() & LLMediaEntry::PERM_OWNER ); + struct functor_getter_perms_owner_interact : public LLSelectedTEGetFunctor< bool > + { + bool get( LLViewerObject* object, S32 face ) + { + if ( object ) + if ( object->getTE(face) ) + if ( object->getTE(face)->getMediaData() ) + return (0 != (object->getTE(face)->getMediaData()->getPermsInteract() & LLMediaEntry::PERM_OWNER)); + LLMediaEntry default_media_data; + return 0 != ( default_media_data.getPermsInteract() & LLMediaEntry::PERM_OWNER ); + }; + + } func_perms_owner_interact; + identical = selected_objects->getSelectedTEValue( &func_perms_owner_interact, value_bool ); + base_key = std::string( LLPanelContents::PERMS_OWNER_INTERACT_KEY ); + mMediaSettings[ base_key ] = value_bool; + mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; + + // Perms - owner control + value_bool = 0 != ( default_media_data.getPermsControl() & LLMediaEntry::PERM_OWNER ); + struct functor_getter_perms_owner_control : public LLSelectedTEGetFunctor< bool > + { + bool get( LLViewerObject* object, S32 face ) + { + if ( object ) + if ( object->getTE(face) ) + if ( object->getTE(face)->getMediaData() ) + return (0 != (object->getTE(face)->getMediaData()->getPermsControl() & LLMediaEntry::PERM_OWNER)); + LLMediaEntry default_media_data; + return 0 != ( default_media_data.getPermsControl() & LLMediaEntry::PERM_OWNER ); + }; + + } func_perms_owner_control; + identical = selected_objects ->getSelectedTEValue( &func_perms_owner_control, value_bool ); + base_key = std::string( LLPanelContents::PERMS_OWNER_CONTROL_KEY ); + mMediaSettings[ base_key ] = value_bool; + mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; + + // Perms - group interact + value_bool = 0 != ( default_media_data.getPermsInteract() & LLMediaEntry::PERM_GROUP ); + struct functor_getter_perms_group_interact : public LLSelectedTEGetFunctor< bool > + { + bool get( LLViewerObject* object, S32 face ) + { + if ( object ) + if ( object->getTE(face) ) + if ( object->getTE(face)->getMediaData() ) + return (0 != (object->getTE(face)->getMediaData()->getPermsInteract() & LLMediaEntry::PERM_GROUP)); + LLMediaEntry default_media_data; + return 0 != ( default_media_data.getPermsInteract() & LLMediaEntry::PERM_GROUP ); + }; + + } func_perms_group_interact; + identical = selected_objects->getSelectedTEValue( &func_perms_group_interact, value_bool ); + base_key = std::string( LLPanelContents::PERMS_GROUP_INTERACT_KEY ); + mMediaSettings[ base_key ] = value_bool; + mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; + + // Perms - group control + value_bool = 0 != ( default_media_data.getPermsControl() & LLMediaEntry::PERM_GROUP ); + struct functor_getter_perms_group_control : public LLSelectedTEGetFunctor< bool > + { + bool get( LLViewerObject* object, S32 face ) + { + if ( object ) + if ( object->getTE(face) ) + if ( object->getTE(face)->getMediaData() ) + return (0 != (object->getTE(face)->getMediaData()->getPermsControl() & LLMediaEntry::PERM_GROUP)); + LLMediaEntry default_media_data; + return 0 != ( default_media_data.getPermsControl() & LLMediaEntry::PERM_GROUP ); + }; + + } func_perms_group_control; + identical = selected_objects->getSelectedTEValue( &func_perms_group_control, value_bool ); + base_key = std::string( LLPanelContents::PERMS_GROUP_CONTROL_KEY ); + mMediaSettings[ base_key ] = value_bool; + mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; + + // Perms - anyone interact + value_bool = 0 != ( default_media_data.getPermsInteract() & LLMediaEntry::PERM_ANYONE ); + struct functor_getter_perms_anyone_interact : public LLSelectedTEGetFunctor< bool > + { + bool get( LLViewerObject* object, S32 face ) + { + if ( object ) + if ( object->getTE(face) ) + if ( object->getTE(face)->getMediaData() ) + return (0 != (object->getTE(face)->getMediaData()->getPermsInteract() & LLMediaEntry::PERM_ANYONE)); + LLMediaEntry default_media_data; + return 0 != ( default_media_data.getPermsInteract() & LLMediaEntry::PERM_ANYONE ); + }; + + } func_perms_anyone_interact; + identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func_perms_anyone_interact, value_bool ); + base_key = std::string( LLPanelContents::PERMS_ANYONE_INTERACT_KEY ); + mMediaSettings[ base_key ] = value_bool; + mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; + + // Perms - anyone control + value_bool = 0 != ( default_media_data.getPermsControl() & LLMediaEntry::PERM_ANYONE ); + struct functor_getter_perms_anyone_control : public LLSelectedTEGetFunctor< bool > + { + bool get( LLViewerObject* object, S32 face ) + { + if ( object ) + if ( object->getTE(face) ) + if ( object->getTE(face)->getMediaData() ) + return (0 != (object->getTE(face)->getMediaData()->getPermsControl() & LLMediaEntry::PERM_ANYONE)); + LLMediaEntry default_media_data; + return 0 != ( default_media_data.getPermsControl() & LLMediaEntry::PERM_ANYONE ); + }; + + } func_perms_anyone_control; + identical = selected_objects->getSelectedTEValue( &func_perms_anyone_control, value_bool ); + base_key = std::string( LLPanelContents::PERMS_ANYONE_CONTROL_KEY ); + mMediaSettings[ base_key ] = value_bool; + mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; + + // security - whitelist enable + value_bool = default_media_data.getWhiteListEnable(); + struct functor_getter_whitelist_enable : public LLSelectedTEGetFunctor< bool > + { + bool get( LLViewerObject* object, S32 face ) + { + if ( object ) + if ( object->getTE(face) ) + if ( object->getTE(face)->getMediaData() ) + return object->getTE(face)->getMediaData()->getWhiteListEnable(); + LLMediaEntry default_media_data; + return default_media_data.getWhiteListEnable(); + }; + + } func_whitelist_enable; + identical = selected_objects->getSelectedTEValue( &func_whitelist_enable, value_bool ); + base_key = std::string( LLMediaEntry::WHITELIST_ENABLE_KEY ); + mMediaSettings[ base_key ] = value_bool; + mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; + + // security - whitelist URLs + std::vector value_vector_str = default_media_data.getWhiteList(); + struct functor_getter_whitelist_urls : public LLSelectedTEGetFunctor< std::vector > + { + std::vector get( LLViewerObject* object, S32 face ) + { + if ( object ) + if ( object->getTE(face) ) + if ( object->getTE(face)->getMediaData() ) + return object->getTE(face)->getMediaData()->getWhiteList(); + LLMediaEntry default_media_data; + return default_media_data.getWhiteList(); + }; + + } func_whitelist_urls; + identical = selected_objects->getSelectedTEValue( &func_whitelist_urls, value_vector_str ); + base_key = std::string( LLMediaEntry::WHITELIST_KEY ); + mMediaSettings[ base_key ].clear(); + std::vector< std::string >::iterator iter = value_vector_str.begin(); + while( iter != value_vector_str.end() ) + { + std::string white_list_url = *iter; + mMediaSettings[ base_key ].append( white_list_url ); + ++iter; + }; + + mMediaSettings[ base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ) ] = ! identical; +} + diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h index 1b9f1d31ec..008c9677ed 100644 --- a/indra/newview/llfloatertools.h +++ b/indra/newview/llfloatertools.h @@ -100,13 +100,24 @@ public: void setStatusText(const std::string& text); static void setEditTool(void* data); + void setTool(const LLSD& user_data); void saveLastTool(); + void onClickBtnDeleteMedia(); + void onClickBtnAddMedia(); + void onClickBtnEditMedia(); + + private: void onClose(); void refresh(); - + void refreshMedia(); + void getMediaState(); + void updateMediaSettings(); + void getMeidaState(); + static bool deleteMediaConfirm(const LLSD& notification, const LLSD& response); + static bool multipleFacesSelectedConfirm(const LLSD& notification, const LLSD& response); static void setObjectType( LLPCode pcode ); - static void onClickGridOptions(void* data); + void onClickGridOptions(); public: LLButton *mBtnFocus; @@ -175,6 +186,10 @@ private: BOOL mDirty; std::map mStatusText; + +protected: + LLSD mMediaSettings; + }; extern LLFloaterTools *gFloaterTools; diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp index 1e975cd447..2b01a56373 100644 --- a/indra/newview/llfloaterurlentry.cpp +++ b/indra/newview/llfloaterurlentry.cpp @@ -35,6 +35,7 @@ #include "llfloaterurlentry.h" #include "llpanellandmedia.h" +#include "llpanelface.h" // project includes #include "llcombobox.h" @@ -145,13 +146,23 @@ void LLFloaterURLEntry::buildURLHistory() void LLFloaterURLEntry::headerFetchComplete(U32 status, const std::string& mime_type) { - LLPanelLandMedia* panel_media = (LLPanelLandMedia*)mPanelLandMediaHandle.get(); + LLPanelLandMedia* panel_media = dynamic_cast(mPanelLandMediaHandle.get()); if (panel_media) { // status is ignored for now -- error = "none/none" panel_media->setMediaType(mime_type); panel_media->setMediaURL(mMediaURLEdit->getValue().asString()); } + else + { + LLPanelFace* panel_face = dynamic_cast(mPanelLandMediaHandle.get()); + if(panel_face) + { + panel_face->setMediaType(mime_type); + panel_face->setMediaURL(mMediaURLEdit->getValue().asString()); + } + + } // Decrement the cursor getWindow()->decBusyCount(); childSetVisible("loading_label", false); @@ -159,29 +170,18 @@ void LLFloaterURLEntry::headerFetchComplete(U32 status, const std::string& mime_ } // static -LLHandle LLFloaterURLEntry::show(LLHandle parent) +LLHandle LLFloaterURLEntry::show(LLHandle parent, const std::string media_url) { - if (sInstance) - { - sInstance->openFloater(); - } - else + if (!sInstance) { sInstance = new LLFloaterURLEntry(parent); } - sInstance->updateFromLandMediaPanel(); + sInstance->openFloater(); + sInstance->addURLToCombobox(media_url); return sInstance->getHandle(); } -void LLFloaterURLEntry::updateFromLandMediaPanel() -{ - LLPanelLandMedia* panel_media = (LLPanelLandMedia*)mPanelLandMediaHandle.get(); - if (panel_media) - { - std::string media_url = panel_media->getMediaURL(); - addURLToCombobox(media_url); - } -} + bool LLFloaterURLEntry::addURLToCombobox(const std::string& media_url) { diff --git a/indra/newview/llfloaterurlentry.h b/indra/newview/llfloaterurlentry.h index 0aeca823b8..6dd9c8453c 100644 --- a/indra/newview/llfloaterurlentry.h +++ b/indra/newview/llfloaterurlentry.h @@ -44,10 +44,8 @@ class LLFloaterURLEntry : public LLFloater public: // Can only be shown by LLPanelLandMedia, and pushes data back into // that panel via the handle. - static LLHandle show(LLHandle panel_land_media_handle); + static LLHandle show(LLHandle panel_land_media_handle, const std::string media_url); /*virtual*/ BOOL postBuild(); - void updateFromLandMediaPanel(); - void headerFetchComplete(U32 status, const std::string& mime_type); bool addURLToCombobox(const std::string& media_url); diff --git a/indra/newview/llfloaterwhitelistentry.cpp b/indra/newview/llfloaterwhitelistentry.cpp new file mode 100644 index 0000000000..551a5191fc --- /dev/null +++ b/indra/newview/llfloaterwhitelistentry.cpp @@ -0,0 +1,97 @@ +/** + * @file llfloaterwhitelistentry.cpp + * @brief LLFloaterWhistListEntry class implementation + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloaterreg.h" +#include "llfloatermediasettings.h" +#include "llfloaterwhitelistentry.h" +#include "llpanelmediasettingssecurity.h" +#include "lluictrlfactory.h" +#include "llwindow.h" +#include "llviewerwindow.h" +#include "lllineeditor.h" + + +/////////////////////////////////////////////////////////////////////////////// +// +LLFloaterWhiteListEntry::LLFloaterWhiteListEntry( const LLSD& key ) : + LLFloater(key) +{ +// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_whitelist_entry.xml"); +} + +/////////////////////////////////////////////////////////////////////////////// +// +LLFloaterWhiteListEntry::~LLFloaterWhiteListEntry() +{ +} + +/////////////////////////////////////////////////////////////////////////////// +// +BOOL LLFloaterWhiteListEntry::postBuild() +{ + mWhiteListEdit = getChild("whitelist_entry"); + + childSetAction("cancel_btn", onBtnCancel, this); + childSetAction("ok_btn", onBtnOK, this); + + setDefaultBtn("ok_btn"); + + return TRUE; +} + +/////////////////////////////////////////////////////////////////////////////// +// static +void LLFloaterWhiteListEntry::onBtnOK( void* userdata ) +{ + LLFloaterWhiteListEntry *self =(LLFloaterWhiteListEntry *)userdata; + + LLPanelMediaSettingsSecurity* panel = LLFloaterReg::getTypedInstance("media_settings")->getPanelSecurity(); + if ( panel ) + { + std::string white_list_item = self->mWhiteListEdit->getText(); + + panel->addWhiteListItem( white_list_item ); + }; + + self->closeFloater(); +} + +/////////////////////////////////////////////////////////////////////////////// +// static +void LLFloaterWhiteListEntry::onBtnCancel( void* userdata ) +{ + LLFloaterWhiteListEntry *self =(LLFloaterWhiteListEntry *)userdata; + + self->closeFloater(); +} diff --git a/indra/newview/llfloaterwhitelistentry.h b/indra/newview/llfloaterwhitelistentry.h new file mode 100644 index 0000000000..8ab5fb78b9 --- /dev/null +++ b/indra/newview/llfloaterwhitelistentry.h @@ -0,0 +1,56 @@ +/** + * @file llfloaterwhitelistentry.h + * @brief LLFloaterWhiteListEntry class definition + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERWHITELISTENTRY_H +#define LL_LLFLOATERWHITELISTENTRY_H + +#include "llfloater.h" + +class LLLineEditor; + +class LLFloaterWhiteListEntry : + public LLFloater +{ + public: + LLFloaterWhiteListEntry(const LLSD& key); + ~LLFloaterWhiteListEntry(); + + BOOL postBuild(); + + private: + LLLineEditor* mWhiteListEdit; + + static void onBtnOK(void*); + static void onBtnCancel(void*); +}; + +#endif // LL_LLFLOATERWHITELISTENTRY_H diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 6ec098b92b..b996c15a7d 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -43,6 +43,7 @@ #include "llviewborder.h" #include "llviewercontrol.h" #include "llviewermedia.h" +#include "llviewertexture.h" #include "llviewerwindow.h" #include "llnotifications.h" #include "llweb.h" @@ -63,6 +64,9 @@ LLMediaCtrl::Params::Params() border_visible("border_visible", true), ignore_ui_scale("ignore_ui_scale", true), hide_loading("hide_loading", false), + decouple_texture_size("decouple_texture_size", false), + texture_width("texture_width", 1024), + texture_height("texture_height", 1024), caret_color("caret_color") {} @@ -82,10 +86,12 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : mMediaSource( 0 ), mTakeFocusOnClick( true ), mCurrentNavUrl( "" ), - mLastSetCursor( UI_CURSOR_ARROW ), mStretchToFill( true ), mMaintainAspectRatio ( true ), - mHideLoading (false) + mHideLoading (false), + mDecoupleTextureSize ( false ), + mTextureWidth ( 1024 ), + mTextureHeight ( 1024 ) { { LLColor4 color = p.caret_color().get(); @@ -99,24 +105,29 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : setBorderVisible(p.border_visible()); mHideLoading = p.hide_loading(); + + setDecoupleTextureSize(p.decouple_texture_size()); + + setTextureSize(p.texture_width(), p.texture_height()); - S32 screen_width = mIgnoreUIScale ? - llround((F32)getRect().getWidth() * LLUI::sGLScaleFactor.mV[VX]) : getRect().getWidth(); - S32 screen_height = mIgnoreUIScale ? - llround((F32)getRect().getHeight() * LLUI::sGLScaleFactor.mV[VY]) : getRect().getHeight(); + if(!getDecoupleTextureSize()) + { + S32 screen_width = mIgnoreUIScale ? + llround((F32)getRect().getWidth() * LLUI::sGLScaleFactor.mV[VX]) : getRect().getWidth(); + S32 screen_height = mIgnoreUIScale ? + llround((F32)getRect().getHeight() * LLUI::sGLScaleFactor.mV[VY]) : getRect().getHeight(); + + setTextureSize(screen_width, screen_height); + } mMediaTextureID.generate(); - mMediaSource = LLViewerMedia::newMediaImpl(mHomePageUrl, mMediaTextureID, screen_width, screen_height, false, false, "text/html"); - if ( !mMediaSource ) + + // We don't need to create the media source up front anymore unless we have a non-empty home URL to navigate to. + if(!mHomePageUrl.empty()) { - llwarns << "media source create failed " << llendl; - // return; + navigateHome(); } - - mMediaSource->setVisible( getVisible() ); - - mMediaSource->addObserver( this ); - + // FIXME: How do we create a bevel now? // LLRect border_rect( 0, getRect().getHeight() + 2, getRect().getWidth() + 2, 0 ); // mBorder = new LLViewBorder( std::string("web control border"), border_rect, LLViewBorder::BEVEL_IN ); @@ -179,9 +190,10 @@ BOOL LLMediaCtrl::handleHover( S32 x, S32 y, MASK mask ) convertInputCoords(x, y); if (mMediaSource) + { mMediaSource->mouseMove(x, y); - - gViewerWindow->setCursor(mLastSetCursor); + gViewerWindow->setCursor(mMediaSource->getLastSetCursor()); + } return TRUE; } @@ -389,19 +401,19 @@ void LLMediaCtrl::onVisibilityChange ( const LLSD& new_visibility ) // void LLMediaCtrl::reshape( S32 width, S32 height, BOOL called_from_parent ) { - S32 screen_width = mIgnoreUIScale ? llround((F32)width * LLUI::sGLScaleFactor.mV[VX]) : width; - S32 screen_height = mIgnoreUIScale ? llround((F32)height * LLUI::sGLScaleFactor.mV[VY]) : height; - -// llinfos << "reshape called with width = " << width << ", height = " << height << llendl; - - // when floater is minimized, these sizes are negative - if ( screen_height > 0 && screen_width > 0 ) + if(!getDecoupleTextureSize()) { - mMediaSource->setSize(screen_width, screen_height); - mForceUpdate = true; - } + S32 screen_width = mIgnoreUIScale ? llround((F32)width * LLUI::sGLScaleFactor.mV[VX]) : width; + S32 screen_height = mIgnoreUIScale ? llround((F32)height * LLUI::sGLScaleFactor.mV[VY]) : height; - LLPanel::reshape( width, height, called_from_parent ); + // when floater is minimized, these sizes are negative + if ( screen_height > 0 && screen_width > 0 ) + { + setTextureSize(screen_width, screen_height); + } + } + + LLUICtrl::reshape( width, height, called_from_parent ); } //////////////////////////////////////////////////////////////////////////////// @@ -475,9 +487,10 @@ void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type) return; } - if (mMediaSource) + if (ensureMediaSourceExists()) { mCurrentNavUrl = url_in; + mMediaSource->setSize(mTextureWidth, mTextureHeight); mMediaSource->navigateTo(url_in, mime_type, mime_type.empty()); } } @@ -513,9 +526,10 @@ void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::str return; } } - if (mMediaSource) + if (ensureMediaSourceExists()) { mCurrentNavUrl = expanded_filename; + mMediaSource->setSize(mTextureWidth, mTextureHeight); mMediaSource->navigateTo(expanded_filename, "text/html", false); } @@ -525,11 +539,11 @@ void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::str // void LLMediaCtrl::navigateHome() { - if( mHomePageUrl.length() ) + if (ensureMediaSourceExists()) { - if (mMediaSource) - mMediaSource->navigateTo(mHomePageUrl); - }; + mMediaSource->setSize(mTextureWidth, mTextureHeight); + mMediaSource->navigateHome(); + } } //////////////////////////////////////////////////////////////////////////////// @@ -537,6 +551,10 @@ void LLMediaCtrl::navigateHome() void LLMediaCtrl::setHomePageUrl( const std::string urlIn ) { mHomePageUrl = urlIn; + if (mMediaSource) + { + mMediaSource->setHomeURL(mHomePageUrl); + } } //////////////////////////////////////////////////////////////////////////////// @@ -546,6 +564,21 @@ bool LLMediaCtrl::setCaretColor(unsigned int red, unsigned int green, unsigned i //NOOP return false; } + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::setTextureSize(S32 width, S32 height) +{ + mTextureWidth = width; + mTextureHeight = height; + + if(mMediaSource) + { + mMediaSource->setSize(mTextureWidth, mTextureHeight); + mForceUpdate = true; + } +} + //////////////////////////////////////////////////////////////////////////////// // std::string LLMediaCtrl::getHomePageUrl() @@ -553,6 +586,38 @@ std::string LLMediaCtrl::getHomePageUrl() return mHomePageUrl; } +//////////////////////////////////////////////////////////////////////////////// +// +bool LLMediaCtrl::ensureMediaSourceExists() +{ + if(mMediaSource.isNull()) + { + // If we don't already have a media source, try to create one. + mMediaSource = LLViewerMedia::newMediaImpl(mMediaTextureID, mTextureWidth, mTextureHeight); + if ( mMediaSource ) + { + mMediaSource->setUsedInUI(true); + mMediaSource->setHomeURL(mHomePageUrl); + mMediaSource->setVisible( getVisible() ); + mMediaSource->addObserver( this ); + } + else + { + llwarns << "media source create failed " << llendl; + // return; + } + } + + return !mMediaSource.isNull(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::unloadMediaSource() +{ + mMediaSource = NULL; +} + //////////////////////////////////////////////////////////////////////////////// // LLPluginClassMedia* LLMediaCtrl::getMediaPlugin() @@ -574,13 +639,17 @@ void LLMediaCtrl::draw() { return; } + + if(!media_plugin || (!media_plugin->textureValid())) + { + // Don't try to draw without a valid texture + return; + } LLViewerMediaTexture* media_texture = LLViewerTextureManager::findMediaTexture(mMediaTextureID); if (!media_texture ) - { return; - } if ( gRestoreGL == 1 ) { @@ -658,7 +727,7 @@ void LLMediaCtrl::draw() width = llmin(media_plugin->getWidth(), r.getWidth()); height = llmin(media_plugin->getHeight(), r.getHeight()); } - + x_offset = (r.getWidth() - width) / 2; y_offset = (r.getHeight() - height) / 2; @@ -774,24 +843,9 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) case MEDIA_EVENT_CURSOR_CHANGED: { LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << self->getCursorName() << LL_ENDL; - - std::string cursor = self->getCursorName(); - - if(cursor == "arrow") - mLastSetCursor = UI_CURSOR_ARROW; - else if(cursor == "ibeam") - mLastSetCursor = UI_CURSOR_IBEAM; - else if(cursor == "splith") - mLastSetCursor = UI_CURSOR_SIZEWE; - else if(cursor == "splitv") - mLastSetCursor = UI_CURSOR_SIZENS; - else if(cursor == "hand") - mLastSetCursor = UI_CURSOR_HAND; - else // for anything else, default to the arrow - mLastSetCursor = UI_CURSOR_ARROW; - }; + } break; - + case MEDIA_EVENT_NAVIGATE_BEGIN: { LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_BEGIN, url is " << self->getNavigateURI() << LL_ENDL; diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index a19b3ad67b..5ea03f1e6c 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -37,7 +37,6 @@ #include "lluictrl.h" #include "llframetimer.h" -#include "lldynamictexture.h" class LLViewBorder; class LLUICtrlFactory; @@ -50,7 +49,6 @@ class LLMediaCtrl : public LLViewerMediaEventEmitter { LOG_CLASS(LLMediaCtrl); - public: struct Params : public LLInitParam::Block { @@ -58,7 +56,11 @@ public: Optional border_visible, ignore_ui_scale, - hide_loading; + hide_loading, + decouple_texture_size; + + Optional texture_width, + texture_height; Optional caret_color; @@ -127,9 +129,17 @@ public: void setForceUpdate(bool force_update) { mForceUpdate = force_update; } bool getForceUpdate() { return mForceUpdate; } + bool ensureMediaSourceExists(); + void unloadMediaSource(); + LLPluginClassMedia* getMediaPlugin(); bool setCaretColor( unsigned int red, unsigned int green, unsigned int blue ); + + void setDecoupleTextureSize(bool decouple) { mDecoupleTextureSize = decouple; } + bool getDecoupleTextureSize() { return mDecoupleTextureSize; } + + void setTextureSize(S32 width, S32 height); // over-rides @@ -173,10 +183,12 @@ public: bool mAlwaysRefresh; viewer_media_t mMediaSource; bool mTakeFocusOnClick; - ECursorType mLastSetCursor; bool mStretchToFill; bool mMaintainAspectRatio; bool mHideLoading; + bool mDecoupleTextureSize; + S32 mTextureWidth; + S32 mTextureHeight; }; #endif // LL_LLMediaCtrl_H diff --git a/indra/newview/llpanelcontents.cpp b/indra/newview/llpanelcontents.cpp index 5da646497b..ea528a1df8 100644 --- a/indra/newview/llpanelcontents.cpp +++ b/indra/newview/llpanelcontents.cpp @@ -72,6 +72,13 @@ // // Globals // +const char* LLPanelContents::TENTATIVE_SUFFIX = "_tentative"; +const char* LLPanelContents::PERMS_OWNER_INTERACT_KEY = "perms_owner_interact"; +const char* LLPanelContents::PERMS_OWNER_CONTROL_KEY = "perms_owner_control"; +const char* LLPanelContents::PERMS_GROUP_INTERACT_KEY = "perms_group_interact"; +const char* LLPanelContents::PERMS_GROUP_CONTROL_KEY = "perms_group_control"; +const char* LLPanelContents::PERMS_ANYONE_INTERACT_KEY = "perms_anyone_interact"; +const char* LLPanelContents::PERMS_ANYONE_CONTROL_KEY = "perms_anyone_control"; BOOL LLPanelContents::postBuild() { @@ -83,7 +90,7 @@ BOOL LLPanelContents::postBuild() childSetAction("button permissions",&LLPanelContents::onClickPermissions, this); mPanelInventory = getChild("contents_inventory"); - + return TRUE; } @@ -112,7 +119,7 @@ void LLPanelContents::getState(LLViewerObject *objectp ) LLSelectMgr::getInstance()->selectGetGroup(group_id); // sets group_id as a side effect SL-23488 // BUG? Check for all objects being editable? - BOOL editable = gAgent.isGodlike() + bool editable = gAgent.isGodlike() || (objectp->permModify() && ( objectp->permYouOwner() || ( !group_id.isNull() && gAgent.isInGroup(group_id) ))); // solves SL-23488 BOOL all_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ); @@ -123,8 +130,8 @@ void LLPanelContents::getState(LLViewerObject *objectp ) all_volume && ((LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() == 1) || (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1))); -} +} void LLPanelContents::refresh() { @@ -135,7 +142,7 @@ void LLPanelContents::refresh() if (mPanelInventory) { mPanelInventory->refresh(); - } + } } diff --git a/indra/newview/llpanelcontents.h b/indra/newview/llpanelcontents.h index de1914bff9..bab980b524 100644 --- a/indra/newview/llpanelcontents.h +++ b/indra/newview/llpanelcontents.h @@ -51,11 +51,23 @@ public: void refresh(); - static void onClickNewScript( void* userdata); - static void onClickPermissions( void* userdata); + + static void onClickNewScript(void*); + static void onClickPermissions(void*); + + // Key suffix for "tentative" fields + static const char* TENTATIVE_SUFFIX; + + // These aren't fields in LLMediaEntry, so we have to define them ourselves for checkbox control + static const char* PERMS_OWNER_INTERACT_KEY; + static const char* PERMS_OWNER_CONTROL_KEY; + static const char* PERMS_GROUP_INTERACT_KEY; + static const char* PERMS_GROUP_CONTROL_KEY; + static const char* PERMS_ANYONE_INTERACT_KEY; + static const char* PERMS_ANYONE_CONTROL_KEY; protected: - void getState(LLViewerObject *object); + void getState(LLViewerObject *object); public: LLPanelInventory* mPanelInventory; diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 08a50d4b6e..c61b987b1c 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -49,6 +49,7 @@ #include "llcombobox.h" #include "lldrawpoolbump.h" #include "lllineeditor.h" +#include "llmediaentry.h" #include "llresmgr.h" #include "llselectmgr.h" #include "llspinctrl.h" @@ -61,6 +62,7 @@ #include "llviewermedia.h" #include "llviewerobject.h" #include "llviewerstats.h" +#include "llvovolume.h" #include "lluictrlfactory.h" #include "llpluginclassmedia.h" @@ -70,6 +72,18 @@ BOOL LLPanelFace::postBuild() { + childSetCommitCallback("combobox shininess",&LLPanelFace::onCommitShiny,this); + childSetCommitCallback("combobox bumpiness",&LLPanelFace::onCommitBump,this); + childSetCommitCallback("TexScaleU",&LLPanelFace::onCommitTextureInfo, this); + childSetCommitCallback("checkbox flip s",&LLPanelFace::onCommitTextureInfo, this); + childSetCommitCallback("TexScaleV",&LLPanelFace::onCommitTextureInfo, this); + childSetCommitCallback("checkbox flip t",&LLPanelFace::onCommitTextureInfo, this); + childSetCommitCallback("TexRot",&LLPanelFace::onCommitTextureInfo, this); + childSetAction("button apply",&LLPanelFace::onClickApply,this); + childSetCommitCallback("TexOffsetU",LLPanelFace::onCommitTextureInfo, this); + childSetCommitCallback("TexOffsetV",LLPanelFace::onCommitTextureInfo, this); + childSetAction("button align",&LLPanelFace::onClickAutoFix,this); + LLRect rect = this->getRect(); LLTextureCtrl* mTextureCtrl; LLColorSwatchCtrl* mColorSwatch; @@ -91,7 +105,7 @@ BOOL LLPanelFace::postBuild() mTextureCtrl->setCommitCallback( boost::bind(&LLPanelFace::onCommitTexture, this, _2) ); mTextureCtrl->setOnCancelCallback( boost::bind(&LLPanelFace::onCancelTexture, this, _2) ); mTextureCtrl->setOnSelectCallback( boost::bind(&LLPanelFace::onSelectTexture, this, _2) ); - mTextureCtrl->setDragCallback(boost::bind(&LLPanelFace::onDragTexture, _2)); + mTextureCtrl->setDragCallback(boost::bind(&LLPanelFace::onDragTexture, this, _2)); mTextureCtrl->setFollowsTop(); mTextureCtrl->setFollowsLeft(); // Don't allow (no copy) or (no transfer) textures to be selected during immediate mode @@ -161,17 +175,6 @@ BOOL LLPanelFace::postBuild() mCtrlGlow->setCommitCallback(LLPanelFace::onCommitGlow, this); } - childSetCommitCallback("combobox shininess",&LLPanelFace::onCommitShiny,this); - childSetCommitCallback("combobox bumpiness",&LLPanelFace::onCommitBump,this); - childSetCommitCallback("TexScaleU",&LLPanelFace::onCommitTextureInfo, this); - childSetCommitCallback("checkbox flip s",&LLPanelFace::onCommitTextureInfo, this); - childSetCommitCallback("TexScaleV",&LLPanelFace::onCommitTextureInfo, this); - childSetCommitCallback("checkbox flip t",&LLPanelFace::onCommitTextureInfo, this); - childSetCommitCallback("TexRot",&LLPanelFace::onCommitTextureInfo, this); - childSetAction("button apply",&onClickApply,this); - childSetCommitCallback("TexOffsetU",LLPanelFace::onCommitTextureInfo, this); - childSetCommitCallback("TexOffsetV",LLPanelFace::onCommitTextureInfo, this); - childSetAction("button align",onClickAutoFix,this); clearCtrls(); @@ -382,10 +385,8 @@ void LLPanelFace::getState() BOOL editable = objectp->permModify(); // only turn on auto-adjust button if there is a media renderer and the media is loaded - childSetEnabled("textbox autofix",FALSE); - //mLabelTexAutoFix->setEnabled ( FALSE ); - childSetEnabled("button align",FALSE); - //mBtnAutoFix->setEnabled ( FALSE ); + childSetEnabled("textbox autofix", editable); + childSetEnabled("button align", editable); //if ( LLMediaEngine::getInstance()->getMediaRenderer () ) // if ( LLMediaEngine::getInstance()->getMediaRenderer ()->isLoaded () ) @@ -785,6 +786,9 @@ void LLPanelFace::getState() childSetEnabled("button align",FALSE); childSetEnabled("button apply",FALSE); + childSetEnabled("has media", FALSE); + childSetEnabled("media info set", FALSE); + } } @@ -862,7 +866,7 @@ void LLPanelFace::onCommitGlow(LLUICtrl* ctrl, void* userdata) } // static -BOOL LLPanelFace::onDragTexture(LLInventoryItem* item) +BOOL LLPanelFace::onDragTexture(LLUICtrl*, LLInventoryItem* item) { BOOL accept = TRUE; for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); @@ -917,15 +921,25 @@ void LLPanelFace::onClickApply(void* userdata) LLSelectMgr::getInstance()->selectionTexScaleAutofit( repeats_per_meter ); } -// commit the fit media texture to prim button - struct LLPanelFaceSetMediaFunctor : public LLSelectedTEFunctor { virtual bool apply(LLViewerObject* object, S32 te) { - // TODO: the media impl pointer should actually be stored by the texture - viewer_media_t pMediaImpl = LLViewerMedia::getMediaImplFromTextureID(object->getTE ( te )->getID()); - // only do this if it's a media texture + viewer_media_t pMediaImpl; + + const LLTextureEntry* tep = object->getTE(te); + const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL; + if ( mep ) + { + pMediaImpl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()); + } + + if ( pMediaImpl.isNull()) + { + // If we didn't find face media for this face, check whether this face is showing parcel media. + pMediaImpl = LLViewerMedia::getMediaImplFromTextureID(tep->getID()); + } + if ( pMediaImpl.notNull()) { LLPluginClassMedia *media = pMediaImpl->getMediaPlugin(); @@ -957,3 +971,14 @@ void LLPanelFace::onClickAutoFix(void* userdata) LLPanelFaceSendFunctor sendfunc; LLSelectMgr::getInstance()->getSelection()->applyToObjects(&sendfunc); } + + + +// TODO: I don't know who put these in or what these are for??? +void LLPanelFace::setMediaURL(const std::string& url) +{ +} +void LLPanelFace::setMediaType(const std::string& mime_type) +{ +} + diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 9600129696..6a8704ce14 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -47,6 +47,7 @@ class LLTextBox; class LLTextureCtrl; class LLUICtrl; class LLViewerObject; +class LLFloater; class LLPanelFace : public LLPanel { @@ -56,6 +57,8 @@ public: virtual ~LLPanelFace(); void refresh(); + void setMediaURL(const std::string& url); + void setMediaType(const std::string& mime_type); protected: void getState(); @@ -69,9 +72,10 @@ protected: void sendShiny(); // applies and sends shininess void sendFullbright(); // applies and sends full bright void sendGlow(); + void sendMedia(); // this function is to return TRUE if the drag should succeed. - static BOOL onDragTexture(LLInventoryItem* item); + static BOOL onDragTexture(LLUICtrl* ctrl, LLInventoryItem* item); void onCommitTexture(const LLSD& data); void onCancelTexture(const LLSD& data); @@ -87,10 +91,11 @@ protected: static void onCommitShiny( LLUICtrl* ctrl, void* userdata); static void onCommitFullbright( LLUICtrl* ctrl, void* userdata); static void onCommitGlow( LLUICtrl* ctrl, void *userdata); - + static void onClickApply(void*); static void onClickAutoFix(void*); static F32 valueGlow(LLViewerObject* object, S32 face); + }; #endif diff --git a/indra/newview/llpanellandmedia.cpp b/indra/newview/llpanellandmedia.cpp index 994bf7e3f9..42ad9820a8 100644 --- a/indra/newview/llpanellandmedia.cpp +++ b/indra/newview/llpanellandmedia.cpp @@ -122,9 +122,6 @@ BOOL LLPanelLandMedia::postBuild() mSetURLButton = getChild("set_media_url"); childSetAction("set_media_url", onSetBtn, this); - mResetURLButton = getChild("reset_media_url"); - childSetAction("reset_media_url", onResetBtn, this); - return TRUE; } @@ -215,13 +212,7 @@ void LLPanelLandMedia::refresh() mMediaTextureCtrl->setEnabled( can_change_media ); mSetURLButton->setEnabled( can_change_media ); - mResetURLButton->setEnabled( can_change_media ); - LLFloaterURLEntry* floater_url_entry = (LLFloaterURLEntry*)mURLEntryFloater.get(); - if (floater_url_entry) - { - floater_url_entry->updateFromLandMediaPanel(); - } } } @@ -341,7 +332,7 @@ void LLPanelLandMedia::onCommitAny(LLUICtrl*, void *userdata) void LLPanelLandMedia::onSetBtn(void *userdata) { LLPanelLandMedia *self = (LLPanelLandMedia *)userdata; - self->mURLEntryFloater = LLFloaterURLEntry::show( self->getHandle() ); + self->mURLEntryFloater = LLFloaterURLEntry::show( self->getHandle(), self->getMediaURL() ); LLFloater* parent_floater = gFloaterView->getParentFloater(self); if (parent_floater) { diff --git a/indra/newview/llpanellandmedia.h b/indra/newview/llpanellandmedia.h index 5ad1f9758d..3deea29d17 100644 --- a/indra/newview/llpanellandmedia.h +++ b/indra/newview/llpanellandmedia.h @@ -63,8 +63,6 @@ private: LLLineEditor* mMediaDescEdit; LLComboBox* mMediaTypeCombo; LLButton* mSetURLButton; - LLButton* mResetURLButton; - LLSpinCtrl* mMediaResetCtrl; LLSpinCtrl* mMediaHeightCtrl; LLSpinCtrl* mMediaWidthCtrl; LLTextBox* mMediaResetCtrlLabel; @@ -74,13 +72,6 @@ private: LLCheckBoxCtrl* mMediaLoopCheck; LLCheckBoxCtrl* mMediaUrlCheck; LLHandle mURLEntryFloater; - LLCheckBoxCtrl* mMediaNavigateAllowCheck; - LLCheckBoxCtrl* mMediaURLFilterCheck; - LLLineEditor* mMediaURLFilterDomainEdit; - LLButton* mMediaURLFilterAddButton; - LLButton* mMediaURLFilterRemoveButton; - LLScrollListCtrl* mURLFilterList; - LLRadioGroup* mRadioNavigateControl; diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index daf0fbd5e0..a7f66f3293 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -70,6 +70,7 @@ #include "llmediactrl.h" #include "llrootview.h" + #include "llfloatertos.h" #include "lltrans.h" #include "llglheaders.h" diff --git a/indra/newview/llpanelmediasettingsgeneral.cpp b/indra/newview/llpanelmediasettingsgeneral.cpp new file mode 100644 index 0000000000..be40d6fb5f --- /dev/null +++ b/indra/newview/llpanelmediasettingsgeneral.cpp @@ -0,0 +1,409 @@ +/** + * @file llpanelmediasettingsgeneral.cpp + * @brief LLPanelMediaSettingsGeneral class implementation + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llpanelmediasettingsgeneral.h" +#include "llcombobox.h" +#include "llcheckboxctrl.h" +#include "llspinctrl.h" +#include "lluictrlfactory.h" +#include "llviewerwindow.h" +#include "llsdutil.h" +#include "llselectmgr.h" +#include "llbutton.h" +#include "lltexturectrl.h" +#include "llurl.h" +#include "llwindow.h" +#include "llmediaentry.h" +#include "llmediactrl.h" +#include "llpanelcontents.h" +#include "llpluginclassmedia.h" +#include "llfloatermediasettings.h" + +//////////////////////////////////////////////////////////////////////////////// +// +LLPanelMediaSettingsGeneral::LLPanelMediaSettingsGeneral() : + mControls( NULL ), + mAutoLoop( NULL ), + mFirstClick( NULL ), + mAutoZoom( NULL ), + mAutoPlay( NULL ), + mAutoScale( NULL ), + mWidthPixels( NULL ), + mHeightPixels( NULL ), + mHomeURL( NULL ), + mCurrentURL( NULL ), + mAltImageEnable( NULL ), + mParent( NULL ) +{ + // build dialog from XML + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_general.xml"); + mCommitCallbackRegistrar.add("Media.ResetCurrentUrl", boost::bind(&LLPanelMediaSettingsGeneral::onBtnResetCurrentUrl, this)); +// mCommitCallbackRegistrar.add("Media.CommitHomeURL", boost::bind(&LLPanelMediaSettingsGeneral::onCommitHomeURL, this)); + +} + +//////////////////////////////////////////////////////////////////////////////// +// +BOOL LLPanelMediaSettingsGeneral::postBuild() +{ + // connect member vars with UI widgets + mAltImageEnable = getChild< LLCheckBoxCtrl >( LLMediaEntry::ALT_IMAGE_ENABLE_KEY ); + mAutoLoop = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_LOOP_KEY ); + mAutoPlay = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_PLAY_KEY ); + mAutoScale = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_SCALE_KEY ); + mAutoZoom = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_ZOOM_KEY ); + mControls = getChild< LLComboBox >( LLMediaEntry::CONTROLS_KEY ); + mCurrentURL = getChild< LLLineEditor >( LLMediaEntry::CURRENT_URL_KEY ); + mFirstClick = getChild< LLCheckBoxCtrl >( LLMediaEntry::FIRST_CLICK_INTERACT_KEY ); + mHeightPixels = getChild< LLSpinCtrl >( LLMediaEntry::HEIGHT_PIXELS_KEY ); + mHomeURL = getChild< LLLineEditor >( LLMediaEntry::HOME_URL_KEY ); + mWidthPixels = getChild< LLSpinCtrl >( LLMediaEntry::WIDTH_PIXELS_KEY ); + mPreviewMedia = getChild("preview_media"); + + // watch commit action for HOME URL + childSetCommitCallback( LLMediaEntry::HOME_URL_KEY, onCommitHomeURL, this); + + // interrogates controls and updates widgets as required + updateMediaPreview(); + updateCurrentURL(); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +LLPanelMediaSettingsGeneral::~LLPanelMediaSettingsGeneral() +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// static +void LLPanelMediaSettingsGeneral::draw() +{ + // housekeeping + LLPanel::draw(); + + // enable/disable pixel values image entry based on auto scale checkbox + if ( mAutoScale->getValue().asBoolean() == false ) + { + childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, true ); + childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, true ); + } + else + { + childSetEnabled( LLMediaEntry::WIDTH_PIXELS_KEY, false ); + childSetEnabled( LLMediaEntry::HEIGHT_PIXELS_KEY, false ); + }; + + // enable/disable UI based on type of media + bool reset_button_is_active = true; + if( mPreviewMedia ) + { + LLPluginClassMedia* media_plugin = mPreviewMedia->getMediaPlugin(); + if( media_plugin ) + { + // some controls are only appropriate for time or browser type plugins + // so we selectively enable/disable them - need to do it in draw + // because the information from plugins arrives assynchronously + bool show_time_controls = media_plugin->pluginSupportsMediaTime(); + if ( show_time_controls ) + { + childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, false ); + reset_button_is_active = false; + childSetEnabled( "current_url_label", false ); + childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, true ); + } + else + { + childSetEnabled( LLMediaEntry::CURRENT_URL_KEY, true ); + reset_button_is_active = true; + childSetEnabled( "current_url_label", true ); + childSetEnabled( LLMediaEntry::AUTO_LOOP_KEY, false ); + }; + }; + }; + + // current URL can change over time. + updateCurrentURL(); + + // enable/disable RESRET button depending on permissions + // since this is the same as a navigate action + U32 owner_mask_on; + U32 owner_mask_off; + U32 valid_owner_perms = LLSelectMgr::getInstance()->selectGetPerm( PERM_OWNER, + &owner_mask_on, &owner_mask_off ); + U32 group_mask_on; + U32 group_mask_off; + U32 valid_group_perms = LLSelectMgr::getInstance()->selectGetPerm( PERM_GROUP, + &group_mask_on, &group_mask_off ); + U32 everyone_mask_on; + U32 everyone_mask_off; + S32 valid_everyone_perms = LLSelectMgr::getInstance()->selectGetPerm( PERM_EVERYONE, + &everyone_mask_on, &everyone_mask_off ); + + bool user_can_press_reset = false; + + // if perms we got back are valid + if ( valid_owner_perms && + valid_group_perms && + valid_everyone_perms ) + { + // if user is allowed to press the RESET button + if ( ( owner_mask_on & PERM_MODIFY ) || + ( group_mask_on & PERM_MODIFY ) || + ( group_mask_on & PERM_MODIFY ) ) + { + user_can_press_reset = true; + } + else + // user is NOT allowed to press the RESET button + { + user_can_press_reset = false; + }; + }; + + // several places modify this widget so we must collect states in one place + if ( reset_button_is_active ) + { + // user has perms to press reset button and it is active + if ( user_can_press_reset ) + { + childSetEnabled( "current_url_reset_btn", true ); + } + // user does not has perms to press reset button and it is active + else + { + childSetEnabled( "current_url_reset_btn", false ); + }; + } + else + // reset button is inactive so we just slam it to off - other states don't matter + { + childSetEnabled( "current_url_reset_btn", false ); + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// static +void LLPanelMediaSettingsGeneral::clearValues( void* userdata ) +{ + LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata; + self->mAltImageEnable ->clear(); + self->mAutoLoop->clear(); + self->mAutoPlay->clear(); + self->mAutoScale->clear(); + self->mAutoZoom ->clear(); + self->mControls->clear(); + self->mCurrentURL->clear(); + self->mFirstClick->clear(); + self->mHeightPixels->clear(); + self->mHomeURL->clear(); + self->mWidthPixels->clear(); + self->mPreviewMedia->unloadMediaSource(); +} + +//////////////////////////////////////////////////////////////////////////////// +// static +void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& media_settings ) +{ + LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata; + + //llinfos << "---------------" << llendl; + //llinfos << ll_pretty_print_sd(media_settings) << llendl; + //llinfos << "---------------" << llendl; + + std::string base_key( "" ); + std::string tentative_key( "" ); + + struct + { + std::string key_name; + LLUICtrl* ctrl_ptr; + std::string ctrl_type; + + } data_set [] = + { + { LLMediaEntry::AUTO_LOOP_KEY, self->mAutoLoop, "LLCheckBoxCtrl" }, + { LLMediaEntry::AUTO_PLAY_KEY, self->mAutoPlay, "LLCheckBoxCtrl" }, + { LLMediaEntry::AUTO_SCALE_KEY, self->mAutoScale, "LLCheckBoxCtrl" }, + { LLMediaEntry::AUTO_ZOOM_KEY, self->mAutoZoom, "LLCheckBoxCtrl" }, + { LLMediaEntry::CONTROLS_KEY, self->mControls, "LLComboBox" }, + { LLMediaEntry::CURRENT_URL_KEY, self->mCurrentURL, "LLLineEditor" }, + { LLMediaEntry::HEIGHT_PIXELS_KEY, self->mHeightPixels, "LLSpinCtrl" }, + { LLMediaEntry::HOME_URL_KEY, self->mHomeURL, "LLLineEditor" }, + { LLMediaEntry::FIRST_CLICK_INTERACT_KEY, self->mFirstClick, "LLCheckBoxCtrl" }, + { LLMediaEntry::WIDTH_PIXELS_KEY, self->mWidthPixels, "LLSpinCtrl" }, + { LLMediaEntry::ALT_IMAGE_ENABLE_KEY, self->mAltImageEnable, "LLCheckBoxCtrl" }, + { "", NULL , "" } + }; + + for( int i = 0; data_set[ i ].key_name.length() > 0; ++i ) + { + base_key = std::string( data_set[ i ].key_name ); + tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ); + // TODO: CP - I bet there is a better way to do this using Boost + if ( media_settings[ base_key ].isDefined() ) + { + if ( data_set[ i ].ctrl_type == "LLLineEditor" ) + { + static_cast< LLLineEditor* >( data_set[ i ].ctrl_ptr )-> + setText( media_settings[ base_key ].asString() ); + } + else + if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" ) + static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )-> + setValue( media_settings[ base_key ].asBoolean() ); + else + if ( data_set[ i ].ctrl_type == "LLComboBox" ) + static_cast< LLComboBox* >( data_set[ i ].ctrl_ptr )-> + setCurrentByIndex( media_settings[ base_key ].asInteger() ); + else + if ( data_set[ i ].ctrl_type == "LLSpinCtrl" ) + static_cast< LLSpinCtrl* >( data_set[ i ].ctrl_ptr )-> + setValue( media_settings[ base_key ].asInteger() ); + + data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() ); + }; + }; + + // interrogates controls and updates widgets as required + self->updateMediaPreview(); + self->updateCurrentURL(); +} + +//////////////////////////////////////////////////////////////////////////////// +// Helper to set media control to media URL as required +void LLPanelMediaSettingsGeneral::updateMediaPreview() +{ + if ( mHomeURL->getValue().asString().length() > 0 ) + { + mPreviewMedia->navigateTo( mHomeURL->getValue().asString() ); + } + else + // new home URL will be empty if media is deleted but + // we still need to clean out the preview. + { + mPreviewMedia->unloadMediaSource(); + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// Helper to set current URL +void LLPanelMediaSettingsGeneral::updateCurrentURL() +{ + if( mPreviewMedia ) + { + LLPluginClassMedia* media_plugin = mPreviewMedia->getMediaPlugin(); + if( media_plugin ) + { + // get current URL from plugin and display + std::string current_location = media_plugin->getLocation(); + if ( current_location.length() ) + { + childSetText( "current_url", current_location ); + } + else + // current location may be empty so we need to clear it + { + const std::string empty_string( "" ); + childSetText( "current_url", empty_string ); + }; + }; + }; +} + +//////////////////////////////////////////////////////////////////////////////// + +void LLPanelMediaSettingsGeneral::onClose() +{ + if(mPreviewMedia) + { + mPreviewMedia->unloadMediaSource(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// static +void LLPanelMediaSettingsGeneral::onCommitHomeURL( LLUICtrl* ctrl, void *userdata ) +{ + LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata; + self->updateMediaPreview(); +} + + +//////////////////////////////////////////////////////////////////////////////// +void LLPanelMediaSettingsGeneral::onBtnResetCurrentUrl() +{ + // TODO: reset home URL but need to consider permissions too + //LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata; +} + +//////////////////////////////////////////////////////////////////////////////// +// static +void LLPanelMediaSettingsGeneral::apply( void* userdata ) +{ + LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata; + + // build LLSD Fragment + LLSD media_data_general; + self->getValues(media_data_general); + + // this merges contents of LLSD passed in with what's there so this is ok + LLSelectMgr::getInstance()->selectionSetMediaData( media_data_general ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLPanelMediaSettingsGeneral::getValues( LLSD &fill_me_in ) +{ + fill_me_in[LLMediaEntry::ALT_IMAGE_ENABLE_KEY] = mAltImageEnable->getValue(); + fill_me_in[LLMediaEntry::AUTO_LOOP_KEY] = mAutoLoop->getValue(); + fill_me_in[LLMediaEntry::AUTO_PLAY_KEY] = mAutoPlay->getValue(); + fill_me_in[LLMediaEntry::AUTO_SCALE_KEY] = mAutoScale->getValue(); + fill_me_in[LLMediaEntry::AUTO_ZOOM_KEY] = mAutoZoom->getValue(); + fill_me_in[LLMediaEntry::CONTROLS_KEY] = mControls->getCurrentIndex(); + // XXX Don't send current URL! + //fill_me_in[LLMediaEntry::CURRENT_URL_KEY] = mCurrentURL->getValue(); + fill_me_in[LLMediaEntry::HEIGHT_PIXELS_KEY] = mHeightPixels->getValue(); + fill_me_in[LLMediaEntry::HOME_URL_KEY] = mHomeURL->getValue(); + fill_me_in[LLMediaEntry::FIRST_CLICK_INTERACT_KEY] = mFirstClick->getValue(); + fill_me_in[LLMediaEntry::WIDTH_PIXELS_KEY] = mWidthPixels->getValue(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLPanelMediaSettingsGeneral::setParent( LLFloaterMediaSettings* parent ) +{ + mParent = parent; +}; diff --git a/indra/newview/llpanelmediasettingsgeneral.h b/indra/newview/llpanelmediasettingsgeneral.h new file mode 100644 index 0000000000..24678a3a07 --- /dev/null +++ b/indra/newview/llpanelmediasettingsgeneral.h @@ -0,0 +1,89 @@ +/** + * @file llpanelmediasettingsgeneral.h + * @brief LLPanelMediaSettingsGeneral class definition + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPANELMEDIAMEDIASETTINGSGENERAL_H +#define LL_LLPANELMEDIAMEDIASETTINGSGENERAL_H + +#include "llpanel.h" + +class LLButton; +class LLCheckBoxCtrl; +class LLComboBox; +class LLLineEditor; +class LLSpinCtrl; +class LLTextureCtrl; +class LLMediaCtrl; +class LLFloaterMediaSettings; + +class LLPanelMediaSettingsGeneral : public LLPanel +{ +public: + BOOL postBuild(); + virtual void draw(); + static void apply(void*); + void getValues(LLSD &fill_me_in); + + LLPanelMediaSettingsGeneral(); + ~LLPanelMediaSettingsGeneral(); + + void setParent( LLFloaterMediaSettings* parent ); + static void initValues( void* userdata, const LLSD& media_settings ); + static void clearValues( void* userdata ); + + void updateMediaPreview(); + void updateCurrentURL(); + + void onClose(); + +protected: + LLFloaterMediaSettings* mParent; + +private: + void onBtnResetCurrentUrl(); + static void onCommitHomeURL(LLUICtrl* ctrl, void *userdata ); + + LLComboBox* mControls; + LLCheckBoxCtrl* mAutoLoop; + LLCheckBoxCtrl* mFirstClick; + LLTextureCtrl* mMediaPreview; + LLCheckBoxCtrl* mAutoZoom; + LLCheckBoxCtrl* mAutoPlay; + LLCheckBoxCtrl* mAutoScale; + LLSpinCtrl* mWidthPixels; + LLSpinCtrl* mHeightPixels; + LLLineEditor* mHomeURL; + LLLineEditor* mCurrentURL; + LLCheckBoxCtrl* mAltImageEnable; + LLMediaCtrl* mPreviewMedia; +}; + +#endif // LL_LLPANELMEDIAMEDIASETTINGSGENERAL_H diff --git a/indra/newview/llpanelmediasettingspermissions.cpp b/indra/newview/llpanelmediasettingspermissions.cpp new file mode 100644 index 0000000000..d6a2677f4b --- /dev/null +++ b/indra/newview/llpanelmediasettingspermissions.cpp @@ -0,0 +1,223 @@ +/** + * @file llpanelmediasettingspermissions.cpp + * @brief LLPanelMediaSettingsPermissions class implementation + * + * note that "permissions" tab is really "Controls" tab - refs to 'perms' and + * 'permissions' not changed to 'controls' since we don't want to change + * shared files in server code and keeping everything the same seemed best. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llpanelmediasettingspermissions.h" +#include "llpanelcontents.h" +#include "llcombobox.h" +#include "llcheckboxctrl.h" +#include "llspinctrl.h" +#include "llurlhistory.h" +#include "lluictrlfactory.h" +#include "llwindow.h" +#include "llviewerwindow.h" +#include "llsdutil.h" +#include "llselectmgr.h" +#include "llmediaentry.h" +#include "llnamebox.h" + +//////////////////////////////////////////////////////////////////////////////// +// +LLPanelMediaSettingsPermissions::LLPanelMediaSettingsPermissions() : + mPermsOwnerInteract( 0 ), + mPermsOwnerControl( 0 ), + mPermsGroupName( 0 ), + mPermsGroupInteract( 0 ), + mPermsGroupControl( 0 ), + mPermsWorldInteract( 0 ), + mPermsWorldControl( 0 ) +{ + // build dialog from XML + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_permissions.xml"); +} + +//////////////////////////////////////////////////////////////////////////////// +// +BOOL LLPanelMediaSettingsPermissions::postBuild() +{ + // connect member vars with UI widgets + mPermsOwnerInteract = getChild< LLCheckBoxCtrl >( LLPanelContents::PERMS_OWNER_INTERACT_KEY ); + mPermsOwnerControl = getChild< LLCheckBoxCtrl >( LLPanelContents::PERMS_OWNER_CONTROL_KEY ); + mPermsGroupInteract = getChild< LLCheckBoxCtrl >( LLPanelContents::PERMS_GROUP_INTERACT_KEY ); + mPermsGroupControl = getChild< LLCheckBoxCtrl >( LLPanelContents::PERMS_GROUP_CONTROL_KEY ); + mPermsWorldInteract = getChild< LLCheckBoxCtrl >( LLPanelContents::PERMS_ANYONE_INTERACT_KEY ); + mPermsWorldControl = getChild< LLCheckBoxCtrl >( LLPanelContents::PERMS_ANYONE_CONTROL_KEY ); + + mPermsGroupName = getChild< LLNameBox >( "perms_group_name" ); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +LLPanelMediaSettingsPermissions::~LLPanelMediaSettingsPermissions() +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +void LLPanelMediaSettingsPermissions::draw() +{ + // housekeeping + LLPanel::draw(); + + childSetText("perms_group_name",LLStringUtil::null); + LLUUID group_id; + BOOL groups_identical = LLSelectMgr::getInstance()->selectGetGroup(group_id); + if (groups_identical) + { + if(mPermsGroupName) + { + mPermsGroupName->setNameID(group_id, true); + mPermsGroupName->setEnabled(true); + }; + } + else + { + if(mPermsGroupName) + { + mPermsGroupName->setNameID(LLUUID::null, TRUE); + mPermsGroupName->refresh(LLUUID::null, LLStringUtil::null, LLStringUtil::null, true); + mPermsGroupName->setEnabled(false); + }; + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// static +void LLPanelMediaSettingsPermissions::clearValues( void* userdata ) +{ + LLPanelMediaSettingsPermissions *self =(LLPanelMediaSettingsPermissions *)userdata; + self->mPermsOwnerInteract->clear(); + self->mPermsOwnerControl->clear(); + self->mPermsGroupInteract ->clear(); + self->mPermsGroupControl->clear(); + self->mPermsWorldInteract ->clear(); + self->mPermsWorldControl ->clear(); +// mPermsGroupName ->setValue(0); + +} + +//////////////////////////////////////////////////////////////////////////////// +// static +void LLPanelMediaSettingsPermissions::initValues( void* userdata, const LLSD& media_settings ) +{ + LLPanelMediaSettingsPermissions *self =(LLPanelMediaSettingsPermissions *)userdata; + + std::string base_key( "" ); + std::string tentative_key( "" ); + + struct + { + std::string key_name; + LLUICtrl* ctrl_ptr; + std::string ctrl_type; + + } data_set [] = + { + { LLPanelContents::PERMS_OWNER_INTERACT_KEY, self->mPermsOwnerInteract, "LLCheckBoxCtrl" }, + { LLPanelContents::PERMS_OWNER_CONTROL_KEY, self->mPermsOwnerControl, "LLCheckBoxCtrl" }, + { LLPanelContents::PERMS_GROUP_INTERACT_KEY, self->mPermsGroupInteract, "LLCheckBoxCtrl" }, + { LLPanelContents::PERMS_GROUP_CONTROL_KEY, self->mPermsGroupControl, "LLCheckBoxCtrl" }, + { LLPanelContents::PERMS_ANYONE_INTERACT_KEY, self->mPermsWorldInteract, "LLCheckBoxCtrl" }, + { LLPanelContents::PERMS_ANYONE_CONTROL_KEY, self->mPermsWorldControl, "LLCheckBoxCtrl" }, + { "", NULL , "" } + }; + + for( int i = 0; data_set[ i ].key_name.length() > 0; ++i ) + { + base_key = std::string( data_set[ i ].key_name ); + tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ); + + // TODO: CP - I bet there is a better way to do this using Boost + if ( media_settings[ base_key ].isDefined() ) + { + if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" ) + { + // the sense of the checkboxes changed and it made sense + // to just reverse their sense back again here and avoid + // changing server code. + static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )-> + setValue( ! media_settings[ base_key ].asBoolean() ); + } + else + if ( data_set[ i ].ctrl_type == "LLComboBox" ) + static_cast< LLComboBox* >( data_set[ i ].ctrl_ptr )-> + setCurrentByIndex( media_settings[ base_key ].asInteger() ); + + data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() ); + }; + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// static +void LLPanelMediaSettingsPermissions::apply( void* userdata ) +{ + LLPanelMediaSettingsPermissions *self =(LLPanelMediaSettingsPermissions *)userdata; + + // build LLSD Fragment + LLSD media_data_permissions; + self->getValues(media_data_permissions); + + // this merges contents of LLSD passed in with what's there so this is ok + LLSelectMgr::getInstance()->selectionSetMediaData( media_data_permissions ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLPanelMediaSettingsPermissions::getValues( LLSD &fill_me_in ) +{ + // *NOTE: For some reason, gcc does not like these symbol references in the + // expressions below (inside the static_casts). I have NO idea why :(. + // For some reason, assigning them to const temp vars here fixes the link + // error. Bizarre. + const U8 none = LLMediaEntry::PERM_NONE; + const U8 owner = LLMediaEntry::PERM_OWNER; + const U8 group = LLMediaEntry::PERM_GROUP; + const U8 anyone = LLMediaEntry::PERM_ANYONE; + const LLSD::Integer control = static_cast( + (mPermsOwnerControl->getValue() ? none : owner ) | + (mPermsGroupControl->getValue() ? none : group ) | + (mPermsWorldControl->getValue() ? none : anyone )); + const LLSD::Integer interact = static_cast( + (mPermsOwnerInteract->getValue() ? none : owner ) | + (mPermsGroupInteract->getValue() ? none : group ) | + (mPermsWorldInteract->getValue() ? none : anyone )); + fill_me_in[LLMediaEntry::PERMS_CONTROL_KEY] = control; + fill_me_in[LLMediaEntry::PERMS_INTERACT_KEY] = interact; +} diff --git a/indra/newview/llpanelmediasettingspermissions.h b/indra/newview/llpanelmediasettingspermissions.h new file mode 100644 index 0000000000..ce293e07b9 --- /dev/null +++ b/indra/newview/llpanelmediasettingspermissions.h @@ -0,0 +1,71 @@ +/** + * @file llpanelmediasettingspermissions.h + * @brief LLPanelMediaSettingsPermissions class definition + * + * note that "permissions" tab is really "Controls" tab - refs to 'perms' and + * 'permissions' not changed to 'controls' since we don't want to change + * shared files in server code and keeping everything the same seemed best. + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPANELMEDIAMEDIASETTINGSPERMISSIONS_H +#define LL_LLPANELMEDIAMEDIASETTINGSPERMISSIONS_H + +#include "llpanel.h" +#include "lluuid.h" + +class LLComboBox; +class LLCheckBoxCtrl; +class LLNameBox; + +class LLPanelMediaSettingsPermissions : public LLPanel +{ + public: + BOOL postBuild(); + virtual void draw(); + static void apply(void*); + void getValues(LLSD &fill_me_in); + + LLPanelMediaSettingsPermissions(); + ~LLPanelMediaSettingsPermissions(); + + static void initValues( void* userdata, const LLSD& media_settings ); + static void clearValues( void* userdata ); + + private: + LLCheckBoxCtrl* mPermsOwnerInteract; + LLCheckBoxCtrl* mPermsOwnerControl; + LLNameBox* mPermsGroupName; + LLCheckBoxCtrl* mPermsGroupInteract; + LLCheckBoxCtrl* mPermsGroupControl; + LLCheckBoxCtrl* mPermsWorldInteract; + LLCheckBoxCtrl* mPermsWorldControl; +}; + +#endif // LL_LLPANELMEDIAMEDIASETTINGSPERMISSIONS_H diff --git a/indra/newview/llpanelmediasettingssecurity.cpp b/indra/newview/llpanelmediasettingssecurity.cpp new file mode 100644 index 0000000000..a4eee82aa9 --- /dev/null +++ b/indra/newview/llpanelmediasettingssecurity.cpp @@ -0,0 +1,233 @@ +/** + * @file llpanelmediasettingssecurity.cpp + * @brief LLPanelMediaSettingsSecurity class implementation + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llfloaterreg.h" +#include "llpanelmediasettingssecurity.h" +#include "llpanelcontents.h" +#include "llcheckboxctrl.h" +#include "llscrolllistctrl.h" +#include "llscrolllistitem.h" +#include "lluictrlfactory.h" +#include "llwindow.h" +#include "llviewerwindow.h" +#include "llsdutil.h" +#include "llselectmgr.h" +#include "llmediaentry.h" +#include "llfloaterwhitelistentry.h" + +//////////////////////////////////////////////////////////////////////////////// +// +LLPanelMediaSettingsSecurity::LLPanelMediaSettingsSecurity() +{ + // build dialog from XML + LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_security.xml"); + mCommitCallbackRegistrar.add("Media.whitelistAdd", boost::bind(&LLPanelMediaSettingsSecurity::onBtnAdd, this)); + mCommitCallbackRegistrar.add("Media.whitelistDelete", boost::bind(&LLPanelMediaSettingsSecurity::onBtnDel, this)); +} + +//////////////////////////////////////////////////////////////////////////////// +// +BOOL LLPanelMediaSettingsSecurity::postBuild() +{ + mEnableWhiteList = getChild< LLCheckBoxCtrl >( LLMediaEntry::WHITELIST_ENABLE_KEY ); + mWhiteListList = getChild< LLScrollListCtrl >( LLMediaEntry::WHITELIST_KEY ); + + childSetAction("whitelist_add", onBtnAdd, this); + childSetAction("whitelist_del", onBtnDel, this); + + setDefaultBtn("whitelist_add"); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +LLPanelMediaSettingsSecurity::~LLPanelMediaSettingsSecurity() +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLPanelMediaSettingsSecurity::draw() +{ + // housekeeping + LLPanel::draw(); + + // if list is empty, disable DEL button and checkbox to enable use of list + if ( mWhiteListList->isEmpty() ) + { + childSetEnabled( "whitelist_del", false ); + childSetEnabled( LLMediaEntry::WHITELIST_KEY, false ); + childSetEnabled( LLMediaEntry::WHITELIST_ENABLE_KEY, false ); + } + else + { + childSetEnabled( "whitelist_del", true ); + childSetEnabled( LLMediaEntry::WHITELIST_KEY, true ); + childSetEnabled( LLMediaEntry::WHITELIST_ENABLE_KEY, true ); + }; + + // if nothing is selected, disable DEL button + if ( mWhiteListList->getSelectedValue().asString().empty() ) + { + childSetEnabled( "whitelist_del", false ); + } + else + { + childSetEnabled( "whitelist_del", true ); + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// static +void LLPanelMediaSettingsSecurity::initValues( void* userdata, const LLSD& media_settings ) +{ + LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata; + + std::string base_key( "" ); + std::string tentative_key( "" ); + + struct + { + std::string key_name; + LLUICtrl* ctrl_ptr; + std::string ctrl_type; + + } data_set [] = + { + { LLMediaEntry::WHITELIST_ENABLE_KEY, self->mEnableWhiteList, "LLCheckBoxCtrl" }, + { LLMediaEntry::WHITELIST_KEY, self->mWhiteListList, "LLScrollListCtrl" }, + { "", NULL , "" } + }; + + for( int i = 0; data_set[ i ].key_name.length() > 0; ++i ) + { + base_key = std::string( data_set[ i ].key_name ); + tentative_key = base_key + std::string( LLPanelContents::TENTATIVE_SUFFIX ); + + // TODO: CP - I bet there is a better way to do this using Boost + if ( media_settings[ base_key ].isDefined() ) + { + if ( data_set[ i ].ctrl_type == "LLCheckBoxCtrl" ) + { + static_cast< LLCheckBoxCtrl* >( data_set[ i ].ctrl_ptr )-> + setValue( media_settings[ base_key ].asBoolean() ); + } + else + if ( data_set[ i ].ctrl_type == "LLScrollListCtrl" ) + { + // get control + LLScrollListCtrl* list = static_cast< LLScrollListCtrl* >( data_set[ i ].ctrl_ptr ); + list->deleteAllItems(); + + // points to list of white list URLs + LLSD url_list = media_settings[ base_key ]; + + // iterate over them and add to scroll list + LLSD::array_iterator iter = url_list.beginArray(); + while( iter != url_list.endArray() ) + { + // TODO: is iter guaranteed to be valid here? + std::string url = *iter; + list->addSimpleElement( url ); + ++iter; + }; + }; + + data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() ); + }; + }; +} + +//////////////////////////////////////////////////////////////////////////////// +// static +void LLPanelMediaSettingsSecurity::clearValues( void* userdata ) +{ + LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata; + self->mEnableWhiteList->clear(); + self->mWhiteListList->deleteAllItems(); +} +//////////////////////////////////////////////////////////////////////////////// +// static +void LLPanelMediaSettingsSecurity::apply( void* userdata ) +{ + LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata; + + // build LLSD Fragment + LLSD media_data_security; + self->getValues(media_data_security); + // this merges contents of LLSD passed in with what's there so this is ok + LLSelectMgr::getInstance()->selectionSetMediaData( media_data_security ); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLPanelMediaSettingsSecurity::getValues( LLSD &fill_me_in ) +{ + fill_me_in[LLMediaEntry::WHITELIST_ENABLE_KEY] = mEnableWhiteList->getValue(); + + // iterate over white list and extract items + std::vector< LLScrollListItem* > white_list_items = mWhiteListList->getAllData(); + std::vector< LLScrollListItem* >::iterator iter = white_list_items.begin(); + fill_me_in[LLMediaEntry::WHITELIST_KEY].clear(); + while( iter != white_list_items.end() ) + { + std::string white_list_url = (*iter)->getValue().asString(); + fill_me_in[ LLMediaEntry::WHITELIST_KEY ].append( white_list_url ); + ++iter; + }; +} + + +/////////////////////////////////////////////////////////////////////////////// +// static +void LLPanelMediaSettingsSecurity::addWhiteListItem(const std::string& url) +{ + mWhiteListList->addSimpleElement( url ); +} + +/////////////////////////////////////////////////////////////////////////////// +// static +void LLPanelMediaSettingsSecurity::onBtnAdd( void* userdata ) +{ + LLFloaterReg::showInstance("whitelist_entry"); +} + +/////////////////////////////////////////////////////////////////////////////// +// static +void LLPanelMediaSettingsSecurity::onBtnDel( void* userdata ) +{ + LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata; + + self->mWhiteListList->deleteSelectedItems(); +} diff --git a/indra/newview/llpanelmediasettingssecurity.h b/indra/newview/llpanelmediasettingssecurity.h new file mode 100644 index 0000000000..d77509897d --- /dev/null +++ b/indra/newview/llpanelmediasettingssecurity.h @@ -0,0 +1,64 @@ +/** + * @file llpanelmediasettingssecurity.h + * @brief LLPanelMediaSettingsSecurity class definition + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPANELMEDIAMEDIASETTINGSSECURITY_H +#define LL_LLPANELMEDIAMEDIASETTINGSSECURITY_H + +#include "llpanel.h" + +class LLCheckBoxCtrl; +class LLScrollListCtrl; + +class LLPanelMediaSettingsSecurity : public LLPanel +{ + public: + BOOL postBuild(); + virtual void draw(); + static void apply(void*); + void getValues(LLSD &fill_me_in); + + LLPanelMediaSettingsSecurity(); + ~LLPanelMediaSettingsSecurity(); + + static void initValues( void* userdata, const LLSD& media_settings ); + static void clearValues( void* userdata ); + void addWhiteListItem(const std::string& url); + + private: + LLCheckBoxCtrl* mEnableWhiteList; + LLScrollListCtrl* mWhiteListList; + + static void onBtnAdd(void*); + static void onBtnDel(void*); +}; + +#endif // LL_LLPANELMEDIAMEDIASETTINGSSECURITY_H diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index b25331e439..ae8c9f770b 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1721,13 +1721,8 @@ void LLSelectMgr::selectionSetFullbright(U8 fullbright) getSelection()->applyToObjects(&sendfunc); } -void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string& media_url) +void LLSelectMgr::selectionSetMedia(U8 media_type) { - U8 media_flags = LLTextureEntry::MF_NONE; - if (media_type == LLViewerObject::MEDIA_TYPE_WEB_PAGE) - { - media_flags = LLTextureEntry::MF_WEB_PAGE; - } struct f : public LLSelectedTEFunctor { @@ -1737,33 +1732,72 @@ void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string& { if (object->permModify()) { - // update viewer side color in anticipation of update from simulator + // update viewer has media object->setTEMediaFlags(te, mMediaFlags); } return true; } - } setfunc(media_flags); + } setfunc(media_type); getSelection()->applyToTEs(&setfunc); - - struct g : public LLSelectedObjectFunctor + struct f2 : public LLSelectedObjectFunctor { - U8 media_type; - const std::string& media_url ; - g(U8 a, const std::string& b) : media_type(a), media_url(b) {} virtual bool apply(LLViewerObject* object) { if (object->permModify()) { object->sendTEUpdate(); - object->setMediaType(media_type); - object->setMediaURL(media_url); } return true; } - } sendfunc(media_type, media_url); - getSelection()->applyToObjects(&sendfunc); + } func2; + mSelectedObjects->applyToObjects( &func2 ); } +// This function expects media_data to be a map containing relevant +// media data name/value pairs (e.g. home_url, etc.) +void LLSelectMgr::selectionSetMediaData(const LLSD &media_data) +{ + + struct f : public LLSelectedTEFunctor + { + const LLSD &mMediaData; + f(const LLSD& t) : mMediaData(t) {} + bool apply(LLViewerObject* object, S32 te) + { + if (object->permModify()) + { + LLVOVolume *vo = dynamic_cast(object); + if (NULL != vo) + { + vo->syncMediaData(te, mMediaData, true/*merge*/, true/*ignore_agent*/); + } + } + return true; + } + } setfunc(media_data); + getSelection()->applyToTEs(&setfunc); + + struct f2 : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + LLVOVolume *vo = dynamic_cast(object); + if (NULL != vo) + { + // Send updated media data FOR THE ENTIRE OBJECT + vo->sendMediaDataUpdate(); + } + } + return true; + } + } func2; + getSelection()->applyToObjects(&func2); +} + + + void LLSelectMgr::selectionSetGlow(F32 glow) { struct f1 : public LLSelectedTEFunctor @@ -5057,7 +5091,15 @@ void LLSelectNode::selectTE(S32 te_index, BOOL selected) { return; } - mTESelectMask |= 0x1 << te_index; + S32 mask = 0x1 << te_index; + if(selected) + { + mTESelectMask |= mask; + } + else + { + mTESelectMask &= ~mask; + } mLastTESelected = te_index; } @@ -6042,6 +6084,29 @@ bool LLObjectSelection::applyToRootNodes(LLSelectedNodeFunctor *func, bool first return result; } +BOOL LLObjectSelection::isMultipleTESelected() +{ + BOOL te_selected = FALSE; + // ...all faces + for (LLObjectSelection::iterator iter = begin(); + iter != end(); iter++) + { + LLSelectNode* nodep = *iter; + for (S32 i = 0; i < SELECT_MAX_TES; i++) + { + if(nodep->isTESelected(i)) + { + if(te_selected) + { + return TRUE; + } + te_selected = TRUE; + } + } + } + return FALSE; +} + //----------------------------------------------------------------------------- // contains() //----------------------------------------------------------------------------- diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index 08c2783746..9e02170d74 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -307,6 +307,7 @@ public: S32 getTECount(); S32 getRootObjectCount(); + BOOL isMultipleTESelected(); BOOL contains(LLViewerObject* object); BOOL contains(LLViewerObject* object, S32 te); @@ -504,7 +505,8 @@ public: void selectionSetTexGen( U8 texgen ); void selectionSetShiny( U8 shiny ); void selectionSetFullbright( U8 fullbright ); - void selectionSetMediaTypeAndURL( U8 media_type, const std::string& media_url ); + void selectionSetMedia( U8 media_type ); + void selectionSetMediaData(const LLSD &media_data); // NOTE: modifies media_data!!! void selectionSetClickAction(U8 action); void selectionSetIncludeInSearch(bool include_in_search); void selectionSetGlow(const F32 glow); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 4e13cb17a2..7bf0d31d94 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -433,6 +433,11 @@ void LLSpatialGroup::clearDrawMap() mDrawMap.clear(); } +BOOL LLSpatialGroup::isRecentlyVisible() const +{ + return (LLDrawable::getCurrentFrame() - (S32)mVisible) < LLDrawable::getMinVisFrameRange() ; +} + BOOL LLSpatialGroup::isVisible() const { return mVisible[LLViewerCamera::sCurCameraID] == LLDrawable::getCurrentFrame() ? TRUE : FALSE; diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 16e8782a8e..64c2a9acbc 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -267,6 +267,7 @@ public: BOOL removeObject(LLDrawable *drawablep, BOOL from_octree = FALSE); BOOL updateInGroup(LLDrawable *drawablep, BOOL immediate = FALSE); // Update position if it's in the group BOOL isVisible() const; + BOOL isRecentlyVisible() const; void setVisible(); void shift(const LLVector3 &offset); BOOL boundObjects(BOOL empty, LLVector3& newMin, LLVector3& newMax); diff --git a/indra/newview/lltool.cpp b/indra/newview/lltool.cpp index ceb1358d1c..880d5d5e12 100644 --- a/indra/newview/lltool.cpp +++ b/indra/newview/lltool.cpp @@ -67,18 +67,20 @@ LLTool::~LLTool() BOOL LLTool::handleAnyMouseClick(S32 x, S32 y, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down) { - // This is necessary to force clicks in the world to cause edit - // boxes that might have keyboard focus to relinquish it, and hence - // cause a commit to update their value. JC - if (down) + BOOL result = LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down); + + // This behavior was moved here from LLViewerWindow::handleAnyMouseClick, so it can be selectively overridden by LLTool subclasses. + if(down && result) { + // This is necessary to force clicks in the world to cause edit + // boxes that might have keyboard focus to relinquish it, and hence + // cause a commit to update their value. JC gFocusMgr.setKeyboardFocus(NULL); } - - return LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down); + + return result; } - BOOL LLTool::handleMouseDown(S32 x, S32 y, MASK mask) { if (gDebugClicks) diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 5c210c5c28..d5db224143 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -48,6 +48,7 @@ #include "lltooltip.h" #include "llhudeffecttrail.h" #include "llhudmanager.h" +#include "llmediaentry.h" #include "llmenugl.h" #include "llmutelist.h" #include "llselectmgr.h" @@ -75,8 +76,6 @@ extern void handle_buy(void*); extern BOOL gDebugClicks; -static bool handle_media_click(const LLPickInfo& info); -static bool handle_media_hover(const LLPickInfo& info); static void handle_click_action_play(); static void handle_click_action_open_media(LLPointer objectp); static ECursorType cursor_from_parcel_media(U8 click_action); @@ -90,6 +89,16 @@ LLToolPie::LLToolPie() { } +BOOL LLToolPie::handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down) +{ + BOOL result = LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down); + + // This override DISABLES the keyboard focus reset that LLTool::handleAnyMouseClick adds. + // LLToolPie will do the right thing in its pick callback. + + return result; +} + BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask) { //left mouse down always picks transparent @@ -258,9 +267,9 @@ BOOL LLToolPie::pickLeftMouseDownCallback() } } - if (handle_media_click(mPick)) + if (handleMediaClick(mPick)) { - return FALSE; + return TRUE; } // put focus back "in world" @@ -466,10 +475,7 @@ void LLToolPie::selectionPropertiesReceived() BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) { mHoverPick = gViewerWindow->pickImmediate(x, y, FALSE); - - // FIXME: This was in the pluginapi branch, but I don't think it's correct. -// gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); - + LLViewerObject *parent = NULL; LLViewerObject *object = mHoverPick.getObject(); @@ -484,7 +490,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) gViewerWindow->setCursor(cursor); lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl; } - else if (handle_media_hover(mHoverPick)) + else if (handleMediaHover(mHoverPick)) { // cursor set by media object lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl; @@ -522,6 +528,9 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask) { LLViewerObject* obj = mPick.getObject(); + + handleMediaMouseUp(); + U8 click_action = final_click_action(obj); if (click_action != CLICK_ACTION_NONE) { @@ -543,6 +552,7 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask) break; } } + mGrabMouseButtonDown = FALSE; LLToolMgr::getInstance()->clearTransientTool(); gAgent.setLookAt(LOOKAT_TARGET_CONVERSATION, obj); // maybe look at object/person clicked on @@ -1038,6 +1048,7 @@ void LLToolPie::stopEditing() void LLToolPie::onMouseCaptureLost() { mMouseOutsideSlop = FALSE; + handleMediaMouseUp(); } @@ -1078,7 +1089,7 @@ static void handle_click_action_play() } } -static bool handle_media_click(const LLPickInfo& pick) +bool LLToolPie::handleMediaClick(const LLPickInfo& pick) { //FIXME: how do we handle object in different parcel than us? LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); @@ -1104,22 +1115,25 @@ static bool handle_media_click(const LLPickInfo& pick) // is media playing on this face? const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace); + LLMediaEntry* mep = (tep->hasMedia()) ? tep->getMediaData() : NULL; + viewer_media_t media_impl = mep ? LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()) : NULL; - viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(tep->getID()); - if (tep - && media_impl.notNull() - && media_impl->hasMedia() - && gSavedSettings.getBOOL("MediaOnAPrimUI")) + if (tep + && mep + && gSavedSettings.getBOOL("MediaOnAPrimUI") + && media_impl.notNull()) { - LLObjectSelectionHandle selection = LLViewerMediaFocus::getInstance()->getSelection(); - if (! selection->contains(pick.getObject(), pick.mObjectFace)) + // LLObjectSelectionHandle selection = /*LLViewerMediaFocus::getInstance()->getSelection()*/ LLSelectMgr::getInstance()->getSelection(); + if (/*! selection->contains(pick.getObject(), pick.mObjectFace)*/ + ! LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) ) { LLViewerMediaFocus::getInstance()->setFocusFace(TRUE, pick.getObject(), pick.mObjectFace, media_impl); } else { - media_impl->mouseDown(pick.mXYCoords.mX, pick.mXYCoords.mY); - media_impl->mouseCapture(); // the mouse-up will happen when capture is lost + media_impl->mouseDown(pick.mUVCoords); + mMediaMouseCaptureID = mep->getMediaID(); + setMouseCapture(TRUE); // This object will send a mouse-up to the media when it loses capture. } return true; @@ -1131,7 +1145,7 @@ static bool handle_media_click(const LLPickInfo& pick) return false; } -static bool handle_media_hover(const LLPickInfo& pick) +bool LLToolPie::handleMediaHover(const LLPickInfo& pick) { //FIXME: how do we handle object in different parcel than us? LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); @@ -1156,15 +1170,20 @@ static bool handle_media_hover(const LLPickInfo& pick) // is media playing on this face? const LLTextureEntry* tep = objectp->getTE(pick.mObjectFace); - viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(tep->getID()); - if (tep - && media_impl.notNull() - && media_impl->hasMedia() + const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL; + if (mep && gSavedSettings.getBOOL("MediaOnAPrimUI")) - { - if(LLViewerMediaFocus::getInstance()->getFocus()) + { + viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()); + if(LLViewerMediaFocus::getInstance()->getFocus() && media_impl.notNull()) { - media_impl->mouseMove(pick.mXYCoords.mX, pick.mXYCoords.mY); + media_impl->mouseMove(pick.mUVCoords); + + gViewerWindow->setCursor(media_impl->getLastSetCursor()); + } + else + { + gViewerWindow->setCursor(UI_CURSOR_ARROW); } // Set mouse over flag if unset @@ -1182,6 +1201,28 @@ static bool handle_media_hover(const LLPickInfo& pick) return false; } +bool LLToolPie::handleMediaMouseUp() +{ + bool result = false; + if(mMediaMouseCaptureID.notNull()) + { + // Face media needs to know the mouse went up. + viewer_media_t media_impl = LLViewerMedia::getMediaImplFromTextureID(mMediaMouseCaptureID); + if(media_impl) + { + // This will send a mouseUp event to the plugin using the last known mouse coordinate (from a mouseDown or mouseMove), which is what we want. + media_impl->onMouseCaptureLost(); + } + + mMediaMouseCaptureID.setNull(); + + setMouseCapture(FALSE); + + result = true; + } + + return result; +} static void handle_click_action_open_media(LLPointer objectp) { diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h index 328653d2b8..f6a67c13b1 100644 --- a/indra/newview/lltoolpie.h +++ b/indra/newview/lltoolpie.h @@ -42,9 +42,12 @@ class LLObjectSelection; class LLToolPie : public LLTool, public LLSingleton { + LOG_CLASS(LLToolPie); public: LLToolPie( ); + // Virtual functions inherited from LLMouseHandler + virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down); virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); @@ -81,9 +84,15 @@ private: BOOL useClickAction (MASK mask, LLViewerObject* object,LLViewerObject* parent); void showVisualContextMenuEffect(); + + bool handleMediaClick(const LLPickInfo& info); + bool handleMediaHover(const LLPickInfo& info); + bool handleMediaMouseUp(); + private: BOOL mGrabMouseButtonDown; BOOL mMouseOutsideSlop; // for this drag, has mouse moved outside slop region + LLUUID mMediaMouseCaptureID; LLPickInfo mPick; LLPickInfo mHoverPick; LLPointer mClickActionObject; diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 725ed57d20..2f656479f6 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -67,6 +67,7 @@ #include "llfloaterhardwaresettings.h" #include "llfloaterhelpbrowser.h" #include "llfloatermediabrowser.h" +#include "llfloatermediasettings.h" #include "llfloaterhud.h" #include "llfloaterimagepreview.h" #include "llimfloater.h" @@ -105,6 +106,7 @@ #include "llfloaterurldisplay.h" #include "llfloatervoicedevicesettings.h" #include "llfloaterwater.h" +#include "llfloaterwhitelistentry.h" #include "llfloaterwindlight.h" #include "llfloaterworldmap.h" #include "llinspectavatar.h" @@ -178,6 +180,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("mem_leaking", "floater_mem_leaking.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("media_browser", "floater_media_browser.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("media_settings", "floater_media_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("message_critical", "floater_critical.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("message_tos", "floater_tos.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("moveview", "floater_moveview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); @@ -238,6 +241,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("voice_call", "floater_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("whitelist_entry", "floater_whitelist_entry.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("world_map", "floater_world_map.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); // *NOTE: Please keep these alphabetized for easier merges diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index f033d66c1f..100a34291b 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -35,12 +35,14 @@ #include "llviewermedia.h" #include "llviewermediafocus.h" #include "llmimetypes.h" +#include "llmediaentry.h" #include "llviewercontrol.h" #include "llviewertexture.h" #include "llviewerparcelmedia.h" #include "llviewerparcelmgr.h" #include "llversionviewer.h" #include "llviewertexturelist.h" +#include "llvovolume.h" #include "llpluginclassmedia.h" #include "llevent.h" // LLSimpleListener @@ -95,10 +97,10 @@ bool LLViewerMediaEventEmitter::remObserver( LLViewerMediaObserver* observer ) /////////////////////////////////////////////////////////////////////////////// // -void LLViewerMediaEventEmitter::emitEvent( LLPluginClassMedia* media, LLPluginClassMediaOwner::EMediaEvent event ) +void LLViewerMediaEventEmitter::emitEvent( LLPluginClassMedia* media, LLViewerMediaObserver::EMediaEvent event ) { + // Broadcast the event to any observers. observerListType::iterator iter = mObservers.begin(); - while( iter != mObservers.end() ) { LLViewerMediaObserver *self = *iter; @@ -166,55 +168,127 @@ public: }; typedef std::vector impl_list; static impl_list sViewerMediaImplList; +static LLTimer sMediaCreateTimer; +static const F32 LLVIEWERMEDIA_CREATE_DELAY = 1.0f; + +////////////////////////////////////////////////////////////////////////////////////////// +static void add_media_impl(LLViewerMediaImpl* media) +{ + sViewerMediaImplList.push_back(media); +} + +////////////////////////////////////////////////////////////////////////////////////////// +static void remove_media_impl(LLViewerMediaImpl* media) +{ + impl_list::iterator iter = sViewerMediaImplList.begin(); + impl_list::iterator end = sViewerMediaImplList.end(); + + for(; iter != end; iter++) + { + if(media == *iter) + { + sViewerMediaImplList.erase(iter); + return; + } + } +} + ////////////////////////////////////////////////////////////////////////////////////////// // LLViewerMedia ////////////////////////////////////////////////////////////////////////////////////////// // static -viewer_media_t LLViewerMedia::newMediaImpl(const std::string& media_url, - const LLUUID& texture_id, - S32 media_width, S32 media_height, U8 media_auto_scale, - U8 media_loop, - std::string mime_type) +viewer_media_t LLViewerMedia::newMediaImpl( + const LLUUID& texture_id, + S32 media_width, + S32 media_height, + U8 media_auto_scale, + U8 media_loop) { LLViewerMediaImpl* media_impl = getMediaImplFromTextureID(texture_id); if(media_impl == NULL || texture_id.isNull()) { // Create the media impl - media_impl = new LLViewerMediaImpl(media_url, texture_id, media_width, media_height, media_auto_scale, media_loop, mime_type); - sViewerMediaImplList.push_back(media_impl); + media_impl = new LLViewerMediaImpl(texture_id, media_width, media_height, media_auto_scale, media_loop); } else { media_impl->stop(); media_impl->mTextureId = texture_id; - media_impl->mMediaURL = media_url; media_impl->mMediaWidth = media_width; media_impl->mMediaHeight = media_height; media_impl->mMediaAutoScale = media_auto_scale; media_impl->mMediaLoop = media_loop; - if(! media_url.empty()) - media_impl->navigateTo(media_url, mime_type, true); } + return media_impl; } -////////////////////////////////////////////////////////////////////////////////////////// -// static -void LLViewerMedia::removeMedia(LLViewerMediaImpl* media) -{ - impl_list::iterator iter = sViewerMediaImplList.begin(); - impl_list::iterator end = sViewerMediaImplList.end(); +viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const std::string& previous_url, bool update_from_self) +{ + // Try to find media with the same media ID + viewer_media_t media_impl = getMediaImplFromTextureID(media_entry->getMediaID()); + + bool was_loaded = false; + bool needs_navigate = false; - for(; iter != end; iter++) + if(media_impl) + { + was_loaded = media_impl->hasMedia(); + + media_impl->setHomeURL(media_entry->getHomeURL()); + + media_impl->mMediaAutoScale = media_entry->getAutoScale(); + media_impl->mMediaLoop = media_entry->getAutoLoop(); + media_impl->mMediaWidth = media_entry->getWidthPixels(); + media_impl->mMediaHeight = media_entry->getHeightPixels(); + if (media_impl->mMediaSource) + { + media_impl->mMediaSource->setAutoScale(media_impl->mMediaAutoScale); + media_impl->mMediaSource->setLoop(media_impl->mMediaLoop); + media_impl->mMediaSource->setSize(media_entry->getWidthPixels(), media_entry->getHeightPixels()); + } + + if((was_loaded || media_entry->getAutoPlay()) && !update_from_self) + { + if(!media_entry->getCurrentURL().empty()) + { + needs_navigate = (media_entry->getCurrentURL() != previous_url); + } + else if(!media_entry->getHomeURL().empty()) + { + needs_navigate = (media_entry->getHomeURL() != previous_url); + } + } + } + else { - if(media == *iter) + media_impl = newMediaImpl( + media_entry->getMediaID(), + media_entry->getWidthPixels(), + media_entry->getHeightPixels(), + media_entry->getAutoScale(), + media_entry->getAutoLoop()); + + media_impl->setHomeURL(media_entry->getHomeURL()); + + if(media_entry->getAutoPlay()) { - sViewerMediaImplList.erase(iter); - return; + needs_navigate = true; } } + + if(media_impl && needs_navigate) + { + std::string url = media_entry->getCurrentURL(); + if(url.empty()) + url = media_entry->getHomeURL(); + + media_impl->navigateTo(url, "", true, true); + } + + return media_impl; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -323,6 +397,36 @@ void LLViewerMedia::setVolume(F32 volume) } } +// This is the predicate function used to sort sViewerMediaImplList by priority. +static inline bool compare_impl_interest(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2) +{ + if(i1->hasFocus()) + { + // The item with user focus always comes to the front of the list, period. + return true; + } + else if(i2->hasFocus()) + { + // The item with user focus always comes to the front of the list, period. + return false; + } + else if(i1->getUsedInUI() && !i2->getUsedInUI()) + { + // i1 is a UI element, i2 is not. This makes i1 "less than" i2, so it sorts earlier in our list. + return true; + } + else if(i2->getUsedInUI() && !i1->getUsedInUI()) + { + // i2 is a UI element, i1 is not. This makes i2 "less than" i1, so it sorts earlier in our list. + return false; + } + else + { + // The object with the larger interest value should be earlier in the list, so we reverse the sense of the comparison here. + return (i1->getInterest() > i2->getInterest()); + } +} + ////////////////////////////////////////////////////////////////////////////////////////// // static void LLViewerMedia::updateMedia() @@ -334,32 +438,138 @@ void LLViewerMedia::updateMedia() { LLViewerMediaImpl* pimpl = *iter; pimpl->update(); + pimpl->calculateInterest(); } + + // Sort the static instance list using our interest criteria + std::stable_sort(sViewerMediaImplList.begin(), sViewerMediaImplList.end(), compare_impl_interest); + + // Go through the list again and adjust according to priority. + iter = sViewerMediaImplList.begin(); + end = sViewerMediaImplList.end(); + + F64 total_cpu = 0.0f; + int impl_count_total = 0; + int impl_count_interest_low = 0; + int impl_count_interest_normal = 0; + +#if 0 + LL_DEBUGS("PluginPriority") << "Sorted impls:" << llendl; +#endif + + U32 max_instances = gSavedSettings.getU32("PluginInstancesTotal"); + U32 max_normal = gSavedSettings.getU32("PluginInstancesNormal"); + U32 max_low = gSavedSettings.getU32("PluginInstancesLow"); + F32 max_cpu = gSavedSettings.getF32("PluginInstancesCPULimit"); + // Setting max_cpu to 0.0 disables CPU usage checking. + bool check_cpu_usage = (max_cpu != 0.0f); + + // Notes on tweakable params: + // max_instances must be set high enough to allow the various instances used in the UI (for the help browser, search, etc.) to be loaded. + // If max_normal + max_low is less than max_instances, things will tend to get unloaded instead of being set to slideshow. + + for(; iter != end; iter++) + { + LLViewerMediaImpl* pimpl = *iter; + + LLPluginClassMedia::EPriority new_priority = LLPluginClassMedia::PRIORITY_NORMAL; + + if(impl_count_total > (int)max_instances) + { + // Hard limit on the number of instances that will be loaded at one time + new_priority = LLPluginClassMedia::PRIORITY_UNLOADED; + } + else if(!pimpl->getVisible()) + { + new_priority = LLPluginClassMedia::PRIORITY_HIDDEN; + } + else if(pimpl->hasFocus()) + { + new_priority = LLPluginClassMedia::PRIORITY_HIGH; + } + else if(pimpl->getUsedInUI()) + { + new_priority = LLPluginClassMedia::PRIORITY_NORMAL; + } + else + { + // Look at interest and CPU usage for instances that aren't in any of the above states. + + // Heuristic -- if the media texture's approximate screen area is less than 1/4 of the native area of the texture, + // turn it down to low instead of normal. This may downsample for plugins that support it. + bool media_is_small = pimpl->getInterest() < (pimpl->getApproximateTextureInterest() / 4); + + if(pimpl->getInterest() == 0.0f) + { + // This media is completely invisible, due to being outside the view frustrum or out of range. + new_priority = LLPluginClassMedia::PRIORITY_HIDDEN; + } + else if(check_cpu_usage && (total_cpu > max_cpu)) + { + // Higher priority plugins have already used up the CPU budget. Set remaining ones to slideshow priority. + new_priority = LLPluginClassMedia::PRIORITY_SLIDESHOW; + } + else if((impl_count_interest_normal < (int)max_normal) && !media_is_small) + { + // Up to max_normal inworld get normal priority + new_priority = LLPluginClassMedia::PRIORITY_NORMAL; + impl_count_interest_normal++; + } + else if (impl_count_interest_low + impl_count_interest_normal < (int)max_low + (int)max_normal) + { + // The next max_low inworld get turned down + new_priority = LLPluginClassMedia::PRIORITY_LOW; + impl_count_interest_low++; + + // Set the low priority size for downsampling to approximately the size the texture is displayed at. + { + F32 approximate_interest_dimension = fsqrtf(pimpl->getInterest()); + + pimpl->setLowPrioritySizeLimit(llround(approximate_interest_dimension)); + } + } + else + { + // Any additional impls (up to max_instances) get very infrequent time + new_priority = LLPluginClassMedia::PRIORITY_SLIDESHOW; + } + } + + pimpl->setPriority(new_priority); + +#if 0 + LL_DEBUGS("PluginPriority") << " " << pimpl + << ", setting priority to " << new_priority + << (pimpl->hasFocus()?", HAS FOCUS":"") + << (pimpl->getUsedInUI()?", is UI":"") + << ", cpu " << pimpl->getCPUUsage() + << ", interest " << pimpl->getInterest() + << ", media url " << pimpl->getMediaURL() << llendl; +#endif + + total_cpu += pimpl->getCPUUsage(); + impl_count_total++; + } + + LL_DEBUGS("PluginPriority") << "Total reported CPU usage is " << total_cpu << llendl; + } ////////////////////////////////////////////////////////////////////////////////////////// // static void LLViewerMedia::cleanupClass() { - // This is no longer necessary, since the list is no longer smart pointers. -#if 0 - while(!sViewerMediaImplList.empty()) - { - sViewerMediaImplList.pop_back(); - } -#endif + // This is no longer necessary, since sViewerMediaImplList is no longer smart pointers. } ////////////////////////////////////////////////////////////////////////////////////////// // LLViewerMediaImpl ////////////////////////////////////////////////////////////////////////////////////////// -LLViewerMediaImpl::LLViewerMediaImpl(const std::string& media_url, - const LLUUID& texture_id, +LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, S32 media_width, S32 media_height, U8 media_auto_scale, - U8 media_loop, - const std::string& mime_type) + U8 media_loop) : mMediaSource( NULL ), mMovieImageHasMips(false), @@ -368,13 +578,30 @@ LLViewerMediaImpl::LLViewerMediaImpl(const std::string& media_url, mMediaHeight(media_height), mMediaAutoScale(media_auto_scale), mMediaLoop(media_loop), - mMediaURL(media_url), - mMimeType(mime_type), mNeedsNewTexture(true), mSuspendUpdates(false), - mVisible(true) + mVisible(true), + mLastSetCursor( UI_CURSOR_ARROW ), + mMediaNavState( MEDIANAVSTATE_NONE ), + mInterest(0.0f), + mUsedInUI(false), + mHasFocus(false), + mPriority(LLPluginClassMedia::PRIORITY_UNLOADED), + mDoNavigateOnLoad(false), + mDoNavigateOnLoadServerRequest(false), + mIsUpdated(false) { - createMediaSource(); + + add_media_impl(this); + + // connect this media_impl to the media texture, creating it if it doesn't exist.0 + // This is necessary because we need to be able to use getMaxVirtualSize() even if the media plugin is not loaded. + LLViewerMediaTexture* media_tex = LLViewerTextureManager::getMediaTexture(mTextureId); + if(media_tex) + { + media_tex->setMediaImpl(); + } + } ////////////////////////////////////////////////////////////////////////////////////////// @@ -386,7 +613,26 @@ LLViewerMediaImpl::~LLViewerMediaImpl() } destroyMediaSource(); - LLViewerMedia::removeMedia(this); + + LLViewerMediaTexture::removeMediaImplFromTexture(mTextureId) ; + + remove_media_impl(this); +} + +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::emitEvent(LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event) +{ + // Broadcast to observers using the superclass version + LLViewerMediaEventEmitter::emitEvent(plugin, event); + + // If this media is on one or more LLVOVolume objects, tell them about the event as well. + std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ; + while(iter != mObjectList.end()) + { + LLVOVolume *self = *iter; + ++iter; + self->mediaEvent(this, plugin, event); + } } ////////////////////////////////////////////////////////////////////////////////////////// @@ -396,11 +642,7 @@ bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type) { if(! initializePlugin(mime_type)) { - LL_WARNS("Plugin") << "plugin intialization failed for mime type: " << mime_type << LL_ENDL; - LLSD args; - args["MIME_TYPE"] = mime_type; - LLNotifications::instance().add("NoPlugin", args); - + // This may be the case where the plugin's priority is PRIORITY_UNLOADED return false; } } @@ -412,29 +654,42 @@ bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type) ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::createMediaSource() { - if(! mMediaURL.empty()) + if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED) { - navigateTo(mMediaURL, mMimeType, true); + // This media shouldn't be created yet. + return; } - else if(! mMimeType.empty()) + + if(mDoNavigateOnLoad) { - initializeMedia(mMimeType); + if(! mMediaURL.empty()) + { + navigateTo(mMediaURL, mMimeType, false, mDoNavigateOnLoadServerRequest); + } + else if(! mMimeType.empty()) + { + initializeMedia(mMimeType); + } } - } ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::destroyMediaSource() { mNeedsNewTexture = true; - if(! mMediaSource) + + // Tell the viewer media texture it's no longer active + LLViewerMediaTexture* oldImage = LLViewerTextureManager::findMediaTexture( mTextureId ); + if (oldImage) { - return; + oldImage->setPlaying(FALSE) ; } - // Restore the texture - updateMovieImage(LLUUID::null, false); - delete mMediaSource; - mMediaSource = NULL; + + if(mMediaSource) + { + delete mMediaSource; + mMediaSource = NULL; + } } ////////////////////////////////////////////////////////////////////////////////////////// @@ -487,6 +742,11 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ } } + LL_WARNS("Plugin") << "plugin intialization failed for mime type: " << media_type << LL_ENDL; + LLSD args; + args["MIME_TYPE"] = media_type; + LLNotifications::instance().add("NoPlugin", args); + return NULL; } @@ -506,7 +766,15 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) // and unconditionally set the mime type mMimeType = media_type; - LLPluginClassMedia* media_source = newSourceFromMediaType(media_type, this, mMediaWidth, mMediaHeight); + if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED) + { + // This impl should not be loaded at this time. + LL_DEBUGS("PluginPriority") << this << "Not loading (PRIORITY_UNLOADED)" << LL_ENDL; + + return false; + } + + LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight); if (media_source) { @@ -543,13 +811,11 @@ void LLViewerMediaImpl::play() { if(!initializePlugin(mMimeType)) { - // Plugin failed initialization... should assert or something + // This may be the case where the plugin's priority is PRIORITY_UNLOADED return; } } - // updateMovieImage(mTextureId, true); - mMediaSource->loadURI( mMediaURL ); if(/*mMediaSource->pluginSupportsMediaTime()*/ true) { @@ -606,6 +872,8 @@ void LLViewerMediaImpl::setVolume(F32 volume) ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::focus(bool focus) { + mHasFocus = focus; + if (mMediaSource) { // call focus just for the hell of it, even though this apopears to be a nop @@ -620,12 +888,20 @@ void LLViewerMediaImpl::focus(bool focus) } } +////////////////////////////////////////////////////////////////////////////////////////// +bool LLViewerMediaImpl::hasFocus() const +{ + // FIXME: This might be able to be a bit smarter by hooking into LLViewerMediaFocus, etc. + return mHasFocus; +} + ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::mouseDown(S32 x, S32 y) { scaleMouse(&x, &y); mLastMouseX = x; mLastMouseY = y; +// llinfos << "mouse down (" << x << ", " << y << ")" << llendl; if (mMediaSource) { mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, x, y, 0); @@ -638,6 +914,7 @@ void LLViewerMediaImpl::mouseUp(S32 x, S32 y) scaleMouse(&x, &y); mLastMouseX = x; mLastMouseY = y; +// llinfos << "mouse up (" << x << ", " << y << ")" << llendl; if (mMediaSource) { mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, x, y, 0); @@ -647,15 +924,47 @@ void LLViewerMediaImpl::mouseUp(S32 x, S32 y) ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::mouseMove(S32 x, S32 y) { - scaleMouse(&x, &y); + scaleMouse(&x, &y); mLastMouseX = x; mLastMouseY = y; +// llinfos << "mouse move (" << x << ", " << y << ")" << llendl; if (mMediaSource) { mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_MOVE, x, y, 0); } } +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::mouseDown(const LLVector2& texture_coords) +{ + if(mMediaSource) + { + mouseDown( + llround(texture_coords.mV[VX] * mMediaSource->getTextureWidth()), + llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight())); + } +} + +void LLViewerMediaImpl::mouseUp(const LLVector2& texture_coords) +{ + if(mMediaSource) + { + mouseUp( + llround(texture_coords.mV[VX] * mMediaSource->getTextureWidth()), + llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight())); + } +} + +void LLViewerMediaImpl::mouseMove(const LLVector2& texture_coords) +{ + if(mMediaSource) + { + mouseMove( + llround(texture_coords.mV[VX] * mMediaSource->getTextureWidth()), + llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight())); + } +} + ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::mouseLeftDoubleClick(S32 x, S32 y) { @@ -694,6 +1003,10 @@ BOOL LLViewerMediaImpl::handleMouseUp(S32 x, S32 y, MASK mask) ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::navigateHome() { + mMediaURL = mHomeURL; + mDoNavigateOnLoad = !mMediaURL.empty(); + mDoNavigateOnLoadServerRequest = false; + if(mMediaSource) { mMediaSource->loadURI( mHomeURL ); @@ -701,17 +1014,43 @@ void LLViewerMediaImpl::navigateHome() } ////////////////////////////////////////////////////////////////////////////////////////// -void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type) +void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type, bool server_request) { + if(server_request) + { + setNavState(MEDIANAVSTATE_SERVER_SENT); + } + else + { + setNavState(MEDIANAVSTATE_NONE); + } + + // Always set the current URL. + mMediaURL = url; + + // If the current URL is not null, make the instance do a navigate on load. + mDoNavigateOnLoad = !mMediaURL.empty(); + + // and if this was a server request, the navigate on load will also need to be one. + mDoNavigateOnLoadServerRequest = server_request; + + if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED) + { + // This impl should not be loaded at this time. + LL_DEBUGS("PluginPriority") << this << "Not loading (PRIORITY_UNLOADED)" << LL_ENDL; + + return; + } + if(rediscover_type) { - LLURI uri(url); + LLURI uri(mMediaURL); std::string scheme = uri.scheme(); if(scheme.empty() || "http" == scheme || "https" == scheme) { - LLHTTPClient::getHeaderOnly( url, new LLMimeDiscoveryResponder(this)); + LLHTTPClient::getHeaderOnly( mMediaURL, new LLMimeDiscoveryResponder(this)); } else if("data" == scheme || "file" == scheme || "about" == scheme) { @@ -719,7 +1058,7 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi // We use "data" internally for a text/html url for loading the login screen if(initializeMedia("text/html")) { - mMediaSource->loadURI( url ); + mMediaSource->loadURI( mMediaURL ); } } else @@ -727,24 +1066,23 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi // This catches 'rtsp://' urls if(initializeMedia(scheme)) { - mMediaSource->loadURI( url ); + mMediaSource->loadURI( mMediaURL ); } } } else if (mMediaSource) { - mMediaSource->loadURI( url ); + mMediaSource->loadURI( mMediaURL ); } else if(initializeMedia(mime_type) && mMediaSource) { - mMediaSource->loadURI( url ); + mMediaSource->loadURI( mMediaURL ); } else { LL_WARNS("Media") << "Couldn't navigate to: " << url << " as there is no media type for: " << mime_type << LL_ENDL; return; } - mMediaURL = url; } @@ -806,49 +1144,27 @@ bool LLViewerMediaImpl::canNavigateBack() return result; } - ////////////////////////////////////////////////////////////////////////////////////////// -void LLViewerMediaImpl::updateMovieImage(const LLUUID& uuid, BOOL active) +void LLViewerMediaImpl::update() { - // IF the media image hasn't changed, do nothing - if (mTextureId == uuid) - { - return; - } - // If we have changed media uuid, restore the old one - if (!mTextureId.isNull()) + if(mMediaSource == NULL) { - LLViewerMediaTexture* old_image = LLViewerTextureManager::findMediaTexture( mTextureId ); - if (old_image) + if(mPriority != LLPluginClassMedia::PRIORITY_UNLOADED) { - old_image->setPlaying(FALSE); - LLViewerTexture* original_texture = old_image->getOldTexture(); - if(original_texture) + // This media may need to be loaded. + if(sMediaCreateTimer.hasExpired()) { - old_image->switchToTexture(original_texture); + LL_DEBUGS("PluginPriority") << this << ": creating media based on timer expiration" << LL_ENDL; + createMediaSource(); + sMediaCreateTimer.setTimerExpirySec(LLVIEWERMEDIA_CREATE_DELAY); + } + else + { + LL_DEBUGS("PluginPriority") << this << ": NOT creating media (waiting on timer)" << LL_ENDL; } } } - // If the movie is playing, set the new media image - if (active && !uuid.isNull()) - { - LLViewerMediaTexture* viewerImage = LLViewerTextureManager::findMediaTexture( uuid ); - if( viewerImage ) - { - mTextureId = uuid; - - // Can't use mipmaps for movies because they don't update the full image - mMovieImageHasMips = viewerImage->getUseMipMaps(); - viewerImage->reinit(FALSE); - // FIXME -// viewerImage->mIsMediaTexture = TRUE; - } - } -} - -////////////////////////////////////////////////////////////////////////////////////////// -void LLViewerMediaImpl::update() -{ + if(mMediaSource == NULL) { return; @@ -877,6 +1193,10 @@ void LLViewerMediaImpl::update() if(placeholder_image) { LLRect dirty_rect; + + // Since we're updating this texture, we know it's playing. Tell the texture to do its replacement magic so it gets rendered. + placeholder_image->setPlaying(TRUE); + if(mMediaSource->getDirty(&dirty_rect)) { // Constrain the dirty rect to be inside the texture @@ -930,12 +1250,11 @@ LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage() if (mNeedsNewTexture || placeholder_image->getUseMipMaps() -// || ! placeholder_image->getType() == LLViewerTexture::MEDIA_TEXTURE || placeholder_image->getWidth() != mMediaSource->getTextureWidth() || placeholder_image->getHeight() != mMediaSource->getTextureHeight()) { - llinfos << "initializing media placeholder" << llendl; - llinfos << "movie image id " << mTextureId << llendl; + LL_DEBUGS("Media") << "initializing media placeholder" << LL_ENDL; + LL_DEBUGS("Media") << "movie image id " << mTextureId << LL_ENDL; int texture_width = mMediaSource->getTextureWidth(); int texture_height = mMediaSource->getTextureHeight(); @@ -960,9 +1279,6 @@ LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage() placeholder_image->createGLTexture(discard_level, raw); - // placeholder_image->setExplicitFormat() - placeholder_image->setUseMipMaps(FALSE); - // MEDIAOPT: set this dynamically on play/stop // FIXME // placeholder_image->mIsMediaTexture = true; @@ -996,11 +1312,6 @@ void LLViewerMediaImpl::setVisible(bool visible) createMediaSource(); } } - - if(mMediaSource) - { - mMediaSource->setPriority(mVisible?LLPluginClassMedia::PRIORITY_NORMAL:LLPluginClassMedia::PRIORITY_HIDDEN); - } } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1059,7 +1370,7 @@ bool LLViewerMediaImpl::hasMedia() } ////////////////////////////////////////////////////////////////////////////////////////// -void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent event) +void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent event) { switch(event) { @@ -1070,11 +1381,77 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* self, LLPluginClass LLNotifications::instance().add("MediaPluginFailed", args); } break; + + case MEDIA_EVENT_CURSOR_CHANGED: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << plugin->getCursorName() << LL_ENDL; + + std::string cursor = plugin->getCursorName(); + + if(cursor == "arrow") + mLastSetCursor = UI_CURSOR_ARROW; + else if(cursor == "ibeam") + mLastSetCursor = UI_CURSOR_IBEAM; + else if(cursor == "splith") + mLastSetCursor = UI_CURSOR_SIZEWE; + else if(cursor == "splitv") + mLastSetCursor = UI_CURSOR_SIZENS; + else if(cursor == "hand") + mLastSetCursor = UI_CURSOR_HAND; + else // for anything else, default to the arrow + mLastSetCursor = UI_CURSOR_ARROW; + } + break; + + case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_BEGIN: + { + LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_BEGIN, uri is: " << plugin->getNavigateURI() << LL_ENDL; + + if(getNavState() == MEDIANAVSTATE_SERVER_SENT) + { + setNavState(MEDIANAVSTATE_SERVER_BEGUN); + } + else + { + setNavState(MEDIANAVSTATE_BEGUN); + } + } + break; + + case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE: + { + LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_COMPLETE, uri is: " << plugin->getNavigateURI() << LL_ENDL; + setNavState(MEDIANAVSTATE_NONE); + } + break; + + case LLViewerMediaObserver::MEDIA_EVENT_LOCATION_CHANGED: + { + LL_DEBUGS("Media") << "MEDIA_EVENT_LOCATION_CHANGED, uri is: " << plugin->getLocation() << LL_ENDL; + + if(getNavState() == MEDIANAVSTATE_BEGUN) + { + setNavState(MEDIANAVSTATE_FIRST_LOCATION_CHANGED); + } + else if(getNavState() == MEDIANAVSTATE_SERVER_BEGUN) + { + setNavState(MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED); + } + else + { + // Don't track redirects. + setNavState(MEDIANAVSTATE_NONE); + } + } + break; + + default: break; } + // Just chain the event to observers. - emitEvent(self, event); + emitEvent(plugin, event); } //////////////////////////////////////////////////////////////////////////////// @@ -1137,6 +1514,146 @@ LLViewerMediaImpl::canPaste() const return FALSE; } +void LLViewerMediaImpl::setUpdated(BOOL updated) +{ + mIsUpdated = updated ; +} + +BOOL LLViewerMediaImpl::isUpdated() +{ + return mIsUpdated ; +} + +void LLViewerMediaImpl::calculateInterest() +{ + LLViewerMediaTexture* texture = LLViewerTextureManager::findMediaTexture( mTextureId ); + + if(texture != NULL) + { + mInterest = texture->getMaxVirtualSize(); + } + else + { + // I don't think this case should ever be hit. + LL_WARNS("Plugin") << "no texture!" << LL_ENDL; + mInterest = 0.0f; + } +} + +F64 LLViewerMediaImpl::getApproximateTextureInterest() +{ + F64 result = 0.0f; + + if(mMediaSource) + { + result = mMediaSource->getFullWidth(); + result *= mMediaSource->getFullHeight(); + } + + return result; +} + +void LLViewerMediaImpl::setUsedInUI(bool used_in_ui) +{ + mUsedInUI = used_in_ui; + + // HACK: Force elements used in UI to load right away. + // This fixes some issues where UI code that uses the browser instance doesn't expect it to be unloaded. + if(mUsedInUI && (mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)) + { + if(getVisible()) + { + mPriority = LLPluginClassMedia::PRIORITY_NORMAL; + } + else + { + mPriority = LLPluginClassMedia::PRIORITY_HIDDEN; + } + + createMediaSource(); + } +}; + +F64 LLViewerMediaImpl::getCPUUsage() const +{ + F64 result = 0.0f; + + if(mMediaSource) + { + result = mMediaSource->getCPUUsage(); + } + + return result; +} + +void LLViewerMediaImpl::setPriority(LLPluginClassMedia::EPriority priority) +{ + mPriority = priority; + + if(priority == LLPluginClassMedia::PRIORITY_UNLOADED) + { + if(mMediaSource) + { + // Need to unload the media source + destroyMediaSource(); + } + } + + if(mMediaSource) + { + mMediaSource->setPriority(mPriority); + } + + // NOTE: loading (or reloading) media sources whose priority has risen above PRIORITY_UNLOADED is done in update(). +} + +void LLViewerMediaImpl::setLowPrioritySizeLimit(int size) +{ + if(mMediaSource) + { + mMediaSource->setLowPrioritySizeLimit(size); + } +} + +void LLViewerMediaImpl::setNavState(EMediaNavState state) +{ + mMediaNavState = state; + + switch (state) + { + case MEDIANAVSTATE_NONE: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_NONE" << llendl; break; + case MEDIANAVSTATE_BEGUN: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_BEGUN" << llendl; break; + case MEDIANAVSTATE_FIRST_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_FIRST_LOCATION_CHANGED" << llendl; break; + case MEDIANAVSTATE_SERVER_SENT: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_SENT" << llendl; break; + case MEDIANAVSTATE_SERVER_BEGUN: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_BEGUN" << llendl; break; + case MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED: LL_DEBUGS("Media") << "Setting nav state to MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED" << llendl; break; + } +} + + +void LLViewerMediaImpl::addObject(LLVOVolume* obj) +{ + std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ; + for(; iter != mObjectList.end() ; ++iter) + { + if(*iter == obj) + { + return ; //already in the list. + } + } + + mObjectList.push_back(obj) ; +} + +void LLViewerMediaImpl::removeObject(LLVOVolume* obj) +{ + mObjectList.remove(obj) ; +} + +const std::list< LLVOVolume* >* LLViewerMediaImpl::getObjectList() const +{ + return &mObjectList ; +} ////////////////////////////////////////////////////////////////////////////////////////// //static diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 9a61394383..775f72d56f 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -41,9 +41,13 @@ #include "llviewermediaobserver.h" +#include "llpluginclassmedia.h" + class LLViewerMediaImpl; class LLUUID; class LLViewerMediaTexture; +class LLMediaEntry; +class LLVOVolume ; typedef LLPointer viewer_media_t; /////////////////////////////////////////////////////////////////////////////// @@ -55,7 +59,7 @@ public: bool addObserver( LLViewerMediaObserver* subject ); bool remObserver( LLViewerMediaObserver* subject ); - void emitEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent event); + virtual void emitEvent(LLPluginClassMedia* self, LLViewerMediaObserver::EMediaEvent event); private: typedef std::list< LLViewerMediaObserver* > observerListType; @@ -69,15 +73,13 @@ class LLViewerMedia // Special case early init for just web browser component // so we can show login screen. See .cpp file for details. JC - static viewer_media_t newMediaImpl(const std::string& media_url, - const LLUUID& texture_id, - S32 media_width, - S32 media_height, - U8 media_auto_scale, - U8 media_loop, - std::string mime_type = "none/none"); + static viewer_media_t newMediaImpl(const LLUUID& texture_id, + S32 media_width = 0, + S32 media_height = 0, + U8 media_auto_scale = false, + U8 media_loop = false); - static void removeMedia(LLViewerMediaImpl* media); + static viewer_media_t updateMediaImpl(LLMediaEntry* media_entry, const std::string& previous_url, bool update_from_self); static LLViewerMediaImpl* getMediaImplFromTextureID(const LLUUID& texture_id); static std::string getCurrentUserAgent(); static void updateBrowserUserAgent(); @@ -102,15 +104,18 @@ class LLViewerMediaImpl LOG_CLASS(LLViewerMediaImpl); public: - LLViewerMediaImpl(const std::string& media_url, + LLViewerMediaImpl( const LLUUID& texture_id, S32 media_width, S32 media_height, U8 media_auto_scale, - U8 media_loop, - const std::string& mime_type); + U8 media_loop); ~LLViewerMediaImpl(); + + // Override inherited version from LLViewerMediaEventEmitter + virtual void emitEvent(LLPluginClassMedia* self, LLViewerMediaObserver::EMediaEvent event); + void createMediaSource(); void destroyMediaSource(); void setMediaType(const std::string& media_type); @@ -126,36 +131,44 @@ public: void seek(F32 time); void setVolume(F32 volume); void focus(bool focus); + // True if the impl has user focus. + bool hasFocus() const; void mouseDown(S32 x, S32 y); void mouseUp(S32 x, S32 y); void mouseMove(S32 x, S32 y); + void mouseDown(const LLVector2& texture_coords); + void mouseUp(const LLVector2& texture_coords); + void mouseMove(const LLVector2& texture_coords); void mouseLeftDoubleClick(S32 x,S32 y ); void mouseCapture(); void navigateHome(); - void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false); + void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false); void navigateStop(); bool handleKeyHere(KEY key, MASK mask); bool handleUnicodeCharHere(llwchar uni_char); bool canNavigateForward(); bool canNavigateBack(); std::string getMediaURL() { return mMediaURL; } - std::string getMediaHomeURL() { return mHomeURL; } + std::string getHomeURL() { return mHomeURL; } + void setHomeURL(const std::string& home_url) { mHomeURL = home_url; }; std::string getMimeType() { return mMimeType; } void scaleMouse(S32 *mouse_x, S32 *mouse_y); void update(); - void updateMovieImage(const LLUUID& image_id, BOOL active); void updateImagesMediaStreams(); LLUUID getMediaTextureID(); void suspendUpdates(bool suspend) { mSuspendUpdates = suspend; }; void setVisible(bool visible); + bool getVisible() const { return mVisible; }; bool isMediaPlaying(); bool isMediaPaused(); bool hasMedia(); + ECursorType getLastSetCursor() { return mLastSetCursor; }; + // utility function to create a ready-to-use media instance from a desired media type. static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height); @@ -191,7 +204,7 @@ public: /*virtual*/ BOOL hasMouseCapture() { return gFocusMgr.getMouseCapture() == this; }; // Inherited from LLPluginClassMediaOwner - /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, LLPluginClassMediaOwner::EMediaEvent); + /*virtual*/ void handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent); // LLEditMenuHandler overrides /*virtual*/ void cut(); @@ -203,6 +216,45 @@ public: /*virtual*/ void paste(); /*virtual*/ BOOL canPaste() const; + void addObject(LLVOVolume* obj) ; + void removeObject(LLVOVolume* obj) ; + const std::list< LLVOVolume* >* getObjectList() const ; + void setUpdated(BOOL updated) ; + BOOL isUpdated() ; + + // Updates the "interest" value in this object + void calculateInterest(); + F64 getInterest() const { return mInterest; }; + F64 getApproximateTextureInterest(); + + // Mark this object as being used in a UI panel instead of on a prim + // This will be used as part of the interest sorting algorithm. + void setUsedInUI(bool used_in_ui); + bool getUsedInUI() const { return mUsedInUI; }; + + F64 getCPUUsage() const; + + void setPriority(LLPluginClassMedia::EPriority priority); + LLPluginClassMedia::EPriority getPriority() { return mPriority; }; + + void setLowPrioritySizeLimit(int size); + + typedef enum + { + MEDIANAVSTATE_NONE, // State is outside what we need to track for navigation. + MEDIANAVSTATE_BEGUN, // a MEDIA_EVENT_NAVIGATE_BEGIN has been received which was not server-directed + MEDIANAVSTATE_FIRST_LOCATION_CHANGED, // first LOCATION_CHANGED event after a non-server-directed BEGIN + MEDIANAVSTATE_SERVER_SENT, // server-directed nav has been requested, but MEDIA_EVENT_NAVIGATE_BEGIN hasn't been received yet + MEDIANAVSTATE_SERVER_BEGUN, // MEDIA_EVENT_NAVIGATE_BEGIN has been received which was server-directed + MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED // first LOCATION_CHANGED event after a server-directed BEGIN + + }EMediaNavState; + + // Returns the current nav state of the media. + // note that this will be updated BEFORE listeners and objects receive media messages + EMediaNavState getNavState() { return mMediaNavState; } + void setNavState(EMediaNavState state); + public: // a single media url with some data and an impl. LLPluginClassMedia* mMediaSource; @@ -220,7 +272,19 @@ public: bool mNeedsNewTexture; bool mSuspendUpdates; bool mVisible; + ECursorType mLastSetCursor; + EMediaNavState mMediaNavState; + F64 mInterest; + bool mUsedInUI; + bool mHasFocus; + LLPluginClassMedia::EPriority mPriority; + bool mDoNavigateOnLoad; + bool mDoNavigateOnLoadServerRequest; + +private: + BOOL mIsUpdated ; + std::list< LLVOVolume* > mObjectList ; private: LLViewerMediaTexture *updatePlaceholderImage(); diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp index e7576d5c76..f9377ab37b 100644 --- a/indra/newview/llviewermediafocus.cpp +++ b/indra/newview/llviewermediafocus.cpp @@ -47,6 +47,7 @@ #include "llparcel.h" #include "llviewerparcelmgr.h" #include "llweb.h" +#include "llmediaentry.h" // // LLViewerMediaFocus // @@ -91,14 +92,38 @@ void LLViewerMediaFocus::cleanupClass() void LLViewerMediaFocus::setFocusFace( BOOL b, LLPointer objectp, S32 face, viewer_media_t media_impl ) { LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + + if(mMediaImpl.notNull()) + { + mMediaImpl->focus(false); + } + if (b && media_impl.notNull()) { + bool face_auto_zoom = false; mMediaImpl = media_impl; + mMediaImpl->focus(true); + LLSelectMgr::getInstance()->deselectAll(); LLSelectMgr::getInstance()->selectObjectOnly(objectp, face); + if(objectp.notNull()) + { + LLTextureEntry* tep = objectp->getTE(face); + if(! tep->hasMedia()) + { + // Error condition + } + LLMediaEntry* mep = tep->getMediaData(); + face_auto_zoom = mep->getAutoZoom(); + if(! mep->getAutoPlay()) + { + std::string url = mep->getCurrentURL().empty() ? mep->getHomeURL() : mep->getCurrentURL(); + media_impl->navigateTo(url, "", true); + } + } mFocus = LLSelectMgr::getInstance()->getSelection(); - if(mMediaHUD.get() && ! parcel->getMediaPreventCameraZoom()) + if(mMediaHUD.get() && face_auto_zoom && ! parcel->getMediaPreventCameraZoom()) { mMediaHUD.get()->resetZoomLevel(); mMediaHUD.get()->nextZoomLevel(); @@ -108,6 +133,7 @@ void LLViewerMediaFocus::setFocusFace( BOOL b, LLPointer objectp gFocusMgr.setKeyboardFocus(this); } mObjectID = objectp->getID(); + mObjectFace = face; // LLViewerMedia::addObserver(this, mObjectID); @@ -133,6 +159,8 @@ void LLViewerMediaFocus::setFocusFace( BOOL b, LLPointer objectp // and null out the media impl mMediaImpl = NULL; + mObjectID = LLUUID::null; + mObjectFace = 0; } if(mMediaHUD.get()) { @@ -230,6 +258,12 @@ void LLViewerMediaFocus::setMouseOverFlag(bool b, viewer_media_t media_impl) gHUDView->addChild(media_hud); } mMediaHUD.get()->setMediaImpl(media_impl); + + if(mMediaImpl.notNull() && (mMediaImpl != media_impl)) + { + mMediaImpl->focus(false); + } + mMediaImpl = media_impl; } mMouseOverFlag = b; @@ -356,3 +390,8 @@ F32 LLViewerMediaFocus::getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& // Return the aspect ratio. return *width / *height; } + +bool LLViewerMediaFocus::isFocusedOnFace(LLPointer objectp, S32 face) +{ + return objectp->getID() == mObjectID && face == mObjectFace; +} diff --git a/indra/newview/llviewermediafocus.h b/indra/newview/llviewermediafocus.h index a078d24b6a..2688a8b708 100644 --- a/indra/newview/llviewermediafocus.h +++ b/indra/newview/llviewermediafocus.h @@ -72,6 +72,9 @@ public: void setPickInfo(LLPickInfo pick_info) { mPickInfo = pick_info; } F32 getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth); + // TODO: figure out why selection mgr hates me + bool isFocusedOnFace(LLPointer objectp, S32 face); + protected: /*virtual*/ void onFocusReceived(); /*virtual*/ void onFocusLost(); @@ -83,6 +86,7 @@ private: LLPickInfo mPickInfo; LLHandle mMediaHUD; LLUUID mObjectID; + S32 mObjectFace; viewer_media_t mMediaImpl; }; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index d3d5f060e1..05011a1568 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -47,6 +47,7 @@ #include "llframetimer.h" #include "llinventory.h" #include "llmaterialtable.h" +#include "llmediadataresponder.h" #include "llmutelist.h" #include "llnamevalue.h" #include "llprimitive.h" @@ -100,6 +101,8 @@ #include "llvowlsky.h" #include "llmanip.h" #include "lltrans.h" +#include "llsdutil.h" +#include "llmediaentry.h" //#define DEBUG_UPDATE_TYPE @@ -470,6 +473,7 @@ void LLViewerObject::cleanupVOClasses() LLVOWater::cleanupClass(); LLVOTree::cleanupClass(); LLVOAvatar::cleanupClass(); + LLVOVolume::cleanupClass(); } // Replaces all name value pairs with data from \n delimited list @@ -700,6 +704,42 @@ void LLViewerObject::hideExtraDisplayItems( BOOL hidden ) } } +U32 LLViewerObject::checkMediaURL(const std::string &media_url) +{ + U32 retval = (U32)0x0; + if (!mMedia && !media_url.empty()) + { + retval |= MEDIA_URL_ADDED; + mMedia = new LLViewerObjectMedia; + mMedia->mMediaURL = media_url; + mMedia->mMediaType = LLViewerObject::MEDIA_SET; + mMedia->mPassedWhitelist = FALSE; + } + else if (mMedia) + { + if (media_url.empty()) + { + retval |= MEDIA_URL_REMOVED; + delete mMedia; + mMedia = NULL; + } + else if (mMedia->mMediaURL != media_url) // <-- This is an optimization. If they are equal don't bother with below's test. + { + /*if (! (LLTextureEntry::getAgentIDFromMediaVersionString(media_url) == gAgent.getID() && + LLTextureEntry::getVersionFromMediaVersionString(media_url) == + LLTextureEntry::getVersionFromMediaVersionString(mMedia->mMediaURL) + 1)) + */ + { + // If the media URL is different and WE were not the one who + // changed it, mark dirty. + retval |= MEDIA_URL_UPDATED; + } + mMedia->mMediaURL = media_url; + mMedia->mPassedWhitelist = FALSE; + } + } + return retval; +} U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, @@ -1045,35 +1085,8 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, std::string media_url; mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_MediaURL, media_url, block_num); - //if (!media_url.empty()) - //{ - // llinfos << "WEBONPRIM media_url " << media_url << llendl; - //} - if (!mMedia && !media_url.empty()) - { - retval |= MEDIA_URL_ADDED; - mMedia = new LLViewerObjectMedia; - mMedia->mMediaURL = media_url; - mMedia->mMediaType = LLViewerObject::MEDIA_TYPE_WEB_PAGE; - mMedia->mPassedWhitelist = FALSE; - } - else if (mMedia) - { - if (media_url.empty()) - { - retval |= MEDIA_URL_REMOVED; - delete mMedia; - mMedia = NULL; - } - else if (mMedia->mMediaURL != media_url) - { - // We just added or changed a web page. - retval |= MEDIA_URL_UPDATED; - mMedia->mMediaURL = media_url; - mMedia->mPassedWhitelist = FALSE; - } - } - + retval |= checkMediaURL(media_url); + // // Unpack particle system data // @@ -1456,31 +1469,12 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, mText = NULL; } + std::string media_url; if (value & 0x200) { - std::string media_url; dp->unpackString(media_url, "MediaURL"); - if (!mMedia) - { - retval |= MEDIA_URL_ADDED; - mMedia = new LLViewerObjectMedia; - mMedia->mMediaURL = media_url; - mMedia->mMediaType = LLViewerObject::MEDIA_TYPE_WEB_PAGE; - mMedia->mPassedWhitelist = FALSE; - } - else if (mMedia->mMediaURL != media_url) - { - retval |= MEDIA_URL_UPDATED; - mMedia->mMediaURL = media_url; - mMedia->mPassedWhitelist = FALSE; - } - } - else if (mMedia) - { - retval |= MEDIA_URL_REMOVED; - delete mMedia; - mMedia = NULL; } + retval |= checkMediaURL(media_url); // // Unpack particle system data @@ -3472,7 +3466,7 @@ U8 LLViewerObject::getMediaType() const } else { - return LLViewerObject::MEDIA_TYPE_NONE; + return LLViewerObject::MEDIA_NONE; } } @@ -3734,16 +3728,13 @@ S32 LLViewerObject::setTETextureCore(const U8 te, const LLUUID& uuid, LLHost hos } -void LLViewerObject::changeTEImage(const LLViewerTexture* old_image, LLViewerTexture* new_image) +void LLViewerObject::changeTEImage(S32 index, LLViewerTexture* new_image) { - U32 end = getNumTEs() ; - for (U32 face = 0 ; face < end ; face++) + if(index < 0 || index >= getNumTEs()) { - if(old_image == mTEImages[face]) - { - mTEImages[face] = new_image ; - } + return ; } + mTEImages[index] = new_image ; } S32 LLViewerObject::setTETexture(const U8 te, const LLUUID& uuid) diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 08e2ec47cd..bec36f9da7 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -158,10 +158,16 @@ public: virtual BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); // Types of media we can associate - enum { MEDIA_TYPE_NONE = 0, MEDIA_TYPE_WEB_PAGE = 1 }; + enum { MEDIA_NONE = 0, MEDIA_SET = 1 }; // Return codes for processUpdateMessage - enum { MEDIA_URL_REMOVED = 0x1, MEDIA_URL_ADDED = 0x2, MEDIA_URL_UPDATED = 0x4, INVALID_UPDATE = 0x80000000 }; + enum { + MEDIA_URL_REMOVED = 0x1, + MEDIA_URL_ADDED = 0x2, + MEDIA_URL_UPDATED = 0x4, + MEDIA_FLAGS_CHANGED = 0x8, + INVALID_UPDATE = 0x80000000 + }; virtual U32 processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, @@ -318,7 +324,7 @@ public: /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow); /*virtual*/ BOOL setMaterial(const U8 material); virtual void setTEImage(const U8 te, LLViewerTexture *imagep); // Not derived from LLPrimitive - void changeTEImage(const LLViewerTexture* old_image, LLViewerTexture* new_image) ; + void changeTEImage(S32 index, LLViewerTexture* new_image) ; LLViewerTexture *getTEImage(const U8 te) const; void fitFaceTexture(const U8 face); @@ -504,6 +510,10 @@ private: ExtraParameter* getExtraParameterEntry(U16 param_type) const; ExtraParameter* getExtraParameterEntryCreate(U16 param_type); bool unpackParameterEntry(U16 param_type, LLDataPacker *dp); + + // This function checks to see if the given media URL has changed its version + // and the update wasn't due to this agent's last action. + U32 checkMediaURL(const std::string &media_url); public: // diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp index 86d51bfd4b..a3f9c839a0 100644 --- a/indra/newview/llviewerparcelmedia.cpp +++ b/indra/newview/llviewerparcelmedia.cpp @@ -46,6 +46,7 @@ #include "llnotifications.h" #include "llfirstuse.h" #include "llpluginclassmedia.h" +#include "llviewertexture.h" // Static Variables @@ -219,17 +220,25 @@ void LLViewerParcelMedia::play(LLParcel* parcel) // Delete the old one first so they don't fight over the texture. sMediaImpl->stop(); - sMediaImpl = LLViewerMedia::newMediaImpl(media_url, placeholder_texture_id, - media_width, media_height, media_auto_scale, + sMediaImpl = LLViewerMedia::newMediaImpl( + placeholder_texture_id, + media_width, + media_height, + media_auto_scale, media_loop); + sMediaImpl->navigateTo(media_url); } } else { // There is no media impl, make a new one - sMediaImpl = LLViewerMedia::newMediaImpl(media_url, placeholder_texture_id, - media_width, media_height, media_auto_scale, + sMediaImpl = LLViewerMedia::newMediaImpl( + placeholder_texture_id, + media_width, + media_height, + media_auto_scale, media_loop); + sMediaImpl->navigateTo(media_url); } LLFirstUse::useMedia(); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 2c68a106c3..7ea55b49e8 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1428,6 +1428,8 @@ void LLViewerRegion::setSeedCapability(const std::string& url) capabilityNames.append("EventQueueGet"); capabilityNames.append("FetchInventory"); capabilityNames.append("WebFetchInventoryDescendents"); + capabilityNames.append("ObjectMedia"); + capabilityNames.append("ObjectMediaNavigate"); capabilityNames.append("FetchLib"); capabilityNames.append("FetchLibDescendents"); capabilityNames.append("GroupProposalBallot"); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index e3d657068f..a2f6b70006 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -62,6 +62,10 @@ #include "llappviewer.h" #include "lltextureatlas.h" #include "lltextureatlasmanager.h" +#include "lltextureentry.h" +#include "llmediaentry.h" +#include "llvovolume.h" +#include "llviewermedia.h" /////////////////////////////////////////////////////////////////////////////// // statics @@ -114,45 +118,18 @@ LLViewerTexture* LLViewerTextureManager::findTexture(const LLUUID& id) LLViewerMediaTexture* LLViewerTextureManager::findMediaTexture(const LLUUID &media_id) { - LLViewerMediaTexture::media_map_t::iterator iter = LLViewerMediaTexture::sMediaMap.find(media_id); - if(iter == LLViewerMediaTexture::sMediaMap.end()) - return NULL; - - ((LLViewerMediaTexture*)(iter->second))->getLastReferencedTimer()->reset() ; - return iter->second; + return LLViewerMediaTexture::findMediaTexture(media_id) ; } LLViewerMediaTexture* LLViewerTextureManager::getMediaTexture(const LLUUID& id, BOOL usemipmaps, LLImageGL* gl_image) { - LLViewerMediaTexture* tex = LLViewerTextureManager::findMediaTexture(id) ; + LLViewerMediaTexture* tex = LLViewerMediaTexture::findMediaTexture(id) ; if(!tex) { tex = LLViewerTextureManager::createMediaTexture(id, usemipmaps, gl_image) ; } - LLViewerTexture* old_tex = tex->getOldTexture() ; - if(!old_tex) - { - //if there is a fetched texture with the same id, replace it by this media texture - old_tex = gTextureList.findImage(id) ; - if(old_tex) - { - tex->setOldTexture(old_tex) ; - } - } - - if (gSavedSettings.getBOOL("ParcelMediaAutoPlayEnable") && gSavedSettings.getBOOL("AudioStreamingVideo")) - { - if(!tex->isPlaying()) - { - if(old_tex) - { - old_tex->switchToTexture(tex) ; - } - tex->setPlaying(TRUE) ; - } - } - tex->getLastReferencedTimer()->reset() ; + tex->initVirtualSize() ; return tex ; } @@ -303,7 +280,7 @@ void LLViewerTextureManager::cleanup() LLViewerFetchedTexture::sMissingAssetImagep = NULL; LLViewerFetchedTexture::sWhiteImagep = NULL; - LLViewerMediaTexture::sMediaMap.clear() ; + LLViewerMediaTexture::cleanup() ; } //---------------------------------------------------------------------------------------------- @@ -437,6 +414,7 @@ void LLViewerTexture::init(bool firstinit) mTextureState = NO_DELETE ; mDontDiscard = FALSE; mMaxVirtualSize = 0.f; + mNeedsResetMaxVirtualSize = FALSE ; } //virtual @@ -538,33 +516,24 @@ void LLViewerTexture::resetTextureStats(BOOL zero) } } +//virtual +F32 LLViewerTexture::getMaxVirtualSize() +{ + return mMaxVirtualSize ; +} + +//virtual void LLViewerTexture::addFace(LLFace* facep) { mFaceList.push_back(facep) ; } + +//virtual void LLViewerTexture::removeFace(LLFace* facep) { mFaceList.remove(facep) ; } -void LLViewerTexture::switchToTexture(LLViewerTexture* new_texture) -{ - if(this == new_texture) - { - return ; - } - - new_texture->addTextureStats(getMaxVirtualSize()) ; - - for(ll_face_list_t::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ) - { - LLFace* facep = *iter++ ; - facep->setTexture(new_texture) ; - facep->getViewerObject()->changeTEImage(this, new_texture) ; - gPipeline.markTextured(facep->getDrawable()); - } -} - void LLViewerTexture::forceActive() { mTextureState = ACTIVE ; @@ -613,7 +582,16 @@ BOOL LLViewerTexture::createGLTexture(S32 discard_level, const LLImageRaw* image { llassert_always(mGLTexturep.notNull()) ; - return mGLTexturep->createGLTexture(discard_level, imageraw, usename) ; + BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename) ; + + if(ret) + { + mFullWidth = mGLTexturep->getCurrentWidth() ; + mFullHeight = mGLTexturep->getCurrentHeight() ; + mComponents = mGLTexturep->getComponents() ; + } + + return ret ; } void LLViewerTexture::setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes) @@ -2142,18 +2120,59 @@ void LLViewerMediaTexture::updateClass() for(media_map_t::iterator iter = sMediaMap.begin() ; iter != sMediaMap.end(); ) { - LLViewerMediaTexture* mediap = iter->second; - ++iter ; + LLViewerMediaTexture* mediap = iter->second; + // + //Note: delay some time to delete the media textures to stop endlessly creating and immediately removing media texture. + // if(mediap->getNumRefs() == 1 && mediap->getLastReferencedTimer()->getElapsedTimeF32() > MAX_INACTIVE_TIME) //one by sMediaMap { - sMediaMap.erase(mediap->getID()) ; + media_map_t::iterator cur = iter++ ; + sMediaMap.erase(cur) ; } + else + { + ++iter ; + } + } +} + +//static +void LLViewerMediaTexture::removeMediaImplFromTexture(const LLUUID& media_id) +{ + LLViewerMediaTexture* media_tex = findMediaTexture(media_id) ; + if(media_tex) + { + media_tex->invalidateMediaImpl() ; } } +//static +void LLViewerMediaTexture::cleanup() +{ + sMediaMap.clear() ; +} + +//static +LLViewerMediaTexture* LLViewerMediaTexture::findMediaTexture(const LLUUID& media_id) +{ + media_map_t::iterator iter = sMediaMap.find(media_id); + if(iter == sMediaMap.end()) + { + return NULL; + } + + LLViewerMediaTexture* media_tex = iter->second ; + media_tex->setMediaImpl() ; + media_tex->getLastReferencedTimer()->reset() ; + + return media_tex; +} + LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LLImageGL* gl_image) - : LLViewerTexture(id, usemipmaps) + : LLViewerTexture(id, usemipmaps), + mMediaImplp(NULL), + mUpdateVirtualSizeTime(0) { sMediaMap.insert(std::make_pair(id, this)); @@ -2165,6 +2184,13 @@ LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LL mGLTexturep->setNeedsAlphaAndPickMask(FALSE) ; mIsPlaying = FALSE ; + + setMediaImpl() ; +} + +//virtual +LLViewerMediaTexture::~LLViewerMediaTexture() +{ } void LLViewerMediaTexture::reinit(BOOL usemipmaps /* = TRUE */) @@ -2172,7 +2198,6 @@ void LLViewerMediaTexture::reinit(BOOL usemipmaps /* = TRUE */) mGLTexturep = NULL ; init(false); mUseMipMaps = usemipmaps ; - mIsPlaying = FALSE ; getLastReferencedTimer()->reset() ; generateGLTexture() ; @@ -2195,14 +2220,336 @@ S8 LLViewerMediaTexture::getType() const return LLViewerTexture::MEDIA_TEXTURE ; } -void LLViewerMediaTexture::setOldTexture(LLViewerTexture* tex) +void LLViewerMediaTexture::invalidateMediaImpl() { - mOldTexturep = tex ; + mMediaImplp = NULL ; } + +void LLViewerMediaTexture::setMediaImpl() +{ + if(!mMediaImplp) + { + mMediaImplp = LLViewerMedia::getMediaImplFromTextureID(mID) ; + } +} + +//return true if all faces to reference to this media texture are found +//Note: mMediaFaceList is valid only for the current instant +// because it does not check the face validity after the current frame. +BOOL LLViewerMediaTexture::findFaces() +{ + mMediaFaceList.clear() ; + + BOOL ret = TRUE ; + + //for parcel media + LLViewerTexture* tex = gTextureList.findImage(mID) ; + if(tex) + { + const ll_face_list_t* face_list = tex->getFaceList() ; + for(ll_face_list_t::const_iterator iter = face_list->begin(); iter != face_list->end(); ++iter) + { + mMediaFaceList.push_back(*iter) ; + } + } -LLViewerTexture* LLViewerMediaTexture::getOldTexture() const + if(!mMediaImplp) + { + return TRUE ; + } + + //for media on a face. + const std::list< LLVOVolume* >* obj_list = mMediaImplp->getObjectList() ; + std::list< LLVOVolume* >::const_iterator iter = obj_list->begin() ; + for(; iter != obj_list->end(); ++iter) + { + LLVOVolume* obj = *iter ; + if(obj->mDrawable.isNull()) + { + ret = FALSE ; + continue ; + } + + S32 face_id = -1 ; + while((face_id = obj->getFaceIndexWithMediaImpl(mMediaImplp, face_id)) > -1) + { + LLFace* facep = obj->mDrawable->getFace(face_id) ; + if(facep) + { + mMediaFaceList.push_back(facep) ; + } + else + { + ret = FALSE ; + } + } + } + + return ret ; +} + +void LLViewerMediaTexture::initVirtualSize() +{ + if(mIsPlaying) + { + return ; + } + + findFaces() ; + for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter) + { + addTextureStats((*iter)->getVirtualSize()) ; + } +} + +void LLViewerMediaTexture::addMediaToFace(LLFace* facep) +{ + if(!mIsPlaying) + { + return ; //no need to add the face because the media is not in playing. + } + + switchTexture(facep) ; +} + +void LLViewerMediaTexture::removeMediaFromFace(LLFace* facep) +{ + if(!mIsPlaying) + { + return ; //no need to remove the face because the media is not in playing. + } + if(!facep) + { + return ; + } + + mIsPlaying = FALSE ; //set to remove the media from the face. + switchTexture(facep) ; + mIsPlaying = TRUE ; //set the flag back. + + if(mFaceList.empty()) //no face referencing to this media + { + stopPlaying() ; + } +} + +//virtual +void LLViewerMediaTexture::addFace(LLFace* facep) +{ + LLViewerTexture::addFace(facep) ; + + const LLTextureEntry* te = facep->getTextureEntry() ; + if(te) + { + LLViewerTexture* tex = gTextureList.findImage(te->getID()) ; + if(tex) + { + mTextureList.push_back(tex) ;//increase the reference number by one for tex to avoid deleting it. + return ; + } + } + llerrs << "The face does not have a valid texture before media texture." << llendl ; +} + +//virtual +void LLViewerMediaTexture::removeFace(LLFace* facep) +{ + LLViewerTexture::removeFace(facep) ; + + const LLTextureEntry* te = facep->getTextureEntry() ; + if(te) + { + LLViewerTexture* tex = gTextureList.findImage(te->getID()) ; + if(tex) + { + for(std::list< LLPointer >::iterator iter = mTextureList.begin(); + iter != mTextureList.end(); ++iter) + { + if(*iter == tex) + { + mTextureList.erase(iter) ; //decrease the reference number for tex by one. + return ; + } + } + + // + //we have some trouble here: the texture of the face is changed. + //we need to find the former texture, and remove it from the list to avoid memory leaking. + if(mFaceList.empty()) + { + mTextureList.clear() ; + return ; + } + S32 end = mFaceList.size() ; + std::vector te_list(end) ; + S32 i = 0 ; + for(ll_face_list_t::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter) + { + te_list[i++] = (*iter)->getTextureEntry() ;//all textures are in use. + } + for(std::list< LLPointer >::iterator iter = mTextureList.begin(); + iter != mTextureList.end(); ++iter) + { + for(i = 0 ; i < end ; i++) + { + if(te_list[i] && te_list[i]->getID() == (*iter)->getID())//the texture is in use. + { + te_list[i] = NULL ; + break ; + } + } + if(i == end) //no hit for this texture, remove it. + { + mTextureList.erase(iter) ; //decrease the reference number for tex by one. + return ; + } + } + } + } + llerrs << "mTextureList texture reference number is corrupted." << llendl ; +} + +void LLViewerMediaTexture::stopPlaying() +{ + if(mMediaImplp) + { + mMediaImplp->stop() ; + } + mIsPlaying = FALSE ; +} + +void LLViewerMediaTexture::switchTexture(LLFace* facep) +{ + if(facep) + { + //check if another media is playing on this face. + if(facep->getTexture() && facep->getTexture() != this + && facep->getTexture()->getType() == LLViewerTexture::MEDIA_TEXTURE) + { + if(mID == facep->getTexture()->getID()) //this is a parcel media + { + return ; //let the prim media win. + } + } + + if(mIsPlaying) //old textures switch to the media texture + { + facep->switchTexture(this) ; + } + else //switch to old textures. + { + const LLTextureEntry* te = facep->getTextureEntry() ; + if(te) + { + LLViewerTexture* tex = gTextureList.findImage(te->getID()) ; + facep->switchTexture(tex) ; + } + } + } +} + +void LLViewerMediaTexture::setPlaying(BOOL playing) { - return mOldTexturep ; + if(!mMediaImplp) + { + return ; + } + if(!playing && !mIsPlaying) + { + return ; //media is already off + } + + if(playing == mIsPlaying && !mMediaImplp->isUpdated()) + { + return ; //nothing has changed since last time. + } + + mIsPlaying = playing ; + if(mIsPlaying) //is about to play this media + { + if(findFaces()) + { + //about to update all faces. + mMediaImplp->setUpdated(FALSE) ; + } + + if(mMediaFaceList.empty())//no face pointing to this media + { + stopPlaying() ; + return ; + } + + for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter) + { + switchTexture(*iter) ; + } + } + else //stop playing this media + { + if(mFaceList.empty()) + { + return ; + } + + ll_face_list_t::iterator cur ; + for(ll_face_list_t::iterator iter = mFaceList.begin(); iter!= mFaceList.end(); ) + { + cur = iter++ ; + switchTexture(*cur) ; //cur could be removed in this function. + } + } + return ; +} + +//virtual +F32 LLViewerMediaTexture::getMaxVirtualSize() +{ + if(LLFrameTimer::getFrameCount() == mUpdateVirtualSizeTime) + { + return mMaxVirtualSize ; + } + mUpdateVirtualSizeTime = LLFrameTimer::getFrameCount() ; + + if(mNeedsResetMaxVirtualSize) + { + mMaxVirtualSize = 0.f ;//reset + mNeedsResetMaxVirtualSize = FALSE ; + } + + if(mIsPlaying) //media is playing + { + if(mFaceList.size() > 0) + { + for(std::list::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter) + { + LLFace* facep = *iter ; + if(facep->getDrawable()->isRecentlyVisible()) + { + addTextureStats(facep->getVirtualSize()) ; + } + } + } + } + else //media is not in playing + { + findFaces() ; + + if(!mMediaFaceList.empty()) + { + for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter) + { + LLFace* facep = *iter ; + if(facep->getDrawable()->isRecentlyVisible()) + { + addTextureStats(facep->getVirtualSize()) ; + } + } + } + } + + mNeedsResetMaxVirtualSize = TRUE ; + + return mMaxVirtualSize ; } //---------------------------------------------------------------------------------------------- //end of LLViewerMediaTexture diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 0be1bf81de..596bfea670 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -49,6 +49,7 @@ class LLFace; class LLImageGL ; +class LLViewerObject; class LLViewerTexture; class LLViewerFetchedTexture ; class LLViewerMediaTexture ; @@ -58,7 +59,9 @@ typedef void (*loaded_callback_func)( BOOL success, LLViewerFetchedTexture *src_ class LLVFile; class LLMessageSystem; - +class LLViewerMediaImpl ; +class LLVOVolume ; + class LLLoadedCallbackEntry { public: @@ -123,6 +126,8 @@ public: BOOST_MAX_LEVEL }; + typedef std::list ll_face_list_t ; + protected: virtual ~LLViewerTexture(); LOG_CLASS(LLViewerTexture); @@ -152,16 +157,17 @@ public: //maxVirtualSize of the texture void addTextureStats(F32 virtual_size) const ; void resetTextureStats(BOOL zero = FALSE); - F32 getMaxVirtualSize()const {return mMaxVirtualSize ;} + virtual F32 getMaxVirtualSize() ; LLFrameTimer* getLastReferencedTimer() {return &mLastReferencedTimer ;} S32 getFullWidth() const { return mFullWidth; } S32 getFullHeight() const { return mFullHeight; } - void addFace(LLFace* facep) ; - void removeFace(LLFace* facep) ; - + virtual void addFace(LLFace* facep) ; + virtual void removeFace(LLFace* facep) ; + const ll_face_list_t* getFaceList() const {return &mFaceList ;} + void generateGLTexture() ; void destroyGLTexture() ; @@ -206,8 +212,6 @@ public: //end of functions to access LLImageGL //--------------------------------------------------------------------------------------------- - void switchToTexture(LLViewerTexture* new_texture) ; //make all faces pointing to this texture to point to new_texture. - //----------------- /*virtual*/ void setActive() ; void forceActive() ; @@ -233,10 +237,9 @@ protected: BOOL mUseMipMaps ; S8 mComponents; mutable F32 mMaxVirtualSize; // The largest virtual size of the image, in pixels - how much data to we need? - + mutable BOOL mNeedsResetMaxVirtualSize ; LLFrameTimer mLastReferencedTimer; - typedef std::list ll_face_list_t ; ll_face_list_t mFaceList ; //reverse pointer pointing to the faces using this image as texture //GL texture @@ -498,34 +501,61 @@ private: class LLViewerMediaTexture : public LLViewerTexture { protected: - /*virtual*/ ~LLViewerMediaTexture() {} + /*virtual*/ ~LLViewerMediaTexture() ; public: LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ; /*virtual*/ S8 getType() const; - void reinit(BOOL usemipmaps = TRUE); BOOL getUseMipMaps() {return mUseMipMaps ; } - void setUseMipMaps(BOOL mipmap) ; + void setUseMipMaps(BOOL mipmap) ; + + void setPlaying(BOOL playing) ; + BOOL isPlaying() const {return mIsPlaying;} + void setMediaImpl() ; - void setOldTexture(LLViewerTexture* tex) ; - LLViewerTexture* getOldTexture() const ; + void initVirtualSize() ; + void invalidateMediaImpl() ; - void setPlaying(BOOL playing) {mIsPlaying = playing ;} - BOOL isPlaying() const {return mIsPlaying;} + void addMediaToFace(LLFace* facep) ; + void removeMediaFromFace(LLFace* facep) ; + + /*virtual*/ void addFace(LLFace* facep) ; + /*virtual*/ void removeFace(LLFace* facep) ; + + /*virtual*/ F32 getMaxVirtualSize() ; +private: + void switchTexture(LLFace* facep) ; + BOOL findFaces() ; + void stopPlaying() ; private: - LLPointer mOldTexturep ; //the texture this media texture replaces. + // + //an instant list, recording all faces referencing or can reference to this media texture. + //NOTE: it is NOT thread safe. + // + std::list< LLFace* > mMediaFaceList ; + + //an instant list keeping all textures which are replaced by the current media texture, + //is only used to avoid the removal of those textures from memory. + std::list< LLPointer > mTextureList ; + + LLViewerMediaImpl* mMediaImplp ; BOOL mIsPlaying ; + U32 mUpdateVirtualSizeTime ; public: static void updateClass() ; + static void cleanup() ; -public: + static LLViewerMediaTexture* findMediaTexture(const LLUUID& media_id) ; + static void removeMediaImplFromTexture(const LLUUID& media_id) ; + +private: typedef std::map< LLUUID, LLPointer > media_map_t ; - static media_map_t sMediaMap ; + static media_map_t sMediaMap ; }; //just an interface class, do not create instance from this class. diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 93cb0f0f45..e69779b2dc 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -46,6 +46,8 @@ #include "llvolumemessage.h" #include "material_codes.h" #include "message.h" +#include "llmediadataresponder.h" +#include "llpluginclassmedia.h" // for code in the mediaEvent handler #include "object_flags.h" #include "llagentconstants.h" #include "lldrawable.h" @@ -65,6 +67,10 @@ #include "llworld.h" #include "llselectmgr.h" #include "pipeline.h" +#include "llsdutil.h" +#include "llmediaentry.h" +#include "llmediadatafetcher.h" +#include "llagent.h" const S32 MIN_QUIET_FRAMES_COALESCE = 30; const F32 FORCE_SIMPLE_RENDER_AREA = 512.f; @@ -100,6 +106,8 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re mLODChanged = FALSE; mSculptChanged = FALSE; mSpotLightPriority = 0.f; + + mMediaImplList.resize(getNumTEs()); } LLVOVolume::~LLVOVolume() @@ -108,14 +116,31 @@ LLVOVolume::~LLVOVolume() mTextureAnimp = NULL; delete mVolumeImpl; mVolumeImpl = NULL; + + if(!mMediaImplList.empty()) + { + for(U32 i = 0 ; i < mMediaImplList.size() ; i++) + { + if(mMediaImplList[i].notNull()) + { + mMediaImplList[i]->removeObject(this) ; + } + } + } } // static void LLVOVolume::initClass() { + LLMediaDataFetcher::initClass(); } +// static +void LLVOVolume::cleanupClass() +{ + LLMediaDataFetcher::cleanupClass(); +} U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, @@ -123,6 +148,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, LLDataPacker *dp) { LLColor4U color; + const S32 teDirtyBits = (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR|TEM_CHANGE_MEDIA); // Do base class updates... U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp); @@ -190,10 +216,15 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, // // Unpack texture entry data // - if (unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num) & (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR)) + S32 result = unpackTEMessage(mesgsys, _PREHASH_ObjectData, block_num); + if (result & teDirtyBits) { updateTEData(); } + if (result & TEM_CHANGE_MEDIA) + { + retval |= MEDIA_FLAGS_CHANGED; + } } else { @@ -226,9 +257,16 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, // llerrs << "Bogus TE data in " << getID() << ", crashing!" << llendl; llwarns << "Bogus TE data in " << getID() << llendl; } - else if (res2 & (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR)) + else { - updateTEData(); + if (res2 & teDirtyBits) + { + updateTEData(); + } + if (res2 & TEM_CHANGE_MEDIA) + { + retval |= MEDIA_FLAGS_CHANGED; + } } U32 value = dp->getPassFlags(); @@ -266,14 +304,29 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, U8 tdpbuffer[1024]; LLDataPackerBinaryBuffer tdp(tdpbuffer, 1024); mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextureEntry, tdpbuffer, 0, block_num); - if ( unpackTEMessage(tdp) & (TEM_CHANGE_TEXTURE|TEM_CHANGE_COLOR)) + S32 result = unpackTEMessage(tdp); + if (result & teDirtyBits) { updateTEData(); } + if (result & TEM_CHANGE_MEDIA) + { + retval |= MEDIA_FLAGS_CHANGED; + } } } } - + if (retval & (MEDIA_URL_REMOVED | MEDIA_URL_ADDED | MEDIA_URL_UPDATED | MEDIA_FLAGS_CHANGED)) { + // If the media changed at all, request new media data + if(mMedia) + { + llinfos << "Media URL: " << mMedia->mMediaURL << llendl; + } + requestMediaDataUpdate(); + } + // ...and clean up any media impls + cleanUpMediaImpls(); + return retval; } @@ -1327,6 +1380,46 @@ BOOL LLVOVolume::isRootEdit() const return TRUE; } +//virtual +void LLVOVolume::setNumTEs(const U8 num_tes) +{ + const U8 old_num_tes = getNumTEs() ; + + if(old_num_tes && old_num_tes < num_tes) //new faces added + { + LLViewerObject::setNumTEs(num_tes) ; + + if(mMediaImplList.size() >= old_num_tes && mMediaImplList[old_num_tes -1].notNull())//duplicate the last media textures if exists. + { + mMediaImplList.resize(num_tes) ; + const LLTextureEntry* te = getTE(old_num_tes - 1) ; + for(U8 i = old_num_tes; i < num_tes ; i++) + { + setTE(i, *te) ; + mMediaImplList[i] = mMediaImplList[old_num_tes -1] ; + } + mMediaImplList[old_num_tes -1]->setUpdated(TRUE) ; + } + } + else if(old_num_tes > num_tes && mMediaImplList.size() > num_tes) //old faces removed + { + U8 end = mMediaImplList.size() ; + for(U8 i = num_tes; i < end ; i++) + { + removeMediaImpl(i) ; + } + mMediaImplList.resize(num_tes) ; + + LLViewerObject::setNumTEs(num_tes) ; + } + else + { + LLViewerObject::setNumTEs(num_tes) ; + } + + return ; +} + void LLVOVolume::setTEImage(const U8 te, LLViewerTexture *imagep) { BOOL changed = (mTEImages[te] != imagep); @@ -1510,6 +1603,321 @@ void LLVOVolume::updateTEData() }*/ } +bool LLVOVolume::hasMedia() const +{ + bool result = false; + const U8 numTEs = getNumTEs(); + for (U8 i = 0; i < numTEs; i++) + { + const LLTextureEntry* te = getTE(i); + if(te->hasMedia()) + { + result = true; + break; + } + } + return result; +} + +void LLVOVolume::requestMediaDataUpdate() +{ + LLMediaDataFetcher::fetchMedia(this); +} + +void LLVOVolume::cleanUpMediaImpls() +{ + // Iterate through our TEs and remove any Impls that are no longer used + const U8 numTEs = getNumTEs(); + for (U8 i = 0; i < numTEs; i++) + { + const LLTextureEntry* te = getTE(i); + if( ! te->hasMedia()) + { + // Delete the media IMPL! + removeMediaImpl(i) ; + } + } +} + +void LLVOVolume::updateObjectMediaData(const LLSD &media_data_array) +{ + // media_data_array is an array of media entry maps + + //llinfos << "updating:" << this->getID() << " " << ll_pretty_print_sd(media_data_array) << llendl; + + LLSD::array_const_iterator iter = media_data_array.beginArray(); + LLSD::array_const_iterator end = media_data_array.endArray(); + U8 texture_index = 0; + for (; iter != end; ++iter, ++texture_index) + { + syncMediaData(texture_index, *iter, false/*merge*/, false/*ignore_agent*/); + } +} + +void LLVOVolume::syncMediaData(S32 texture_index, const LLSD &media_data, bool merge, bool ignore_agent) +{ + LLTextureEntry *te = getTE(texture_index); + //llinfos << "BEFORE: texture_index = " << texture_index + // << " hasMedia = " << te->hasMedia() << " : " + // << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << llendl; + + std::string previous_url; + LLMediaEntry* mep = te->getMediaData(); + if(mep) + { + // Save the "current url" from before the update so we can tell if + // it changes. + previous_url = mep->getCurrentURL(); + } + + if (merge) + { + te->mergeIntoMediaData(media_data); + } + else { + // XXX Question: what if the media data is undefined LLSD, but the + // update we got above said that we have media flags?? Here we clobber + // that, assuming the data from the service is more up-to-date. + te->updateMediaData(media_data); + } + + mep = te->getMediaData(); + if(mep) + { + bool update_from_self = false; + if (!ignore_agent) + { + LLUUID updating_agent = LLTextureEntry::getAgentIDFromMediaVersionString(getMediaURL()); + update_from_self = (updating_agent == gAgent.getID()); + } + viewer_media_t media_impl = LLViewerMedia::updateMediaImpl(mep, previous_url, update_from_self); + + addMediaImpl(media_impl, texture_index) ; + } + + //llinfos << "AFTER: texture_index = " << texture_index + // << " hasMedia = " << te->hasMedia() << " : " + // << ((NULL == te->getMediaData()) ? "NULL MEDIA DATA" : ll_pretty_print_sd(te->getMediaData()->asLLSD())) << llendl; +} + +void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event) +{ + switch(event) + { + + case LLViewerMediaObserver::MEDIA_EVENT_LOCATION_CHANGED: + { + switch(impl->getNavState()) + { + case LLViewerMediaImpl::MEDIANAVSTATE_FIRST_LOCATION_CHANGED: + { + // This is the first location changed event after the start of a non-server-directed nav. It may need to be broadcast. + + bool block_navigation = false; + // FIXME: if/when we allow the same media impl to be used by multiple faces, the logic here will need to be fixed + // to deal with multiple face indices. + int face_index = getFaceIndexWithMediaImpl(impl, -1); + std::string new_location = plugin->getLocation(); + + // Find the media entry for this navigate + LLMediaEntry* mep = NULL; + LLTextureEntry *te = getTE(face_index); + if(te) + { + mep = te->getMediaData(); + } + + if(mep) + { + if(!mep->checkCandidateUrl(new_location)) + { + block_navigation = true; + } + } + else + { + llwarns << "Couldn't find media entry!" << llendl; + } + + if(block_navigation) + { + llinfos << "blocking navigate to URI " << new_location << llendl; + + // "bounce back" to the current URL from the media entry + // NOTE: the only way block_navigation can be true is if we found the media entry, so we're guaranteed here that mep is not NULL. + impl->navigateTo(mep->getCurrentURL()); + } + else + { + + llinfos << "broadcasting navigate with URI " << new_location << llendl; + + // Post the navigate to the cap + std::string cap = getRegion()->getCapability("ObjectMediaNavigate"); + if(cap.empty()) + { + // XXX *TODO: deal with no cap! It may happen! (retry?) + LL_WARNS("Media") << "Can't broadcast navigate event -- ObjectMediaNavigate cap is not available" << LL_ENDL; + return; + } + + // If we got here, the cap is available. Index through all faces that have this media and send the navigate message. + LLSD sd; + sd["object_id"] = mID; + sd["current_url"] = new_location; + sd["texture_index"] = face_index; + LLHTTPClient::post(cap, sd, new LLMediaDataResponder("ObjectMediaNavigate", sd, this)); + } + } + break; + + case LLViewerMediaImpl::MEDIANAVSTATE_SERVER_FIRST_LOCATION_CHANGED: + // This is the first location changed event after the start of a server-directed nav. Don't broadcast it. + llinfos << " NOT broadcasting navigate (server-directed)" << llendl; + break; + + default: + // This is a subsequent location-changed due to a redirect. Don't broadcast. + llinfos << " NOT broadcasting navigate (redirect)" << llendl; + break; + } + } + break; + + default: + break; + } + +} + +void LLVOVolume::sendMediaDataUpdate() const +{ + std::string url = getRegion()->getCapability("ObjectMedia"); + if (!url.empty()) + { + LLSD sd_payload; + sd_payload["verb"] = "UPDATE"; + sd_payload[LLTextureEntry::OBJECT_ID_KEY] = mID; + LLSD object_media_data; + for (int i=0; i < getNumTEs(); i++) { + LLTextureEntry *texture_entry = getTE(i); + llassert((texture_entry->getMediaData() != NULL) == texture_entry->hasMedia()); + const LLSD &media_data = + (texture_entry->getMediaData() == NULL) ? LLSD() : texture_entry->getMediaData()->asLLSD(); + object_media_data.append(media_data); + } + sd_payload[LLTextureEntry::OBJECT_MEDIA_DATA_KEY] = object_media_data; + + llinfos << "Sending media data: " << getID() << " " << ll_pretty_print_sd(sd_payload) << llendl; + + LLHTTPClient::post(url, sd_payload, new LLMediaDataResponder("ObjectMedia", sd_payload, this)); + } + // XXX *TODO: deal with no cap! It may happen! (retry?) +} + +void LLVOVolume::removeMediaImpl(S32 texture_index) +{ + if(mMediaImplList.size() <= (U32)texture_index || mMediaImplList[texture_index].isNull()) + { + return ; + } + + //make the face referencing to mMediaImplList[texture_index] to point back to the old texture. + if(mDrawable) + { + LLFace* facep = mDrawable->getFace(texture_index) ; + if(facep) + { + LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ; + if(media_tex) + { + media_tex->removeMediaFromFace(facep) ; + } + } + } + + //check if some other face(s) of this object reference(s)to this media impl. + S32 i ; + S32 end = (S32)mMediaImplList.size() ; + for(i = 0; i < end ; i++) + { + if( i != texture_index && mMediaImplList[i] == mMediaImplList[texture_index]) + { + break ; + } + } + + if(i == end) //this object does not need this media impl. + { + mMediaImplList[texture_index]->removeObject(this) ; + } + + mMediaImplList[texture_index] = NULL ; + return ; +} + +void LLVOVolume::addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) +{ + if((S32)mMediaImplList.size() < texture_index + 1) + { + mMediaImplList.resize(texture_index + 1) ; + } + + if(mMediaImplList[texture_index].notNull()) + { + if(mMediaImplList[texture_index] == media_impl) + { + return ; + } + + removeMediaImpl(texture_index) ; + } + + mMediaImplList[texture_index] = media_impl; + media_impl->addObject(this) ; + + //add the face to show the media if it is in playing + if(mDrawable) + { + LLFace* facep = mDrawable->getFace(texture_index) ; + if(facep) + { + LLViewerMediaTexture* media_tex = LLViewerTextureManager::findMediaTexture(mMediaImplList[texture_index]->getMediaTextureID()) ; + if(media_tex) + { + media_tex->addMediaToFace(facep) ; + } + } + else //the face is not available now, start media on this face later. + { + media_impl->setUpdated(TRUE) ; + } + } + return ; +} + +viewer_media_t LLVOVolume::getMediaImpl(U8 face_id) const +{ + if(mMediaImplList.size() > face_id) + { + return mMediaImplList[face_id]; + } + return NULL; +} + +S32 LLVOVolume::getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id) +{ + S32 end = (S32)mMediaImplList.size() ; + for(S32 face_id = start_face_id + 1; face_id < end; face_id++) + { + if(mMediaImplList[face_id] == media_impl) + { + return face_id ; + } + } + return -1 ; +} + //---------------------------------------------------------------------------- void LLVOVolume::setLightTextureID(LLUUID id) diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 1b90219836..9a79b620d5 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -35,6 +35,7 @@ #include "llviewerobject.h" #include "llviewertexture.h" +#include "llviewermedia.h" #include "llframetimer.h" #include "llapr.h" #include "m3math.h" // LLMatrix3 @@ -45,6 +46,8 @@ class LLViewerTextureAnim; class LLDrawPool; class LLSelectNode; +typedef std::vector media_list_t; + enum LLVolumeInterfaceType { INTERFACE_FLEXIBLE = 1, @@ -75,12 +78,14 @@ public: // Class which embodies all Volume objects (with pcode LL_PCODE_VOLUME) class LLVOVolume : public LLViewerObject { + LOG_CLASS(LLVOVolume); protected: virtual ~LLVOVolume(); public: static void initClass(); - static void preUpdateGeom(); + static void cleanupClass(); + static void preUpdateGeom(); enum { @@ -153,6 +158,7 @@ public: /*virtual*/ void setScale(const LLVector3 &scale, BOOL damped); + /*virtual*/ void setNumTEs(const U8 num_tes); /*virtual*/ void setTEImage(const U8 te, LLViewerTexture *imagep); /*virtual*/ S32 setTETexture(const U8 te, const LLUUID &uuid); /*virtual*/ S32 setTEColor(const U8 te, const LLColor3 &color); @@ -224,13 +230,31 @@ public: BOOL isVolumeGlobal() const; BOOL canBeFlexible() const; BOOL setIsFlexible(BOOL is_flexible); - + + void updateObjectMediaData(const LLSD &media_data_duples); + void mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event); + + // Sync the given media data with the impl and the given te + void syncMediaData(S32 te, const LLSD &media_data, bool merge, bool ignore_agent); + + // Send media data update to the simulator. + void sendMediaDataUpdate() const; + + viewer_media_t getMediaImpl(U8 face_id) const; + S32 getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id); + + bool hasMedia() const; + protected: S32 computeLODDetail(F32 distance, F32 radius); BOOL calcLOD(); LLFace* addFace(S32 face_index); void updateTEData(); + void requestMediaDataUpdate(); + void cleanUpMediaImpls(); + void addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) ; + void removeMediaImpl(S32 texture_index) ; public: LLViewerTextureAnim *mTextureAnimp; U8 mTexAnimMode; @@ -251,6 +275,7 @@ private: LLVolumeInterface *mVolumeImpl; LLPointer mSculptTexture; LLPointer mLightTexture; + media_list_t mMediaImplList; // statics public: diff --git a/indra/newview/skins/default/xui/en/floater_media_settings.xml b/indra/newview/skins/default/xui/en/floater_media_settings.xml new file mode 100644 index 0000000000..6ba26f938d --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_media_settings.xml @@ -0,0 +1,20 @@ + + + + + width="134"> + + + + + name="checkbox edit linked parts" > + + + + height="22" > + + Transparency % @@ -2261,7 +2306,7 @@ layout="topleft" left_delta="0" name="glow label" - top_pad="4" + top_pad="2" width="80"> Glow @@ -2281,7 +2326,7 @@ layout="topleft" left_delta="0" name="checkbox fullbright" - top_pad="7" + top_pad="4" width="81" /> Mapping @@ -2439,6 +2484,40 @@ name="weave" value="weave" /> + Repeats per Face @@ -2461,7 +2540,7 @@ left="20" max_val="100" name="TexScaleU" - top_pad="10" + top_pad="6" width="160" /> - - Rotation (degrees) - + - - Repeats Per Meter - + top_delta="25" + width="170" /> + + top_delta="20" + width="170" /> + + - + + + + + Enter a URL or URL pattern to add to the list of allowed domains + + + + + + + + + + Preview + + + + Controls: + + + + Standard + + + Mini + + + + + + + + + + + + + + Note: Parcel Owners & Residents can override this setting + + + + + Size: + + + + X + + + + diff --git a/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml b/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml new file mode 100644 index 0000000000..f11364874a --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml @@ -0,0 +1,49 @@ + + + + + Owner + + + + + + + Group + + + + + + + + Anyone + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_media_settings_security.xml b/indra/newview/skins/default/xui/en/panel_media_settings_security.xml new file mode 100644 index 0000000000..695e956e41 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_media_settings_security.xml @@ -0,0 +1,56 @@ + + + + + + + diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 311bf0503a..13b1ec7308 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -1728,13 +1728,25 @@ Releases the specified URL, it will no longer be usable llHTTPResponse(key request_id, integer status, string body) Responds to request_id with status and body - + string llGetHTTPHeader(key request_id, string header) Returns the value for header for request_id - - + +llSetPrimMediaParams(integer face, list params) +Set the media params for a particular face on an object. List is a set of name/value pairs (in no particular order). The possible names are below, along with the types of values and what they mean. If media is not already on this object, add it. Params not specified are unchanged, or if new media is added set to the default specified. + + +list llGetPrimMediaParams(integer face, list params) +Get the media params for a particular face on an object, given the desired list of names. Returns a list of values in the order requested. Returns an empty list if no media exists on the face. + + +llClearPrimMedia(integer face) +Clears (deletes) the media and all params from the given face. + + + Set Not Away Set Away Set Not Busy diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index aa6a144247..036fa4923f 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -169,6 +169,12 @@ class WindowsManifest(ViewerManifest): # the final exe is complicated because we're not sure where it's coming from, # nor do we have a fixed name for the executable self.path(self.find_existing_file('debug/secondlife-bin.exe', 'release/secondlife-bin.exe', 'relwithdebinfo/secondlife-bin.exe'), dst=self.final_exe()) + + # Plugin host application + self.path(os.path.join(os.pardir, + 'llplugin', 'slplugin', self.args['configuration'], "slplugin.exe"), + "slplugin.exe") + # need to get the kdu dll from any of the build directories as well try: self.path(self.find_existing_file('../llkdu/%s/llkdu.dll' % self.args['configuration'], @@ -193,11 +199,6 @@ class WindowsManifest(ViewerManifest): self.path("openjpeg.dll") self.end_prefix() - # Plugin host application - if self.prefix(src='../llplugin/slplugin/%s' % self.args['configuration'], dst="llplugin"): - self.path("slplugin.exe") - self.end_prefix() - # Media plugins - QuickTime if self.prefix(src='../media_plugins/quicktime/%s' % self.args['configuration'], dst="llplugin"): self.path("media_plugin_quicktime.dll") @@ -487,9 +488,11 @@ class DarwinManifest(ViewerManifest): self.path("../mac_crash_logger/" + self.args['configuration'] + "/mac-crash-logger.app", "mac-crash-logger.app") self.path("../mac_updater/" + self.args['configuration'] + "/mac-updater.app", "mac-updater.app") + # plugin launcher + self.path("../llplugin/slplugin/" + self.args['configuration'] + "/SLPlugin", "SLPlugin") + # plugins if self.prefix(src="", dst="llplugin"): - self.path("../llplugin/slplugin/" + self.args['configuration'] + "/SLPlugin", "SLPlugin") self.path("../media_plugins/quicktime/" + self.args['configuration'] + "/media_plugin_quicktime.dylib", "media_plugin_quicktime.dylib") self.path("../media_plugins/webkit/" + self.args['configuration'] + "/media_plugin_webkit.dylib", "media_plugin_webkit.dylib") self.path("../../libraries/universal-darwin/lib_release/libllqtwebkit.dylib", "libllqtwebkit.dylib") @@ -680,6 +683,7 @@ class Linux_i686Manifest(LinuxManifest): self.path("secondlife-stripped","bin/do-not-directly-run-secondlife-bin") self.path("../linux_crash_logger/linux-crash-logger-stripped","bin/linux-crash-logger.bin") self.path("../linux_updater/linux-updater-stripped", "bin/linux-updater.bin") + self.path("../llplugin/slplugin/SLPlugin", "bin/SLPlugin") if self.prefix("res-sdl"): self.path("*") # recurse @@ -687,7 +691,6 @@ class Linux_i686Manifest(LinuxManifest): # plugins if self.prefix(src="", dst="bin/llplugin"): - self.path("../llplugin/slplugin/SLPlugin", "SLPlugin") self.path("../media_plugins/webkit/libmedia_plugin_webkit.so", "libmedia_plugin_webkit.so") self.path("../media_plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_quicktime.so") self.end_prefix("bin/llplugin") -- cgit v1.2.3 From a0a5c8e615869d449bfad94ec9a650aad82cab91 Mon Sep 17 00:00:00 2001 From: Martin Reddy Date: Thu, 1 Oct 2009 09:52:05 +0000 Subject: EXT-1251: strip leading/trailing whitespace from user input in the navigation bar when trying to access if the input is a valid SLURL. --- indra/newview/lllocationinputctrl.cpp | 5 +++-- indra/newview/llnavigationbar.cpp | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index a6c2435e1e..68dc3854db 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -656,8 +656,9 @@ void LLLocationInputCtrl::changeLocationPresentation() { //change location presentation only if user does not select anything and //human-readable region name is being displayed - if(mTextEntry && !mTextEntry->hasSelection() && - !LLSLURL::isSLURL(mTextEntry->getText())) + std::string text = mTextEntry->getText(); + LLStringUtil::trim(text); + if(mTextEntry && !mTextEntry->hasSelection() && !LLSLURL::isSLURL(text)) { //needs unescaped one mTextEntry->setText(LLAgentUI::buildSLURL(false)); diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp index b1db51dd26..19fee20740 100644 --- a/indra/newview/llnavigationbar.cpp +++ b/indra/newview/llnavigationbar.cpp @@ -317,6 +317,7 @@ void LLNavigationBar::onTeleportHistoryMenuItemClicked(const LLSD& userdata) void LLNavigationBar::onLocationSelection() { std::string typed_location = mCmbLocation->getSimple(); + LLStringUtil::trim(typed_location); // Will not teleport to empty location. if (typed_location.empty()) -- cgit v1.2.3 From 090977608d3d4e1d6d26689064910221c66f6084 Mon Sep 17 00:00:00 2001 From: Martin Reddy Date: Thu, 1 Oct 2009 10:23:23 +0000 Subject: DEV-39995: the help browser would crash on open if the media ctrl returned no media plugin for text/html (NULL dereference), which seems to be happening in viewer-2.0.0-3 for me at the moment. Clearly there's not too much to do if we can't display HTML, but this fix will at least stop the help browser from crashing. --- indra/newview/llfloaterhelpbrowser.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llfloaterhelpbrowser.cpp b/indra/newview/llfloaterhelpbrowser.cpp index d67b26d36c..6b0b5ed5e0 100644 --- a/indra/newview/llfloaterhelpbrowser.cpp +++ b/indra/newview/llfloaterhelpbrowser.cpp @@ -72,7 +72,11 @@ void LLFloaterHelpBrowser::buildURLHistory() LLSD browser_history = LLURLHistory::getURLHistory("browser"); // initialize URL history in the plugin - mBrowser->getMediaPlugin()->initializeUrlHistory(browser_history); + LLPluginClassMedia *plugin = mBrowser->getMediaPlugin(); + if (plugin) + { + plugin->initializeUrlHistory(browser_history); + } } void LLFloaterHelpBrowser::onClose() -- cgit v1.2.3 From f05df68656d2abdc38d86cd6746398fa90eb8614 Mon Sep 17 00:00:00 2001 From: Steven Bennetts Date: Thu, 1 Oct 2009 17:44:44 +0000 Subject: merge https://svn.aws.productengine.com/secondlife/export-from-ll/viewer-2-0@1868 https://svn.aws.productengine.com/secondlife/pe/stable-2@1876 -> viewer-2.0.0-3 * Bugs: EXT-1111 EXT-915 EXT-1131 EXT-1200 EXT-1202 EXT-1201 EXT-1205 EXT-1212 EXT-1173 EXT-1229 EXT-1218 EXT-1164 EXT-996 EXT-821 EXT-1030 EXT-1031 EXT-816 * Major Bugs: EXT-1142 (timeout during login due to processing group IMs) * Changes: EXT-1216 (minimize message well) --- indra/newview/llavatarlist.cpp | 136 ++++--- indra/newview/llavatarlist.h | 25 +- indra/newview/llbottomtray.cpp | 5 +- indra/newview/llchannelmanager.cpp | 54 ++- indra/newview/llchannelmanager.h | 16 +- indra/newview/llchatitemscontainerctrl.cpp | 392 ++++----------------- indra/newview/llchatitemscontainerctrl.h | 86 +---- indra/newview/llchatmsgbox.cpp | 2 +- indra/newview/llchiclet.cpp | 31 +- indra/newview/llchiclet.h | 3 +- indra/newview/llfavoritesbar.cpp | 11 + indra/newview/llfavoritesbar.h | 2 +- indra/newview/llfloaterchatterbox.cpp | 3 +- indra/newview/llgrouplist.cpp | 49 ++- indra/newview/llgrouplist.h | 24 +- indra/newview/llimfloater.cpp | 73 ++-- indra/newview/llimfloater.h | 6 +- indra/newview/llimhandler.cpp | 4 +- indra/newview/llimpanel.cpp | 87 +---- indra/newview/llimpanel.h | 7 +- indra/newview/llimview.cpp | 246 ++++++++++--- indra/newview/llimview.h | 67 +++- indra/newview/llnearbychat.cpp | 29 +- indra/newview/llnearbychat.h | 6 +- indra/newview/llnearbychathandler.cpp | 242 +++++++++++-- indra/newview/llnotificationalerthandler.cpp | 13 +- indra/newview/llnotificationgrouphandler.cpp | 5 +- indra/newview/llnotificationhandler.h | 4 +- indra/newview/llnotificationscripthandler.cpp | 11 +- indra/newview/llnotificationtiphandler.cpp | 5 +- indra/newview/llpanelavatar.cpp | 2 +- indra/newview/llpanelgroup.cpp | 15 +- indra/newview/llpanelgroupgeneral.cpp | 2 + indra/newview/llpanelpeople.cpp | 285 ++++----------- indra/newview/llpanelpeople.h | 27 +- indra/newview/llpanelpick.cpp | 47 ++- indra/newview/llpanelpick.h | 5 + indra/newview/llpanelpicks.cpp | 7 +- indra/newview/llpanelpicks.h | 2 +- indra/newview/llpanelplaces.cpp | 10 +- indra/newview/llpanelteleporthistory.cpp | 8 +- indra/newview/llscreenchannel.cpp | 74 ++-- indra/newview/llscreenchannel.h | 139 +++++--- indra/newview/llsidetray.cpp | 10 +- indra/newview/llstatusbar.cpp | 17 +- indra/newview/llstatusbar.h | 4 +- indra/newview/llsyswellwindow.cpp | 43 ++- indra/newview/llsyswellwindow.h | 6 +- indra/newview/lltoast.cpp | 19 +- indra/newview/lltoast.h | 3 + indra/newview/lltoastpanel.h | 6 + indra/newview/llviewermenu.cpp | 13 + indra/newview/llviewermenu.h | 1 + indra/newview/llviewerwindow.cpp | 6 +- .../skins/default/xui/en/floater_sys_well.xml | 12 +- indra/newview/skins/default/xui/en/menu_viewer.xml | 4 +- .../skins/default/xui/en/panel_bottomtray.xml | 3 - .../default/xui/en/panel_group_info_sidetray.xml | 3 +- .../skins/default/xui/en/panel_nearby_chat_bar.xml | 2 + indra/newview/skins/default/xui/en/panel_notes.xml | 4 +- indra/newview/skins/default/xui/en/panel_picks.xml | 4 +- .../newview/skins/default/xui/en/panel_profile.xml | 6 +- .../skins/default/xui/en/panel_profile_view.xml | 4 +- .../default/xui/en/panel_teleport_history.xml | 2 +- .../skins/default/xui/en/widgets/scroll_list.xml | 6 +- .../default/xui/en/widgets/search_combo_box.xml | 5 +- 66 files changed, 1358 insertions(+), 1092 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index ee14a2ff86..36f9780ad0 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -41,6 +41,10 @@ static LLDefaultChildRegistry::Register r("avatar_list"); +// Maximum number of avatars that can be added to a list in one pass. +// Used to limit time spent for avatar list update per frame. +static const unsigned ADD_LIMIT = 50; + static bool findInsensitive(std::string haystack, const std::string& needle_upper) { LLStringUtil::toUpper(haystack); @@ -65,6 +69,7 @@ LLAvatarList::LLAvatarList(const Params& p) : LLFlatListView(p) , mOnlineGoFirst(p.online_go_first) , mContextMenu(NULL) +, mDirty(true) // to force initial update { setCommitOnSelectionChange(true); @@ -72,44 +77,40 @@ LLAvatarList::LLAvatarList(const Params& p) setComparator(&NAME_COMPARATOR); } -void LLAvatarList::computeDifference( - const std::vector& vnew_unsorted, - std::vector& vadded, - std::vector& vremoved) +// virtual +void LLAvatarList::draw() { - std::vector vcur; - std::vector vnew = vnew_unsorted; + if (mDirty) + refresh(); - // Convert LLSDs to LLUUIDs. - { - std::vector vcur_values; - getValues(vcur_values); + LLFlatListView::draw(); +} - for (size_t i=0; i::iterator it; - size_t maxsize = llmax(vcur.size(), vnew.size()); - vadded.resize(maxsize); - vremoved.resize(maxsize); - - // what to remove - it = set_difference(vcur.begin(), vcur.end(), vnew.begin(), vnew.end(), vremoved.begin()); - vremoved.erase(it, vremoved.end()); - - // what to add - it = set_difference(vnew.begin(), vnew.end(), vcur.begin(), vcur.end(), vadded.begin()); - vadded.erase(it, vadded.end()); +void LLAvatarList::sortByName() +{ + setComparator(&NAME_COMPARATOR); + sort(); } -BOOL LLAvatarList::update(const std::vector& all_buddies, const std::string& name_filter) +////////////////////////////////////////////////////////////////////////// +// PROTECTED SECTION +////////////////////////////////////////////////////////////////////////// + +void LLAvatarList::refresh() { - BOOL have_names = TRUE; - bool have_filter = name_filter != LLStringUtil::null; + bool have_names = TRUE; + bool add_limit_exceeded = false; + bool modified = false; + bool have_filter = !mNameFilter.empty(); // Save selection. std::vector selected_ids; @@ -118,22 +119,36 @@ BOOL LLAvatarList::update(const std::vector& all_buddies, const std::str // Determine what to add and what to remove. std::vector added, removed; - LLAvatarList::computeDifference(all_buddies, added, removed); + LLAvatarList::computeDifference(getIDs(), added, removed); // Handle added items. + unsigned nadded = 0; for (std::vector::const_iterator it=added.begin(); it != added.end(); it++) { std::string name; const LLUUID& buddy_id = *it; - have_names &= gCacheName->getFullName(buddy_id, name); - if (!have_filter || findInsensitive(name, name_filter)) - addNewItem(buddy_id, name, LLAvatarTracker::instance().isBuddyOnline(buddy_id)); + have_names &= (bool)gCacheName->getFullName(buddy_id, name); + if (!have_filter || findInsensitive(name, mNameFilter)) + { + if (nadded >= ADD_LIMIT) + { + add_limit_exceeded = true; + break; + } + else + { + addNewItem(buddy_id, name, LLAvatarTracker::instance().isBuddyOnline(buddy_id)); + modified = true; + nadded++; + } + } } // Handle removed items. for (std::vector::const_iterator it=removed.begin(); it != removed.end(); it++) { removeItemByUUID(*it); + modified = true; } // Handle filter. @@ -146,9 +161,12 @@ BOOL LLAvatarList::update(const std::vector& all_buddies, const std::str { std::string name; const LLUUID& buddy_id = it->asUUID(); - have_names &= gCacheName->getFullName(buddy_id, name); - if (!findInsensitive(name, name_filter)) + have_names &= (bool)gCacheName->getFullName(buddy_id, name); + if (!findInsensitive(name, mNameFilter)) + { removeItemByUUID(buddy_id); + modified = true; + } } } @@ -167,18 +185,15 @@ BOOL LLAvatarList::update(const std::vector& all_buddies, const std::str // // Otherwise, if we have no filter then no need to update again // because the items will update their names. - return !have_filter || have_names; -} + bool dirty = add_limit_exceeded || (have_filter && !have_names); + setDirty(dirty); -void LLAvatarList::sortByName() -{ - setComparator(&NAME_COMPARATOR); - sort(); + // Commit if we've added/removed items. + if (modified) + onCommit(); } -////////////////////////////////////////////////////////////////////////// -// PROTECTED SECTION -////////////////////////////////////////////////////////////////////////// + void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos) { LLAvatarListItem* item = new LLAvatarListItem(); @@ -194,8 +209,39 @@ void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is addItem(item, id, pos); } +void LLAvatarList::computeDifference( + const std::vector& vnew_unsorted, + std::vector& vadded, + std::vector& vremoved) +{ + std::vector vcur; + std::vector vnew = vnew_unsorted; + // Convert LLSDs to LLUUIDs. + { + std::vector vcur_values; + getValues(vcur_values); + for (size_t i=0; i::iterator it; + size_t maxsize = llmax(vcur.size(), vnew.size()); + vadded.resize(maxsize); + vremoved.resize(maxsize); + + // what to remove + it = set_difference(vcur.begin(), vcur.end(), vnew.begin(), vnew.end(), vremoved.begin()); + vremoved.erase(it, vremoved.end()); + + // what to add + it = set_difference(vnew.begin(), vnew.end(), vcur.begin(), vcur.end(), vadded.begin()); + vadded.erase(it, vadded.end()); +} bool LLAvatarItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const { diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h index 8d79e073d2..ec801645fe 100644 --- a/indra/newview/llavatarlist.h +++ b/indra/newview/llavatarlist.h @@ -37,10 +37,22 @@ #include "llavatarlistitem.h" +/** + * Generic list of avatars. + * + * Updates itself when it's dirty, using optional name filter. + * To initiate update, modify the UUID list and call setDirty(). + * + * @see getIDs() + * @see setDirty() + * @see setNameFilter() + */ class LLAvatarList : public LLFlatListView { LOG_CLASS(LLAvatarList); public: + typedef std::vector uuid_vector_t; + struct Params : public LLInitParam::Block { Optional volume_column_width; @@ -51,14 +63,19 @@ public: LLAvatarList(const Params&); virtual ~LLAvatarList() {} - BOOL update(const std::vector& all_buddies, - const std::string& name_filter = LLStringUtil::null); + virtual void draw(); // from LLView + + void setNameFilter(const std::string& filter); + void setDirty(bool val = true) { mDirty = val; } + uuid_vector_t& getIDs() { return mIDs; } void setContextMenu(LLAvatarListItem::ContextMenu* menu) { mContextMenu = menu; } void sortByName(); protected: + void refresh(); + void addNewItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos = ADD_BOTTOM); void computeDifference( const std::vector& vnew, @@ -68,6 +85,10 @@ protected: private: bool mOnlineGoFirst; + bool mDirty; + + std::string mNameFilter; + uuid_vector_t mIDs; LLAvatarListItem::ContextMenu* mContextMenu; }; diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index 46151b469f..8771611b1c 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -133,6 +133,7 @@ LLIMChiclet* LLBottomTray::createIMChiclet(const LLUUID& session_id) case LLIMChiclet::TYPE_IM: return getChicletPanel()->createChiclet(session_id); case LLIMChiclet::TYPE_GROUP: + case LLIMChiclet::TYPE_AD_HOC: return getChicletPanel()->createChiclet(session_id); case LLIMChiclet::TYPE_UNKNOWN: break; @@ -231,7 +232,7 @@ void LLBottomTray::showBottomTrayContextMenu(S32 x, S32 y, MASK mask) mBottomTrayContextMenu->updateParent(LLMenuGL::sMenuContainer); LLMenuGL::showPopup(this, mBottomTrayContextMenu, x, y); - } + } } void LLBottomTray::showGestureButton(BOOL visible) @@ -243,7 +244,7 @@ void LLBottomTray::showGestureButton(BOOL visible) mGestureCombo->setVisible(visible); if (!visible) - { + { LLFloaterReg::hideFloaterInstance("gestures"); r.mRight -= mGestureCombo->getRect().getWidth(); } diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp index 7ae9976338..b4b680416c 100644 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -77,7 +77,7 @@ LLScreenChannel* LLChannelManager::createNotificationChannel() p.channel_align = CA_RIGHT; // Getting a Channel for our notifications - return LLChannelManager::getInstance()->getChannel(p); + return dynamic_cast (LLChannelManager::getInstance()->createChannel(p)); } //-------------------------------------------------------------------------- @@ -113,7 +113,7 @@ void LLChannelManager::onLoginCompleted() LLChannelManager::Params p; p.id = LLUUID(gSavedSettings.getString("StartUpChannelUUID")); p.channel_align = CA_RIGHT; - mStartUpChannel = getChannel(p); + mStartUpChannel = createChannel(p); if(!mStartUpChannel) { @@ -147,22 +147,32 @@ void LLChannelManager::onStartUpToastClose() LLScreenChannel::setStartUpToastShown(); // force NEARBY CHAT CHANNEL to repost all toasts if present - LLScreenChannel* nearby_channel = findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); - nearby_channel->loadStoredToastsToChannel(); - nearby_channel->setCanStoreToasts(false); + //LLScreenChannelBase* nearby_channel = findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); + //!!!!!!!!!!!!!! + //FIXME + //nearby_channel->loadStoredToastsToChannel(); + //nearby_channel->setCanStoreToasts(false); } //-------------------------------------------------------------------------- -LLScreenChannel* LLChannelManager::getChannel(LLChannelManager::Params& p) + +LLScreenChannelBase* LLChannelManager::addChannel(LLScreenChannelBase* channel) { - LLScreenChannel* new_channel = NULL; + if(!channel) + return 0; - new_channel = findChannelByID(p.id); + ChannelElem new_elem; + new_elem.id = channel->getChannelID(); + new_elem.channel = channel; - if(new_channel) - return new_channel; + mChannelList.push_back(new_elem); - new_channel = new LLScreenChannel(p.id); + return channel; +} + +LLScreenChannel* LLChannelManager::createChannel(LLChannelManager::Params& p) +{ + LLScreenChannel* new_channel = new LLScreenChannel(p.id); if(!new_channel) { @@ -172,20 +182,26 @@ LLScreenChannel* LLChannelManager::getChannel(LLChannelManager::Params& p) { new_channel->setToastAlignment(p.toast_align); new_channel->setChannelAlignment(p.channel_align); - new_channel->setDisplayToastsAlways(p.display_toasts_always); - - ChannelElem new_elem; - new_elem.id = p.id; - new_elem.channel = new_channel; + new_channel->setDisplayToastsAlways(p.display_toasts_always); - mChannelList.push_back(new_elem); + addChannel(new_channel); } - return new_channel; } +LLScreenChannelBase* LLChannelManager::getChannel(LLChannelManager::Params& p) +{ + LLScreenChannelBase* new_channel = findChannelByID(p.id); + + if(new_channel) + return new_channel; + + return createChannel(p); + +} + //-------------------------------------------------------------------------- -LLScreenChannel* LLChannelManager::findChannelByID(const LLUUID id) +LLScreenChannelBase* LLChannelManager::findChannelByID(const LLUUID id) { std::vector::iterator it = find(mChannelList.begin(), mChannelList.end(), id); if(it != mChannelList.end()) diff --git a/indra/newview/llchannelmanager.h b/indra/newview/llchannelmanager.h index 811fa06d2b..b927d369cd 100644 --- a/indra/newview/llchannelmanager.h +++ b/indra/newview/llchannelmanager.h @@ -52,8 +52,8 @@ class LLChannelManager : public LLSingleton public: struct Params { - LLUUID id; - bool display_toasts_always; + LLUUID id; + bool display_toasts_always; EToastAlignment toast_align; EChannelAlignment channel_align; @@ -64,7 +64,7 @@ public: struct ChannelElem { LLUUID id; - LLScreenChannel* channel; + LLScreenChannelBase* channel; ChannelElem() : id(LLUUID("")), channel(NULL) { } @@ -89,19 +89,23 @@ public: void onStartUpToastClose(); // creates a new ScreenChannel according to the given parameters or returns existing if present - LLScreenChannel* getChannel(LLChannelManager::Params& p); + LLScreenChannelBase* getChannel(LLChannelManager::Params& p); + + LLScreenChannelBase* addChannel(LLScreenChannelBase* channel); // returns a channel by its ID - LLScreenChannel* findChannelByID(const LLUUID id); + LLScreenChannelBase* findChannelByID(const LLUUID id); // creator of the Notification channel, that is used in more than one handler - LLScreenChannel* createNotificationChannel(); + LLScreenChannel* createNotificationChannel(); // remove channel methods void removeChannelByID(const LLUUID id); private: + LLScreenChannel* createChannel(LLChannelManager::Params& p); + LLScreenChannel* mStartUpChannel; std::vector mChannelList; }; diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 6fb6552f2d..c2d7e0d935 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -44,6 +44,7 @@ #include "llviewercontrol.h" #include "llagentdata.h" +/* static const S32 BORDER_MARGIN = 2; static const S32 PARENT_BORDER_MARGIN = 0; @@ -53,33 +54,27 @@ static const F32 MIN_AUTO_SCROLL_RATE = 120.f; static const F32 MAX_AUTO_SCROLL_RATE = 500.f; static const F32 AUTO_SCROLL_RATE_ACCEL = 120.f; -static const S32 msg_left_offset = 30; -static const S32 msg_right_offset = 10; - #define MAX_CHAT_HISTORY 100 +*/ +static const S32 msg_left_offset = 30; +static const S32 msg_right_offset = 10; -static LLDefaultChildRegistry::Register t2("chat_items_container"); - - +//static LLDefaultChildRegistry::Register t2("chat_items_container"); //******************************************************************************************************************* //LLChatItemCtrl //******************************************************************************************************************* -LLChatItemCtrl* LLChatItemCtrl::createInstance() +LLNearbyChatToastPanel* LLNearbyChatToastPanel::createInstance() { - LLChatItemCtrl* item = new LLChatItemCtrl(); + LLNearbyChatToastPanel* item = new LLNearbyChatToastPanel(); LLUICtrlFactory::getInstance()->buildPanel(item, "panel_chat_item.xml"); + item->setFollows(FOLLOWS_NONE); return item; } -void LLChatItemCtrl::draw() -{ - LLPanel::draw(); -} - -void LLChatItemCtrl::reshape (S32 width, S32 height, BOOL called_from_parent ) +void LLNearbyChatToastPanel::reshape (S32 width, S32 height, BOOL called_from_parent ) { LLPanel::reshape(width, height,called_from_parent); @@ -101,13 +96,13 @@ void LLChatItemCtrl::reshape (S32 width, S32 height, BOOL called_from_parent ) } } -BOOL LLChatItemCtrl::postBuild() +BOOL LLNearbyChatToastPanel::postBuild() { return LLPanel::postBuild(); } -std::string LLChatItemCtrl::appendTime() +std::string LLNearbyChatToastPanel::appendTime() { time_t utc_time; utc_time = time_corrected(); @@ -124,48 +119,63 @@ std::string LLChatItemCtrl::appendTime() -void LLChatItemCtrl::addText (const std::string& message) +void LLNearbyChatToastPanel::addText (const std::string& message) { LLChatMsgBox* msg_text = getChild("msg_text", false); msg_text->addText(message); mMessages.push_back(message); } -void LLChatItemCtrl::setMessage (const LLChat& msg) +void LLNearbyChatToastPanel::init(LLSD& notification) { LLPanel* caption = getChild("msg_caption", false); + mText = notification["message"].asString(); // UTF-8 line of text + mFromName = notification["from"].asString(); // agent or object name + mFromID = notification["from_id"].asUUID(); // agent id or object id + int sType = notification["source"].asInteger(); + mSourceType = (EChatSourceType)sType; + std::string str_sender; - - if(gAgentID != msg.mFromID) - str_sender = msg.mFromName; + if(gAgentID != mFromID) + str_sender = mFromName; else str_sender = LLTrans::getString("You");; caption->getChild("sender_name", false)->setText(str_sender); - std::string tt = appendTime(); - - caption->getChild("msg_time", false)->setText(tt); - - - caption->getChild("avatar_icon", false)->setValue(msg.mFromID); + caption->getChild("msg_time", false)->setText(appendTime()); - mOriginalMessage = msg; LLChatMsgBox* msg_text = getChild("msg_text", false); - msg_text->setText(msg.mText); + msg_text->setText(mText); LLUICtrl* msg_inspector = caption->getChild("msg_inspector"); - if(mOriginalMessage.mSourceType != CHAT_SOURCE_AGENT) + if(mSourceType != CHAT_SOURCE_AGENT) msg_inspector->setVisible(false); mMessages.clear(); + snapToMessageHeight (); + + mIsDirty = true;//will set Avatar Icon in draw +} + +void LLNearbyChatToastPanel::setMessage (const LLChat& chat_msg) +{ + LLSD notification; + notification["message"] = chat_msg.mText; + notification["from"] = chat_msg.mFromName; + notification["from_id"] = chat_msg.mFromID; + notification["time"] = chat_msg.mTime; + notification["source"] = (S32)chat_msg.mSourceType; + + init(notification); + } -void LLChatItemCtrl::snapToMessageHeight () +void LLNearbyChatToastPanel::snapToMessageHeight () { LLChatMsgBox* text_box = getChild("msg_text", false); S32 new_height = text_box->getTextPixelHeight(); @@ -184,14 +194,14 @@ void LLChatItemCtrl::snapToMessageHeight () } -void LLChatItemCtrl::setWidth(S32 width) +void LLNearbyChatToastPanel::setWidth(S32 width) { LLChatMsgBox* text_box = getChild("msg_text", false); text_box->reshape(width - msg_left_offset - msg_right_offset,100/*its not magic number, we just need any number*/); LLChatMsgBox* msg_text = getChild("msg_text", false); - if(mOriginalMessage.mText.length()) - msg_text->setText(mOriginalMessage.mText); + if(mText.length()) + msg_text->setText(mText); for(size_t i=0;iaddText(mMessages[i]); @@ -200,25 +210,25 @@ void LLChatItemCtrl::setWidth(S32 width) snapToMessageHeight (); } -void LLChatItemCtrl::onMouseLeave (S32 x, S32 y, MASK mask) +void LLNearbyChatToastPanel::onMouseLeave (S32 x, S32 y, MASK mask) { LLPanel* caption = getChild("msg_caption", false); LLUICtrl* msg_inspector = caption->getChild("msg_inspector"); msg_inspector->setVisible(false); } -void LLChatItemCtrl::onMouseEnter (S32 x, S32 y, MASK mask) +void LLNearbyChatToastPanel::onMouseEnter (S32 x, S32 y, MASK mask) { - if(mOriginalMessage.mSourceType != CHAT_SOURCE_AGENT) + if(mSourceType != CHAT_SOURCE_AGENT) return; LLPanel* caption = getChild("msg_caption", false); LLUICtrl* msg_inspector = caption->getChild("msg_inspector"); msg_inspector->setVisible(true); } -BOOL LLChatItemCtrl::handleMouseDown (S32 x, S32 y, MASK mask) +BOOL LLNearbyChatToastPanel::handleMouseDown (S32 x, S32 y, MASK mask) { - if(mOriginalMessage.mSourceType != CHAT_SOURCE_AGENT) + if(mSourceType != CHAT_SOURCE_AGENT) return LLPanel::handleMouseDown(x,y,mask); LLPanel* caption = getChild("msg_caption", false); LLUICtrl* msg_inspector = caption->getChild("msg_inspector"); @@ -226,12 +236,16 @@ BOOL LLChatItemCtrl::handleMouseDown (S32 x, S32 y, MASK mask) S32 local_y = y - msg_inspector->getRect().mBottom - caption->getRect().mBottom; if(msg_inspector->pointInView(local_x, local_y)) { - LLFloaterReg::showInstance("inspect_avatar", mOriginalMessage.mFromID); + LLFloaterReg::showInstance("inspect_avatar", mFromID); + } + else + { + LLFloaterReg::showInstance("nearby_chat",LLSD()); } return LLPanel::handleMouseDown(x,y,mask); } -void LLChatItemCtrl::setHeaderVisibility(EShowItemHeader e) +void LLNearbyChatToastPanel::setHeaderVisibility(EShowItemHeader e) { LLPanel* caption = getChild("msg_caption", false); @@ -243,7 +257,7 @@ void LLChatItemCtrl::setHeaderVisibility(EShowItemHeader e) } -bool LLChatItemCtrl::canAddText () +bool LLNearbyChatToastPanel::canAddText () { LLChatMsgBox* msg_text = findChild("msg_text"); if(!msg_text) @@ -251,7 +265,7 @@ bool LLChatItemCtrl::canAddText () return msg_text->getTextLinesNum()<10; } -BOOL LLChatItemCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) +BOOL LLNearbyChatToastPanel::handleRightMouseDown(S32 x, S32 y, MASK mask) { LLPanel* caption = getChild("msg_caption", false); LLUICtrl* avatar_icon = caption->getChild("avatar_icon", false); @@ -260,296 +274,20 @@ BOOL LLChatItemCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) S32 local_y = y - avatar_icon->getRect().mBottom - caption->getRect().mBottom; //eat message for avatar icon if msg was from object - if(avatar_icon->pointInView(local_x, local_y) && mOriginalMessage.mSourceType != CHAT_SOURCE_AGENT) + if(avatar_icon->pointInView(local_x, local_y) && mSourceType != CHAT_SOURCE_AGENT) return TRUE; return LLPanel::handleRightMouseDown(x,y,mask); } - - -//******************************************************************************************************************* -//LLChatItemsContainerCtrl -//******************************************************************************************************************* - -LLChatItemsContainerCtrl::LLChatItemsContainerCtrl(const Params& params):LLPanel(params) -{ - mEShowItemHeader = CHATITEMHEADER_SHOW_BOTH; -} - - -void LLChatItemsContainerCtrl::addMessage(const LLChat& msg) -{ - /* - if(msg.mChatType == CHAT_TYPE_DEBUG_MSG) - return; - */ - if(mItems.size() >= MAX_CHAT_HISTORY) - { - LLChatItemCtrl* item = mItems[0]; - removeChild(item); - delete item; - mItems.erase(mItems.begin()); - } - - - if(mItems.size() > 0 - && msg.mFromID == mItems[mItems.size()-1]->getMessage().mFromID - && (msg.mTime-mItems[mItems.size()-1]->getMessage().mTime)<60 - && mItems[mItems.size()-1]->canAddText() - ) - { - mItems[mItems.size()-1]->addText(msg.mText); - mItems[mItems.size()-1]->snapToMessageHeight(); - } - else - { - LLChatItemCtrl* item = LLChatItemCtrl::createInstance(); - mItems.push_back(item); - addChild(item,0); - item->setWidth(getRect().getWidth() - 16); - item->setMessage(msg); - item->snapToMessageHeight(); - - item->setHeaderVisibility((EShowItemHeader)gSavedSettings.getS32("nearbychat_showicons_and_names")); - - item->setVisible(true); - } - - arrange(getRect().getWidth(),getRect().getHeight()); - updateLayout(getRect().getWidth(),getRect().getHeight()); - scrollToBottom(); -} - -void LLChatItemsContainerCtrl::scrollToBottom () -{ - if(mScrollbar->getVisible()) - { - mScrollbar->setDocPos(mScrollbar->getDocPosMax()); - onScrollPosChangeCallback(0,0); - } -} - -void LLChatItemsContainerCtrl::draw() -{ - LLLocalClipRect clip(getRect()); - LLPanel::draw(); -} - -void LLChatItemsContainerCtrl::reshape (S32 width, S32 height, BOOL called_from_parent ) -{ - S32 delta_width = width - getRect().getWidth(); - S32 delta_height = height - getRect().getHeight(); - - if (delta_width || delta_height || sForceReshape) - { - arrange(width, height); - } - - updateBoundingRect(); -} - -void LLChatItemsContainerCtrl::arrange (S32 width, S32 height) +void LLNearbyChatToastPanel::draw() { - S32 delta_width = width - getRect().getWidth(); - if(delta_width)//width changed...too bad. now we need to reformat all items - reformatHistoryScrollItems(width); - - calcRecuiredHeight(); - - show_hide_scrollbar(width,height); - - updateLayout(width,height); -} - -void LLChatItemsContainerCtrl::reformatHistoryScrollItems(S32 width) -{ - for(std::vector::iterator it = mItems.begin(); it != mItems.end();++it) - { - (*it)->setWidth(width); - } -} - -S32 LLChatItemsContainerCtrl::calcRecuiredHeight () -{ - S32 rec_height = 0; - - std::vector::iterator it; - for(it=mItems.begin(); it!=mItems.end(); ++it) - { - rec_height += (*it)->getRect().getHeight(); - } - - mInnerRect.setLeftTopAndSize(0,rec_height + BORDER_MARGIN*2,getRect().getWidth(),rec_height + BORDER_MARGIN); - - return mInnerRect.getHeight(); -} - - -void LLChatItemsContainerCtrl::updateLayout (S32 width, S32 height) -{ - S32 panel_top = height - BORDER_MARGIN ; - S32 panel_width = width; - if(mScrollbar->getVisible()) - { - static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); - - panel_top+=mScrollbar->getDocPos(); - panel_width-=scrollbar_size; - } - - - //set sizes for first panels and dragbars - for(size_t i=0;igetRect(); - panelSetLeftTopAndSize(mItems[i],panel_rect.mLeft,panel_top,panel_width,panel_rect.getHeight()); - panel_top-=panel_rect.getHeight(); - } -} - -void LLChatItemsContainerCtrl::show_hide_scrollbar (S32 width, S32 height) -{ - calcRecuiredHeight(); - if(getRecuiredHeight() > height ) - showScrollbar(width, height); - else - hideScrollbar(width, height); -} - -void LLChatItemsContainerCtrl::showScrollbar (S32 width, S32 height) -{ - bool was_visible = mScrollbar->getVisible(); - - mScrollbar->setVisible(true); - - static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); - - panelSetLeftTopAndSize(mScrollbar,width-scrollbar_size - ,height-PARENT_BORDER_MARGIN,scrollbar_size,height-2*PARENT_BORDER_MARGIN); - - mScrollbar->setPageSize(height); - mScrollbar->setDocParams(mInnerRect.getHeight(),mScrollbar->getDocPos()); - - if(was_visible) - { - S32 scroll_pos = llmin(mScrollbar->getDocPos(), getRecuiredHeight() - height - 1); - mScrollbar->setDocPos(scroll_pos); - updateLayout(width,height); - return; - } -} - -void LLChatItemsContainerCtrl::hideScrollbar (S32 width, S32 height) -{ - if(mScrollbar->getVisible() == false) - return; - mScrollbar->setVisible(false); - - mScrollbar->setDocPos(0); - - if(mItems.size()>0) - { - S32 panel_top = height - BORDER_MARGIN; // Top coordinate of the first panel - S32 diff = panel_top - mItems[0]->getRect().mTop; - shiftPanels(diff); - } -} - -//--------------------------------------------------------------------------------- -void LLChatItemsContainerCtrl::panelSetLeftTopAndSize(LLView* panel, S32 left, S32 top, S32 width, S32 height) -{ - if(!panel) - return; - LLRect panel_rect = panel->getRect(); - panel_rect.setLeftTopAndSize( left, top, width, height); - panel->reshape( width, height, 1); - panel->setRect(panel_rect); -} - -void LLChatItemsContainerCtrl::panelShiftVertical(LLView* panel,S32 delta) -{ - if(!panel) - return; - panel->translate(0,delta); -} - -void LLChatItemsContainerCtrl::shiftPanels(S32 delta) -{ - //Arrange panels - for(std::vector::iterator it = mItems.begin(); it != mItems.end();++it) - { - panelShiftVertical((*it),delta); - } - -} - -//--------------------------------------------------------------------------------- - -void LLChatItemsContainerCtrl::onScrollPosChangeCallback(S32, LLScrollbar*) -{ - updateLayout(getRect().getWidth(),getRect().getHeight()); -} - -BOOL LLChatItemsContainerCtrl::postBuild() -{ - static LLUICachedControl scrollbar_size ("UIScrollbarSize", 0); - - LLRect scroll_rect; - scroll_rect.setOriginAndSize( - getRect().getWidth() - scrollbar_size, - 1, - scrollbar_size, - getRect().getHeight() - 1); - - - LLScrollbar::Params sbparams; - sbparams.name("scrollable vertical"); - sbparams.rect(scroll_rect); - sbparams.orientation(LLScrollbar::VERTICAL); - sbparams.doc_size(mInnerRect.getHeight()); - sbparams.doc_pos(0); - sbparams.page_size(mInnerRect.getHeight()); - sbparams.step_size(VERTICAL_MULTIPLE); - sbparams.follows.flags(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM); - sbparams.change_callback(boost::bind(&LLChatItemsContainerCtrl::onScrollPosChangeCallback, this, _1, _2)); - - mScrollbar = LLUICtrlFactory::create (sbparams); - LLView::addChild( mScrollbar ); - mScrollbar->setVisible( true ); - mScrollbar->setFollowsRight(); - mScrollbar->setFollowsTop(); - mScrollbar->setFollowsBottom(); - - reformatHistoryScrollItems(getRect().getWidth()); - arrange(getRect().getWidth(),getRect().getHeight()); - - return LLPanel::postBuild(); -} -BOOL LLChatItemsContainerCtrl::handleMouseDown (S32 x, S32 y, MASK mask) -{ - return LLPanel::handleMouseDown(x,y,mask); -} -BOOL LLChatItemsContainerCtrl::handleKeyHere (KEY key, MASK mask) -{ - if( mScrollbar->getVisible() && mScrollbar->handleKeyHere( key,mask ) ) - return TRUE; - return LLPanel::handleKeyHere(key,mask); -} -BOOL LLChatItemsContainerCtrl::handleScrollWheel ( S32 x, S32 y, S32 clicks ) -{ - if( mScrollbar->getVisible() && mScrollbar->handleScrollWheel( 0, 0, clicks ) ) - return TRUE; - return false; -} - -void LLChatItemsContainerCtrl::setHeaderVisibility(EShowItemHeader e) -{ - if(e == mEShowItemHeader) - return; - mEShowItemHeader = e; - for(std::vector::iterator it = mItems.begin(); it != mItems.end();++it) + if(mIsDirty) { - (*it)->setHeaderVisibility(e); + LLPanel* caption = findChild("msg_caption", false); + if(caption) + caption->getChild("avatar_icon", false)->setValue(mFromID); + mIsDirty = false; } + LLToastPanelBase::draw(); } diff --git a/indra/newview/llchatitemscontainerctrl.h b/indra/newview/llchatitemscontainerctrl.h index de16cf9505..8fb045b6d9 100644 --- a/indra/newview/llchatitemscontainerctrl.h +++ b/indra/newview/llchatitemscontainerctrl.h @@ -37,6 +37,7 @@ #include "llscrollbar.h" #include "string" #include "llchat.h" +#include "lltoastpanel.h" typedef enum e_show_item_header { @@ -45,20 +46,18 @@ typedef enum e_show_item_header CHATITEMHEADER_SHOW_BOTH } EShowItemHeader; -class LLChatItemCtrl: public LLPanel +class LLNearbyChatToastPanel: public LLToastPanelBase { protected: - LLChatItemCtrl(){}; + LLNearbyChatToastPanel():mIsDirty(false){}; public: - ~LLChatItemCtrl(){} + ~LLNearbyChatToastPanel(){} - static LLChatItemCtrl* createInstance(); + static LLNearbyChatToastPanel* createInstance(); - void draw(); - - const LLChat& getMessage() const { return mOriginalMessage;} + const LLUUID& getFromID() const { return mFromID;} void addText (const std::string& message); void setMessage (const LLChat& msg); @@ -77,78 +76,27 @@ public: void setHeaderVisibility(EShowItemHeader e); BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); -private: - - std::string appendTime (); - -private: - LLChat mOriginalMessage; - - std::vector mMessages; -}; - -class LLChatItemsContainerCtrl: public LLPanel -{ -public: - struct Params - : public LLInitParam::Block - { - Params(){}; - }; - - LLChatItemsContainerCtrl(const Params& params); - - - ~LLChatItemsContainerCtrl(){} - - void addMessage (const LLChat& msg); - - void draw(); - - void reshape (S32 width, S32 height, BOOL called_from_parent = TRUE); - - void onScrollPosChangeCallback(S32, LLScrollbar*); - - virtual BOOL postBuild(); - - BOOL handleMouseDown (S32 x, S32 y, MASK mask); - BOOL handleKeyHere (KEY key, MASK mask); - BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); - - void scrollToBottom (); - - void setHeaderVisibility(EShowItemHeader e); - EShowItemHeader getHeaderVisibility() const { return mEShowItemHeader;}; + virtual void init(LLSD& data); + virtual void draw(); private: - void reformatHistoryScrollItems(S32 width); - void arrange (S32 width, S32 height); - - S32 calcRecuiredHeight (); - S32 getRecuiredHeight () const { return mInnerRect.getHeight(); } - - void updateLayout (S32 width, S32 height); - - void show_hide_scrollbar (S32 width, S32 height); - - void showScrollbar (S32 width, S32 height); - void hideScrollbar (S32 width, S32 height); - - void panelSetLeftTopAndSize (LLView* panel, S32 left, S32 top, S32 width, S32 height); - void panelShiftVertical (LLView* panel,S32 delta); - void shiftPanels (S32 delta); + + std::string appendTime (); private: - std::vector mItems; + std::string mText; // UTF-8 line of text + std::string mFromName; // agent or object name + LLUUID mFromID; // agent id or object id + EChatSourceType mSourceType; - EShowItemHeader mEShowItemHeader; - LLRect mInnerRect; - LLScrollbar* mScrollbar; + std::vector mMessages; + bool mIsDirty; }; + #endif diff --git a/indra/newview/llchatmsgbox.cpp b/indra/newview/llchatmsgbox.cpp index e6398dd47a..bd0c36b44a 100644 --- a/indra/newview/llchatmsgbox.cpp +++ b/indra/newview/llchatmsgbox.cpp @@ -102,7 +102,7 @@ void LLChatMsgBox::drawText(S32 x, S32 y, const LLWString &text, const LLColor4 // iterate through each block of text that has been added y -= mLineSpacing; - for (std::vector::iterator it = mSeparatorOffset.begin(); true ;) + for (std::vector::iterator it = mSeparatorOffset.begin(); it != mSeparatorOffset.end() ;) { // display the text for this block S32 num_chars = *it - start; diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 20c44d5b11..98e492cada 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -49,6 +49,7 @@ #include "llvoicecontrolpanel.h" #include "llgroupmgr.h" #include "llnotificationmanager.h" +#include "lltransientfloatermgr.h" static LLDefaultChildRegistry::Register t1("chiclet_panel"); static LLDefaultChildRegistry::Register t2("chiclet_talk"); @@ -243,26 +244,36 @@ void LLIMChiclet::draw() LLIMChiclet::EType LLIMChiclet::getIMSessionType(const LLUUID& session_id) { EType type = TYPE_UNKNOWN; - LLFloaterIMPanel* im = NULL; if(session_id.isNull()) return type; - if (!(im = LLIMMgr::getInstance()->findFloaterBySession(session_id))) + EInstantMessage im_type = LLIMModel::getInstance()->getType(session_id); + if (IM_COUNT == im_type) { llassert_always(0 && "IM session not found"); // should never happen return type; } - switch(im->getDialogType()) + switch(im_type) { case IM_NOTHING_SPECIAL: + case IM_SESSION_P2P_INVITE: type = TYPE_IM; break; case IM_SESSION_GROUP_START: case IM_SESSION_INVITE: - type = TYPE_GROUP; + if (gAgent.isInGroup(session_id)) + { + type = TYPE_GROUP; + } + else + { + type = TYPE_AD_HOC; + } break; + case IM_SESSION_CONFERENCE_START: + type = TYPE_AD_HOC; default: break; } @@ -285,6 +296,11 @@ LLIMP2PChiclet::Params::Params() avatar_icon.name("avatar_icon"); avatar_icon.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_BOTTOM); + + // *NOTE dzaporozhan + // Changed icon height from 25 to 24 to fix ticket EXT-794. + // In some cases(after changing UI scale) 25 pixel height icon was + // drawn incorrectly, i'm not sure why. avatar_icon.rect(LLRect(0, 24, 25, 0)); avatar_icon.mouse_opaque(false); @@ -458,6 +474,11 @@ LLIMGroupChiclet::Params::Params() rect(LLRect(0, 25, 45, 0)); group_icon.name("group_icon"); + + // *NOTE dzaporozhan + // Changed icon height from 25 to 24 to fix ticket EXT-794. + // In some cases(after changing UI scale) 25 pixel height icon was + // drawn incorrectly, i'm not sure why. group_icon.rect(LLRect(0, 24, 25, 0)); unread_notifications.name("unread"); @@ -1164,6 +1185,7 @@ LLTalkButton::LLTalkButton(const Params& p) speak_params.rect(speak_rect); mSpeakBtn = LLUICtrlFactory::create(speak_params); addChild(mSpeakBtn); + LLTransientFloaterMgr::getInstance()->addControlView(mSpeakBtn); mSpeakBtn->setClickedCallback(boost::bind(&LLTalkButton::onClick_SpeakBtn, this)); mSpeakBtn->setToggleState(FALSE); @@ -1172,6 +1194,7 @@ LLTalkButton::LLTalkButton(const Params& p) show_params.rect(show_rect); mShowBtn = LLUICtrlFactory::create(show_params); addChild(mShowBtn); + LLTransientFloaterMgr::getInstance()->addControlView(mShowBtn); mShowBtn->setClickedCallback(boost::bind(&LLTalkButton::onClick_ShowBtn, this)); mShowBtn->setToggleState(FALSE); diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 316348cf1d..ef47b54333 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -275,7 +275,8 @@ public: enum EType { TYPE_UNKNOWN, TYPE_IM, - TYPE_GROUP + TYPE_GROUP, + TYPE_AD_HOC }; /*virtual*/ ~LLIMChiclet() {}; diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 6b18984f88..ea947a5565 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -934,6 +934,17 @@ void LLFavoritesBarCtrl::onButtonRightClick( LLUUID item_id,LLView* fav_button,S LLMenuGL::showPopup(fav_button, menu, x, y); } +BOOL LLFavoritesBarCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + BOOL handled = childrenHandleRightMouseDown( x, y, mask) != NULL; + if(!handled && !gMenuHolder->hasVisibleMenu()) + { + show_navbar_context_menu(this,x,y); + handled = true; + } + + return handled; +} void copy_slurl_to_clipboard_cb(std::string& slurl) { gClipboard.copyFromString(utf8str_to_wstring(slurl)); diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index 0be8de29a9..97117c3b4a 100644 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -62,7 +62,7 @@ public: std::string& tooltip_msg); /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); - + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); // LLInventoryObserver observer trigger virtual void changed(U32 mask); virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); diff --git a/indra/newview/llfloaterchatterbox.cpp b/indra/newview/llfloaterchatterbox.cpp index 05ea800d0e..dea656b0e4 100644 --- a/indra/newview/llfloaterchatterbox.cpp +++ b/indra/newview/llfloaterchatterbox.cpp @@ -363,7 +363,8 @@ LLFloater* LLFloaterChatterBox::getCurrentVoiceFloater() { // only LLFloaterIMPanels are called "im_floater" LLFloaterIMPanel* im_floaterp = (LLFloaterIMPanel*)panelp; - if (im_floaterp->getVoiceChannel() == LLVoiceChannel::getCurrentVoiceChannel()) + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(im_floaterp->getSessionID()); + if (voice_channel == LLVoiceChannel::getCurrentVoiceChannel()) { return im_floaterp; } diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index d3b013237b..905857f393 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -73,7 +73,11 @@ LLGroupList::Params::Params() LLGroupList::LLGroupList(const Params& p) : LLFlatListView(p) + , mDirty(true) // to force initial update { + // Listen for agent group changes. + gAgent.addListener(this, "new group"); + mShowIcons = gSavedSettings.getBOOL("GroupListShowIcons"); setCommitOnSelectionChange(true); // TODO: implement context menu @@ -84,17 +88,41 @@ LLGroupList::LLGroupList(const Params& p) setComparator(&GROUP_COMPARATOR); } +LLGroupList::~LLGroupList() +{ + gAgent.removeListener(this); +} + +// virtual +void LLGroupList::draw() +{ + if (mDirty) + refresh(); + + LLFlatListView::draw(); +} + +void LLGroupList::setNameFilter(const std::string& filter) +{ + if (mNameFilter != filter) + { + mNameFilter = filter; + setDirty(); + } +} + static bool findInsensitive(std::string haystack, const std::string& needle_upper) { LLStringUtil::toUpper(haystack); return haystack.find(needle_upper) != std::string::npos; } -BOOL LLGroupList::update(const std::string& name_filter) +void LLGroupList::refresh() { const LLUUID& highlight_id = gAgent.getGroupID(); S32 count = gAgent.mGroups.count(); LLUUID id; + bool have_filter = !mNameFilter.empty(); clear(); @@ -102,7 +130,7 @@ BOOL LLGroupList::update(const std::string& name_filter) { id = gAgent.mGroups.get(i).mID; const LLGroupData& group_data = gAgent.mGroups.get(i); - if (name_filter != LLStringUtil::null && !findInsensitive(group_data.mName, name_filter)) + if (have_filter && !findInsensitive(group_data.mName, mNameFilter)) continue; addNewItem(id, group_data.mName, group_data.mInsigniaID, highlight_id == id, ADD_BOTTOM); } @@ -113,13 +141,14 @@ BOOL LLGroupList::update(const std::string& name_filter) // add "none" to list at top { std::string loc_none = LLTrans::getString("GroupsNone"); - if (name_filter == LLStringUtil::null || findInsensitive(loc_none, name_filter)) + if (have_filter || findInsensitive(loc_none, mNameFilter)) addNewItem(LLUUID::null, loc_none, LLUUID::null, highlight_id.isNull(), ADD_TOP); } selectItemByUUID(highlight_id); - return TRUE; + setDirty(false); + onCommit(); } void LLGroupList::toggleIcons() @@ -158,6 +187,18 @@ void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LL // setCommentVisible(false); } +// virtual +bool LLGroupList::handleEvent(LLPointer event, const LLSD& userdata) +{ + // Why is "new group" sufficient? + if (event->desc() == "new group") + { + setDirty(); + return true; + } + + return false; +} /************************************************************************/ /* LLGroupListItem implementation */ diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h index 7708b58de6..9c3ab88901 100644 --- a/indra/newview/llgrouplist.h +++ b/indra/newview/llgrouplist.h @@ -33,10 +33,19 @@ #ifndef LL_LLGROUPLIST_H #define LL_LLGROUPLIST_H +#include "llevent.h" #include "llflatlistview.h" #include "llpanel.h" +#include "llpointer.h" -class LLGroupList: public LLFlatListView +/** + * Auto-updating list of agent groups. + * + * Can use optional group name filter. + * + * @see setNameFilter() + */ +class LLGroupList: public LLFlatListView, public LLOldEvents::LLSimpleListener { LOG_CLASS(LLGroupList); public: @@ -46,14 +55,23 @@ public: }; LLGroupList(const Params& p); - BOOL update(const std::string& name_filter = LLStringUtil::null); + virtual ~LLGroupList(); + + virtual void draw(); // from LLView + + void setNameFilter(const std::string& filter); void toggleIcons(); bool getIconsVisible() const { return mShowIcons; } - + private: + void setDirty(bool val = true) { mDirty = val; } + void refresh(); void addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, BOOL is_bold, EAddPosition pos = ADD_BOTTOM); + bool handleEvent(LLPointer event, const LLSD& userdata); // called on agent group list changes bool mShowIcons; + bool mDirty; + std::string mNameFilter; }; class LLButton; diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 254e16e1fb..1c144b11b0 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -48,6 +48,7 @@ #include "lltrans.h" #include "llviewertexteditor.h" #include "llviewerwindow.h" +#include "lltransientfloatermgr.h" @@ -62,33 +63,46 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id) mInputEditor(NULL), mPositioned(false) { - LLIMModel::LLIMSession* session = get_if_there(LLIMModel::instance().sSessionsMap, mSessionID, (LLIMModel::LLIMSession*)NULL); - if(session) + EInstantMessage type = LLIMModel::getInstance()->getType(session_id); + if(IM_COUNT != type) { - mDialog = session->mType; - } + mDialog = type; - if (mDialog == IM_NOTHING_SPECIAL) - { - mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelIMControl, this); - } - else - { - mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); + if (IM_NOTHING_SPECIAL == mDialog || IM_SESSION_P2P_INVITE == mDialog) + { + mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelIMControl, this); + } + else + { + mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this); + } } -// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_im_session.xml"); LLUI::getRootView()->setFocusLostCallback(boost::bind(&LLIMFloater::focusChangeCallback, this)); mCloseSignal.connect(boost::bind(&LLIMFloater::onClose, this)); + + LLTransientFloaterMgr::getInstance()->registerTransientFloater(this); } void LLIMFloater::onClose() { LLIMModel::instance().sendLeaveSession(mSessionID, mOtherParticipantUUID); + + //*TODO - move to the IMModel::sendLeaveSession() for the integrity (IB) gIMMgr->removeSession(mSessionID); } +void LLIMFloater::setMinimized(BOOL minimize) +{ + if(!isDocked()) + { + setVisible(!minimize); + } + + LLFloater::setMinimized(minimize); +} + /* static */ void LLIMFloater::newIMCallback(const LLSD& data){ @@ -152,16 +166,17 @@ void LLIMFloater::sendMsg() LLIMFloater::~LLIMFloater() { + LLTransientFloaterMgr::getInstance()->unregisterTransientFloater(this); } //virtual BOOL LLIMFloater::postBuild() { - LLIMModel::LLIMSession* session = get_if_there(LLIMModel::instance().sSessionsMap, mSessionID, (LLIMModel::LLIMSession*)NULL); - if(session) + const LLUUID& other_party_id = LLIMModel::getInstance()->getOtherParticipantID(mSessionID); + if (other_party_id.notNull()) { - mOtherParticipantUUID = session->mOtherParticipantID; - mControlPanel->setID(session->mOtherParticipantID); + mOtherParticipantUUID = other_party_id; + mControlPanel->setID(mOtherParticipantUUID); } LLButton* slide_left = getChild("slide_left_btn"); @@ -216,17 +231,6 @@ void* LLIMFloater::createPanelGroupControl(void* userdata) return self->mControlPanel; } - - -void LLIMFloater::focusChangeCallback() -{ - // hide docked floater if user clicked inside in-world area - if (isDocked()) - { - setVisible(false); - } -} - void LLIMFloater::onSlide() { LLPanel* im_control_panel = getChild("panel_im_control_panel"); @@ -271,13 +275,13 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id) } floater->setDockControl(new LLDockControl(chiclet, floater, floater->getDockTongue(), - LLDockControl::TOP, boost::bind(&LLIMFloater::getEnabledRect, floater, _1))); + LLDockControl::TOP, boost::bind(&LLIMFloater::getAllowedRect, floater, _1))); } return floater; } -void LLIMFloater::getEnabledRect(LLRect& rect) +void LLIMFloater::getAllowedRect(LLRect& rect) { rect = gViewerWindow->getWorldViewRect(); } @@ -285,8 +289,10 @@ void LLIMFloater::getEnabledRect(LLRect& rect) void LLIMFloater::setDocked(bool docked, bool pop_on_undock) { // update notification channel state - LLNotificationsUI::LLScreenChannel* channel = LLNotificationsUI::LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))); + LLNotificationsUI::LLScreenChannel* channel = dynamic_cast + (LLNotificationsUI::LLChannelManager::getInstance()-> + findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + LLDockableFloater::setDocked(docked, pop_on_undock); // update notification channel state @@ -298,8 +304,9 @@ void LLIMFloater::setDocked(bool docked, bool pop_on_undock) void LLIMFloater::setVisible(BOOL visible) { - LLNotificationsUI::LLScreenChannel* channel = LLNotificationsUI::LLChannelManager::getInstance()-> - findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))); + LLNotificationsUI::LLScreenChannel* channel = dynamic_cast + (LLNotificationsUI::LLChannelManager::getInstance()-> + findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); LLDockableFloater::setVisible(visible); // update notification channel state diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index 276f38e829..a183212f04 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -57,6 +57,8 @@ public: // LLFloater overrides /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); + // override LLFloater's minimization according to EXT-1216 + /*virtual*/ void setMinimized(BOOL minimize); // Make IM conversion visible and update the message history static LLIMFloater* show(const LLUUID& session_id); @@ -90,8 +92,8 @@ private: void onSlide(); static void* createPanelIMControl(void* userdata); static void* createPanelGroupControl(void* userdata); - void focusChangeCallback(); - void getEnabledRect(LLRect& rect); + // gets a rect that bounds possible positions for the LLIMFloater on a screen (EXT-1111) + void getAllowedRect(LLRect& rect); LLPanelChatControlPanel* mControlPanel; LLUUID mSessionID; diff --git a/indra/newview/llimhandler.cpp b/indra/newview/llimhandler.cpp index 46067c081f..74971f3fd8 100644 --- a/indra/newview/llimhandler.cpp +++ b/indra/newview/llimhandler.cpp @@ -109,7 +109,9 @@ bool LLIMHandler::processNotification(const LLSD& notify) p.panel = im_box; p.can_be_stored = false; p.on_delete_toast = boost::bind(&LLIMHandler::onDeleteToast, this, _1); - mChannel->addToast(p); + LLScreenChannel* channel = dynamic_cast(mChannel); + if(channel) + channel->addToast(p); // send a signal to the counter manager; mNewNotificationSignal(); diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index aa2beabf3d..abd3cd4def 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -940,7 +940,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label, mHistoryEditor(NULL), mSessionUUID(session_id), mSessionLabel(session_label), - mVoiceChannel(NULL), mSessionInitialized(FALSE), mSessionStartMsgPos(0), mOtherParticipantUUID(other_participant_id), @@ -956,7 +955,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label, mTextIMPossible(TRUE), mProfileButtonEnabled(TRUE), mCallBackEnabled(TRUE), - mSpeakers(NULL), mSpeakerPanel(NULL), mFirstKeystrokeTimer(), mLastKeystrokeTimer() @@ -967,7 +965,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label, case IM_SESSION_GROUP_START: mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, this); xml_filename = "floater_instant_message_group.xml"; - mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, mSessionLabel); break; case IM_SESSION_INVITE: mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, this); @@ -979,16 +976,13 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label, { xml_filename = "floater_instant_message_ad_hoc.xml"; } - mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, mSessionLabel); break; case IM_SESSION_P2P_INVITE: xml_filename = "floater_instant_message.xml"; - mVoiceChannel = new LLVoiceChannelP2P(mSessionUUID, mSessionLabel, mOtherParticipantUUID); break; case IM_SESSION_CONFERENCE_START: mFactoryMap["active_speakers_panel"] = LLCallbackMap(createSpeakersPanel, this); xml_filename = "floater_instant_message_ad_hoc.xml"; - mVoiceChannel = new LLVoiceChannelGroup(mSessionUUID, mSessionLabel); break; // just received text from another user case IM_NOTHING_SPECIAL: @@ -998,8 +992,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label, mTextIMPossible = LLVoiceClient::getInstance()->isSessionTextIMPossible(mSessionUUID); mProfileButtonEnabled = LLVoiceClient::getInstance()->isParticipantAvatar(mSessionUUID); mCallBackEnabled = LLVoiceClient::getInstance()->isSessionCallBackPossible(mSessionUUID); - - mVoiceChannel = new LLVoiceChannelP2P(mSessionUUID, mSessionLabel, mOtherParticipantUUID); break; default: llwarns << "Unknown session type" << llendl; @@ -1007,10 +999,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label, break; } - mSpeakers = new LLIMSpeakerMgr(mVoiceChannel); - // All participants will be added to the list of people we've recently interacted with. - mSpeakers->addListener(&LLRecentPeople::instance(), "add"); - LLUICtrlFactory::getInstance()->buildFloater(this, xml_filename, NULL); setTitle(mSessionLabel); @@ -1058,33 +1046,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label, LLFloaterIMPanel::~LLFloaterIMPanel() { - delete mSpeakers; - mSpeakers = NULL; - - // End the text IM session if necessary - if(gVoiceClient && mOtherParticipantUUID.notNull()) - { - switch(mDialog) - { - case IM_NOTHING_SPECIAL: - case IM_SESSION_P2P_INVITE: - gVoiceClient->endUserIMSession(mOtherParticipantUUID); - break; - - default: - // Appease the compiler - break; - } - } - - //kicks you out of the voice channel if it is currently active - - // HAVE to do this here -- if it happens in the LLVoiceChannel destructor it will call the wrong version (since the object's partially deconstructed at that point). - mVoiceChannel->deactivate(); - - delete mVoiceChannel; - mVoiceChannel = NULL; - //delete focus lost callback mFocusCallbackConnection.disconnect(); } @@ -1152,7 +1113,8 @@ BOOL LLFloaterIMPanel::postBuild() void* LLFloaterIMPanel::createSpeakersPanel(void* data) { LLFloaterIMPanel* floaterp = (LLFloaterIMPanel*)data; - floaterp->mSpeakerPanel = new LLPanelActiveSpeakers(floaterp->mSpeakers, TRUE); + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(floaterp->mSessionUUID); + floaterp->mSpeakerPanel = new LLPanelActiveSpeakers(speaker_mgr, TRUE); return floaterp->mSpeakerPanel; } @@ -1198,12 +1160,14 @@ void LLFloaterIMPanel::draw() && mCallBackEnabled; // hide/show start call and end call buttons - childSetVisible("end_call_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->getState() >= LLVoiceChannel::STATE_CALL_STARTED); - childSetVisible("start_call_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->getState() < LLVoiceChannel::STATE_CALL_STARTED); + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionUUID); + childSetVisible("end_call_btn", LLVoiceClient::voiceEnabled() && voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED); + childSetVisible("start_call_btn", LLVoiceClient::voiceEnabled() && voice_channel->getState() < LLVoiceChannel::STATE_CALL_STARTED); childSetEnabled("start_call_btn", enable_connect); childSetEnabled("send_btn", !childGetValue("chat_editor").asString().empty()); - LLPointer self_speaker = mSpeakers->findSpeaker(gAgent.getID()); + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionUUID); + LLPointer self_speaker = speaker_mgr->findSpeaker(gAgent.getID()); if(!mTextIMPossible) { mInputEditor->setEnabled(FALSE); @@ -1227,7 +1191,7 @@ void LLFloaterIMPanel::draw() } // show speakers window when voice first connects - if (mShowSpeakersOnConnect && mVoiceChannel->isActive()) + if (mShowSpeakersOnConnect && voice_channel->isActive()) { childSetVisible("active_speakers_panel", TRUE); mShowSpeakersOnConnect = FALSE; @@ -1263,11 +1227,11 @@ void LLFloaterIMPanel::draw() else { // refresh volume and mute checkbox - childSetVisible("speaker_volume", LLVoiceClient::voiceEnabled() && mVoiceChannel->isActive()); + childSetVisible("speaker_volume", LLVoiceClient::voiceEnabled() && voice_channel->isActive()); childSetValue("speaker_volume", gVoiceClient->getUserVolume(mOtherParticipantUUID)); childSetValue("mute_btn", LLMuteList::getInstance()->isMuted(mOtherParticipantUUID, LLMute::flagVoiceChat)); - childSetVisible("mute_btn", LLVoiceClient::voiceEnabled() && mVoiceChannel->isActive()); + childSetVisible("mute_btn", LLVoiceClient::voiceEnabled() && voice_channel->isActive()); } LLFloater::draw(); } @@ -1403,12 +1367,6 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4 { mNumUnreadMessages++; } - - if (source != LLUUID::null) - { - mSpeakers->speakerChatted(source); - mSpeakers->setSpeakerTyping(source, FALSE); - } } @@ -1589,7 +1547,7 @@ void LLFloaterIMPanel::onClickStartCall(void* userdata) { LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata; - self->mVoiceChannel->activate(); + LLIMModel::getInstance()->getVoiceChannel(self->mSessionUUID)->activate(); } // static @@ -1597,7 +1555,7 @@ void LLFloaterIMPanel::onClickEndCall(void* userdata) { LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata; - self->getVoiceChannel()->deactivate(); + LLIMModel::getInstance()->getVoiceChannel(self->mSessionUUID)->deactivate(); } // static @@ -1671,7 +1629,8 @@ void LLFloaterIMPanel::onVisibilityChange(const LLSD& new_visibility) mNumUnreadMessages = 0; } - if (new_visibility.asBoolean() && mVoiceChannel->getState() == LLVoiceChannel::STATE_CONNECTED) + LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionUUID); + if (new_visibility.asBoolean() && voice_channel->getState() == LLVoiceChannel::STATE_CONNECTED) LLFloaterReg::showInstance("voice_call", mSessionUUID); else LLFloaterReg::hideInstance("voice_call", mSessionUUID); @@ -1723,11 +1682,6 @@ void LLFloaterIMPanel::sendMsg() mSentTypingState = TRUE; } -void LLFloaterIMPanel::updateSpeakersList(const LLSD& speaker_updates) -{ - mSpeakers->updateSpeakers(speaker_updates); -} - void LLFloaterIMPanel::processSessionUpdate(const LLSD& session_update) { if ( @@ -1751,15 +1705,9 @@ void LLFloaterIMPanel::processSessionUpdate(const LLSD& session_update) } } -void LLFloaterIMPanel::setSpeakers(const LLSD& speaker_list) -{ - mSpeakers->setSpeakers(speaker_list); -} - void LLFloaterIMPanel::sessionInitReplyReceived(const LLUUID& session_id) { mSessionUUID = session_id; - mVoiceChannel->updateSessionID(session_id); mSessionInitialized = TRUE; //we assume the history editor hasn't moved at all since @@ -1790,6 +1738,7 @@ void LLFloaterIMPanel::requestAutoConnect() void LLFloaterIMPanel::setTyping(BOOL typing) { + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionUUID); if (typing) { // Every time you type something, reset this timer @@ -1804,7 +1753,7 @@ void LLFloaterIMPanel::setTyping(BOOL typing) mSentTypingState = FALSE; } - mSpeakers->setSpeakerTyping(gAgent.getID(), TRUE); + speaker_mgr->setSpeakerTyping(gAgent.getID(), TRUE); } else { @@ -1814,7 +1763,7 @@ void LLFloaterIMPanel::setTyping(BOOL typing) sendTypingState(FALSE); mSentTypingState = TRUE; } - mSpeakers->setSpeakerTyping(gAgent.getID(), FALSE); + speaker_mgr->setSpeakerTyping(gAgent.getID(), FALSE); } mTyping = typing; @@ -1874,7 +1823,7 @@ void LLFloaterIMPanel::removeTypingIndicator(const LLIMInfo* im_info) mHistoryEditor->removeTextFromEnd(chars_to_remove); if (im_info) { - mSpeakers->setSpeakerTyping(im_info->mFromID, FALSE); + LLIMModel::getInstance()->getSpeakerManager(mSessionUUID)->setSpeakerTyping(im_info->mFromID, FALSE); } } } diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h index fd1134ee5e..fb9b28ad16 100644 --- a/indra/newview/llimpanel.h +++ b/indra/newview/llimpanel.h @@ -33,6 +33,7 @@ #ifndef LL_IMPANEL_H #define LL_IMPANEL_H +#include "llimview.h" //for LLIMModel #include "lldockablefloater.h" #include "lllogchat.h" #include "lluuid.h" @@ -245,11 +246,7 @@ public: const LLUUID& getSessionID() const { return mSessionUUID; } const LLUUID& getOtherParticipantID() const { return mOtherParticipantUUID; } - LLIMSpeakerMgr* getSpeakerManager() const { return mSpeakers; } - void updateSpeakersList(const LLSD& speaker_updates); void processSessionUpdate(const LLSD& update); - void setSpeakers(const LLSD& speaker_list); - LLVoiceChannel* getVoiceChannel() { return mVoiceChannel; } EInstantMessage getDialogType() const { return mDialog; } void setDialogType(EInstantMessage dialog) { mDialog = dialog; } @@ -305,7 +302,6 @@ private: LLUUID mSessionUUID; std::string mSessionLabel; - LLVoiceChannel* mVoiceChannel; BOOL mSessionInitialized; LLSD mQueuedMsgsForInit; @@ -346,7 +342,6 @@ private: BOOL mProfileButtonEnabled; BOOL mCallBackEnabled; - LLIMSpeakerMgr* mSpeakers; LLPanelActiveSpeakers* mSpeakerPanel; // Optimization: Don't send "User is typing..." until the diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 3cf78f957b..556eb5ffd7 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -114,10 +114,84 @@ void toast_callback(const LLSD& msg){ LLIMModel::LLIMModel() { - addChangedCallback(toast_callback); addChangedCallback(LLIMFloater::newIMCallback); + addChangedCallback(toast_callback); +} + + +LLIMModel::LLIMSession::LLIMSession( const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id ) +: mSessionID(session_id), + mName(name), + mType(type), + mNumUnread(0), + mOtherParticipantID(other_participant_id), + mVoiceChannel(NULL), + mSpeakers(NULL) +{ + if (IM_NOTHING_SPECIAL == type || IM_SESSION_P2P_INVITE == type) + { + mVoiceChannel = new LLVoiceChannelP2P(session_id, name, other_participant_id); + } + else + { + mVoiceChannel = new LLVoiceChannelGroup(session_id, name); + } + mSpeakers = new LLIMSpeakerMgr(mVoiceChannel); + + // All participants will be added to the list of people we've recently interacted with. + mSpeakers->addListener(&LLRecentPeople::instance(), "add"); +} + +LLIMModel::LLIMSession::~LLIMSession() +{ + delete mSpeakers; + mSpeakers = NULL; + + // End the text IM session if necessary + if(gVoiceClient && mOtherParticipantID.notNull()) + { + switch(mType) + { + case IM_NOTHING_SPECIAL: + case IM_SESSION_P2P_INVITE: + gVoiceClient->endUserIMSession(mOtherParticipantID); + break; + + default: + // Appease the linux compiler + break; + } + } + + // HAVE to do this here -- if it happens in the LLVoiceChannel destructor it will call the wrong version (since the object's partially deconstructed at that point). + mVoiceChannel->deactivate(); + + delete mVoiceChannel; + mVoiceChannel = NULL; } +LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const +{ + return get_if_there(LLIMModel::instance().sSessionsMap, session_id, + (LLIMModel::LLIMSession*) NULL); +} + +void LLIMModel::updateSessionID(const LLUUID& old_session_id, const LLUUID& new_session_id) +{ + if (new_session_id == old_session_id) return; + + LLIMSession* session = findIMSession(old_session_id); + if (session) + { + session->mSessionID = new_session_id; + session->mVoiceChannel->updateSessionID(new_session_id); + + //*TODO set session initialized flag here? (IB) + + sSessionsMap.erase(old_session_id); + sSessionsMap[new_session_id] = session; + } +} void LLIMModel::testMessages() { @@ -153,7 +227,7 @@ bool LLIMModel::newSession(LLUUID session_id, std::string name, EInstantMessage return false; } - LLIMSession* session = new LLIMSession(name, type, other_participant_id); + LLIMSession* session = new LLIMSession(session_id, name, type, other_participant_id); sSessionsMap[session_id] = session; LLIMMgr::getInstance()->notifyObserverSessionAdded(session_id, name, other_participant_id); @@ -170,12 +244,12 @@ bool LLIMModel::clearSession(LLUUID session_id) return true; } +//*TODO remake it, instead of returing the list pass it as as parameter (IB) std::list LLIMModel::getMessages(LLUUID session_id, int start_index) { std::list return_list; - LLIMSession* session = get_if_there(sSessionsMap, session_id, (LLIMSession*)NULL); - + LLIMSession* session = findIMSession(session_id); if (!session) { llwarns << "session " << session_id << "does not exist " << llendl; @@ -202,13 +276,14 @@ std::list LLIMModel::getMessages(LLUUID session_id, int start_index) mChangedSignal(arg); // TODO: in the future is there a more efficient way to return these + //of course there is - return as parameter (IB) return return_list; } bool LLIMModel::addToHistory(LLUUID session_id, std::string from, std::string utf8_text) { - LLIMSession* session = get_if_there(sSessionsMap, session_id, (LLIMSession*)NULL); + LLIMSession* session = findIMSession(session_id); if (!session) { @@ -231,7 +306,7 @@ bool LLIMModel::addToHistory(LLUUID session_id, std::string from, std::string ut bool LLIMModel::addMessage(LLUUID session_id, std::string from, LLUUID from_id, std::string utf8_text) { - LLIMSession* session = get_if_there(sSessionsMap, session_id, (LLIMSession*)NULL); + LLIMSession* session = findIMSession(session_id); if (!session) { @@ -260,9 +335,9 @@ bool LLIMModel::addMessage(LLUUID session_id, std::string from, LLUUID from_id, } -const std::string& LLIMModel::getName(LLUUID session_id) +const std::string& LLIMModel::getName(const LLUUID& session_id) const { - LLIMSession* session = get_if_there(sSessionsMap, session_id, (LLIMSession*)NULL); + LLIMSession* session = findIMSession(session_id); if (!session) { @@ -273,6 +348,66 @@ const std::string& LLIMModel::getName(LLUUID session_id) return session->mName; } +const S32 LLIMModel::getNumUnread(const LLUUID& session_id) const +{ + LLIMSession* session = findIMSession(session_id); + if (!session) + { + llwarns << "session " << session_id << "does not exist " << llendl; + return -1; + } + + return session->mNumUnread; +} + +const LLUUID& LLIMModel::getOtherParticipantID(const LLUUID& session_id) const +{ + LLIMSession* session = findIMSession(session_id); + if (!session) + { + llwarns << "session " << session_id << "does not exist " << llendl; + return LLUUID::null; + } + + return session->mOtherParticipantID; +} + +EInstantMessage LLIMModel::getType(const LLUUID& session_id) const +{ + LLIMSession* session = findIMSession(session_id); + if (!session) + { + llwarns << "session " << session_id << "does not exist " << llendl; + return IM_COUNT; + } + + return session->mType; +} + +LLVoiceChannel* LLIMModel::getVoiceChannel( const LLUUID& session_id ) const +{ + LLIMSession* session = findIMSession(session_id); + if (!session) + { + llwarns << "session " << session_id << "does not exist " << llendl; + return NULL; + } + + return session->mVoiceChannel; +} + +LLIMSpeakerMgr* LLIMModel::getSpeakerManager( const LLUUID& session_id ) const +{ + LLIMSession* session = findIMSession(session_id); + if (!session) + { + llwarns << "session " << session_id << "does not exist " << llendl; + return NULL; + } + + return session->mSpeakers; +} + // TODO get rid of other participant ID void LLIMModel::sendTypingState(LLUUID session_id, LLUUID other_participant_id, BOOL typing) @@ -316,7 +451,7 @@ void LLIMModel::sendLeaveSession(LLUUID session_id, LLUUID other_participant_id) } - +//*TODO update list of messages in a LLIMSession (IB) void LLIMModel::sendMessage(const std::string& utf8_text, const LLUUID& im_session_id, const LLUUID& other_participant_id, @@ -415,9 +550,16 @@ void LLIMModel::sendMessage(const std::string& utf8_text, LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(im_session_id); if (floater) floater->addHistoryLine(history_echo, LLUIColorTable::instance().getColor("IMChatColor"), true, gAgent.getID()); + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(im_session_id); + if (speaker_mgr) + { + speaker_mgr->speakerChatted(gAgentID); + speaker_mgr->setSpeakerTyping(gAgentID, FALSE); + } } // Add the recipient to the recent people list. + //*TODO should be deleted, because speaker manager updates through callback the recent list LLRecentPeople::instance().add(other_participant_id); } @@ -633,10 +775,8 @@ public: { if ( gIMMgr) { - LLFloaterIMPanel* floaterp = - gIMMgr->findFloaterBySession(mSessionID); - - if (floaterp) + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionID); + if (speaker_mgr) { //we've accepted our invitation //and received a list of agents that were @@ -650,15 +790,20 @@ public: //but unfortunately, our base that we are receiving here //may not be the most up to date. It was accurate at //some point in time though. - floaterp->setSpeakers(content); + speaker_mgr->setSpeakers(content); //we now have our base of users in the session //that was accurate at some point, but maybe not now //so now we apply all of the udpates we've received //in case of race conditions - floaterp->updateSpeakersList( - gIMMgr->getPendingAgentListUpdates(mSessionID)); + speaker_mgr->updateSpeakers(gIMMgr->getPendingAgentListUpdates(mSessionID)); + } + + LLFloaterIMPanel* floaterp = + gIMMgr->findFloaterBySession(mSessionID); + if (floaterp) + { if ( mInvitiationType == LLIMMgr::INVITATION_TYPE_VOICE ) { floaterp->requestAutoConnect(); @@ -1104,6 +1249,12 @@ void LLIMMgr::addMessage( //no session ID...compute new one new_session_id = computeSessionID(dialog, other_participant_id); } + + if (!LLIMModel::getInstance()->findIMSession(new_session_id)) + { + LLIMModel::instance().newSession(session_id, session_name, dialog, other_participant_id); + } + floater = findFloaterBySession(new_session_id); if (!floater) { @@ -1169,6 +1320,14 @@ void LLIMMgr::addMessage( else { floater->addHistoryLine(msg, color, true, other_participant_id, from); // Insert linked name to front of message + + //*TODO consider moving that speaker management stuff into model (IB) + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(new_session_id); + if (speaker_mgr) + { + speaker_mgr->speakerChatted(gAgentID); + speaker_mgr->setSpeakerTyping(gAgentID, FALSE); + } } LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg); @@ -1273,11 +1432,10 @@ LLUUID LLIMMgr::addP2PSession(const std::string& name, { LLUUID session_id = addSession(name, IM_NOTHING_SPECIAL, other_participant_id); - LLFloaterIMPanel* floater = findFloaterBySession(session_id); - if(floater) + LLVoiceChannelP2P* voice_channel = (LLVoiceChannelP2P*) LLIMModel::getInstance()->getSpeakerManager(session_id); + if (voice_channel) { - LLVoiceChannelP2P* voice_channelp = (LLVoiceChannelP2P*)floater->getVoiceChannel(); - voice_channelp->setSessionHandle(voice_session_handle, caller_uri); + voice_channel->setSessionHandle(voice_session_handle, caller_uri); } return session_id; @@ -1312,6 +1470,11 @@ LLUUID LLIMMgr::addSession( LLUUID session_id = computeSessionID(dialog,other_participant_id); + if (!LLIMModel::getInstance()->findIMSession(session_id)) + { + LLIMModel::instance().newSession(session_id, name, dialog, other_participant_id); + } + LLFloaterIMPanel* floater = findFloaterBySession(session_id); if(!floater) { @@ -1335,17 +1498,10 @@ LLUUID LLIMMgr::addSession( noteMutedUsers(floater, ids); } } - else - { - // *TODO: Remove this? Otherwise old communicate window opens on - // second initiation of IM session from People panel? - // floater->openFloater(); - } - //mTabContainer->selectTabPanel(panel); floater->setInputFocus(TRUE); LLIMFloater::show(session_id); - notifyObserverSessionAdded(floater->getSessionID(), name, other_participant_id); - return floater->getSessionID(); + + return session_id; } // This removes the panel referenced by the uuid, and then restores @@ -1705,7 +1861,6 @@ LLFloaterIMPanel* LLIMMgr::createFloater( LLTabContainer::eInsertionPoint i_pt = user_initiated ? LLTabContainer::RIGHT_OF_CURRENT : LLTabContainer::END; LLFloaterChatterBox::getInstance()->addFloater(floater, FALSE, i_pt); mFloaters.insert(floater->getHandle()); - LLIMModel::instance().newSession(session_id, session_label, dialog, other_participant_id); return floater; } @@ -1825,24 +1980,25 @@ public: gIMMgr->updateFloaterSessionID( temp_session_id, session_id); + + LLIMModel::getInstance()->updateSessionID(temp_session_id, session_id); + + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id); + if (speaker_mgr) + { + speaker_mgr->setSpeakers(body); + speaker_mgr->updateSpeakers(gIMMgr->getPendingAgentListUpdates(session_id)); + } + LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(session_id); if (floaterp) { - floaterp->setSpeakers(body); - - //apply updates we've possibly received previously - floaterp->updateSpeakersList( - gIMMgr->getPendingAgentListUpdates(session_id)); - if ( body.has("session_info") ) { floaterp->processSessionUpdate(body["session_info"]); } - - //aply updates we've possibly received previously - floaterp->updateSpeakersList( - gIMMgr->getPendingAgentListUpdates(session_id)); } + gIMMgr->clearPendingAgentListUpdates(session_id); } else @@ -1932,15 +2088,15 @@ public: const LLSD& context, const LLSD& input) const { - LLFloaterIMPanel* floaterp = gIMMgr->findFloaterBySession(input["body"]["session_id"].asUUID()); - if (floaterp) + const LLUUID& session_id = input["body"]["session_id"].asUUID(); + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id); + if (speaker_mgr) { - floaterp->updateSpeakersList( - input["body"]); + speaker_mgr->updateSpeakers(input["body"]); } else { - //we don't have a floater yet..something went wrong + //we don't have a speaker manager yet..something went wrong //we are probably receiving an update here before //a start or an acceptance of an invitation. Race condition. gIMMgr->addPendingAgentListUpdates( diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index 219af0705d..9a94d01bb2 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -34,6 +34,8 @@ #define LL_LLIMVIEW_H #include "lldarray.h" +#include "llfloateractivespeakers.h" //for LLIMSpeakerMgr +#include "llimpanel.h" //for voice channels #include "llmodaldialog.h" #include "llinstantmessage.h" #include "lluuid.h" @@ -50,21 +52,40 @@ public: struct LLIMSession { - LLIMSession(std::string name, EInstantMessage type, LLUUID other_participant_id) - :mName(name), mType(type), mNumUnread(0), mOtherParticipantID(other_participant_id) {} - + LLIMSession(const LLUUID& session_id, const std::string& name, + const EInstantMessage& type, const LLUUID& other_participant_id); + virtual ~LLIMSession(); + + LLUUID mSessionID; std::string mName; EInstantMessage mType; LLUUID mOtherParticipantID; S32 mNumUnread; std::list mMsgs; + + LLVoiceChannel* mVoiceChannel; + LLIMSpeakerMgr* mSpeakers; }; LLIMModel(); + //*TODO make it non-static as LLIMMOdel is a singleton (IB) static std::map sSessionsMap; //mapping session_id to session + boost::signals2::signal mChangedSignal; + + /** + * Find an IM Session corresponding to session_id + * Returns NULL if the session does not exist + */ + LLIMSession* findIMSession(const LLUUID& session_id) const; + + /** + * Rebind session data to a new session id. + */ + void updateSessionID(const LLUUID& old_session_id, const LLUUID& new_session_id); + boost::signals2::connection addChangedCallback( boost::function cb ); bool newSession(LLUUID session_id, std::string name, EInstantMessage type, LLUUID other_participant_id); @@ -72,10 +93,42 @@ public: std::list getMessages(LLUUID session_id, int start_index = 0); bool addMessage(LLUUID session_id, std::string from, LLUUID other_participant_id, std::string utf8_text); bool addToHistory(LLUUID session_id, std::string from, std::string utf8_text); - //used to get the name of the session, for use as the title - //currently just the other avatar name - const std::string& getName(LLUUID session_id); - + //used to get the name of the session, for use as the title + //currently just the other avatar name + const std::string& getName(const LLUUID& session_id) const; + + /** + * Get number of unread messages in a session with session_id + * Returns -1 if the session with session_id doesn't exist + */ + const S32 getNumUnread(const LLUUID& session_id) const; + + /** + * Get uuid of other participant in a session with session_id + * Returns LLUUID::null if the session doesn't exist + * + * *TODO what to do with other participants in ad-hoc and group chats? + */ + const LLUUID& getOtherParticipantID(const LLUUID& session_id) const; + + /** + * Get type of a session specified by session_id + * Returns EInstantMessage::IM_COUNT if the session does not exist + */ + EInstantMessage getType(const LLUUID& session_id) const; + + /** + * Get voice channel for the session specified by session_id + * Returns NULL if the session does not exist + */ + LLVoiceChannel* getVoiceChannel(const LLUUID& session_id) const; + + /** + * Get im speaker manager for the session specified by session_id + * Returns NULL if the session does not exist + */ + LLIMSpeakerMgr* getSpeakerManager(const LLUUID& session_id) const; + static void sendLeaveSession(LLUUID session_id, LLUUID other_participant_id); static bool sendStartSession(const LLUUID& temp_session_id, const LLUUID& other_participant_id, const std::vector& ids, EInstantMessage dialog); diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index b53bb586f3..8430937933 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -65,6 +65,7 @@ LLNearbyChat::LLNearbyChat(const LLSD& key) : mChatCaptionPanel(NULL), mChatHistoryEditor(NULL) { + m_isDirty = false; } LLNearbyChat::~LLNearbyChat() @@ -181,7 +182,7 @@ LLColor4 nearbychat_get_text_color(const LLChat& chat) return text_color; } -void nearbychat_add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4& color) +void LLNearbyChat::add_timestamped_line(const LLChat& chat, const LLColor4& color) { std::string line = chat.mText; @@ -194,25 +195,28 @@ void nearbychat_add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, cons bool prepend_newline = true; if (gSavedSettings.getBOOL("ChatShowTimestamps")) { - edit->appendTime(prepend_newline); + mChatHistoryEditor->appendTime(prepend_newline); prepend_newline = false; } // If the msg is from an agent (not yourself though), // extract out the sender name and replace it with the hotlinked name. + + std::string str_URL = chat.mURL; + if (chat.mSourceType == CHAT_SOURCE_AGENT && chat.mFromID != LLUUID::null) { - chat.mURL = llformat("secondlife:///app/agent/%s/about",chat.mFromID.asString().c_str()); + str_URL = llformat("secondlife:///app/agent/%s/about",chat.mFromID.asString().c_str()); } // If the chat line has an associated url, link it up to the name. - if (!chat.mURL.empty() + if (!str_URL.empty() && (line.length() > chat.mFromName.length() && line.find(chat.mFromName,0) == 0)) { std::string start_line = line.substr(0, chat.mFromName.length() + 1); line = line.substr(chat.mFromName.length() + 1); - edit->appendStyledText(start_line, false, prepend_newline, LLStyleMap::instance().lookup(chat.mFromID,chat.mURL)); + mChatHistoryEditor->appendStyledText(start_line, false, prepend_newline, LLStyleMap::instance().lookup(chat.mFromID,str_URL)); prepend_newline = false; } @@ -225,11 +229,9 @@ void nearbychat_add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, cons else if (2 == font_size) font_name = "sansserifbig"; - edit->appendColoredText(line, false, prepend_newline, color, font_name); + mChatHistoryEditor->appendColoredText(line, false, prepend_newline, color, font_name); } - - void LLNearbyChat::addMessage(const LLChat& chat) { LLColor4 color = nearbychat_get_text_color(chat); @@ -254,7 +256,7 @@ void LLNearbyChat::addMessage(const LLChat& chat) mChatHistoryEditor->setParseHighlights(TRUE); if (!chat.mMuted) - nearbychat_add_timestamped_line(mChatHistoryEditor, chat, color); + add_timestamped_line(chat, color); } void LLNearbyChat::onNearbySpeakers() @@ -482,9 +484,16 @@ BOOL LLNearbyChat::handleRightMouseDown(S32 x, S32 y, MASK mask) void LLNearbyChat::onOpen(const LLSD& key ) { - LLNotificationsUI::LLScreenChannel* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); + LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); if(chat_channel) { chat_channel->removeToastsFromChannel(); } } + +void LLNearbyChat::draw () +{ + LLFloater::draw(); +} + + diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h index efa2e479e6..599e6b6859 100644 --- a/indra/newview/llnearbychat.h +++ b/indra/newview/llnearbychat.h @@ -76,7 +76,10 @@ public: virtual void onOpen (const LLSD& key); + virtual void draw (); + private: + void add_timestamped_line(const LLChat& chat, const LLColor4& color); void pinn_panel(); void float_panel(); @@ -86,10 +89,11 @@ private: S32 mStart_X; S32 mStart_Y; - //LLResizeBar* mResizeBar[RESIZE_BAR_COUNT]; LLHandle mPopupMenuHandle; LLPanel* mChatCaptionPanel; LLViewerTextEditor* mChatHistoryEditor; + + bool m_isDirty; }; #endif diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 7eb5d91e53..eb42e83994 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -41,30 +41,227 @@ #include "llviewercontrol.h" #include "llfloaterreg.h"//for LLFloaterReg::getTypedInstance +#include "llviewerwindow.h"//for screen channel position //add LLNearbyChatHandler to LLNotificationsUI namespace -namespace LLNotificationsUI{ +using namespace LLNotificationsUI; +//----------------------------------------------------------------------------------------------- +//LLNearbyChatScreenChannel +//----------------------------------------------------------------------------------------------- +LLToastPanelBase* createToastPanel() +{ + LLNearbyChatToastPanel* item = LLNearbyChatToastPanel::createInstance(); + static S32 chat_item_width = 304; + item->setWidth(chat_item_width); + return item; +} + + +class LLNearbyChatScreenChannel: public LLScreenChannelBase +{ +public: + LLNearbyChatScreenChannel(const LLUUID& id):LLScreenChannelBase(id) { mActiveMessages = 0;}; + void init (S32 channel_left, S32 channel_right); + + void addNotification (LLSD& notification); + void arrangeToasts (); + void showToastsBottom (); + + typedef boost::function create_toast_panel_callback_t; + void setCreatePanelCallback(create_toast_panel_callback_t value) { m_create_toast_panel_callback_t = value;} + + void onToastDestroyed (LLToast* toast); + void onToastFade (LLToast* toast); + + // hide all toasts from screen, but not remove them from a channel + virtual void hideToastsFromScreen() + { + }; + // removes all toasts from a channel + virtual void removeToastsFromChannel() + { + for(std::vector::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it) + { + LLToast* toast = (*it); + toast->setVisible(FALSE); + toast->stopTimer(); + m_toast_pool.push_back(toast); + + } + m_active_toasts.clear(); + }; + +protected: + void createOverflowToast(S32 bottom, F32 timer); + + create_toast_panel_callback_t m_create_toast_panel_callback_t; + + bool createPoolToast(); + + std::vector m_active_toasts; + std::list m_toast_pool; + + S32 mActiveMessages; +}; + +void LLNearbyChatScreenChannel::init(S32 channel_left, S32 channel_right) +{ + S32 channel_top = gViewerWindow->getWorldViewRect().getHeight(); + S32 channel_bottom = gViewerWindow->getWorldViewRect().mBottom; + setRect(LLRect(channel_left, channel_top, channel_right, channel_bottom)); + setVisible(TRUE); +} + + +void LLNearbyChatScreenChannel::createOverflowToast(S32 bottom, F32 timer) +{ + //we don't need overflow toast in nearby chat +} + +void LLNearbyChatScreenChannel::onToastDestroyed(LLToast* toast) +{ +} + +void LLNearbyChatScreenChannel::onToastFade(LLToast* toast) +{ + //fade mean we put toast to toast pool + if(!toast) + return; + m_toast_pool.push_back(toast); + + std::vector::iterator pos = std::find(m_active_toasts.begin(),m_active_toasts.end(),toast); + if(pos!=m_active_toasts.end()) + m_active_toasts.erase(pos); + + arrangeToasts(); +} + + +bool LLNearbyChatScreenChannel::createPoolToast() +{ + LLToastPanelBase* panel= m_create_toast_panel_callback_t(); + if(!panel) + return false; + + LLToast::Params p; + p.panel = panel; + + LLToast* toast = new LLToast(p); + + + toast->setOnFadeCallback(boost::bind(&LLNearbyChatScreenChannel::onToastFade, this, _1)); + toast->setOnToastDestroyedCallback(boost::bind(&LLNearbyChatScreenChannel::onToastDestroyed, this, _1)); + + m_toast_pool.push_back(toast); + return true; +} + +void LLNearbyChatScreenChannel::addNotification(LLSD& notification) +{ + //look in pool. if there is any message + + + if(m_toast_pool.empty()) + { + //"pool" is empty - create one more panel + if(!createPoolToast())//created toast will go to pool. so next call will find it + return; + addNotification(notification); + return; + } + + //take 1st element from pool, (re)initialize it, put it in active toasts + + LLToast* toast = m_toast_pool.back(); + + m_toast_pool.pop_back(); + + + LLToastPanelBase* panel = dynamic_cast(toast->getPanel()); + if(!panel) + return; + panel->init(notification); + + toast->reshapeToPanel(); + toast->resetTimer(); + + m_active_toasts.insert(m_active_toasts.begin(),toast); + + arrangeToasts(); +} + +void LLNearbyChatScreenChannel::arrangeToasts() +{ + if(m_active_toasts.size() == 0 || mIsHovering) + return; + + hideToastsFromScreen(); + + showToastsBottom(); +} + +void LLNearbyChatScreenChannel::showToastsBottom() +{ + LLRect rect = getRect(); + + LLRect toast_rect; + S32 bottom = getRect().mBottom; + + for(std::vector::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it) + { + LLToast* toast = (*it); + toast_rect = toast->getRect(); + toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastMargin"), toast_rect.getWidth() ,toast_rect.getHeight()); + + toast->setRect(toast_rect); + + if(toast->getRect().mTop > getRect().getHeight()) + { + while(it!=m_active_toasts.end()) + { + (*it)->setVisible(FALSE); + (*it)->stopTimer(); + m_toast_pool.push_back(*it); + it=m_active_toasts.erase(it); + } + break; + } + toast->setVisible(TRUE); + bottom = toast->getRect().mTop; + } +} + + +//----------------------------------------------------------------------------------------------- +//LLNearbyChatHandler +//----------------------------------------------------------------------------------------------- LLNearbyChatHandler::LLNearbyChatHandler(e_notification_type type, const LLSD& id) { mType = type; - LLChannelManager::Params p; - p.id = LLUUID(gSavedSettings.getString("NearByChatChannelUUID")); // Getting a Channel for our notifications - mChannel = LLChannelManager::getInstance()->getChannel(p); + LLNearbyChatScreenChannel* channel = new LLNearbyChatScreenChannel(LLUUID(gSavedSettings.getString("NearByChatChannelUUID"))); + + LLNearbyChatScreenChannel::create_toast_panel_callback_t callback = createToastPanel; + + channel->setCreatePanelCallback(callback); + + mChannel = LLChannelManager::getInstance()->addChannel(channel); mChannel->setOverflowFormatString("You have %d unread nearby chat messages"); } + LLNearbyChatHandler::~LLNearbyChatHandler() { } + void LLNearbyChatHandler::initChannel() { LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat", LLSD()); S32 channel_right_bound = nearby_chat->getRect().mRight; - S32 channel_width = nearby_chat->getRect().mRight - 16; //HACK: 16 - ? + S32 channel_width = nearby_chat->getRect().mRight; mChannel->init(channel_right_bound - channel_width, channel_right_bound); } @@ -77,41 +274,42 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg) if(chat_msg.mText.empty()) return;//don't process empty messages - + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat", LLSD()); nearby_chat->addMessage(chat_msg); if(nearby_chat->getVisible()) return;//no need in toast if chat is visible - + // arrange a channel on a screen if(!mChannel->getVisible()) { initChannel(); } - + LLUUID id; id.generate(); - LLChatItemCtrl* item = LLChatItemCtrl::createInstance(); - - item->setMessage(chat_msg); - //static S32 chat_item_width = nearby_chat->getRect().getWidth() - 16; - static S32 chat_item_width = 304; - item->setWidth(chat_item_width); - item->setHeaderVisibility((EShowItemHeader)gSavedSettings.getS32("nearbychat_showicons_and_names")); + LLNearbyChatScreenChannel* channel = dynamic_cast(mChannel); - item->setVisible(true); - LLToast::Params p; - p.notif_id = id; - p.panel = item; - p.on_delete_toast = boost::bind(&LLNearbyChatHandler::onDeleteToast, this, _1); - mChannel->addToast(p); + if(channel) + { + LLSD notification; + notification["id"] = id; + notification["message"] = chat_msg.mText; + notification["from"] = chat_msg.mFromName; + notification["from_id"] = chat_msg.mFromID; + notification["time"] = chat_msg.mTime; + notification["source"] = (S32)chat_msg.mSourceType; + + channel->addNotification(notification); + } + } void LLNearbyChatHandler::onDeleteToast(LLToast* toast) { } -} + diff --git a/indra/newview/llnotificationalerthandler.cpp b/indra/newview/llnotificationalerthandler.cpp index 3893eaa0d4..755f1235a6 100644 --- a/indra/newview/llnotificationalerthandler.cpp +++ b/indra/newview/llnotificationalerthandler.cpp @@ -100,16 +100,23 @@ bool LLAlertHandler::processNotification(const LLSD& notify) p.can_fade = false; p.is_modal = mIsModal; p.on_delete_toast = boost::bind(&LLAlertHandler::onDeleteToast, this, _1); - mChannel->addToast(p); + + LLScreenChannel* channel = dynamic_cast(mChannel); + if(channel) + channel->addToast(p); } else if (notify["sigtype"].asString() == "change") { LLToastAlertPanel* alert_dialog = new LLToastAlertPanel(notification, mIsModal); - mChannel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog); + LLScreenChannel* channel = dynamic_cast(mChannel); + if(channel) + channel->modifyToastByNotificationID(notification->getID(), (LLToastPanel*)alert_dialog); } else { - mChannel->killToastByNotificationID(notification->getID()); + LLScreenChannel* channel = dynamic_cast(mChannel); + if(channel) + channel->killToastByNotificationID(notification->getID()); } return true; } diff --git a/indra/newview/llnotificationgrouphandler.cpp b/indra/newview/llnotificationgrouphandler.cpp index c488d37ea5..ffa92b543c 100644 --- a/indra/newview/llnotificationgrouphandler.cpp +++ b/indra/newview/llnotificationgrouphandler.cpp @@ -89,7 +89,10 @@ bool LLGroupHandler::processNotification(const LLSD& notify) p.notification = notification; p.panel = notify_box; p.on_delete_toast = boost::bind(&LLGroupHandler::onDeleteToast, this, _1); - mChannel->addToast(p); + + LLScreenChannel* channel = dynamic_cast(mChannel); + if(channel) + channel->addToast(p); // send a signal to the counter manager mNewNotificationSignal(); diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 90ff5fbaac..cd4e640ec4 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -104,8 +104,8 @@ protected: // at the moment, when a handlers creates a channel. virtual void initChannel()=0; - LLScreenChannel* mChannel; - e_notification_type mType; + LLScreenChannelBase* mChannel; + e_notification_type mType; }; diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 72855ac0fd..070af432d6 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -48,7 +48,11 @@ LLScriptHandler::LLScriptHandler(e_notification_type type, const LLSD& id) // Getting a Channel for our notifications mChannel = LLChannelManager::getInstance()->createNotificationChannel(); mChannel->setControlHovering(true); - mChannel->setOnRejectToastCallback(boost::bind(&LLScriptHandler::onRejectToast, this, _1)); + + LLScreenChannel* channel = dynamic_cast(mChannel); + if(channel) + channel->setOnRejectToastCallback(boost::bind(&LLScriptHandler::onRejectToast, this, _1)); + } //-------------------------------------------------------------------------- @@ -92,7 +96,10 @@ bool LLScriptHandler::processNotification(const LLSD& notify) p.notification = notification; p.panel = notify_box; p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1); - mChannel->addToast(p); + + LLScreenChannel* channel = dynamic_cast(mChannel); + if(channel) + channel->addToast(p); // send a signal to the counter manager mNewNotificationSignal(); diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index 740acb6365..5186a93569 100644 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -93,8 +93,9 @@ bool LLTipHandler::processNotification(const LLSD& notify) p.is_tip = true; p.can_be_stored = false; - mChannel->addToast(p); - + LLScreenChannel* channel = dynamic_cast(mChannel); + if(channel) + channel->addToast(p); } else if (notify["sigtype"].asString() == "delete") { diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 649697e091..7ccff73080 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -313,7 +313,7 @@ void LLPanelProfileTab::scrollToTop() { LLScrollContainer* scrollContainer = findChild("profile_scroll"); if (scrollContainer) - scrollContainer->goToTop(); + scrollContainer->goToTop(); } ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index 490c845c94..2b584910a3 100644 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -195,7 +195,7 @@ BOOL LLPanelGroup::postBuild() if(panel_land) mTabs.push_back(panel_land); if(panel_general) - panel_general->setupCtrls(this); + panel_general->setupCtrls(this); return TRUE; } @@ -206,8 +206,8 @@ void LLPanelGroup::reposButton(const std::string& name) if(!button) return; LLRect btn_rect = button->getRect(); - btn_rect.setLeftTopAndSize( btn_rect.mLeft, btn_rect.getHeight() + 2, btn_rect.getWidth(), btn_rect.getHeight()); - button->setRect(btn_rect); + btn_rect.setLeftTopAndSize( btn_rect.mLeft, btn_rect.getHeight() + 2, btn_rect.getWidth(), btn_rect.getHeight()); + button->setRect(btn_rect); } void LLPanelGroup::reshape(S32 width, S32 height, BOOL called_from_parent ) @@ -235,7 +235,14 @@ void LLPanelGroup::onBtnCreate() if(!panel_general) return; std::string apply_mesg; - panel_general->apply(apply_mesg);//yes yes you need to call apply to create... + if(panel_general->apply(apply_mesg))//yes yes you need to call apply to create... + return; + if ( !apply_mesg.empty() ) + { + LLSD args; + args["MESSAGE"] = apply_mesg; + LLNotifications::instance().add("GenericAlert", args); + } } void LLPanelGroup::onBtnRefresh(void* user_data) diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index 5eb7b8f5f5..2e1d971995 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -835,6 +835,7 @@ void LLPanelGroupGeneral::reset() { std::string empty_str = ""; mEditCharter->setText(empty_str); + mGroupNameEditor->setText(empty_str); } { @@ -850,6 +851,7 @@ void LLPanelGroupGeneral::reset() { mComboMature->setEnabled(true); mComboMature->setVisible( !gAgent.isTeen() ); + mComboMature->selectFirstItem(); } diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 6a41b6feb9..b2a0a01005 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -60,11 +60,8 @@ #include "llvoiceclient.h" #include "llworld.h" -using namespace LLOldEvents; - #define FRIEND_LIST_UPDATE_TIMEOUT 0.5 #define NEARBY_LIST_UPDATE_INTERVAL 1 -#define RECENT_LIST_UPDATE_DELAY 1 static const std::string NEARBY_TAB_NAME = "nearby_panel"; static const std::string FRIENDS_TAB_NAME = "friends_panel"; @@ -102,7 +99,7 @@ static LLRegisterPanelClassWrapper t_people("panel_people"); class LLPanelPeople::Updater { public: - typedef boost::function callback_t; + typedef boost::function callback_t; Updater(callback_t cb) : mCallback(cb) { @@ -112,16 +109,6 @@ public: { } - /** - * Force the list updates. - * - * This may start repeated updates until all names are complete. - */ - virtual void forceUpdate() - { - updateList(); - } - /** * Activate/deactivate updater. * @@ -130,9 +117,9 @@ public: virtual void setActive(bool) {} protected: - bool updateList(U32 mask = 0) + void updateList() { - return mCallback(mask); + mCallback(); } callback_t mCallback; @@ -147,6 +134,11 @@ public: { mEventTimer.stop(); } + + virtual BOOL tick() // from LLEventTimer + { + return FALSE; + } }; /** @@ -178,13 +170,6 @@ public: LLAvatarTracker::instance().removeObserver(this); } - /*virtual*/ void forceUpdate() - { - // Perform updates until all names are loaded. - if (!updateList(LLFriendObserver::ADD)) - changed(LLFriendObserver::ADD); - } - /*virtual*/ void changed(U32 mask) { // events can arrive quickly in bulk - we need not process EVERY one of them - @@ -198,12 +183,12 @@ public: /*virtual*/ BOOL tick() { - if (updateList(mMask)) - { - // Got all names, stop updates. - mEventTimer.stop(); - mMask = 0; - } + if (mMask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE)) + updateList(); + + // Stop updates. + mEventTimer.stop(); + mMask = 0; return FALSE; } @@ -329,68 +314,9 @@ class LLRecentListUpdater : public LLAvatarListUpdater, public boost::signals2:: public: LLRecentListUpdater(callback_t cb) - : LLAvatarListUpdater(cb, RECENT_LIST_UPDATE_DELAY) - { - LLRecentPeople::instance().setChangedCallback(boost::bind(&LLRecentListUpdater::onRecentPeopleChanged, this)); - } - -private: - /*virtual*/ void forceUpdate() - { - onRecentPeopleChanged(); - } - - /*virtual*/ BOOL tick() - { - // Update the list until we get all the names. - if (updateList()) - { - // Got all names, stop updates. - mEventTimer.stop(); - } - - return FALSE; - } - - void onRecentPeopleChanged() - { - if (!updateList()) - { - // Some names are incomplete, schedule another update. - mEventTimer.start(); - } - } -}; - -/** - * Updates the group list on events from LLAgent. - */ -class LLGroupListUpdater : public LLPanelPeople::Updater, public LLSimpleListener -{ - LOG_CLASS(LLGroupListUpdater); - -public: - LLGroupListUpdater(callback_t cb) - : LLPanelPeople::Updater(cb) - { - gAgent.addListener(this, "new group"); - } - - ~LLGroupListUpdater() + : LLAvatarListUpdater(cb, 0) { - gAgent.removeListener(this); - } - - /*virtual*/ bool handleEvent(LLPointer event, const LLSD& userdata) - { - // Why is "new group" sufficient? - if (event->desc() == "new group") - { - updateList(); - return true; - } - - return false; + LLRecentPeople::instance().setChangedCallback(boost::bind(&LLRecentListUpdater::updateList, this)); } }; @@ -404,12 +330,12 @@ LLPanelPeople::LLPanelPeople() mOnlineFriendList(NULL), mAllFriendList(NULL), mNearbyList(NULL), - mRecentList(NULL) + mRecentList(NULL), + mGroupList(NULL) { - mFriendListUpdater = new LLFriendListUpdater(boost::bind(&LLPanelPeople::onFriendListUpdate,this, _1)); + mFriendListUpdater = new LLFriendListUpdater(boost::bind(&LLPanelPeople::updateFriendList, this)); mNearbyListUpdater = new LLNearbyListUpdater(boost::bind(&LLPanelPeople::updateNearbyList, this)); mRecentListUpdater = new LLRecentListUpdater(boost::bind(&LLPanelPeople::updateRecentList, this)); - mGroupListUpdater = new LLGroupListUpdater (boost::bind(&LLPanelPeople::updateGroupList, this)); } LLPanelPeople::~LLPanelPeople() @@ -417,7 +343,6 @@ LLPanelPeople::~LLPanelPeople() delete mNearbyListUpdater; delete mFriendListUpdater; delete mRecentListUpdater; - delete mGroupListUpdater; LLView::deleteViewByHandle(mGroupPlusMenuHandle); LLView::deleteViewByHandle(mNearbyViewSortMenuHandle); @@ -512,7 +437,7 @@ BOOL LLPanelPeople::postBuild() buttonSetAction("share_btn", boost::bind(&LLPanelPeople::onShareButtonClicked, this)); getChild(NEARBY_TAB_NAME)->childSetAction("nearby_view_sort_btn",boost::bind(&LLPanelPeople::onNearbyViewSortButtonClicked, this)); - getChild(RECENT_TAB_NAME)->childSetAction("recent_viewsort_btn",boost::bind(&LLPanelPeople::onRecentViewSortButtonClicked, this)); + getChild(RECENT_TAB_NAME)->childSetAction("recent_viewsort_btn",boost::bind(&LLPanelPeople::onRecentViewSortButtonClicked, this)); getChild(FRIENDS_TAB_NAME)->childSetAction("friends_viewsort_btn",boost::bind(&LLPanelPeople::onFriendsViewSortButtonClicked, this)); getChild(GROUP_TAB_NAME)->childSetAction("groups_viewsort_btn",boost::bind(&LLPanelPeople::onGroupsViewSortButtonClicked, this)); @@ -547,137 +472,71 @@ BOOL LLPanelPeople::postBuild() if(recent_view_sort) mRecentViewSortMenuHandle = recent_view_sort->getHandle(); - - - // Perform initial update. - mFriendListUpdater->forceUpdate(); - mNearbyListUpdater->forceUpdate(); - mGroupListUpdater->forceUpdate(); - mRecentListUpdater->forceUpdate(); - // call this method in case some list is empty and buttons can be in inconsistent state updateButtons(); return TRUE; } -void LLPanelPeople::applyFilterToTab(const std::string& tab_name) -{ - if (tab_name == FRIENDS_TAB_NAME) // this tab has two lists - filterFriendList(); - else if (tab_name == NEARBY_TAB_NAME) - filterNearbyList(); - else if (tab_name == RECENT_TAB_NAME) - filterRecentList(); - else if (tab_name == GROUP_TAB_NAME) - updateGroupList(); -} - -bool LLPanelPeople::updateFriendList(U32 changed_mask) +void LLPanelPeople::updateFriendList() { - // Refresh names. - if (changed_mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE)) - { - // get all buddies we know about - const LLAvatarTracker& av_tracker = LLAvatarTracker::instance(); - LLAvatarTracker::buddy_map_t all_buddies; - av_tracker.copyBuddyList(all_buddies); - - // *TODO: it's suboptimal to rebuild the whole lists on online status change. + if (!mOnlineFriendList || !mAllFriendList) + return; - // save them to the online and all friends vectors - mOnlineFriendVec.clear(); - mAllFriendVec.clear(); + // get all buddies we know about + const LLAvatarTracker& av_tracker = LLAvatarTracker::instance(); + LLAvatarTracker::buddy_map_t all_buddies; + av_tracker.copyBuddyList(all_buddies); - LLFriendCardsManager::folderid_buddies_map_t listMap; + // save them to the online and all friends vectors + LLAvatarList::uuid_vector_t& online_friendsp = mOnlineFriendList->getIDs(); + LLAvatarList::uuid_vector_t& all_friendsp = mAllFriendList->getIDs(); - // *NOTE: For now collectFriendsLists returns data only for Friends/All folder. EXT-694. - LLFriendCardsManager::instance().collectFriendsLists(listMap); - if (listMap.size() > 0) - { - lldebugs << "Friends Cards were found, count: " << listMap.begin()->second.size() << llendl; - mAllFriendVec = listMap.begin()->second; - } - else - { - lldebugs << "Friends Cards were not found" << llendl; - } + all_friendsp.clear(); + online_friendsp.clear(); - LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin(); - for (; buddy_it != all_buddies.end(); ++buddy_it) - { - LLUUID buddy_id = buddy_it->first; - if (av_tracker.isBuddyOnline(buddy_id)) - mOnlineFriendVec.push_back(buddy_id); - } + LLFriendCardsManager::folderid_buddies_map_t listMap; - return filterFriendList(); + // *NOTE: For now collectFriendsLists returns data only for Friends/All folder. EXT-694. + LLFriendCardsManager::instance().collectFriendsLists(listMap); + if (listMap.size() > 0) + { + lldebugs << "Friends Cards were found, count: " << listMap.begin()->second.size() << llendl; + all_friendsp = listMap.begin()->second; + } + else + { + lldebugs << "Friends Cards were not found" << llendl; } - return true; -} - -bool LLPanelPeople::updateNearbyList() -{ - LLWorld::getInstance()->getAvatars(&mNearbyVec, NULL, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange")); - filterNearbyList(); - - return true; -} - -bool LLPanelPeople::updateRecentList() -{ - LLRecentPeople::instance().get(mRecentVec); - filterRecentList(); - - return true; -} - -bool LLPanelPeople::updateGroupList() -{ - if (!mGroupList) - return true; // there's no point in further updates + LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin(); + for (; buddy_it != all_buddies.end(); ++buddy_it) + { + LLUUID buddy_id = buddy_it->first; + if (av_tracker.isBuddyOnline(buddy_id)) + online_friendsp.push_back(buddy_id); + } - bool have_names = mGroupList->update(mFilterSubString); - updateButtons(); - return have_names; + mOnlineFriendList->setDirty(); + mAllFriendList->setDirty(); } -bool LLPanelPeople::filterFriendList() +void LLPanelPeople::updateNearbyList() { - if (!mOnlineFriendList || !mAllFriendList) - return true; // there's no point in further updates - - // We must always update Friends list to clear the latest removed friend. - bool have_names = - mOnlineFriendList->update(mOnlineFriendVec, mFilterSubString) & - mAllFriendList->update(mAllFriendVec, mFilterSubString); - - - updateButtons(); - return have_names; -} + if (!mNearbyList) + return; -bool LLPanelPeople::filterNearbyList() -{ - bool have_names = mNearbyList->update(mNearbyVec, mFilterSubString); - updateButtons(); - return have_names; + LLWorld::getInstance()->getAvatars(&mNearbyList->getIDs(), NULL, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange")); + mNearbyList->setDirty(); } -bool LLPanelPeople::filterRecentList() +void LLPanelPeople::updateRecentList() { if (!mRecentList) - return true; - - if (mRecentVec.size() > 0) - { - bool updated = mRecentList->update(mRecentVec, mFilterSubString); - updateButtons(); - return updated; - } + return; - return true; + LLRecentPeople::instance().get(mRecentList->getIDs()); + mRecentList->setDirty(); } void LLPanelPeople::buttonSetVisible(std::string btn_name, BOOL visible) @@ -846,16 +705,19 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string) LLStringUtil::toUpper(mFilterSubString); LLStringUtil::trimHead(mFilterSubString); - // Apply new filter to current tab. - applyFilterToTab(getActiveTabName()); + // Apply new filter. + mNearbyList->setNameFilter(mFilterSubString); + mOnlineFriendList->setNameFilter(mFilterSubString); + mAllFriendList->setNameFilter(mFilterSubString); + mRecentList->setNameFilter(mFilterSubString); + mGroupList->setNameFilter(mFilterSubString); } void LLPanelPeople::onTabSelected(const LLSD& param) { std::string tab_name = getChild(param.asString())->getName(); mNearbyListUpdater->setActive(tab_name == NEARBY_TAB_NAME); - applyFilterToTab(tab_name); - // No need to call updateButtons() because applyFilterToTab() does that. + updateButtons(); if (GROUP_TAB_NAME == tab_name) mFilterEditor->setLabel(getString("groups_filter_label")); @@ -960,17 +822,6 @@ void LLPanelPeople::onAvatarPicked( LLAvatarActions::requestFriendshipDialog(ids[0], names[0]); } -bool LLPanelPeople::onFriendListUpdate(U32 changed_mask) -{ - bool have_names = updateFriendList(changed_mask); - - // Update online status in the Recent tab. - // *TODO: isn't it too much to update the whole list? -// updateRecentList(); // mantipov: seems online status should be supported by LLAvatarListItem itself. - - return have_names; -} - void LLPanelPeople::onGroupPlusButtonClicked() { LLMenuGL* plus_menu = (LLMenuGL*)mGroupPlusMenuHandle.get(); diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 8cd3cc7feb..de27814388 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -58,15 +58,10 @@ public: private: // methods indirectly called by the updaters - bool updateFriendList(U32 changed_mask); - bool updateNearbyList(); - bool updateRecentList(); - bool updateGroupList(); - - bool filterFriendList(); - bool filterNearbyList(); - bool filterRecentList(); - void applyFilterToTab(const std::string& tab_name); + void updateFriendList(); + void updateNearbyList(); + void updateRecentList(); + void updateButtons(); const std::string& getActiveTabName() const; LLUUID getCurrentItemID() const; @@ -110,7 +105,6 @@ private: void onRecentViewSortMenuItemClicked(const LLSD& userdata); // misc callbacks - bool onFriendListUpdate(U32 changed_mask); static void onAvatarPicked( const std::vector& names, const std::vector& ids, @@ -135,21 +129,8 @@ private: Updater* mFriendListUpdater; Updater* mNearbyListUpdater; Updater* mRecentListUpdater; - Updater* mGroupListUpdater; std::string mFilterSubString; - - // The vectors below contain up-to date avatar lists - // for the corresponding tabs. - // When the user enters a filter, it gets applied - // to all the vectors and the result is shown in the tabs. - // We don't need to have such a vector for the groups tab - // since re-fetching the groups list is always fast. - typedef std::vector uuid_vector_t; - uuid_vector_t mNearbyVec; - uuid_vector_t mOnlineFriendVec; - uuid_vector_t mAllFriendVec; - uuid_vector_t mRecentVec; }; #endif //LL_LLPANELPEOPLE_H diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp index 42185d28e5..5df3d4f1d6 100644 --- a/indra/newview/llpanelpick.cpp +++ b/indra/newview/llpanelpick.cpp @@ -39,8 +39,10 @@ #include "message.h" #include "llagent.h" #include "llbutton.h" +#include "lllineeditor.h" #include "llparcel.h" #include "llviewerparcelmgr.h" +#include "lltexteditor.h" #include "lltexturectrl.h" #include "lluiconstants.h" #include "llworldmap.h" @@ -73,7 +75,8 @@ LLPanelPick::LLPanelPick(BOOL edit_mode/* = FALSE */) mPickId(LLUUID::null), mCreatorId(LLUUID::null), mDataReceived(FALSE), - mIsPickNew(false) + mIsPickNew(false), + mLocationChanged(false) { if (edit_mode) { @@ -123,6 +126,16 @@ BOOL LLPanelPick::postBuild() if (mEditMode) { + enableSaveButton(FALSE); + + mSnapshotCtrl->setOnSelectCallback(boost::bind(&LLPanelPick::onPickChanged, this, _1)); + + LLLineEditor* line_edit = getChild("pick_name"); + line_edit->setKeystrokeCallback(boost::bind(&LLPanelPick::onPickChanged, this, _1), NULL); + + LLTextEditor* text_edit = getChild("pick_desc"); + text_edit->setKeystrokeCallback(boost::bind(&LLPanelPick::onPickChanged, this, _1)); + childSetAction("cancel_btn", boost::bind(&LLPanelPick::onClickCancel, this)); childSetAction("set_to_curr_location_btn", boost::bind(&LLPanelPick::onClickSet, this)); childSetAction(XML_BTN_SAVE, boost::bind(&LLPanelPick::onClickSave, this)); @@ -287,6 +300,26 @@ void LLPanelPick::setEditMode( BOOL edit_mode ) updateButtons(); } +void LLPanelPick::onPickChanged(LLUICtrl* ctrl) +{ + if(mLocationChanged) + { + // Pick was enabled in onClickSet + return; + } + + if( mSnapshotCtrl->isDirty() + || getChild("pick_name")->isDirty() + || getChild("pick_desc")->isDirty() ) + { + enableSaveButton(TRUE); + } + else + { + enableSaveButton(FALSE); + } +} + ////////////////////////////////////////////////////////////////////////// // PROTECTED AREA ////////////////////////////////////////////////////////////////////////// @@ -466,6 +499,9 @@ void LLPanelPick::onClickSet() mSimName = parcel->getName(); } setPickLocation(createLocationText(std::string(""), SET_LOCATION_NOTICE, mSimName, mPosGlobal)); + + mLocationChanged = true; + enableSaveButton(TRUE); } // static @@ -552,3 +588,12 @@ void LLPanelPick::processParcelInfo(const LLParcelData& parcel_data) //*NOTE we don't removeObserver(...) ourselves cause LLRemoveParcelProcessor does it for us } + +void LLPanelPick::enableSaveButton(bool enable) +{ + if(!mEditMode) + { + return; + } + childSetEnabled(XML_BTN_SAVE, enable); +} diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h index 7ce58b59af..82cba72bc4 100644 --- a/indra/newview/llpanelpick.h +++ b/indra/newview/llpanelpick.h @@ -74,6 +74,8 @@ public: // switches the panel to either View or Edit mode void setEditMode(BOOL edit_mode); + void onPickChanged(LLUICtrl* ctrl); + // because this panel works in two modes (edit/view) we are // free from managing two panel for editing and viewing picks and so // are free from controlling switching between them in the parent panel (e.g. Me Profile) @@ -128,6 +130,8 @@ protected: void onClickSave(); void onClickCancel(); + void enableSaveButton(bool enable); + protected: BOOL mEditMode; LLTextureCtrl* mSnapshotCtrl; @@ -146,6 +150,7 @@ protected: std::string mLocation; commit_callback_t mBackCb; + bool mLocationChanged; }; #endif // LL_LLPANELPICK_H diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index 93317e613f..e74afba25a 100644 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -126,8 +126,7 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type) mPicksList->addItem(picture, pick_value); picture->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickItem, this, _1)); - picture->setRightMouseDownCallback(boost::bind(&LLPanelPicks::onRightMouseDownItem, this, _1, _2, _3, _4)); - picture->setRightMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this)); + picture->setRightMouseUpCallback(boost::bind(&LLPanelPicks::onRightMouseUpItem, this, _1, _2, _3, _4)); picture->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this)); } @@ -260,8 +259,10 @@ void LLPanelPicks::onClickMap() } -void LLPanelPicks::onRightMouseDownItem(LLUICtrl* item, S32 x, S32 y, MASK mask) +void LLPanelPicks::onRightMouseUpItem(LLUICtrl* item, S32 x, S32 y, MASK mask) { + updateButtons(); + if (mPopupMenu) { mPopupMenu->buildDrawLabels(); diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h index 27a21305b3..7ebdc3089c 100644 --- a/indra/newview/llpanelpicks.h +++ b/indra/newview/llpanelpicks.h @@ -100,7 +100,7 @@ private: void updateButtons(); virtual void onDoubleClickItem(LLUICtrl* item); - virtual void onRightMouseDownItem(LLUICtrl* item, S32 x, S32 y, MASK mask); + virtual void onRightMouseUpItem(LLUICtrl* item, S32 x, S32 y, MASK mask); LLPanelProfile* getProfilePanel(); diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 4e070df7eb..80ecc95afb 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -337,7 +337,7 @@ void LLPanelPlaces::onFilterEdit(const std::string& search_string) LLStringUtil::trimHead(mFilterSubString); if (mActivePanel) - mActivePanel->onSearchEdit(mFilterSubString); + mActivePanel->onSearchEdit(mFilterSubString); } } @@ -386,7 +386,7 @@ void LLPanelPlaces::onTeleportButtonClicked() else { if (mActivePanel) - mActivePanel->onTeleport(); + mActivePanel->onTeleport(); } } @@ -432,7 +432,7 @@ void LLPanelPlaces::onShowOnMapButtonClicked() else { if (mActivePanel) - mActivePanel->onShowOnMap(); + mActivePanel->onShowOnMap(); } } @@ -510,7 +510,7 @@ void LLPanelPlaces::onOverflowMenuItemClicked(const LLSD& param) addChild(mPickPanel); mPickPanel->setExitCallback(boost::bind(&LLPanelPlaces::togglePickPanel, this, FALSE)); - } + } togglePickPanel(TRUE); @@ -733,7 +733,7 @@ void LLPanelPlaces::updateVerbs() else { if (mActivePanel) - mActivePanel->updateVerbs(); + mActivePanel->updateVerbs(); } } diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index f6672d9c8b..32cccc4ac0 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -306,12 +306,12 @@ void LLTeleportHistoryPanel::showTeleportHistory() if (curr_tab <= tabs_cnt - 4) { - curr_date.secondsSinceEpoch(curr_date.secondsSinceEpoch() - seconds_in_day); + curr_date.secondsSinceEpoch(curr_date.secondsSinceEpoch() - seconds_in_day); } else if (curr_tab == tabs_cnt - 3) // 6 day and older, low boundary is 1 month { curr_date = LLDate::now(); - curr_date.split(&curr_year, &curr_month, &curr_day); + curr_date.split(&curr_year, &curr_month, &curr_day); curr_month--; if (0 == curr_month) { @@ -376,7 +376,7 @@ void LLTeleportHistoryPanel::handleItemSelect(LLFlatListView* selected) S32 tabs_cnt = mItemContainers.size(); for (S32 n = 0; n < tabs_cnt; n++) - { + { LLAccordionCtrlTab* tab = mItemContainers.get(n); if (!tab->getVisible()) @@ -390,7 +390,7 @@ void LLTeleportHistoryPanel::handleItemSelect(LLFlatListView* selected) continue; flv->resetSelection(true); - } + } updateVerbs(); } diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 082bba027f..06bdf64b19 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -55,36 +55,30 @@ using namespace LLNotificationsUI; bool LLScreenChannel::mWasStartUpToastShown = false; //-------------------------------------------------------------------------- -LLScreenChannel::LLScreenChannel(LLUUID& id): mOverflowToastPanel(NULL), mStartUpToastPanel(NULL), - mToastAlignment(NA_BOTTOM), mCanStoreToasts(true), - mHiddenToastsNum(0), mOverflowToastHidden(false), - mIsHovering(false), mControlHovering(false), - mShowToasts(true) +////////////////////// +// LLScreenChannelBase +////////////////////// +LLScreenChannelBase::LLScreenChannelBase(const LLUUID& id) : + mOverflowToastPanel(NULL) + ,mToastAlignment(NA_BOTTOM) + ,mCanStoreToasts(true) + ,mHiddenToastsNum(0) + ,mOverflowToastHidden(false) + ,mIsHovering(false) + ,mControlHovering(false) + ,mShowToasts(false) { mID = id; mOverflowFormatString = LLTrans::getString("OverflowInfoChannelString"); - mWorldViewRectConnection = gViewerWindow->setOnWorldViewRectUpdated(boost::bind(&LLScreenChannel::updatePositionAndSize, this, _1, _2)); + mWorldViewRectConnection = gViewerWindow->setOnWorldViewRectUpdated(boost::bind(&LLScreenChannelBase::updatePositionAndSize, this, _1, _2)); setMouseOpaque( false ); setVisible(FALSE); } - -//-------------------------------------------------------------------------- -void LLScreenChannel::init(S32 channel_left, S32 channel_right) -{ - S32 channel_top = gViewerWindow->getWorldViewRect().getHeight(); - S32 channel_bottom = gViewerWindow->getWorldViewRect().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin"); - setRect(LLRect(channel_left, channel_top, channel_right, channel_bottom)); - setVisible(TRUE); -} - -//-------------------------------------------------------------------------- -LLScreenChannel::~LLScreenChannel() +LLScreenChannelBase::~LLScreenChannelBase() { mWorldViewRectConnection.disconnect(); } - -//-------------------------------------------------------------------------- -void LLScreenChannel::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect) +void LLScreenChannelBase::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect) { S32 top_delta = old_world_rect.mTop - new_world_rect.mTop; S32 right_delta = old_world_rect.mRight - new_world_rect.mRight; @@ -105,6 +99,42 @@ void LLScreenChannel::updatePositionAndSize(LLRect old_world_rect, LLRect new_wo } setRect(this_rect); redrawToasts(); + +} + +void LLScreenChannelBase::init(S32 channel_left, S32 channel_right) +{ + S32 channel_top = gViewerWindow->getWorldViewRect().getHeight(); + S32 channel_bottom = gViewerWindow->getWorldViewRect().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin"); + setRect(LLRect(channel_left, channel_top, channel_right, channel_bottom)); + setVisible(TRUE); +} + +//-------------------------------------------------------------------------- +////////////////////// +// LLScreenChannel +////////////////////// +//-------------------------------------------------------------------------- +LLScreenChannel::LLScreenChannel(LLUUID& id): LLScreenChannelBase(id) +{ +} + +//-------------------------------------------------------------------------- +void LLScreenChannel::init(S32 channel_left, S32 channel_right) +{ + LLScreenChannelBase::init(channel_left, channel_right); +} + +//-------------------------------------------------------------------------- +LLScreenChannel::~LLScreenChannel() +{ + +} + +//-------------------------------------------------------------------------- +void LLScreenChannel::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect) +{ + LLScreenChannelBase::updatePositionAndSize(old_world_rect, new_world_rect); } //-------------------------------------------------------------------------- @@ -561,7 +591,7 @@ void LLScreenChannel::removeAndStoreAllStorableToasts() else { ++it; - } + } } redrawToasts(); } diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index f1ef6bd64d..459c28ac7c 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -55,10 +55,95 @@ typedef enum e_channel_alignment CA_RIGHT, } EChannelAlignment; +class LLScreenChannelBase : public LLUICtrl +{ + friend class LLChannelManager; +public: + LLScreenChannelBase(const LLUUID& id); + ~LLScreenChannelBase(); + + // Channel's outfit-functions + // update channel's size and position in the World View + virtual void updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect); + // initialization of channel's shape and position + virtual void init(S32 channel_left, S32 channel_right); + + + virtual void setToastAlignment(EToastAlignment align) {mToastAlignment = align;} + + virtual void setChannelAlignment(EChannelAlignment align) {mChannelAlignment = align;} + virtual void setOverflowFormatString ( const std::string& str) { mOverflowFormatString = str; } + + // kill or modify a toast by its ID + virtual void killToastByNotificationID(LLUUID id) {}; + virtual void modifyToastNotificationByID(LLUUID id, LLSD data) {}; + + // hide all toasts from screen, but not remove them from a channel + virtual void hideToastsFromScreen() {}; + // removes all toasts from a channel + virtual void removeToastsFromChannel() {}; + + // show all toasts in a channel + virtual void redrawToasts() {}; + + virtual void closeOverflowToastPanel() {}; + virtual void hideOverflowToastPanel() {}; + + + // Channel's behavior-functions + // set whether a channel will control hovering inside itself or not + virtual void setControlHovering(bool control) { mControlHovering = control; } + // set Hovering flag for a channel + virtual void setHovering(bool hovering) { mIsHovering = hovering; } + + void setCanStoreToasts(bool store) { mCanStoreToasts = store; } + + void setDisplayToastsAlways(bool display_toasts) { mDisplayToastsAlways = display_toasts; } + bool getDisplayToastsAlways() { return mDisplayToastsAlways; } + + // get number of hidden notifications from a channel + S32 getNumberOfHiddenToasts() { return mHiddenToastsNum;} + + + void setShowToasts(bool show) { mShowToasts = show; } + bool getShowToasts() { return mShowToasts; } + + // get toast allignment preset for a channel + e_notification_toast_alignment getToastAlignment() {return mToastAlignment;} + + // get ID of a channel + LLUUID getChannelID() { return mID; } + +protected: + // Channel's flags + bool mControlHovering; + bool mIsHovering; + bool mCanStoreToasts; + bool mDisplayToastsAlways; + bool mOverflowToastHidden; + // controls whether a channel shows toasts or not + bool mShowToasts; + // + EToastAlignment mToastAlignment; + EChannelAlignment mChannelAlignment; + + // attributes for the Overflow Toast + S32 mHiddenToastsNum; + LLToast* mOverflowToastPanel; + std::string mOverflowFormatString; + + // channel's ID + LLUUID mID; + + // store a connection to prevent futher crash that is caused by sending a signal to a destroyed channel + boost::signals2::connection mWorldViewRectConnection; +}; + + /** * Screen channel manages toasts visibility and positioning on the screen. */ -class LLScreenChannel : public LLUICtrl +class LLScreenChannel : public LLScreenChannelBase { friend class LLChannelManager; public: @@ -70,12 +155,6 @@ public: void updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect); // initialization of channel's shape and position void init(S32 channel_left, S32 channel_right); - // set allignment of toasts inside a channel - void setToastAlignment(EToastAlignment align) {mToastAlignment = align;} - // set allignment of channel inside a world view - void setChannelAlignment(EChannelAlignment align) {mChannelAlignment = align;} - // set a template for a string in the OverflowToast - void setOverflowFormatString ( std::string str) { mOverflowFormatString = str; } // Operating with toasts // add a toast to a channel @@ -104,37 +183,17 @@ public: // close the StartUp Toast void closeStartUpToast(); - // Channel's behavior-functions - // set whether a channel will control hovering inside itself or not - void setControlHovering(bool control) { mControlHovering = control; } - // set Hovering flag for a channel - void setHovering(bool hovering) { mIsHovering = hovering; } - // set whether a channel will store faded toasts or not - void setCanStoreToasts(bool store) { mCanStoreToasts = store; } - // tell all channels that the StartUp toast was shown and allow them showing of toasts - static void setStartUpToastShown() { mWasStartUpToastShown = true; } // get StartUp Toast's state static bool getStartUpToastShown() { return mWasStartUpToastShown; } - // set mode for dislaying of toasts - void setDisplayToastsAlways(bool display_toasts) { mDisplayToastsAlways = display_toasts; } - // get mode for dislaying of toasts - bool getDisplayToastsAlways() { return mDisplayToastsAlways; } - // tell a channel to show toasts or not - void setShowToasts(bool show) { mShowToasts = show; } - // determine whether channel shows toasts or not - bool getShowToasts() { return mShowToasts; } + // tell all channels that the StartUp toast was shown and allow them showing of toasts + static void setStartUpToastShown() { mWasStartUpToastShown = true; } // let a channel update its ShowToast flag void updateShowToastsState(); + // Channel's other interface functions functions - // get number of hidden notifications from a channel - S32 getNumberOfHiddenToasts() { return mHiddenToastsNum;} // update number of notifications in the StartUp Toast void updateStartUpString(S32 num); - // get toast allignment preset for a channel - e_notification_toast_alignment getToastAlignment() {return mToastAlignment;} - // get ID of a channel - LLUUID getChannelID() { return mID; } // Channel's signals // signal on storing of faded toasts event @@ -201,30 +260,10 @@ private: // Channel's flags static bool mWasStartUpToastShown; - bool mControlHovering; - bool mIsHovering; - bool mCanStoreToasts; - bool mDisplayToastsAlways; - bool mOverflowToastHidden; - // controls whether a channel shows toasts or not - bool mShowToasts; - // - EToastAlignment mToastAlignment; - EChannelAlignment mChannelAlignment; - - // attributes for the Overflow Toast - S32 mHiddenToastsNum; - LLToast* mOverflowToastPanel; - std::string mOverflowFormatString; // attributes for the StartUp Toast LLToast* mStartUpToastPanel; - // channel's ID - LLUUID mID; - - // store a connection to prevent futher crash that is caused by sending a signal to a destroyed channel - boost::signals2::connection mWorldViewRectConnection; std::vector mToastList; std::vector mStoredToastList; diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index 381e63f020..2be0aa40d2 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -48,6 +48,7 @@ #include "lliconctrl.h"//for Home tab icon #include "llsidetraypanelcontainer.h" #include "llwindow.h"//for SetCursor +#include "lltransientfloatermgr.h" //#include "llscrollcontainer.h" @@ -248,6 +249,7 @@ LLSideTray::LLSideTray(Params& params) // register handler function to process data from the xml. // panel_name should be specified via "parameter" attribute. commit.add("SideTray.ShowPanel", boost::bind(&LLSideTray::showPanel, this, _2, LLUUID::null)); + LLTransientFloaterMgr::getInstance()->addControlView(this); } @@ -448,13 +450,17 @@ void LLSideTray::reflectCollapseChange() setPanelRect(); if(mCollapsed) + { gFloaterView->setSnapOffsetRight(0); + setFocus(FALSE); + } else + { gFloaterView->setSnapOffsetRight(mMaxBarWidth); + setFocus(TRUE); + } gFloaterView->refresh(); - - setFocus( FALSE ); } void LLSideTray::arrange () diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index d7df258750..b0930cd86d 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -225,22 +225,14 @@ void LLStatusBar::draw() BOOL LLStatusBar::handleRightMouseDown(S32 x, S32 y, MASK mask) { - if (mHideNavbarContextMenu) - { - mHideNavbarContextMenu->buildDrawLabels(); - mHideNavbarContextMenu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(this, mHideNavbarContextMenu, x, y); - } - + show_navbar_context_menu(this,x,y); return TRUE; } BOOL LLStatusBar::postBuild() { - mHideNavbarContextMenu = LLUICtrlFactory::getInstance()->createFromFile("menu_hide_navbar.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - gMenuHolder->addChild(mHideNavbarContextMenu); - gMenuBarView->setRightMouseDownCallback(boost::bind(&LLStatusBar::onMainMenuRightClicked, this, _1, _2, _3, _4)); + gMenuBarView->setRightMouseDownCallback(boost::bind(&show_navbar_context_menu, _1, _2, _3)); return TRUE; } @@ -560,11 +552,6 @@ void LLStatusBar::setupDate() } } -void LLStatusBar::onMainMenuRightClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask) -{ - handleRightMouseDown(x, y, mask); -} - // static void LLStatusBar::onClickStatGraph(void* data) { diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h index 81a69e9590..d5629e6f1e 100644 --- a/indra/newview/llstatusbar.h +++ b/indra/newview/llstatusbar.h @@ -91,7 +91,6 @@ private: // simple method to setup the part that holds the date void setupDate(); - void onMainMenuRightClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask); static void onCommitSearch(LLUICtrl*, void* data); static void onClickSearch(void* data); static void onClickStatGraph(void* data); @@ -111,8 +110,7 @@ private: S32 mSquareMetersCommitted; LLFrameTimer* mBalanceTimer; LLFrameTimer* mHealthTimer; - LLMenuGL* mHideNavbarContextMenu; - + static std::vector sDays; static std::vector sMonths; static const U32 MAX_DATE_STRING_LENGTH; diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index c1eecf4c12..2206e79c6f 100644 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -108,6 +108,14 @@ BOOL LLSysWellWindow::postBuild() return LLDockableFloater::postBuild(); } +//--------------------------------------------------------------------------------- +void LLSysWellWindow::setMinimized(BOOL minimize) +{ + setVisible(!minimize); + + LLFloater::setMinimized(minimize); +} + //--------------------------------------------------------------------------------- void LLSysWellWindow::connectListUpdaterToSignal(std::string notification_type) { @@ -155,10 +163,10 @@ void LLSysWellWindow::addItem(LLSysWellItem::Params p) { handleItemAdded(IT_NOTIFICATION); - reshapeWindow(); + reshapeWindow(); - new_item->setOnItemCloseCallback(boost::bind(&LLSysWellWindow::onItemClose, this, _1)); - new_item->setOnItemClickCallback(boost::bind(&LLSysWellWindow::onItemClick, this, _1)); + new_item->setOnItemCloseCallback(boost::bind(&LLSysWellWindow::onItemClose, this, _1)); + new_item->setOnItemClickCallback(boost::bind(&LLSysWellWindow::onItemClick, this, _1)); } else { @@ -226,11 +234,11 @@ void LLSysWellWindow::onStoreToast(LLPanel* info_panel, LLUUID id) //--------------------------------------------------------------------------------- void LLSysWellWindow::initChannel() { - LLNotificationsUI::LLScreenChannel* channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID( + LLNotificationsUI::LLScreenChannelBase* channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID( LLUUID(gSavedSettings.getString("NotificationChannelUUID"))); - if(channel) + mChannel = dynamic_cast(channel); + if(mChannel) { - mChannel = channel; mChannel->setOnStoreToastCallback(boost::bind(&LLSysWellWindow::onStoreToast, this, _1, _2)); } else @@ -240,7 +248,7 @@ void LLSysWellWindow::initChannel() } //--------------------------------------------------------------------------------- -void LLSysWellWindow::getEnabledRect(LLRect& rect) +void LLSysWellWindow::getAllowedRect(LLRect& rect) { rect = gViewerWindow->getWorldViewRect(); } @@ -252,7 +260,7 @@ void LLSysWellWindow::toggleWindow() { setDockControl(new LLDockControl( LLBottomTray::getInstance()->getSysWell(), this, - getDockTongue(), LLDockControl::TOP, boost::bind(&LLSysWellWindow::getEnabledRect, this, _1))); + getDockTongue(), LLDockControl::TOP, boost::bind(&LLSysWellWindow::getAllowedRect, this, _1))); } if(!getVisible()) @@ -404,20 +412,18 @@ bool LLSysWellWindow::isWindowEmpty() //--------------------------------------------------------------------------------- //virtual -void LLSysWellWindow::sessionAdded(const LLUUID& sessionId, - const std::string& name, const LLUUID& otherParticipantId) +void LLSysWellWindow::sessionAdded(const LLUUID& session_id, + const std::string& name, const LLUUID& other_participant_id) { - if (mMessageList->getItemByValue(get_session_value(sessionId)) == NULL) + //*TODO get rid of get_session_value, session_id's are unique, cause performance degradation with lots chiclets (IB) + if (mMessageList->getItemByValue(get_session_value(session_id)) == NULL) { - S32 chicletCounter = 0; - LLIMModel::LLIMSession* session = get_if_there(LLIMModel::sSessionsMap, - sessionId, (LLIMModel::LLIMSession*) NULL); - if (session != NULL) + S32 chicletCounter = LLIMModel::getInstance()->getNumUnread(session_id); + if (chicletCounter > -1) { - chicletCounter = session->mNumUnread; + addIMRow(session_id, chicletCounter, name, other_participant_id); + reshapeWindow(); } - addIMRow(sessionId, chicletCounter, name, otherParticipantId); - reshapeWindow(); } } @@ -491,6 +497,7 @@ LLSysWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID& switch (im_chiclet_type) { case LLIMChiclet::TYPE_GROUP: + case LLIMChiclet::TYPE_AD_HOC: mChiclet = getChild("group_chiclet"); childSetVisible("p2p_chiclet", false); break; diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h index 37a2690a82..203b949715 100644 --- a/indra/newview/llsyswellwindow.h +++ b/indra/newview/llsyswellwindow.h @@ -68,6 +68,8 @@ public: void toggleWindow(); /*virtual*/ BOOL canClose() { return FALSE; } /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); + // override LLFloater's minimization according to EXT-1216 + /*virtual*/ void setMinimized(BOOL minimize); // Handlers void onItemClick(LLSysWellItem* item); @@ -86,8 +88,8 @@ private: IT_INSTANT_MESSAGE }EItemType; - // gets a rect valid for SysWellWindow's position on a screen (EXT-1111) - void getEnabledRect(LLRect& rect); + // gets a rect that bounds possible positions for the SysWellWindow on a screen (EXT-1111) + void getAllowedRect(LLRect& rect); // connect counter and list updaters to the corresponding signals void connectListUpdaterToSignal(std::string notification_type); // init Window's channel diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index 97a15759bf..ecaf4fb150 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -167,15 +167,30 @@ void LLToast::tick() } //-------------------------------------------------------------------------- -void LLToast::insertPanel(LLPanel* panel) + +void LLToast::reshapeToPanel() { - LLRect panel_rect, toast_rect; + LLPanel* panel = getPanel(); + if(!panel) + return; + + LLRect panel_rect; panel_rect = panel->getRect(); reshape(panel_rect.getWidth(), panel_rect.getHeight()); panel_rect.setLeftTopAndSize(0, panel_rect.getHeight(), panel_rect.getWidth(), panel_rect.getHeight()); panel->setRect(panel_rect); + + LLRect toast_rect = getRect(); + toast_rect.setLeftTopAndSize(toast_rect.mLeft,toast_rect.mTop,panel_rect.getWidth(), panel_rect.getHeight()); + setRect(toast_rect); + +} + +void LLToast::insertPanel(LLPanel* panel) +{ addChild(panel); + reshapeToPanel(); } //-------------------------------------------------------------------------- diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index 9248747c43..2166351fd0 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -99,6 +99,9 @@ public: // Operating with toasts // insert a panel to a toast void insertPanel(LLPanel* panel); + + void reshapeToPanel(); + // get toast's panel LLPanel* getPanel() { return mPanel; } // enable/disable Toast's Hide button diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h index bc9888f4b4..418373e8c6 100644 --- a/indra/newview/lltoastpanel.h +++ b/indra/newview/lltoastpanel.h @@ -39,6 +39,12 @@ #include +class LLToastPanelBase: public LLPanel +{ +public: + virtual void init(LLSD& data){}; +}; + /** * Base class for all panels that can be added to the toast. * All toast panels should contain necessary logic for representing certain notification diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 671a62962b..12253455a3 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7666,6 +7666,19 @@ class LLHelpShowFirstTimeTip : public view_listener_t } }; +void show_navbar_context_menu(LLView* ctrl, S32 x, S32 y) +{ + static LLMenuGL* show_navbar_context_menu = LLUICtrlFactory::getInstance()->createFromFile("menu_hide_navbar.xml", + gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + if(gMenuHolder->hasVisibleMenu()) + { + gMenuHolder->hideMenus(); + } + show_navbar_context_menu->buildDrawLabels(); + show_navbar_context_menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(ctrl, show_navbar_context_menu, x, y); +} + void initialize_menus() { // A parameterized event handler used as ctrl-8/9/0 zoom controls below. diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index cf482266d6..dd6aac2dd3 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -52,6 +52,7 @@ void show_debug_menus(); // checks for if menus should be shown first. void toggle_debug_menus(void*); void show_context_menu( S32 x, S32 y, MASK mask ); void show_build_mode_context_menu(S32 x, S32 y, MASK mask); +void show_navbar_context_menu(LLView* ctrl, S32 x, S32 y); BOOL enable_save_into_inventory(void*); void handle_reset_view(); void handle_cut(void*); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index d23f10f880..4a0efbaddc 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -3223,9 +3223,9 @@ LLPickInfo LLViewerWindow::pickImmediate(S32 x, S32 y_from_bot, BOOL pick_trans // assume that pickAsync put the results in the back of the mPicks list if(mPicks.size() != 0) { - mLastPick = mPicks.back(); - mLastPick.fetchResults(); - mPicks.pop_back(); + mLastPick = mPicks.back(); + mLastPick.fetchResults(); + mPicks.pop_back(); } else { diff --git a/indra/newview/skins/default/xui/en/floater_sys_well.xml b/indra/newview/skins/default/xui/en/floater_sys_well.xml index 30406cad63..aef5707fd4 100644 --- a/indra/newview/skins/default/xui/en/floater_sys_well.xml +++ b/indra/newview/skins/default/xui/en/floater_sys_well.xml @@ -12,7 +12,7 @@ width="320" min_width="320" height="23" - can_minimize="false" + can_minimize="true" can_tear_off="false" can_resize="false" can_drag_on_left="false" @@ -22,10 +22,10 @@ + height="0" + width="318"/> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 648c3458e0..2c77f61da6 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -128,13 +128,13 @@ function="World.SetAway" /> + layout="topleft"/> + function="World.SetBusy"/> @@ -117,7 +116,6 @@ label="View" layout="topleft" left="0" - tab_stop="false" tool_tip="Shows/Hide Camera controls" top="6" name="camera_btn" @@ -133,7 +131,6 @@ height="20" width="20" left_pad="0" - tab_stop="false" is_toggle="true" picture_style="true" image_selected="toggle_button_selected" diff --git a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml index c4c8aa24c4..fb4ce436e8 100644 --- a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml @@ -28,7 +28,7 @@ width="25" height="25" label="" - follows="top|left" + follows="top|right" image_overlay="BackArrow_Off" tab_stop="false" /> (Loading...)