FIRE-3192: Predictive name completion in nearby chat, derived from Satomi Ahn's implementation

meow-7.2.2
Cinders 2013-04-25 11:28:27 -06:00
parent bbdb1929b2
commit 2ba94087cd
2 changed files with 125 additions and 1 deletions

View File

@ -18755,7 +18755,7 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>FSChatbarGestureAutoCompleteEnable</key>
<map>
<key>Comment</key>
<string>Toggles the auto complete in chat bar</string>
<string>Toggles gesture auto complete in chat bar</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -18763,6 +18763,17 @@ Change of this parameter will affect the layout of buttons in notification toast
<key>Value</key>
<integer>1</integer>
</map>
<key>FSChatBarNamePrediction</key>
<map>
<key>Comment</key>
<string>Toggles name prediction in nearby chat</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>FSDisableAvatarTrackerAtCloseIn</key>
<map>
<key>Comment</key>

View File

@ -88,6 +88,11 @@
// #include "llanimationstates.h" // ANIM_AGENT_WHISPER, ANIM_AGENT_TALK, ANIM_AGENT_SHOUT
// #include "llviewerstats.h"
// </FS:Zi>
// <FS:CR> FIRE-3192 - Name Prediction
#include "llworld.h"
#define NAME_PREDICTION_MINIMUM_LENGTH 2
// </FS:CR>
static LLDefaultChildRegistry::Register<FSNearbyChatControl> r("fs_nearby_chat_control");
@ -199,6 +204,114 @@ void FSNearbyChatControl::onKeystroke(LLLineEditor* caller,void* userdata)
caller->setCursorToEnd();
}
}
// <FS:CR> FIRE-3192 - Predictive name completion, based on code by Satomi Ahn
static LLCachedControl<bool> sNameAutocomplete(gSavedSettings, "FSChatBarNamePrediction");
if (length > NAME_PREDICTION_MINIMUM_LENGTH && sNameAutocomplete && key < KEY_SPECIAL)
{
std::string text = caller->getText();
S32 cur_pos = caller->getCursor();
if (cur_pos && (text.at(cur_pos - 1) != ' ' || caller->hasSelection()))
{
// Get a list of avatars within range
std::vector<LLUUID> avatar_ids;
std::vector<LLVector3d> positions;
LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgent.getPositionGlobal(), gSavedSettings.getF32("NearMeRange"));
if (avatar_ids.empty()) return; // Nobody's in range!
// Parse text for a pattern to search
std::string prefix = text.substr(0, cur_pos); // Text before search string
std::string suffix = text.substr(cur_pos, text.length() - cur_pos); // Text after search string
U32 last_space = prefix.rfind(" ");
std::string pattern = prefix.substr(last_space + 1, prefix.length() - last_space - 1); // Search pattern
prefix = prefix.substr(0, last_space + 1);
std::string match_pattern = "";
if (pattern.size() < NAME_PREDICTION_MINIMUM_LENGTH) return;
match_pattern = prefix.substr(last_space + 1, prefix.length() - last_space -1);
prefix = prefix.substr(0, last_space + 1);
LLStringUtil::toLower(pattern);
std::string name;
bool found = false;
bool full_name = false;
std::vector<LLUUID>::iterator iter = avatar_ids.begin();
if (last_space != std::string::npos && !prefix.empty())
{
last_space = prefix.substr(0, prefix.length() - 2).rfind(" ");
match_pattern = prefix.substr(last_space + 1, prefix.length() - last_space -1);
prefix = prefix.substr(0, last_space + 1);
// prepare search pattern
std::string full_pattern(match_pattern + pattern);
LLStringUtil::toLower(full_pattern);
// Look for a match
while (iter != avatar_ids.end() && !found)
{
if ((bool)gCacheName->getFullName(*iter++, name))
{
if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
{
name = RlvStrings::getAnonym(name);
}
LLStringUtil::toLower(name);
found = (name.find(full_pattern) == 0);
}
}
}
if (found)
{
full_name = true; // ignore OnlyFirstName in case we want to disambiguate
}
else if (!pattern.empty()) // if first search did not work, try matching with last word before cursor only
{
prefix += match_pattern; // first part of the pattern wasn't a pattern, so keep it in prefix
LLStringUtil::toLower(pattern);
iter = avatar_ids.begin();
// Look for a match
while (iter != avatar_ids.end() && !found)
{
if ((bool)gCacheName->getFullName(*iter++, name))
{
if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
{
name = RlvStrings::getAnonym(name);
}
LLStringUtil::toLower(name);
found = (name.find(pattern) == 0);
}
}
}
// if we found something by either method, replace the pattern by the avatar name
if (found)
{
std::string name;
gCacheName->getFullName(*(iter - 1), name);
if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES))
{
prefix += RlvStrings::getAnonym(name) + " ";
}
else
{
if (!full_name)
{
U32 space = name.find(" ");
if (space != std::string::npos)
name = name.substr(0, space);
}
prefix += name + " ";
}
caller->setText(prefix + suffix);
caller->setSelection(prefix.length(), cur_pos);
}
}
}
// </FS:CR>
}
BOOL FSNearbyChatControl::matchChatTypeTrigger(const std::string& in_str, std::string* out_str)