//----------------------------------------------------------------------------- // onBtnPlay() //----------------------------------------------------------------------------- void LLFloaterAnimPreview::onBtnPlay(void* user_data) { LLFloaterAnimPreview* previewp = (LLFloaterAnimPreview*)user_data; if (!previewp->getEnabled()) return; if (previewp->mMotionID.notNull() && previewp->mAnimPreview) { LLVOAvatar* avatarp = previewp->mAnimPreview->getDummyAvatar(); if(!avatarp->isMotionActive(previewp->mMotionID)) { previewp->resetMotion(); previewp->mPauseRequest = NULL; } else { if (avatarp->areAnimationsPaused()) { previewp->mPauseRequest = NULL; } else { previewp->mPauseRequest = avatarp->requestPause(); } } } }
//----------------------------------------------------------------------------- // refresh() //----------------------------------------------------------------------------- void LLFloaterAnimPreview::refresh() { if (!mAnimPreview) { childShow("bad_animation_text"); mPlayButton->setEnabled(FALSE); mStopButton->setEnabled(FALSE); childDisable("ok_btn"); } else { childHide("bad_animation_text"); mPlayButton->setEnabled(TRUE); LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); if (avatarp->isMotionActive(mMotionID)) { mStopButton->setEnabled(TRUE); LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(mMotionID); if (avatarp->areAnimationsPaused()) { mPlayButton->setImages(std::string("button_anim_play.tga"), std::string("button_anim_play_selected.tga")); } else { if (motionp) { F32 fraction_complete = motionp->getLastUpdateTime() / motionp->getDuration(); childSetValue("playback_slider", fraction_complete); } mPlayButton->setImages(std::string("button_anim_pause.tga"), std::string("button_anim_pause_selected.tga")); } } else { mPauseRequest = avatarp->requestPause(); mPlayButton->setImages(std::string("button_anim_play.tga"), std::string("button_anim_play_selected.tga")); mStopButton->setEnabled(TRUE); // stop also resets, leave enabled. } childEnable("ok_btn"); mAnimPreview->requestUpdate(); } }
//----------------------------------------------------------------------------- // refresh() //----------------------------------------------------------------------------- void LLFloaterAnimPreview::refresh() { // Are we showing the play button (default) or the pause button? bool show_play = true; if (!mAnimPreview) { getChildView("bad_animation_text")->setVisible(TRUE); // play button visible but disabled mPlayButton->setEnabled(FALSE); mStopButton->setEnabled(FALSE); getChildView("ok_btn")->setEnabled(FALSE); } else { getChildView("bad_animation_text")->setVisible(FALSE); // re-enabled in case previous animation was bad mPlayButton->setEnabled(TRUE); mStopButton->setEnabled(TRUE); LLVOAvatar* avatarp = mAnimPreview->getPreviewAvatar(); if (avatarp->isMotionActive(mMotionID)) { mStopButton->setEnabled(TRUE); LLKeyframeMotion* motionp = (LLKeyframeMotion*)avatarp->findMotion(mMotionID); if (!avatarp->areAnimationsPaused()) { // animation is playing if (motionp) { F32 fraction_complete = motionp->getLastUpdateTime() / motionp->getDuration(); getChild<LLUICtrl>("playback_slider")->setValue(fraction_complete); } show_play = false; } } else { // Motion just finished playing mPauseRequest = avatarp->requestPause(); } getChildView("ok_btn")->setEnabled(TRUE); mAnimPreview->requestUpdate(); } mPlayButton->setVisible(show_play); mPauseButton->setVisible(!show_play); }
//----------------------------------------------------------------------------- // onBtnPause() //----------------------------------------------------------------------------- void LLFloaterAnimPreview::onBtnPause() { if (!getEnabled()) return; if (mMotionID.notNull() && mAnimPreview) { LLVOAvatar* avatarp = mAnimPreview->getPreviewAvatar(); if (avatarp->isMotionActive(mMotionID)) { if (!avatarp->areAnimationsPaused()) { mPauseRequest = avatarp->requestPause(); } } } }
//----------------------------------------------------------------------------- // onBtnPlay() //----------------------------------------------------------------------------- void LLFloaterAnimPreview::onBtnPlay() { if (!getEnabled()) return; if (mMotionID.notNull() && mAnimPreview) { LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar(); if (!avatarp->isMotionActive(mMotionID)) { resetMotion(); mPauseRequest = NULL; } else if (avatarp->areAnimationsPaused()) { mPauseRequest = NULL; } } }
void FSRadar::updateRadarList() { //Configuration LLWorld* world = LLWorld::getInstance(); LLMuteList* mutelist = LLMuteList::getInstance(); FSWSAssetBlacklist* blacklist = FSWSAssetBlacklist::getInstance(); static const F32 chat_range_say = LFSimFeatureHandler::getInstance()->sayRange(); static const F32 chat_range_shout = LFSimFeatureHandler::getInstance()->shoutRange(); static const std::string str_chat_entering = LLTrans::getString("entering_chat_range"); static const std::string str_chat_leaving = LLTrans::getString("leaving_chat_range"); static const std::string str_draw_distance_entering = LLTrans::getString("entering_draw_distance"); static const std::string str_draw_distance_leaving = LLTrans::getString("leaving_draw_distance"); static const std::string str_region_entering = LLTrans::getString("entering_region"); static const std::string str_region_entering_distance = LLTrans::getString("entering_region_distance"); static const std::string str_region_leaving = LLTrans::getString("leaving_region"); static const std::string str_avatar_age_alert = LLTrans::getString("avatar_age_alert"); static LLCachedControl<bool> RadarReportChatRangeEnter(gSavedSettings, "RadarReportChatRangeEnter"); static LLCachedControl<bool> RadarReportChatRangeLeave(gSavedSettings, "RadarReportChatRangeLeave"); static LLCachedControl<bool> RadarReportDrawRangeEnter(gSavedSettings, "RadarReportDrawRangeEnter"); static LLCachedControl<bool> RadarReportDrawRangeLeave(gSavedSettings, "RadarReportDrawRangeLeave"); static LLCachedControl<bool> RadarReportSimRangeEnter(gSavedSettings, "RadarReportSimRangeEnter"); static LLCachedControl<bool> RadarReportSimRangeLeave(gSavedSettings, "RadarReportSimRangeLeave"); static LLCachedControl<bool> RadarEnterChannelAlert(gSavedSettings, "RadarEnterChannelAlert"); static LLCachedControl<bool> RadarLeaveChannelAlert(gSavedSettings, "RadarLeaveChannelAlert"); static LLCachedControl<bool> RadarAvatarAgeAlert(gSavedSettings, "RadarAvatarAgeAlert"); static LLCachedControl<F32> nearMeRange(gSavedSettings, "NearMeRange"); static LLCachedControl<bool> limitRange(gSavedSettings, "LimitRadarByRange"); static LLCachedControl<F32> RenderFarClip(gSavedSettings, "RenderFarClip"); static LLCachedControl<bool> sFSLegacyRadarFriendColoring(gSavedSettings, "FSLegacyRadarFriendColoring"); static LLCachedControl<bool> sRadarColorNamesByDistance(gSavedSettings, "FSRadarColorNamesByDistance", false); static LLCachedControl<bool> RadarShowMutedAndDerendered(gSavedSettings, "FSRadarShowMutedAndDerendered"); static LLCachedControl<bool> sFSRadarEnhanceByBridge(gSavedSettings, "FSRadarEnhanceByBridge"); bool sUseLSLBridge = FSLSLBridge::instance().canUseBridge(); F32 drawRadius(RenderFarClip); const LLVector3d& posSelf = gAgent.getPositionGlobal(); LLViewerRegion* own_reg = gAgent.getRegion(); LLUUID regionSelf; if (own_reg) { regionSelf = own_reg->getRegionID(); } bool alertScripts = mRadarAlertRequest; // save the current value, so it doesn't get changed out from under us by another thread time_t now = time(NULL); //STEP 0: Clear model data mRadarEnterAlerts.clear(); mRadarLeaveAlerts.clear(); mRadarOffsetRequests.clear(); mRadarEntriesData.clear(); mAvatarStats.clear(); //STEP 1: Update our basic data model: detect Avatars & Positions in our defined range std::vector<LLVector3d> positions; uuid_vec_t avatar_ids; if (limitRange) { world->getAvatars(&avatar_ids, &positions, gAgent.getPositionGlobal(), nearMeRange); } else { world->getAvatars(&avatar_ids, &positions); } // Determine lists of new added and removed avatars uuid_vec_t current_vec, added_vec, removed_vec; uuid_vec_t::iterator vec_it_end; entry_map_t::iterator em_it_end = mEntryList.end(); current_vec.reserve(mEntryList.size()); for (entry_map_t::iterator em_it = mEntryList.begin(); em_it != em_it_end; ++em_it) { current_vec.push_back(em_it->first); } LLCommonUtils::computeDifference(avatar_ids, current_vec, added_vec, removed_vec); // Remove old avatars from our list vec_it_end = removed_vec.end(); for (uuid_vec_t::iterator it = removed_vec.begin(); it != vec_it_end; ++it) { LLUUID avid = *it; entry_map_t::iterator found = mEntryList.find(avid); if (found != mEntryList.end()) { delete found->second; mEntryList.erase(found); } } // Add new avatars vec_it_end = added_vec.end(); for (uuid_vec_t::iterator it = added_vec.begin(); it != vec_it_end; ++it) { LLUUID avid = *it; mEntryList[avid] = new FSRadarEntry(avid); } LLLocalSpeakerMgr::getInstance()->update(TRUE); //STEP 2: Transform detected model list data into more flexible multimap data structure; //TS: Count avatars in chat range and in the same region U32 inChatRange = 0; U32 inSameRegion = 0; std::vector<LLVector3d>::const_iterator pos_it = positions.begin(), pos_end = positions.end(); uuid_vec_t::const_iterator item_it = avatar_ids.begin(), item_end = avatar_ids.end(); for (;pos_it != pos_end && item_it != item_end; ++pos_it, ++item_it) { // //2a. For each detected av, gather up all data we would want to display or use to drive alerts // LLUUID avId = static_cast<LLUUID>(*item_it); LLVector3d avPos = static_cast<LLVector3d>(*pos_it); if (avId == gAgentID) { continue; } // Skip modelling this avatar if its basic data is either inaccessible, or it's a dummy placeholder FSRadarEntry* ent = getEntry(avId); LLViewerRegion *reg = world->getRegionFromPosGlobal(avPos); if (!ent) // don't update this radar listing if data is inaccessible { continue; } // Try to get the avatar's viewer object - we will need it anyway later LLVOAvatar* avVo = (LLVOAvatar*)gObjectList.findObject(avId); static LLUICachedControl<bool> showdummyav("FSShowDummyAVsinRadar"); if (!showdummyav) { if (avVo && avVo->mIsDummy) { continue; } } bool is_muted = mutelist->isMuted(avId); bool is_blacklisted = blacklist->isBlacklisted(avId, LLAssetType::AT_OBJECT); bool should_be_ignored = is_muted || is_blacklisted; ent->mIgnore = should_be_ignored; if (!RadarShowMutedAndDerendered && should_be_ignored) { continue; } LLUUID avRegion; if (reg) { avRegion = reg->getRegionID(); } bool isInSameRegion = (avRegion == regionSelf); S32 seentime = (S32)difftime(now, ent->mFirstSeen); S32 hours = (S32)(seentime / 3600); S32 mins = (S32)((seentime - hours * 3600) / 60); S32 secs = (S32)((seentime - hours * 3600 - mins * 60)); std::string avSeenStr = llformat("%d:%02d:%02d", hours, mins, secs); S32 avStatusFlags = ent->mStatus; ERadarPaymentInfoFlag avFlag = FSRADAR_PAYMENT_INFO_NONE; if (avStatusFlags & AVATAR_TRANSACTED) { avFlag = FSRADAR_PAYMENT_INFO_USED; } else if (avStatusFlags & AVATAR_IDENTIFIED) { avFlag = FSRADAR_PAYMENT_INFO_FILLED; } S32 avAge = ent->mAge; std::string avName = ent->mName; U32 lastZOffsetTime = ent->mLastZOffsetTime; F32 avZOffset = ent->mZOffset; if (avPos[VZ] == AVATAR_UNKNOWN_Z_OFFSET) // if our official z position is AVATAR_UNKNOWN_Z_OFFSET, we need a correction. { // set correction if we have it if (avZOffset > 0.1f) { avPos[VZ] = avZOffset; } //schedule offset requests, if needed if (sUseLSLBridge && sFSRadarEnhanceByBridge && (now > (mRadarLastBulkOffsetRequestTime + FSRADAR_COARSE_OFFSET_INTERVAL)) && (now > lastZOffsetTime + FSRADAR_COARSE_OFFSET_INTERVAL)) { mRadarOffsetRequests.push_back(avId); ent->mLastZOffsetTime = now; } } F32 avRange = (avPos[VZ] != AVATAR_UNKNOWN_Z_OFFSET ? dist_vec(avPos, posSelf) : AVATAR_UNKNOWN_RANGE); ent->mRange = avRange; ent->mGlobalPos = avPos; ent->mRegion = avRegion; // //2b. Process newly detected avatars // radarfields_map_t::iterator last_sweep_found_it = mLastRadarSweep.find(avId); if (last_sweep_found_it == mLastRadarSweep.end()) { // chat alerts if (RadarReportChatRangeEnter && (avRange <= chat_range_say) && avRange > AVATAR_UNKNOWN_RANGE) { LLStringUtil::format_map_t args; args["DISTANCE"] = llformat("%3.2f", avRange); std::string message = formatString(str_chat_entering, args); make_ui_sound("UISndRadarChatEnter"); // <FS:PP> FIRE-6069: Radar alerts sounds LLAvatarNameCache::get(avId, boost::bind(&FSRadar::radarAlertMsg, this, _1, _2, message)); } if (RadarReportDrawRangeEnter && (avRange <= drawRadius) && avRange > AVATAR_UNKNOWN_RANGE) { LLStringUtil::format_map_t args; args["DISTANCE"] = llformat("%3.2f", avRange); std::string message = formatString(str_draw_distance_entering, args); make_ui_sound("UISndRadarDrawEnter"); // <FS:PP> FIRE-6069: Radar alerts sounds LLAvatarNameCache::get(avId, boost::bind(&FSRadar::radarAlertMsg, this, _1, _2, message)); } if (RadarReportSimRangeEnter && isInSameRegion) { make_ui_sound("UISndRadarSimEnter"); // <FS:PP> FIRE-6069: Radar alerts sounds if (avRange != AVATAR_UNKNOWN_RANGE) // Don't report an inaccurate range in localchat, if the true range is not known. { LLStringUtil::format_map_t args; args["DISTANCE"] = llformat("%3.2f", avRange); std::string message = formatString(str_region_entering_distance, args); LLAvatarNameCache::get(avId, boost::bind(&FSRadar::radarAlertMsg, this, _1, _2, message)); } else { LLAvatarNameCache::get(avId, boost::bind(&FSRadar::radarAlertMsg, this, _1, _2, str_region_entering)); } } if (RadarEnterChannelAlert || (alertScripts)) { // Autodetect Phoenix chat UUID compatibility. // If Leave channel alerts are not set, restrict reports to same-sim only. if (!RadarLeaveChannelAlert) { if (isInSameRegion) { mRadarEnterAlerts.push_back(avId); } } else { mRadarEnterAlerts.push_back(avId); } } } // // 2c. Process previously detected avatars // else { RadarFields rf = last_sweep_found_it->second; if (RadarReportChatRangeEnter || RadarReportChatRangeLeave) { if (RadarReportChatRangeEnter && (avRange <= chat_range_say && avRange > AVATAR_UNKNOWN_RANGE) && (rf.lastDistance > chat_range_say || rf.lastDistance == AVATAR_UNKNOWN_RANGE)) { LLStringUtil::format_map_t args; args["DISTANCE"] = llformat("%3.2f", avRange); std::string message = formatString(str_chat_entering, args); make_ui_sound("UISndRadarChatEnter"); // <FS:PP> FIRE-6069: Radar alerts sounds LLAvatarNameCache::get(avId, boost::bind(&FSRadar::radarAlertMsg, this, _1, _2, message)); } else if (RadarReportChatRangeLeave && (avRange > chat_range_say || avRange == AVATAR_UNKNOWN_RANGE) && (rf.lastDistance <= chat_range_say && rf.lastDistance > AVATAR_UNKNOWN_RANGE)) { make_ui_sound("UISndRadarChatLeave"); // <FS:PP> FIRE-6069: Radar alerts sounds LLAvatarNameCache::get(avId, boost::bind(&FSRadar::radarAlertMsg, this, _1, _2, str_chat_leaving)); } } if (RadarReportDrawRangeEnter || RadarReportDrawRangeLeave) { if (RadarReportDrawRangeEnter && (avRange <= drawRadius && avRange > AVATAR_UNKNOWN_RANGE) && (rf.lastDistance > drawRadius || rf.lastDistance == AVATAR_UNKNOWN_RANGE)) { LLStringUtil::format_map_t args; args["DISTANCE"] = llformat("%3.2f", avRange); std::string message = formatString(str_draw_distance_entering, args); make_ui_sound("UISndRadarDrawEnter"); // <FS:PP> FIRE-6069: Radar alerts sounds LLAvatarNameCache::get(avId, boost::bind(&FSRadar::radarAlertMsg, this, _1, _2, message)); } else if (RadarReportDrawRangeLeave && (avRange > drawRadius || avRange == AVATAR_UNKNOWN_RANGE) && (rf.lastDistance <= drawRadius && rf.lastDistance > AVATAR_UNKNOWN_RANGE)) { make_ui_sound("UISndRadarDrawLeave"); // <FS:PP> FIRE-6069: Radar alerts sounds LLAvatarNameCache::get(avId, boost::bind(&FSRadar::radarAlertMsg, this, _1, _2, str_draw_distance_leaving)); } } if (RadarReportSimRangeEnter || RadarReportSimRangeLeave) { if (RadarReportSimRangeEnter && isInSameRegion && avRegion != rf.lastRegion && rf.lastRegion.notNull()) { make_ui_sound("UISndRadarSimEnter"); // <FS:PP> FIRE-6069: Radar alerts sounds if (avRange != AVATAR_UNKNOWN_RANGE) // Don't report an inaccurate range in localchat, if the true range is not known. { LLStringUtil::format_map_t args; args["DISTANCE"] = llformat("%3.2f", avRange); std::string message = formatString(str_region_entering_distance, args); LLAvatarNameCache::get(avId, boost::bind(&FSRadar::radarAlertMsg, this, _1, _2, message)); } else { LLAvatarNameCache::get(avId, boost::bind(&FSRadar::radarAlertMsg, this, _1, _2, str_region_entering)); } } else if (RadarReportSimRangeLeave && rf.lastRegion == regionSelf && !isInSameRegion && avRegion.notNull()) { make_ui_sound("UISndRadarSimLeave"); // <FS:PP> FIRE-6069: Radar alerts sounds LLAvatarNameCache::get(avId, boost::bind(&FSRadar::radarAlertMsg, this, _1, _2, str_region_leaving)); } } //If we were manually asked to update an external source for all existing avatars, add them to the queue. if (alertScripts) { mRadarEnterAlerts.push_back(avId); } } // //2d. Prepare data for presentation view for this avatar // if (isInSameRegion) { inSameRegion++; } LLSD entry; LLSD entry_options; entry["id"] = avId; entry["name"] = avName; entry["in_region"] = isInSameRegion; entry["flags"] = avFlag; entry["seen"] = avSeenStr; entry["range"] = (avRange > AVATAR_UNKNOWN_RANGE ? llformat("%3.2f", avRange) : llformat(">%3.2f", drawRadius)); entry["typing"] = (avVo && avVo->isTyping()); entry["sitting"] = (avVo && (avVo->getParent() || avVo->isMotionActive(ANIM_AGENT_SIT_GROUND) || avVo->isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED))); entry["has_notes"] = ent->hasNotes(); if (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) { entry["age"] = (avAge > -1 ? llformat("%d", avAge) : ""); if (ent->hasAlertAge()) { entry_options["age_color"] = LLUIColorTable::instance().getColor("AvatarListItemAgeAlert", LLColor4::red).get().getValue(); if (RadarAvatarAgeAlert && !ent->hasAgeAlertPerformed()) { make_ui_sound("UISndRadarAgeAlert"); LLStringUtil::format_map_t args; args["AGE"] = llformat("%d", avAge); std::string message = formatString(str_avatar_age_alert, args); LLAvatarNameCache::get(avId, boost::bind(&FSRadar::radarAlertMsg, this, _1, _2, message)); } ent->mAgeAlertPerformed = true; } } else { entry["age"] = "---"; } //AO: Set any range colors / styles LLUIColor range_color; if (avRange > AVATAR_UNKNOWN_RANGE) { if (avRange <= chat_range_say) { range_color = LLUIColorTable::instance().getColor("AvatarListItemChatRange", LLColor4::red); inChatRange++; } else if (avRange <= chat_range_shout) { range_color = LLUIColorTable::instance().getColor("AvatarListItemShoutRange", LLColor4::white); } else { range_color = LLUIColorTable::instance().getColor("AvatarListItemBeyondShoutRange", LLColor4::white); } } else { range_color = LLUIColorTable::instance().getColor("AvatarListItemBeyondShoutRange", LLColor4::white); } entry_options["range_color"] = range_color.get().getValue(); // Check if avatar is in draw distance and a VOAvatar instance actually exists if (avRange <= drawRadius && avRange > AVATAR_UNKNOWN_RANGE && avVo) { entry_options["range_style"] = LLFontGL::BOLD; } else { entry_options["range_style"] = LLFontGL::NORMAL; } // Set friends colors / styles LLFontGL::StyleFlags nameCellStyle = LLFontGL::NORMAL; const LLRelationship* relation = LLAvatarTracker::instance().getBuddyInfo(avId); if (relation && !sFSLegacyRadarFriendColoring && !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) { nameCellStyle = (LLFontGL::StyleFlags)(nameCellStyle | LLFontGL::BOLD); } if (is_muted) { nameCellStyle = (LLFontGL::StyleFlags)(nameCellStyle | LLFontGL::ITALIC); } entry_options["name_style"] = nameCellStyle; LLUIColor name_color = LLUIColorTable::instance().getColor("AvatarListItemIconDefaultColor", LLColor4::white); name_color = LGGContactSets::getInstance()->colorize(avId, (sRadarColorNamesByDistance ? range_color : name_color), LGG_CS_RADAR); if (LGGContactSets::getInstance()->hasFriendColorThatShouldShow(avId, LGG_CS_RADAR)) { name_color = LGGContactSets::getInstance()->getFriendColor(avId); } entry_options["name_color"] = name_color.get().getValue(); // Voice power level indicator LLVoiceClient* voice_client = LLVoiceClient::getInstance(); if (voice_client->voiceEnabled() && voice_client->isVoiceWorking()) { LLSpeaker* speaker = LLLocalSpeakerMgr::getInstance()->findSpeaker(avId); if (speaker && speaker->isInVoiceChannel()) { EVoicePowerLevel power_level = voice_client->getPowerLevel(avId); switch (power_level) { case VPL_PTT_Off: entry["voice_level_icon"] = "Radar_VoicePTT_Off"; break; case VPL_PTT_On: entry["voice_level_icon"] = "Radar_VoicePTT_On"; break; case VPL_Level1: entry["voice_level_icon"] = "Radar_VoicePTT_Lvl1"; break; case VPL_Level2: entry["voice_level_icon"] = "Radar_VoicePTT_Lvl2"; break; case VPL_Level3: entry["voice_level_icon"] = "Radar_VoicePTT_Lvl3"; break; default: break; } } } // Save data for our listeners LLSD entry_data; entry_data["entry"] = entry; entry_data["options"] = entry_options; mRadarEntriesData.push_back(entry_data); } // End STEP 2, all model/presentation row processing complete. // //STEP 3, process any bulk actions that require the whole model to be known first // // //3a. dispatch requests for ZOffset updates, working around minimap's inaccurate height // if (mRadarOffsetRequests.size() > 0) { static const std::string prefix = "getZOffsets|"; std::string msg = ""; U32 updatesPerRequest = 0; while (mRadarOffsetRequests.size() > 0) { LLUUID avId = mRadarOffsetRequests.back(); mRadarOffsetRequests.pop_back(); msg = llformat("%s%s,", msg.c_str(), avId.asString().c_str()); if (++updatesPerRequest > FSRADAR_MAX_OFFSET_REQUESTS) { msg = msg.substr(0, msg.size() - 1); FSLSLBridgeRequestResponder* responder = new FSLSLBridgeRequestRadarPosResponder(); FSLSLBridge::instance().viewerToLSL(prefix + msg, responder); //LL_INFOS() << " OFFSET REQUEST SEGMENT"<< prefix << msg << LL_ENDL; msg = ""; updatesPerRequest = 0; } } if (updatesPerRequest > 0) { msg = msg.substr(0, msg.size() - 1); FSLSLBridgeRequestResponder* responder = new FSLSLBridgeRequestRadarPosResponder(); FSLSLBridge::instance().viewerToLSL(prefix + msg, responder); //LL_INFOS() << " OFFSET REQUEST FINAL " << prefix << msg << LL_ENDL; } // clear out the dispatch queue mRadarOffsetRequests.clear(); mRadarLastBulkOffsetRequestTime = now; } // //3b: process alerts for avatars that where here last frame, but gone this frame (ie, they left) // as well as dispatch all earlier detected alerts for crossing range thresholds. // radarfields_map_t::iterator rf_it_end = mLastRadarSweep.end(); for (radarfields_map_t::iterator i = mLastRadarSweep.begin(); i != rf_it_end; ++i) { LLUUID prevId = i->first; RadarFields rf = i->second; if ((RadarShowMutedAndDerendered || !rf.lastIgnore) && mEntryList.find(prevId) == mEntryList.end()) { if (RadarReportChatRangeLeave && (rf.lastDistance <= chat_range_say) && rf.lastDistance > AVATAR_UNKNOWN_RANGE) { make_ui_sound("UISndRadarChatLeave"); // <FS:PP> FIRE-6069: Radar alerts sounds LLAvatarNameCache::get(prevId, boost::bind(&FSRadar::radarAlertMsg, this, _1, _2, str_chat_leaving)); } if (RadarReportDrawRangeLeave && (rf.lastDistance <= drawRadius) && rf.lastDistance > AVATAR_UNKNOWN_RANGE) { make_ui_sound("UISndRadarDrawLeave"); // <FS:PP> FIRE-6069: Radar alerts sounds LLAvatarNameCache::get(prevId, boost::bind(&FSRadar::radarAlertMsg, this, _1, _2, str_draw_distance_leaving)); } if (RadarReportSimRangeLeave && (rf.lastRegion == regionSelf || rf.lastRegion.isNull())) { make_ui_sound("UISndRadarSimLeave"); // <FS:PP> FIRE-6069: Radar alerts sounds LLAvatarNameCache::get(prevId, boost::bind(&FSRadar::radarAlertMsg, this, _1, _2, str_region_leaving)); } if (RadarLeaveChannelAlert) { mRadarLeaveAlerts.push_back(prevId); } } } static LLCachedControl<S32> RadarAlertChannel(gSavedSettings, "RadarAlertChannel"); U32 num_entering = mRadarEnterAlerts.size(); if (num_entering > 0) { mRadarFrameCount++; S32 chan(RadarAlertChannel); U32 num_this_pass = llmin(FSRADAR_MAX_AVATARS_PER_ALERT, num_entering); std::string msg = llformat("%d,%d", mRadarFrameCount, num_this_pass); U32 loop = 0; while (loop < num_entering) { for (S32 i = 0; i < num_this_pass; i++) { msg = llformat("%s,%s", msg.c_str(), mRadarEnterAlerts[loop + i].asString().c_str()); } LLMessageSystem* msgs = gMessageSystem; msgs->newMessage("ScriptDialogReply"); msgs->nextBlock("AgentData"); msgs->addUUID("AgentID", gAgent.getID()); msgs->addUUID("SessionID", gAgent.getSessionID()); msgs->nextBlock("Data"); msgs->addUUID("ObjectID", gAgent.getID()); msgs->addS32("ChatChannel", chan); msgs->addS32("ButtonIndex", 1); msgs->addString("ButtonLabel", msg.c_str()); gAgent.sendReliableMessage(); loop += num_this_pass; num_this_pass = llmin(FSRADAR_MAX_AVATARS_PER_ALERT, num_entering - loop); msg = llformat("%d,%d", mRadarFrameCount, num_this_pass); } } U32 num_leaving = mRadarLeaveAlerts.size(); if (num_leaving > 0) { mRadarFrameCount++; S32 chan(RadarAlertChannel); U32 num_this_pass = llmin(FSRADAR_MAX_AVATARS_PER_ALERT, num_leaving); std::string msg = llformat("%d,-%d", mRadarFrameCount, llmin(FSRADAR_MAX_AVATARS_PER_ALERT, num_leaving)); U32 loop = 0; while (loop < num_leaving) { for (S32 i = 0; i < num_this_pass; i++) { msg = llformat("%s,%s", msg.c_str(), mRadarLeaveAlerts[loop + i].asString().c_str()); } LLMessageSystem* msgs = gMessageSystem; msgs->newMessage("ScriptDialogReply"); msgs->nextBlock("AgentData"); msgs->addUUID("AgentID", gAgent.getID()); msgs->addUUID("SessionID", gAgent.getSessionID()); msgs->nextBlock("Data"); msgs->addUUID("ObjectID", gAgent.getID()); msgs->addS32("ChatChannel", chan); msgs->addS32("ButtonIndex", 1); msgs->addString("ButtonLabel", msg.c_str()); gAgent.sendReliableMessage(); loop += num_this_pass; num_this_pass = llmin(FSRADAR_MAX_AVATARS_PER_ALERT, num_leaving - loop); msg = llformat("%d,-%d", mRadarFrameCount, num_this_pass); } } // reset any active alert requests if (alertScripts) { mRadarAlertRequest = false; } // //STEP 4: Cache our current model data, so we can compare it with the next fresh group of model data for fast change detection. // mLastRadarSweep.clear(); em_it_end = mEntryList.end(); for (entry_map_t::iterator em_it = mEntryList.begin(); em_it != em_it_end; ++em_it) { FSRadarEntry* ent = em_it->second; RadarFields rf; rf.lastDistance = ent->mRange; rf.lastIgnore = ent->mIgnore; rf.lastRegion = LLUUID::null; if (ent->mGlobalPos != LLVector3d(0.0f, 0.0f, 0.0f)) { LLViewerRegion* lastRegion = world->getRegionFromPosGlobal(ent->mGlobalPos); if (lastRegion) { rf.lastRegion = lastRegion->getRegionID(); } } mLastRadarSweep[ent->mID] = rf; } // //STEP 5: Final data updates and notification of subscribers // mAvatarStats["total"] = llformat("%d", mLastRadarSweep.size() - 1); mAvatarStats["region"] = llformat("%d", inSameRegion); mAvatarStats["chatrange"] = llformat("%d", inChatRange); checkTracking(); // Inform our subscribers about updates if (!mUpdateSignal.empty()) { mUpdateSignal(mRadarEntriesData, mAvatarStats); } }