bool SHCommandHandler::handleCommand(bool from_chat, const std::string &full_str, const LLUUID &callerid, LLViewerObject *pCaller) { static const LLCachedControl<bool> sh_allow_script_commands("SHAllowScriptCommands",true); //Are script commands enabled? static const LLCachedControl<bool> sh_allow_chat_commands("AscentCmdLine",true); //Are chat commands enabled? static const LLCachedControl<std::string> sh_script_cmd_prefix("SHScriptCommandPrefix","#@#@!");//Incomming script commands are prefixed with this string. static const LLCachedControl<std::string> sh_chat_cmd_prefix("SHChatCommandPrefix",">>"); //Outgoing chat commands are prefixed with this string. static const LLCachedControl<std::string> sh_script_cmd_sep("SHScriptCommandSeparator","|"); //Separator for script commands static const LLCachedControl<std::string> sh_chat_cmd_sep("SHChatCommandSeparator"," "); //Separator for chat commands const char *szPrefix = from_chat ? sh_chat_cmd_prefix.get().c_str() : sh_script_cmd_prefix.get().c_str(); const size_t prefix_len = strlen(szPrefix); if(full_str.length() <= prefix_len || (prefix_len && full_str.substr(0,prefix_len)!=szPrefix)) return false; //Not a command else if(!isalnum(full_str.c_str()[prefix_len])) return false; //Commands must start with a # or letter else if((!from_chat && !sh_allow_script_commands) || (from_chat && !sh_allow_chat_commands)) return !!prefix_len; //These commands are disabled. const std::string trimmed_str = full_str.substr(prefix_len,std::string::npos); typedef boost::char_separator<char> sep_t; const sep_t sep(from_chat ? sh_chat_cmd_sep.get().c_str(): sh_script_cmd_sep.get().c_str(),"", boost::keep_empty_tokens); const boost::tokenizer<sep_t> tokens(trimmed_str, sep); const boost::tokenizer<sep_t>::const_iterator tok_end = tokens.end(); boost::tokenizer<sep_t>::const_iterator tok_iter = tokens.begin(); if(tok_iter == tok_end) //Shouldn't ever be true. return !from_chat && !!prefix_len; //Don't spam if the prefix was correct yet the string was empty. LLSD cmd_args; //Push tokens into LLSD so args can be looked up via args[#] bool found = false; //Return this if found. Also used to determine if cmd_args has been set up. //Now look for the command. std::list<SHCommandHandler*> &CommandList = from_chat ? getChatCommandList() : getScriptCommandList(); std::list<SHCommandHandler*>::iterator cmd_iter = CommandList.begin(); const std::list<SHCommandHandler*>::iterator cmd_end = CommandList.end(); const std::string search_arg = utf8str_tolower(*tok_iter); for(cmd_iter;cmd_iter!=cmd_end;++cmd_iter) { if(search_arg==utf8str_tolower((*cmd_iter)->getName())) { if(!found) { found = true; int i = -1; for(tok_iter;tok_iter!=tok_end;++tok_iter) //Fill the LLSD cmd_args[++i] = (*tok_iter); } (*cmd_iter)->Dispatch(cmd_args,trimmed_str,callerid,pCaller); } } return found || !!prefix_len; //Don't spam if the prefix was correct yet the command wasn't found. }
void LLFloaterAvatarList::assessColumns() { BIND_COLUMN_TO_SETTINGS(LIST_MARK,Mark); BIND_COLUMN_TO_SETTINGS(LIST_POSITION,Position); BIND_COLUMN_TO_SETTINGS(LIST_ALTITUDE,Altitude); BIND_COLUMN_TO_SETTINGS(LIST_ACTIVITY,Activity); BIND_COLUMN_TO_SETTINGS(LIST_AGE,Age); BIND_COLUMN_TO_SETTINGS(LIST_TIME,Time); static const LLCachedControl<bool> hide_client(gSavedSettings, "RadarColumnClientHidden"); static LLCachedControl<S32> width_name(gSavedSettings, "RadarColumnNameWidth"); bool client_hidden = hide_client || gHippoGridManager->getConnectedGrid()->isSecondLife(); LLScrollListColumn* name_col = mAvatarList->getColumn(LIST_AVATAR_NAME); LLScrollListColumn* client_col = mAvatarList->getColumn(LIST_CLIENT); if (client_hidden != !!name_col->mDynamicWidth) { //Don't save if its being hidden because of detected grid. Not that it really matters, as this setting(along with the other RadarColumn*Width settings) //isn't handled in a way that allows it to carry across sessions, but I assume that may want to be fixed in the future.. if(client_hidden && !gHippoGridManager->getConnectedGrid()->isSecondLife() && name_col->getWidth() > 0) width_name = name_col->getWidth(); //MUST call setWidth(0) first to clear out mTotalStaticColumnWidth accumulation in parent before changing the mDynamicWidth value client_col->setWidth(0); name_col->setWidth(0); client_col->mDynamicWidth = !client_hidden; name_col->mDynamicWidth = client_hidden; if(!client_hidden) { name_col->setWidth(llmax(width_name.get(),10)); } } mAvatarList->updateLayout(); }
/** * Redraws the avatar list * Only does anything if the avatar list is visible. * @author Dale Glass */ void LLFloaterAvatarList::refreshAvatarList() { // Don't update list when interface is hidden if (!sInstance->getVisible()) return; // We rebuild the list fully each time it's refreshed // The assumption is that it's faster to refill it and sort than // to rebuild the whole list. LLDynamicArray<LLUUID> selected = mAvatarList->getSelectedIDs(); S32 scrollpos = mAvatarList->getScrollPos(); mAvatarList->deleteAllItems(); LLVector3d mypos = gAgent.getPositionGlobal(); LLVector3d posagent; posagent.setVec(gAgent.getPositionAgent()); LLVector3d simpos = mypos - posagent; std::map<LLUUID, LLAvatarListEntry>::iterator iter; for (iter = mAvatars.begin(); iter != mAvatars.end(); iter++) { LLSD element; LLUUID av_id; std::string av_name; LLAvatarListEntry *entry = &iter->second; // Skip if avatar hasn't been around if (entry->isDead()) { continue; } av_id = entry->getID(); av_name = entry->getName().c_str(); LLVector3d position = entry->getPosition(); BOOL UnknownAltitude = false; LLVector3d delta = position - mypos; F32 distance = (F32)delta.magVec(); if (position.mdV[VZ] == 0.0) { UnknownAltitude = true; distance = 9000.0; } delta.mdV[2] = 0.0f; F32 side_distance = (F32)delta.magVec(); // HACK: Workaround for an apparent bug: // sometimes avatar entries get stuck, and are registered // by the client as perpetually moving in the same direction. // this makes sure they get removed from the visible list eventually //jcool410 -- this f***s up seeing dueds thru minimap data > 1024m away, so, lets just say > 2048m to the side is bad //aka 8 sims if (side_distance > 2048.0f) { continue; } if (av_id.isNull()) { //llwarns << "Avatar with null key somehow got into the list!" << llendl; continue; } element["id"] = av_id; element["columns"][LIST_MARK]["column"] = "marked"; element["columns"][LIST_MARK]["type"] = "text"; if (entry->isMarked()) { element["columns"][LIST_MARK]["value"] = "X"; element["columns"][LIST_MARK]["color"] = LLColor4::blue.getValue(); element["columns"][LIST_MARK]["font-style"] = "BOLD"; } else { element["columns"][LIST_MARK]["value"] = ""; } element["columns"][LIST_AVATAR_NAME]["column"] = "avatar_name"; element["columns"][LIST_AVATAR_NAME]["type"] = "text"; element["columns"][LIST_AVATAR_NAME]["value"] = av_name; if (entry->isFocused()) { element["columns"][LIST_AVATAR_NAME]["font-style"] = "BOLD"; } //<edit> custom colors for certain types of avatars! //Changed a bit so people can modify them in settings. And since they're colors, again it's possibly account-based. Starting to think I need a function just to determine that. - HgB //element["columns"][LIST_AVATAR_NAME]["color"] = gColors.getColor( "MapAvatar" ).getValue(); LLViewerRegion* parent_estate = LLWorld::getInstance()->getRegionFromPosGlobal(entry->getPosition()); LLUUID estate_owner = LLUUID::null; if(parent_estate && parent_estate->isAlive()) { estate_owner = parent_estate->getOwner(); } //Lindens are always more Linden than your friend, make that take precedence if(LLMuteList::getInstance()->isLinden(av_name)) { static const LLCachedControl<LLColor4> ascent_linden_color("AscentLindenColor",LLColor4(0.f,0.f,1.f,1.f)); element["columns"][LIST_AVATAR_NAME]["color"] = ascent_linden_color.get().getValue(); } //check if they are an estate owner at their current position else if(estate_owner.notNull() && av_id == estate_owner) { static const LLCachedControl<LLColor4> ascent_estate_owner_color("AscentEstateOwnerColor",LLColor4(1.f,0.6f,1.f,1.f)); element["columns"][LIST_AVATAR_NAME]["color"] = ascent_estate_owner_color.get().getValue(); } //without these dots, SL would suck. else if(is_agent_friend(av_id)) { static const LLCachedControl<LLColor4> ascent_friend_color("AscentFriendColor",LLColor4(1.f,1.f,0.f,1.f)); element["columns"][LIST_AVATAR_NAME]["color"] = ascent_friend_color.get().getValue(); } //big fat jerkface who is probably a jerk, display them as such. else if(LLMuteList::getInstance()->isMuted(av_id)) { static const LLCachedControl<LLColor4> ascent_muted_color("AscentMutedColor",LLColor4(0.7f,0.7f,0.7f,1.f)); element["columns"][LIST_AVATAR_NAME]["color"] = ascent_muted_color.get().getValue(); } char temp[32]; LLColor4 color = LLColor4::black; element["columns"][LIST_DISTANCE]["column"] = "distance"; element["columns"][LIST_DISTANCE]["type"] = "text"; if (UnknownAltitude) { strcpy(temp, "?"); if (entry->isDrawn()) { color = LLColor4::green2; } } else { if (distance < 100.0) { snprintf(temp, sizeof(temp), "%.1f", distance); if (distance > 20.0f) { color = LLColor4::yellow1; } else { color = LLColor4::red; } } else { if (entry->isDrawn()) { color = LLColor4::green2; } snprintf(temp, sizeof(temp), "%d", (S32)distance); } } element["columns"][LIST_DISTANCE]["value"] = temp; element["columns"][LIST_DISTANCE]["color"] = color.getValue(); position = position - simpos; S32 x = (S32)position.mdV[VX]; S32 y = (S32)position.mdV[VY]; if (x >= 0 && x <= 256 && y >= 0 && y <= 256) { snprintf(temp, sizeof(temp), "%d, %d", x, y); } else { temp[0] = '\0'; if (y < 0) { strcat(temp, "S"); } else if (y > 256) { strcat(temp, "N"); } if (x < 0) { strcat(temp, "W"); } else if (x > 256) { strcat(temp, "E"); } } element["columns"][LIST_POSITION]["column"] = "position"; element["columns"][LIST_POSITION]["type"] = "text"; element["columns"][LIST_POSITION]["value"] = temp; element["columns"][LIST_ALTITUDE]["column"] = "altitude"; element["columns"][LIST_ALTITUDE]["type"] = "text"; if (UnknownAltitude) { strcpy(temp, "?"); } else { snprintf(temp, sizeof(temp), "%d", (S32)position.mdV[VZ]); } element["columns"][LIST_ALTITUDE]["value"] = temp; element["columns"][LIST_CLIENT]["column"] = "client"; element["columns"][LIST_CLIENT]["type"] = "text"; element["columns"][LIST_METADATA]["column"] = "metadata"; element["columns"][LIST_METADATA]["type"] = "text"; static const LLCachedControl<LLColor4> avatar_name_color("AvatarNameColor",LLColor4(LLColor4U(251, 175, 93, 255)), gColors ); static const LLCachedControl<LLColor4> unselected_color("ScrollUnselectedColor",LLColor4(LLColor4U(0, 0, 0, 204)), gColors ); LLColor4 name_color(avatar_name_color); std::string client; LLVOAvatar *avatarp = gObjectList.findAvatar(av_id); if(avatarp) { avatarp->getClientInfo(client, name_color, TRUE); if(client == "") { name_color = unselected_color; client = "?"; } element["columns"][LIST_CLIENT]["value"] = client.c_str(); // <dogmode> // Don't expose Emerald's metadata. if(avatarp->extraMetadata.length()) { element["columns"][LIST_METADATA]["value"] = avatarp->extraMetadata.c_str(); } } else { element["columns"][LIST_CLIENT]["value"] = "Out Of Range"; } //Blend to make the color show up better name_color = name_color *.5f + unselected_color * .5f; element["columns"][LIST_CLIENT]["color"] = avatar_name_color.get().getValue(); // Add to list mAvatarList->addElement(element, ADD_BOTTOM); } // finish mAvatarList->sortItems(); mAvatarList->selectMultiple(selected); mAvatarList->setScrollPos(scrollpos); // llinfos << "radar refresh: done" << llendl; }
void LLConsole::draw() { LLGLSUIDefault gls_ui; { LLMutexLock lock(&mQueueMutex); for(paragraph_t::iterator paragraph_it = mNewParagraphs.begin(); paragraph_it != mNewParagraphs.end(); paragraph_it++) { Paragraph* paragraph = *paragraph_it; mParagraphs.push_back(paragraph); paragraph->updateLines((F32)getRect().getWidth(), mFont); } mNewParagraphs.clear(); } if (mParagraphs.empty()) //No text to draw. { return; } // skip lines added more than mLinePersistTime ago F32 cur_time = mTimer.getElapsedTimeF32(); F32 skip_time = cur_time - mLinePersistTime; F32 fade_time = cur_time - mFadeTime; static const LLCachedControl<S32> max_lines("ConsoleMaxLines"); U32 num_lines=0; paragraph_t::reverse_iterator paragraph_it; paragraph_it = mParagraphs.rbegin(); U32 paragraph_num=mParagraphs.size(); while (!mParagraphs.empty() && paragraph_it != mParagraphs.rend()) { num_lines += (*paragraph_it)->mLines.size(); if(num_lines > (U32)max_lines.get() || ( (mLinePersistTime > (F32)0.f) && ((*paragraph_it)->mAddTime - skip_time)/(mLinePersistTime - mFadeTime) <= (F32)0.f)) { //All lines above here are done. Lose them. for (U32 i=0;i<paragraph_num;i++) { if (!mParagraphs.empty()) { Paragraph* paragraph = mParagraphs.front(); mParagraphs.pop_front(); delete paragraph; } } break; } paragraph_num--; paragraph_it++; } if (mParagraphs.empty()) { return; } // draw remaining lines F32 y_pos = 0.f; LLUIImagePtr imagep = LLUI::getUIImage("rounded_square.tga"); static const LLCachedControl<F32> console_background_opacity("ConsoleBackgroundOpacity"); F32 console_opacity = llclamp(console_background_opacity.get(), 0.f, 1.f); static const LLCachedControl<LLColor4> console_background(gColors,"ConsoleBackground"); LLColor4 color = console_background; color.mV[VALPHA] *= console_opacity; F32 line_height = mFont->getLineHeight(); S32 message_spacing = 0; //080813 Spatters: This section makes a single huge black box behind all the text. S32 bkg_height=8; S32 bkg_width=0; // VWR-8999 // ChatSpacing: 0 -- chat lines are close together, as they were in the 1.20 viewer. // 4 -- chat lines are farther apart as they are in SnowGlobe 1.4. static LLCachedControl<S32> chat_spacing("ChatSpacing", 0); // Perform clamping. S32 const clamped_chat_spacing = llclamp((S32)chat_spacing, -16, 128); if (chat_spacing != clamped_chat_spacing) { chat_spacing = clamped_chat_spacing; } // Adjust spacing. message_spacing += chat_spacing; bkg_height -= chat_spacing; for(paragraph_it = mParagraphs.rbegin(); paragraph_it != mParagraphs.rend(); paragraph_it++) { S32 target_height = llfloor( (*paragraph_it)->mLines.size() * line_height + message_spacing); S32 target_width = llfloor( (*paragraph_it)->mMaxWidth + CONSOLE_GUTTER_RIGHT); bkg_height+= target_height; if (target_width > bkg_width) { bkg_width=target_width; } // Why is this not using llfloor as above? y_pos += ((*paragraph_it)->mLines.size()) * line_height; y_pos += message_spacing; //Extra spacing between messages. } imagep->drawSolid(-CONSOLE_GUTTER_LEFT, (S32)(y_pos + line_height - bkg_height - message_spacing), bkg_width, bkg_height, color); y_pos = 0.f; //End screen-eating black void for(paragraph_it = mParagraphs.rbegin(); paragraph_it != mParagraphs.rend(); paragraph_it++) { //080813 Spatters: Dainty per-message block boxes // S32 target_height = llfloor( (*paragraph_it)->mLines.size() * line_height + 8); S32 target_width = llfloor( (*paragraph_it)->mMaxWidth + CONSOLE_GUTTER_RIGHT); y_pos += ((*paragraph_it)->mLines.size()) * line_height; //080813 Spatters: Dainty per-message block boxes // imagep->drawSolid(-14, (S32)(y_pos + line_height - target_height), target_width, target_height, color); F32 y_off=0; F32 alpha; if ((mLinePersistTime > 0.f) && ((*paragraph_it)->mAddTime < fade_time)) { alpha = ((*paragraph_it)->mAddTime - skip_time)/(mLinePersistTime - mFadeTime); } else { alpha = 1.0f; } if( alpha > 0.f ) { for (lines_t::iterator line_it=(*paragraph_it)->mLines.begin(); line_it != (*paragraph_it)->mLines.end(); line_it ++) { for (line_color_segments_t::iterator seg_it = (*line_it).begin(); seg_it != (*line_it).end(); seg_it++) { mFont->render((*seg_it).mText, 0, (*seg_it).mXPosition - 8, y_pos - y_off, LLColor4( (*seg_it).mColor.mV[VRED], (*seg_it).mColor.mV[VGREEN], (*seg_it).mColor.mV[VBLUE], (*seg_it).mColor.mV[VALPHA]*alpha), LLFontGL::LEFT, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::DROP_SHADOW, S32_MAX, target_width ); } y_off += line_height; } } y_pos += message_spacing; //Extra spacing between messages. } }