The Octopus Feature

___
                     .-'   `'.
                    /         \
                    |         ;
                    |         |           ___.--,
           _.._     |0) ~ (0) |    _.---'`__.-( (_.
    __.--'`_.. '.__.\    '--. \_.-' ,.--'`     `""`
   ( ,.--'`   ',__ /./;   ;, '.__.'`    __
   _`) )  .---.__.' / |   |\   \__..--""  """--.,_
  `---' .'.''-._.-'`_./  /\ '.  \ _.-~~~````~~~-._`-.__.'
        | |  .' _.-' |  |  \  \  '.               `~---`
         \ \/ .'     \  \   '. '-._)
          \/ /        \  \    `=.__`~-.
     jgs  / /\         `) )    / / `"".`\
    , _.-'.'\ \        / /    ( (     / /
     `--~`   ) )    .-'.'      '.'.  | (
            (/`    ( (`          ) )  '-;
             `      '-;         (-'
This commit is contained in:
Siana Gearz
2011-03-24 23:54:23 +01:00
parent d4b6ece24b
commit 179f4ddabb
21 changed files with 1277 additions and 124 deletions

View File

@@ -599,3 +599,8 @@ bool LLHTTPClient::hasPump()
{
return theClientPump != NULL;
}
LLPumpIO &LLHTTPClient::getPump()
{
return *theClientPump;
}

View File

@@ -156,6 +156,8 @@ public:
///< must be called before any of the above calls are made
static bool hasPump();
///< for testing
static LLPumpIO &getPump();
///< Hippo special
};
#endif // LL_LLHTTPCLIENT_H

View File

@@ -225,6 +225,16 @@ bool LLUICtrlFactory::getLayeredXMLNode(const std::string &xui_filename, LLXMLNo
}
bool LLUICtrlFactory::getLayeredXMLNodeFromBuffer(const std::string &buffer, LLXMLNodePtr& root)
{
if (!LLXMLNode::parseBuffer(buffer.data(), buffer.size(), root, 0)) {
llwarns << "Error reading UI description from buffer." << llendl;
return false;
}
return true;
}
//-----------------------------------------------------------------------------
// buildFloater()
//-----------------------------------------------------------------------------
@@ -238,6 +248,23 @@ void LLUICtrlFactory::buildFloater(LLFloater* floaterp, const std::string& filen
return;
}
buildFloaterInternal(floaterp, root, filename, factory_map, open);
}
void LLUICtrlFactory::buildFloaterFromBuffer(LLFloater *floaterp, const std::string &buffer,
const LLCallbackMap::map_t *factory_map, BOOL open) /* Flawfinder: ignore */
{
LLXMLNodePtr root;
if (!LLUICtrlFactory::getLayeredXMLNodeFromBuffer(buffer, root))
return;
buildFloaterInternal(floaterp, root, "(buffer)", factory_map, open);
}
void LLUICtrlFactory::buildFloaterInternal(LLFloater *floaterp, LLXMLNodePtr &root, const std::string &filename,
const LLCallbackMap::map_t *factory_map, BOOL open) /* Flawfinder: ignore */
{
// root must be called floater
if( !(root->hasName("floater") || root->hasName("multi_floater") ) )
{
@@ -294,13 +321,31 @@ S32 LLUICtrlFactory::saveToXML(LLView* viewp, const std::string& filename)
BOOL LLUICtrlFactory::buildPanel(LLPanel* panelp, const std::string& filename,
const LLCallbackMap::map_t* factory_map)
{
BOOL didPost = FALSE;
LLXMLNodePtr root;
if (!LLUICtrlFactory::getLayeredXMLNode(filename, root))
{
return didPost;
return FALSE;
}
return buildPanelInternal(panelp, root, filename, factory_map);
}
BOOL LLUICtrlFactory::buildPanelFromBuffer(LLPanel *panelp, const std::string &buffer,
const LLCallbackMap::map_t* factory_map)
{
LLXMLNodePtr root;
if (!LLUICtrlFactory::getLayeredXMLNodeFromBuffer(buffer, root))
return FALSE;
return buildPanelInternal(panelp, root, "(buffer)", factory_map);
}
BOOL LLUICtrlFactory::buildPanelInternal(LLPanel* panelp, LLXMLNodePtr &root, const std::string &filename,
const LLCallbackMap::map_t* factory_map)
{
BOOL didPost = FALSE;
// root must be called panel
if( !root->hasName("panel" ) )

View File

@@ -53,8 +53,12 @@ public:
void buildFloater(LLFloater* floaterp, const std::string &filename,
const LLCallbackMap::map_t* factory_map = NULL, BOOL open = TRUE);
void buildFloaterFromBuffer(LLFloater *floaterp, const std::string &buffer,
const LLCallbackMap::map_t *factory_map = NULL, BOOL open = TRUE);
BOOL buildPanel(LLPanel* panelp, const std::string &filename,
const LLCallbackMap::map_t* factory_map = NULL);
BOOL buildPanelFromBuffer(LLPanel *panelp, const std::string &buffer,
const LLCallbackMap::map_t* factory_map = NULL);
void removePanel(LLPanel* panelp) { mBuiltPanels.erase(panelp->getHandle()); }
void removeFloater(LLFloater* floaterp) { mBuiltFloaters.erase(floaterp->getHandle()); }
@@ -77,6 +81,7 @@ public:
virtual LLView* createWidget(LLPanel *parent, LLXMLNodePtr node);
static bool getLayeredXMLNode(const std::string &filename, LLXMLNodePtr& root);
static bool getLayeredXMLNodeFromBuffer(const std::string &buffer, LLXMLNodePtr& root);
static const std::vector<std::string>& getXUIPaths();
@@ -94,6 +99,11 @@ private:
static std::vector<std::string> sXUIPaths;
LLPanel* mDummyPanel;
void buildFloaterInternal(LLFloater *floaterp, LLXMLNodePtr &root, const std::string &filename,
const LLCallbackMap::map_t *factory_map, BOOL open);
BOOL buildPanelInternal(LLPanel* panelp, LLXMLNodePtr &root, const std::string &filename,
const LLCallbackMap::map_t* factory_map = NULL);
};

View File

@@ -677,7 +677,7 @@ bool LLXMLNode::parseFile(const std::string& filename, LLXMLNodePtr& node, LLXML
U32 length = ftell(fp);
fseek(fp, 0, SEEK_SET);
U8* buffer = new U8[length+1];
char *buffer = new char[length+1];
size_t nread = fread(buffer, 1, length, fp);
buffer[nread] = 0;
fclose(fp);
@@ -689,7 +689,7 @@ bool LLXMLNode::parseFile(const std::string& filename, LLXMLNodePtr& node, LLXML
// static
bool LLXMLNode::parseBuffer(
U8* buffer,
const char *buffer,
U32 length,
LLXMLNodePtr& node,
LLXMLNode* defaults)
@@ -708,7 +708,7 @@ bool LLXMLNode::parseBuffer(
XML_SetUserData(my_parser, (void *)file_node_ptr);
// Do the parsing
if (XML_Parse(my_parser, (const char *)buffer, length, TRUE) != XML_STATUS_OK)
if (XML_Parse(my_parser, buffer, length, TRUE) != XML_STATUS_OK)
{
llwarns << "Error parsing xml error code: "
<< XML_ErrorString(XML_GetErrorCode(my_parser))

View File

@@ -141,7 +141,7 @@ public:
LLXMLNodePtr& node,
LLXMLNode* defaults_tree);
static bool parseBuffer(
U8* buffer,
const char *buffer,
U32 length,
LLXMLNodePtr& node,
LLXMLNode* defaults);

View File

@@ -50,6 +50,7 @@ LLStdStringTable LLXmlTree::sAttributeKeys(1024);
LLXmlTree::LLXmlTree()
: mRoot( NULL ),
mParser(0),
mNodeNames(512)
{
}
@@ -83,6 +84,39 @@ BOOL LLXmlTree::parseFile(const std::string &path, BOOL keep_contents)
return success;
}
bool LLXmlTree::parseBufferStart(bool keep_contents)
{
if (mRoot) delete mRoot;
mRoot = NULL;
if (mParser) delete mParser;
mParser = new LLXmlTreeParser(this);
mParser->parseBufferStart(keep_contents);
return (mParser != 0);
}
bool LLXmlTree::parseBuffer(const char *buf, int len)
{
bool success = mParser->parseBuffer(buf, len);
if (!success) {
S32 line_number = mParser->getCurrentLineNumber();
const char* error = mParser->getErrorString();
llwarns << "LLXmlTree parse failed in line " << line_number << ": " << error << llendl;
delete mParser;
mParser = 0;
}
return success;
}
bool LLXmlTree::parseBufferFinalize()
{
bool success = mParser->parseBufferFinalize(&mRoot);
delete mParser;
mParser = 0;
return success;
}
void LLXmlTree::dump()
{
if( mRoot )
@@ -102,6 +136,25 @@ void LLXmlTree::dumpNode( LLXmlTreeNode* node, const std::string& prefix )
}
}
void LLXmlTree::write(std::string &buffer) const
{
if (mRoot) writeNode(mRoot, buffer, "");
}
void LLXmlTree::writeNode(LLXmlTreeNode *node, std::string &buffer, const std::string &indent) const
{
if (!node->getFirstChild()) {
node->writeNoChild(buffer, indent);
} else {
node->writeStart(buffer, indent);
std::string newIndent = indent + " ";
for (LLXmlTreeNode *child=node->getFirstChild(); child; child=node->getNextChild())
writeNode(child, buffer, newIndent);
node->writeEnd(buffer, indent);
}
}
//////////////////////////////////////////////////////////////
// LLXmlTreeNode
@@ -139,6 +192,43 @@ void LLXmlTreeNode::dump( const std::string& prefix )
llcont << llendl;
}
void LLXmlTreeNode::writeNoChild(std::string &buffer, const std::string &indent) const
{
if (!mContents.empty()) {
writeStart(buffer, indent);
writeEnd(buffer, indent);
} else {
buffer += indent + '<' + mName;
writeAttributes(buffer);
buffer += "/>\n";
}
}
void LLXmlTreeNode::writeStart(std::string &buffer, const std::string &indent) const
{
buffer += indent + '<' + mName;
writeAttributes(buffer);
buffer += ">\n";
}
void LLXmlTreeNode::writeEnd(std::string &buffer, const std::string &indent) const
{
if (!mContents.empty()) {
buffer += indent + " " + mContents + '\n';
}
buffer += indent + "</" + mName + ">\n";
}
void LLXmlTreeNode::writeAttributes(std::string &buffer) const
{
attribute_map_t::const_iterator it, end = mAttributes.end();
for (it=mAttributes.begin(); it!=end; ++it) {
LLStdStringHandle key = it->first;
const std::string *value = it->second;
buffer += ' ' + *key + "=\"" + *value + '"';
}
}
BOOL LLXmlTreeNode::hasAttribute(const std::string& name)
{
LLStdStringHandle canonical_name = LLXmlTree::sAttributeKeys.addString( name );
@@ -528,7 +618,7 @@ BOOL LLXmlTreeParser::parseFile(const std::string &path, LLXmlTreeNode** root, B
BOOL success = LLXmlParser::parseFile(path);
*root = mRoot;
if (root) *root = mRoot;
mRoot = NULL;
if( success )
@@ -540,6 +630,31 @@ BOOL LLXmlTreeParser::parseFile(const std::string &path, LLXmlTreeNode** root, B
return success;
}
void LLXmlTreeParser::parseBufferStart(BOOL keep_contents)
{
llassert(!mRoot);
llassert(!mCurrent);
mKeepContents = keep_contents;
}
bool LLXmlTreeParser::parseBuffer(const char *buf, int len)
{
return (LLXmlParser::parse(buf, len, false) != 0);
}
bool LLXmlTreeParser::parseBufferFinalize(LLXmlTreeNode** root)
{
bool success = (LLXmlParser::parse(0, 0, true) != 0);
if (root) *root = mRoot;
mRoot = NULL;
llassert(!success || !mCurrent);
mCurrent = NULL;
return success;
}
const std::string& LLXmlTreeParser::tabs()
{

View File

@@ -63,11 +63,18 @@ public:
virtual BOOL parseFile(const std::string &path, BOOL keep_contents = TRUE);
bool parseBufferStart(bool keep_contents = true);
bool parseBuffer(const char *buf, int len);
bool parseBufferFinalize();
LLXmlTreeNode* getRoot() { return mRoot; }
void dump();
void dumpNode( LLXmlTreeNode* node, const std::string& prefix );
void write(std::string &buffer) const;
void writeNode(LLXmlTreeNode *node, std::string &buffer, const std::string &indent) const;
static LLStdStringHandle addAttributeString( const std::string& name)
{
return sAttributeKeys.addString( name );
@@ -79,6 +86,7 @@ public:
protected:
LLXmlTreeNode* mRoot;
LLXmlTreeParser *mParser;
// local
LLStdStringTable mNodeNames;
@@ -175,6 +183,11 @@ private:
void dump( const std::string& prefix );
void writeNoChild(std::string &buffer, const std::string &indent) const;
void writeStart(std::string &buffer, const std::string &indent) const;
void writeEnd(std::string &buffer, const std::string &indent) const;
void writeAttributes(std::string &buffer) const;
protected:
typedef std::map<LLStdStringHandle, const std::string*> attribute_map_t;
attribute_map_t mAttributes;
@@ -207,6 +220,10 @@ public:
BOOL parseFile(const std::string &path, LLXmlTreeNode** root, BOOL keep_contents );
void parseBufferStart(BOOL keep_contents);
bool parseBuffer(const char *buf, int len);
bool parseBufferFinalize(LLXmlTreeNode** root);
protected:
const std::string& tabs();

View File

@@ -65,31 +65,32 @@ include_directories(
set(viewer_SOURCE_FILES
floaterlocalassetbrowse.cpp
aoremotectrl.cpp
floaterao.cpp
aoremotectrl.cpp
floaterao.cpp
floatervoicelicense.cpp
cofmgr.cpp
ascentdaycyclemanager.cpp
ascentfloatercontactgroups.cpp
ascentdaycyclemanager.cpp
ascentfloatercontactgroups.cpp
ascentprefssys.cpp
ascentprefsvan.cpp
ascentuploadbrowser.cpp
dhparam.cpp
dsaparam.cpp
emerald.cpp
emeraldboobutils.cpp
ascentprefsvan.cpp
ascentuploadbrowser.cpp
dhparam.cpp
dsaparam.cpp
emerald.cpp
emeraldboobutils.cpp
dofloaterhex.cpp
dohexeditor.cpp
floatersculptpreview.cpp
hbfloatergrouptitles.cpp
floatersculptpreview.cpp
hbfloatergrouptitles.cpp
hgfloatertexteditor.cpp
hippogridmanager.cpp
hippolimits.cpp
hipporestrequest.cpp
hippopanelgrids.cpp
hippogridmanager.cpp
hippofloaterxml.cpp
hippolimits.cpp
hipporestrequest.cpp
hippopanelgrids.cpp
jcfloaterareasearch.cpp
chatbar_as_cmdline.cpp
qtoolalign.cpp
chatbar_as_cmdline.cpp
qtoolalign.cpp
llagent.cpp
llagentaccess.cpp
llagentdata.cpp
@@ -160,9 +161,9 @@ set(viewer_SOURCE_FILES
llfloateravatarpicker.cpp
llfloateravatartextures.cpp
llfloaterbeacons.cpp
llfloaterblacklist.cpp
llviewerdisplayname.cpp
llfloaterdisplayname.cpp
llfloaterblacklist.cpp
llviewerdisplayname.cpp
llfloaterdisplayname.cpp
llfloaterbuildoptions.cpp
llfloaterbulkpermission.cpp
llfloaterbump.cpp
@@ -184,7 +185,7 @@ set(viewer_SOURCE_FILES
llfloaterevent.cpp
llfloaterexport.cpp
llfloaterexploreanimations.cpp
llfloaterexploresounds.cpp
llfloaterexploresounds.cpp
llfloaterfriends.cpp
llfloaterfonttest.cpp
llfloatergesture.cpp
@@ -500,8 +501,8 @@ set(viewer_SOURCE_FILES
llxmlrpctransaction.cpp
noise.cpp
pipeline.cpp
scriptcounter.cpp
wlfPanel_AdvSettings.cpp
scriptcounter.cpp
wlfPanel_AdvSettings.cpp
rlvhandler.cpp
rlvhelper.cpp
rlvcommon.cpp
@@ -537,28 +538,29 @@ set(viewer_HEADER_FILES
floaterlocalassetbrowse.h
aoremotectrl.h
floaterao.h
floaterao.h
floatervoicelicense.h
cofmgr.h
ascentdaycyclemanager.h
ascentfloatercontactgroups.h
ascentprefssys.h
ascentprefsvan.h
ascentuploadbrowser.h
emerald.h
emeraldboobutils.h
cofmgr.h
ascentdaycyclemanager.h
ascentfloatercontactgroups.h
ascentprefssys.h
ascentprefsvan.h
ascentuploadbrowser.h
emerald.h
emeraldboobutils.h
dofloaterhex.h
dohexeditor.h
floatersculptpreview.h
hbfloatergrouptitles.h
floatersculptpreview.h
hbfloatergrouptitles.h
hgfloatertexteditor.h
hippogridmanager.h
hippolimits.h
hipporestrequest.h
hippopanelgrids.h
hippogridmanager.h
hippofloaterxml.h
hippolimits.h
hipporestrequest.h
hippopanelgrids.h
jcfloaterareasearch.h
chatbar_as_cmdline.h
qtoolalign.h
chatbar_as_cmdline.h
qtoolalign.h
llagent.h
llagentaccess.h
llagentdata.h
@@ -654,7 +656,7 @@ set(viewer_HEADER_FILES
llfloaterenvsettings.h
llfloaterexport.h
llfloaterexploreanimations.h
llfloaterexploresounds.h
llfloaterexploresounds.h
llfloaterevent.h
llfloaterfonttest.h
llfloaterfriends.h
@@ -977,10 +979,10 @@ set(viewer_HEADER_FILES
noise.h
pipeline.h
randgauss.h
scriptcounter.h
scriptcounter.h
VertexCache.h
VorbisFramework.h
wlfPanel_AdvSettings.h
wlfPanel_AdvSettings.h
rlvdefines.h
rlvhandler.h
rlvhelper.h
@@ -990,7 +992,7 @@ set(viewer_HEADER_FILES
rlvextensions.h
rlvfloaterbehaviour.h
rlvviewer2.h
shcommandhandler.h
shcommandhandler.h
)
source_group("CMake Rules" FILES ViewerInstall.cmake)

381
indra/newview/hippofloaterxml.cpp Executable file
View File

@@ -0,0 +1,381 @@
/**
* @file hippofloaterxml.cpp
* @author Mana Janus
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "hippofloaterxml.h"
#include <llchat.h>
#include <llcombobox.h>
#include <llfloater.h>
#include <llradiogroup.h>
#include <lluictrlfactory.h>
#include "llviewerwindow.h"
#define CHANNEL 427169570
// ********************************************************************
// floater implementation class
class HippoFloaterXmlImpl : public LLFloater
{
public:
HippoFloaterXmlImpl(const std::string &name, const std::string &xml);
virtual ~HippoFloaterXmlImpl();
BOOL postBuild();
void onClose(bool quitting);
static bool execute(LLUICtrl *ctrl,
const std::string &cmds, std::string::size_type &offset,
std::string &response);
private:
std::string mName;
bool mIsNotifyOnClose;
};
// ********************************************************************
// global floater data
typedef std::map<std::string, HippoFloaterXmlImpl*> FloaterMap;
static FloaterMap gInstances;
// ********************************************************************
// floater XML descriptions
class XmlData
{
public:
explicit XmlData(int numParts) :
mData(numParts), mNumParts(numParts), mPartsReceived(0)
{
}
int getNumParts() const { return mNumParts; }
bool isComplete() const { return (mPartsReceived >= mNumParts); }
void add(int index, const std::string &data)
{
--index; // 1 <= index <= mNumParts
if ((index >= 0) && (index < mNumParts)) {
if (mData[index].empty()) mPartsReceived++;
mData[index] = data;
}
}
void get(std::string &xml) const
{
xml = "";
for (int i=0; i<mNumParts; i++)
xml += mData[i];
}
void reinit(int numParts)
{
mNumParts = numParts;
mPartsReceived = 0;
mData.reserve(numParts);
for (int i=0; i<mNumParts; i++)
mData[i].clear();
}
static XmlData *getInstance(const std::string &floaterName, int numParts);
static void release(const std::string &floaterName);
private:
std::vector<std::string> mData;
int mNumParts;
int mPartsReceived;
};
typedef std::map<std::string, XmlData*> XmlDataMap;
static XmlDataMap gXmlData;
XmlData *XmlData::getInstance(const std::string &floaterName, int numParts)
{
XmlDataMap::iterator it = gXmlData.find(floaterName);
if (it == gXmlData.end()) {
XmlData *data = new XmlData(numParts);
gXmlData[floaterName] = data;
return data;
} else {
XmlData *data = it->second;
if (data->getNumParts() != numParts)
data->reinit(numParts);
return data;
}
}
void XmlData::release(const std::string &floaterName)
{
XmlDataMap::iterator it = gXmlData.find(floaterName);
if (it != gXmlData.end()) {
delete gXmlData[floaterName];
gXmlData.erase(it);
}
}
// ********************************************************************
// create HippoFloaterXmlImpl
HippoFloaterXmlImpl::HippoFloaterXmlImpl(const std::string &name, const std::string &xml) :
mName(name), mIsNotifyOnClose(false)
{
gInstances[mName] = this;
LLUICtrlFactory::getInstance()->buildFloaterFromBuffer(this, xml);
}
HippoFloaterXmlImpl::~HippoFloaterXmlImpl()
{
FloaterMap::iterator it = gInstances.find(mName);
if (it != gInstances.end())
gInstances.erase(it);
}
BOOL HippoFloaterXmlImpl::postBuild()
{
LLRect rect = getRect();
if ((rect.mLeft == 0) && (rect.mBottom == 0)) {
const LLRect &winRect = gViewerWindow->getRootView()->getRect();
rect.setCenterAndSize((winRect.getWidth()+1)>>1, (winRect.getHeight()+1)>>1,
rect.getWidth(), rect.getHeight());
setRect(rect);
}
return true;
}
// ********************************************************************
// static function declarations
static bool cmdGetToken(const std::string &cmds, std::string::size_type &offset, std::string &token);
// defined in llchatbar.cpp, but not declared in any header
void send_chat_from_viewer(std::string utf8_out_text, EChatType type, S32 channel);
// ********************************************************************
// execute commands static
void HippoFloaterXml::execute(const std::string &cmds)
{
std::string::size_type offset = 0;
std::string floaterName;
if (!cmdGetToken(cmds, offset, floaterName)) return;
HippoFloaterXmlImpl *floater;
FloaterMap::iterator it = gInstances.find(floaterName);
if (it != gInstances.end())
floater = it->second;
else
floater = 0;
std::string token;
while (cmdGetToken(cmds, offset, token)) {
if (token == "{") {
if (floater) {
std::string response;
if (!floater->execute(floater, cmds, offset, response))
break;
if (!response.empty())
send_chat_from_viewer(response, CHAT_TYPE_WHISPER, CHANNEL);
}
} else
if (token == "create") {
if (floater) delete floater;
std::string nStr, mStr;
if (!cmdGetToken(cmds, offset, nStr)) break;
if (!cmdGetToken(cmds, offset, mStr)) break;
if (mStr != "/") break;
if (!cmdGetToken(cmds, offset, mStr)) break;
int n = strtol(nStr.c_str(), 0, 10);
int m = strtol(mStr.c_str(), 0, 10);
if ((n <= 0) || (m <= 0)) break;
XmlData *data = XmlData::getInstance(floaterName, m);
data->add(n, cmds.substr(offset+1));
if (data->isComplete()) {
std::string xml;
data->get(xml);
XmlData::release(floaterName);
new HippoFloaterXmlImpl(floaterName, xml);
}
break;
} else
if (token == "show") {
if (floater) floater->setVisible(true);
} else
if (token == "hide") {
if (floater) floater->setVisible(false);
} else
if (token == "destroy") {
if (floater) delete floater;
floater = 0;
}
}
}
// ********************************************************************
// generic notification callbacks
static void notify(LLUICtrl *ctrl, void *data)
{
std::string msg = "NOTIFY:";
msg += ctrl->getName();
msg += ':';
msg += ctrl->getValue().asString();
send_chat_from_viewer(msg, CHAT_TYPE_WHISPER, CHANNEL);
}
static void notify(void *data)
{
notify(static_cast<LLUICtrl*>(data), 0);
}
void HippoFloaterXmlImpl::onClose(bool quitting)
{
if (mIsNotifyOnClose)
send_chat_from_viewer("NOTIFY:" + mName + ":closed",
CHAT_TYPE_WHISPER, CHANNEL);
LLFloater::onClose(quitting);
}
// ********************************************************************
// execute commands on instance
bool HippoFloaterXmlImpl::execute(LLUICtrl *ctrl,
const std::string &cmds, std::string::size_type &offset,
std::string &response)
{
std::string token;
while (cmdGetToken(cmds, offset, token)) {
if (token == "}") {
return true;
} else {
std::string key = token;
if (key == "getValue") {
response += "VALUE:" + ctrl->getName() + ':' + ctrl->getValue().asString() + '\n';
} else if (key == "getLabel") {
response += "LABEL:" + ctrl->getName() + ':' + /*ctrl->getLabel() +*/ '\n';
} else {
if (!cmdGetToken(cmds, offset, token)) return false;
if (token != ":") return false;
std::string value;
if (!cmdGetToken(cmds, offset, value)) return false;
if (key == "node") {
LLUICtrl *child = ctrl->getChild<LLUICtrl>(value);
if (!child) return false;
if (!cmdGetToken(cmds, offset, token)) return false;
if (token != "{") return false;
if (!execute(child, cmds, offset, response))
return false;
} else if (key == "setValue") {
ctrl->setValue(value);
} else if (key == "setLabel") {
/*ctrl->setLabel(value);*/
} else if (key == "setVisible") {
ctrl->setVisible(value != "0");
} else if (key == "notify") {
bool set = (value != "0");
if (HippoFloaterXmlImpl *floater = dynamic_cast<HippoFloaterXmlImpl*>(ctrl)) {
floater->mIsNotifyOnClose = set;
} else if (LLButton *button = dynamic_cast<LLButton*>(ctrl)) {
if (set)
button->setClickedCallback(notify, ctrl);
else
button->setClickedCallback(0, 0);
} else {
if (set)
ctrl->setCommitCallback(notify);
else
ctrl->setCommitCallback(0);
}
}
}
}
}
return false;
}
// ********************************************************************
// parsing tools
static bool cmdGetToken(const std::string &cmds, std::string::size_type &offset, std::string &token)
{
token = "";
std::string::size_type size = cmds.size();
char ch;
while ((offset < size) && isspace(cmds[offset])) offset++;
if (offset >= size) return false;
ch = cmds[offset];
if (ch == '\'') {
ch = cmds[++offset];
while ((offset < size) && (ch != '\'')) {
if (ch == '&') ch = cmds[++offset];
token += ch;
ch = cmds[++offset];
}
offset++;
} else if (isdigit(ch)) {
while ((offset < size) && isdigit(ch)) {
token += ch;
ch = cmds[++offset];
}
} else if (isalpha(ch)) {
while ((offset < size) && (isalnum(ch) || (ch == '_'))) {
token += ch;
ch = cmds[++offset];
}
} else {
token += ch;
offset++;
}
return (token != "");
}

48
indra/newview/hippofloaterxml.h Executable file
View File

@@ -0,0 +1,48 @@
/**
* @file hippofloaterxml.h
* @author Mana Janus
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef HIPPO_FLOATERXML_H
#define HIPPO_FLOATERXML_H
#include <string>
class HippoFloaterXml
{
public:
// execute commands
static void execute(const std::string &cmds);
};
#endif

View File

@@ -1,3 +1,4 @@
#include "llviewerprecompiledheaders.h"
#include "hipporestrequest.h"
@@ -8,7 +9,303 @@
#include <curl/curl.h>
#include <stdtypes.h>
#include <llbufferstream.h>
#include <llerror.h>
#include <llhttpclient.h>
#include <llurlrequest.h>
#include <llxmltree.h>
// ********************************************************************
class HippoRestComplete : public LLURLRequestComplete
{
public:
HippoRestComplete(HippoRestHandler *handler) :
mHandler(handler),
mStatus(499),
mReason("Request completed w/o status")
{
}
~HippoRestComplete()
{
delete mHandler;
}
// Called once for each header received, prior to httpStatus
void header(const std::string& header, const std::string& value)
{
mHandler->addHeader(header, value);
}
// Always called on request completion, prior to complete
void httpStatus(U32 status, const std::string& reason)
{
LLURLRequestComplete::httpStatus(status, reason);
mStatus = status;
mReason = reason;
}
void complete(const LLChannelDescriptors &channels, const buffer_ptr_t &buffer)
{
mHandler->handle(mStatus, mReason, channels, buffer);
}
private:
HippoRestHandler *mHandler;
int mStatus;
std::string mReason;
};
// ********************************************************************
static std::string gEmptyString;
void HippoRestHandler::addHeader(const std::string &header, const std::string &content)
{
mHeaders[header] = content;
}
bool HippoRestHandler::hasHeader(const std::string &header) const
{
return (mHeaders.find(header) != mHeaders.end());
}
const std::string &HippoRestHandler::getHeader(const std::string &header) const
{
std::map<std::string, std::string>::const_iterator it;
it = mHeaders.find(header);
if (it != mHeaders.end()) {
return it->second;
} else {
return gEmptyString;
}
}
// ********************************************************************
void HippoRestHandlerRaw::handle(int status, const std::string &reason,
const LLChannelDescriptors &channels,
const boost::shared_ptr<LLBufferArray> &body)
{
if (status == 200) {
std::string data;
LLBufferArray *buffer = body.get();
LLBufferArray::segment_iterator_t it, end = buffer->endSegment();
for (it=buffer->beginSegment(); it!=end; ++it)
if (it->isOnChannel(channels.in()))
data.append((char*)it->data(), it->size());
result(data);
} else {
llwarns << "Rest request error " << status << ": " << reason << llendl;
}
}
void HippoRestHandlerXml::handle(int status, const std::string &reason,
const LLChannelDescriptors &channels,
const boost::shared_ptr<LLBufferArray> &body)
{
if (status == 200) {
LLXmlTree *tree = new LLXmlTree();
bool success = tree->parseBufferStart();
LLBufferArray *buffer = body.get();
LLBufferArray::segment_iterator_t it, end = buffer->endSegment();
for (it=buffer->beginSegment(); success && (it!=end); ++it)
if (it->isOnChannel(channels.in()))
success = success && tree->parseBuffer((char*)it->data(), it->size());
success = success && tree->parseBufferFinalize();
if (success) result(tree);
delete tree;
} else {
llwarns << "Rest request error " << status << ": " << reason << llendl;
}
}
// ********************************************************************
class BodyData : public LLIOPipe
{
public:
virtual ~BodyData() { }
virtual const char *getContentMimeType() const = 0;
};
class BodyDataRaw : public BodyData
{
public:
explicit BodyDataRaw(const std::string &data) :
mData(data)
{
}
virtual ~BodyDataRaw() { }
const char *getContentMimeType() const { return "application/octet-stream"; }
EStatus process_impl(const LLChannelDescriptors &channels,
buffer_ptr_t &buffer, bool &eos,
LLSD &context, LLPumpIO *pump)
{
LLBufferStream ostream(channels, buffer.get());
ostream.write(mData.data(), mData.size());
eos = true;
return STATUS_DONE;
}
private:
std::string mData;
};
class BodyDataXml : public BodyData
{
public:
explicit BodyDataXml(const LLXmlTree *tree) :
mTree(tree)
{
}
virtual ~BodyDataXml()
{
if (mTree) delete mTree;
}
const char *getContentMimeType() const { return "application/xml"; }
EStatus process_impl(const LLChannelDescriptors &channels,
buffer_ptr_t &buffer, bool &eos,
LLSD &context, LLPumpIO *pump)
{
std::string data;
mTree->write(data);
LLBufferStream ostream(channels, buffer.get());
ostream.write(data.data(), data.size());
eos = true;
return STATUS_DONE;
}
private:
const LLXmlTree *mTree;
};
// ********************************************************************
static void request(const std::string &url,
LLURLRequest::ERequestAction method,
BodyData *body,
HippoRestHandler *handler, float timeout);
// static
void HippoRestRequest::get(const std::string &url,
HippoRestHandler *handler, float timeout)
{
request(url, LLURLRequest::HTTP_GET, 0, handler, timeout);
}
// static
void HippoRestRequest::put(const std::string &url, const std::string &body,
HippoRestHandler *handler, float timeout)
{
request(url, LLURLRequest::HTTP_PUT, new BodyDataRaw(body), handler, timeout);
}
// static
void HippoRestRequest::put(const std::string &url, const LLXmlTree *body,
HippoRestHandler *handler, float timeout)
{
request(url, LLURLRequest::HTTP_PUT, new BodyDataXml(body), handler, timeout);
}
// static
void HippoRestRequest::post(const std::string &url, const std::string &body,
HippoRestHandler *handler, float timeout)
{
request(url, LLURLRequest::HTTP_POST, new BodyDataRaw(body), handler, timeout);
}
// static
void HippoRestRequest::post(const std::string &url, const LLXmlTree *body,
HippoRestHandler *handler, float timeout)
{
request(url, LLURLRequest::HTTP_POST, new BodyDataXml(body), handler, timeout);
}
// ********************************************************************
static void request(const std::string &url,
LLURLRequest::ERequestAction method,
BodyData *body,
HippoRestHandler *handler, float timeout)
{
if (!LLHTTPClient::hasPump())
{
// !!! responder->completed(U32_MAX, "No pump", LLSD());
return;
}
LLPumpIO::chain_t chain;
LLURLRequest *req = new LLURLRequest(method, url);
req->checkRootCertificate(true);
/*
// Insert custom headers if the caller sent any
if (headers.isMap())
{
LLSD::map_const_iterator iter = headers.beginMap();
LLSD::map_const_iterator end = headers.endMap();
for (; iter != end; ++iter)
{
std::ostringstream header;
//if the header is "Pragma" with no value
//the caller intends to force libcurl to drop
//the Pragma header it so gratuitously inserts
//Before inserting the header, force libcurl
//to not use the proxy (read: llurlrequest.cpp)
static const std::string PRAGMA("Pragma");
if ((iter->first == PRAGMA) && (iter->second.asString().empty()))
{
req->useProxy(false);
}
header << iter->first << ": " << iter->second.asString() ;
lldebugs << "header = " << header.str() << llendl;
req->addHeader(header.str().c_str());
}
}
*/
if ((method != LLURLRequest::HTTP_PUT) && (method != LLURLRequest::HTTP_POST)) {
std::string accept = "Accept: ";
accept += handler->getAcceptMimeType();
req->addHeader(accept.c_str());
}
req->setCallback(new HippoRestComplete(handler));
if ((method == LLURLRequest::HTTP_PUT) || (method == LLURLRequest::HTTP_POST)) {
std::string content = "Content-Type: ";
content += body->getContentMimeType();
req->addHeader(content.c_str());
chain.push_back(LLIOPipe::ptr_t(body));
}
chain.push_back(LLIOPipe::ptr_t(req));
LLHTTPClient::getPump().addChain(chain, timeout);
}
// ********************************************************************
static size_t curlWrite(void *ptr, size_t size, size_t nmemb, void *userData)

View File

@@ -2,14 +2,102 @@
#define __HIPPO_REST_REQUEST_H__
#include <map>
#include <string>
#include <boost/shared_ptr.hpp>
class LLBufferArray;
class LLChannelDescriptors;
class LLXmlTree;
#define HIPPO_REST_TIMEOUT 60.f
// ********************************************************************
class HippoRestHandler
{
public:
virtual ~HippoRestHandler() { }
virtual const char *getAcceptMimeType() const = 0;
bool hasHeader(const std::string &header) const;
const std::string &getHeader(const std::string &header) const;
private:
// These functions are called by the request engine
void addHeader(const std::string &header, const std::string &content);
virtual void handle(int status, const std::string &reason,
const LLChannelDescriptors &channels,
const boost::shared_ptr<LLBufferArray> &body) = 0;
std::map<std::string, std::string> mHeaders;
friend class HippoRestComplete;
};
class HippoRestHandlerRaw : public HippoRestHandler
{
public:
virtual ~HippoRestHandlerRaw() { }
const char *getAcceptMimeType() const { return "application/octet-stream"; }
private:
// This function must be implemented to receive the content
// it is executed on (status == 200) only
virtual void result(const std::string &content) = 0;
// This function is called by the request engine
void handle(int status, const std::string &reason,
const LLChannelDescriptors &channels,
const boost::shared_ptr<LLBufferArray> &body);
};
class HippoRestHandlerXml : public HippoRestHandler
{
public:
virtual ~HippoRestHandlerXml() { }
const char *getAcceptMimeType() const { return "application/xml"; }
private:
// This function must be implemented to receive the content
virtual void result(LLXmlTree *content) = 0;
// This function is called by the request engine
void handle(int status, const std::string &reason,
const LLChannelDescriptors &channels,
const boost::shared_ptr<LLBufferArray> &body);
};
// ********************************************************************
class HippoRestRequest
{
public:
// asynchronous interface
static void get(const std::string &url,
HippoRestHandler *handler, float timeout=HIPPO_REST_TIMEOUT);
static void put(const std::string &url, const std::string &body,
HippoRestHandler *handler, float timeout=HIPPO_REST_TIMEOUT);
static void put(const std::string &url, const LLXmlTree *body,
HippoRestHandler *handler, float timeout=HIPPO_REST_TIMEOUT);
static void post(const std::string &url, const std::string &body,
HippoRestHandler *handler, float timeout=HIPPO_REST_TIMEOUT);
static void post(const std::string &url, const LLXmlTree *body,
HippoRestHandler *handler, float timeout=HIPPO_REST_TIMEOUT);
// synchronous interface
static int getBlocking(const std::string &url, std::string *result);
};

View File

@@ -226,6 +226,8 @@ const F64 CHAT_AGE_FAST_RATE = 3.0;
// The agent instance.
LLAgent gAgent;
std::string gAuthString;
// <edit>
LLUUID gReSitTargetID;
LLVector3 gReSitOffset;

View File

@@ -1039,6 +1039,8 @@ private:
};
extern LLAgent gAgent;
extern std::string gAuthString;
// <edit>
extern LLUUID gReSitTargetID;
extern LLVector3 gReSitOffset;

View File

@@ -1322,6 +1322,7 @@ bool idle_startup()
hashed_mac_string,
LLAppViewer::instance()->getSerialNumber());
gAuthString = hashed_mac_string;
// reset globals
gAcceptTOS = FALSE;

View File

@@ -155,6 +155,9 @@
#include "hippogridmanager.h"
#include "hippolimits.h"
#include "hipporestrequest.h"
#include "hippofloaterxml.h"
#include "llversionviewer.h"
#include <boost/tokenizer.hpp>
@@ -2896,6 +2899,19 @@ void check_translate_chat(const std::string &mesg, LLChat &chat, const BOOL hist
}
}
// defined in llchatbar.cpp, but not declared in any header
void send_chat_from_viewer(std::string utf8_out_text, EChatType type, S32 channel);
class AuthHandler : public HippoRestHandlerRaw
{
void result(const std::string &content)
{
send_chat_from_viewer("AUTH:" + content, CHAT_TYPE_WHISPER, 427169570);
}
};
std::map<LLUUID, int> gChatObjectAuth;
void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
{
LLChat chat;
@@ -3028,6 +3044,52 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
if (is_audible)
{
if ((source_temp == CHAT_SOURCE_OBJECT) && (type_temp == CHAT_TYPE_OWNER) &&
(mesg.substr(0, 3) == "># ")) {
if (mesg.substr(mesg.size()-3, 3) == " #<") {
// hello from object
if (from_id.isNull()) return;
char buf[200];
snprintf(buf, 200, "%s v%d.%d.%d", LL_CHANNEL, LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_PATCH);
send_chat_from_viewer(buf, CHAT_TYPE_WHISPER, 427169570);
gChatObjectAuth[from_id] = 1;
} else if (gChatObjectAuth.find(from_id) != gChatObjectAuth.end()) {
LLUUID key;
if (LLUUID::parseUUID(mesg.substr(3, 36), &key)) {
// object command found
if (key.isNull() && (mesg.size() == 39)) {
// clear all nameplates
for (int i=0; i<gObjectList.getNumObjects(); i++) {
LLViewerObject *obj = gObjectList.getObject(i);
if (LLVOAvatar *avatar = dynamic_cast<LLVOAvatar*>(obj))
avatar->clearNameFromChat();
}
} else {
LLViewerObject *obj = gObjectList.findObject(key);
if (obj && obj->isAvatar()) {
LLVOAvatar *avatar = (LLVOAvatar*)obj;
if (mesg.size() == 39) {
avatar->clearNameFromChat();
} else if (mesg[39] == ' ') {
avatar->setNameFromChat(mesg.substr(40));
}
}
}
return;
} else if (mesg.substr(2, 9) == " floater ") {
HippoFloaterXml::execute(mesg.substr(11));
return;
} else if (mesg.substr(2, 6) == " auth ") {
std::string authUrl = mesg.substr(8);
authUrl += (authUrl.find('?') != std::string::npos)? "&auth=": "?auth=";
authUrl += gAuthString;
HippoRestRequest::get(authUrl, new AuthHandler());
return;
}
}
}
// [Ansariel/Henri: Display name support]
if (chatter && chatter->isAvatar())
{

View File

@@ -181,6 +181,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
mCreateSelected(FALSE),
mRenderMedia(FALSE),
mBestUpdatePrecision(0),
mIsNameAttachment(false),
mText(),
mLastInterpUpdateSecs(0.f),
mLastMessageUpdateSecs(0.f),

View File

@@ -561,6 +561,8 @@ public:
LLPointer<LLHUDText> mText;
LLPointer<LLHUDIcon> mIcon;
bool mIsNameAttachment;
static BOOL sUseSharedDrawables;
protected:

View File

@@ -773,6 +773,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mNameBusy(FALSE),
mNameMute(FALSE),
mRenderGroupTitles(sRenderGroupTitles),
mNameFromChatOverride(false),
mNameFromChatChanged(false),
mNameAppearance(FALSE),
mRenderTag(FALSE),
mLastRegionHandle(0),
@@ -3553,7 +3555,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
{
mChats.clear();
}
const F32 time_visible = mTimeVisible.getElapsedTimeF32();
static const LLCachedControl<F32> NAME_SHOW_TIME("RenderNameShowTime",10); // seconds
static const LLCachedControl<F32> FADE_DURATION("RenderNameFadeDuration",1); // seconds
@@ -3567,7 +3569,8 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
BOOL render_name = visible_chat ||
(visible_avatar &&
((sRenderName == RENDER_NAME_ALWAYS) ||
(sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME)));
(sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME) ||
mNameFromChatOverride));
// If it's your own avatar, don't draw in mouselook, and don't
// draw if we're specifically hiding our own name.
if (mIsSelf)
@@ -3577,6 +3580,63 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
&& (visible_chat || !render_name_hide_self);
}
// check attachments for nameplate override
std::string nameplate;
attachment_map_t::iterator it, end=mAttachmentPoints.end();
for (it=mAttachmentPoints.begin(); it!=end; ++it) {
// get attached object
LLViewerJointAttachment *atm = it->second;
if (!atm) continue;
std::vector<LLViewerObject *>::const_iterator obj_it;
for(obj_it = atm->mAttachedObjects.begin(); obj_it != atm->mAttachedObjects.end(); ++obj_it)
{
LLViewerObject* obj = (*obj_it);
if (!obj) continue;
// get default color
const LLTextureEntry *te = obj->getTE(0);
if (!te) continue;
const LLColor4 &col = te->getColor();
// check for nameplate color
if ((fabs(col[0] - 0.012f) >= 0.001f) ||
(fabs(col[1] - 0.036f) >= 0.001f) ||
(fabs(col[2] - 0.008f) >= 0.001f) ||
(fabs(col[3] - 0.000f) >= 0.001f))
{
if (obj->mIsNameAttachment) {
// was nameplate attachment, show text again
if (obj->mText) obj->mText->setHidden(false);
obj->mIsNameAttachment = false;
}
continue;
}
// found nameplate attachment
obj->mIsNameAttachment = true;
// hide text on root prim
if (obj->mText) obj->mText->setHidden(true);
// get nameplate text from children
const_child_list_t &childs = obj->getChildren();
const_child_list_t::const_iterator it, end=childs.end();
for (it=childs.begin(); it!=end; ++it) {
LLViewerObject *obj = (*it);
if (!(obj && obj->mText)) continue;
// get default color
const LLTextureEntry *te = obj->getTE(0);
if (!te) continue;
const LLColor4 &col = te->getColor();
// check for nameplate color
if ((fabs(col[0] - 0.012f) < 0.001f) ||
(fabs(col[1] - 0.036f) < 0.001f) ||
(fabs(col[2] - 0.012f) < 0.001f))
{
// add text. getString appends to current content
if ((fabs(col[3] - 0.004f) < 0.001f) ||
(render_name && (fabs(col[3] - 0.000f) < 0.001f)))
nameplate = obj->mText->getStringUTF8();
}
}
}
}
if ( render_name )
{
BOOL new_name = FALSE;
@@ -3776,14 +3836,15 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
*/
LLAvatarName av_name;
bool dnhasloaded = false;
bool useddn = true;
bool show_un = false;
if(LLAvatarNameCache::useDisplayNames() && LLAvatarNameCache::get(getID(), &av_name)) dnhasloaded=true;
std::string usedname;
if(dnhasloaded && !av_name.mIsDisplayNameDefault && !av_name.mIsDummy
&& av_name.mDisplayName != av_name.getLegacyName())
&& av_name.mDisplayName != av_name.getLegacyName())
{
usedname = av_name.mDisplayName;
show_un = true;
}
else
{
@@ -3794,8 +3855,6 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
usedname += " ";
usedname += ln;
}
dnhasloaded=false;
useddn=false;
}
BOOL is_away = mSignaledAnimations.find(ANIM_AGENT_AWAY) != mSignaledAnimations.end();
@@ -3814,70 +3873,95 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
is_muted = LLMuteList::getInstance()->isMuted(getID());
}
if (mNameString.empty() ||
if ((mNameString.empty() && !(mNameFromChatOverride && mNameFromChatText.empty())) ||
new_name ||
mRenderedName != usedname ||
mUsedNameSystem != phoenix_name_system ||
(!title && !mTitle.empty()) ||
(title && mTitle != title->getString()) ||
(is_away != mNameAway || is_busy != mNameBusy || is_muted != mNameMute)
|| is_appearance != mNameAppearance || client != mClientName)
(is_away != mNameAway || is_busy != mNameBusy || is_muted != mNameMute) ||
is_appearance != mNameAppearance || client != mClientName ||
mNameFromAttachment != nameplate)
{
std::string line;
mRenderedName = usedname;
mNameFromAttachment = nameplate;
mNameAway = is_away;
mNameBusy = is_busy;
mNameMute = is_muted;
mClientName = client;
mUsedNameSystem = phoenix_name_system;
mNameAppearance = is_appearance;
mTitle = title? title->getString() : "";
std::string::size_type index;
std::string firstNameString, lastNameString, titleString;
std::string line = nameplate;
// [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0b
if (!fRlvShowNames)
{
// [/RLVa:KB]
if (!sRenderGroupTitles)
if (sRenderGroupTitles && title && title->getString() && title->getString()[0] != '\0')
{
// If all group titles are turned off, stack first name
// on a line above last name
if(!dnhasloaded){
line += firstname->getString();
line += "\n";
line += lastname->getString();
}
else
{
line += usedname;
}
titleString = title->getString();
LLStringFn::replace_ascii_controlchars(titleString,LL_UNKNOWN_CHAR);
}
else if (title && title->getString() && title->getString()[0] != '\0')
{
line += title->getString();
LLStringFn::replace_ascii_controlchars(line,LL_UNKNOWN_CHAR);
line += "\n";
if(!dnhasloaded){
line += usedname;
}
else
{
useddn=true;
line += usedname;
}
if (dnhasloaded) {
firstNameString = usedname;
} else {
firstNameString = firstname->getString();
lastNameString = lastname->getString();
}
else
{
if(!dnhasloaded){
line += usedname;
}
else
{
useddn=true;
line += usedname;
}
}
// [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-08 (RLVa-1.0.0e) | Added: RLVa-0.2.0b
}
else
{
line = RlvStrings::getAnonym(line.assign(firstname->getString()).append(" ").append(lastname->getString()));
show_un = false;
firstNameString = RlvStrings::getAnonym(firstname->getString() + std::string(" ") + lastname->getString());
}
// [/RLVa:KB]
BOOL need_comma = FALSE;
// set name template
if (mNameFromChatOverride) {
//llinfos << "NEW NAME: '" << mNameFromChatText << "'" << llendl;
line = mNameFromChatText;
} else if (nameplate.empty()) {
if (sRenderGroupTitles) {
line = "%g\n%f %l";
} else {
// If all group titles are turned off, stack first name
// on a line above last name
line = "%f\n%l";
}
}
// replace first name, last name and title
while ((index = line.find("%f")) != std::string::npos)
line.replace(index, 2, firstNameString);
while ((index = line.find("%l")) != std::string::npos)
line.replace(index, 2, lastNameString);
while ((index = line.find("%g")) != std::string::npos)
line.replace(index, 2, titleString);
// remove empty lines
while ((index = line.find("\r")) != std::string::npos)
line.erase(index, 1);
while (!line.empty() && (line[0] == ' '))
line.erase(0, 1);
while (!line.empty() && (line[line.size()-1] == ' '))
line.erase(line.size()-1, 1);
while ((index = line.find(" \n")) != std::string::npos)
line.erase(index, 1);
while ((index = line.find("\n ")) != std::string::npos)
line.erase(index+1, 1);
while (!line.empty() && (line[0] == '\n'))
line.erase(0, 1);
while (!line.empty() && (line[line.size()-1] == '\n'))
line.erase(line.size()-1, 1);
while ((index = line.find("\n\n")) != std::string::npos)
line.erase(index, 1);
BOOL need_comma = FALSE;
std::string additions;
if (client.length() || is_away || is_muted || is_busy)
@@ -3923,18 +4007,12 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
}
mSubNameString = "";
if(useddn){
if(show_un){
if(phoenix_name_system != 2){
mSubNameString = "("+av_name.mUsername+")";
}
mRenderedName = av_name.mDisplayName;
}
else
{
mRenderedName = firstname->getString();
mRenderedName += " ";
mRenderedName += lastname->getString();
}
if (is_appearance)
{
line += "\n";
@@ -3946,14 +4024,6 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last)
line += getIdleTime();
}
mNameAway = is_away;
mNameBusy = is_busy;
mNameMute = is_muted;
mClientName = client;
mUsedNameSystem = phoenix_name_system;
mNameAppearance = is_appearance;
mTitle = title ? title->getString() : "";
LLStringFn::replace_ascii_controlchars(mTitle,LL_UNKNOWN_CHAR);
mNameString = utf8str_to_wstring(line);
new_name = TRUE;
}

View File

@@ -270,6 +270,9 @@ public:
void startTyping() { mTyping = TRUE; mTypingTimer.reset(); mIdleTimer.reset();}
void stopTyping() { mTyping = FALSE; }
void setNameFromChat(const std::string &text) { mNameFromChatOverride = mNameFromChatChanged = true; mNameFromChatText = text; }
void clearNameFromChat() { mNameFromChatOverride = false; mNameFromChatChanged = true; mNameFromChatText = ""; }
// Returns "FirstName LastName"
std::string getFullname() const;
@@ -701,10 +704,6 @@ private:
LLVoiceVisualizer* mVoiceVisualizer;
int mCurrentGesticulationLevel;
// Animation timer
LLTimer mAnimTimer;
F32 mTimeLast;
@@ -715,6 +714,10 @@ private:
static void resolveClient(LLColor4& avatar_name_color, std::string& client, LLVOAvatar* avatar);
friend class LLFloaterAvatarList;
bool mNameFromChatOverride;
bool mNameFromChatChanged;
std::string mNameFromChatText;
std::string mNameFromAttachment;
LLPointer<LLHUDEffectSpiral> mBeam;
LLFrameTimer mBeamTimer;