llfloatereventlog.cpp

Go to the documentation of this file.
00001 #include "llviewerprecompiledheaders.h"
00002 #include "llfloatereventlog.h"
00003 
00004 #include "llvieweruictrlfactory.h" // builds floaters from XML
00005 #include "llviewerwindow.h"
00006 #include "llscrolllistctrl.h"
00007 #include "viewer.h"
00008 #include "llagent.h"
00009 #include "llpartdata.h"
00010 #include "llfloateravatarinfo.h"
00011 #include "llmutelist.h"
00012 #include "lltracker.h"
00013 #include "llviewerregion.h"
00014 #include "llviewerobject.h"
00015 #include "llviewerpartsource.h"
00016 #include "lltextbox.h"
00017 #include "audioengine.h"
00018 #include <iostream>
00019 #include <vector>
00020 #include <algorithm>
00021 
00022 
00023 // TODO
00024 // Angel Fluffy:
00025 //      1) cols need to be narrower
00026 //      2) score needs to be the 2nd col
00027 //      3) you need to be able to right click the key and copy it
00028 //      5) you need headers to make numbers readable (what does 'distance' mean, for example?
00029 //      8) perhaps a toggle to list all objects owned by avatars under the avatar's name, without doing individual objects? 
00030 //      9) I know that but I think you need to color-code it so that people don't go "is >10 a griefer? >100? >1000? >10,000?" the numbers are... less good.
00031 //      10) Those boxes need to be clearly marked so that you know what they are
00032 //          e.g. "Textures by score" with "#1" and "#2" and "#3" below them
00033 //
00034 // Michi Lumin:
00035 //      1) gohome button
00036 //
00037 // DONE:
00038 // Thomas Shikami: 
00039 //      1) add a bonus at that z-bouncing types
00040 //
00041 // NOT POSSIBLE/INCORRECT
00042 //      6) the blue button needs a purpose 
00043 //      7) if the particle texture has a name, then it would be great to show the name too
00044 
00045 
00046 
00047 LLFloaterEventLog *gFloaterEventLog = NULL;
00048 
00049 /*************************************************************************
00050 * Events
00051 *************************************************************************/
00052 
00053 void LLWorldEvent::incCount(S32 count)
00054 {
00055         if ( mLastFrame != gFrameCount )
00056         {
00057                 mAgeTimer.reset();
00058                 mDuration += mDurationTimer.getElapsedTimeAndResetF32();
00059                 mLastFrame = gFrameCount;
00060         }
00061 
00062         mCount += count;
00063 }
00064 
00065 LLParticleEvent::LLParticleEvent(const LLPartSysData &data)
00066 {
00067         mTexture = data.mPartImageID;
00068 }
00069 
00070 S32 LLParticleEvent::getScore() const
00071 {
00072 
00073         // Extra score for being bouncy
00074         F32 bounce_factor = 1.0f;
00075         if ( mPartSysData.mPartData.mFlags & LLPartData::LL_PART_BOUNCE_MASK )
00076                 bounce_factor = 1.5f;
00077 
00078         // TODO: Add bonus for bouncing
00079         return (S32)(mPartSysData.mBurstPartCount *
00080                ( 1 + mPartSysData.mPartData.mMaxAge ) *
00081                ( 1 / mPartSysData.mBurstRate ) *
00082                ( 1 + mPartSysData.mPartData.mStartScale.magVec() + 
00083                      mPartSysData.mPartData.mEndScale.magVec() ) *
00084                      bounce_factor );
00085 }
00086 
00087 
00088 /*************************************************************************
00089 * Emitters
00090 *************************************************************************/
00091 
00092 LLAvatarOwnedEmitter::LLAvatarOwnedEmitter(const LLUUID& id, const LLString& name)
00093 {
00094         mNamePending = false;
00095         setOwner(id, name);
00096 
00097 }
00098 
00099 void LLAvatarOwnedEmitter::setOwner(const LLUUID &id, const LLString &name)
00100 {
00101         mOwnerID = id;
00102         mOwnerName = name;
00103 }
00104 
00105 void LLAvatarOwnedEmitter::update()
00106 {
00107         if ( mOwnerName.empty() && !mNamePending )
00108         {
00109                 llinfos << "Requesting name for id " << mOwnerID << llendl;
00110                 mNamePending = true;
00111                 gCacheName->get( mOwnerID, FALSE, nameLookupCallback, this );
00112         }
00113 }
00114 
00115 // static
00116 void LLAvatarOwnedEmitter::nameLookupCallback(const LLUUID&id, const char *first, const char *last, BOOL group, void *userdata)
00117 {
00118         if ( first && last && !id.isNull())
00119         {
00120                 
00121 
00122                 LLAvatarOwnedEmitter *em = (LLAvatarOwnedEmitter*)userdata;
00123 
00124                 LLString name;
00125 
00126                 name += first;
00127                 name += " ";
00128                 name += last;
00129         
00130                 llinfos << "Setting name for id " << em->mOwnerID << " to " << name << llendl;
00131 //              em->mOwnerID = id;
00132                 em->mOwnerName = name;
00133                 em->mNamePending = false;
00134         }
00135 }
00136 
00137 LLAvatarOwnedEmitter::~LLAvatarOwnedEmitter()
00138 {
00139         if ( mNamePending && gCacheName )
00140         {
00141                 gCacheName->cancelCallback( mOwnerID, nameLookupCallback, this );
00142         }
00143 }
00144 
00145 LLObjectEmitter::LLObjectEmitter(const LLUUID& id, const LLUUID &owner)
00146 {
00147         mRequestedProperties = false;
00148 
00149         setOwner(owner);
00150         setObject(id);
00151 }
00152 
00153 LLObjectEmitter::LLObjectEmitter(LLPointer<LLViewerObject> vo)
00154 {
00155         mRequestedProperties = false;
00156         setObject(vo->getID());
00157         setPosition(vo->getPositionGlobal());
00158 
00159         if ( vo->isParticleSource() )
00160         {
00161                 setOwner(vo->mPartSourcep->getOwnerUUID());
00162         }
00163 
00164         requestObjectInfo(vo->getRegion());
00165 }
00166 
00167 
00168 void LLObjectEmitter::setObject( const LLUUID& id, const LLString &name )
00169 {
00170         if ( id.isNull() )
00171         {
00172                 llwarns << "Trying to set object id to null" << llendl;
00173                 return;
00174         }       
00175         mObjectID = id; mObjectName = name; 
00176 }
00177 
00178 void LLObjectEmitter::requestObjectInfo(const LLViewerRegion *reg)
00179 {
00180         LLAvatarOwnedEmitter::update();
00181 
00182         if ( !mObjectID.isNull() && mObjectName.empty() && !mRequestedProperties )
00183         {
00184                 llinfos << "Requesting object data for " << mObjectID << llendl;
00185 
00186                 mRequestedProperties = true;
00187                 
00188                 LLMessageSystem* msg = gMessageSystem;
00189  
00190                 msg->newMessageFast(_PREHASH_RequestObjectPropertiesFamily);
00191                 msg->nextBlockFast(_PREHASH_AgentData);
00192                 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00193                 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00194                 msg->nextBlockFast(_PREHASH_ObjectData);
00195                 msg->addU32Fast(_PREHASH_RequestFlags, 0x0 );
00196                 msg->addUUIDFast(_PREHASH_ObjectID, mObjectID );
00197                 
00198                 //LLViewerRegion* regionp = gAgent.getRegion();
00199                 msg->sendReliable( reg->getHost() );
00200         }
00201 }
00202 
00203 
00204 /*************************************************************************
00205 * Event Log
00206 *************************************************************************/
00207 
00208 
00209 LLFloaterEventLog::LLFloaterEventLog() :  LLFloater("event log")
00210 {
00211         // Create interface from XML
00212         gUICtrlFactory->buildFloater(this, "floater_event_log.xml");
00213 
00214         // Floater starts hidden        
00215         setVisible(FALSE);
00216 
00217         // Get a pointer to the scroll list from the interface
00218         mEventList = LLUICtrlFactory::getScrollListByName(this, "event_log");
00219         mSelectedTexture = LLUICtrlFactory::getTexturePickerByName(this, "selected_texture");
00220 
00221         // List of all the names of the action buttons
00222         // This is used to help with translation issues: We copy the button's name
00223         // to the configurable button.
00224         mActionButtons[QB_AVATAR_PROFILE]   = LLUICtrlFactory::getButtonByName(this, "av_profile_btn");
00225         mActionButtons[QB_AVATAR_KEY]       = LLUICtrlFactory::getButtonByName(this, "av_get_key_btn");
00226         mActionButtons[QB_AVATAR_TRACK]     = LLUICtrlFactory::getButtonByName(this, "av_track_btn");
00227         mActionButtons[QB_AVATAR_MUTE]      = LLUICtrlFactory::getButtonByName(this, "av_mute_btn");
00228         mActionButtons[QB_AVATAR_EJECT]     = LLUICtrlFactory::getButtonByName(this, "av_eject_btn");
00229         mActionButtons[QB_AVATAR_LW_GOHOME] = LLUICtrlFactory::getButtonByName(this, "av_luskwood_gohome_btn");
00230         mActionButtons[QB_OBJECT_KEY]       = LLUICtrlFactory::getButtonByName(this, "obj_get_key_btn");
00231         mActionButtons[QB_OBJECT_TRACK]     = LLUICtrlFactory::getButtonByName(this, "obj_track_btn");
00232         mActionButtons[QB_OBJECT_MUTE]      = LLUICtrlFactory::getButtonByName(this, "obj_mute_btn");
00233         mActionButtons[QB_OBJECT_RETURN]    = LLUICtrlFactory::getButtonByName(this, "obj_return_btn");
00234         mActionButtons[QB_UUID_BLACKLIST]   = LLUICtrlFactory::getButtonByName(this, "uuid_blacklist_btn");
00235         mActionButtons[QB_UUID_WHITELIST]   = LLUICtrlFactory::getButtonByName(this, "uuid_whitelist_btn");
00236         mActionButtons[QB_UUID_MUTELIST]    = LLUICtrlFactory::getButtonByName(this, "uuid_mutelist_btn");
00237 
00238 
00239         mActionButtonsType[QB_AVATAR_PROFILE]   = QBT_AVATAR;
00240         mActionButtonsType[QB_AVATAR_KEY]       = QBT_AVATAR;
00241         mActionButtonsType[QB_AVATAR_TRACK]     = QBT_AVATAR;
00242         mActionButtonsType[QB_AVATAR_MUTE]      = QBT_AVATAR;
00243         mActionButtonsType[QB_AVATAR_EJECT]     = QBT_AVATAR;
00244         mActionButtonsType[QB_AVATAR_LW_GOHOME] = QBT_AVATAR;
00245         mActionButtonsType[QB_OBJECT_KEY]       = QBT_OBJECT;
00246         mActionButtonsType[QB_OBJECT_TRACK]     = QBT_OBJECT;
00247         mActionButtonsType[QB_OBJECT_MUTE]      = QBT_OBJECT;
00248         mActionButtonsType[QB_OBJECT_RETURN]    = QBT_OBJECT;
00249         mActionButtonsType[QB_UUID_BLACKLIST]   = QBT_UUID;
00250         mActionButtonsType[QB_UUID_WHITELIST]   = QBT_UUID;
00251         mActionButtonsType[QB_UUID_MUTELIST]    = QBT_UUID;
00252 
00253 
00254         // Make list of texture selectors
00255         for(int i=0;i<MAX_INTERESTING_TEXTURES;i++)
00256         {
00257                 std::ostringstream o;
00258                 o << "hiscore_texture_" << i;
00259                 mHiscoreTextures[i] = LLUICtrlFactory::getTexturePickerByName(this, o.str());
00260 
00261                 o.str(""); o << "hiscore_name_" << i;
00262                 mHiscoreNames[i] = LLUICtrlFactory::getTextBoxByName(this, o.str());
00263 
00264                 o.str(""); o << "hiscore_owner_" << i;
00265                 mHiscoreOwners[i] = LLUICtrlFactory::getTextBoxByName(this, o.str());
00266 
00267                 o.str(""); o << "hiscore_action_" << i;
00268                 mHiscoreButtons[i] = LLUICtrlFactory::getButtonByName(this, o.str());
00269 
00270                 childSetAction(o.str(), onClickQuickButton, mHiscoreButtons[i]);
00271         }
00272         
00273 
00274         mEventList->setCallbackUserData(this);
00275         mEventList->sortByColumn("score", FALSE);
00276         mEventList->setDoubleClickCallback(onDoubleClick);
00277 
00278         childSetAction("av_profile_btn",         onClickAvatarProfile, this);
00279         childSetAction("av_get_key_btn",         onClickAvatarGetKey, this);
00280         childSetAction("av_track_btn",           onClickAvatarTrack, this);
00281         childSetAction("av_mute_btn",            onClickAvatarMute, this);
00282         childSetAction("av_eject_btn",           onClickAvatarEject, this);
00283         childSetAction("av_luskwood_gohome_btn", onClickAvatarGohomerSendHome, this);
00284 
00285         childSetAction("obj_get_key_btn",        onClickObjectGetKey, this);
00286         childSetAction("obj_track_btn",          onClickObjectTrack, this);
00287         childSetAction("obj_mute_btn",           onClickObjectMute, this);
00288         childSetAction("obj_return_btn",         onClickObjectReturn, this);
00289 
00290 
00291         childSetAction("uuid_blacklist_btn",     onClickUUIDBlacklist, this);
00292         childSetAction("uuid_whitelist_btn",     onClickUUIDWhitelist, this);
00293         childSetAction("uuid_mutelist_btn",      onClickUUIDMutelist, this);
00294 
00295         LLMessageSystem *msg = gMessageSystem;
00296         msg->addHandlerFuncFast(_PREHASH_ObjectPropertiesFamily, processObjectPropertiesFamily);
00297         msg->addHandlerFuncFast(_PREHASH_ObjectPropertiesFamily, processObjectProperties);
00298 
00299         updateControlsState();
00300         
00301 }
00302 
00303 LLFloaterEventLog::~LLFloaterEventLog()
00304 {
00305         LLMessageSystem *msg = gMessageSystem;
00306         if ( msg )
00307         {
00308                 msg->delHandlerFuncFast(_PREHASH_ObjectPropertiesFamily, processObjectPropertiesFamily);
00309                 msg->delHandlerFuncFast(_PREHASH_ObjectPropertiesFamily, processObjectProperties);
00310         }
00311 }
00312 
00313 void LLFloaterEventLog::show()
00314 {
00315         // Make sure we make a noise.
00316         open();
00317 }
00318 
00319 void LLFloaterEventLog::updateControlsState()
00320 {
00321         BOOL row_selected = FALSE;
00322         EVENT_TYPE type = LLFloaterEventLog::EVENT_PARTICLE; // TODO: fix
00323 
00324         if ( mEventList->getFirstSelected() ) row_selected = TRUE;
00325 
00326 
00327         childSetVisible("particle_info_container", row_selected && type == LLFloaterEventLog::EVENT_PARTICLE);
00328         childSetEnabled("av_profile_btn", row_selected);
00329         childSetEnabled("av_get_key_btn", row_selected);
00330         childSetEnabled("av_track_btn", row_selected);
00331         childSetEnabled("av_mute_btn", row_selected);
00332         childSetEnabled("av_eject_btn", row_selected);
00333         childSetEnabled("av_luskwood_gohome_btn", row_selected);
00334 
00335         childSetEnabled("obj_get_key_btn", row_selected);
00336         childSetEnabled("obj_track_btn", row_selected);
00337         childSetEnabled("obj_mute_btn", row_selected);
00338         childSetEnabled("obj_return_btn", row_selected);
00339 
00340         childSetEnabled("uuid_blacklist_btn", row_selected);
00341         childSetEnabled("uuid_whitelist_btn", row_selected);
00342         childSetEnabled("uuid_mutelist_btn", row_selected);
00343 }
00344 
00345 //static
00346 void LLFloaterEventLog::toggle(void*) {
00347         if (!gFloaterEventLog) {
00348                 llinfos << "No event log!" << llendl;
00349                 return;
00350         }
00351 
00352         if (gFloaterEventLog->getVisible())
00353         {
00354                 gFloaterEventLog->close();
00355         }
00356         else
00357         {
00358                 gFloaterEventLog->show();
00359         }
00360 }
00361 
00362 //static
00363 BOOL LLFloaterEventLog::visible(void*)
00364 {
00365         return (gFloaterEventLog && gFloaterEventLog->getVisible());
00366 }
00367 
00368 void LLFloaterEventLog::logAvatarEvent( const LLUUID &avatar, const LLString &name, LLPointer <LLWorldEvent> ev)
00369 {
00370         logEvent( new LLAvatarEmitter(avatar, name), ev);
00371 }
00372 
00373 void LLFloaterEventLog::logObjectEvent( const LLUUID &object, const LLUUID &owner, LLPointer <LLWorldEvent> ev)
00374 {
00375         LLObjectEmitter *em = new LLObjectEmitter(object, owner);
00376         logEvent( em, ev);
00377 }
00378 
00379 void LLFloaterEventLog::logEvent( LLPointer<LLEventEmitter> emitter, LLPointer <LLWorldEvent> event)
00380 {
00381         LLUUID id = emitter->getID();
00382 
00383         LLPointer<LLEventEmitter> em = getEmitter(id);
00384 
00385         if ( !em )
00386         {
00387                 em = emitter;
00388                 mEmitters[id] = em;
00389         }
00390 
00391         LLPointer<LLWorldEvent> ev = em->getEvent(event->getID());
00392         if ( !ev )
00393         {
00394                 em->addEvent(event);
00395                 ev = event;
00396         }
00397 
00398         //ev->incCount();
00399         *ev += *event;
00400 }
00401 
00402 void LLFloaterEventLog::logObject(  LLPointer<LLViewerObject> vo )
00403 {
00404 
00405         // Ignore things that aren't interesting.
00406         if ( !vo->isParticleSource() ) return;
00407 
00408         LLUUID emitter_id = vo->getID();
00409 
00410         LLPointer<LLEventEmitter> em = getEmitter(emitter_id);
00411         LLPointer<LLWorldEvent> ev;
00412 
00413         if ( !em )
00414         {
00415                 em = new LLObjectEmitter(vo);
00416                 mEmitters[emitter_id] = em;
00417         }
00418 
00419 
00420 
00421         if ( vo->isParticleSource() )
00422         {
00423                 ev = em->getEvent( vo->mPartSourcep->mPartSysData.mPartImageID );
00424                 if ( ! ev )
00425                 {
00426                         ev = new LLParticleEvent( vo->mPartSourcep->mPartSysData );
00427                         em->addEvent( ev );
00428                 }
00429 
00430                 ev->incCount( vo->mPartSourcep->mPartSysData.mBurstPartCount );
00431 
00432                 LLParticleEvent *pev = dynamic_cast<LLParticleEvent*>( ev.get() );
00433                 if ( pev )
00434                 {
00435                         pev->setParticleData(vo->mPartSourcep->mPartSysData);
00436                 }
00437         }
00438 
00439         LLAudioSource *src = vo->getAudioSource( em->getOwnerID() );
00440 
00441         if ( src )
00442         {
00443                 // If there wasn't a sound played, getAudioSource adds one, with gain = 0.02f as
00444                 // some sort of placeholder. That's not very interesting, so we ignore very 
00445                 // silent sounds.
00446 
00447                 LLAudioData *data = src->getCurrentData();
00448 
00449                 if ( data )
00450                 {
00451                         LLUUID sound_id = data->getID();
00452                         ev = em->getEvent( sound_id );
00453 
00454                         if ( !ev )
00455                         {
00456                                 ev = new LLSoundEvent( sound_id );
00457                                 em->addEvent( ev );
00458                         }
00459                 }
00460         }
00461 
00462 }
00463 
00464 
00465 struct DescendingEventSort
00466 {
00467      bool operator()(LLPointer<LLWorldEvent> a, LLPointer<LLWorldEvent> b)
00468      {
00469           return a->getScore() > b->getScore();
00470      }
00471 };
00472 
00473 void LLFloaterEventLog::updateList()
00474 {
00475         BOOL show_null       = LLUICtrlFactory::getCheckBoxByName(this, "show_null_cb")->getValue();
00476         BOOL show_zero_count = LLUICtrlFactory::getCheckBoxByName(this, "show_zero_count_cb")->getValue();
00477 
00478         LLDynamicArray<LLUUID> selected = mEventList->getSelectedIDs();
00479         S32 scrollpos = mEventList->getScrollPos();
00480 
00481         U32 max_age = gSavedSettings.getU32("EventLogMaxAge");
00482         U32 max_entries = gSavedSettings.getU32("EventLogMaxEntries");
00483         LLVector3d mypos = gAgent.getPositionGlobal();
00484 
00485         mEventList->deleteAllItems();
00486 
00487 
00488         std::vector< LLPointer<LLWorldEvent> > annoyances;
00489 
00490         
00491         std::map<LLUUID, LLPointer<LLEventEmitter> >::iterator iter;
00492 
00493         for(iter = mEmitters.begin(); iter != mEmitters.end(); iter++)
00494         {
00495                 LLPointer<LLEventEmitter> em = iter->second;
00496 
00497 
00498                 LLVector3d delta = em->getPosition() - mypos;
00499                 F32 distance = (F32)delta.magVec();
00500 
00501                 //llinfos << "Emitter: " << em->getID() << llendl;
00502 
00503                 std::map<LLUUID, LLPointer<LLWorldEvent> >::iterator iter_events;
00504                 for(iter_events = em->mEvents.begin(); iter_events != em->mEvents.end(); iter_events++)
00505                 {
00506                         LLPointer<LLWorldEvent> ev = iter_events->second;
00507 
00508                         if ( ev->getAge() > max_age ) continue;
00509                         if ( --max_entries == 0 ) goto too_many_entries;
00510                         if ( !show_null && ev->getID().isNull() ) continue;
00511                         if ( !show_zero_count && ev->getCount() == 0 ) continue;
00512 
00513                         ev->checkDuration();
00514 
00515                         if ( !ev->getID().isNull() && ev->getAge() < 1.0f )
00516                         {
00517                                 annoyances.push_back( ev );
00518                         }
00519 
00520                         LLSD row;
00521 
00522                         row["id"] = ev->getGlobalID();
00523 
00524                         row["columns"][LIST_EVENT_ICON]["column"] = "type_icon";
00525                         row["columns"][LIST_EVENT_ICON]["type"]   = "icon";
00526                         row["columns"][LIST_EVENT_ICON]["value"]  = ev->getIcon();
00527 
00528                         row["columns"][LIST_OWNER_NAME]["column"] = "owner_name";
00529                         row["columns"][LIST_OWNER_NAME]["type"]   = "text";
00530                         row["columns"][LIST_OWNER_NAME]["value"]  = em->getOwnerName();
00531 
00532                         row["columns"][LIST_OBJECT_NAME]["column"] = "object_name";
00533                         row["columns"][LIST_OBJECT_NAME]["type"]   = "text";
00534                         row["columns"][LIST_OBJECT_NAME]["value"]  = em->getName();
00535 
00536                         row["columns"][LIST_ID]["column"] = "id";
00537                         row["columns"][LIST_ID]["type"]   = "text";
00538                         row["columns"][LIST_ID]["value"]  = ev->getID();
00539 
00540                         row["columns"][LIST_DISTANCE]["column"] = "distance";
00541                         row["columns"][LIST_DISTANCE]["type"]   = "text";
00542                         row["columns"][LIST_DISTANCE]["value"]  = llformat("%.2f", distance);
00543 
00544                         row["columns"][LIST_COUNT]["column"] = "count";
00545                         row["columns"][LIST_COUNT]["type"]   = "text";
00546                         row["columns"][LIST_COUNT]["value"]  = ev->getCount();
00547 
00548                         row["columns"][LIST_DURATION]["column"] = "duration";
00549                         row["columns"][LIST_DURATION]["type"]   = "text";
00550                         row["columns"][LIST_DURATION]["value"]  = llformat("%.2f", ev->getDuration());
00551                          
00552                         row["columns"][LIST_AGE]["column"] = "age";
00553                         row["columns"][LIST_AGE]["type"]   = "text";
00554                         row["columns"][LIST_AGE]["value"]  = llformat("%.2f", ev->getAge());
00555 
00556                         row["columns"][LIST_SCORE]["column"] = "score";
00557                         row["columns"][LIST_SCORE]["type"]   = "text";
00558                         row["columns"][LIST_SCORE]["value"]  = ev->getScore();
00559 
00560                         // Add to list
00561                         //llinfos << "Event: " << ev->getID() << llendl;
00562                         mEventList->addElement(row, ADD_BOTTOM);
00563                 }
00564 
00565                 em->update();
00566         }
00567 
00568 too_many_entries:
00569         // finish
00570         mEventList->sort();
00571         mEventList->selectMultiple(selected);
00572         mEventList->setScrollPos(scrollpos);
00573 
00574 
00575         // Update list of major annoyances
00576         std::sort(annoyances.begin(), annoyances.end(), DescendingEventSort());
00577         int count = 0;
00578         while( annoyances.size() > count && count < MAX_INTERESTING_TEXTURES)
00579         {
00580                 mHiscoreTextures[count]->setImageAssetID( annoyances[count]->getID() );
00581                 mHiscoreNames[count]->setText( annoyances[count]->getParent()->getName() );
00582                 mHiscoreOwners[count]->setText( annoyances[count]->getParent()->getOwnerName() );
00583                 mHiscoreButtons[count]->setEnabled(TRUE);
00584                 mHiscoreEvents[count] = annoyances[count];
00585                 count++;
00586         }
00587 
00588         // Clear remaining ones if any
00589         while( count < MAX_INTERESTING_TEXTURES )
00590         {
00591                 mHiscoreTextures[count]->setImageAssetID( LLUUID::null );
00592                 mHiscoreNames[count]->setText(LLString(""));
00593                 mHiscoreOwners[count]->setText(LLString(""));
00594                 mHiscoreButtons[count]->setEnabled(FALSE);
00595                 mHiscoreEvents[count] = NULL;
00596                 count++;
00597         }
00598 
00599 }
00600 
00601 
00602 void LLFloaterEventLog::updateQuickButtons()
00603 {
00604         S32 action = gSavedSettings.getS32("EventLogQuickAction");
00605         if ( action >= QB_COUNT )
00606         {
00607                 llwarns << "Quick action button set to out of range value: " << action << llendl;
00608                 return;
00609         }
00610 
00611         LLString text = mActionButtons[action]->getLabelSelected();
00612 
00613         switch( mActionButtonsType[action] )
00614         {
00615                 case QBT_AVATAR: text = "Avatar: " + text; break;
00616                 case QBT_OBJECT: text = "Object: " + text; break;
00617                 case QBT_UUID:   text = "UUID: " + text; break;
00618         }
00619 
00620         for(S32 i = 0;i<MAX_INTERESTING_TEXTURES;i++)
00621         {
00622                 mHiscoreButtons[i]->setLabel(text);
00623         }
00624 }
00625 
00626 void LLFloaterEventLog::updateSelectedEventInfo()
00627 {
00628 
00629 
00630         // Update texture selectors
00631         LLScrollListItem *selected_item =   mEventList->getFirstSelected();
00632         if ( selected_item )
00633         {
00634                 LLParticleEvent *pev = dynamic_cast<LLParticleEvent*>( findEventBySelectedID(selected_item->getUUID()).get() );
00635                 if ( pev )
00636                 {
00637                         mSelectedTexture->setImageAssetID( pev->getID() );
00638                         LLString pattern;
00639 
00640                         switch( pev->mPartSysData.mPattern )
00641                         {
00642                                 case LLPartSysData::LL_PART_SRC_PATTERN_DROP:             pattern = "DROP"; break;
00643                                 case LLPartSysData::LL_PART_SRC_PATTERN_EXPLODE:          pattern = "EXPLODE"; break;
00644                                 case LLPartSysData::LL_PART_SRC_PATTERN_ANGLE:            pattern = "ANGLE"; break;
00645                                 case LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE:       pattern = "ANGLE_CONE"; break;
00646                                 case LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE_EMPTY: pattern = "ANGLE_CONE_EMPTY"; break;
00647                                 default:                                   pattern = "UNKNOWN"; break;
00648                         }
00649 
00650                         childSetTextArg("part_pattern",    "[PATTERN]",        pattern);
00651                         childSetTextArg("part_texture",    "[TEXTURE]",        pev->getID().asString());
00652                         childSetTextArg("part_burst_rate", "[BURST_COUNT]",    llformat("%i", (U32)pev->mPartSysData.mBurstPartCount));
00653                         childSetTextArg("part_burst_rate", "[BURST_RATE]",     llformat("%.3f", pev->mPartSysData.mBurstRate));
00654                         childSetTextArg("part_burst_rate", "[PARTICLE_COUNT]", llformat("%.3f", pev->mPartSysData.mBurstPartCount *
00655                                                                                                 (1 / pev->mPartSysData.mBurstRate)) );
00656 
00657                         childSetTextArg("part_radius",     "[RADIUS]",         llformat("%.3f", pev->mPartSysData.mBurstRadius));
00658                         childSetTextArg("part_angle",      "[ANGLE_BEGIN]",    llformat("%.3f", pev->mPartSysData.mInnerAngle));
00659                         childSetTextArg("part_angle",      "[ANGLE_END]",      llformat("%.3f", pev->mPartSysData.mOuterAngle));
00660 
00661                         childSetTextArg("part_speed",      "[SPEED_MIN]",      llformat("%.3f", pev->mPartSysData.mBurstSpeedMin));
00662                         childSetTextArg("part_speed",      "[SPEED_MAX]",      llformat("%.3f", pev->mPartSysData.mBurstSpeedMax));
00663 
00664                         childSetTextArg("part_size",       "[SCALE_BEGIN]",    llformat("<%.3f, %.3f>", pev->mPartSysData.mPartData.mStartScale.mV[VX],
00665                                                                                                         pev->mPartSysData.mPartData.mStartScale.mV[VY]));
00666                         childSetTextArg("part_size",       "[SCALE_END]",      llformat("<%.3f, %.3f>", pev->mPartSysData.mPartData.mEndScale.mV[VX],
00667                                                                                                         pev->mPartSysData.mPartData.mEndScale.mV[VY]));
00668                         childSetTextArg("part_color",      "[COLOR_BEGIN]",    llformat("<%.3f, %.3f, %.3f>", pev->mPartSysData.mPartData.mStartColor.mV[0],
00669                                                                                                               pev->mPartSysData.mPartData.mStartColor.mV[1],
00670                                                                                                               pev->mPartSysData.mPartData.mStartColor.mV[2]));
00671                         childSetTextArg("part_color",      "[COLOR_END]",      llformat("<%.3f, %.3f, %.3f>", pev->mPartSysData.mPartData.mEndColor.mV[0],
00672                                                                                                               pev->mPartSysData.mPartData.mEndColor.mV[1],
00673                                                                                                               pev->mPartSysData.mPartData.mEndColor.mV[2]));
00674                         childSetTextArg("part_alpha",      "[ALPHA_BEGIN]",    llformat("%.3f", pev->mPartSysData.mPartData.mStartColor.mV[3]));
00675                         childSetTextArg("part_alpha",      "[ALPHA_END]",      llformat("%.3f", pev->mPartSysData.mPartData.mEndColor.mV[3]));
00676 
00677                         
00678                         LLString flags = "";
00679                         U32 f = pev->mPartSysData.mPartData.mFlags;
00680                         if ( f &  LLPartData::LL_PART_INTERP_COLOR_MASK )      flags += "interp_color ";
00681                         if ( f &  LLPartData::LL_PART_INTERP_SCALE_MASK )      flags += "interp_size ";
00682                         if ( f &  LLPartData::LL_PART_BOUNCE_MASK )            flags += "bounce ";
00683                         if ( f &  LLPartData::LL_PART_WIND_MASK )              flags += "wind ";
00684                         if ( f &  LLPartData::LL_PART_FOLLOW_SRC_MASK )        flags += "follow_src ";
00685                         if ( f &  LLPartData::LL_PART_FOLLOW_VELOCITY_MASK )   flags += "follow_vel ";
00686                         if ( f &  LLPartData::LL_PART_TARGET_POS_MASK )        flags += "target ";
00687                         if ( f &  LLPartData::LL_PART_TARGET_LINEAR_MASK )     flags += "linear ";
00688                         if ( f &  LLPartData::LL_PART_EMISSIVE_MASK )          flags += "glow ";
00689                         if ( f &  LLPartData::LL_PART_BEAM_MASK )              flags += "beam ";
00690                         if ( f &  LLPartData::LL_PART_DEAD_MASK )              flags += "dead ";
00691 
00692                         childSetTextArg("part_flags",      "[FLAGS]", flags);
00693                 }
00694         }
00695 
00696 }
00697 
00698 void LLFloaterEventLog::updateWindow()
00699 {
00700         if (!LLFloaterEventLog::visible(NULL))
00701         {
00702                 return;
00703         }
00704 
00705 
00706         BOOL enabled         = LLUICtrlFactory::getCheckBoxByName(this, "enabled_cb")->getValue();
00707         if ( enabled ) updateList();
00708 
00709 
00710         updateSelectedEventInfo();
00711         updateControlsState();
00712         updateQuickButtons();
00713 }
00714 
00715 
00716 //static
00717 void LLFloaterEventLog::processObjectProperties(LLMessageSystem *msg, void **user_data)
00718 {
00719         S32 i;
00720         S32 count = msg->getNumberOfBlocksFast(_PREHASH_ObjectData);
00721         for( i = 0; i < count; i++ )
00722         {
00723                 LLUUID id;
00724                 char name[DB_INV_ITEM_NAME_BUF_SIZE];           /* Flawfinder: ignore */
00725 
00726                 
00727                 msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ObjectID, id, i);
00728                 llinfos << "Processing object data for " << id << llendl;
00729 
00730                 if ( gFloaterEventLog->mEmitters.count( id ) > 0 )
00731                 {
00732                         llinfos << "Setting data for " << id << llendl;
00733                         LLPointer<LLEventEmitter> em = gFloaterEventLog->mEmitters[id];
00734 
00735                         msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Name, DB_INV_ITEM_NAME_BUF_SIZE, name, i);
00736 
00737                         em->setName( name );
00738                 }
00739 
00740         }
00741 }
00742 
00743 //static
00744 void LLFloaterEventLog::processObjectPropertiesFamily(LLMessageSystem *msg, void **user_data)
00745 {
00746 
00747         LLUUID id;
00748         U32 request_flags;
00749 
00750         char name[DB_INV_ITEM_NAME_BUF_SIZE];           /* Flawfinder: ignore */
00751 
00752         
00753         msg->getU32Fast(_PREHASH_ObjectData, _PREHASH_RequestFlags,     request_flags );
00754          msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ObjectID,                id );
00755 
00756         llinfos << "Processing object data for " << id << llendl;
00757 
00758         if ( gFloaterEventLog->mEmitters.count( id ) > 0 )
00759         {
00760                 LLPointer<LLEventEmitter> em = gFloaterEventLog->mEmitters[id];
00761 
00762                 msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Name, DB_INV_ITEM_NAME_BUF_SIZE, name);
00763 
00764                 em->setName( name );
00765         }
00766 
00767 
00768 }
00769 
00770 LLPointer<LLEventEmitter> LLFloaterEventLog::findEmitterBySelectedID(const LLUUID &id)
00771 {
00772         std::map<LLUUID, LLPointer<LLEventEmitter> >::iterator iter;
00773         for(iter = mEmitters.begin(); iter != mEmitters.end(); iter++)
00774         {
00775                 LLPointer<LLEventEmitter> em = iter->second;
00776 
00777                 std::map<LLUUID, LLPointer<LLWorldEvent> >::iterator iter_events;
00778                 for(iter_events = em->mEvents.begin(); iter_events != em->mEvents.end(); iter_events++)
00779                 {
00780                         LLPointer<LLWorldEvent> ev = iter_events->second;
00781 
00782                         if ( ev->getGlobalID() == id )
00783                         {
00784                                 return em;
00785                         }
00786                 }
00787         }
00788         
00789         return NULL;
00790 }
00791 
00792 LLPointer<LLWorldEvent> LLFloaterEventLog::findEventBySelectedID(const LLUUID &id)
00793 {
00794         std::map<LLUUID, LLPointer<LLEventEmitter> >::iterator iter;
00795         for(iter = mEmitters.begin(); iter != mEmitters.end(); iter++)
00796         {
00797                 LLPointer<LLEventEmitter> em = iter->second;
00798 
00799                 std::map<LLUUID, LLPointer<LLWorldEvent> >::iterator iter_events;
00800                 for(iter_events = em->mEvents.begin(); iter_events != em->mEvents.end(); iter_events++)
00801                 {
00802                         LLPointer<LLWorldEvent> ev = iter_events->second;
00803 
00804                         if ( ev->getGlobalID() == id )
00805                         {
00806                                 return ev;
00807                         }
00808                 }
00809         }
00810 
00811         return NULL;
00812 }
00813 
00814 //static
00815 void LLFloaterEventLog::onDoubleClick(void *userdata)
00816 {
00817         LLFloaterEventLog *self = (LLFloaterEventLog*)userdata;
00818         LLScrollListItem *item =   self->mEventList->getFirstSelected();
00819         LLUUID item_id = item->getUUID();
00820 
00821 
00822         // TODO: Ok, this is rather ugly and should be reworked.
00823         // We've assigned an arbitrary ID to each element, as there's no way to
00824         // uniquely identify a row otherwise -- as both emitters and events may not
00825         // be unique.
00826         //
00827         // Now we need to find the emitter for a key, so we scan through the whole
00828         // list looking for it
00829 
00830         LLPointer<LLEventEmitter> em = self->findEmitterBySelectedID(item_id);
00831         if ( em )
00832         {
00833                 gAgent.lookAtObject(em->getID(), CAMERA_POSITION_OBJECT);
00834                 
00835         }
00836         else
00837         {
00838                 llwarns << "Searched the whole list for " << item_id << " but couldn't find it!" << llendl;
00839         }
00840 }
00841 
00842 
00843 
00844 void LLFloaterEventLog::doCommand(avlist_command_t func, bool use_object_id, bool first_only)
00845 {
00846         LLDynamicArray<LLUUID> ids = mEventList->getSelectedIDs();
00847 
00848         std::map<LLUUID, S32> seen_ids;
00849 
00850         // Go through the list of selections, removing duplicated object or avatar IDs.
00851         for(LLDynamicArray<LLUUID>::iterator itr = ids.begin(); itr != ids.end(); ++itr)
00852         {
00853                 LLUUID id = *itr;
00854                 LLPointer<LLEventEmitter> pev = findEmitterBySelectedID(id);
00855 
00856                 if ( pev  )
00857                 {
00858                         LLUUID dest_id;
00859                         LLString dest_name;
00860 
00861                         if ( use_object_id )
00862                         {
00863                                 dest_id   = pev->getID();
00864                                 dest_name = pev->getName();
00865                         }
00866                         else
00867                         {
00868                                 dest_id   = pev->getOwnerID();
00869                                 dest_name = pev->getOwnerName();
00870                         }
00871 
00872                         
00873                         if ( seen_ids.count( dest_id ) < 1 )
00874                         {
00875                                 func(dest_id, dest_name);
00876 
00877                                 if ( first_only ) return;
00878                         }
00879 
00880                         seen_ids[dest_id] = 1;
00881                 }
00882         }
00883 
00884 
00885 
00886 }
00887 
00888 
00889 static void cmd_eject(const LLUUID& avatar, const LLString &name)       { /*send_eject(avatar, false);*/ }
00890 static void cmd_profile(const LLUUID& avatar, const LLString &name)     { LLFloaterAvatarInfo::showFromDirectory(avatar); }
00891 static void cmd_mute(const LLUUID&avatar, const LLString &name)         { gMuteListp->add(LLMute(avatar, name, LLMute::AGENT)); }
00892 static void cmd_gohome(const LLUUID&avatar, const LLString &name)       { gAgent.sendChat("gohome " + name + " " + avatar.asString(), 0, CHAT_TYPE_SHOUT); }
00893 static void cmd_track(const LLUUID&avatar, const LLString &name)        { LLTracker::trackAvatar(avatar, name); }
00894 static void cmd_get_key(const LLUUID&avatar, const LLString &name)
00895 {
00896         char buffer[UUID_STR_LENGTH];           /*Flawfinder: ignore*/
00897         avatar.toString(buffer);
00898         gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer));
00899 }
00900 
00902 // Button handlers for avatars
00904 
00905 //static
00906 void LLFloaterEventLog::onClickAvatarGohomerSendHome(void *userdata)
00907 {
00908         LLFloaterEventLog *self = (LLFloaterEventLog*)userdata;
00909         self->doCommand(cmd_gohome, false);
00910 }
00911 
00912 //static
00913 void LLFloaterEventLog::onClickAvatarGetKey(void *userdata)
00914 {
00915         LLFloaterEventLog *self = (LLFloaterEventLog*)userdata;
00916         self->doCommand(cmd_get_key, false, true);
00917 }
00918 
00919 //static
00920 void LLFloaterEventLog::onClickAvatarEject(void *userdata)
00921 {
00922         LLFloaterEventLog *self = (LLFloaterEventLog*)userdata;
00923         self->doCommand(cmd_eject, false);
00924 }
00925 
00926 //static
00927 void LLFloaterEventLog::onClickAvatarMute(void *userdata)
00928 {
00929         LLFloaterEventLog *self = (LLFloaterEventLog*)userdata;
00930         self->doCommand(cmd_mute, false);
00931 }
00932 
00933 //static
00934 void LLFloaterEventLog::onClickAvatarProfile(void* userdata)
00935 {
00936         LLFloaterEventLog *self = (LLFloaterEventLog*)userdata;
00937         self->doCommand(cmd_profile, false);
00938 }
00939 
00940 //static
00941 void LLFloaterEventLog::onClickAvatarTrack(void *userdata)
00942 {
00943         LLFloaterEventLog *self = (LLFloaterEventLog*)userdata;
00944         self->doCommand(cmd_track, false, true);
00945 }
00946 
00948 // Button handlers for objects
00950 
00951 //static
00952 void LLFloaterEventLog::onClickObjectGetKey(void* userdata)
00953 {
00954         LLFloaterEventLog *self = (LLFloaterEventLog*)userdata;
00955         self->doCommand(cmd_get_key, true, true);
00956 }
00957 
00958 
00959 //static
00960 void LLFloaterEventLog::onClickObjectTrack(void* userdata)
00961 {
00962         LLFloaterEventLog *self = (LLFloaterEventLog*)userdata;
00963         self->doCommand(cmd_track, true, true);
00964 }
00965 
00966 //static
00967 void LLFloaterEventLog::onClickObjectMute(void* userdata)
00968 {
00969         LLFloaterEventLog *self = (LLFloaterEventLog*)userdata;
00970         self->doCommand(cmd_mute, true);
00971 }
00972 
00973 //static
00974 void LLFloaterEventLog::onClickObjectReturn(void* userdata)
00975 {
00976 //      LLFloaterEventLog *self = (LLFloaterEventLog*)userdata;
00977 //      self->doCommand(cmd_mute, true);
00978         llinfos << "not implemented" << llendl;
00979 }
00980 
00982 // Button handlers for UUIDs
00984 
00985 //static
00986 void LLFloaterEventLog::onClickUUIDBlacklist(void* userdata)
00987 {
00988 //      LLFloaterEventLog *self = (LLFloaterEventLog*)userdata;
00989 //      self->doCommand(cmd_mute, true);
00990         llinfos << "not implemented" << llendl;
00991 }
00992 
00993 //static
00994 void LLFloaterEventLog::onClickUUIDWhitelist(void* userdata)
00995 {
00996 //      LLFloaterEventLog *self = (LLFloaterEventLog*)userdata;
00997 //      self->doCommand(cmd_mute, true);
00998         llinfos << "not implemented" << llendl;
00999 }
01000 
01001 //static
01002 void LLFloaterEventLog::onClickUUIDMutelist(void* userdata)
01003 {
01004 //      LLFloaterEventLog *self = (LLFloaterEventLog*)userdata;
01005 //      self->doCommand(cmd_mute, true);
01006         llinfos << "not implemented" << llendl;
01007 }
01008 
01009 
01011 // Quick buttons
01013 //static
01014 void LLFloaterEventLog::onClickQuickButton(void *button)
01015 {
01016         S32 pos = -1;
01017         
01018         // Find this button in the list of buttons to obtain its position
01019         for(S32 i=0;i<MAX_INTERESTING_TEXTURES;i++)
01020         {
01021                 if ( gFloaterEventLog->mHiscoreButtons[i] == button )
01022                 {
01023                         pos = i;
01024                         break;
01025                 }
01026         }
01027 
01028         if ( pos < 0 )
01029         {
01030                 llwarns << "Failed to find myself in the floater!" << llendl;
01031                 return;
01032         }
01033         
01034         // Get the event associated with that position
01035         LLPointer<LLWorldEvent>   ev = gFloaterEventLog->mHiscoreEvents[pos];
01036         LLPointer<LLEventEmitter> em = ev->getParent();
01037 
01038         S32 action = gSavedSettings.getS32("EventLogQuickAction");
01039         switch(action)
01040         {
01041                 case QB_AVATAR_PROFILE:   cmd_profile( em->getOwnerID(), em->getOwnerName() ); break;
01042                 case QB_AVATAR_KEY:       cmd_get_key( em->getOwnerID(), em->getOwnerName() ); break;
01043                 case QB_AVATAR_TRACK:     cmd_track( em->getOwnerID(), em->getOwnerName() ); break;
01044                 case QB_AVATAR_MUTE:      cmd_mute( em->getOwnerID(), em->getOwnerName() ); break;
01045                 case QB_AVATAR_EJECT:     cmd_eject( em->getOwnerID(), em->getOwnerName() ); break;
01046                 case QB_AVATAR_LW_GOHOME: cmd_gohome( em->getOwnerID(), em->getOwnerName() ); break;
01047                 case QB_OBJECT_KEY:       cmd_get_key( em->getID(), em->getName() ); break;
01048                 case QB_OBJECT_TRACK:     cmd_track( em->getID(), em->getName() ); break;
01049                 case QB_OBJECT_MUTE:      cmd_mute( em->getID(), em->getName() ); break;
01050                 case QB_OBJECT_RETURN:    llwarns << "Not implemented" << llendl; break;
01051                 case QB_UUID_BLACKLIST:   llwarns << "Not implemented" << llendl; break;
01052                 case QB_UUID_WHITELIST:   llwarns << "Not implemented" << llendl; break;
01053                 case QB_UUID_MUTELIST:    llwarns << "Not implemented" << llendl; break;
01054                 default:                  llwarns << "Unknown action " << action << llendl; break;
01055         }
01056 }
01057 

Generated on Thu Jul 1 06:08:33 2010 for Second Life Viewer by  doxygen 1.4.7