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;

}
示例#4
0
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.
	}
}