Merge branch 'master' into DRTVWR-516-maint

master
Andrey Lihatskiy 2021-04-01 20:45:16 +03:00
commit 9fe758e8bc
65 changed files with 6447 additions and 2110 deletions

View File

@ -580,9 +580,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>cc26af2ebfa241891caca829a6e46b88</string>
<string>856ba0e5b7be4bf683cf2849bce845e0</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/65005/607316/dullahan-1.7.0.202008031101_81.3.10_gb223419_chromium-81.0.4044.138-darwin64-546064.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/72458/699860/dullahan-1.7.0.202011160759_81.3.10_gb223419_chromium-81.0.4044.138-darwin64-552313.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
@ -592,9 +592,9 @@
<key>archive</key>
<map>
<key>hash</key>
<string>4e5b9e2fe65d94e30a4f3d831c767199</string>
<string>515950c911a53ff910b18c7c417ea984</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/65004/607304/dullahan-1.7.0.202008031759_81.3.10_gb223419_chromium-81.0.4044.138-windows-546064.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/72460/699870/dullahan-1.7.0.202011161603_81.3.10_gb223419_chromium-81.0.4044.138-windows-552313.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
@ -604,16 +604,16 @@
<key>archive</key>
<map>
<key>hash</key>
<string>6f7bf7f915f3d75dbdad08a2d41ca74e</string>
<string>f1dccbdfe0603f488eeee4c8f518c959</string>
<key>url</key>
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/65003/607308/dullahan-1.7.0.202008031800_81.3.10_gb223419_chromium-81.0.4044.138-windows64-546064.tar.bz2</string>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/72459/699874/dullahan-1.7.0.202011161603_81.3.10_gb223419_chromium-81.0.4044.138-windows64-552313.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
</map>
<key>version</key>
<string>1.7.0.202008031800_81.3.10_gb223419_chromium-81.0.4044.138</string>
<string>1.7.0.202011161603_81.3.10_gb223419_chromium-81.0.4044.138</string>
</map>
<key>elfio</key>
<map>

View File

@ -71,6 +71,7 @@ set(llcommon_SOURCE_FILES
llinitparam.cpp
llinitdestroyclass.cpp
llinstancetracker.cpp
llkeybind.cpp
llleap.cpp
llleaplistener.cpp
llliveappconfig.cpp
@ -182,6 +183,7 @@ set(llcommon_HEADER_FILES
llinitdestroyclass.h
llinitparam.h
llinstancetracker.h
llkeybind.h
llkeythrottle.h
llleap.h
llleaplistener.h

View File

@ -54,6 +54,17 @@ enum ETerrainBrushType
E_LANDBRUSH_INVALID = 6
};
enum EMouseClickType{
CLICK_NONE = -1,
CLICK_LEFT = 0,
CLICK_MIDDLE,
CLICK_RIGHT,
CLICK_BUTTON4,
CLICK_BUTTON5,
CLICK_DOUBLELEFT,
CLICK_COUNT // 'size', CLICK_NONE does not counts
};
// keys
// Bit masks for various keyboard modifier keys.
const MASK MASK_NONE = 0x0000;

View File

@ -0,0 +1,395 @@
/**
* @file llkeybind.cpp
* @brief Information about key combinations.
*
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2019, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llkeybind.h"
#include "llsd.h"
#include "llsdutil.h"
LLKeyData::LLKeyData()
:
mMouse(CLICK_NONE),
mKey(KEY_NONE),
mMask(MASK_NONE),
mIgnoreMasks(false)
{
}
LLKeyData::LLKeyData(EMouseClickType mouse, KEY key, MASK mask)
:
mMouse(mouse),
mKey(key),
mMask(mask),
mIgnoreMasks(false)
{
}
LLKeyData::LLKeyData(EMouseClickType mouse, KEY key, bool ignore_mask)
:
mMouse(mouse),
mKey(key),
mMask(MASK_NONE),
mIgnoreMasks(ignore_mask)
{
}
LLKeyData::LLKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask)
:
mMouse(mouse),
mKey(key),
mMask(mask),
mIgnoreMasks(ignore_mask)
{
}
LLKeyData::LLKeyData(const LLSD &key_data)
{
if (key_data.has("mouse"))
{
mMouse = (EMouseClickType)key_data["mouse"].asInteger();
}
if (key_data.has("key"))
{
mKey = key_data["key"].asInteger();
}
if (key_data.has("ignore_accelerators"))
{
mIgnoreMasks = key_data["ignore_accelerators"];
}
if (key_data.has("mask"))
{
mMask = key_data["mask"].asInteger();
}
}
LLSD LLKeyData::asLLSD() const
{
LLSD data;
data["mouse"] = (LLSD::Integer)mMouse;
data["key"] = (LLSD::Integer)mKey;
data["mask"] = (LLSD::Integer)mMask;
if (mIgnoreMasks)
{
data["ignore_accelerators"] = (LLSD::Boolean)mIgnoreMasks;
}
return data;
}
bool LLKeyData::isEmpty() const
{
return mMouse == CLICK_NONE && mKey == KEY_NONE;
}
void LLKeyData::reset()
{
mMouse = CLICK_NONE;
mKey = KEY_NONE;
mMask = MASK_NONE;
mIgnoreMasks = false;
}
LLKeyData& LLKeyData::operator=(const LLKeyData& rhs)
{
mMouse = rhs.mMouse;
mKey = rhs.mKey;
mMask = rhs.mMask;
mIgnoreMasks = rhs.mIgnoreMasks;
return *this;
}
bool LLKeyData::operator==(const LLKeyData& rhs)
{
if (mMouse != rhs.mMouse) return false;
if (mKey != rhs.mKey) return false;
if (mMask != rhs.mMask) return false;
if (mIgnoreMasks != rhs.mIgnoreMasks) return false;
return true;
}
bool LLKeyData::operator!=(const LLKeyData& rhs)
{
if (mMouse != rhs.mMouse) return true;
if (mKey != rhs.mKey) return true;
if (mMask != rhs.mMask) return true;
if (mIgnoreMasks != rhs.mIgnoreMasks) return true;
return false;
}
bool LLKeyData::canHandle(const LLKeyData& data) const
{
if (data.mKey == mKey
&& data.mMouse == mMouse
&& ((mIgnoreMasks && (data.mMask & mMask) == mMask) || data.mMask == mMask))
{
return true;
}
return false;
}
bool LLKeyData::canHandle(EMouseClickType mouse, KEY key, MASK mask) const
{
if (mouse == mMouse
&& key == mKey
&& ((mIgnoreMasks && (mask & mMask) == mMask) || mask == mMask))
{
return true;
}
return false;
}
// LLKeyBind
LLKeyBind::LLKeyBind(const LLSD &key_bind)
{
if (key_bind.isArray())
{
for (LLSD::array_const_iterator data = key_bind.beginArray(), endLists = key_bind.endArray();
data != endLists;
data++
)
{
mData.push_back(LLKeyData(*data));
}
}
}
bool LLKeyBind::operator==(const LLKeyBind& rhs)
{
U32 size = mData.size();
if (size != rhs.mData.size()) return false;
for (U32 i = 0; i < size; i++)
{
if (mData[i] != rhs.mData[i]) return false;
}
return true;
}
bool LLKeyBind::operator!=(const LLKeyBind& rhs)
{
U32 size = mData.size();
if (size != rhs.mData.size()) return true;
for (U32 i = 0; i < size; i++)
{
if (mData[i] != rhs.mData[i]) return true;
}
return false;
}
bool LLKeyBind::isEmpty() const
{
for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++)
{
if (!iter->isEmpty()) return false;
}
return true;
}
LLSD LLKeyBind::asLLSD() const
{
S32 last = mData.size() - 1;
while (mData[last].empty())
{
last--;
}
LLSD data;
for (S32 i = 0; i <= last; ++i)
{
// append even if empty to not affect visual representation
data.append(mData[i].asLLSD());
}
return data;
}
bool LLKeyBind::canHandle(EMouseClickType mouse, KEY key, MASK mask) const
{
if (mouse == CLICK_NONE && key == KEY_NONE)
{
// assume placeholder
return false;
}
for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++)
{
if (iter->canHandle(mouse, key, mask))
{
return true;
}
}
return false;
}
bool LLKeyBind::canHandleKey(KEY key, MASK mask) const
{
return canHandle(CLICK_NONE, key, mask);
}
bool LLKeyBind::canHandleMouse(EMouseClickType mouse, MASK mask) const
{
return canHandle(mouse, KEY_NONE, mask);
}
bool LLKeyBind::hasKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const
{
if (mouse != CLICK_NONE || key != KEY_NONE)
{
for (data_vector_t::const_iterator iter = mData.begin(); iter != mData.end(); iter++)
{
if (iter->mKey == key
&& iter->mMask == mask
&& iter->mMouse == mouse
&& iter->mIgnoreMasks == ignore)
{
return true;
}
}
}
return false;
}
bool LLKeyBind::hasKeyData(const LLKeyData& data) const
{
return hasKeyData(data.mMouse, data.mKey, data.mMask, data.mIgnoreMasks);
}
bool LLKeyBind::hasKeyData(U32 index) const
{
return mData.size() > index;
}
S32 LLKeyBind::findKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const
{
if (mouse != CLICK_NONE || key != KEY_NONE)
{
for (S32 i = 0; i < mData.size(); ++i)
{
if (mData[i].mKey == key
&& mData[i].mMask == mask
&& mData[i].mMouse == mouse
&& mData[i].mIgnoreMasks == ignore)
{
return i;
}
}
}
return -1;
}
S32 LLKeyBind::findKeyData(const LLKeyData& data) const
{
return findKeyData(data.mMouse, data.mKey, data.mMask, data.mIgnoreMasks);
}
LLKeyData LLKeyBind::getKeyData(U32 index) const
{
if (mData.size() > index)
{
return mData[index];
}
return LLKeyData();
}
bool LLKeyBind::addKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore)
{
if (!hasKeyData(mouse, key, mask, ignore))
{
mData.push_back(LLKeyData(mouse, key, mask, ignore));
return true;
}
return false;
}
bool LLKeyBind::addKeyData(const LLKeyData& data)
{
if (!hasKeyData(data))
{
mData.push_back(data);
return true;
}
return false;
}
void LLKeyBind::replaceKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore, U32 index)
{
replaceKeyData(LLKeyData(mouse, key, mask, ignore), index);
}
void LLKeyBind::replaceKeyData(const LLKeyData& data, U32 index)
{
if (!data.isEmpty())
{
// if both click and key are none (isEmpty()), we are inserting a placeholder, we don't want to reset anything
// otherwise reset identical key
for (data_vector_t::iterator iter = mData.begin(); iter != mData.end(); iter++)
{
if (iter->mKey == data.mKey
&& iter->mMouse == data.mMouse
&& iter->mIgnoreMasks == data.mIgnoreMasks
&& iter->mMask == data.mMask)
{
// Replacing only fully equal combinations even in case 'ignore' is set
// Reason: Simplicity and user might decide to do a 'move' command as W and Shift+Ctrl+W, and 'run' as Shift+W
iter->reset();
break;
}
}
}
if (mData.size() <= index)
{
mData.resize(index + 1);
}
mData[index] = data;
}
void LLKeyBind::resetKeyData(S32 index)
{
if (mData.size() > index)
{
mData[index].reset();
}
}
void LLKeyBind::trimEmpty()
{
S32 last = mData.size() - 1;
while (last >= 0 && mData[last].empty())
{
mData.erase(mData.begin() + last);
last--;
}
}
U32 LLKeyBind::getDataCount()
{
return mData.size();
}

106
indra/llcommon/llkeybind.h Normal file
View File

@ -0,0 +1,106 @@
/**
* @file llkeybind.h
* @brief Information about key combinations.
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_KEYBIND_H
#define LL_KEYBIND_H
#include "indra_constants.h"
// KeyData - single key combination (mouse/mask/keyboard)
class LL_COMMON_API LLKeyData
{
public:
LLKeyData();
LLKeyData(EMouseClickType mouse, KEY key, MASK mask);
LLKeyData(EMouseClickType mouse, KEY key, bool ignore_mask);
LLKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask);
LLKeyData(const LLSD &key_data);
LLSD asLLSD() const;
bool isEmpty() const;
bool empty() const { return isEmpty(); };
void reset();
LLKeyData& operator=(const LLKeyData& rhs);
bool operator==(const LLKeyData& rhs);
bool operator!=(const LLKeyData& rhs);
bool canHandle(const LLKeyData& data) const;
bool canHandle(EMouseClickType mouse, KEY key, MASK mask) const;
EMouseClickType mMouse;
KEY mKey;
MASK mMask;
// Either to expect exact match or ignore not expected masks as long as expected mask-bit is present
bool mIgnoreMasks;
};
// One function can bind to multiple Key options
class LLKeyBind
{
public:
LLKeyBind() {}
LLKeyBind(const LLSD &key_bind);
bool operator==(const LLKeyBind& rhs);
bool operator!=(const LLKeyBind& rhs);
bool isEmpty() const;
bool empty() const { return isEmpty(); };
LLSD asLLSD() const;
bool canHandle(EMouseClickType mouse, KEY key, MASK mask) const;
bool canHandleKey(KEY key, MASK mask) const;
bool canHandleMouse(EMouseClickType mouse, MASK mask) const;
// contains specified combination
bool hasKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const;
bool hasKeyData(const LLKeyData& data) const;
bool hasKeyData(U32 index) const;
// index of contained LLKeyData
S32 findKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore) const;
S32 findKeyData(const LLKeyData& data) const;
LLKeyData getKeyData(U32 index) const;
// these methods enshure there will be no repeats
bool addKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore);
bool addKeyData(const LLKeyData& data);
void replaceKeyData(EMouseClickType mouse, KEY key, MASK mask, bool ignore, U32 index);
void replaceKeyData(const LLKeyData& data, U32 index);
void resetKeyData(S32 index);
void clear() { mData.clear(); }
// if there any empty LLKeyData in the end of the array, remove them
void trimEmpty();
U32 getDataCount();
private:
typedef std::vector<LLKeyData> data_vector_t;
data_vector_t mData;
};
#endif // LL_KEYBIND_H

View File

@ -434,7 +434,7 @@ void LLModel::generateNormals(F32 angle_cutoff)
if (vol_face.mNumIndices > 65535)
{
LL_WARNS() << "Too many vertices for normal generation to work." << LL_ENDL;
LL_WARNS("MESHSKININFO") << "Too many vertices for normal generation to work." << LL_ENDL;
continue;
}
@ -1100,7 +1100,7 @@ bool LLModel::loadModel(std::istream& is)
{
if (!LLSDSerialize::fromBinary(header, is, 1024*1024*1024))
{
LL_WARNS() << "Mesh header parse error. Not a valid mesh asset!" << LL_ENDL;
LL_WARNS("MESHSKININFO") << "Mesh header parse error. Not a valid mesh asset!" << LL_ENDL;
return false;
}
}
@ -1132,7 +1132,7 @@ bool LLModel::loadModel(std::istream& is)
if (header[lod_name[lod]]["offset"].asInteger() == -1 ||
header[lod_name[lod]]["size"].asInteger() == 0 )
{ //cannot load requested LOD
LL_WARNS() << "LoD data is invalid!" << LL_ENDL;
LL_WARNS("MESHSKININFO") << "LoD data is invalid!" << LL_ENDL;
return false;
}
@ -1195,7 +1195,7 @@ bool LLModel::loadModel(std::istream& is)
}
else
{
LL_WARNS() << "unpackVolumeFaces failed!" << LL_ENDL;
LL_WARNS("MESHSKININFO") << "unpackVolumeFaces failed!" << LL_ENDL;
}
return false;
@ -1223,7 +1223,7 @@ bool LLModel::isMaterialListSubset( LLModel* ref )
if (!foundRef)
{
LL_INFOS() << "Could not find material " << mMaterialList[src] << " in reference model " << ref->mLabel << LL_ENDL;
LL_INFOS("MESHSKININFO") << "Could not find material " << mMaterialList[src] << " in reference model " << ref->mLabel << LL_ENDL;
return false;
}
}
@ -1259,7 +1259,7 @@ bool LLModel::matchMaterialOrder(LLModel* ref, int& refFaceCnt, int& modelFaceCn
bool isASubset = isMaterialListSubset( ref );
if ( !isASubset )
{
LL_INFOS()<<"Material of model is not a subset of reference."<<LL_ENDL;
LL_INFOS("MESHSKININFO")<<"Material of model is not a subset of reference."<<LL_ENDL;
return false;
}
@ -1398,6 +1398,14 @@ void LLMeshSkinInfo::fromLLSD(LLSD& skin)
mInvBindMatrix.push_back(mat);
}
if (mJointNames.size() != mInvBindMatrix.size())
{
LL_WARNS("MESHSKININFO") << "Joints vs bind matrix count mismatch. Dropping joint bindings." << LL_ENDL;
mJointNames.clear();
mJointNums.clear();
mInvBindMatrix.clear();
}
}
if (skin.has("bind_shape_matrix"))
@ -1842,14 +1850,14 @@ bool validate_face(const LLVolumeFace& face)
{
if (face.mIndices[i] >= face.mNumVertices)
{
LL_WARNS() << "Face has invalid index." << LL_ENDL;
LL_WARNS("MESHSKININFO") << "Face has invalid index." << LL_ENDL;
return false;
}
}
if (face.mNumIndices % 3 != 0 || face.mNumIndices == 0)
{
LL_WARNS() << "Face has invalid number of indices." << LL_ENDL;
LL_WARNS("MESHSKININFO") << "Face has invalid number of indices." << LL_ENDL;
return false;
}
@ -1879,7 +1887,7 @@ bool validate_model(const LLModel* mdl)
{
if (mdl->getNumVolumeFaces() == 0)
{
LL_WARNS() << "Model has no faces!" << LL_ENDL;
LL_WARNS("MESHSKININFO") << "Model has no faces!" << LL_ENDL;
return false;
}
@ -1887,13 +1895,13 @@ bool validate_model(const LLModel* mdl)
{
if (mdl->getVolumeFace(i).mNumVertices == 0)
{
LL_WARNS() << "Face has no vertices." << LL_ENDL;
LL_WARNS("MESHSKININFO") << "Face has no vertices." << LL_ENDL;
return false;
}
if (mdl->getVolumeFace(i).mNumIndices == 0)
{
LL_WARNS() << "Face has no indices." << LL_ENDL;
LL_WARNS("MESHSKININFO") << "Face has no indices." << LL_ENDL;
return false;
}

View File

@ -212,6 +212,12 @@ LLSD LLMenuItemGL::getValue() const
return getLabel();
}
//virtual
bool LLMenuItemGL::hasAccelerator(const KEY &key, const MASK &mask) const
{
return (mAcceleratorKey == key) && (mAcceleratorMask == mask);
}
//virtual
BOOL LLMenuItemGL::handleAcceleratorKey(KEY key, MASK mask)
{
@ -263,13 +269,13 @@ BOOL LLMenuItemGL::handleRightMouseUp(S32 x, S32 y, MASK mask)
// This function checks to see if the accelerator key is already in use;
// if not, it will be added to the list
BOOL LLMenuItemGL::addToAcceleratorList(std::list <LLKeyBinding*> *listp)
BOOL LLMenuItemGL::addToAcceleratorList(std::list <LLMenuKeyboardBinding*> *listp)
{
LLKeyBinding *accelerator = NULL;
LLMenuKeyboardBinding *accelerator = NULL;
if (mAcceleratorKey != KEY_NONE)
{
std::list<LLKeyBinding*>::iterator list_it;
std::list<LLMenuKeyboardBinding*>::iterator list_it;
for (list_it = listp->begin(); list_it != listp->end(); ++list_it)
{
accelerator = *list_it;
@ -293,7 +299,7 @@ BOOL LLMenuItemGL::addToAcceleratorList(std::list <LLKeyBinding*> *listp)
}
if (!accelerator)
{
accelerator = new LLKeyBinding;
accelerator = new LLMenuKeyboardBinding;
if (accelerator)
{
accelerator->mKey = mAcceleratorKey;
@ -1017,6 +1023,11 @@ BOOL LLMenuItemBranchGL::handleMouseUp(S32 x, S32 y, MASK mask)
return TRUE;
}
bool LLMenuItemBranchGL::hasAccelerator(const KEY &key, const MASK &mask) const
{
return getBranch() && getBranch()->hasAccelerator(key, mask);
}
BOOL LLMenuItemBranchGL::handleAcceleratorKey(KEY key, MASK mask)
{
return getBranch() && getBranch()->handleAcceleratorKey(key, mask);
@ -1024,7 +1035,7 @@ BOOL LLMenuItemBranchGL::handleAcceleratorKey(KEY key, MASK mask)
// This function checks to see if the accelerator key is already in use;
// if not, it will be added to the list
BOOL LLMenuItemBranchGL::addToAcceleratorList(std::list<LLKeyBinding*> *listp)
BOOL LLMenuItemBranchGL::addToAcceleratorList(std::list<LLMenuKeyboardBinding*> *listp)
{
LLMenuGL* branch = getBranch();
if (!branch)
@ -3023,6 +3034,27 @@ void LLMenuGL::updateParent(LLView* parentp)
}
}
bool LLMenuGL::hasAccelerator(const KEY &key, const MASK &mask) const
{
if (key == KEY_NONE)
{
return false;
}
// Note: checking this way because mAccelerators seems to be broken
// mAccelerators probably needs to be cleaned up or fixed
// It was used for dupplicate accelerator avoidance.
item_list_t::const_iterator item_iter;
for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
{
LLMenuItemGL* itemp = *item_iter;
if (itemp->hasAccelerator(key, mask))
{
return true;
}
}
return false;
}
BOOL LLMenuGL::handleAcceleratorKey(KEY key, MASK mask)
{
// don't handle if not enabled

View File

@ -42,6 +42,13 @@
extern S32 MENU_BAR_HEIGHT;
extern S32 MENU_BAR_WIDTH;
class LLMenuKeyboardBinding
{
public:
KEY mKey;
MASK mMask;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLMenuItemGL
//
@ -91,6 +98,7 @@ public:
/*virtual*/ void setValue(const LLSD& value);
/*virtual*/ LLSD getValue() const;
virtual bool hasAccelerator(const KEY &key, const MASK &mask) const;
virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
LLColor4 getHighlightBgColor() { return mHighlightBackground.get(); }
@ -109,7 +117,7 @@ public:
virtual void setBriefItem(BOOL brief);
virtual BOOL isBriefItem() const;
virtual BOOL addToAcceleratorList(std::list<LLKeyBinding*> *listp);
virtual BOOL addToAcceleratorList(std::list<LLMenuKeyboardBinding*> *listp);
void setAllowKeyRepeat(BOOL allow) { mAllowKeyRepeat = allow; }
BOOL getAllowKeyRepeat() const { return mAllowKeyRepeat; }
@ -436,7 +444,8 @@ public:
/*virtual*/ bool addChild(LLView* view, S32 tab_group = 0);
/*virtual*/ void removeChild( LLView* ctrl);
/*virtual*/ BOOL postBuild();
virtual bool hasAccelerator(const KEY &key, const MASK &mask) const;
virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
LLMenuGL* findChildMenuByName(const std::string& name, BOOL recurse) const;
@ -628,10 +637,11 @@ public:
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual bool hasAccelerator(const KEY &key, const MASK &mask) const;
virtual BOOL handleAcceleratorKey(KEY key, MASK mask);
// check if we've used these accelerators already
virtual BOOL addToAcceleratorList(std::list <LLKeyBinding*> *listp);
virtual BOOL addToAcceleratorList(std::list <LLMenuKeyboardBinding*> *listp);
// called to rebuild the draw label
virtual void buildDrawLabel( void );
@ -797,7 +807,7 @@ private:
void checkMenuTrigger();
std::list <LLKeyBinding*> mAccelerators;
std::list <LLMenuKeyboardBinding*> mAccelerators;
BOOL mAltKeyTrigger;
};

View File

@ -50,6 +50,10 @@ LLScrollListCell* LLScrollListCell::create(const LLScrollListCell::Params& cell_
{
cell = new LLScrollListDate(cell_p);
}
else if (cell_p.type() == "icontext")
{
cell = new LLScrollListIconText(cell_p);
}
else // default is "text"
{
cell = new LLScrollListText(cell_p);
@ -168,7 +172,7 @@ U32 LLScrollListText::sCount = 0;
LLScrollListText::LLScrollListText(const LLScrollListCell::Params& p)
: LLScrollListCell(p),
mText(p.value().asString()),
mText(p.label.isProvided() ? p.label() : p.value().asString()),
mFont(p.font),
mColor(p.color),
mUseColor(p.color.isProvided()),
@ -192,7 +196,7 @@ LLScrollListText::LLScrollListText(const LLScrollListCell::Params& p)
void LLScrollListText::highlightText(S32 offset, S32 num_chars)
{
mHighlightOffset = offset;
mHighlightCount = num_chars;
mHighlightCount = llmax(0, num_chars);
}
//virtual
@ -292,11 +296,12 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col
if (mHighlightCount > 0)
{
// Highlight text
S32 left = 0;
switch(mFontAlignment)
{
case LLFontGL::LEFT:
left = mFont->getWidth(mText.getString(), 0, mHighlightOffset);
left = mFont->getWidth(mText.getString(), 1, mHighlightOffset);
break;
case LLFontGL::RIGHT:
left = getWidth() - mFont->getWidth(mText.getString(), mHighlightOffset, S32_MAX);
@ -319,7 +324,7 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col
switch(mFontAlignment)
{
case LLFontGL::LEFT:
start_x = 0.f;
start_x = 1.f;
break;
case LLFontGL::RIGHT:
start_x = (F32)getWidth();
@ -435,3 +440,139 @@ const LLSD LLScrollListDate::getValue() const
{
return mDate;
}
//
// LLScrollListIconText
//
LLScrollListIconText::LLScrollListIconText(const LLScrollListCell::Params& p)
: LLScrollListText(p),
mIcon(p.value().isUUID() ? LLUI::getUIImageByID(p.value().asUUID()) : LLUI::getUIImage(p.value().asString())),
mPad(4)
{
mTextWidth = getWidth() - mPad /*padding*/ - mFont->getLineHeight();
}
LLScrollListIconText::~LLScrollListIconText()
{
}
const LLSD LLScrollListIconText::getValue() const
{
if (mIcon.isNull())
{
return LLStringUtil::null;
}
return mIcon->getName();
}
void LLScrollListIconText::setValue(const LLSD& value)
{
if (value.isUUID())
{
// don't use default image specified by LLUUID::null, use no image in that case
LLUUID image_id = value.asUUID();
mIcon = image_id.notNull() ? LLUI::getUIImageByID(image_id) : LLUIImagePtr(NULL);
}
else
{
std::string value_string = value.asString();
if (LLUUID::validate(value_string))
{
setValue(LLUUID(value_string));
}
else if (!value_string.empty())
{
mIcon = LLUI::getUIImage(value.asString());
}
else
{
mIcon = NULL;
}
}
}
void LLScrollListIconText::setWidth(S32 width)
{
LLScrollListCell::setWidth(width);
// Assume that iamge height and width is identical to font height and width
mTextWidth = width - mPad /*padding*/ - mFont->getLineHeight();
}
void LLScrollListIconText::draw(const LLColor4& color, const LLColor4& highlight_color) const
{
LLColor4 display_color;
if (mUseColor)
{
display_color = mColor;
}
else
{
display_color = color;
}
S32 icon_height = mFont->getLineHeight();
S32 icon_space = mIcon ? (icon_height + mPad) : 0;
if (mHighlightCount > 0)
{
S32 left = 0;
switch (mFontAlignment)
{
case LLFontGL::LEFT:
left = mFont->getWidth(mText.getString(), icon_space + 1, mHighlightOffset);
break;
case LLFontGL::RIGHT:
left = getWidth() - mFont->getWidth(mText.getString(), mHighlightOffset, S32_MAX) - icon_space;
break;
case LLFontGL::HCENTER:
left = (getWidth() - mFont->getWidth(mText.getString()) - icon_space) / 2;
break;
}
LLRect highlight_rect(left - 2,
mFont->getLineHeight() + 1,
left + mFont->getWidth(mText.getString(), mHighlightOffset, mHighlightCount) + 1,
1);
mRoundedRectImage->draw(highlight_rect, highlight_color);
}
// Try to draw the entire string
F32 right_x;
U32 string_chars = mText.length();
F32 start_text_x = 0.f;
S32 start_icon_x = 0;
switch (mFontAlignment)
{
case LLFontGL::LEFT:
start_text_x = icon_space + 1;
start_icon_x = 1;
break;
case LLFontGL::RIGHT:
start_text_x = (F32)getWidth();
start_icon_x = getWidth() - mFont->getWidth(mText.getString()) - icon_space;
break;
case LLFontGL::HCENTER:
F32 center = (F32)getWidth()* 0.5f;
start_text_x = center + ((F32)icon_space * 0.5f);
start_icon_x = center - (((F32)icon_space + mFont->getWidth(mText.getString())) * 0.5f);
break;
}
mFont->render(mText.getWString(), 0,
start_text_x, 0.f,
display_color,
mFontAlignment,
LLFontGL::BOTTOM,
0,
LLFontGL::NO_SHADOW,
string_chars,
getTextWidth(),
&right_x,
TRUE);
if (mIcon)
{
mIcon->draw(start_icon_x, 0, icon_height, icon_height, mColor);
}
}

View File

@ -59,7 +59,8 @@ public:
visible;
Optional<void*> userdata;
Optional<LLSD> value;
Optional<LLSD> value; // state of checkbox, icon id/name, date
Optional<std::string> label; // description or text
Optional<std::string> tool_tip;
Optional<const LLFontGL*> font;
@ -75,6 +76,7 @@ public:
enabled("enabled", true),
visible("visible", true),
value("value"),
label("label"),
tool_tip("tool_tip", ""),
font("font", LLFontGL::getFontSansSerifSmall()),
font_color("font_color", LLColor4::black),
@ -152,11 +154,12 @@ public:
void setText(const LLStringExplicit& text);
void setFontStyle(const U8 font_style);
private:
protected:
LLUIString mText;
S32 mTextWidth;
const LLFontGL* mFont;
LLColor4 mColor;
LLColor4 mHighlightColor;
U8 mUseColor;
LLFontGL::HAlign mFontAlignment;
BOOL mVisible;
@ -169,7 +172,7 @@ private:
};
/*
* Cell displaying an image.
* Cell displaying an image. AT the moment, this is specifically UI image
*/
class LLScrollListIcon : public LLScrollListCell
{
@ -223,4 +226,26 @@ private:
LLDate mDate;
};
/*
* Cell displaying icon and text.
*/
class LLScrollListIconText : public LLScrollListText
{
public:
LLScrollListIconText(const LLScrollListCell::Params& p);
/*virtual*/ ~LLScrollListIconText();
/*virtual*/ void draw(const LLColor4& color, const LLColor4& highlight_color) const;
/*virtual*/ const LLSD getValue() const;
/*virtual*/ void setValue(const LLSD& value);
S32 getIconWidth() const;
/*virtual*/ void setWidth(S32 width);/* { LLScrollListCell::setWidth(width); mTextWidth = width - ; }*/
private:
LLPointer<LLUIImage> mIcon;
S32 mPad;
};
#endif

View File

@ -115,6 +115,13 @@ struct SortScrollListItem
// LLScrollListCtrl
//---------------------------------------------------------------------------
void LLScrollListCtrl::SelectionTypeNames::declareValues()
{
declare("row", LLScrollListCtrl::ROW);
declare("cell", LLScrollListCtrl::CELL);
declare("header", LLScrollListCtrl::HEADER);
}
LLScrollListCtrl::Contents::Contents()
: columns("column"),
rows("row")
@ -128,8 +135,10 @@ LLScrollListCtrl::Params::Params()
has_border("draw_border"),
draw_heading("draw_heading"),
search_column("search_column", 0),
selection_type("selection_type", ROW),
sort_column("sort_column", -1),
sort_ascending("sort_ascending", true),
can_sort("can_sort", true),
mouse_wheel_opaque("mouse_wheel_opaque", false),
commit_on_keyboard_movement("commit_on_keyboard_movement", true),
commit_on_selection_change("commit_on_selection_change", false),
@ -165,8 +174,10 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p)
mCommitOnKeyboardMovement(p.commit_on_keyboard_movement),
mCommitOnSelectionChange(p.commit_on_selection_change),
mSelectionChanged(false),
mSelectionType(p.selection_type),
mNeedsScroll(false),
mCanSelect(true),
mCanSort(p.can_sort),
mColumnsDirty(false),
mMaxItemCount(INT_MAX),
mBorderThickness( 2 ),
@ -840,7 +851,15 @@ BOOL LLScrollListCtrl::selectFirstItem()
{
if (!itemp->getSelected())
{
selectItem(itemp);
switch (mSelectionType)
{
case CELL:
selectItem(itemp, 0);
break;
case HEADER:
case ROW:
selectItem(itemp, -1);
}
}
success = TRUE;
mOriginalSelection = 0;
@ -899,7 +918,8 @@ BOOL LLScrollListCtrl::selectItemRange( S32 first_index, S32 last_index )
{
if( itemp->getEnabled() )
{
selectItem(itemp, FALSE);
// TODO: support range selection for cells
selectItem(itemp, -1, FALSE);
success = TRUE;
}
}
@ -1025,10 +1045,14 @@ void LLScrollListCtrl::clearHighlightedItems()
void LLScrollListCtrl::mouseOverHighlightNthItem(S32 target_index)
{
if (mHighlightedItem != target_index)
{
mHighlightedItem = target_index;
}
if (mHighlightedItem != target_index)
{
if (mHighlightedItem >= 0 && mHighlightedItem < mItemList.size())
{
mItemList[mHighlightedItem]->setHoverCell(-1);
}
mHighlightedItem = target_index;
}
}
S32 LLScrollListCtrl::selectMultiple( uuid_vec_t ids )
@ -1043,7 +1067,8 @@ S32 LLScrollListCtrl::selectMultiple( uuid_vec_t ids )
{
if (item->getEnabled() && (item->getUUID() == (*iditr)))
{
selectItem(item,FALSE);
// TODO: support multiple selection for cells
selectItem(item, -1, FALSE);
++count;
break;
}
@ -1116,7 +1141,7 @@ void LLScrollListCtrl::selectPrevItem( BOOL extend_selection)
{
if (prev_item)
{
selectItem(prev_item, !extend_selection);
selectItem(prev_item, cur_item->getSelectedCell(), !extend_selection);
}
else
{
@ -1160,7 +1185,7 @@ void LLScrollListCtrl::selectNextItem( BOOL extend_selection)
{
if (next_item)
{
selectItem(next_item, !extend_selection);
selectItem(next_item, cur_item->getSelectedCell(), !extend_selection);
}
else
{
@ -1231,7 +1256,7 @@ BOOL LLScrollListCtrl::selectItemByLabel(const std::string& label, BOOL case_sen
bool found = NULL != item;
if(found)
{
selectItem(item);
selectItem(item, -1);
}
if (mCommitOnSelectionChange)
@ -1299,7 +1324,7 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen
BOOL select = cellp ? item->getEnabled() && ('\0' == cellp->getValue().asString()[0]) : FALSE;
if (select)
{
selectItem(item);
selectItem(item, -1);
found = TRUE;
break;
}
@ -1339,7 +1364,7 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen
// find offset of matching text (might have leading whitespace)
S32 offset = item_label.find(target_trimmed);
cellp->highlightText(offset, target_trimmed.size());
selectItem(item);
selectItem(item, -1);
found = TRUE;
break;
}
@ -1421,7 +1446,7 @@ BOOL LLScrollListCtrl::setSelectedByValue(const LLSD& value, BOOL selected)
{
if (selected)
{
selectItem(item);
selectItem(item, -1);
}
else
{
@ -1501,7 +1526,7 @@ void LLScrollListCtrl::drawItems()
S32 max_columns = 0;
LLColor4 highlight_color = LLColor4::white;
LLColor4 highlight_color = LLColor4::white; // ex: text inside cells
static LLUICachedControl<F32> type_ahead_timeout ("TypeAheadTimeout", 0);
highlight_color.mV[VALPHA] = clamp_rescale(mSearchTimer.getElapsedTimeF32(), type_ahead_timeout * 0.7f, type_ahead_timeout(), 0.4f, 0.f);
@ -1527,7 +1552,8 @@ void LLScrollListCtrl::drawItems()
max_columns = llmax(max_columns, item->getNumColumns());
LLColor4 fg_color;
LLColor4 bg_color(LLColor4::transparent);
LLColor4 hover_color(LLColor4::transparent);
LLColor4 select_color(LLColor4::transparent);
if( mScrollLines <= line && line < mScrollLines + num_page_lines )
{
@ -1536,44 +1562,44 @@ void LLScrollListCtrl::drawItems()
{
if(item->getHighlighted()) // if it's highlighted, average the colors
{
bg_color = lerp(mBgSelectedColor.get(), mHighlightedColor.get(), 0.5f);
select_color = lerp(mBgSelectedColor.get(), mHighlightedColor.get(), 0.5f);
}
else // otherwise just select-highlight it
{
bg_color = mBgSelectedColor.get();
select_color = mBgSelectedColor.get();
}
fg_color = (item->getEnabled() ? mFgSelectedColor.get() : mFgDisabledColor.get());
}
else if (mHighlightedItem == line && mCanSelect)
if (mHighlightedItem == line && mCanSelect)
{
if(item->getHighlighted()) // if it's highlighted, average the colors
{
bg_color = lerp(mHoveredColor.get(), mHighlightedColor.get(), 0.5f);
hover_color = lerp(mHoveredColor.get(), mHighlightedColor.get(), 0.5f);
}
else // otherwise just hover-highlight it
{
bg_color = mHoveredColor.get();
hover_color = mHoveredColor.get();
}
}
else if (item->getHighlighted())
{
bg_color = mHighlightedColor.get();
hover_color = mHighlightedColor.get();
}
else
{
if (mDrawStripes && (line % 2 == 0) && (max_columns > 1))
{
bg_color = mBgStripeColor.get();
hover_color = mBgStripeColor.get();
}
}
if (!item->getEnabled())
{
bg_color = mBgReadOnlyColor.get();
hover_color = mBgReadOnlyColor.get();
}
item->draw(item_rect, fg_color % alpha, bg_color% alpha, highlight_color % alpha, mColumnPadding);
item->draw(item_rect, fg_color % alpha, hover_color% alpha, select_color% alpha, highlight_color % alpha, mColumnPadding);
cur_y -= mLineHeight;
}
@ -1725,7 +1751,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
{
if (mLastSelected == NULL)
{
selectItem(hit_item);
selectItem(hit_item, getColumnIndexFromOffset(x));
}
else
{
@ -1749,7 +1775,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
LLScrollListItem *item = *itor;
if (item == hit_item || item == lastSelected)
{
selectItem(item, FALSE);
selectItem(item, getColumnIndexFromOffset(x), FALSE);
selecting = !selecting;
if (hit_item == lastSelected)
{
@ -1759,7 +1785,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
}
if (selecting)
{
selectItem(item, FALSE);
selectItem(item, getColumnIndexFromOffset(x), FALSE);
}
}
}
@ -1774,7 +1800,7 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
{
if(!(mMaxSelectable > 0 && getAllSelected().size() >= mMaxSelectable))
{
selectItem(hit_item, FALSE);
selectItem(hit_item, getColumnIndexFromOffset(x), FALSE);
}
else
{
@ -1788,12 +1814,12 @@ BOOL LLScrollListCtrl::selectItemAt(S32 x, S32 y, MASK mask)
else
{
deselectAllItems(TRUE);
selectItem(hit_item);
selectItem(hit_item, getColumnIndexFromOffset(x));
}
}
else
{
selectItem(hit_item);
selectItem(hit_item, getColumnIndexFromOffset(x));
}
selection_changed = mSelectionChanged;
@ -2161,8 +2187,29 @@ BOOL LLScrollListCtrl::handleHover(S32 x,S32 y,MASK mask)
{
LLScrollListItem* item = hitItem(x, y);
if (item)
{
mouseOverHighlightNthItem(getItemIndex(item));
{
mouseOverHighlightNthItem(getItemIndex(item));
switch (mSelectionType)
{
case CELL:
item->setHoverCell(getColumnIndexFromOffset(x));
break;
case HEADER:
{
S32 cell = getColumnIndexFromOffset(x);
if (cell > 0)
{
item->setHoverCell(cell);
}
else
{
item->setHoverCell(-1);
}
break;
}
case ROW:
break;
}
}
else
{
@ -2210,6 +2257,58 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask )
handled = TRUE;
}
break;
case KEY_LEFT:
if (mAllowKeyboardMovement || hasFocus())
{
// TODO: support multi-select
LLScrollListItem *item = getFirstSelected();
if (item)
{
S32 cell = item->getSelectedCell();
switch (mSelectionType)
{
case CELL:
if (cell < mColumns.size()) cell++;
break;
case HEADER:
if (cell == -1) cell = 1;
else if (cell > 1 && cell < mColumns.size()) cell++; // skip header
break;
case ROW:
cell = -1;
break;
}
item->setSelectedCell(cell);
handled = TRUE;
}
}
break;
case KEY_RIGHT:
if (mAllowKeyboardMovement || hasFocus())
{
// TODO: support multi-select
LLScrollListItem *item = getFirstSelected();
if (item)
{
S32 cell = item->getSelectedCell();
switch (mSelectionType)
{
case CELL:
if (cell >= 0) cell--;
break;
case HEADER:
if (cell > 1) cell--;
else if (cell == 1) cell = -1; // skip header
break;
case ROW:
cell = -1;
break;
}
item->setSelectedCell(cell);
handled = TRUE;
}
}
break;
case KEY_PAGE_UP:
if (mAllowKeyboardMovement || hasFocus())
{
@ -2378,7 +2477,7 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char)
LLWString item_label = utf8str_to_wstring(cellp->getValue().asString());
if (item->getEnabled() && LLStringOps::toLower(item_label[0]) == uni_char)
{
selectItem(item);
selectItem(item, -1);
mNeedsScroll = true;
cellp->highlightText(0, 1);
mSearchTimer.reset();
@ -2430,7 +2529,7 @@ BOOL LLScrollListCtrl::isRepeatedChars(const LLWString& string) const
return TRUE;
}
void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, BOOL select_single_item)
void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, S32 cell, BOOL select_single_item)
{
if (!itemp) return;
@ -2449,6 +2548,18 @@ void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, BOOL select_single_it
deselectAllItems(TRUE);
}
itemp->setSelected(TRUE);
switch (mSelectionType)
{
case CELL:
itemp->setSelectedCell(cell);
break;
case HEADER:
itemp->setSelectedCell(cell <= 0 ? -1 : cell);
break;
case ROW:
itemp->setSelectedCell(-1);
break;
}
mLastSelected = itemp;
mSelectionChanged = true;
}
@ -2709,7 +2820,7 @@ void LLScrollListCtrl::selectAll()
LLScrollListItem *itemp = *iter;
if( itemp->getEnabled() )
{
selectItem(itemp, FALSE);
selectItem(itemp, -1, FALSE);
}
}
@ -2838,6 +2949,8 @@ void LLScrollListCtrl::onClickColumn(void *userdata)
LLScrollListCtrl *parent = info->mParentCtrl;
if (!parent) return;
if (!parent->mCanSort) return;
S32 column_index = info->mIndex;
LLScrollListColumn* column = parent->mColumnsIndexed[info->mIndex];

View File

@ -54,6 +54,18 @@ class LLScrollListCtrl : public LLUICtrl, public LLEditMenuHandler,
public LLCtrlListInterface, public LLCtrlScrollInterface
{
public:
typedef enum e_selection_type
{
ROW, // default
CELL, // does not support multi-selection
HEADER, // when pointing to cells in column 0 will highlight whole row, otherwise cell, no multi-select
} ESelectionType;
struct SelectionTypeNames : public LLInitParam::TypeValuesHelper<LLScrollListCtrl::ESelectionType, SelectionTypeNames>
{
static void declareValues();
};
struct Contents : public LLInitParam::Block<Contents>
{
Multiple<LLScrollListColumn::Params> columns;
@ -100,6 +112,8 @@ public:
commit_on_selection_change,
mouse_wheel_opaque;
Optional<ESelectionType, SelectionTypeNames> selection_type;
// display flags
Optional<bool> has_border,
draw_heading,
@ -116,7 +130,8 @@ public:
// sort and search behavior
Optional<S32> search_column,
sort_column;
Optional<bool> sort_ascending;
Optional<bool> sort_ascending,
can_sort; // whether user is allowed to sort
// colors
Optional<LLUIColor> fg_unselected_color,
@ -433,7 +448,7 @@ private:
void updateLineHeightInsert(LLScrollListItem* item);
void reportInvalidInput();
BOOL isRepeatedChars(const LLWString& string) const;
void selectItem(LLScrollListItem* itemp, BOOL single_select = TRUE);
void selectItem(LLScrollListItem* itemp, S32 cell, BOOL single_select = TRUE);
void deselectItem(LLScrollListItem* itemp);
void commitIfChanged();
BOOL setSort(S32 column, BOOL ascending);
@ -458,9 +473,11 @@ private:
bool mCommitOnKeyboardMovement;
bool mCommitOnSelectionChange;
bool mSelectionChanged;
ESelectionType mSelectionType;
bool mNeedsScroll;
bool mMouseWheelOpaque;
bool mCanSelect;
bool mCanSort; // Whether user is allowed to sort
bool mDisplayColumnHeaders;
bool mColumnsDirty;
bool mColumnWidthsDirty;

View File

@ -40,6 +40,8 @@
LLScrollListItem::LLScrollListItem( const Params& p )
: mSelected(FALSE),
mHighlighted(FALSE),
mHoverIndex(-1),
mSelectedIndex(-1),
mEnabled(p.enabled),
mUserdata(p.userdata),
mItemValue(p.value)
@ -53,6 +55,28 @@ LLScrollListItem::~LLScrollListItem()
mColumns.clear();
}
void LLScrollListItem::setSelected(BOOL b)
{
mSelected = b;
mSelectedIndex = -1;
}
void LLScrollListItem::setHighlighted(BOOL b)
{
mHighlighted = b;
mHoverIndex = -1;
}
void LLScrollListItem::setHoverCell(S32 cell)
{
mHoverIndex = cell;
}
void LLScrollListItem::setSelectedCell(S32 cell)
{
mSelectedIndex = cell;
}
void LLScrollListItem::addColumn(const LLScrollListCell::Params& p)
{
mColumns.push_back(LLScrollListCell::create(p));
@ -120,12 +144,21 @@ std::string LLScrollListItem::getContentsCSV() const
}
void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding)
void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& hover_color, const LLColor4& select_color, const LLColor4& highlight_color, S32 column_padding)
{
// draw background rect
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
LLRect bg_rect = rect;
gl_rect_2d( bg_rect, bg_color );
if (mSelectedIndex < 0 && getSelected())
{
// Whole item is highlighted/selected
gl_rect_2d(bg_rect, select_color);
}
else if (mHoverIndex < 0)
{
// Whole item is highlighted/selected
gl_rect_2d(bg_rect, hover_color);
}
S32 cur_x = rect.mLeft;
S32 num_cols = getNumColumns();
@ -141,6 +174,25 @@ void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const
{
LLUI::translate((F32) cur_x, (F32) rect.mBottom);
if (mSelectedIndex == cur_col)
{
// select specific cell
LLRect highlight_rect(0,
cell->getHeight(),
cell->getWidth(),
0);
gl_rect_2d(highlight_rect, select_color);
}
else if (mHoverIndex == cur_col)
{
// highlight specific cell
LLRect highlight_rect(0,
cell->getHeight(),
cell->getWidth() ,
0);
gl_rect_2d(highlight_rect, hover_color);
}
cell->draw( fg_color, highlight_color );
}
LLUI::popMatrix();

View File

@ -77,15 +77,21 @@ public:
virtual ~LLScrollListItem();
void setSelected( BOOL b ) { mSelected = b; }
void setSelected( BOOL b );
BOOL getSelected() const { return mSelected; }
void setEnabled( BOOL b ) { mEnabled = b; }
BOOL getEnabled() const { return mEnabled; }
void setHighlighted( BOOL b ) { mHighlighted = b; }
void setHighlighted( BOOL b );
BOOL getHighlighted() const { return mHighlighted; }
void setSelectedCell( S32 cell );
S32 getSelectedCell() const { return mSelectedIndex; }
void setHoverCell( S32 cell );
S32 getHoverCell() const { return mHoverIndex; }
void setUserdata( void* userdata ) { mUserdata = userdata; }
void* getUserdata() const { return mUserdata; }
@ -107,14 +113,21 @@ public:
std::string getContentsCSV() const;
virtual void draw(const LLRect& rect, const LLColor4& fg_color, const LLColor4& bg_color, const LLColor4& highlight_color, S32 column_padding);
virtual void draw(const LLRect& rect,
const LLColor4& fg_color,
const LLColor4& hover_color, // highlight/hover selection of whole item or cell
const LLColor4& select_color, // highlight/hover selection of whole item or cell
const LLColor4& highlight_color, // highlights contents of cells (ex: text)
S32 column_padding);
protected:
LLScrollListItem( const Params& );
private:
BOOL mSelected;
BOOL mHighlighted;
BOOL mHighlighted;
S32 mHoverIndex;
S32 mSelectedIndex;
BOOL mEnabled;
void* mUserdata;
LLSD mItemValue;

View File

@ -327,7 +327,7 @@ BOOL LLKeyboard::keyFromString(const std::string& str, KEY *key)
// static
std::string LLKeyboard::stringFromKey(KEY key)
std::string LLKeyboard::stringFromKey(KEY key, bool translate)
{
std::string res = get_if_there(sKeysToNames, key, std::string());
if (res.empty())
@ -338,16 +338,60 @@ std::string LLKeyboard::stringFromKey(KEY key)
res = std::string(buffer);
}
LLKeyStringTranslatorFunc *trans = gKeyboard->mStringTranslator;
if (trans != NULL)
if (translate)
{
res = trans(res.c_str());
LLKeyStringTranslatorFunc *trans = gKeyboard->mStringTranslator;
if (trans != NULL)
{
res = trans(res.c_str());
}
}
return res;
}
//static
std::string LLKeyboard::stringFromAccelerator(MASK accel_mask)
{
std::string res;
LLKeyStringTranslatorFunc *trans = gKeyboard->mStringTranslator;
if (trans == NULL)
{
LL_ERRS() << "No mKeyStringTranslator" << LL_ENDL;
return res;
}
// Append any masks
#ifdef LL_DARWIN
// Standard Mac names for modifier keys in menu equivalents
// We could use the symbol characters, but they only exist in certain fonts.
if (accel_mask & MASK_CONTROL)
{
if (accel_mask & MASK_MAC_CONTROL)
{
res.append(trans("accel-mac-control"));
}
else
{
res.append(trans("accel-mac-command")); // Symbol would be "\xE2\x8C\x98"
}
}
if (accel_mask & MASK_ALT)
res.append(trans("accel-mac-option")); // Symbol would be "\xE2\x8C\xA5"
if (accel_mask & MASK_SHIFT)
res.append(trans("accel-mac-shift")); // Symbol would be "\xE2\x8C\xA7"
#else
if (accel_mask & MASK_CONTROL)
res.append(trans("accel-win-control"));
if (accel_mask & MASK_ALT)
res.append(trans("accel-win-alt"));
if (accel_mask & MASK_SHIFT)
res.append(trans("accel-win-shift"));
#endif
return res;
}
//static
std::string LLKeyboard::stringFromAccelerator( MASK accel_mask, KEY key )
{
@ -359,41 +403,7 @@ std::string LLKeyboard::stringFromAccelerator( MASK accel_mask, KEY key )
return res;
}
LLKeyStringTranslatorFunc *trans = gKeyboard->mStringTranslator;
if( trans == NULL )
{
LL_ERRS() << "No mKeyStringTranslator" << LL_ENDL;
return res;
}
// Append any masks
#ifdef LL_DARWIN
// Standard Mac names for modifier keys in menu equivalents
// We could use the symbol characters, but they only exist in certain fonts.
if( accel_mask & MASK_CONTROL )
{
if ( accel_mask & MASK_MAC_CONTROL )
{
res.append( trans("accel-mac-control") );
}
else
{
res.append( trans("accel-mac-command") ); // Symbol would be "\xE2\x8C\x98"
}
}
if( accel_mask & MASK_ALT )
res.append( trans("accel-mac-option") ); // Symbol would be "\xE2\x8C\xA5"
if( accel_mask & MASK_SHIFT )
res.append( trans("accel-mac-shift") ); // Symbol would be "\xE2\x8C\xA7"
#else
if( accel_mask & MASK_CONTROL )
res.append( trans("accel-win-control") );
if( accel_mask & MASK_ALT )
res.append( trans("accel-win-alt") );
if( accel_mask & MASK_SHIFT )
res.append( trans("accel-win-shift") );
#endif
res.append(stringFromAccelerator(accel_mask));
std::string key_string = LLKeyboard::stringFromKey(key);
if ((accel_mask & MASK_NORMALKEYS) &&
(key_string[0] == '-' || key_string[0] == '=' || key_string[0] == '+'))

View File

@ -38,10 +38,10 @@ enum EKeystate
{
KEYSTATE_DOWN,
KEYSTATE_LEVEL,
KEYSTATE_UP
KEYSTATE_UP
};
typedef boost::function<void(EKeystate keystate)> LLKeyFunc;
typedef boost::function<bool(EKeystate keystate)> LLKeyFunc;
typedef std::string (LLKeyStringTranslatorFunc)(const char *label);
enum EKeyboardInsertMode
@ -50,15 +50,6 @@ enum EKeyboardInsertMode
LL_KIM_OVERWRITE
};
class LLKeyBinding
{
public:
KEY mKey;
MASK mMask;
// const char *mName; // unused
LLKeyFunc mFunction;
};
class LLWindowCallbacks;
class LLKeyboard
@ -103,7 +94,8 @@ public:
static BOOL maskFromString(const std::string& str, MASK *mask); // False on failure
static BOOL keyFromString(const std::string& str, KEY *key); // False on failure
static std::string stringFromKey(KEY key);
static std::string stringFromKey(KEY key, bool translate = true);
static std::string stringFromAccelerator( MASK accel_mask ); // separated for convinience, returns with "+": "Shift+" or "Shift+Alt+"...
static std::string stringFromAccelerator( MASK accel_mask, KEY key );
void setCallbacks(LLWindowCallbacks *cbs) { mCallbacks = cbs; }

View File

@ -27,7 +27,7 @@
#include "llmousehandler.h"
//virtual
BOOL LLMouseHandler::handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down)
BOOL LLMouseHandler::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down)
{
BOOL handled = FALSE;
if (down)

View File

@ -29,6 +29,7 @@
#include "linden_common.h"
#include "llrect.h"
#include "indra_constants.h"
// Mostly-abstract interface.
// Intended for use via multiple inheritance.
@ -46,16 +47,7 @@ public:
SHOW_ALWAYS,
} EShowToolTip;
typedef enum {
CLICK_LEFT,
CLICK_MIDDLE,
CLICK_RIGHT,
CLICK_BUTTON4,
CLICK_BUTTON5,
CLICK_DOUBLELEFT
} EClickType;
virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down);
virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) = 0;
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) = 0;
virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask) = 0;

View File

@ -375,6 +375,7 @@ set(viewer_SOURCE_FILES
llinventoryobserver.cpp
llinventorypanel.cpp
lljoystickbutton.cpp
llkeyconflict.cpp
lllandmarkactions.cpp
lllandmarklist.cpp
lllegacyatmospherics.cpp
@ -556,6 +557,7 @@ set(viewer_SOURCE_FILES
llsecapi.cpp
llsechandler_basic.cpp
llselectmgr.cpp
llsetkeybinddialog.cpp
llsettingspicker.cpp
llsettingsvo.cpp
llshareavatarhandler.cpp
@ -661,7 +663,7 @@ set(viewer_SOURCE_FILES
llviewerjointattachment.cpp
llviewerjointmesh.cpp
llviewerjoystick.cpp
llviewerkeyboard.cpp
llviewerinput.cpp
llviewerlayer.cpp
llviewermedia.cpp
llviewermedia_streamingaudio.cpp
@ -1007,6 +1009,7 @@ set(viewer_HEADER_FILES
llinventoryobserver.h
llinventorypanel.h
lljoystickbutton.h
llkeyconflict.h
lllandmarkactions.h
lllandmarklist.h
lllightconstants.h
@ -1178,6 +1181,7 @@ set(viewer_HEADER_FILES
llsecapi.h
llsechandler_basic.h
llselectmgr.h
llsetkeybinddialog.h
llsettingspicker.h
llsettingsvo.h
llsidepanelappearance.h
@ -1285,7 +1289,7 @@ set(viewer_HEADER_FILES
llviewerjointattachment.h
llviewerjointmesh.h
llviewerjoystick.h
llviewerkeyboard.h
llviewerinput.h
llviewerlayer.h
llviewermedia.h
llviewermediafocus.h
@ -1662,7 +1666,7 @@ set(viewer_APPSETTINGS_FILES
app_settings/grass.xml
app_settings/high_graphics.xml
app_settings/ignorable_dialogs.xml
app_settings/keys.xml
app_settings/key_bindings.xml
app_settings/keywords_lsl_default.xml
app_settings/logcontrol.xml
app_settings/low_graphics.xml

View File

@ -1 +1 @@
6.4.17
6.4.18

View File

@ -28,34 +28,11 @@
<binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
<binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="A" mask="SHIFT" command="slide_left"/>
<binding key="D" mask="SHIFT" command="slide_right"/>
<binding key="W" mask="SHIFT" command="push_forward"/>
<binding key="S" mask="SHIFT" command="push_backward"/>
<binding key="E" mask="SHIFT" command="jump"/>
<binding key="C" mask="SHIFT" command="push_down"/>
<binding key="F" mask="SHIFT" command="toggle_fly"/>
<binding key="SPACE" mask="NONE" command="stop_moving"/>
<binding key="ENTER" mask="NONE" command="start_chat"/>
<binding key="DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="LEFT" mask="SHIFT" command="slide_left"/>
<binding key="RIGHT" mask="SHIFT" command="slide_right"/>
<binding key="UP" mask="SHIFT" command="push_forward"/>
<binding key="DOWN" mask="SHIFT" command="push_backward"/>
<binding key="PGUP" mask="SHIFT" command="jump"/>
<binding key="PGDN" mask="SHIFT" command="push_down"/>
<binding key="PAD_LEFT" mask="SHIFT" command="slide_left"/>
<binding key="PAD_RIGHT" mask="SHIFT" command="slide_right"/>
<binding key="PAD_UP" mask="SHIFT" command="push_forward"/>
<binding key="PAD_DOWN" mask="SHIFT" command="push_backward"/>
<binding key="PAD_PGUP" mask="SHIFT" command="jump"/>
<binding key="PAD_PGDN" mask="SHIFT" command="push_down"/>
<binding key="PAD_HOME" mask="SHIFT" command="toggle_fly"/>
<binding key="PAD_ENTER" mask="SHIFT" command="start_chat"/>
<binding key="PAD_DIVIDE" mask="SHIFT" command="start_gesture"/>
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
</first_person>
<third_person>
<binding key="A" mask="NONE" command="turn_left"/>
@ -64,15 +41,10 @@
<binding key="D" mask="SHIFT" command="slide_right"/>
<binding key="W" mask="NONE" command="push_forward"/>
<binding key="S" mask="NONE" command="push_backward"/>
<binding key="W" mask="SHIFT" command="push_forward"/>
<binding key="S" mask="SHIFT" command="push_backward"/>
<binding key="E" mask="NONE" command="jump"/>
<binding key="C" mask="NONE" command="push_down"/>
<binding key="E" mask="SHIFT" command="jump"/>
<binding key="C" mask="SHIFT" command="push_down"/>
<binding key="F" mask="NONE" command="toggle_fly"/>
<binding key="F" mask="SHIFT" command="toggle_fly"/>
<binding key="SPACE" mask="NONE" command="stop_moving"/>
<binding key="ENTER" mask="NONE" command="start_chat"/>
@ -84,13 +56,8 @@
<binding key="RIGHT" mask="SHIFT" command="slide_right"/>
<binding key="UP" mask="NONE" command="push_forward"/>
<binding key="DOWN" mask="NONE" command="push_backward"/>
<binding key="UP" mask="SHIFT" command="push_forward"/>
<binding key="DOWN" mask="SHIFT" command="push_backward"/>
<binding key="PGUP" mask="NONE" command="jump"/>
<binding key="PGDN" mask="NONE" command="push_down"/>
<binding key="PGUP" mask="SHIFT" command="jump"/>
<binding key="PGDN" mask="SHIFT" command="push_down"/>
<binding key="HOME" mask="SHIFT" command="toggle_fly"/>
<binding key="HOME" mask="NONE" command="toggle_fly"/>
<binding key="PAD_LEFT" mask="NONE" command="turn_left"/>
@ -99,20 +66,12 @@
<binding key="PAD_RIGHT" mask="SHIFT" command="slide_right"/>
<binding key="PAD_UP" mask="NONE" command="push_forward"/>
<binding key="PAD_DOWN" mask="NONE" command="push_backward"/>
<binding key="PAD_UP" mask="SHIFT" command="push_forward"/>
<binding key="PAD_DOWN" mask="SHIFT" command="push_backward"/>
<binding key="PAD_PGUP" mask="NONE" command="jump"/>
<binding key="PAD_PGDN" mask="NONE" command="push_down"/>
<binding key="PAD_PGUP" mask="SHIFT" command="jump"/>
<binding key="PAD_PGDN" mask="SHIFT" command="push_down"/>
<binding key="PAD_HOME" mask="NONE" command="toggle_fly"/>
<binding key="PAD_HOME" mask="SHIFT" command="toggle_fly"/>
<binding key="PAD_CENTER" mask="NONE" command="stop_moving"/>
<binding key="PAD_CENTER" mask="SHIFT" command="stop_moving"/>
<binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
<binding key="PAD_ENTER" mask="SHIFT" command="start_chat"/>
<binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="PAD_DIVIDE" mask="SHIFT" command="start_gesture"/>
<!--Camera controls in third person on Alt-->
<binding key="LEFT" mask="ALT" command="spin_around_cw"/>
@ -139,28 +98,14 @@
<binding key="PAD_DIVIDE" mask="ALT" command="start_gesture"/>
<!--mimic alt zoom behavior with keyboard only-->
<binding key="A" mask="CTL_ALT" command="spin_around_cw"/>
<binding key="D" mask="CTL_ALT" command="spin_around_ccw"/>
<binding key="W" mask="CTL_ALT" command="spin_over"/>
<binding key="S" mask="CTL_ALT" command="spin_under"/>
<binding key="E" mask="CTL_ALT" command="spin_over"/>
<binding key="C" mask="CTL_ALT" command="spin_under"/>
<binding key="LEFT" mask="CTL_ALT" command="spin_around_cw"/>
<binding key="RIGHT" mask="CTL_ALT" command="spin_around_ccw"/>
<binding key="UP" mask="CTL_ALT" command="spin_over"/>
<binding key="DOWN" mask="CTL_ALT" command="spin_under"/>
<binding key="PGUP" mask="CTL_ALT" command="spin_over"/>
<binding key="PGDN" mask="CTL_ALT" command="spin_under"/>
<binding key="PAD_LEFT" mask="CTL_ALT" command="spin_around_cw"/>
<binding key="PAD_RIGHT" mask="CTL_ALT" command="spin_around_ccw"/>
<binding key="PAD_UP" mask="CTL_ALT" command="spin_over"/>
<binding key="PAD_DOWN" mask="CTL_ALT" command="spin_under"/>
<binding key="PAD_PGUP" mask="CTL_ALT" command="spin_over"/>
<binding key="PAD_PGDN" mask="CTL_ALT" command="spin_under"/>
<binding key="PAD_ENTER" mask="CTL_ALT" command="start_chat"/>
<binding key="PAD_DIVIDE" mask="CTL_ALT" command="start_gesture"/>
<!--Therefore pan on Alt-Shift-->
<binding key="A" mask="CTL_ALT_SHIFT" command="pan_left"/>
@ -179,63 +124,10 @@
<binding key="PAD_DOWN" mask="CTL_ALT_SHIFT" command="pan_down"/>
<binding key="PAD_ENTER" mask="CTL_ALT_SHIFT" command="start_chat"/>
<binding key="PAD_DIVIDE" mask="CTL_ALT_SHIFT" command="start_gesture"/>
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
<binding key="" mask="NONE" mouse="LMB" command="walk_to"/>
</third_person>
<!-- Basic editing camera control -->
<edit>
<binding key="A" mask="NONE" command="spin_around_cw"/>
<binding key="D" mask="NONE" command="spin_around_ccw"/>
<binding key="W" mask="NONE" command="move_forward"/>
<binding key="S" mask="NONE" command="move_backward"/>
<binding key="E" mask="NONE" command="spin_over"/>
<binding key="C" mask="NONE" command="spin_under"/>
<binding key="ENTER" mask="NONE" command="start_chat"/>
<binding key="DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
<binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="LEFT" mask="NONE" command="spin_around_cw"/>
<binding key="RIGHT" mask="NONE" command="spin_around_ccw"/>
<binding key="UP" mask="NONE" command="move_forward"/>
<binding key="DOWN" mask="NONE" command="move_backward"/>
<binding key="PGUP" mask="NONE" command="spin_over"/>
<binding key="PGDN" mask="NONE" command="spin_under"/>
<binding key="A" mask="SHIFT" command="pan_left"/>
<binding key="D" mask="SHIFT" command="pan_right"/>
<binding key="W" mask="SHIFT" command="pan_up"/>
<binding key="S" mask="SHIFT" command="pan_down"/>
<binding key="LEFT" mask="SHIFT" command="pan_left"/>
<binding key="RIGHT" mask="SHIFT" command="pan_right"/>
<binding key="UP" mask="SHIFT" command="pan_up"/>
<binding key="DOWN" mask="SHIFT" command="pan_down"/>
<!--Walking works with ALT held down.-->
<binding key="A" mask="ALT" command="slide_left"/>
<binding key="D" mask="ALT" command="slide_right"/>
<binding key="W" mask="ALT" command="push_forward"/>
<binding key="S" mask="ALT" command="push_backward"/>
<binding key="E" mask="ALT" command="jump"/>
<binding key="C" mask="ALT" command="push_down"/>
<binding key="LEFT" mask="ALT" command="slide_left"/>
<binding key="RIGHT" mask="ALT" command="slide_right"/>
<binding key="UP" mask="ALT" command="push_forward"/>
<binding key="DOWN" mask="ALT" command="push_backward"/>
<binding key="PGUP" mask="ALT" command="jump"/>
<binding key="PGDN" mask="ALT" command="push_down"/>
<binding key="HOME" mask="ALT" command="toggle_fly"/>
<binding key="PAD_LEFT" mask="ALT" command="slide_left"/>
<binding key="PAD_RIGHT" mask="ALT" command="slide_right"/>
<binding key="PAD_UP" mask="ALT" command="push_forward"/>
<binding key="PAD_DOWN" mask="ALT" command="push_backward"/>
<binding key="PAD_PGUP" mask="ALT" command="jump"/>
<binding key="PAD_PGDN" mask="ALT" command="push_down"/>
<binding key="PAD_ENTER" mask="ALT" command="start_chat"/>
<binding key="PAD_DIVIDE" mask="ALT" command="start_gesture"/>
</edit>
<sitting>
<binding key="A" mask="ALT" command="spin_around_cw"/>
<binding key="D" mask="ALT" command="spin_around_ccw"/>
@ -251,15 +143,11 @@
<binding key="PGUP" mask="ALT" command="spin_over"/>
<binding key="PGDN" mask="ALT" command="spin_under"/>
<binding key="A" mask="CTL_ALT" command="spin_around_cw"/>
<binding key="D" mask="CTL_ALT" command="spin_around_ccw"/>
<binding key="W" mask="CTL_ALT" command="spin_over"/>
<binding key="S" mask="CTL_ALT" command="spin_under"/>
<binding key="E" mask="CTL_ALT" command="spin_over"/>
<binding key="C" mask="CTL_ALT" command="spin_under"/>
<binding key="LEFT" mask="CTL_ALT" command="spin_around_cw"/>
<binding key="RIGHT" mask="CTL_ALT" command="spin_around_ccw"/>
<binding key="UP" mask="CTL_ALT" command="spin_over"/>
<binding key="DOWN" mask="CTL_ALT" command="spin_under"/>
<binding key="PGUP" mask="CTL_ALT" command="spin_over"/>
@ -294,23 +182,23 @@
<binding key="A" mask="SHIFT" command="slide_left"/>
<binding key="D" mask="SHIFT" command="slide_right"/>
<binding key="W" mask="SHIFT" command="move_forward_sitting"/>
<binding key="S" mask="SHIFT" command="move_backward_sitting"/>
<binding key="E" mask="SHIFT" command="spin_over_sitting"/>
<binding key="C" mask="SHIFT" command="spin_under_sitting"/>
<binding key="S" mask="SHIFT" command="move_backward_sitting"/>
<binding key="E" mask="SHIFT" command="spin_over_sitting"/>
<binding key="C" mask="SHIFT" command="spin_under_sitting"/>
<binding key="LEFT" mask="SHIFT" command="slide_left"/>
<binding key="RIGHT" mask="SHIFT" command="slide_right"/>
<binding key="UP" mask="SHIFT" command="move_forward_sitting"/>
<binding key="DOWN" mask="SHIFT" command="move_backward_sitting"/>
<binding key="PGUP" mask="SHIFT" command="spin_over_sitting"/>
<binding key="PGDN" mask="SHIFT" command="spin_under_sitting"/>
<binding key="DOWN" mask="SHIFT" command="move_backward_sitting"/>
<binding key="PGUP" mask="SHIFT" command="spin_over_sitting"/>
<binding key="PGDN" mask="SHIFT" command="spin_under_sitting"/>
<binding key="PAD_LEFT" mask="SHIFT" command="slide_left"/>
<binding key="PAD_RIGHT" mask="SHIFT" command="slide_right"/>
<binding key="PAD_UP" mask="SHIFT" command="move_forward_sitting"/>
<binding key="PAD_DOWN" mask="SHIFT" command="move_backward_sitting"/>
<binding key="PAD_PGUP" mask="SHIFT" command="spin_over_sitting"/>
<binding key="PAD_PGDN" mask="SHIFT" command="spin_under_sitting"/>
<binding key="PAD_DOWN" mask="SHIFT" command="move_backward_sitting"/>
<binding key="PAD_PGUP" mask="SHIFT" command="spin_over_sitting"/>
<binding key="PAD_PGDN" mask="SHIFT" command="spin_under_sitting"/>
<binding key="PAD_ENTER" mask="SHIFT" command="start_chat"/>
<binding key="PAD_DIVIDE" mask="SHIFT" command="start_gesture"/>
@ -334,6 +222,8 @@
<binding key="ENTER" mask="NONE" command="start_chat"/>
<binding key="DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
</sitting>
<edit_avatar>
<!--Avatar editing camera controls-->
@ -359,5 +249,7 @@
<binding key="PAD_PGDN" mask="NONE" command="edit_avatar_spin_under"/>
<binding key="PAD_ENTER" mask="NONE" command="start_chat"/>
<binding key="PAD_DIVIDE" mask="NONE" command="start_gesture"/>
<binding key="" mask="NONE" mouse="MMB" command="toggle_voice"/>
</edit_avatar>
</keys>
</keys>

View File

@ -3542,7 +3542,7 @@
<key>DoubleClickAutoPilot</key>
<map>
<key>Comment</key>
<string>Enable double-click auto pilot</string>
<string>(Obsolete)Enable double-click auto pilot</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -3550,10 +3550,10 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>DoubleClickTeleport</key>
<key>DoubleClickTeleport</key>
<map>
<key>Comment</key>
<string>Enable double-click to teleport where allowed</string>
<string>Enable double-click to teleport where allowed (afects minimap and people panel)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -8282,7 +8282,7 @@
<key>PushToTalkButton</key>
<map>
<key>Comment</key>
<string>Which button or keyboard key is used for push-to-talk</string>
<string>(Obsolete)Which button or keyboard key is used for push-to-talk</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@ -15554,7 +15554,7 @@
<key>ClickToWalk</key>
<map>
<key>Comment</key>
<string>Click in world to walk to location</string>
<string>(obsolete)Click in world to walk to location</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>

View File

@ -2702,10 +2702,19 @@ void LLAgentCamera::setFocusOnAvatar(BOOL focus_on_avatar, BOOL animate, BOOL re
LLVector3 at_axis;
if (!isAgentAvatarValid() || !gAgentAvatarp->getParent())
{
at_axis = LLViewerCamera::getInstance()->getAtAxis();
at_axis.mV[VZ] = 0.f;
at_axis.normalize();
gAgent.resetAxes(at_axis);
// In case of front view rotate agent to look into direction opposite to camera
// In case of rear view rotate agent into diraction same as camera, e t c
LLVector3 vect = getCameraOffsetInitial();
F32 rotxy = F32(atan2(vect.mV[VY], vect.mV[VX]));
LLCoordFrame frameCamera = *((LLCoordFrame*)LLViewerCamera::getInstance());
// front view angle rotxy is zero, rear view rotxy angle is 180, compensate
frameCamera.yaw((180 * DEG_TO_RAD) - rotxy);
at_axis = frameCamera.getAtAxis();
at_axis.mV[VZ] = 0.f;
at_axis.normalize();
gAgent.resetAxes(at_axis);
gAgent.yaw(0);
}
}
}

View File

@ -49,6 +49,7 @@
#include "llwindow.h"
#include "llviewerstats.h"
#include "llviewerstatsrecorder.h"
#include "llkeyconflict.h" // for legacy keybinding support, remove later
#include "llmarketplacefunctions.h"
#include "llmarketplacenotifications.h"
#include "llmd5.h"
@ -150,7 +151,7 @@
#include "llapr.h"
#include <boost/lexical_cast.hpp>
#include "llviewerkeyboard.h"
#include "llviewerinput.h"
#include "lllfsthread.h"
#include "llworkerthread.h"
#include "lltexturecache.h"
@ -1006,23 +1007,6 @@ bool LLAppViewer::init()
gGLManager.getGLInfo(gDebugInfo);
gGLManager.printGLInfoString();
// Load Default bindings
std::string key_bindings_file = gDirUtilp->findFile("keys.xml",
gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
if (!gViewerKeyboard.loadBindingsXML(key_bindings_file))
{
std::string key_bindings_file = gDirUtilp->findFile("keys.ini",
gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""),
gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, ""));
if (!gViewerKeyboard.loadBindings(key_bindings_file))
{
LL_ERRS("InitInfo") << "Unable to open keys.ini" << LL_ENDL;
}
}
// If we don't have the right GL requirements, exit.
if (!gGLManager.mHasRequirements)
{
@ -1306,6 +1290,9 @@ bool LLAppViewer::init()
gSavedSettings.getControl("FramePerSecondLimit")->getSignal()->connect(boost::bind(&LLAppViewer::onChangeFrameLimit, this, _2));
onChangeFrameLimit(gSavedSettings.getLLSD("FramePerSecondLimit"));
// Load User's bindings
loadKeyBindings();
return true;
}
@ -1495,6 +1482,7 @@ bool LLAppViewer::doFrame()
{
joystick->scanJoystick();
gKeyboard->scanKeyboard();
gViewerInput.scanMouse();
}
// Update state based on messages, user input, object idle.
@ -4437,6 +4425,134 @@ void LLAppViewer::addOnIdleCallback(const boost::function<void()>& cb)
LLDeferredTaskList::instance().addTask(cb);
}
void LLAppViewer::loadKeyBindings()
{
std::string key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "key_bindings.xml");
#if 1
// Legacy support
// Remove #if-#endif section half a year after DRTVWR-501 releases.
// Mouse actions are part of keybinding file since DRTVWR-501 instead of being stored in
// settings.xml. To support legacy viewers that were storing in settings.xml we need to
// transfer old variables to new format.
// Also part of backward compatibility is present in LLKeyConflictHandler to modify
// legacy variables on changes in new system (to make sure we won't enforce
// legacy values again if user dropped to defaults in new system)
if (LLVersionInfo::getInstance()->getChannelAndVersion() != gLastRunVersion
|| !gDirUtilp->fileExists(key_bindings_file)) // if file is missing, assume that there were no changes by user yet
{
// copy mouse actions and voice key changes to new file
LL_INFOS("InitInfo") << "Converting legacy mouse bindings to new format" << LL_ENDL;
// Load settings from file
LLKeyConflictHandler third_person_view(LLKeyConflictHandler::MODE_THIRD_PERSON);
LLKeyConflictHandler sitting_view(LLKeyConflictHandler::MODE_SITTING);
// Since we are only modifying keybindings if personal file doesn't exist yet,
// it should be safe to just overwrite the value
// If key is already in use somewhere by default, LLKeyConflictHandler should resolve it.
BOOL value = gSavedSettings.getBOOL("DoubleClickAutoPilot");
third_person_view.registerControl("walk_to",
0,
value ? EMouseClickType::CLICK_DOUBLELEFT : EMouseClickType::CLICK_NONE,
KEY_NONE,
MASK_NONE,
value);
U32 index = value ? 1 : 0; // we can store multiple combinations per action, so if first is in use by doubleclick, go to second
value = gSavedSettings.getBOOL("ClickToWalk");
third_person_view.registerControl("walk_to",
index,
value ? EMouseClickType::CLICK_LEFT : EMouseClickType::CLICK_NONE,
KEY_NONE,
MASK_NONE,
value);
value = gSavedSettings.getBOOL("DoubleClickTeleport");
third_person_view.registerControl("teleport_to",
0,
value ? EMouseClickType::CLICK_DOUBLELEFT : EMouseClickType::CLICK_NONE,
KEY_NONE,
MASK_NONE,
value);
// sitting also supports teleport
sitting_view.registerControl("teleport_to",
0,
value ? EMouseClickType::CLICK_DOUBLELEFT : EMouseClickType::CLICK_NONE,
KEY_NONE,
MASK_NONE,
value);
std::string key_string = gSavedSettings.getString("PushToTalkButton");
EMouseClickType mouse = EMouseClickType::CLICK_NONE;
KEY key = KEY_NONE;
if (key_string == "MiddleMouse")
{
mouse = EMouseClickType::CLICK_MIDDLE;
}
else if (key_string == "MouseButton4")
{
mouse = EMouseClickType::CLICK_BUTTON4;
}
else if (key_string == "MouseButton5")
{
mouse = EMouseClickType::CLICK_BUTTON5;
}
else
{
LLKeyboard::keyFromString(key_string, &key);
}
value = gSavedSettings.getBOOL("PushToTalkToggle");
std::string control_name = value ? "toggle_voice" : "voice_follow_key";
third_person_view.registerControl(control_name, 0, mouse, key, MASK_NONE, true);
sitting_view.registerControl(control_name, 0, mouse, key, MASK_NONE, true);
if (third_person_view.hasUnsavedChanges())
{
// calls loadBindingsXML()
third_person_view.saveToSettings();
}
if (sitting_view.hasUnsavedChanges())
{
// calls loadBindingsXML()
sitting_view.saveToSettings();
}
// in case of voice we need to repeat this in other modes
for (U32 i = 0; i < LLKeyConflictHandler::MODE_COUNT - 1; ++i)
{
// edit and first person modes; MODE_SAVED_SETTINGS not in use at the moment
if (i != LLKeyConflictHandler::MODE_THIRD_PERSON && i != LLKeyConflictHandler::MODE_SITTING)
{
LLKeyConflictHandler handler((LLKeyConflictHandler::ESourceMode)i);
handler.registerControl(control_name, 0, mouse, key, MASK_NONE, true);
if (handler.hasUnsavedChanges())
{
// calls loadBindingsXML()
handler.saveToSettings();
}
}
}
}
// since something might have gone wrong or there might have been nothing to save
// (and because otherwise following code will have to be encased in else{}),
// load everything one last time
#endif
if (!gDirUtilp->fileExists(key_bindings_file) || !gViewerInput.loadBindingsXML(key_bindings_file))
{
// Failed to load custom bindings, try default ones
key_bindings_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "key_bindings.xml");
if (!gViewerInput.loadBindingsXML(key_bindings_file))
{
LL_ERRS("InitInfo") << "Unable to open default key bindings from " << key_bindings_file << LL_ENDL;
}
}
}
void LLAppViewer::purgeCache()
{
LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << LL_ENDL;

View File

@ -198,6 +198,8 @@ public:
void purgeCache(); // Clear the local cache.
void purgeCacheImmediate(); //clear local cache immediately.
S32 updateTextureThreads(F32 max_time);
void loadKeyBindings();
// mute/unmute the system's master audio
virtual void setMasterSystemAudioMute(bool mute);

File diff suppressed because it is too large Load Diff

View File

@ -37,13 +37,17 @@
#include "llavatarpropertiesprocessor.h"
#include "llconversationlog.h"
#include "llsearcheditor.h"
#include "llsetkeybinddialog.h"
#include "llkeyconflict.h"
class LLConversationLogObserver;
class LLPanelPreference;
class LLPanelLCD;
class LLPanelDebug;
class LLMessageSystem;
class LLComboBox;
class LLScrollListCtrl;
class LLScrollListCell;
class LLSliderCtrl;
class LLSD;
class LLTextBox;
@ -102,6 +106,8 @@ public:
void selectPrivacyPanel();
void selectChatPanel();
void getControlNames(std::vector<std::string>& names);
// updates click/double-click action controls depending on values from settings.xml
void updateClickActionViews();
protected:
void onBtnOK(const LLSD& userdata);
@ -129,9 +135,7 @@ protected:
// callback for commit in the "Single click on land" and "Double click on land" comboboxes.
void onClickActionChange();
// updates click/double-click action settings depending on controls values
void updateClickActionSettings();
// updates click/double-click action controls depending on values from settings.xml
// updates click/double-click action keybindngs depending on view values
void updateClickActionControls();
public:
@ -146,10 +150,6 @@ public:
void onClickResetCache();
void onClickSkin(LLUICtrl* ctrl,const LLSD& userdata);
void onSelectSkin();
void onClickSetKey();
void setKey(KEY key);
void setMouse(LLMouseHandler::EClickType click);
void onClickSetMiddleMouse();
void onClickSetSounds();
void onClickEnablePopup();
void onClickDisablePopup();
@ -204,7 +204,6 @@ private:
static std::string sSkin;
notifications_map mNotificationOptions;
bool mClickActionDirty; ///< Set to true when the click/double-click options get changed by user.
bool mGotPersonalInfo;
bool mOriginalIMViaEmail;
bool mLanguageChanged;
@ -294,6 +293,60 @@ private:
LOG_CLASS(LLPanelPreferenceGraphics);
};
class LLPanelPreferenceControls : public LLPanelPreference, public LLKeyBindResponderInterface
{
LOG_CLASS(LLPanelPreferenceControls);
public:
LLPanelPreferenceControls();
virtual ~LLPanelPreferenceControls();
BOOL postBuild();
void apply();
void cancel();
void saveSettings();
void resetDirtyChilds();
void onListCommit();
void onModeCommit();
void onRestoreDefaultsBtn();
void onRestoreDefaultsResponse(const LLSD& notification, const LLSD& response);
// Bypass to let Move & view read values without need to create own key binding handler
// Todo: consider a better way to share access to keybindings
bool canKeyBindHandle(const std::string &control, EMouseClickType click, KEY key, MASK mask);
// Bypasses to let Move & view modify values without need to create own key binding handler
void setKeyBind(const std::string &control, EMouseClickType click, KEY key, MASK mask, bool set /*set or reset*/ );
void updateAndApply();
// from interface
/*virtual*/ bool onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes);
/*virtual*/ void onDefaultKeyBind(bool all_modes);
/*virtual*/ void onCancelKeyBind();
private:
// reloads settings, discards current changes, updates table
void regenerateControls();
// These fuctions do not clean previous content
bool addControlTableColumns(const std::string &filename);
bool addControlTableRows(const std::string &filename);
void addControlTableSeparator();
// Cleans content and then adds content from xml files according to current mEditingMode
void populateControlTable();
// Updates keybindings from storage to table
void updateTable();
LLScrollListCtrl* pControlsTable;
LLComboBox *pKeyModeBox;
LLKeyConflictHandler mConflictHandler[LLKeyConflictHandler::MODE_COUNT];
std::string mEditingControl;
S32 mEditingColumn;
S32 mEditingMode;
};
class LLFloaterPreferenceGraphicsAdvanced : public LLFloater
{
public:

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,175 @@
/**
* @file llkeyconflict.h
* @brief
*
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2019, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLKEYCONFLICT_H
#define LL_LLKEYCONFLICT_H
#include "llkeybind.h"
#include "llviewerinput.h"
class LLKeyConflict
{
public:
LLKeyConflict() : mAssignable(true), mConflictMask(U32_MAX) {} //temporary assignable, don't forget to change once all keys are recorded
LLKeyConflict(bool assignable, U32 conflict_mask)
: mAssignable(assignable), mConflictMask(conflict_mask) {}
LLKeyConflict(const LLKeyBind &bind, bool assignable, U32 conflict_mask)
: mAssignable(assignable), mConflictMask(conflict_mask), mKeyBind(bind) {}
LLKeyData getPrimaryKeyData() { return mKeyBind.getKeyData(0); }
LLKeyData getKeyData(U32 index) { return mKeyBind.getKeyData(index); }
void setPrimaryKeyData(const LLKeyData& data) { mKeyBind.replaceKeyData(data, 0); }
void setKeyData(const LLKeyData& data, U32 index) { mKeyBind.replaceKeyData(data, index); }
bool canHandle(EMouseClickType mouse, KEY key, MASK mask) { return mKeyBind.canHandle(mouse, key, mask); }
LLKeyBind mKeyBind;
bool mAssignable; // whether user can change key or key simply acts as placeholder
U32 mConflictMask;
};
class LLKeyConflictHandler
{
public:
enum ESourceMode // partially repeats e_keyboard_mode
{
MODE_FIRST_PERSON,
MODE_THIRD_PERSON,
MODE_EDIT_AVATAR,
MODE_SITTING,
MODE_SAVED_SETTINGS, // for settings from saved settings
MODE_COUNT
};
const U32 CONFLICT_NOTHING = 0;
// at the moment this just means that key will conflict with everything that is identical
const U32 CONFLICT_ANY = U32_MAX;
// Note: missed selection and edition commands (would be really nice to go through selection via MB4/5 or wheel)
LLKeyConflictHandler();
LLKeyConflictHandler(ESourceMode mode);
~LLKeyConflictHandler();
bool canHandleControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask);
bool canHandleKey(const std::string &control_name, KEY key, MASK mask);
bool canHandleMouse(const std::string &control_name, EMouseClickType mouse_ind, MASK mask);
bool canHandleMouse(const std::string &control_name, S32 mouse_ind, MASK mask); //Just for convinience
bool canAssignControl(const std::string &control_name);
static bool isReservedByMenu(const KEY &key, const MASK &mask);
static bool isReservedByMenu(const LLKeyData &data);
// @control_name - see REGISTER_KEYBOARD_ACTION in llviewerinput for avaliable options,
// usually this is just name of the function
// @data_index - single control (function) can have multiple key combinations trigering
// it, this index indicates combination function will change/add; Note that preferences
// floater can only display up to 3 options, but data_index can be bigger than that
// @mouse_ind - mouse action (middle click, MB5 etc)
// @key - keyboard key action
// @mask - shift/ctrl/alt flags
// @ignore_mask - Either to expect exact match (ctrl+K will not trigger if ctrl+shift+K
// is active) or ignore not expected masks as long as expected mask is present
// (ctrl+K will be triggered if ctrl+shift+K is active)
bool registerControl(const std::string &control_name, U32 data_index, EMouseClickType mouse_ind, KEY key, MASK mask, bool ignore_mask); //todo: return conflicts?
bool clearControl(const std::string &control_name, U32 data_index);
LLKeyData getControl(const std::string &control_name, U32 data_index);
bool isControlEmpty(const std::string &control_name);
// localized string
static std::string getStringFromKeyData(const LLKeyData& keydata);
std::string getControlString(const std::string &control_name, U32 data_index);
// Load single control, overrides existing one if names match
void loadFromControlSettings(const std::string &name);
// Drops any changes loads controls with ones from 'saved settings' or from xml
void loadFromSettings(ESourceMode load_mode);
// Saves settings to 'saved settings' or to xml
// If 'temporary' is set, function will save settings to temporary
// file and reload input bindings from temporary file.
// 'temporary' does not support gSavedSettings, those are handled
// by preferences, so 'temporary' is such case will simply not
// reset mHasUnsavedChanges
//
// 'temporary' exists to support ability of live-editing settings in
// preferences: temporary for testing changes 'live' without saving them,
// then hitting ok/cancel and save/discard values permanently.
void saveToSettings(bool apply_temporary = false);
LLKeyData getDefaultControl(const std::string &control_name, U32 data_index);
// Resets keybinding to default variant from 'saved settings' or xml
void resetToDefault(const std::string &control_name, U32 index);
void resetToDefault(const std::string &control_name);
// resets current mode to defaults
void resetToDefaults();
bool empty() { return mControlsMap.empty(); }
void clear();
// reloads bindings from last valid user's xml or from default xml
// to keyboard's handler
static void resetKeyboardBindings();
bool hasUnsavedChanges() { return mHasUnsavedChanges; }
void setLoadMode(ESourceMode mode) { mLoadMode = mode; }
ESourceMode getLoadMode() { return mLoadMode; }
private:
void resetToDefaultAndResolve(const std::string &control_name, bool ignore_conflicts);
void resetToDefaults(ESourceMode mode);
// at the moment these kind of control is not savable, but takes part in conflict resolution
void registerTemporaryControl(const std::string &control_name, EMouseClickType mouse_ind, KEY key, MASK mask, U32 conflict_mask);
void registerTemporaryControl(const std::string &control_name, U32 conflict_mask = 0);
typedef std::map<std::string, LLKeyConflict> control_map_t;
void loadFromSettings(const LLViewerInput::KeyMode& keymode, control_map_t *destination);
bool loadFromSettings(const ESourceMode &load_mode, const std::string &filename, control_map_t *destination);
void generatePlaceholders(ESourceMode load_mode); //E.x. non-assignable values
// returns false in case user is trying to reuse control that can't be reassigned
bool removeConflicts(const LLKeyData &data, const U32 &conlict_mask);
// removes flags and removes temporary file, returns 'true' if file was removed
bool clearUnsavedChanges();
// return true if there was a file to remove
static bool clearTemporaryFile();
control_map_t mControlsMap;
control_map_t mDefaultsMap;
bool mHasUnsavedChanges;
ESourceMode mLoadMode;
// To implement 'apply immediately'+revert on cancel, class applies changes to temporary file
// but this only works for settings from keybndings files (key_bindings.xml)
// saved setting rely onto external mechanism of preferences floater
bool mUsesTemporaryFile;
static S32 sTemporaryFileUseCount;
};
#endif // LL_LLKEYCONFLICT_H

View File

@ -373,11 +373,11 @@ BOOL LLPreviewGesture::postBuild()
mReplaceEditor = edit;
combo = getChild<LLComboBox>( "modifier_combo");
combo->setCommitCallback(onCommitSetDirty, this);
combo->setCommitCallback(boost::bind(&LLPreviewGesture::onCommitKeyorModifier, this));
mModifierCombo = combo;
combo = getChild<LLComboBox>( "key_combo");
combo->setCommitCallback(onCommitSetDirty, this);
combo->setCommitCallback(boost::bind(&LLPreviewGesture::onCommitKeyorModifier, this));
mKeyCombo = combo;
list = getChild<LLScrollListCtrl>("library_list");
@ -937,12 +937,16 @@ void LLPreviewGesture::loadUIFromGesture(LLMultiGesture* gesture)
break;
}
mModifierCombo->setEnabledByValue(CTRL_LABEL, gesture->mKey != KEY_F10);
mKeyCombo->setCurrentByIndex(0);
if (gesture->mKey != KEY_NONE)
{
mKeyCombo->setSimple(LLKeyboard::stringFromKey(gesture->mKey));
}
mKeyCombo->setEnabledByValue(LLKeyboard::stringFromKey(KEY_F10), gesture->mMask != MASK_CONTROL);
// Make UI steps for each gesture step
S32 i;
S32 count = gesture->mSteps.size();
@ -1338,6 +1342,17 @@ LLMultiGesture* LLPreviewGesture::createGesture()
}
void LLPreviewGesture::onCommitKeyorModifier()
{
// SL-14139: ctrl-F10 is currently used to access top menu,
// so don't allow to bound gestures to this combination.
mKeyCombo->setEnabledByValue(LLKeyboard::stringFromKey(KEY_F10), mModifierCombo->getSimple() != CTRL_LABEL);
mModifierCombo->setEnabledByValue(CTRL_LABEL, mKeyCombo->getSimple() != LLKeyboard::stringFromKey(KEY_F10));
mDirty = TRUE;
refresh();
}
// static
void LLPreviewGesture::updateLabel(LLScrollListItem* item)
{

View File

@ -103,6 +103,8 @@ protected:
LLScrollListItem* addStep(const enum EStepType step_type);
void onVisibilityChanged ( const LLSD& new_visibility );
void onCommitKeyorModifier();
static std::string getLabel(std::vector<std::string> labels);
static void updateLabel(LLScrollListItem* item);

View File

@ -0,0 +1,380 @@
/**
* @file llsetkeybinddialog.cpp
* @brief LLSetKeyBindDialog class implementation.
*
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2019, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llsetkeybinddialog.h"
#include "llbutton.h"
#include "llcheckboxctrl.h"
#include "lleventtimer.h"
#include "llfloaterreg.h"
#include "llfocusmgr.h"
#include "llkeyconflict.h"
#include "llviewercontrol.h"
class LLSetKeyBindDialog::Updater : public LLEventTimer
{
public:
typedef boost::function<void(MASK)> callback_t;
Updater(callback_t cb, F32 period, MASK mask)
:LLEventTimer(period),
mMask(mask),
mCallback(cb)
{
mEventTimer.start();
}
virtual ~Updater(){}
protected:
BOOL tick()
{
mCallback(mMask);
// Deletes itseft after execution
return TRUE;
}
private:
MASK mMask;
callback_t mCallback;
};
bool LLSetKeyBindDialog::sRecordKeys = false;
LLSetKeyBindDialog::LLSetKeyBindDialog(const LLSD& key)
: LLModalDialog(key),
pParent(NULL),
mKeyFilterMask(DEFAULT_KEY_FILTER),
pUpdater(NULL),
mLastMaskKey(0),
mContextConeOpacity(0.f),
mContextConeInAlpha(0.f),
mContextConeOutAlpha(0.f),
mContextConeFadeTime(0.f)
{
mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha");
mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha");
mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime");
}
LLSetKeyBindDialog::~LLSetKeyBindDialog()
{
}
//virtual
BOOL LLSetKeyBindDialog::postBuild()
{
childSetAction("SetEmpty", onBlank, this);
childSetAction("Default", onDefault, this);
childSetAction("Cancel", onCancel, this);
getChild<LLUICtrl>("Cancel")->setFocus(TRUE);
pCheckBox = getChild<LLCheckBoxCtrl>("apply_all");
pDesription = getChild<LLTextBase>("descritption");
gFocusMgr.setKeystrokesOnly(TRUE);
return TRUE;
}
//virtual
void LLSetKeyBindDialog::onOpen(const LLSD& data)
{
sRecordKeys = true;
LLModalDialog::onOpen(data);
}
//virtual
void LLSetKeyBindDialog::onClose(bool app_quiting)
{
sRecordKeys = false;
if (pParent)
{
pParent->onCancelKeyBind();
pParent = NULL;
}
if (pUpdater)
{
// Doubleclick timer has't fired, delete it
delete pUpdater;
pUpdater = NULL;
}
LLModalDialog::onClose(app_quiting);
}
void LLSetKeyBindDialog::drawFrustum()
{
static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f);
drawConeToOwner(mContextConeOpacity, max_opacity, mFrustumOrigin.get(), mContextConeFadeTime, mContextConeInAlpha, mContextConeOutAlpha);
}
//virtual
void LLSetKeyBindDialog::draw()
{
drawFrustum();
LLModalDialog::draw();
}
void LLSetKeyBindDialog::setParent(LLKeyBindResponderInterface* parent, LLView* frustum_origin, U32 key_mask)
{
pParent = parent;
mFrustumOrigin = frustum_origin->getHandle();
mKeyFilterMask = key_mask;
std::string input;
if ((key_mask & ALLOW_MOUSE) != 0)
{
input = getString("mouse");
}
if ((key_mask & ALLOW_KEYS) != 0)
{
if (!input.empty())
{
input += ", ";
}
input += getString("keyboard");
}
pDesription->setText(getString("basic_description"));
pDesription->setTextArg("[INPUT]", input);
}
// static
bool LLSetKeyBindDialog::recordKey(KEY key, MASK mask, BOOL down)
{
if (sRecordKeys)
{
LLSetKeyBindDialog* dialog = LLFloaterReg::getTypedInstance<LLSetKeyBindDialog>("keybind_dialog", LLSD());
if (dialog && dialog->getVisible())
{
return dialog->recordAndHandleKey(key, mask, down);
}
else
{
LL_WARNS() << "Key recording was set despite no open dialog" << LL_ENDL;
sRecordKeys = false;
}
}
return false;
}
bool LLSetKeyBindDialog::recordAndHandleKey(KEY key, MASK mask, BOOL down)
{
if ((key == 'Q' && mask == MASK_CONTROL)
|| key == KEY_ESCAPE)
{
sRecordKeys = false;
closeFloater();
return true;
}
if (key == KEY_DELETE)
{
setKeyBind(CLICK_NONE, KEY_NONE, MASK_NONE, false);
sRecordKeys = false;
closeFloater();
return false;
}
// forbidden keys
if (key == KEY_NONE
|| key == KEY_RETURN
|| key == KEY_BACKSPACE)
{
return false;
}
if (key == KEY_CONTROL || key == KEY_SHIFT || key == KEY_ALT)
{
// Mask keys get special treatment
if ((mKeyFilterMask & ALLOW_MASKS) == 0)
{
// Masks by themself are not allowed
return false;
}
if (down == TRUE)
{
// Most keys are handled on 'down' event because menu is handled on 'down'
// masks are exceptions to let other keys be handled
mLastMaskKey = key;
return false;
}
if (mLastMaskKey != key)
{
// This was mask+key combination that got rejected, don't handle mask's key
// Or user did something like: press shift, press ctrl, release shift
return false;
}
// Mask up event often generates things like 'shift key + shift mask', filter it out.
if (key == KEY_CONTROL)
{
mask &= ~MASK_CONTROL;
}
if (key == KEY_SHIFT)
{
mask &= ~MASK_SHIFT;
}
if (key == KEY_ALT)
{
mask &= ~MASK_ALT;
}
}
if ((mKeyFilterMask & ALLOW_KEYS) == 0)
{
// basic keys not allowed
return false;
}
else if ((mKeyFilterMask & ALLOW_MASK_KEYS) == 0 && mask != 0)
{
// masked keys not allowed
return false;
}
if (LLKeyConflictHandler::isReservedByMenu(key, mask))
{
pDesription->setText(getString("reserved_by_menu"));
pDesription->setTextArg("[KEYSTR]", LLKeyboard::stringFromAccelerator(mask,key));
mLastMaskKey = 0;
return true;
}
setKeyBind(CLICK_NONE, key, mask, pCheckBox->getValue().asBoolean());
// Note/Todo: To warranty zero interference we should also consume
// an 'up' event if we recorded on 'down', not just close floater
// on first recorded combination.
sRecordKeys = false;
closeFloater();
return true;
}
BOOL LLSetKeyBindDialog::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down)
{
BOOL result = FALSE;
if (!pParent)
{
// we already processed 'down' event, this is 'up', consume
closeFloater();
result = TRUE;
}
if (!result && clicktype == CLICK_LEFT)
{
// try handling buttons first
if (down)
{
result = LLView::handleMouseDown(x, y, mask);
}
else
{
result = LLView::handleMouseUp(x, y, mask);
}
if (result)
{
setFocus(TRUE);
gFocusMgr.setKeystrokesOnly(TRUE);
}
// ignore selection related combinations
else if (down && (mask & (MASK_SHIFT | MASK_CONTROL)) == 0)
{
// this can be a double click, wait a bit;
if (!pUpdater)
{
// Note: default doubleclick time is 500ms, but can stretch up to 5s
pUpdater = new Updater(boost::bind(&onClickTimeout, this, _1), 0.7f, mask);
result = TRUE;
}
}
}
if (!result
&& (clicktype != CLICK_LEFT) // subcases were handled above
&& ((mKeyFilterMask & ALLOW_MOUSE) != 0)
&& (clicktype != CLICK_RIGHT || mask != 0) // reassigning menu button is not supported
&& ((mKeyFilterMask & ALLOW_MASK_MOUSE) != 0 || mask == 0)) // reserved for selection
{
setKeyBind(clicktype, KEY_NONE, mask, pCheckBox->getValue().asBoolean());
result = TRUE;
if (!down)
{
// wait for 'up' event before closing
// alternative: set pUpdater
closeFloater();
}
}
return result;
}
//static
void LLSetKeyBindDialog::onCancel(void* user_data)
{
LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data;
self->closeFloater();
}
//static
void LLSetKeyBindDialog::onBlank(void* user_data)
{
LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data;
// tmp needs 'no key' button
self->setKeyBind(CLICK_NONE, KEY_NONE, MASK_NONE, false);
self->closeFloater();
}
//static
void LLSetKeyBindDialog::onDefault(void* user_data)
{
LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data;
if (self->pParent)
{
self->pParent->onDefaultKeyBind(self->pCheckBox->getValue().asBoolean());
self->pParent = NULL;
}
self->closeFloater();
}
//static
void LLSetKeyBindDialog::onClickTimeout(void* user_data, MASK mask)
{
LLSetKeyBindDialog* self = (LLSetKeyBindDialog*)user_data;
// timer will delete itself after timeout
self->pUpdater = NULL;
self->setKeyBind(CLICK_LEFT, KEY_NONE, mask, self->pCheckBox->getValue().asBoolean());
self->closeFloater();
}
void LLSetKeyBindDialog::setKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes)
{
if (pParent)
{
pParent->onSetKeyBind(click, key, mask, all_modes);
pParent = NULL;
}
}

View File

@ -0,0 +1,106 @@
/**
* @file llsetkeybinddialog.h
* @brief LLSetKeyBindDialog class definition
*
* $LicenseInfo:firstyear=2019&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2019, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLSETKEYBINDDIALOG_H
#define LL_LLSETKEYBINDDIALOG_H
#include "llmodaldialog.h"
class LLCheckBoxCtrl;
class LLTextBase;
// Filters for LLSetKeyBindDialog
static const U32 ALLOW_MOUSE = 1;
static const U32 ALLOW_MASK_MOUSE = 2;
static const U32 ALLOW_KEYS = 4; //keyboard
static const U32 ALLOW_MASK_KEYS = 8;
static const U32 ALLOW_MASKS = 16;
static const U32 DEFAULT_KEY_FILTER = ALLOW_MOUSE | ALLOW_MASK_MOUSE | ALLOW_KEYS | ALLOW_MASKS | ALLOW_MASK_KEYS;
class LLKeyBindResponderInterface
{
public:
virtual ~LLKeyBindResponderInterface() {};
virtual void onCancelKeyBind() = 0;
virtual void onDefaultKeyBind(bool all_modes) = 0;
// returns true if parent failed to set key due to key being in use
virtual bool onSetKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes) = 0;
};
class LLSetKeyBindDialog : public LLModalDialog
{
public:
LLSetKeyBindDialog(const LLSD& key);
~LLSetKeyBindDialog();
/*virtual*/ BOOL postBuild();
/*virtual*/ void onOpen(const LLSD& data);
/*virtual*/ void onClose(bool app_quiting);
/*virtual*/ void draw();
void setParent(LLKeyBindResponderInterface* parent, LLView* frustum_origin, U32 key_mask = DEFAULT_KEY_FILTER);
// Wrapper around recordAndHandleKey
// It does not record, it handles, but handleKey function is already in use
static bool recordKey(KEY key, MASK mask, BOOL down);
BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down);
static void onCancel(void* user_data);
static void onBlank(void* user_data);
static void onDefault(void* user_data);
static void onClickTimeout(void* user_data, MASK mask);
class Updater;
private:
bool recordAndHandleKey(KEY key, MASK mask, BOOL down);
void setKeyBind(EMouseClickType click, KEY key, MASK mask, bool all_modes);
LLKeyBindResponderInterface *pParent;
LLCheckBoxCtrl *pCheckBox;
LLTextBase *pDesription;
U32 mKeyFilterMask;
Updater *pUpdater;
KEY mLastMaskKey;
static bool sRecordKeys; // for convinience and not to check instance each time
// drawFrustum
private:
void drawFrustum();
LLHandle <LLView> mFrustumOrigin;
F32 mContextConeOpacity;
F32 mContextConeInAlpha;
F32 mContextConeOutAlpha;
F32 mContextConeFadeTime;
};
#endif // LL_LLSETKEYBINDDIALOG_H

View File

@ -309,7 +309,8 @@ void LLSkinningUtil::updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *a
if (vol_face.mJointRiggingInfoTab.needsUpdate())
{
S32 num_verts = vol_face.mNumVertices;
if (num_verts>0 && vol_face.mWeights && (skin->mJointNames.size()>0))
S32 num_joints = skin->mJointNames.size();
if (num_verts > 0 && vol_face.mWeights && num_joints > 0)
{
initJointNums(const_cast<LLMeshSkinInfo*>(skin), avatar);
if (vol_face.mJointRiggingInfoTab.size()==0)
@ -343,7 +344,7 @@ void LLSkinningUtil::updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *a
for (U32 k=0; k<4; ++k)
{
S32 joint_index = idx[k];
if (wght[k] > 0.0f)
if (wght[k] > 0.0f && num_joints > joint_index)
{
S32 joint_num = skin->mJointNums[joint_index];
if (joint_num >= 0 && joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS)
@ -394,35 +395,6 @@ void LLSkinningUtil::updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *a
}
}
void LLSkinningUtil::updateRiggingInfo_(LLMeshSkinInfo* skin, LLVOAvatar *avatar, S32 num_verts, LLVector4a* weights, LLVector4a* positions, U8* joint_indices, LLJointRiggingInfoTab &rig_info_tab)
{
LL_RECORD_BLOCK_TIME(FTM_FACE_RIGGING_INFO);
for (S32 i=0; i < num_verts; i++)
{
LLVector4a& pos = positions[i];
LLVector4a& wght = weights[i];
for (U32 k=0; k<4; ++k)
{
S32 joint_num = skin->mJointNums[joint_indices[k]];
llassert(joint_num >= 0 && joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS);
{
rig_info_tab[joint_num].setIsRiggedTo(true);
LLMatrix4a bind_shape;
bind_shape.loadu(skin->mBindShapeMatrix);
LLMatrix4a inv_bind;
inv_bind.loadu(skin->mInvBindMatrix[joint_indices[k]]);
LLMatrix4a mat;
matMul(bind_shape, inv_bind, mat);
LLVector4a pos_joint_space;
mat.affineTransform(pos, pos_joint_space);
pos_joint_space.mul(wght[k]);
LLVector4a *extents = rig_info_tab[joint_num].getRiggedExtents();
update_min_max(extents[0], extents[1], pos_joint_space);
}
}
}
}
// This is used for extracting rotation from a bind shape matrix that
// already has scales baked in
LLQuaternion LLSkinningUtil::getUnscaledQuaternion(const LLMatrix4& mat4)

View File

@ -67,7 +67,6 @@ namespace LLSkinningUtil
void initJointNums(LLMeshSkinInfo* skin, LLVOAvatar *avatar);
void updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *avatar, LLVolumeFace& vol_face);
void updateRiggingInfo_(LLMeshSkinInfo* skin, LLVOAvatar *avatar, S32 num_verts, LLVector4a* weights, LLVector4a* positions, U8* joint_indices, LLJointRiggingInfoTab &rig_info_tab);
LLQuaternion getUnscaledQuaternion(const LLMatrix4& mat4);
};

View File

@ -996,7 +996,7 @@ LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible)
}
LLSpatialGroup* group = drawablep->getSpatialGroup();
llassert(group != NULL);
//llassert(group != NULL);
if (group && was_visible && group->isOcclusionState(LLSpatialGroup::QUERY_PENDING))
{

View File

@ -1425,7 +1425,10 @@ bool idle_startup()
// update the voice settings *after* gCacheName initialization
// so that we can construct voice UI that relies on the name cache
LLVoiceClient::getInstance()->updateSettings();
if (LLVoiceClient::instanceExists())
{
LLVoiceClient::getInstance()->updateSettings();
}
display_startup();
// create a container's instance for start a controlling conversation windows

View File

@ -73,6 +73,7 @@
#include "llavatarappearancedefines.h"
static const S32 LOCAL_TRACKING_ID_COLUMN = 1;
//static const char CURRENT_IMAGE_NAME[] = "Current Texture";

View File

@ -60,7 +60,7 @@ LLTool::~LLTool()
}
}
BOOL LLTool::handleAnyMouseClick(S32 x, S32 y, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down)
BOOL LLTool::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down)
{
BOOL result = LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down);
@ -83,9 +83,9 @@ BOOL LLTool::handleMouseDown(S32 x, S32 y, MASK mask)
LL_INFOS() << "LLTool left mouse down" << LL_ENDL;
}
// by default, didn't handle it
// AGENT_CONTROL_LBUTTON_DOWN is handled by scanMouse() and scanKey()
// LL_INFOS() << "LLTool::handleMouseDown" << LL_ENDL;
gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_DOWN);
return TRUE;
return FALSE;
}
BOOL LLTool::handleMouseUp(S32 x, S32 y, MASK mask)
@ -95,8 +95,8 @@ BOOL LLTool::handleMouseUp(S32 x, S32 y, MASK mask)
LL_INFOS() << "LLTool left mouse up" << LL_ENDL;
}
// by default, didn't handle it
// AGENT_CONTROL_LBUTTON_UP is handled by scanMouse() and scanKey()
// LL_INFOS() << "LLTool::handleMouseUp" << LL_ENDL;
gAgent.setControlFlags(AGENT_CONTROL_LBUTTON_UP);
return TRUE;
}

View File

@ -49,7 +49,7 @@ public:
virtual BOOL isView() const { return FALSE; }
// Virtual functions inherited from LLMouseHandler
virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down);
virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask);

View File

@ -63,6 +63,7 @@
#include "llviewerobject.h"
#include "llviewerparcelmgr.h"
#include "llviewerwindow.h"
#include "llviewerinput.h"
#include "llviewermedia.h"
#include "llvoavatarself.h"
#include "llviewermediafocus.h"
@ -83,7 +84,6 @@ LLToolPie::LLToolPie()
mMouseOutsideSlop( false ),
mMouseSteerX(-1),
mMouseSteerY(-1),
mBlockClickToWalk(false),
mClickAction(0),
mClickActionBuyEnabled( gSavedSettings.getBOOL("ClickActionBuyEnabled") ),
mClickActionPayEnabled( gSavedSettings.getBOOL("ClickActionPayEnabled") ),
@ -91,7 +91,7 @@ LLToolPie::LLToolPie()
{
}
BOOL LLToolPie::handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down)
BOOL LLToolPie::handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down)
{
BOOL result = LLMouseHandler::handleAnyMouseClick(x, y, mask, clicktype, down);
@ -172,10 +172,8 @@ BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask)
mPick.mKeyMask = mask;
mMouseButtonDown = true;
handleLeftClickPick();
return TRUE;
return handleLeftClickPick();
}
// Spawn context menus on right mouse down so you can drag over and select
@ -391,8 +389,6 @@ BOOL LLToolPie::handleLeftClickPick()
// put focus back "in world"
if (gFocusMgr.getKeyboardFocus())
{
// don't click to walk on attempt to give focus to world
mBlockClickToWalk = true;
gFocusMgr.setKeyboardFocus(NULL);
}
@ -436,7 +432,7 @@ BOOL LLToolPie::handleLeftClickPick()
}
object = (LLViewerObject*)object->getParent();
}
if (object && object == gAgentAvatarp && !gSavedSettings.getBOOL("ClickToWalk"))
if (object && object == gAgentAvatarp)
{
// we left clicked on avatar, switch to focus mode
mMouseButtonDown = false;
@ -453,7 +449,6 @@ BOOL LLToolPie::handleLeftClickPick()
// LLFirstUse::useLeftClickNoHit();
/////////
// Eat the event
return LLTool::handleMouseDown(x, y, mask);
}
@ -560,17 +555,120 @@ void LLToolPie::resetSelection()
mClickAction = 0;
}
void LLToolPie::walkToClickedLocation()
bool LLToolPie::walkToClickedLocation()
{
if(mAutoPilotDestination) { mAutoPilotDestination->markDead(); }
mAutoPilotDestination = (LLHUDEffectBlob *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BLOB, FALSE);
mAutoPilotDestination->setPositionGlobal(mPick.mPosGlobal);
mAutoPilotDestination->setPixelSize(5);
mAutoPilotDestination->setColor(LLColor4U(170, 210, 190));
mAutoPilotDestination->setDuration(3.f);
if (gAgent.getFlying() // don't auto-navigate while flying until that works
|| !gAgentAvatarp
|| gAgentAvatarp->isSitting())
{
return false;
}
LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal;
gAgent.startAutoPilotGlobal(pos, std::string(), NULL, NULL, NULL, 0.f, 0.03f, FALSE);
LLPickInfo saved_pick = mPick;
if (gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK)
{
mPick = gViewerWindow->pickImmediate(mHoverPick.mMousePt.mX, mHoverPick.mMousePt.mY,
FALSE /* ignore transparent */,
FALSE /* ignore rigged */,
FALSE /* ignore particles */);
}
else
{
// We do not handle hover in mouselook as we do in other modes, so
// use croshair's position to do a pick
mPick = gViewerWindow->pickImmediate(gViewerWindow->getWorldViewRectScaled().getWidth() / 2,
gViewerWindow->getWorldViewRectScaled().getHeight() / 2,
FALSE /* ignore transparent */,
FALSE /* ignore rigged */,
FALSE /* ignore particles */);
}
if (mPick.mPickType == LLPickInfo::PICK_OBJECT)
{
if (mPick.getObject() && mPick.getObject()->isHUDAttachment())
{
mPick = saved_pick;
return false;
}
}
LLViewerObject* avatar_object = mPick.getObject();
// get pointer to avatar
while (avatar_object && !avatar_object->isAvatar())
{
avatar_object = (LLViewerObject*)avatar_object->getParent();
}
if (avatar_object && ((LLVOAvatar*)avatar_object)->isSelf())
{
const F64 SELF_CLICK_WALK_DISTANCE = 3.0;
// pretend we picked some point a bit in front of avatar
mPick.mPosGlobal = gAgent.getPositionGlobal() + LLVector3d(LLViewerCamera::instance().getAtAxis()) * SELF_CLICK_WALK_DISTANCE;
}
if ((mPick.mPickType == LLPickInfo::PICK_LAND && !mPick.mPosGlobal.isExactlyZero()) ||
(mPick.mObjectID.notNull() && !mPick.mPosGlobal.isExactlyZero()))
{
gAgentCamera.setFocusOnAvatar(TRUE, TRUE);
if (mAutoPilotDestination) { mAutoPilotDestination->markDead(); }
mAutoPilotDestination = (LLHUDEffectBlob *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BLOB, FALSE);
mAutoPilotDestination->setPositionGlobal(mPick.mPosGlobal);
mAutoPilotDestination->setPixelSize(5);
mAutoPilotDestination->setColor(LLColor4U(170, 210, 190));
mAutoPilotDestination->setDuration(3.f);
LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal;
gAgent.startAutoPilotGlobal(pos, std::string(), NULL, NULL, NULL, 0.f, 0.03f, FALSE);
LLFirstUse::notMoving(false);
showVisualContextMenuEffect();
return true;
}
else
{
LL_DEBUGS() << "walk target was "
<< (mPick.mPosGlobal.isExactlyZero() ? "zero" : "not zero")
<< ", pick type was " << (mPick.mPickType == LLPickInfo::PICK_LAND ? "land" : "not land")
<< ", pick object was " << mPick.mObjectID
<< LL_ENDL;
mPick = saved_pick;
return false;
}
return true;
}
bool LLToolPie::teleportToClickedLocation()
{
if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK)
{
// We do not handle hover in mouselook as we do in other modes, so
// use croshair's position to do a pick
BOOL pick_rigged = false;
mHoverPick = gViewerWindow->pickImmediate(gViewerWindow->getWorldViewRectScaled().getWidth() / 2,
gViewerWindow->getWorldViewRectScaled().getHeight() / 2,
FALSE,
pick_rigged);
}
LLViewerObject* objp = mHoverPick.getObject();
LLViewerObject* parentp = objp ? objp->getRootEdit() : NULL;
bool is_in_world = mHoverPick.mObjectID.notNull() && objp && !objp->isHUDAttachment();
bool is_land = mHoverPick.mPickType == LLPickInfo::PICK_LAND;
bool pos_non_zero = !mHoverPick.mPosGlobal.isExactlyZero();
bool has_touch_handler = (objp && objp->flagHandleTouch()) || (parentp && parentp->flagHandleTouch());
bool has_click_action = final_click_action(objp);
if (pos_non_zero && (is_land || (is_in_world && !has_touch_handler && !has_click_action)))
{
LLVector3d pos = mHoverPick.mPosGlobal;
pos.mdV[VZ] += gAgentAvatarp->getPelvisToFoot();
gAgent.teleportViaLocationLookAt(pos);
mPick = mHoverPick;
showVisualContextMenuEffect();
return true;
}
return false;
}
// When we get object properties after left-clicking on an object
@ -646,8 +744,9 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
LL_DEBUGS("UserInput") << "hover handled by LLToolPie (inactive)" << LL_ENDL;
}
else if (!mMouseOutsideSlop
&& mMouseButtonDown
&& gSavedSettings.getBOOL("ClickToWalk"))
&& mMouseButtonDown
// disable camera steering if click on land is not used for moving
&& gViewerInput.isMouseBindUsed(CLICK_LEFT))
{
S32 delta_x = x - mMouseDownX;
S32 delta_y = y - mMouseDownY;
@ -732,70 +831,10 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask)
mDoubleClickTimer.reset();
}
LLViewerObject* obj = mPick.getObject();
U8 click_action = final_click_action(obj);
// let media have first pass at click
if (handleMediaMouseUp() || LLViewerMediaFocus::getInstance()->getFocus())
{
mBlockClickToWalk = true;
}
stopCameraSteering();
mMouseButtonDown = false;
if (click_action == CLICK_ACTION_NONE // not doing 1-click action
&& gSavedSettings.getBOOL("ClickToWalk") // click to walk enabled
&& !gAgent.getFlying() // don't auto-navigate while flying until that works
&& gAgentAvatarp
&& !gAgentAvatarp->isSitting()
&& !mBlockClickToWalk // another behavior hasn't cancelled click to walk
)
{
// We may be doing click to walk, but we don't want to use a target on
// a transparent object because the user thought they were clicking on
// whatever they were seeing through it, so recompute what was clicked on
// ignoring transparent objects
LLPickInfo savedPick = mPick;
mPick = gViewerWindow->pickImmediate(savedPick.mMousePt.mX, savedPick.mMousePt.mY,
FALSE /* ignore transparent */,
FALSE /* ignore rigged */,
FALSE /* ignore particles */);
if (!mPick.mPosGlobal.isExactlyZero() // valid coordinates for pick
&& (mPick.mPickType == LLPickInfo::PICK_LAND // we clicked on land
|| mPick.mObjectID.notNull())) // or on an object
{
// handle special cases of steering picks
LLViewerObject* avatar_object = mPick.getObject();
// get pointer to avatar
while (avatar_object && !avatar_object->isAvatar())
{
avatar_object = (LLViewerObject*)avatar_object->getParent();
}
if (avatar_object && ((LLVOAvatar*)avatar_object)->isSelf())
{
const F64 SELF_CLICK_WALK_DISTANCE = 3.0;
// pretend we picked some point a bit in front of avatar
mPick.mPosGlobal = gAgent.getPositionGlobal() + LLVector3d(LLViewerCamera::instance().getAtAxis()) * SELF_CLICK_WALK_DISTANCE;
}
gAgentCamera.setFocusOnAvatar(TRUE, TRUE);
walkToClickedLocation();
LLFirstUse::notMoving(false);
return TRUE;
}
else
{
LL_DEBUGS("maint5901") << "walk target was "
<< (mPick.mPosGlobal.isExactlyZero() ? "zero" : "not zero")
<< ", pick type was " << (mPick.mPickType == LLPickInfo::PICK_LAND ? "land" : "not land")
<< ", pick object was " << mPick.mObjectID
<< LL_ENDL;
// we didn't click to walk, so restore the original target
mPick = savedPick;
}
}
gViewerWindow->setCursor(UI_CURSOR_ARROW);
if (hasMouseCapture())
{
@ -805,7 +844,6 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask)
LLToolMgr::getInstance()->clearTransientTool();
gAgentCamera.setLookAt(LOOKAT_TARGET_CONVERSATION, obj); // maybe look at object/person clicked on
mBlockClickToWalk = false;
return LLTool::handleMouseUp(x, y, mask);
}
@ -831,66 +869,13 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask)
return TRUE;
}
if (!mDoubleClickTimer.getStarted() || (mDoubleClickTimer.getElapsedTimeF32() > 0.3f))
if (!mDoubleClickTimer.getStarted() || (mDoubleClickTimer.getElapsedTimeF32() > 0.3f))
{
mDoubleClickTimer.stop();
return FALSE;
}
mDoubleClickTimer.stop();
if (gSavedSettings.getBOOL("DoubleClickAutoPilot"))
{
// We may be doing double click to walk, but we don't want to use a target on
// a transparent object because the user thought they were clicking on
// whatever they were seeing through it, so recompute what was clicked on
// ignoring transparent objects
LLPickInfo savedPick = mPick;
mPick = gViewerWindow->pickImmediate(savedPick.mMousePt.mX, savedPick.mMousePt.mY,
FALSE /* ignore transparent */,
FALSE /* ignore rigged */,
FALSE /* ignore particles */);
if(mPick.mPickType == LLPickInfo::PICK_OBJECT)
{
if (mPick.getObject() && mPick.getObject()->isHUDAttachment())
{
mPick = savedPick;
return FALSE;
}
}
if ((mPick.mPickType == LLPickInfo::PICK_LAND && !mPick.mPosGlobal.isExactlyZero()) ||
(mPick.mObjectID.notNull() && !mPick.mPosGlobal.isExactlyZero()))
{
walkToClickedLocation();
return TRUE;
}
else
{
// restore the original pick for any other purpose
mPick = savedPick;
}
}
else if (gSavedSettings.getBOOL("DoubleClickTeleport"))
{
LLViewerObject* objp = mPick.getObject();
LLViewerObject* parentp = objp ? objp->getRootEdit() : NULL;
bool is_in_world = mPick.mObjectID.notNull() && objp && !objp->isHUDAttachment();
bool is_land = mPick.mPickType == LLPickInfo::PICK_LAND;
bool pos_non_zero = !mPick.mPosGlobal.isExactlyZero();
bool has_touch_handler = (objp && objp->flagHandleTouch()) || (parentp && parentp->flagHandleTouch());
bool has_click_action = final_click_action(objp);
if (pos_non_zero && (is_land || (is_in_world && !has_touch_handler && !has_click_action)))
{
LLVector3d pos = mPick.mPosGlobal;
pos.mdV[VZ] += gAgentAvatarp->getPelvisToFoot();
gAgent.teleportViaLocationLookAt(pos);
return TRUE;
}
}
return FALSE;
}
@ -1423,7 +1408,6 @@ void LLToolPie::VisitHomePage(const LLPickInfo& info)
void LLToolPie::handleSelect()
{
// tool is reselected when app gets focus, etc.
mBlockClickToWalk = true;
}
void LLToolPie::handleDeselect()
@ -1484,7 +1468,7 @@ void LLToolPie::stopCameraSteering()
bool LLToolPie::inCameraSteerMode()
{
return mMouseButtonDown && mMouseOutsideSlop && gSavedSettings.getBOOL("ClickToWalk");
return mMouseButtonDown && mMouseOutsideSlop;
}
// true if x,y outside small box around start_x,start_y
@ -1935,7 +1919,6 @@ void LLToolPie::startCameraSteering()
{
LLFirstUse::notMoving(false);
mMouseOutsideSlop = true;
mBlockClickToWalk = true;
if (gAgentCamera.getFocusOnAvatar())
{

View File

@ -42,7 +42,7 @@ class LLToolPie : public LLTool, public LLSingleton<LLToolPie>
public:
// Virtual functions inherited from LLMouseHandler
virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EClickType clicktype, BOOL down);
virtual BOOL handleAnyMouseClick(S32 x, S32 y, MASK mask, EMouseClickType clicktype, BOOL down);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
@ -68,8 +68,8 @@ public:
LLViewerObject* getClickActionObject() { return mClickActionObject; }
LLObjectSelection* getLeftClickSelection() { return (LLObjectSelection*)mLeftClickSelection; }
void resetSelection();
void walkToClickedLocation();
void blockClickToWalk() { mBlockClickToWalk = true; }
bool walkToClickedLocation();
bool teleportToClickedLocation();
void stopClickToWalk();
static void selectionPropertiesReceived();
@ -111,7 +111,6 @@ private:
LLPointer<LLHUDEffectBlob> mAutoPilotDestination;
LLPointer<LLHUDEffectBlob> mMouseSteerGrabPoint;
bool mClockwise;
bool mBlockClickToWalk;
LLUUID mMediaMouseCaptureID;
LLPickInfo mPick;
LLPickInfo mHoverPick;

View File

@ -510,7 +510,10 @@ bool handleHighResSnapshotChanged(const LLSD& newvalue)
bool handleVoiceClientPrefsChanged(const LLSD& newvalue)
{
LLVoiceClient::getInstance()->updateSettings();
if (LLVoiceClient::instanceExists())
{
LLVoiceClient::getInstance()->updateSettings();
}
return true;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,179 @@
/**
* @file llviewerinput.h
* @brief LLViewerInput class header file
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLVIEWERINPUT_H
#define LL_LLVIEWERINPUT_H
#include "llkeyboard.h" // For EKeystate
#include "llinitparam.h"
const S32 MAX_KEY_BINDINGS = 128; // was 60
class LLNamedFunction
{
public:
LLNamedFunction() : mFunction(NULL) { };
~LLNamedFunction() { };
std::string mName;
LLKeyFunc mFunction;
};
class LLKeyboardBinding
{
public:
KEY mKey;
MASK mMask;
LLKeyFunc mFunction;
};
class LLMouseBinding
{
public:
EMouseClickType mMouse;
MASK mMask;
LLKeyFunc mFunction;
};
typedef enum e_keyboard_mode
{
MODE_FIRST_PERSON,
MODE_THIRD_PERSON,
MODE_EDIT_AVATAR,
MODE_SITTING,
MODE_COUNT
} EKeyboardMode;
class LLWindow;
void bind_keyboard_functions();
class LLViewerInput
{
public:
struct KeyBinding : public LLInitParam::Block<KeyBinding>
{
Mandatory<std::string> key,
mask,
command;
Optional<std::string> mouse; // Note, not mandatory for the sake of backward campatibility with keys.xml
KeyBinding();
};
struct KeyMode : public LLInitParam::Block<KeyMode>
{
Multiple<KeyBinding> bindings;
KeyMode();
};
struct Keys : public LLInitParam::Block<Keys>
{
Optional<KeyMode> first_person,
third_person,
sitting,
edit_avatar;
Keys();
};
LLViewerInput();
BOOL handleKey(KEY key, MASK mask, BOOL repeated);
BOOL handleKeyUp(KEY key, MASK mask);
S32 loadBindingsXML(const std::string& filename); // returns number bound, 0 on error
EKeyboardMode getMode() const;
static BOOL modeFromString(const std::string& string, S32 *mode); // False on failure
static BOOL mouseFromString(const std::string& string, EMouseClickType *mode);// False on failure
bool scanKey(KEY key,
BOOL key_down,
BOOL key_up,
BOOL key_level) const;
// handleMouse() records state, scanMouse() goes through states, scanMouse(click) processes individual saved states after UI is done with them
BOOL handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down);
void scanMouse();
bool isMouseBindUsed(const EMouseClickType mouse, const MASK mask = MASK_NONE, const S32 mode = MODE_THIRD_PERSON);
private:
bool scanKey(const std::vector<LLKeyboardBinding> &binding,
S32 binding_count,
KEY key,
MASK mask,
BOOL key_down,
BOOL key_up,
BOOL key_level,
bool repeat) const;
enum EMouseState
{
MOUSE_STATE_DOWN, // key down this frame
MOUSE_STATE_CLICK, // key went up and down in scope of same frame
MOUSE_STATE_LEVEL, // clicked again fast, or never released
MOUSE_STATE_UP, // went up this frame
MOUSE_STATE_SILENT // notified about 'up', do not notify again
};
bool scanMouse(EMouseClickType click, EMouseState state) const;
bool scanMouse(const std::vector<LLMouseBinding> &binding,
S32 binding_count,
EMouseClickType mouse,
MASK mask,
EMouseState state) const;
S32 loadBindingMode(const LLViewerInput::KeyMode& keymode, S32 mode);
BOOL bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name);
BOOL bindMouse(const S32 mode, const EMouseClickType mouse, const MASK mask, const std::string& function_name);
void resetBindings();
// Hold all the ugly stuff torn out to make LLKeyboard non-viewer-specific here
// TODO: at some point it is better to remake this, especially keyaboard part
// would be much better to send to functions actual state of the button than
// to send what we think function wants based on collection of bools (mKeyRepeated, mKeyLevel, mKeyDown)
std::vector<LLKeyboardBinding> mKeyBindings[MODE_COUNT];
std::vector<LLMouseBinding> mMouseBindings[MODE_COUNT];
typedef std::map<U32, U32> key_remap_t;
key_remap_t mRemapKeys[MODE_COUNT];
std::set<KEY> mKeysSkippedByUI;
BOOL mKeyHandledByUI[KEY_COUNT]; // key processed successfully by UI
// This is indentical to what llkeyboard does (mKeyRepeated, mKeyLevel, mKeyDown e t c),
// just instead of remembering individually as bools, we record state as enum
EMouseState mMouseLevel[CLICK_COUNT]; // records of key state
};
extern LLViewerInput gViewerInput;
#endif // LL_LLVIEWERINPUT_H

File diff suppressed because it is too large Load Diff

View File

@ -1,118 +0,0 @@
/**
* @file llviewerkeyboard.h
* @brief LLViewerKeyboard class header file
*
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_LLVIEWERKEYBOARD_H
#define LL_LLVIEWERKEYBOARD_H
#include "llkeyboard.h" // For EKeystate
#include "llinitparam.h"
const S32 MAX_NAMED_FUNCTIONS = 100;
const S32 MAX_KEY_BINDINGS = 128; // was 60
class LLNamedFunction
{
public:
LLNamedFunction() : mFunction(NULL) { };
~LLNamedFunction() { };
std::string mName;
LLKeyFunc mFunction;
};
typedef enum e_keyboard_mode
{
MODE_FIRST_PERSON,
MODE_THIRD_PERSON,
MODE_EDIT,
MODE_EDIT_AVATAR,
MODE_SITTING,
MODE_COUNT
} EKeyboardMode;
void bind_keyboard_functions();
class LLViewerKeyboard
{
public:
struct KeyBinding : public LLInitParam::Block<KeyBinding>
{
Mandatory<std::string> key,
mask,
command;
KeyBinding();
};
struct KeyMode : public LLInitParam::Block<KeyMode>
{
Multiple<KeyBinding> bindings;
EKeyboardMode mode;
KeyMode(EKeyboardMode mode);
};
struct Keys : public LLInitParam::Block<Keys>
{
Optional<KeyMode> first_person,
third_person,
edit,
sitting,
edit_avatar;
Keys();
};
LLViewerKeyboard();
BOOL handleKey(KEY key, MASK mask, BOOL repeated);
BOOL handleKeyUp(KEY key, MASK mask);
S32 loadBindings(const std::string& filename); // returns number bound, 0 on error
S32 loadBindingsXML(const std::string& filename); // returns number bound, 0 on error
EKeyboardMode getMode();
BOOL modeFromString(const std::string& string, S32 *mode); // False on failure
void scanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level);
private:
S32 loadBindingMode(const LLViewerKeyboard::KeyMode& keymode);
BOOL bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name);
// Hold all the ugly stuff torn out to make LLKeyboard non-viewer-specific here
S32 mBindingCount[MODE_COUNT];
LLKeyBinding mBindings[MODE_COUNT][MAX_KEY_BINDINGS];
typedef std::map<U32, U32> key_remap_t;
key_remap_t mRemapKeys[MODE_COUNT];
std::set<KEY> mKeysSkippedByUI;
BOOL mKeyHandledByUI[KEY_COUNT]; // key processed successfully by UI
};
extern LLViewerKeyboard gViewerKeyboard;
#endif // LL_LLVIEWERKEYBOARD_H

View File

@ -4662,6 +4662,18 @@ void handle_take_copy()
derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id);
}
void handle_link_objects()
{
if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
{
LLFloaterReg::toggleInstanceOrBringToFront("places");
}
else
{
LLSelectMgr::getInstance()->linkObjects();
}
}
// You can return an object to its owner if it is on your land.
class LLObjectReturn : public view_listener_t
{
@ -8108,7 +8120,6 @@ BOOL LLViewerMenuHolderGL::hideMenus()
if (LLMenuHolderGL::hideMenus())
{
LLToolPie::instance().blockClickToWalk();
handled = TRUE;
}
@ -9058,7 +9069,7 @@ void initialize_menus()
view_listener_t::addMenu(new LLToolsSnapObjectXY(), "Tools.SnapObjectXY");
view_listener_t::addMenu(new LLToolsUseSelectionForGrid(), "Tools.UseSelectionForGrid");
view_listener_t::addMenu(new LLToolsSelectNextPartFace(), "Tools.SelectNextPart");
commit.add("Tools.Link", boost::bind(&LLSelectMgr::linkObjects, LLSelectMgr::getInstance()));
commit.add("Tools.Link", boost::bind(&handle_link_objects));
commit.add("Tools.Unlink", boost::bind(&LLSelectMgr::unlinkObjects, LLSelectMgr::getInstance()));
view_listener_t::addMenu(new LLToolsStopAllAnimations(), "Tools.StopAllAnimations");
view_listener_t::addMenu(new LLToolsReleaseKeys(), "Tools.ReleaseKeys");

View File

@ -45,7 +45,8 @@
#include "llmeshrepository.h"
#include "llnotificationhandler.h"
#include "llpanellogin.h"
#include "llviewerkeyboard.h"
#include "llsetkeybinddialog.h"
#include "llviewerinput.h"
#include "llviewermenu.h"
#include "llviewquery.h"
@ -173,7 +174,7 @@
#include "llviewergesture.h"
#include "llviewertexturelist.h"
#include "llviewerinventory.h"
#include "llviewerkeyboard.h"
#include "llviewerinput.h"
#include "llviewermedia.h"
#include "llviewermediafocus.h"
#include "llviewermenu.h"
@ -920,7 +921,18 @@ LLViewerWindow::Params::Params()
{}
BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down)
void LLViewerWindow::handlePieMenu(S32 x, S32 y, MASK mask)
{
if (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance() && gAgent.isInitialized())
{
// If the current tool didn't process the click, we should show
// the pie menu. This can be done by passing the event to the pie
// menu tool.
LLToolPie::getInstance()->handleRightMouseDown(x, y, mask);
}
}
BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down)
{
const char* buttonname = "";
const char* buttonstatestr = "";
@ -944,28 +956,30 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK
switch (clicktype)
{
case LLMouseHandler::CLICK_LEFT:
case CLICK_LEFT:
mLeftMouseDown = down;
buttonname = "Left";
break;
case LLMouseHandler::CLICK_RIGHT:
case CLICK_RIGHT:
mRightMouseDown = down;
buttonname = "Right";
break;
case LLMouseHandler::CLICK_MIDDLE:
case CLICK_MIDDLE:
mMiddleMouseDown = down;
buttonname = "Middle";
break;
case LLMouseHandler::CLICK_DOUBLELEFT:
case CLICK_DOUBLELEFT:
mLeftMouseDown = down;
buttonname = "Left Double Click";
break;
case LLMouseHandler::CLICK_BUTTON4:
case CLICK_BUTTON4:
buttonname = "Button 4";
break;
case LLMouseHandler::CLICK_BUTTON5:
case CLICK_BUTTON5:
buttonname = "Button 5";
break;
default:
break; // COUNT and NONE
}
LLView::sMouseHandlerMessage.clear();
@ -1016,6 +1030,11 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK
LLViewerEventRecorder::instance().logMouseEvent(std::string(buttonstatestr),std::string(buttonname));
}
else if (down && clicktype == CLICK_RIGHT)
{
handlePieMenu(x, y, mask);
r = TRUE;
}
return r;
}
@ -1062,7 +1081,12 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK
return TRUE;
}
if (down && clicktype == CLICK_RIGHT)
{
handlePieMenu(x, y, mask);
return TRUE;
}
// If we got this far on a down-click, it wasn't handled.
// Up-clicks, though, are always handled as far as the OS is concerned.
BOOL default_rtn = !down;
@ -1081,7 +1105,8 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask
mMouseDownTimer.reset();
}
BOOL down = TRUE;
return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_LEFT,down);
//handleMouse() loops back to LLViewerWindow::handleAnyMouseClick
return gViewerInput.handleMouse(window, pos, mask, CLICK_LEFT, down);
}
BOOL LLViewerWindow::handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK mask)
@ -1089,8 +1114,7 @@ BOOL LLViewerWindow::handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK ma
// try handling as a double-click first, then a single-click if that
// wasn't handled.
BOOL down = TRUE;
if (handleAnyMouseClick(window, pos, mask,
LLMouseHandler::CLICK_DOUBLELEFT, down))
if (gViewerInput.handleMouse(window, pos, mask, CLICK_DOUBLELEFT, down))
{
return TRUE;
}
@ -1104,47 +1128,24 @@ BOOL LLViewerWindow::handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask)
mMouseDownTimer.stop();
}
BOOL down = FALSE;
return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_LEFT,down);
return gViewerInput.handleMouse(window, pos, mask, CLICK_LEFT, down);
}
BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask)
{
S32 x = pos.mX;
S32 y = pos.mY;
x = ll_round((F32)x / mDisplayScale.mV[VX]);
y = ll_round((F32)y / mDisplayScale.mV[VY]);
BOOL down = TRUE;
BOOL handle = handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_RIGHT,down);
if (handle)
return handle;
// *HACK: this should be rolled into the composite tool logic, not
// hardcoded at the top level.
if (CAMERA_MODE_CUSTOMIZE_AVATAR != gAgentCamera.getCameraMode() && LLToolMgr::getInstance()->getCurrentTool() != LLToolPie::getInstance() && gAgent.isInitialized())
{
// If the current tool didn't process the click, we should show
// the pie menu. This can be done by passing the event to the pie
// menu tool.
LLToolPie::getInstance()->handleRightMouseDown(x, y, mask);
// show_context_menu( x, y, mask );
}
return TRUE;
return gViewerInput.handleMouse(window, pos, mask, CLICK_RIGHT, down);
}
BOOL LLViewerWindow::handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask)
{
BOOL down = FALSE;
return handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_RIGHT,down);
return gViewerInput.handleMouse(window, pos, mask, CLICK_RIGHT, down);
}
BOOL LLViewerWindow::handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask)
{
BOOL down = TRUE;
LLVoiceClient::getInstance()->updateMouseState(LLMouseHandler::CLICK_MIDDLE, true);
handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
gViewerInput.handleMouse(window, pos, mask, CLICK_MIDDLE, down);
// Always handled as far as the OS is concerned.
return TRUE;
@ -1299,8 +1300,7 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi
BOOL LLViewerWindow::handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask)
{
BOOL down = FALSE;
LLVoiceClient::getInstance()->updateMouseState(LLMouseHandler::CLICK_MIDDLE, false);
handleAnyMouseClick(window,pos,mask,LLMouseHandler::CLICK_MIDDLE,down);
gViewerInput.handleMouse(window, pos, mask, CLICK_MIDDLE, down);
// Always handled as far as the OS is concerned.
return TRUE;
@ -1311,12 +1311,10 @@ BOOL LLViewerWindow::handleOtherMouse(LLWindow *window, LLCoordGL pos, MASK mask
switch (button)
{
case 4:
LLVoiceClient::getInstance()->updateMouseState(LLMouseHandler::CLICK_BUTTON4, down);
handleAnyMouseClick(window, pos, mask, LLMouseHandler::CLICK_BUTTON4, down);
gViewerInput.handleMouse(window, pos, mask, CLICK_BUTTON4, down);
break;
case 5:
LLVoiceClient::getInstance()->updateMouseState(LLMouseHandler::CLICK_BUTTON5, down);
handleAnyMouseClick(window, pos, mask, LLMouseHandler::CLICK_BUTTON5, down);
gViewerInput.handleMouse(window, pos, mask, CLICK_BUTTON5, down);
break;
default:
break;
@ -1463,9 +1461,6 @@ void LLViewerWindow::handleFocusLost(LLWindow *window)
BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key, MASK mask, BOOL repeated)
{
// Let the voice chat code check for its PTT key. Note that this never affects event processing.
LLVoiceClient::getInstance()->keyDown(key, mask);
if (gAwayTimer.getElapsedTimeF32() > LLAgent::MIN_AFK_TIME)
{
gAgent.clearAFK();
@ -1484,14 +1479,12 @@ BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key, MASK mask, BOOL repeated)
return FALSE;
}
return gViewerKeyboard.handleKey(key, mask, repeated);
// remaps, handles ignored cases and returns back to viewer window.
return gViewerInput.handleKey(key, mask, repeated);
}
BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key, MASK mask)
{
// Let the voice chat code check for its PTT key. Note that this never affects event processing.
LLVoiceClient::getInstance()->keyUp(key, mask);
// Let the inspect tool code check for ALT key to set LLToolSelectRect active instead LLToolCamera
LLToolCompInspect * tool_inspectp = LLToolCompInspect::getInstance();
if (LLToolMgr::getInstance()->getCurrentTool() == tool_inspectp)
@ -1499,13 +1492,13 @@ BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key, MASK mask)
tool_inspectp->keyUp(key, mask);
}
return gViewerKeyboard.handleKeyUp(key, mask);
return gViewerInput.handleKeyUp(key, mask);
}
void LLViewerWindow::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level)
{
LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true);
gViewerKeyboard.scanKey(key, key_down, key_up, key_level);
gViewerInput.scanKey(key, key_down, key_up, key_level);
return; // Be clear this function returns nothing
}
@ -2702,6 +2695,13 @@ void LLViewerWindow::draw()
// Takes a single keyup event, usually when UI is visible
BOOL LLViewerWindow::handleKeyUp(KEY key, MASK mask)
{
if (LLSetKeyBindDialog::recordKey(key, mask, FALSE))
{
LL_DEBUGS() << "KeyUp handled by LLSetKeyBindDialog" << LL_ENDL;
LLViewerEventRecorder::instance().logKeyEvent(key, mask);
return TRUE;
}
LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
if (keyboard_focus
@ -2745,23 +2745,74 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
// hide tooltips on keypress
LLToolTipMgr::instance().blockToolTips();
LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
// Menus get handled on key down instead of key up
// so keybindings have to be recorded before that
if (LLSetKeyBindDialog::recordKey(key, mask, TRUE))
{
LL_DEBUGS() << "Key handled by LLSetKeyBindDialog" << LL_ENDL;
LLViewerEventRecorder::instance().logKeyEvent(key,mask);
return TRUE;
}
LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
if (keyboard_focus
&& !(mask & (MASK_CONTROL | MASK_ALT))
&& !gFocusMgr.getKeystrokesOnly())
{
// We have keyboard focus, and it's not an accelerator
if (keyboard_focus && keyboard_focus->wantsKeyUpKeyDown())
&& !gFocusMgr.getKeystrokesOnly())
{
#ifdef LL_WINDOWS
// On windows Alt Gr key generates additional Ctrl event, as result handling situations
// like 'AltGr + D' will result in 'Alt+Ctrl+D'. If it results in WM_CHAR, don't let it
// pass into menu or it will trigger 'develop' menu assigned to this combination on top
// of character handling.
// Alt Gr can be additionally modified by Shift
const MASK alt_gr = MASK_CONTROL | MASK_ALT;
if ((mask & alt_gr) != 0
&& key >= 0x30
&& key <= 0x5A
&& (GetKeyState(VK_RMENU) & 0x8000) != 0
&& (GetKeyState(VK_RCONTROL) & 0x8000) == 0) // ensure right control is not pressed, only left one
{
return keyboard_focus->handleKey(key, mask, FALSE );
// Alt Gr key is represented as right alt and left control.
// Any alt+ctrl combination is treated as Alt Gr by TranslateMessage() and
// will generate a WM_CHAR message, but here we only treat virtual Alt Graph
// key by checking if this specific combination has unicode char.
//
// I decided to handle only virtual RAlt+LCtrl==AltGr combination to minimize
// impact on menu, but the right way might be to handle all Alt+Ctrl calls.
BYTE keyboard_state[256];
if (GetKeyboardState(keyboard_state))
{
const int char_count = 6;
wchar_t chars[char_count];
HKL layout = GetKeyboardLayout(0);
// ToUnicodeEx changes buffer state on OS below Win10, which is undesirable,
// but since we already did a TranslateMessage() in gatherInput(), this
// should have no negative effect
int res = ToUnicodeEx(key, 0, keyboard_state, chars, char_count, 1 << 2 /*do not modify buffer flag*/, layout);
if (res == 1 && chars[0] >= 0x20)
{
// Let it fall through to character handler and get a WM_CHAR.
return TRUE;
}
}
}
else if (key < 0x80)
{
// Not a special key, so likely (we hope) to generate a character. Let it fall through to character handler first.
return (keyboard_focus != NULL);
}
}
#endif
if (!(mask & (MASK_CONTROL | MASK_ALT)))
{
// We have keyboard focus, and it's not an accelerator
if (keyboard_focus && keyboard_focus->wantsKeyUpKeyDown())
{
return keyboard_focus->handleKey(key, mask, FALSE);
}
else if (key < 0x80)
{
// Not a special key, so likely (we hope) to generate a character. Let it fall through to character handler first.
return TRUE;
}
}
}
// let menus handle navigation keys for navigation
if ((gMenuBarView && gMenuBarView->handleKey(key, mask, TRUE))
@ -2960,7 +3011,8 @@ BOOL LLViewerWindow::handleUnicodeChar(llwchar uni_char, MASK mask)
{
if (mask != MASK_ALT)
{
return gViewerKeyboard.handleKey(KEY_RETURN, mask, gKeyboard->getKeyRepeated(KEY_RETURN));
// remaps, handles ignored cases and returns back to viewer window.
return gViewerInput.handleKey(KEY_RETURN, mask, gKeyboard->getKeyRepeated(KEY_RETURN));
}
}

View File

@ -175,8 +175,9 @@ public:
void initWorldUI();
void setUIVisibility(bool);
bool getUIVisibility();
void handlePieMenu(S32 x, S32 y, MASK mask);
BOOL handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, LLMouseHandler::EClickType clicktype, BOOL down);
BOOL handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK mask, EMouseClickType clicktype, BOOL down);
//
// LLWindowCallback interface implementation

View File

@ -200,8 +200,6 @@ const LLVoiceVersionInfo LLVoiceClient::getVersion()
void LLVoiceClient::updateSettings()
{
setUsePTT(gSavedSettings.getBOOL("PTTCurrentlyEnabled"));
std::string keyString = gSavedSettings.getString("PushToTalkButton");
setPTTKey(keyString);
setPTTIsToggle(gSavedSettings.getBOOL("PushToTalkToggle"));
mDisableMic = gSavedSettings.getBOOL("VoiceDisableMic");
@ -637,32 +635,6 @@ bool LLVoiceClient::getPTTIsToggle()
return mPTTIsToggle;
}
void LLVoiceClient::setPTTKey(std::string &key)
{
// Value is stored as text for readability
if(key == "MiddleMouse")
{
mPTTMouseButton = LLMouseHandler::CLICK_MIDDLE;
}
else if(key == "MouseButton4")
{
mPTTMouseButton = LLMouseHandler::CLICK_BUTTON4;
}
else if (key == "MouseButton5")
{
mPTTMouseButton = LLMouseHandler::CLICK_BUTTON5;
}
else
{
mPTTMouseButton = 0;
if(!LLKeyboard::keyFromString(key, &mPTTKey))
{
// If the call failed, don't match any key.
key = KEY_NONE;
}
}
}
void LLVoiceClient::inputUserControlState(bool down)
{
if(mPTTIsToggle)
@ -683,43 +655,6 @@ void LLVoiceClient::toggleUserPTTState(void)
setUserPTTState(!getUserPTTState());
}
void LLVoiceClient::keyDown(KEY key, MASK mask)
{
if (gKeyboard->getKeyRepeated(key))
{
// ignore auto-repeat keys
return;
}
if (mPTTMouseButton == 0 && LLAgent::isActionAllowed("speak") && (key == mPTTKey))
{
bool down = gKeyboard->getKeyDown(mPTTKey);
if (down)
{
inputUserControlState(down);
}
}
}
void LLVoiceClient::keyUp(KEY key, MASK mask)
{
if (mPTTMouseButton == 0 && (key == mPTTKey))
{
bool down = gKeyboard->getKeyDown(mPTTKey);
if (!down)
{
inputUserControlState(down);
}
}
}
void LLVoiceClient::updateMouseState(S32 click, bool down)
{
if(mPTTMouseButton == click && LLAgent::isActionAllowed("speak"))
{
inputUserControlState(down);
}
}
//-------------------------------------------
// nearby speaker accessors

View File

@ -408,16 +408,10 @@ public:
void setUsePTT(bool usePTT);
void setPTTIsToggle(bool PTTIsToggle);
bool getPTTIsToggle();
void setPTTKey(std::string &key);
void updateMicMuteLogic();
BOOL lipSyncEnabled();
// PTT key triggering
void keyDown(KEY key, MASK mask);
void keyUp(KEY key, MASK mask);
void updateMouseState(S32 click, bool down);
boost::signals2::connection MicroChangedCallback(const micro_changed_signal_t::slot_type& cb ) { return mMicroChangedSignal.connect(cb); }

View File

@ -37,7 +37,7 @@
#include "llview.h"
#include "llviewinject.h"
#include "llviewerwindow.h"
#include "llviewerkeyboard.h"
#include "llviewerinput.h"
#include "llrootview.h"
#include "llsdutil.h"
#include "stringize.h"
@ -279,7 +279,7 @@ void LLWindowListener::keyDown(LLSD const & evt)
response.setResponse(target_view->getInfo());
gFocusMgr.setKeyboardFocus(target_view);
gViewerKeyboard.handleKey(key, mask, false);
gViewerInput.handleKey(key, mask, false);
if(key < 0x80) mWindow->handleUnicodeChar(key, mask);
}
else
@ -291,7 +291,7 @@ void LLWindowListener::keyDown(LLSD const & evt)
}
else
{
gViewerKeyboard.handleKey(key, mask, false);
gViewerInput.handleKey(key, mask, false);
if(key < 0x80) mWindow->handleUnicodeChar(key, mask);
}
}

View File

@ -0,0 +1,240 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<contents>
<rows
enabled="false"
name="camera_actions"
value="">
<columns
type="icontext"
column="lst_action"
font="SansSerif"
halign="left"
label="Camera"
name="lst_action"
value="Cam_FreeCam_Off" />
</rows>
<rows
name="look_up"
value="look_up">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Look Up" />
</rows>
<rows
name="look_down"
value="look_down">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Look Down" />
</rows>
<rows
name="move_forward"
value="move_forward">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Forward" />
</rows>
<rows
name="move_backward"
value="move_backward">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Backward" />
</rows>
<rows
name="move_forward_fast"
value="move_forward_fast">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Forward Fast" />
</rows>
<rows
name="move_backward_fast"
value="move_backward_fast">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Backward Fast" />
</rows>
<rows
name="spin_over"
value="spin_over">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Spin Over" />
</rows>
<rows
name="spin_under"
value="spin_under">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Spin Under" />
</rows>
<rows
name="pan_up"
value="pan_up">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Pan Up" />
</rows>
<rows
name="pan_down"
value="pan_down">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Pan Down" />
</rows>
<rows
name="pan_left"
value="pan_left">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Pan Left" />
</rows>
<rows
name="pan_right"
value="pan_right">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Pan Right" />
</rows>
<rows
name="pan_in"
value="pan_in">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Pan In" />
</rows>
<rows
name="pan_out"
value="pan_out">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Pan Out" />
</rows>
<rows
name="spin_around_ccw"
value="spin_around_ccw">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
tool_tip="Camera spin around counterclockwise"
value="Counterclockwise" />
</rows>
<rows
name="spin_around_cw"
value="spin_around_cw">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
tool_tip="Camera spin around clockwise"
value="Clockwise" />
</rows>
<rows
name="move_forward_sitting"
value="move_forward_sitting">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Forward Sitting" />
</rows>
<rows
name="move_backward_sitting"
value="move_backward_sitting">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Backward Sitting" />
</rows>
<rows
name="spin_over_sitting"
value="spin_over_sitting">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Spin Over Sitting" />
</rows>
<rows
name="spin_under_sitting"
value="spin_under_sitting">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Spin Under Sitting" />
</rows>
<rows
name="spin_around_ccw_sitting"
value="spin_around_ccw_sitting">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
tool_tip="Camera spin around counterclockwise sitting"
value="Counterclockwise Sitting" />
</rows>
<rows
name="spin_around_cw_sitting"
value="spin_around_cw_sitting">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
tool_tip="Camera spin around clockwise sitting"
value="Clockwise Sitting" />
</rows>
</contents>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<contents>
<columns
relative_width="0.34"
label="Action"
name="lst_action" />
<columns
relative_width="0.22"
label="Primary Control"
name="lst_ctrl1" />
<columns
relative_width="0.22"
label="Alternate 1"
name="lst_ctrl2" />
<columns
relative_width="0.22"
label="Alternate 2"
name="lst_ctrl3" />
</contents>

View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<contents>
<rows
enabled="false"
name="editing_actions"
value="">
<columns
type="icontext"
column="lst_action"
font="SansSerif"
halign="left"
label="Editing"
name="lst_action"
value="Tool_Dozer" />
</rows>
<rows
name="edit_avatar_spin_ccw"
value="edit_avatar_spin_ccw">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
tool_tip="Camera spin around avatar counterclockwise"
value="Counterclockwise" />
</rows>
<rows
name="edit_avatar_spin_cw"
value="edit_avatar_spin_cw">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
tool_tip="Camera spin around avatar clockwise"
value="Clockwise" />
</rows>
<rows
name="edit_avatar_spin_over"
value="edit_avatar_spin_over">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
tool_tip="Camera spin over avatar"
value="Camera Spin Over" />
</rows>
<rows
name="edit_avatar_spin_under"
value="edit_avatar_spin_under">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
tool_tip="Camera spin under avatar"
value="Camera Spin Under" />
</rows>
<rows
name="edit_avatar_move_forward"
value="edit_avatar_move_forward">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Forward" />
</rows>
<rows
name="edit_avatar_move_backward"
value="edit_avatar_move_backward">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Camera Backward" />
</rows>
</contents>

View File

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<contents>
<rows
enabled="false"
name="media_actions"
value="">
<columns
type="icontext"
column="lst_action"
font="SansSerif"
halign="left"
label="Sound and Media"
name="lst_action"
value="Audio_Press" />
</rows>
<rows
name="toggle_pause_media"
value="toggle_pause_media">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Play/Pause Media" />
</rows>
<rows
name="toggle_enable_media"
value="toggle_enable_media">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Play/Stop All Media" />
</rows>
<rows
name="voice_follow_key"
value="voice_follow_key">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Voice" />
</rows>
<rows
name="toggle_voice"
value="toggle_voice">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Toggle Voice" />
</rows>
<rows
name="start_chat"
value="start_chat">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Start Chat" />
</rows>
<rows
name="start_gesture"
value="start_gesture">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Start Gesture" />
</rows>
</contents>

View File

@ -0,0 +1,198 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<contents>
<rows
enabled="false"
name="move_actions"
value="">
<columns
type="icontext"
column="lst_action"
font="SansSerif"
halign="left"
label="Move Actions"
name="lst_action"
value="Move_Walk_Off" />
</rows>
<rows
name="walk_to"
value="walk_to">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
tool_tip="Walk to location mouse cursor points to"
value="Walk to" />
</rows>
<rows
name="teleport_to"
value="teleport_to">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
tool_tip="Teleport to location mouse cursor points to, but not all locations allow direct teleportation so you might be teleported closer to destination instead"
value="Teleport to" />
</rows>
<rows
name="push_forward"
value="push_forward">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Move Forward" />
</rows>
<rows
name="push_backward"
value="push_backward">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Move Backward" />
</rows>
<rows
name="turn_left"
value="turn_left">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Left" />
</rows>
<rows
name="turn_right"
value="turn_right">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Right" />
</rows>
<rows
name="slide_left"
value="slide_left">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Strafe left" />
</rows>
<rows
name="slide_right"
value="slide_right">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Strafe right" />
</rows>
<rows
name="jump"
value="jump">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Jump/Up" />
</rows>
<rows
name="push_down"
value="push_down">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Down" />
</rows>
<rows
name="run_forward"
value="run_forward">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Run Forward" />
</rows>
<rows
name="run_backward"
value="run_backward">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Run Backward" />
</rows>
<rows
name="run_left"
value="run_left">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Run Left" />
</rows>
<rows
name="run_right"
value="run_right">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Run Right" />
</rows>
<rows
name="toggle_run"
value="toggle_run">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Toggle Run" />
</rows>
<rows
name="toggle_fly"
value="toggle_fly">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Fly/Stop flying" />
</rows>
<rows
name="toggle_sit"
value="toggle_sit">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Sit/Stand" />
</rows>
<rows
name="stop_moving"
value="stop_moving">
<columns
column="lst_action"
font="SansSerif"
halign="left"
name="lst_action"
value="Stop Moving" />
</rows>
</contents>

View File

@ -169,6 +169,13 @@ https://accounts.secondlife.com/change_email/
layout="topleft"
help_topic="preferences_uploads_tab"
name="uploads" />
<panel
class="panel_preference_controls"
filename="panel_preferences_controls.xml"
label="Controls"
layout="topleft"
help_topic="preferences_controls_tab"
name="controls" />
</tab_container>
</floater>

View File

@ -4,10 +4,27 @@
border="false"
can_close="false"
can_minimize="false"
height="90"
height="116"
layout="topleft"
name="modal container"
width="240">
width="272">
<floater.string
name="keyboard">
Keyboard
</floater.string>
<floater.string
name="mouse">
Mouse Buttons
</floater.string>
<floater.string
name="basic_description">
Press a key to set your trigger.
Allowed input: [INPUT].
</floater.string>
<floater.string
name="reserved_by_menu">
Combination [KEYSTR] is reserved by menu.
</floater.string>
<text
type="string"
halign="center"
@ -16,19 +33,47 @@
height="30"
layout="topleft"
left="30"
name="Save item as:"
name="descritption"
top="25"
word_wrap="true"
width="180">
Press a key to set your Speak button trigger.
width="212">
Press a key to set your trigger.
Allowed input: [INPUT].
</text>
<check_box
follows="top|left"
height="20"
initial_value="false"
label="Apply to all"
layout="topleft"
left="90"
name="apply_all"
tool_tip="Viewer uses different control combinations depending on what you are doing in world, setting this will apply your change to all combinations"
top_pad="8"
width="160" />
<button
height="23"
label="Set Empty"
layout="topleft"
left="8"
name="SetEmpty"
top_pad="6"
width="80" />
<button
height="23"
label="Default"
layout="topleft"
left_pad="8"
name="Default"
top_delta="0"
width="80" />
<button
height="23"
label="Cancel"
label_selected="Cancel"
layout="topleft"
right="-10"
left_pad="8"
name="Cancel"
top_pad="8"
width="100" />
top_delta="0"
width="80" />
</floater>

View File

@ -56,10 +56,10 @@
</menu_item_call>
<menu_item_call
label="Places..."
name="Places">
name="Places"
shortcut="control|L">
<menu_item_call.on_click
function="Floater.ToggleOrBringToFront"
parameter="places" />
function="Tools.Link"/>
</menu_item_call>
<menu_item_call
label="Picks..."
@ -85,11 +85,24 @@
<menu_item_separator/>
<menu_item_call
label="Camera Controls..."
name="Camera Controls">
name="Camera Controls"
shortcut="control|K">
<menu_item_call.on_click
function="Floater.ToggleOrBringToFront"
parameter="camera" />
</menu_item_call>
<menu_item_call
label="Hover Height"
name="HoverHeight"
shortcut="alt|control|H"
use_mac_ctrl="true"
visible="false">
<menu_item_call.on_click
function="Floater.ToggleOrBringToFront"
parameter="edit_hover_height"/>
<menu_item_call.on_enable
function="Edit.EnableHoverHeight"/>
</menu_item_call>
<menu
create_jump_keys="true"
label="Movement"
@ -150,7 +163,9 @@
</menu_item_check>
<menu_item_call
label="Stop Animating Me"
name="Stop Animating My Avatar">
name="Stop Animating My Avatar"
allow_key_repeat="true"
shortcut="alt|shift|A">
<menu_item_call.on_click
function="Tools.StopAllAnimations" />
</menu_item_call>
@ -458,7 +473,8 @@
</menu_item_check>
<menu_item_call
label="Events"
name="Events">
name="Events"
shortcut="control|E">
<menu_item_call.on_click
function="Advanced.ShowURL"
parameter="https://secondlife.com/my/community/events"/>
@ -606,8 +622,7 @@
<menu_item_separator />
<menu_item_check
label="Advanced Menu"
name="Show Advanced Menu"
shortcut="control|alt|shift|D">
name="Show Advanced Menu">
<on_check
function="CheckControl"
parameter="UseDebugMenus" />
@ -647,7 +662,8 @@
tear_off="true">
<menu_item_check
label="Sunrise"
name="Sunrise">
name="Sunrise"
shortcut="control|shift|O">
<menu_item_check.on_click
function="World.EnvSettings"
parameter="sunrise" />
@ -679,7 +695,8 @@
</menu_item_check>
<menu_item_check
label="Midnight"
name="Midnight">
name="Midnight"
shortcut="control|shift|Z">
<menu_item_check.on_click
function="World.EnvSettings"
parameter="midnight" />
@ -1317,7 +1334,8 @@ function="World.EnvPreset"
<menu_item_call
label="Model..."
layout="topleft"
name="Upload Model">
name="Upload Model"
shortcut="alt|control|U">
<menu_item_call.on_click
function="File.UploadModel"
parameter="" />
@ -1982,20 +2000,6 @@ function="World.EnvPreset"
name="Shortcuts"
tear_off="true"
visible="false">
<!-- This second, alternative shortcut for Show Advanced Menu is for backward compatibility. The main shortcut has been changed so it's Linux-friendly, where the old shortcut is typically eaten by the window manager. -->
<menu_item_check
label="Show Advanced Menu - legacy shortcut"
name="Show Advanced Menu - legacy shortcut"
shortcut="control|alt|D">
<on_check
function="CheckControl"
parameter="UseDebugMenus" />
<on_click
function="ToggleControl"
parameter="UseDebugMenus" />
</menu_item_check>
<menu_item_separator/>
<menu_item_call
label="Close Window"
@ -3633,7 +3637,7 @@ function="World.EnvPreset"
<menu_item_call
label="Debug Avatar Textures"
name="Debug Avatar Textures"
shortcut="control|alt|shift|A">
shortcut="control|alt|shift|K">
<menu_item_call.on_click
function="Advanced.DebugAvatarTextures" />
</menu_item_call>

View File

@ -11450,6 +11450,19 @@ Cannot create large prims that intersect other residents. Please re-try when ot
notext="Cancel"
yestext="OK"/>
</notification>
<notification
icon="alertmodal.tga"
name="PreferenceControlsDefaults"
type="alertmodal">
Do you want to restore default values for controls?
<tag>confirm</tag>
<usetemplate
canceltext="Cancel"
name="yesnocancelbuttons"
notext="Current mode"
yestext="All modes"/>
</notification>
<notification
icon="alertmodal.tga"

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<panel
border="true"
follows="all"
height="408"
label="Controls"
layout="topleft"
left="102"
name="controls"
top="1"
width="517">
<combo_box
follows="top|left"
layout="topleft"
top="6"
left="10"
height="23"
width="232"
name="key_mode">
<combo_box.item
label="When in third person"
name="third_person"
value="1"/>
<combo_box.item
label="When in first person mode (Mouselook)"
name="first_person"
value="0"/>
<combo_box.item
label="When editing avatar"
name="edit_avatar"
value="2"/>
<combo_box.item
label="When sitting"
name="sitting"
value="3"/>
</combo_box>
<button
follows="top|left"
layout="topleft"
top="6"
right="-10"
height="23"
width="140"
label="Restore Defaults"
tool_tip="Restores default values for all control modes."
name="restore_defaults"/>
<scroll_list
draw_heading="true"
follows="all"
layout="topleft"
column_padding="0"
selection_type="header"
top="31"
left="3"
bottom="-3"
right="-3"
can_sort="false"
multi_select="false"
name="controls_list"
fg_disable_color="ScrollUnselectedColor"/>
</panel>

View File

@ -463,52 +463,13 @@
enabled_control="EnableVoiceChat"
control_name="PushToTalkToggle"
height="15"
label="Toggle speak on/off when I press:"
label="Toggle speak on/off when I press button in toolbar"
layout="topleft"
left="44"
name="push_to_talk_toggle_check"
width="237"
tool_tip="When in toggle mode, press and release the trigger key ONCE to switch your microphone on or off. When not in toggle mode, the microphone broadcasts your voice only while the trigger is being held down."
top_pad="3"/>
<line_editor
follows="top|left"
control_name="PushToTalkButton"
enabled="false"
enabled_control="EnableVoiceChat"
height="23"
left="80"
max_length_bytes="200"
name="modifier_combo"
label="Push-to-Speak trigger"
top_pad="3"
width="200" />
<button
layout="topleft"
follows="top|left"
enabled_control="EnableVoiceChat"
height="23"
label="Set Key"
left_pad="5"
name="set_voice_hotkey_button"
width="100">
<button.commit_callback
function="Pref.VoiceSetKey" />
</button>
<button
enabled_control="EnableVoiceChat"
follows="top|left"
halign="center"
height="23"
image_overlay="Refresh_Off"
layout="topleft"
tool_tip="Reset to Middle Mouse Button"
mouse_opaque="true"
name="set_voice_middlemouse_button"
left_pad="5"
width="25">
<button.commit_callback
function="Pref.VoiceSetMiddleMouse" />
</button>
<button
control_name="ShowDeviceSettings"
follows="left|top"

View File

@ -4090,6 +4090,15 @@ Try enclosing path to the editor with double quotes.
<string name="Z">Z</string>
<!-- Key names end -->
<!-- Mouse button names (short) begin -->
<string name="LMB">LMB</string>
<string name="MMB">MMB</string>
<string name="RMB">RMB</string>
<string name="MB4">MB4</string>
<string name="MB5">MB5</string>
<string name="Double LMB">Double LMB</string>
<!-- Mouse button names end -->
<!-- llviewerwindow -->
<string name="BeaconParticle">Viewing particle beacons (blue)</string>
<string name="BeaconPhysical">Viewing physical object beacons (green)</string>