merge out changes up to but not including the STORM-610 change
commit
6bdfc3d048
6
.hgtags
6
.hgtags
|
|
@ -52,6 +52,7 @@ a82e5b1e22c7f90e3c7977d146b80588f004ed0d 2.5.0-start
|
|||
345b17e7cf630db77e840b4fe3451bd476d750a3 76f586a8e22b
|
||||
0000000000000000000000000000000000000000 76f586a8e22b
|
||||
54d772d8687c69b1d773f6ce14bbc7bdc9d6c05f 2.5.0-beta2
|
||||
b542f8134a2bb5dd054ff4e509a44b2ee463b1bf nat-eventapi2-base
|
||||
7076e22f9f43f479a4ea75eac447a36364bead5a DRTVWR-5_2.2.0-beta1
|
||||
9822eb3e25f7fe0c28ffd8aba45c507caa383cbc DRTVWR-3_2.2.0-beta2
|
||||
b0cd7e150009809a0b5b0a9d5785cd4bb230413a DRTVWR-7_2.2.0-beta3
|
||||
|
|
@ -70,6 +71,7 @@ b723921b5c711bd24dbe77dc76ef488b544dac78 DRTVWR-34_2.5.0-beta3
|
|||
b723921b5c711bd24dbe77dc76ef488b544dac78 2.5.0-release
|
||||
b723921b5c711bd24dbe77dc76ef488b544dac78 DRTVWR-31_2.5.0-release
|
||||
92e58e51776a4f8c29069b1a62ff21454d2085f0 2.6.0-start
|
||||
3178e311da3a8739a85363665006ea3c4610cad4 dons-headless-hackathon-work
|
||||
63a6aedfce785a6c760377bf685b2dae616797d2 2.5.1-start
|
||||
4dede9ae1ec74d41f6887719f6f1de7340d8578d 2.5.1-release
|
||||
4dede9ae1ec74d41f6887719f6f1de7340d8578d DRTVWR-37_2.5.1-release
|
||||
|
|
@ -88,6 +90,8 @@ c5bdef3aaa2744626aef3c217ce29e1900d357b3 DRTVWR-43_2.6.1-beta1
|
|||
c5bdef3aaa2744626aef3c217ce29e1900d357b3 2.6.1-beta1
|
||||
9e4641f4a7870c0f565a25a2971368d5a29516a1 DRTVWR-41_2.6.0-beta2
|
||||
9e4641f4a7870c0f565a25a2971368d5a29516a1 2.6.0-beta2
|
||||
c9182ed77d427c759cfacf49a7b71a2e20d522aa DRTVWR-42_2.6.1-release
|
||||
c9182ed77d427c759cfacf49a7b71a2e20d522aa 2.6.1-release
|
||||
56b2778c743c2a964d82e1caf11084d76a87de2c 2.6.2-start
|
||||
42f32494bac475d0737799346f6831558ae8bf5d DRTVWR-39_2.6.0-release
|
||||
42f32494bac475d0737799346f6831558ae8bf5d 2.6.0-release
|
||||
|
|
@ -95,3 +99,5 @@ d1203046bb653b763f835b04d184646949d8dd5c DRTVWR-45_2.6.2-beta1
|
|||
d1203046bb653b763f835b04d184646949d8dd5c 2.6.2-beta1
|
||||
52b2263ab28f0976c689fd0b76c55a9eb027cdbf end-of-develop.py
|
||||
ec32f1045e7c2644015245df3a9933620aa194b8 2.6.3-start
|
||||
d7fcefabdf32bb61a9ea6d6037c1bb26190a85bc DRTVWR-47_2.6.3-beta1
|
||||
d7fcefabdf32bb61a9ea6d6037c1bb26190a85bc 2.6.3-beta1
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ viewer-pre-release.viewer_channel = "Second Life Release"
|
|||
viewer-pre-release.login_channel = "Second Life Release"
|
||||
viewer-pre-release.build_debug_release_separately = true
|
||||
viewer-pre-release.build_viewer_update_version_manager = true
|
||||
viewer-pre-release.release-viewer.jira = DRTVWR-42
|
||||
#viewer-pre-release.release-viewer.jira = DRTVWR-13
|
||||
|
||||
# =======================================
|
||||
# brad
|
||||
# ========================================
|
||||
|
|
@ -154,7 +155,7 @@ media.build_viewer_update_version_manager = false
|
|||
# oz
|
||||
# ================
|
||||
|
||||
oz-viewer-devreview.build_debug_release_separately = true
|
||||
oz_viewer-devreview.build_debug_release_separately = true
|
||||
|
||||
viewer-devreview.build_debug_release_separately = true
|
||||
|
||||
|
|
|
|||
|
|
@ -417,6 +417,8 @@ Jonathan Yap
|
|||
STORM-1020
|
||||
STORM-1064
|
||||
STORM-960
|
||||
STORM-1108
|
||||
STORM-1094
|
||||
STORM-1077
|
||||
STORM-953
|
||||
Kage Pixel
|
||||
|
|
@ -440,6 +442,8 @@ Kitty Barnett
|
|||
Kunnis Basiat
|
||||
VWR-82
|
||||
VWR-102
|
||||
Lance Corrimal
|
||||
VWR-25269
|
||||
Latif Khalifa
|
||||
VWR-5370
|
||||
Lisa Lowe
|
||||
|
|
@ -789,6 +793,7 @@ Thickbrick Sleaford
|
|||
VWR-13483
|
||||
VWR-13947
|
||||
VWR-24420
|
||||
STORM-1147
|
||||
Thraxis Epsilon
|
||||
SVC-371
|
||||
VWR-383
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ set(llcommon_SOURCE_FILES
|
|||
llformat.cpp
|
||||
llframetimer.cpp
|
||||
llheartbeat.cpp
|
||||
llinstancetracker.cpp
|
||||
llliveappconfig.cpp
|
||||
lllivefile.cpp
|
||||
lllog.cpp
|
||||
|
|
@ -314,6 +315,7 @@ if (LL_TESTS)
|
|||
LL_ADD_INTEGRATION_TEST(lluri "" "${test_libs}")
|
||||
LL_ADD_INTEGRATION_TEST(reflection "" "${test_libs}")
|
||||
LL_ADD_INTEGRATION_TEST(stringize "" "${test_libs}")
|
||||
LL_ADD_INTEGRATION_TEST(lleventdispatcher "" "${test_libs}")
|
||||
|
||||
# *TODO - reenable these once tcmalloc libs no longer break the build.
|
||||
#ADD_BUILD_TEST(llallocator llcommon)
|
||||
|
|
|
|||
|
|
@ -41,6 +41,354 @@
|
|||
#include "llevents.h"
|
||||
#include "llerror.h"
|
||||
#include "llsdutil.h"
|
||||
#include "stringize.h"
|
||||
#include <memory> // std::auto_ptr
|
||||
|
||||
/*****************************************************************************
|
||||
* LLSDArgsSource
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* Store an LLSD array, producing its elements one at a time. Die with LL_ERRS
|
||||
* if the consumer requests more elements than the array contains.
|
||||
*/
|
||||
class LL_COMMON_API LLSDArgsSource
|
||||
{
|
||||
public:
|
||||
LLSDArgsSource(const std::string function, const LLSD& args);
|
||||
~LLSDArgsSource();
|
||||
|
||||
LLSD next();
|
||||
|
||||
void done() const;
|
||||
|
||||
private:
|
||||
std::string _function;
|
||||
LLSD _args;
|
||||
LLSD::Integer _index;
|
||||
};
|
||||
|
||||
LLSDArgsSource::LLSDArgsSource(const std::string function, const LLSD& args):
|
||||
_function(function),
|
||||
_args(args),
|
||||
_index(0)
|
||||
{
|
||||
if (! (_args.isUndefined() || _args.isArray()))
|
||||
{
|
||||
LL_ERRS("LLSDArgsSource") << _function << " needs an args array instead of "
|
||||
<< _args << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
LLSDArgsSource::~LLSDArgsSource()
|
||||
{
|
||||
done();
|
||||
}
|
||||
|
||||
LLSD LLSDArgsSource::next()
|
||||
{
|
||||
if (_index >= _args.size())
|
||||
{
|
||||
LL_ERRS("LLSDArgsSource") << _function << " requires more arguments than the "
|
||||
<< _args.size() << " provided: " << _args << LL_ENDL;
|
||||
}
|
||||
return _args[_index++];
|
||||
}
|
||||
|
||||
void LLSDArgsSource::done() const
|
||||
{
|
||||
if (_index < _args.size())
|
||||
{
|
||||
LL_WARNS("LLSDArgsSource") << _function << " only consumed " << _index
|
||||
<< " of the " << _args.size() << " arguments provided: "
|
||||
<< _args << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* LLSDArgsMapper
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* From a formal parameters description and a map of arguments, construct an
|
||||
* arguments array.
|
||||
*
|
||||
* That is, given:
|
||||
* - an LLSD array of length n containing parameter-name strings,
|
||||
* corresponding to the arguments of a function of interest
|
||||
* - an LLSD collection specifying default parameter values, either:
|
||||
* - an LLSD array of length m <= n, matching the rightmost m params, or
|
||||
* - an LLSD map explicitly stating default name=value pairs
|
||||
* - an LLSD map of parameter names and actual values for a particular
|
||||
* function call
|
||||
* construct an LLSD array of actual argument values for this function call.
|
||||
*
|
||||
* The parameter-names array and the defaults collection describe the function
|
||||
* being called. The map might vary with every call, providing argument values
|
||||
* for the described parameters.
|
||||
*
|
||||
* The array of parameter names must match the number of parameters expected
|
||||
* by the function of interest.
|
||||
*
|
||||
* If you pass a map of default parameter values, it provides default values
|
||||
* as you might expect. It is an error to specify a default value for a name
|
||||
* not listed in the parameters array.
|
||||
*
|
||||
* If you pass an array of default parameter values, it is mapped to the
|
||||
* rightmost m of the n parameter names. It is an error if the default-values
|
||||
* array is longer than the parameter-names array. Consider the following
|
||||
* parameter names: ["a", "b", "c", "d"].
|
||||
*
|
||||
* - An empty array of default values (or an isUndefined() value) asserts that
|
||||
* every one of the above parameter names is required.
|
||||
* - An array of four default values [1, 2, 3, 4] asserts that every one of
|
||||
* the above parameters is optional. If the current parameter map is empty,
|
||||
* they will be passed to the function as [1, 2, 3, 4].
|
||||
* - An array of two default values [11, 12] asserts that parameters "a" and
|
||||
* "b" are required, while "c" and "d" are optional, having default values
|
||||
* "c"=11 and "d"=12.
|
||||
*
|
||||
* The arguments array is constructed as follows:
|
||||
*
|
||||
* - Arguments-map keys not found in the parameter-names array are ignored.
|
||||
* - Entries from the map provide values for an improper subset of the
|
||||
* parameters named in the parameter-names array. This results in a
|
||||
* tentative values array with "holes." (size of map) + (number of holes) =
|
||||
* (size of names array)
|
||||
* - Holes are filled with the default values.
|
||||
* - Any remaining holes constitute an error.
|
||||
*/
|
||||
class LL_COMMON_API LLSDArgsMapper
|
||||
{
|
||||
public:
|
||||
/// Accept description of function: function name, param names, param
|
||||
/// default values
|
||||
LLSDArgsMapper(const std::string& function, const LLSD& names, const LLSD& defaults);
|
||||
|
||||
/// Given arguments map, return LLSD::Array of parameter values, or LL_ERRS.
|
||||
LLSD map(const LLSD& argsmap) const;
|
||||
|
||||
private:
|
||||
static std::string formatlist(const LLSD&);
|
||||
|
||||
// The function-name string is purely descriptive. We want error messages
|
||||
// to be able to indicate which function's LLSDArgsMapper has the problem.
|
||||
std::string _function;
|
||||
// Store the names array pretty much as given.
|
||||
LLSD _names;
|
||||
// Though we're handed an array of name strings, it's more useful to us to
|
||||
// store it as a map from name string to position index. Of course that's
|
||||
// easy to generate from the incoming names array, but why do it more than
|
||||
// once?
|
||||
typedef std::map<LLSD::String, LLSD::Integer> IndexMap;
|
||||
IndexMap _indexes;
|
||||
// Generated array of default values, aligned with the array of param names.
|
||||
LLSD _defaults;
|
||||
// Indicate whether we have a default value for each param.
|
||||
typedef std::vector<char> FilledVector;
|
||||
FilledVector _has_dft;
|
||||
};
|
||||
|
||||
LLSDArgsMapper::LLSDArgsMapper(const std::string& function,
|
||||
const LLSD& names, const LLSD& defaults):
|
||||
_function(function),
|
||||
_names(names),
|
||||
_has_dft(names.size())
|
||||
{
|
||||
if (! (_names.isUndefined() || _names.isArray()))
|
||||
{
|
||||
LL_ERRS("LLSDArgsMapper") << function << " names must be an array, not " << names << LL_ENDL;
|
||||
}
|
||||
LLSD::Integer nparams(_names.size());
|
||||
// From _names generate _indexes.
|
||||
for (LLSD::Integer ni = 0, nend = _names.size(); ni < nend; ++ni)
|
||||
{
|
||||
_indexes[_names[ni]] = ni;
|
||||
}
|
||||
|
||||
// Presize _defaults() array so we don't have to resize it more than once.
|
||||
// All entries are initialized to LLSD(); but since _has_dft is still all
|
||||
// 0, they're all "holes" for now.
|
||||
if (nparams)
|
||||
{
|
||||
_defaults[nparams - 1] = LLSD();
|
||||
}
|
||||
|
||||
if (defaults.isUndefined() || defaults.isArray())
|
||||
{
|
||||
LLSD::Integer ndefaults = defaults.size();
|
||||
// defaults is a (possibly empty) array. Right-align it with names.
|
||||
if (ndefaults > nparams)
|
||||
{
|
||||
LL_ERRS("LLSDArgsMapper") << function << " names array " << names
|
||||
<< " shorter than defaults array " << defaults << LL_ENDL;
|
||||
}
|
||||
|
||||
// Offset by which we slide defaults array right to right-align with
|
||||
// _names array
|
||||
LLSD::Integer offset = nparams - ndefaults;
|
||||
// Fill rightmost _defaults entries from defaults, and mark them as
|
||||
// filled
|
||||
for (LLSD::Integer i = 0, iend = ndefaults; i < iend; ++i)
|
||||
{
|
||||
_defaults[i + offset] = defaults[i];
|
||||
_has_dft[i + offset] = 1;
|
||||
}
|
||||
}
|
||||
else if (defaults.isMap())
|
||||
{
|
||||
// defaults is a map. Use it to populate the _defaults array.
|
||||
LLSD bogus;
|
||||
for (LLSD::map_const_iterator mi(defaults.beginMap()), mend(defaults.endMap());
|
||||
mi != mend; ++mi)
|
||||
{
|
||||
IndexMap::const_iterator ixit(_indexes.find(mi->first));
|
||||
if (ixit == _indexes.end())
|
||||
{
|
||||
bogus.append(mi->first);
|
||||
continue;
|
||||
}
|
||||
|
||||
LLSD::Integer pos = ixit->second;
|
||||
// Store default value at that position in the _defaults array.
|
||||
_defaults[pos] = mi->second;
|
||||
// Don't forget to record the fact that we've filled this
|
||||
// position.
|
||||
_has_dft[pos] = 1;
|
||||
}
|
||||
if (bogus.size())
|
||||
{
|
||||
LL_ERRS("LLSDArgsMapper") << function << " defaults specified for nonexistent params "
|
||||
<< formatlist(bogus) << LL_ENDL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_ERRS("LLSDArgsMapper") << function << " defaults must be a map or an array, not "
|
||||
<< defaults << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
LLSD LLSDArgsMapper::map(const LLSD& argsmap) const
|
||||
{
|
||||
if (! (argsmap.isUndefined() || argsmap.isMap() || argsmap.isArray()))
|
||||
{
|
||||
LL_ERRS("LLSDArgsMapper") << _function << " map() needs a map or array, not "
|
||||
<< argsmap << LL_ENDL;
|
||||
}
|
||||
// Initialize the args array. Indexing a non-const LLSD array grows it
|
||||
// to appropriate size, but we don't want to resize this one on each
|
||||
// new operation. Just make it as big as we need before we start
|
||||
// stuffing values into it.
|
||||
LLSD args(LLSD::emptyArray());
|
||||
if (_defaults.size() == 0)
|
||||
{
|
||||
// If this function requires no arguments, fast exit. (Don't try to
|
||||
// assign to args[-1].)
|
||||
return args;
|
||||
}
|
||||
args[_defaults.size() - 1] = LLSD();
|
||||
|
||||
// Get a vector of chars to indicate holes. It's tempting to just scan
|
||||
// for LLSD::isUndefined() values after filling the args array from
|
||||
// the map, but it's plausible for caller to explicitly pass
|
||||
// isUndefined() as the value of some parameter name. That's legal
|
||||
// since isUndefined() has well-defined conversions (default value)
|
||||
// for LLSD data types. So use a whole separate array for detecting
|
||||
// holes. (Avoid std::vector<bool> which is known to be odd -- can we
|
||||
// iterate?)
|
||||
FilledVector filled(args.size());
|
||||
|
||||
if (argsmap.isArray())
|
||||
{
|
||||
// Fill args from array. If there are too many args in passed array,
|
||||
// ignore the rest.
|
||||
LLSD::Integer size(argsmap.size());
|
||||
if (size > args.size())
|
||||
{
|
||||
// We don't just use std::min() because we want to sneak in this
|
||||
// warning if caller passes too many args.
|
||||
LL_WARNS("LLSDArgsMapper") << _function << " needs " << args.size()
|
||||
<< " params, ignoring last " << (size - args.size())
|
||||
<< " of passed " << size << ": " << argsmap << LL_ENDL;
|
||||
size = args.size();
|
||||
}
|
||||
for (LLSD::Integer i(0); i < size; ++i)
|
||||
{
|
||||
// Copy the actual argument from argsmap
|
||||
args[i] = argsmap[i];
|
||||
// Note that it's been filled
|
||||
filled[i] = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// argsmap is in fact a map. Walk the map.
|
||||
for (LLSD::map_const_iterator mi(argsmap.beginMap()), mend(argsmap.endMap());
|
||||
mi != mend; ++mi)
|
||||
{
|
||||
// mi->first is a parameter-name string, with mi->second its
|
||||
// value. Look up the name's position index in _indexes.
|
||||
IndexMap::const_iterator ixit(_indexes.find(mi->first));
|
||||
if (ixit == _indexes.end())
|
||||
{
|
||||
// Allow for a map containing more params than were passed in
|
||||
// our names array. Caller typically receives a map containing
|
||||
// the function name, cruft such as reqid, etc. Ignore keys
|
||||
// not defined in _indexes.
|
||||
LL_DEBUGS("LLSDArgsMapper") << _function << " ignoring "
|
||||
<< mi->first << "=" << mi->second << LL_ENDL;
|
||||
continue;
|
||||
}
|
||||
LLSD::Integer pos = ixit->second;
|
||||
// Store the value at that position in the args array.
|
||||
args[pos] = mi->second;
|
||||
// Don't forget to record the fact that we've filled this
|
||||
// position.
|
||||
filled[pos] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill any remaining holes from _defaults.
|
||||
LLSD unfilled(LLSD::emptyArray());
|
||||
for (LLSD::Integer i = 0, iend = args.size(); i < iend; ++i)
|
||||
{
|
||||
if (! filled[i])
|
||||
{
|
||||
// If there's no default value for this parameter, that's an
|
||||
// error.
|
||||
if (! _has_dft[i])
|
||||
{
|
||||
unfilled.append(_names[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
args[i] = _defaults[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
// If any required args -- args without defaults -- were left unfilled
|
||||
// by argsmap, that's a problem.
|
||||
if (unfilled.size())
|
||||
{
|
||||
LL_ERRS("LLSDArgsMapper") << _function << " missing required arguments "
|
||||
<< formatlist(unfilled) << " from " << argsmap << LL_ENDL;
|
||||
}
|
||||
|
||||
// done
|
||||
return args;
|
||||
}
|
||||
|
||||
std::string LLSDArgsMapper::formatlist(const LLSD& list)
|
||||
{
|
||||
std::ostringstream out;
|
||||
const char* delim = "";
|
||||
for (LLSD::array_const_iterator li(list.beginArray()), lend(list.endArray());
|
||||
li != lend; ++li)
|
||||
{
|
||||
out << delim << li->asString();
|
||||
delim = ", ";
|
||||
}
|
||||
return out.str();
|
||||
}
|
||||
|
||||
LLEventDispatcher::LLEventDispatcher(const std::string& desc, const std::string& key):
|
||||
mDesc(desc),
|
||||
|
|
@ -52,12 +400,181 @@ LLEventDispatcher::~LLEventDispatcher()
|
|||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* DispatchEntry subclass used for callables accepting(const LLSD&)
|
||||
*/
|
||||
struct LLEventDispatcher::LLSDDispatchEntry: public LLEventDispatcher::DispatchEntry
|
||||
{
|
||||
LLSDDispatchEntry(const std::string& desc, const Callable& func, const LLSD& required):
|
||||
DispatchEntry(desc),
|
||||
mFunc(func),
|
||||
mRequired(required)
|
||||
{}
|
||||
|
||||
Callable mFunc;
|
||||
LLSD mRequired;
|
||||
|
||||
virtual void call(const std::string& desc, const LLSD& event) const
|
||||
{
|
||||
// Validate the syntax of the event itself.
|
||||
std::string mismatch(llsd_matches(mRequired, event));
|
||||
if (! mismatch.empty())
|
||||
{
|
||||
LL_ERRS("LLEventDispatcher") << desc << ": bad request: " << mismatch << LL_ENDL;
|
||||
}
|
||||
// Event syntax looks good, go for it!
|
||||
mFunc(event);
|
||||
}
|
||||
|
||||
virtual LLSD addMetadata(LLSD meta) const
|
||||
{
|
||||
meta["required"] = mRequired;
|
||||
return meta;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* DispatchEntry subclass for passing LLSD to functions accepting
|
||||
* arbitrary argument types (convertible via LLSDParam)
|
||||
*/
|
||||
struct LLEventDispatcher::ParamsDispatchEntry: public LLEventDispatcher::DispatchEntry
|
||||
{
|
||||
ParamsDispatchEntry(const std::string& desc, const invoker_function& func):
|
||||
DispatchEntry(desc),
|
||||
mInvoker(func)
|
||||
{}
|
||||
|
||||
invoker_function mInvoker;
|
||||
|
||||
virtual void call(const std::string& desc, const LLSD& event) const
|
||||
{
|
||||
LLSDArgsSource src(desc, event);
|
||||
mInvoker(boost::bind(&LLSDArgsSource::next, boost::ref(src)));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* DispatchEntry subclass for dispatching LLSD::Array to functions accepting
|
||||
* arbitrary argument types (convertible via LLSDParam)
|
||||
*/
|
||||
struct LLEventDispatcher::ArrayParamsDispatchEntry: public LLEventDispatcher::ParamsDispatchEntry
|
||||
{
|
||||
ArrayParamsDispatchEntry(const std::string& desc, const invoker_function& func,
|
||||
LLSD::Integer arity):
|
||||
ParamsDispatchEntry(desc, func),
|
||||
mArity(arity)
|
||||
{}
|
||||
|
||||
LLSD::Integer mArity;
|
||||
|
||||
virtual LLSD addMetadata(LLSD meta) const
|
||||
{
|
||||
LLSD array(LLSD::emptyArray());
|
||||
// Resize to number of arguments required
|
||||
if (mArity)
|
||||
array[mArity - 1] = LLSD();
|
||||
llassert_always(array.size() == mArity);
|
||||
meta["required"] = array;
|
||||
return meta;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* DispatchEntry subclass for dispatching LLSD::Map to functions accepting
|
||||
* arbitrary argument types (convertible via LLSDParam)
|
||||
*/
|
||||
struct LLEventDispatcher::MapParamsDispatchEntry: public LLEventDispatcher::ParamsDispatchEntry
|
||||
{
|
||||
MapParamsDispatchEntry(const std::string& name, const std::string& desc,
|
||||
const invoker_function& func,
|
||||
const LLSD& params, const LLSD& defaults):
|
||||
ParamsDispatchEntry(desc, func),
|
||||
mMapper(name, params, defaults),
|
||||
mRequired(LLSD::emptyMap())
|
||||
{
|
||||
// Build the set of all param keys, then delete the ones that are
|
||||
// optional. What's left are the ones that are required.
|
||||
for (LLSD::array_const_iterator pi(params.beginArray()), pend(params.endArray());
|
||||
pi != pend; ++pi)
|
||||
{
|
||||
mRequired[pi->asString()] = LLSD();
|
||||
}
|
||||
|
||||
if (defaults.isArray() || defaults.isUndefined())
|
||||
{
|
||||
// Right-align the params and defaults arrays.
|
||||
LLSD::Integer offset = params.size() - defaults.size();
|
||||
// Now the name of every defaults[i] is at params[i + offset].
|
||||
for (LLSD::Integer i(0), iend(defaults.size()); i < iend; ++i)
|
||||
{
|
||||
// Erase this optional param from mRequired.
|
||||
mRequired.erase(params[i + offset].asString());
|
||||
// Instead, make an entry in mOptional with the default
|
||||
// param's name and value.
|
||||
mOptional[params[i + offset].asString()] = defaults[i];
|
||||
}
|
||||
}
|
||||
else if (defaults.isMap())
|
||||
{
|
||||
// if defaults is already a map, then it's already in the form we
|
||||
// intend to deliver in metadata
|
||||
mOptional = defaults;
|
||||
// Just delete from mRequired every key appearing in mOptional.
|
||||
for (LLSD::map_const_iterator mi(mOptional.beginMap()), mend(mOptional.endMap());
|
||||
mi != mend; ++mi)
|
||||
{
|
||||
mRequired.erase(mi->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LLSDArgsMapper mMapper;
|
||||
LLSD mRequired;
|
||||
LLSD mOptional;
|
||||
|
||||
virtual void call(const std::string& desc, const LLSD& event) const
|
||||
{
|
||||
// Just convert from LLSD::Map to LLSD::Array using mMapper, then pass
|
||||
// to base-class call() method.
|
||||
ParamsDispatchEntry::call(desc, mMapper.map(event));
|
||||
}
|
||||
|
||||
virtual LLSD addMetadata(LLSD meta) const
|
||||
{
|
||||
meta["required"] = mRequired;
|
||||
meta["optional"] = mOptional;
|
||||
return meta;
|
||||
}
|
||||
};
|
||||
|
||||
void LLEventDispatcher::addArrayParamsDispatchEntry(const std::string& name,
|
||||
const std::string& desc,
|
||||
const invoker_function& invoker,
|
||||
LLSD::Integer arity)
|
||||
{
|
||||
mDispatch.insert(
|
||||
DispatchMap::value_type(name, DispatchMap::mapped_type(
|
||||
new ArrayParamsDispatchEntry(desc, invoker, arity))));
|
||||
}
|
||||
|
||||
void LLEventDispatcher::addMapParamsDispatchEntry(const std::string& name,
|
||||
const std::string& desc,
|
||||
const invoker_function& invoker,
|
||||
const LLSD& params,
|
||||
const LLSD& defaults)
|
||||
{
|
||||
mDispatch.insert(
|
||||
DispatchMap::value_type(name, DispatchMap::mapped_type(
|
||||
new MapParamsDispatchEntry(name, desc, invoker, params, defaults))));
|
||||
}
|
||||
|
||||
/// Register a callable by name
|
||||
void LLEventDispatcher::add(const std::string& name, const std::string& desc,
|
||||
const Callable& callable, const LLSD& required)
|
||||
{
|
||||
mDispatch.insert(DispatchMap::value_type(name,
|
||||
DispatchMap::mapped_type(callable, desc, required)));
|
||||
mDispatch.insert(
|
||||
DispatchMap::value_type(name, DispatchMap::mapped_type(
|
||||
new LLSDDispatchEntry(desc, callable, required))));
|
||||
}
|
||||
|
||||
void LLEventDispatcher::addFail(const std::string& name, const std::string& classname) const
|
||||
|
|
@ -83,7 +600,7 @@ bool LLEventDispatcher::remove(const std::string& name)
|
|||
/// such callable exists, die with LL_ERRS.
|
||||
void LLEventDispatcher::operator()(const std::string& name, const LLSD& event) const
|
||||
{
|
||||
if (! attemptCall(name, event))
|
||||
if (! try_call(name, event))
|
||||
{
|
||||
LL_ERRS("LLEventDispatcher") << "LLEventDispatcher(" << mDesc << "): '" << name
|
||||
<< "' not found" << LL_ENDL;
|
||||
|
|
@ -98,44 +615,29 @@ void LLEventDispatcher::operator()(const LLSD& event) const
|
|||
// This could/should be implemented in terms of the two-arg overload.
|
||||
// However -- we can produce a more informative error message.
|
||||
std::string name(event[mKey]);
|
||||
if (! attemptCall(name, event))
|
||||
if (! try_call(name, event))
|
||||
{
|
||||
LL_ERRS("LLEventDispatcher") << "LLEventDispatcher(" << mDesc << "): bad " << mKey
|
||||
<< " value '" << name << "'" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
bool LLEventDispatcher::attemptCall(const std::string& name, const LLSD& event) const
|
||||
bool LLEventDispatcher::try_call(const LLSD& event) const
|
||||
{
|
||||
DispatchMap::const_iterator found = mDispatch.find(name);
|
||||
if (found == mDispatch.end())
|
||||
{
|
||||
// The reason we only return false, leaving it up to our caller to die
|
||||
// with LL_ERRS, is that different callers have different amounts of
|
||||
// available information.
|
||||
return false;
|
||||
}
|
||||
// Found the name, so it's plausible to even attempt the call. But first,
|
||||
// validate the syntax of the event itself.
|
||||
std::string mismatch(llsd_matches(found->second.mRequired, event));
|
||||
if (! mismatch.empty())
|
||||
{
|
||||
LL_ERRS("LLEventDispatcher") << "LLEventDispatcher(" << mDesc << ") calling '" << name
|
||||
<< "': bad request: " << mismatch << LL_ENDL;
|
||||
}
|
||||
// Event syntax looks good, go for it!
|
||||
(found->second.mFunc)(event);
|
||||
return true; // tell caller we were able to call
|
||||
return try_call(event[mKey], event);
|
||||
}
|
||||
|
||||
LLEventDispatcher::Callable LLEventDispatcher::get(const std::string& name) const
|
||||
bool LLEventDispatcher::try_call(const std::string& name, const LLSD& event) const
|
||||
{
|
||||
DispatchMap::const_iterator found = mDispatch.find(name);
|
||||
if (found == mDispatch.end())
|
||||
{
|
||||
return Callable();
|
||||
return false;
|
||||
}
|
||||
return found->second.mFunc;
|
||||
// Found the name, so it's plausible to even attempt the call.
|
||||
found->second->call(STRINGIZE("LLEventDispatcher(" << mDesc << ") calling '" << name << "'"),
|
||||
event);
|
||||
return true; // tell caller we were able to call
|
||||
}
|
||||
|
||||
LLSD LLEventDispatcher::getMetadata(const std::string& name) const
|
||||
|
|
@ -147,9 +649,8 @@ LLSD LLEventDispatcher::getMetadata(const std::string& name) const
|
|||
}
|
||||
LLSD meta;
|
||||
meta["name"] = name;
|
||||
meta["desc"] = found->second.mDesc;
|
||||
meta["required"] = found->second.mRequired;
|
||||
return meta;
|
||||
meta["desc"] = found->second->mDesc;
|
||||
return found->second->addMetadata(meta);
|
||||
}
|
||||
|
||||
LLDispatchListener::LLDispatchListener(const std::string& pumpname, const std::string& key):
|
||||
|
|
@ -164,3 +665,8 @@ bool LLDispatchListener::process(const LLSD& event)
|
|||
(*this)(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
LLEventDispatcher::DispatchEntry::DispatchEntry(const std::string& desc):
|
||||
mDesc(desc)
|
||||
{}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,18 +27,56 @@
|
|||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*
|
||||
* The invoker machinery that constructs a boost::fusion argument list for use
|
||||
* with boost::fusion::invoke() is derived from
|
||||
* http://www.boost.org/doc/libs/1_45_0/libs/function_types/example/interpreter.hpp
|
||||
* whose license information is copied below:
|
||||
*
|
||||
* "(C) Copyright Tobias Schwinger
|
||||
*
|
||||
* Use modification and distribution are subject to the boost Software License,
|
||||
* Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt)."
|
||||
*/
|
||||
|
||||
#if ! defined(LL_LLEVENTDISPATCHER_H)
|
||||
#define LL_LLEVENTDISPATCHER_H
|
||||
|
||||
// nil is too generic a term to be allowed to be a global macro. In
|
||||
// particular, boost::fusion defines a 'class nil' (properly encapsulated in a
|
||||
// namespace) that a global 'nil' macro breaks badly.
|
||||
#if defined(nil)
|
||||
// Capture the value of the macro 'nil', hoping int is an appropriate type.
|
||||
static const int nil_(nil);
|
||||
// Now forget the macro.
|
||||
#undef nil
|
||||
// Finally, reintroduce 'nil' as a properly-scoped alias for the previously-
|
||||
// defined const 'nil_'. Make it static since otherwise it produces duplicate-
|
||||
// symbol link errors later.
|
||||
static const int& nil(nil_);
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/function_types/is_nonmember_callable_builtin.hpp>
|
||||
#include <boost/function_types/parameter_types.hpp>
|
||||
#include <boost/function_types/function_arity.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/fusion/include/push_back.hpp>
|
||||
#include <boost/fusion/include/cons.hpp>
|
||||
#include <boost/fusion/include/invoke.hpp>
|
||||
#include <boost/mpl/begin.hpp>
|
||||
#include <boost/mpl/end.hpp>
|
||||
#include <boost/mpl/next.hpp>
|
||||
#include <boost/mpl/deref.hpp>
|
||||
#include <typeinfo>
|
||||
#include "llevents.h"
|
||||
#include "llsdutil.h"
|
||||
|
||||
class LLSD;
|
||||
|
||||
|
|
@ -54,12 +92,18 @@ public:
|
|||
LLEventDispatcher(const std::string& desc, const std::string& key);
|
||||
virtual ~LLEventDispatcher();
|
||||
|
||||
/// Accept any C++ callable, typically a boost::bind() expression
|
||||
/// @name Register functions accepting(const LLSD&)
|
||||
//@{
|
||||
|
||||
/// Accept any C++ callable with the right signature, typically a
|
||||
/// boost::bind() expression
|
||||
typedef boost::function<void(const LLSD&)> Callable;
|
||||
|
||||
/**
|
||||
* Register a @a callable by @a name. The optional @a required parameter
|
||||
* is used to validate the structure of each incoming event (see
|
||||
* Register a @a callable by @a name. The passed @a callable accepts a
|
||||
* single LLSD value and uses it in any way desired, e.g. extract
|
||||
* parameters and call some other function. The optional @a required
|
||||
* parameter is used to validate the structure of each incoming event (see
|
||||
* llsd_matches()).
|
||||
*/
|
||||
void add(const std::string& name,
|
||||
|
|
@ -67,10 +111,24 @@ public:
|
|||
const Callable& callable,
|
||||
const LLSD& required=LLSD());
|
||||
|
||||
/**
|
||||
* The case of a free function (or static method) accepting(const LLSD&)
|
||||
* could also be intercepted by the arbitrary-args overload below. Ensure
|
||||
* that it's directed to the Callable overload above instead.
|
||||
*/
|
||||
void add(const std::string& name,
|
||||
const std::string& desc,
|
||||
void (*f)(const LLSD&),
|
||||
const LLSD& required=LLSD())
|
||||
{
|
||||
add(name, desc, Callable(f), required);
|
||||
}
|
||||
|
||||
/**
|
||||
* Special case: a subclass of this class can pass an unbound member
|
||||
* function pointer without explicitly specifying the
|
||||
* <tt>boost::bind()</tt> expression.
|
||||
* function pointer (of an LLEventDispatcher subclass) without explicitly
|
||||
* specifying the <tt>boost::bind()</tt> expression. The passed @a method
|
||||
* accepts a single LLSD value, presumably containing other parameters.
|
||||
*/
|
||||
template <class CLASS>
|
||||
void add(const std::string& name,
|
||||
|
|
@ -81,7 +139,8 @@ public:
|
|||
addMethod<CLASS>(name, desc, method, required);
|
||||
}
|
||||
|
||||
/// Overload for both const and non-const methods
|
||||
/// Overload for both const and non-const methods. The passed @a method
|
||||
/// accepts a single LLSD value, presumably containing other parameters.
|
||||
template <class CLASS>
|
||||
void add(const std::string& name,
|
||||
const std::string& desc,
|
||||
|
|
@ -91,15 +150,106 @@ public:
|
|||
addMethod<CLASS>(name, desc, method, required);
|
||||
}
|
||||
|
||||
/// Convenience: for LLEventDispatcher, not every callable needs a
|
||||
/// documentation string.
|
||||
template <typename CALLABLE>
|
||||
void add(const std::string& name,
|
||||
CALLABLE callable,
|
||||
const LLSD& required=LLSD())
|
||||
{
|
||||
add(name, "", callable, required);
|
||||
}
|
||||
//@}
|
||||
|
||||
/// @name Register functions with arbitrary param lists
|
||||
//@{
|
||||
|
||||
/**
|
||||
* Register a free function with arbitrary parameters. (This also works
|
||||
* for static class methods.)
|
||||
*
|
||||
* @note This supports functions with up to about 6 parameters -- after
|
||||
* that you start getting dismaying compile errors in which
|
||||
* boost::fusion::joint_view is mentioned a surprising number of times.
|
||||
*
|
||||
* When calling this name, pass an LLSD::Array. Each entry in turn will be
|
||||
* converted to the corresponding parameter type using LLSDParam.
|
||||
*/
|
||||
template<typename Function>
|
||||
typename boost::enable_if< boost::function_types::is_nonmember_callable_builtin<Function>
|
||||
>::type add(const std::string& name,
|
||||
const std::string& desc,
|
||||
Function f);
|
||||
|
||||
/**
|
||||
* Register a nonstatic class method with arbitrary parameters.
|
||||
*
|
||||
* @note This supports functions with up to about 6 parameters -- after
|
||||
* that you start getting dismaying compile errors in which
|
||||
* boost::fusion::joint_view is mentioned a surprising number of times.
|
||||
*
|
||||
* To cover cases such as a method on an LLSingleton we don't yet want to
|
||||
* instantiate, instead of directly storing an instance pointer, accept a
|
||||
* nullary callable returning a pointer/reference to the desired class
|
||||
* instance. If you already have an instance in hand,
|
||||
* boost::lambda::var(instance) or boost::lambda::constant(instance_ptr)
|
||||
* produce suitable callables.
|
||||
*
|
||||
* When calling this name, pass an LLSD::Array. Each entry in turn will be
|
||||
* converted to the corresponding parameter type using LLSDParam.
|
||||
*/
|
||||
template<typename Method, typename InstanceGetter>
|
||||
typename boost::enable_if< boost::function_types::is_member_function_pointer<Method>
|
||||
>::type add(const std::string& name,
|
||||
const std::string& desc,
|
||||
Method f,
|
||||
const InstanceGetter& getter);
|
||||
|
||||
/**
|
||||
* Register a free function with arbitrary parameters. (This also works
|
||||
* for static class methods.)
|
||||
*
|
||||
* @note This supports functions with up to about 6 parameters -- after
|
||||
* that you start getting dismaying compile errors in which
|
||||
* boost::fusion::joint_view is mentioned a surprising number of times.
|
||||
*
|
||||
* Pass an LLSD::Array of parameter names, and optionally another
|
||||
* LLSD::Array of default parameter values, a la LLSDArgsMapper.
|
||||
*
|
||||
* When calling this name, pass an LLSD::Map. We will internally generate
|
||||
* an LLSD::Array using LLSDArgsMapper and then convert each entry in turn
|
||||
* to the corresponding parameter type using LLSDParam.
|
||||
*/
|
||||
template<typename Function>
|
||||
typename boost::enable_if< boost::function_types::is_nonmember_callable_builtin<Function>
|
||||
>::type add(const std::string& name,
|
||||
const std::string& desc,
|
||||
Function f,
|
||||
const LLSD& params,
|
||||
const LLSD& defaults=LLSD());
|
||||
|
||||
/**
|
||||
* Register a nonstatic class method with arbitrary parameters.
|
||||
*
|
||||
* @note This supports functions with up to about 6 parameters -- after
|
||||
* that you start getting dismaying compile errors in which
|
||||
* boost::fusion::joint_view is mentioned a surprising number of times.
|
||||
*
|
||||
* To cover cases such as a method on an LLSingleton we don't yet want to
|
||||
* instantiate, instead of directly storing an instance pointer, accept a
|
||||
* nullary callable returning a pointer/reference to the desired class
|
||||
* instance. If you already have an instance in hand,
|
||||
* boost::lambda::var(instance) or boost::lambda::constant(instance_ptr)
|
||||
* produce suitable callables.
|
||||
*
|
||||
* Pass an LLSD::Array of parameter names, and optionally another
|
||||
* LLSD::Array of default parameter values, a la LLSDArgsMapper.
|
||||
*
|
||||
* When calling this name, pass an LLSD::Map. We will internally generate
|
||||
* an LLSD::Array using LLSDArgsMapper and then convert each entry in turn
|
||||
* to the corresponding parameter type using LLSDParam.
|
||||
*/
|
||||
template<typename Method, typename InstanceGetter>
|
||||
typename boost::enable_if< boost::function_types::is_member_function_pointer<Method>
|
||||
>::type add(const std::string& name,
|
||||
const std::string& desc,
|
||||
Method f,
|
||||
const InstanceGetter& getter,
|
||||
const LLSD& params,
|
||||
const LLSD& defaults=LLSD());
|
||||
|
||||
//@}
|
||||
|
||||
/// Unregister a callable
|
||||
bool remove(const std::string& name);
|
||||
|
|
@ -109,12 +259,25 @@ public:
|
|||
/// the @a required prototype specified at add() time, die with LL_ERRS.
|
||||
void operator()(const std::string& name, const LLSD& event) const;
|
||||
|
||||
/// Call a registered callable with an explicitly-specified name and
|
||||
/// return <tt>true</tt>. If no such callable exists, return
|
||||
/// <tt>false</tt>. If the @a event fails to match the @a required
|
||||
/// prototype specified at add() time, die with LL_ERRS.
|
||||
bool try_call(const std::string& name, const LLSD& event) const;
|
||||
|
||||
/// Extract the @a key value from the incoming @a event, and call the
|
||||
/// callable whose name is specified by that map @a key. If no such
|
||||
/// callable exists, die with LL_ERRS. If the @a event fails to match the
|
||||
/// @a required prototype specified at add() time, die with LL_ERRS.
|
||||
void operator()(const LLSD& event) const;
|
||||
|
||||
/// Extract the @a key value from the incoming @a event, call the callable
|
||||
/// whose name is specified by that map @a key and return <tt>true</tt>.
|
||||
/// If no such callable exists, return <tt>false</tt>. If the @a event
|
||||
/// fails to match the @a required prototype specified at add() time, die
|
||||
/// with LL_ERRS.
|
||||
bool try_call(const LLSD& event) const;
|
||||
|
||||
/// @name Iterate over defined names
|
||||
//@{
|
||||
typedef std::pair<std::string, std::string> NameDesc;
|
||||
|
|
@ -122,16 +285,22 @@ public:
|
|||
private:
|
||||
struct DispatchEntry
|
||||
{
|
||||
DispatchEntry(const Callable& func, const std::string& desc, const LLSD& required):
|
||||
mFunc(func),
|
||||
mDesc(desc),
|
||||
mRequired(required)
|
||||
{}
|
||||
Callable mFunc;
|
||||
DispatchEntry(const std::string& desc);
|
||||
virtual ~DispatchEntry() {} // suppress MSVC warning, sigh
|
||||
|
||||
std::string mDesc;
|
||||
LLSD mRequired;
|
||||
|
||||
virtual void call(const std::string& desc, const LLSD& event) const = 0;
|
||||
virtual LLSD addMetadata(LLSD) const = 0;
|
||||
};
|
||||
typedef std::map<std::string, DispatchEntry> DispatchMap;
|
||||
// Tried using boost::ptr_map<std::string, DispatchEntry>, but ptr_map<>
|
||||
// wants its value type to be "clonable," even just to dereference an
|
||||
// iterator. I don't want to clone entries -- if I have to copy an entry
|
||||
// around, I want it to continue pointing to the same DispatchEntry
|
||||
// subclass object. However, I definitely want DispatchMap to destroy
|
||||
// DispatchEntry if no references are outstanding at the time an entry is
|
||||
// removed. This looks like a job for boost::shared_ptr.
|
||||
typedef std::map<std::string, boost::shared_ptr<DispatchEntry> > DispatchMap;
|
||||
|
||||
public:
|
||||
/// We want the flexibility to redefine what data we store per name,
|
||||
|
|
@ -149,10 +318,6 @@ public:
|
|||
}
|
||||
//@}
|
||||
|
||||
/// Fetch the Callable for the specified name. If no such name was
|
||||
/// registered, return an empty() Callable.
|
||||
Callable get(const std::string& name) const;
|
||||
|
||||
/// Get information about a specific Callable
|
||||
LLSD getMetadata(const std::string& name) const;
|
||||
|
||||
|
|
@ -175,18 +340,184 @@ private:
|
|||
}
|
||||
}
|
||||
void addFail(const std::string& name, const std::string& classname) const;
|
||||
/// try to dispatch, return @c true if success
|
||||
bool attemptCall(const std::string& name, const LLSD& event) const;
|
||||
|
||||
std::string mDesc, mKey;
|
||||
DispatchMap mDispatch;
|
||||
|
||||
static NameDesc makeNameDesc(const DispatchMap::value_type& item)
|
||||
{
|
||||
return NameDesc(item.first, item.second.mDesc);
|
||||
return NameDesc(item.first, item.second->mDesc);
|
||||
}
|
||||
|
||||
struct LLSDDispatchEntry;
|
||||
struct ParamsDispatchEntry;
|
||||
struct ArrayParamsDispatchEntry;
|
||||
struct MapParamsDispatchEntry;
|
||||
|
||||
// Step 2 of parameter analysis. Instantiating invoker<some_function_type>
|
||||
// implicitly sets its From and To parameters to the (compile time) begin
|
||||
// and end iterators over that function's parameter types.
|
||||
template< typename Function
|
||||
, class From = typename boost::mpl::begin< boost::function_types::parameter_types<Function> >::type
|
||||
, class To = typename boost::mpl::end< boost::function_types::parameter_types<Function> >::type
|
||||
>
|
||||
struct invoker;
|
||||
|
||||
// deliver LLSD arguments one at a time
|
||||
typedef boost::function<LLSD()> args_source;
|
||||
// obtain args from an args_source to build param list and call target
|
||||
// function
|
||||
typedef boost::function<void(const args_source&)> invoker_function;
|
||||
|
||||
template <typename Function>
|
||||
invoker_function make_invoker(Function f);
|
||||
template <typename Method, typename InstanceGetter>
|
||||
invoker_function make_invoker(Method f, const InstanceGetter& getter);
|
||||
void addArrayParamsDispatchEntry(const std::string& name,
|
||||
const std::string& desc,
|
||||
const invoker_function& invoker,
|
||||
LLSD::Integer arity);
|
||||
void addMapParamsDispatchEntry(const std::string& name,
|
||||
const std::string& desc,
|
||||
const invoker_function& invoker,
|
||||
const LLSD& params,
|
||||
const LLSD& defaults);
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* LLEventDispatcher template implementation details
|
||||
*****************************************************************************/
|
||||
// Step 3 of parameter analysis, the recursive case.
|
||||
template<typename Function, class From, class To>
|
||||
struct LLEventDispatcher::invoker
|
||||
{
|
||||
template<typename T>
|
||||
struct remove_cv_ref
|
||||
: boost::remove_cv< typename boost::remove_reference<T>::type >
|
||||
{ };
|
||||
|
||||
// apply() accepts an arbitrary boost::fusion sequence as args. It
|
||||
// examines the next parameter type in the parameter-types sequence
|
||||
// bounded by From and To, obtains the next LLSD object from the passed
|
||||
// args_source and constructs an LLSDParam of appropriate type to try
|
||||
// to convert the value. It then recurs with the next parameter-types
|
||||
// iterator, passing the args sequence thus far.
|
||||
template<typename Args>
|
||||
static inline
|
||||
void apply(Function func, const args_source& argsrc, Args const & args)
|
||||
{
|
||||
typedef typename boost::mpl::deref<From>::type arg_type;
|
||||
typedef typename boost::mpl::next<From>::type next_iter_type;
|
||||
typedef typename remove_cv_ref<arg_type>::type plain_arg_type;
|
||||
|
||||
invoker<Function, next_iter_type, To>::apply
|
||||
( func, argsrc, boost::fusion::push_back(args, LLSDParam<plain_arg_type>(argsrc())));
|
||||
}
|
||||
|
||||
// Special treatment for instance (first) parameter of a non-static member
|
||||
// function. Accept the instance-getter callable, calling that to produce
|
||||
// the first args value. Since we know we're at the top of the recursion
|
||||
// chain, we need not also require a partial args sequence from our caller.
|
||||
template <typename InstanceGetter>
|
||||
static inline
|
||||
void method_apply(Function func, const args_source& argsrc, const InstanceGetter& getter)
|
||||
{
|
||||
typedef typename boost::mpl::next<From>::type next_iter_type;
|
||||
|
||||
// Instead of grabbing the first item from argsrc and making an
|
||||
// LLSDParam of it, call getter() and pass that as the instance param.
|
||||
invoker<Function, next_iter_type, To>::apply
|
||||
( func, argsrc, boost::fusion::push_back(boost::fusion::nil(), boost::ref(getter())));
|
||||
}
|
||||
};
|
||||
|
||||
// Step 4 of parameter analysis, the leaf case. When the general
|
||||
// invoker<Function, From, To> logic has advanced From until it matches To,
|
||||
// the compiler will pick this template specialization.
|
||||
template<typename Function, class To>
|
||||
struct LLEventDispatcher::invoker<Function,To,To>
|
||||
{
|
||||
// the argument list is complete, now call the function
|
||||
template<typename Args>
|
||||
static inline
|
||||
void apply(Function func, const args_source&, Args const & args)
|
||||
{
|
||||
boost::fusion::invoke(func, args);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Function>
|
||||
typename boost::enable_if< boost::function_types::is_nonmember_callable_builtin<Function> >::type
|
||||
LLEventDispatcher::add(const std::string& name, const std::string& desc, Function f)
|
||||
{
|
||||
// Construct an invoker_function, a callable accepting const args_source&.
|
||||
// Add to DispatchMap an ArrayParamsDispatchEntry that will handle the
|
||||
// caller's LLSD::Array.
|
||||
addArrayParamsDispatchEntry(name, desc, make_invoker(f),
|
||||
boost::function_types::function_arity<Function>::value);
|
||||
}
|
||||
|
||||
template<typename Method, typename InstanceGetter>
|
||||
typename boost::enable_if< boost::function_types::is_member_function_pointer<Method> >::type
|
||||
LLEventDispatcher::add(const std::string& name, const std::string& desc, Method f,
|
||||
const InstanceGetter& getter)
|
||||
{
|
||||
// Subtract 1 from the compile-time arity because the getter takes care of
|
||||
// the first parameter. We only need (arity - 1) additional arguments.
|
||||
addArrayParamsDispatchEntry(name, desc, make_invoker(f, getter),
|
||||
boost::function_types::function_arity<Method>::value - 1);
|
||||
}
|
||||
|
||||
template<typename Function>
|
||||
typename boost::enable_if< boost::function_types::is_nonmember_callable_builtin<Function> >::type
|
||||
LLEventDispatcher::add(const std::string& name, const std::string& desc, Function f,
|
||||
const LLSD& params, const LLSD& defaults)
|
||||
{
|
||||
// See comments for previous is_nonmember_callable_builtin add().
|
||||
addMapParamsDispatchEntry(name, desc, make_invoker(f), params, defaults);
|
||||
}
|
||||
|
||||
template<typename Method, typename InstanceGetter>
|
||||
typename boost::enable_if< boost::function_types::is_member_function_pointer<Method> >::type
|
||||
LLEventDispatcher::add(const std::string& name, const std::string& desc, Method f,
|
||||
const InstanceGetter& getter,
|
||||
const LLSD& params, const LLSD& defaults)
|
||||
{
|
||||
addMapParamsDispatchEntry(name, desc, make_invoker(f, getter), params, defaults);
|
||||
}
|
||||
|
||||
template <typename Function>
|
||||
LLEventDispatcher::invoker_function
|
||||
LLEventDispatcher::make_invoker(Function f)
|
||||
{
|
||||
// Step 1 of parameter analysis, the top of the recursion. Passing a
|
||||
// suitable f (see add()'s enable_if condition) to this method causes it
|
||||
// to infer the function type; specifying that function type to invoker<>
|
||||
// causes it to fill in the begin/end MPL iterators over the function's
|
||||
// list of parameter types.
|
||||
// While normally invoker::apply() could infer its template type from the
|
||||
// boost::fusion::nil parameter value, here we must be explicit since
|
||||
// we're boost::bind()ing it rather than calling it directly.
|
||||
return boost::bind(&invoker<Function>::template apply<boost::fusion::nil>,
|
||||
f,
|
||||
_1,
|
||||
boost::fusion::nil());
|
||||
}
|
||||
|
||||
template <typename Method, typename InstanceGetter>
|
||||
LLEventDispatcher::invoker_function
|
||||
LLEventDispatcher::make_invoker(Method f, const InstanceGetter& getter)
|
||||
{
|
||||
// Use invoker::method_apply() to treat the instance (first) arg specially.
|
||||
return boost::bind(&invoker<Method>::template method_apply<InstanceGetter>,
|
||||
f,
|
||||
_1,
|
||||
getter);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* LLDispatchListener
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* Bundle an LLEventPump and a listener with an LLEventDispatcher. A class
|
||||
* that contains (or derives from) LLDispatchListener need only specify the
|
||||
|
|
|
|||
|
|
@ -588,3 +588,16 @@ void LLReqID::stamp(LLSD& response) const
|
|||
}
|
||||
response["reqid"] = mReqid;
|
||||
}
|
||||
|
||||
bool sendReply(const LLSD& reply, const LLSD& request, const std::string& replyKey)
|
||||
{
|
||||
// Copy 'reply' to modify it.
|
||||
LLSD newreply(reply);
|
||||
// Get the ["reqid"] element from request
|
||||
LLReqID reqID(request);
|
||||
// and copy it to 'newreply'.
|
||||
reqID.stamp(newreply);
|
||||
// Send reply on LLEventPump named in request[replyKey]. Don't forget to
|
||||
// send the modified 'newreply' instead of the original 'reply'.
|
||||
return LLEventPumps::instance().obtain(request[replyKey]).post(newreply);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -691,6 +691,20 @@ private:
|
|||
LLSD mReqid;
|
||||
};
|
||||
|
||||
/**
|
||||
* Conventionally send a reply to a request event.
|
||||
*
|
||||
* @a reply is the LLSD reply event to send
|
||||
* @a request is the corresponding LLSD request event
|
||||
* @a replyKey is the key in the @a request event, conventionally ["reply"],
|
||||
* whose value is the name of the LLEventPump on which to send the reply.
|
||||
*
|
||||
* Before sending the reply event, sendReply() copies the ["reqid"] item from
|
||||
* the request to the reply.
|
||||
*/
|
||||
LL_COMMON_API bool sendReply(const LLSD& reply, const LLSD& request,
|
||||
const std::string& replyKey="reply");
|
||||
|
||||
/**
|
||||
* Base class for LLListenerWrapper. See visit_and_connect() and llwrap(). We
|
||||
* provide virtual @c accept_xxx() methods, customization points allowing a
|
||||
|
|
|
|||
|
|
@ -32,6 +32,17 @@
|
|||
// external library headers
|
||||
// other Linden headers
|
||||
|
||||
// llinstancetracker.h is presently header-only. This file exists only because our CMake
|
||||
// test macro ADD_BUILD_TEST requires it.
|
||||
int dummy = 0;
|
||||
//static
|
||||
void * & LLInstanceTrackerBase::getInstances(std::type_info const & info)
|
||||
{
|
||||
static std::map<std::string, void *> instances;
|
||||
|
||||
std::string k = info.name();
|
||||
if(instances.find(k) == instances.end())
|
||||
{
|
||||
instances[k] = NULL;
|
||||
}
|
||||
|
||||
return instances[k];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,14 +37,21 @@
|
|||
#include <boost/iterator/transform_iterator.hpp>
|
||||
#include <boost/iterator/indirect_iterator.hpp>
|
||||
|
||||
class LL_COMMON_API LLInstanceTrackerBase : public boost::noncopyable
|
||||
{
|
||||
protected:
|
||||
static void * & getInstances(std::type_info const & info);
|
||||
};
|
||||
|
||||
/// This mix-in class adds support for tracking all instances of the specified class parameter T
|
||||
/// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup
|
||||
/// If KEY is not provided, then instances are stored in a simple set
|
||||
/// @NOTE: see explicit specialization below for default KEY==T* case
|
||||
template<typename T, typename KEY = T*>
|
||||
class LLInstanceTracker : boost::noncopyable
|
||||
class LLInstanceTracker : public LLInstanceTrackerBase
|
||||
{
|
||||
typedef typename std::map<KEY, T*> InstanceMap;
|
||||
typedef LLInstanceTracker<T, KEY> MyT;
|
||||
typedef boost::function<const KEY&(typename InstanceMap::value_type&)> KeyGetter;
|
||||
typedef boost::function<T*(typename InstanceMap::value_type&)> InstancePtrGetter;
|
||||
public:
|
||||
|
|
@ -99,25 +106,26 @@ private:
|
|||
|
||||
static InstanceMap& getMap_()
|
||||
{
|
||||
if (! sInstances)
|
||||
void * & instances = getInstances(typeid(MyT));
|
||||
if (! instances)
|
||||
{
|
||||
sInstances = new InstanceMap;
|
||||
instances = new InstanceMap;
|
||||
}
|
||||
return *sInstances;
|
||||
return * static_cast<InstanceMap*>(instances);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
KEY mKey;
|
||||
static InstanceMap* sInstances;
|
||||
};
|
||||
|
||||
/// explicit specialization for default case where KEY is T*
|
||||
/// use a simple std::set<T*>
|
||||
template<typename T>
|
||||
class LLInstanceTracker<T, T*>
|
||||
class LLInstanceTracker<T, T*> : public LLInstanceTrackerBase
|
||||
{
|
||||
typedef typename std::set<T*> InstanceSet;
|
||||
typedef LLInstanceTracker<T, T*> MyT;
|
||||
public:
|
||||
/// Dereferencing key_iter gives you a T* (since T* is the key)
|
||||
typedef typename InstanceSet::iterator key_iter;
|
||||
|
|
@ -172,19 +180,17 @@ protected:
|
|||
|
||||
static InstanceSet& getSet_()
|
||||
{
|
||||
if (! sInstances)
|
||||
void * & instances = getInstances(typeid(MyT));
|
||||
if (! instances)
|
||||
{
|
||||
sInstances = new InstanceSet;
|
||||
instances = new InstanceSet;
|
||||
}
|
||||
return *sInstances;
|
||||
return * static_cast<InstanceSet *>(instances);
|
||||
}
|
||||
|
||||
static InstanceSet* sInstances;
|
||||
static S32 sIterationNestDepth;
|
||||
};
|
||||
|
||||
template <typename T, typename KEY> typename LLInstanceTracker<T, KEY>::InstanceMap* LLInstanceTracker<T, KEY>::sInstances = NULL;
|
||||
template <typename T> typename LLInstanceTracker<T, T*>::InstanceSet* LLInstanceTracker<T, T*>::sInstances = NULL;
|
||||
template <typename T> S32 LLInstanceTracker<T, T*>::sIterationNestDepth = 0;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "llsdserialize.h"
|
||||
#include "stringize.h"
|
||||
#include "is_approx_equal_fraction.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
|
@ -571,7 +572,7 @@ std::string llsd_matches(const LLSD& prototype, const LLSD& data, const std::str
|
|||
return match_types(prototype.type(), TypeVector(), data.type(), pfx);
|
||||
}
|
||||
|
||||
bool llsd_equals(const LLSD& lhs, const LLSD& rhs)
|
||||
bool llsd_equals(const LLSD& lhs, const LLSD& rhs, unsigned bits)
|
||||
{
|
||||
// We're comparing strict equality of LLSD representation rather than
|
||||
// performing any conversions. So if the types aren't equal, the LLSD
|
||||
|
|
@ -588,6 +589,20 @@ bool llsd_equals(const LLSD& lhs, const LLSD& rhs)
|
|||
// Both are TypeUndefined. There's nothing more to know.
|
||||
return true;
|
||||
|
||||
case LLSD::TypeReal:
|
||||
// This is where the 'bits' argument comes in handy. If passed
|
||||
// explicitly, it means to use is_approx_equal_fraction() to compare.
|
||||
if (bits >= 0)
|
||||
{
|
||||
return is_approx_equal_fraction(lhs.asReal(), rhs.asReal(), bits);
|
||||
}
|
||||
// Otherwise we compare bit representations, and the usual caveats
|
||||
// about comparing floating-point numbers apply. Omitting 'bits' when
|
||||
// comparing Real values is only useful when we expect identical bit
|
||||
// representation for a given Real value, e.g. for integer-valued
|
||||
// Reals.
|
||||
return (lhs.asReal() == rhs.asReal());
|
||||
|
||||
#define COMPARE_SCALAR(type) \
|
||||
case LLSD::Type##type: \
|
||||
/* LLSD::URI has operator!=() but not operator==() */ \
|
||||
|
|
@ -596,10 +611,6 @@ bool llsd_equals(const LLSD& lhs, const LLSD& rhs)
|
|||
|
||||
COMPARE_SCALAR(Boolean);
|
||||
COMPARE_SCALAR(Integer);
|
||||
// The usual caveats about comparing floating-point numbers apply. This is
|
||||
// only useful when we expect identical bit representation for a given
|
||||
// Real value, e.g. for integer-valued Reals.
|
||||
COMPARE_SCALAR(Real);
|
||||
COMPARE_SCALAR(String);
|
||||
COMPARE_SCALAR(UUID);
|
||||
COMPARE_SCALAR(Date);
|
||||
|
|
@ -617,7 +628,7 @@ bool llsd_equals(const LLSD& lhs, const LLSD& rhs)
|
|||
for ( ; lai != laend && rai != raend; ++lai, ++rai)
|
||||
{
|
||||
// If any one array element is unequal, the arrays are unequal.
|
||||
if (! llsd_equals(*lai, *rai))
|
||||
if (! llsd_equals(*lai, *rai, bits))
|
||||
return false;
|
||||
}
|
||||
// Here we've reached the end of one or the other array. They're equal
|
||||
|
|
@ -644,7 +655,7 @@ bool llsd_equals(const LLSD& lhs, const LLSD& rhs)
|
|||
if (rhskeys.erase(lmi->first) != 1)
|
||||
return false;
|
||||
// Both maps have the current key. Compare values.
|
||||
if (! llsd_equals(lmi->second, rhs[lmi->first]))
|
||||
if (! llsd_equals(lmi->second, rhs[lmi->first], bits))
|
||||
return false;
|
||||
}
|
||||
// We've now established that all the lhs keys have equal values in
|
||||
|
|
@ -657,7 +668,7 @@ bool llsd_equals(const LLSD& lhs, const LLSD& rhs)
|
|||
// We expect that every possible type() value is specifically handled
|
||||
// above. Failing to extend this switch to support a new LLSD type is
|
||||
// an error that must be brought to the coder's attention.
|
||||
LL_ERRS("llsd_equals") << "llsd_equals(" << lhs << ", " << rhs << "): "
|
||||
LL_ERRS("llsd_equals") << "llsd_equals(" << lhs << ", " << rhs << ", " << bits << "): "
|
||||
"unknown type " << lhs.type() << LL_ENDL;
|
||||
return false; // pacify the compiler
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,8 +123,10 @@ LL_COMMON_API BOOL compare_llsd_with_template(
|
|||
*/
|
||||
LL_COMMON_API std::string llsd_matches(const LLSD& prototype, const LLSD& data, const std::string& pfx="");
|
||||
|
||||
/// Deep equality
|
||||
LL_COMMON_API bool llsd_equals(const LLSD& lhs, const LLSD& rhs);
|
||||
/// Deep equality. If you want to compare LLSD::Real values for approximate
|
||||
/// equality rather than bitwise equality, pass @a bits as for
|
||||
/// is_approx_equal_fraction().
|
||||
LL_COMMON_API bool llsd_equals(const LLSD& lhs, const LLSD& rhs, unsigned bits=-1);
|
||||
|
||||
// Simple function to copy data out of input & output iterators if
|
||||
// there is no need for casting.
|
||||
|
|
@ -138,4 +140,283 @@ template<typename Input> LLSD llsd_copy_array(Input iter, Input end)
|
|||
return dest;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* LLSDArray
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* Construct an LLSD::Array inline, with implicit conversion to LLSD. Usage:
|
||||
*
|
||||
* @code
|
||||
* void somefunc(const LLSD&);
|
||||
* ...
|
||||
* somefunc(LLSDArray("text")(17)(3.14));
|
||||
* @endcode
|
||||
*
|
||||
* For completeness, LLSDArray() with no args constructs an empty array, so
|
||||
* <tt>LLSDArray()("text")(17)(3.14)</tt> produces an array equivalent to the
|
||||
* above. But for most purposes, LLSD() is already equivalent to an empty
|
||||
* array, and if you explicitly want an empty isArray(), there's
|
||||
* LLSD::emptyArray(). However, supporting a no-args LLSDArray() constructor
|
||||
* follows the principle of least astonishment.
|
||||
*/
|
||||
class LLSDArray
|
||||
{
|
||||
public:
|
||||
LLSDArray():
|
||||
_data(LLSD::emptyArray())
|
||||
{}
|
||||
|
||||
/**
|
||||
* Need an explicit copy constructor. Consider the following:
|
||||
*
|
||||
* @code
|
||||
* LLSD array_of_arrays(LLSDArray(LLSDArray(17)(34))
|
||||
* (LLSDArray("x")("y")));
|
||||
* @endcode
|
||||
*
|
||||
* The coder intends to construct [[17, 34], ["x", "y"]].
|
||||
*
|
||||
* With the compiler's implicit copy constructor, s/he gets instead
|
||||
* [17, 34, ["x", "y"]].
|
||||
*
|
||||
* The expression LLSDArray(17)(34) constructs an LLSDArray with those two
|
||||
* values. The reader assumes it should be converted to LLSD, as we always
|
||||
* want with LLSDArray, before passing it to the @em outer LLSDArray
|
||||
* constructor! This copy constructor makes that happen.
|
||||
*/
|
||||
LLSDArray(const LLSDArray& inner):
|
||||
_data(LLSD::emptyArray())
|
||||
{
|
||||
_data.append(inner);
|
||||
}
|
||||
|
||||
LLSDArray(const LLSD& value):
|
||||
_data(LLSD::emptyArray())
|
||||
{
|
||||
_data.append(value);
|
||||
}
|
||||
|
||||
LLSDArray& operator()(const LLSD& value)
|
||||
{
|
||||
_data.append(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator LLSD() const { return _data; }
|
||||
LLSD get() const { return _data; }
|
||||
|
||||
private:
|
||||
LLSD _data;
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* LLSDMap
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* Construct an LLSD::Map inline, with implicit conversion to LLSD. Usage:
|
||||
*
|
||||
* @code
|
||||
* void somefunc(const LLSD&);
|
||||
* ...
|
||||
* somefunc(LLSDMap("alpha", "abc")("number", 17)("pi", 3.14));
|
||||
* @endcode
|
||||
*
|
||||
* For completeness, LLSDMap() with no args constructs an empty map, so
|
||||
* <tt>LLSDMap()("alpha", "abc")("number", 17)("pi", 3.14)</tt> produces a map
|
||||
* equivalent to the above. But for most purposes, LLSD() is already
|
||||
* equivalent to an empty map, and if you explicitly want an empty isMap(),
|
||||
* there's LLSD::emptyMap(). However, supporting a no-args LLSDMap()
|
||||
* constructor follows the principle of least astonishment.
|
||||
*/
|
||||
class LLSDMap
|
||||
{
|
||||
public:
|
||||
LLSDMap():
|
||||
_data(LLSD::emptyMap())
|
||||
{}
|
||||
LLSDMap(const LLSD::String& key, const LLSD& value):
|
||||
_data(LLSD::emptyMap())
|
||||
{
|
||||
_data[key] = value;
|
||||
}
|
||||
|
||||
LLSDMap& operator()(const LLSD::String& key, const LLSD& value)
|
||||
{
|
||||
_data[key] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator LLSD() const { return _data; }
|
||||
LLSD get() const { return _data; }
|
||||
|
||||
private:
|
||||
LLSD _data;
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* LLSDParam
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* LLSDParam is a customization point for passing LLSD values to function
|
||||
* parameters of more or less arbitrary type. LLSD provides a small set of
|
||||
* native conversions; but if a generic algorithm explicitly constructs an
|
||||
* LLSDParam object in the function's argument list, a consumer can provide
|
||||
* LLSDParam specializations to support more different parameter types than
|
||||
* LLSD's native conversions.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* @code
|
||||
* void somefunc(const paramtype&);
|
||||
* ...
|
||||
* somefunc(..., LLSDParam<paramtype>(someLLSD), ...);
|
||||
* @endcode
|
||||
*/
|
||||
template <typename T>
|
||||
class LLSDParam
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Default implementation converts to T on construction, saves converted
|
||||
* value for later retrieval
|
||||
*/
|
||||
LLSDParam(const LLSD& value):
|
||||
_value(value)
|
||||
{}
|
||||
|
||||
operator T() const { return _value; }
|
||||
|
||||
private:
|
||||
T _value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Turns out that several target types could accept an LLSD param using any of
|
||||
* a few different conversions, e.g. LLUUID's constructor can accept LLUUID or
|
||||
* std::string. Therefore, the compiler can't decide which LLSD conversion
|
||||
* operator to choose, even though to us it seems obvious. But that's okay, we
|
||||
* can specialize LLSDParam for such target types, explicitly specifying the
|
||||
* desired conversion -- that's part of what LLSDParam is all about. Turns out
|
||||
* we have to do that enough to make it worthwhile generalizing. Use a macro
|
||||
* because I need to specify one of the asReal, etc., explicit conversion
|
||||
* methods as well as a type. If I'm overlooking a clever way to implement
|
||||
* that using a template instead, feel free to reimplement.
|
||||
*/
|
||||
#define LLSDParam_for(T, AS) \
|
||||
template <> \
|
||||
class LLSDParam<T> \
|
||||
{ \
|
||||
public: \
|
||||
LLSDParam(const LLSD& value): \
|
||||
_value(value.AS()) \
|
||||
{} \
|
||||
\
|
||||
operator T() const { return _value; } \
|
||||
\
|
||||
private: \
|
||||
T _value; \
|
||||
}
|
||||
|
||||
LLSDParam_for(float, asReal);
|
||||
LLSDParam_for(LLUUID, asUUID);
|
||||
LLSDParam_for(LLDate, asDate);
|
||||
LLSDParam_for(LLURI, asURI);
|
||||
LLSDParam_for(LLSD::Binary, asBinary);
|
||||
|
||||
/**
|
||||
* LLSDParam<const char*> is an example of the kind of conversion you can
|
||||
* support with LLSDParam beyond native LLSD conversions. Normally you can't
|
||||
* pass an LLSD object to a function accepting const char* -- but you can
|
||||
* safely pass an LLSDParam<const char*>(yourLLSD).
|
||||
*/
|
||||
template <>
|
||||
class LLSDParam<const char*>
|
||||
{
|
||||
private:
|
||||
// The difference here is that we store a std::string rather than a const
|
||||
// char*. It's important that the LLSDParam object own the std::string.
|
||||
std::string _value;
|
||||
// We don't bother storing the incoming LLSD object, but we do have to
|
||||
// distinguish whether _value is an empty string because the LLSD object
|
||||
// contains an empty string or because it's isUndefined().
|
||||
bool _undefined;
|
||||
|
||||
public:
|
||||
LLSDParam(const LLSD& value):
|
||||
_value(value),
|
||||
_undefined(value.isUndefined())
|
||||
{}
|
||||
|
||||
// The const char* we retrieve is for storage owned by our _value member.
|
||||
// That's how we guarantee that the const char* is valid for the lifetime
|
||||
// of this LLSDParam object. Constructing your LLSDParam in the argument
|
||||
// list should ensure that the LLSDParam object will persist for the
|
||||
// duration of the function call.
|
||||
operator const char*() const
|
||||
{
|
||||
if (_undefined)
|
||||
{
|
||||
// By default, an isUndefined() LLSD object's asString() method
|
||||
// will produce an empty string. But for a function accepting
|
||||
// const char*, it's often important to be able to pass NULL, and
|
||||
// isUndefined() seems like the best way. If you want to pass an
|
||||
// empty string, you can still pass LLSD(""). Without this special
|
||||
// case, though, no LLSD value could pass NULL.
|
||||
return NULL;
|
||||
}
|
||||
return _value.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
namespace llsd
|
||||
{
|
||||
|
||||
/*****************************************************************************
|
||||
* BOOST_FOREACH() helpers for LLSD
|
||||
*****************************************************************************/
|
||||
/// Usage: BOOST_FOREACH(LLSD item, inArray(someLLSDarray)) { ... }
|
||||
class inArray
|
||||
{
|
||||
public:
|
||||
inArray(const LLSD& array):
|
||||
_array(array)
|
||||
{}
|
||||
|
||||
typedef LLSD::array_const_iterator const_iterator;
|
||||
typedef LLSD::array_iterator iterator;
|
||||
|
||||
iterator begin() { return _array.beginArray(); }
|
||||
iterator end() { return _array.endArray(); }
|
||||
const_iterator begin() const { return _array.beginArray(); }
|
||||
const_iterator end() const { return _array.endArray(); }
|
||||
|
||||
private:
|
||||
LLSD _array;
|
||||
};
|
||||
|
||||
/// MapEntry is what you get from dereferencing an LLSD::map_[const_]iterator.
|
||||
typedef std::map<LLSD::String, LLSD>::value_type MapEntry;
|
||||
|
||||
/// Usage: BOOST_FOREACH([const] MapEntry& e, inMap(someLLSDmap)) { ... }
|
||||
class inMap
|
||||
{
|
||||
public:
|
||||
inMap(const LLSD& map):
|
||||
_map(map)
|
||||
{}
|
||||
|
||||
typedef LLSD::map_const_iterator const_iterator;
|
||||
typedef LLSD::map_iterator iterator;
|
||||
|
||||
iterator begin() { return _map.beginMap(); }
|
||||
iterator end() { return _map.endMap(); }
|
||||
const_iterator begin() const { return _map.beginMap(); }
|
||||
const_iterator end() const { return _map.endMap(); }
|
||||
|
||||
private:
|
||||
LLSD _map;
|
||||
};
|
||||
|
||||
} // namespace llsd
|
||||
|
||||
#endif // LL_LLSDUTIL_H
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -144,8 +144,10 @@ void LLPluginClassMedia::reset()
|
|||
mStatusText.clear();
|
||||
mProgressPercent = 0;
|
||||
mClickURL.clear();
|
||||
mClickNavType.clear();
|
||||
mClickTarget.clear();
|
||||
mClickUUID.clear();
|
||||
mStatusCode = 0;
|
||||
|
||||
// media_time class
|
||||
mCurrentTime = 0.0f;
|
||||
|
|
@ -1024,9 +1026,15 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
|
|||
else if(message_name == "click_nofollow")
|
||||
{
|
||||
mClickURL = message.getValue("uri");
|
||||
mClickNavType = message.getValue("nav_type");
|
||||
mClickTarget.clear();
|
||||
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW);
|
||||
}
|
||||
else if(message_name == "navigate_error_page")
|
||||
{
|
||||
mStatusCode = message.getValueS32("status_code");
|
||||
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_ERROR_PAGE);
|
||||
}
|
||||
else if(message_name == "cookie_set")
|
||||
{
|
||||
if(mOwner)
|
||||
|
|
@ -1192,16 +1200,6 @@ void LLPluginClassMedia::browse_back()
|
|||
sendMessage(message);
|
||||
}
|
||||
|
||||
void LLPluginClassMedia::set_status_redirect(int code, const std::string &url)
|
||||
{
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_status_redirect");
|
||||
|
||||
message.setValueS32("code", code);
|
||||
message.setValue("url", url);
|
||||
|
||||
sendMessage(message);
|
||||
}
|
||||
|
||||
void LLPluginClassMedia::setBrowserUserAgent(const std::string& user_agent)
|
||||
{
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_user_agent");
|
||||
|
|
|
|||
|
|
@ -199,7 +199,6 @@ public:
|
|||
void browse_reload(bool ignore_cache = false);
|
||||
void browse_forward();
|
||||
void browse_back();
|
||||
void set_status_redirect(int code, const std::string &url);
|
||||
void setBrowserUserAgent(const std::string& user_agent);
|
||||
void proxyWindowOpened(const std::string &target, const std::string &uuid);
|
||||
void proxyWindowClosed(const std::string &uuid);
|
||||
|
|
@ -227,11 +226,17 @@ public:
|
|||
// This is valid after MEDIA_EVENT_CLICK_LINK_HREF or MEDIA_EVENT_CLICK_LINK_NOFOLLOW
|
||||
std::string getClickURL() const { return mClickURL; };
|
||||
|
||||
// This is valid after MEDIA_EVENT_CLICK_LINK_NOFOLLOW
|
||||
std::string getClickNavType() const { return mClickNavType; };
|
||||
|
||||
// This is valid after MEDIA_EVENT_CLICK_LINK_HREF
|
||||
std::string getClickTarget() const { return mClickTarget; };
|
||||
|
||||
// This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE
|
||||
std::string getClickUUID() const { return mClickUUID; };
|
||||
|
||||
// This is valid after MEDIA_EVENT_NAVIGATE_ERROR_PAGE
|
||||
S32 getStatusCode() const { return mStatusCode; };
|
||||
|
||||
// These are valid during MEDIA_EVENT_GEOMETRY_CHANGE
|
||||
S32 getGeometryX() const { return mGeometryX; };
|
||||
|
|
@ -378,12 +383,14 @@ protected:
|
|||
int mProgressPercent;
|
||||
std::string mLocation;
|
||||
std::string mClickURL;
|
||||
std::string mClickNavType;
|
||||
std::string mClickTarget;
|
||||
std::string mClickUUID;
|
||||
S32 mGeometryX;
|
||||
S32 mGeometryY;
|
||||
S32 mGeometryWidth;
|
||||
S32 mGeometryHeight;
|
||||
S32 mStatusCode;
|
||||
std::string mAuthURL;
|
||||
std::string mAuthRealm;
|
||||
std::string mHoverText;
|
||||
|
|
|
|||
|
|
@ -52,12 +52,13 @@ public:
|
|||
MEDIA_EVENT_STATUS_TEXT_CHANGED, // browser has updated the status text
|
||||
MEDIA_EVENT_NAME_CHANGED, // browser has updated the name of the media (typically <title> tag)
|
||||
MEDIA_EVENT_LOCATION_CHANGED, // browser location (URL) has changed (maybe due to internal navagation/frames/etc)
|
||||
MEDIA_EVENT_NAVIGATE_ERROR_PAGE, // browser navigated to a page that resulted in an HTTP error
|
||||
MEDIA_EVENT_CLICK_LINK_HREF, // I'm not entirely sure what the semantics of these two are
|
||||
MEDIA_EVENT_CLICK_LINK_NOFOLLOW,
|
||||
MEDIA_EVENT_CLOSE_REQUEST, // The plugin requested its window be closed (currently hooked up to javascript window.close in webkit)
|
||||
MEDIA_EVENT_PICK_FILE_REQUEST, // The plugin wants the user to pick a file
|
||||
MEDIA_EVENT_GEOMETRY_CHANGE, // The plugin requested its window geometry be changed (per the javascript window interface)
|
||||
|
||||
|
||||
MEDIA_EVENT_PLUGIN_FAILED_LAUNCH, // The plugin failed to launch
|
||||
MEDIA_EVENT_PLUGIN_FAILED, // The plugin died unexpectedly
|
||||
|
||||
|
|
|
|||
|
|
@ -57,9 +57,12 @@
|
|||
BOOL gDebugSession = FALSE;
|
||||
BOOL gDebugGL = FALSE;
|
||||
BOOL gClothRipple = FALSE;
|
||||
BOOL gNoRender = FALSE;
|
||||
BOOL gHeadlessClient = FALSE;
|
||||
BOOL gGLActive = FALSE;
|
||||
|
||||
static const std::string HEADLESS_VENDOR_STRING("Linden Lab");
|
||||
static const std::string HEADLESS_RENDERER_STRING("Headless");
|
||||
static const std::string HEADLESS_VERSION_STRING("1.0");
|
||||
|
||||
std::ofstream gFailLog;
|
||||
|
||||
|
|
@ -538,9 +541,19 @@ void LLGLManager::setToDebugGPU()
|
|||
|
||||
void LLGLManager::getGLInfo(LLSD& info)
|
||||
{
|
||||
info["GLInfo"]["GLVendor"] = std::string((const char *)glGetString(GL_VENDOR));
|
||||
info["GLInfo"]["GLRenderer"] = std::string((const char *)glGetString(GL_RENDERER));
|
||||
info["GLInfo"]["GLVersion"] = std::string((const char *)glGetString(GL_VERSION));
|
||||
if (gHeadlessClient)
|
||||
{
|
||||
info["GLInfo"]["GLVendor"] = HEADLESS_VENDOR_STRING;
|
||||
info["GLInfo"]["GLRenderer"] = HEADLESS_RENDERER_STRING;
|
||||
info["GLInfo"]["GLVersion"] = HEADLESS_VERSION_STRING;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
info["GLInfo"]["GLVendor"] = std::string((const char *)glGetString(GL_VENDOR));
|
||||
info["GLInfo"]["GLRenderer"] = std::string((const char *)glGetString(GL_RENDERER));
|
||||
info["GLInfo"]["GLVersion"] = std::string((const char *)glGetString(GL_VERSION));
|
||||
}
|
||||
|
||||
#if !LL_MESA_HEADLESS
|
||||
std::string all_exts = ll_safe_string((const char *)gGLHExts.mSysExts);
|
||||
|
|
@ -556,14 +569,22 @@ void LLGLManager::getGLInfo(LLSD& info)
|
|||
std::string LLGLManager::getGLInfoString()
|
||||
{
|
||||
std::string info_str;
|
||||
std::string all_exts, line;
|
||||
|
||||
info_str += std::string("GL_VENDOR ") + ll_safe_string((const char *)glGetString(GL_VENDOR)) + std::string("\n");
|
||||
info_str += std::string("GL_RENDERER ") + ll_safe_string((const char *)glGetString(GL_RENDERER)) + std::string("\n");
|
||||
info_str += std::string("GL_VERSION ") + ll_safe_string((const char *)glGetString(GL_VERSION)) + std::string("\n");
|
||||
if (gHeadlessClient)
|
||||
{
|
||||
info_str += std::string("GL_VENDOR ") + HEADLESS_VENDOR_STRING + std::string("\n");
|
||||
info_str += std::string("GL_RENDERER ") + HEADLESS_RENDERER_STRING + std::string("\n");
|
||||
info_str += std::string("GL_VERSION ") + HEADLESS_VERSION_STRING + std::string("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
info_str += std::string("GL_VENDOR ") + ll_safe_string((const char *)glGetString(GL_VENDOR)) + std::string("\n");
|
||||
info_str += std::string("GL_RENDERER ") + ll_safe_string((const char *)glGetString(GL_RENDERER)) + std::string("\n");
|
||||
info_str += std::string("GL_VERSION ") + ll_safe_string((const char *)glGetString(GL_VERSION)) + std::string("\n");
|
||||
}
|
||||
|
||||
#if !LL_MESA_HEADLESS
|
||||
all_exts = (const char *)gGLHExts.mSysExts;
|
||||
std::string all_exts= ll_safe_string(((const char *)gGLHExts.mSysExts));
|
||||
LLStringUtil::replaceChar(all_exts, ' ', '\n');
|
||||
info_str += std::string("GL_EXTENSIONS:\n") + all_exts + std::string("\n");
|
||||
#endif
|
||||
|
|
@ -573,15 +594,21 @@ std::string LLGLManager::getGLInfoString()
|
|||
|
||||
void LLGLManager::printGLInfoString()
|
||||
{
|
||||
std::string info_str;
|
||||
std::string all_exts, line;
|
||||
|
||||
LL_INFOS("RenderInit") << "GL_VENDOR: " << ((const char *)glGetString(GL_VENDOR)) << LL_ENDL;
|
||||
LL_INFOS("RenderInit") << "GL_RENDERER: " << ((const char *)glGetString(GL_RENDERER)) << LL_ENDL;
|
||||
LL_INFOS("RenderInit") << "GL_VERSION: " << ((const char *)glGetString(GL_VERSION)) << LL_ENDL;
|
||||
if (gHeadlessClient)
|
||||
{
|
||||
LL_INFOS("RenderInit") << "GL_VENDOR: " << HEADLESS_VENDOR_STRING << LL_ENDL;
|
||||
LL_INFOS("RenderInit") << "GL_RENDERER: " << HEADLESS_RENDERER_STRING << LL_ENDL;
|
||||
LL_INFOS("RenderInit") << "GL_VERSION: " << HEADLESS_VERSION_STRING << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS("RenderInit") << "GL_VENDOR: " << ((const char *)glGetString(GL_VENDOR)) << LL_ENDL;
|
||||
LL_INFOS("RenderInit") << "GL_RENDERER: " << ((const char *)glGetString(GL_RENDERER)) << LL_ENDL;
|
||||
LL_INFOS("RenderInit") << "GL_VERSION: " << ((const char *)glGetString(GL_VERSION)) << LL_ENDL;
|
||||
}
|
||||
|
||||
#if !LL_MESA_HEADLESS
|
||||
all_exts = std::string(gGLHExts.mSysExts);
|
||||
std::string all_exts= ll_safe_string(((const char *)gGLHExts.mSysExts));
|
||||
LLStringUtil::replaceChar(all_exts, ' ', '\n');
|
||||
LL_DEBUGS("RenderInit") << "GL_EXTENSIONS:\n" << all_exts << LL_ENDL;
|
||||
#endif
|
||||
|
|
@ -590,7 +617,14 @@ void LLGLManager::printGLInfoString()
|
|||
std::string LLGLManager::getRawGLString()
|
||||
{
|
||||
std::string gl_string;
|
||||
gl_string = ll_safe_string((char*)glGetString(GL_VENDOR)) + " " + ll_safe_string((char*)glGetString(GL_RENDERER));
|
||||
if (gHeadlessClient)
|
||||
{
|
||||
gl_string = HEADLESS_VENDOR_STRING + " " + HEADLESS_RENDERER_STRING;
|
||||
}
|
||||
else
|
||||
{
|
||||
gl_string = ll_safe_string((char*)glGetString(GL_VENDOR)) + " " + ll_safe_string((char*)glGetString(GL_RENDERER));
|
||||
}
|
||||
return gl_string;
|
||||
}
|
||||
|
||||
|
|
@ -614,47 +648,47 @@ void LLGLManager::initExtensions()
|
|||
mHasMultitexture = TRUE;
|
||||
# else
|
||||
mHasMultitexture = FALSE;
|
||||
# endif
|
||||
# endif // GL_ARB_multitexture
|
||||
# ifdef GL_ARB_texture_env_combine
|
||||
mHasARBEnvCombine = TRUE;
|
||||
# else
|
||||
mHasARBEnvCombine = FALSE;
|
||||
# endif
|
||||
# endif // GL_ARB_texture_env_combine
|
||||
# ifdef GL_ARB_texture_compression
|
||||
mHasCompressedTextures = TRUE;
|
||||
# else
|
||||
mHasCompressedTextures = FALSE;
|
||||
# endif
|
||||
# endif // GL_ARB_texture_compression
|
||||
# ifdef GL_ARB_vertex_buffer_object
|
||||
mHasVertexBufferObject = TRUE;
|
||||
# else
|
||||
mHasVertexBufferObject = FALSE;
|
||||
# endif
|
||||
# endif // GL_ARB_vertex_buffer_object
|
||||
# ifdef GL_EXT_framebuffer_object
|
||||
mHasFramebufferObject = TRUE;
|
||||
# else
|
||||
mHasFramebufferObject = FALSE;
|
||||
# endif
|
||||
# endif // GL_EXT_framebuffer_object
|
||||
# ifdef GL_EXT_framebuffer_multisample
|
||||
mHasFramebufferMultisample = TRUE;
|
||||
# else
|
||||
mHasFramebufferMultisample = FALSE;
|
||||
# endif
|
||||
# endif // GL_EXT_framebuffer_multisample
|
||||
# ifdef GL_ARB_draw_buffers
|
||||
mHasDrawBuffers = TRUE;
|
||||
#else
|
||||
mHasDrawBuffers = FALSE;
|
||||
# endif
|
||||
# endif // GL_ARB_draw_buffers
|
||||
# if defined(GL_NV_depth_clamp) || defined(GL_ARB_depth_clamp)
|
||||
mHasDepthClamp = TRUE;
|
||||
#else
|
||||
mHasDepthClamp = FALSE;
|
||||
#endif
|
||||
#endif // defined(GL_NV_depth_clamp) || defined(GL_ARB_depth_clamp)
|
||||
# if GL_EXT_blend_func_separate
|
||||
mHasBlendFuncSeparate = TRUE;
|
||||
#else
|
||||
mHasBlendFuncSeparate = FALSE;
|
||||
# endif
|
||||
# endif // GL_EXT_blend_func_separate
|
||||
mHasMipMapGeneration = FALSE;
|
||||
mHasSeparateSpecularColor = FALSE;
|
||||
mHasAnisotropic = FALSE;
|
||||
|
|
@ -1145,7 +1179,7 @@ void assert_glerror()
|
|||
}
|
||||
}
|
||||
|
||||
if (!gNoRender && gDebugGL)
|
||||
if (gDebugGL)
|
||||
{
|
||||
do_assert_glerror();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -415,7 +415,7 @@ void set_binormals(const S32 index, const U32 stride, const LLVector3 *binormals
|
|||
void parse_gl_version( S32* major, S32* minor, S32* release, std::string* vendor_specific );
|
||||
|
||||
extern BOOL gClothRipple;
|
||||
extern BOOL gNoRender;
|
||||
extern BOOL gHeadlessClient;
|
||||
extern BOOL gGLActive;
|
||||
|
||||
#endif // LL_LLGL_H
|
||||
|
|
|
|||
|
|
@ -967,12 +967,14 @@ BOOL LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3
|
|||
}
|
||||
if (mTexName == 0)
|
||||
{
|
||||
llwarns << "Setting subimage on image without GL texture" << llendl;
|
||||
// *TODO: Re-enable warning? Ran into thread locking issues? DK 2011-02-18
|
||||
//llwarns << "Setting subimage on image without GL texture" << llendl;
|
||||
return FALSE;
|
||||
}
|
||||
if (datap == NULL)
|
||||
{
|
||||
llwarns << "Setting subimage on image with NULL datap" << llendl;
|
||||
// *TODO: Re-enable warning? Ran into thread locking issues? DK 2011-02-18
|
||||
//llwarns << "Setting subimage on image with NULL datap" << llendl;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -1100,6 +1102,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
|
|||
//the texture is assiciate with some image by calling glTexImage outside LLImageGL
|
||||
BOOL LLImageGL::createGLTexture()
|
||||
{
|
||||
if (gHeadlessClient) return FALSE;
|
||||
if (gGLManager.mIsDisabled)
|
||||
{
|
||||
llwarns << "Trying to create a texture while GL is disabled!" << llendl;
|
||||
|
|
@ -1128,6 +1131,7 @@ BOOL LLImageGL::createGLTexture()
|
|||
|
||||
BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename/*=0*/, BOOL to_create, S32 category)
|
||||
{
|
||||
if (gHeadlessClient) return FALSE;
|
||||
if (gGLManager.mIsDisabled)
|
||||
{
|
||||
llwarns << "Trying to create a texture while GL is disabled!" << llendl;
|
||||
|
|
|
|||
|
|
@ -60,6 +60,11 @@ LLFloaterRegListener::LLFloaterRegListener():
|
|||
"Ask to toggle the state of the floater specified in [\"name\"]",
|
||||
&LLFloaterRegListener::toggleInstance,
|
||||
requiredName);
|
||||
add("instanceVisible",
|
||||
"Return on [\"reply\"] an event whose [\"visible\"] indicates the visibility "
|
||||
"of the floater specified in [\"name\"]",
|
||||
&LLFloaterRegListener::instanceVisible,
|
||||
requiredName);
|
||||
LLSD requiredNameButton;
|
||||
requiredNameButton["name"] = LLSD();
|
||||
requiredNameButton["button"] = LLSD();
|
||||
|
|
@ -71,9 +76,7 @@ LLFloaterRegListener::LLFloaterRegListener():
|
|||
|
||||
void LLFloaterRegListener::getBuildMap(const LLSD& event) const
|
||||
{
|
||||
// Honor the "reqid" convention by echoing event["reqid"] in our reply packet.
|
||||
LLReqID reqID(event);
|
||||
LLSD reply(reqID.makeResponse());
|
||||
LLSD reply;
|
||||
// Build an LLSD map that mirrors sBuildMap. Since we have no good way to
|
||||
// represent a C++ callable in LLSD, the only part of BuildData we can
|
||||
// store is the filename. For each LLSD map entry, it would be more
|
||||
|
|
@ -86,7 +89,7 @@ void LLFloaterRegListener::getBuildMap(const LLSD& event) const
|
|||
reply[mi->first] = mi->second.mFile;
|
||||
}
|
||||
// Send the reply to the LLEventPump named in event["reply"].
|
||||
LLEventPumps::instance().obtain(event["reply"]).post(reply);
|
||||
sendReply(reply, event);
|
||||
}
|
||||
|
||||
void LLFloaterRegListener::showInstance(const LLSD& event) const
|
||||
|
|
@ -104,6 +107,12 @@ void LLFloaterRegListener::toggleInstance(const LLSD& event) const
|
|||
LLFloaterReg::toggleInstance(event["name"], event["key"]);
|
||||
}
|
||||
|
||||
void LLFloaterRegListener::instanceVisible(const LLSD& event) const
|
||||
{
|
||||
sendReply(LLSDMap("visible", LLFloaterReg::instanceVisible(event["name"], event["key"])),
|
||||
event);
|
||||
}
|
||||
|
||||
void LLFloaterRegListener::clickButton(const LLSD& event) const
|
||||
{
|
||||
// If the caller requests a reply, build the reply.
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ private:
|
|||
void showInstance(const LLSD& event) const;
|
||||
void hideInstance(const LLSD& event) const;
|
||||
void toggleInstance(const LLSD& event) const;
|
||||
void instanceVisible(const LLSD& event) const;
|
||||
void clickButton(const LLSD& event) const;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ public:
|
|||
|
||||
void setColor(const LLColor4& color) { mColor = color; }
|
||||
void setImage(LLPointer<LLUIImage> image) { mImagep = image; }
|
||||
const LLPointer<LLUIImage> getImage() { return mImagep; }
|
||||
|
||||
private:
|
||||
void setIconImageDrawSize() ;
|
||||
|
|
|
|||
|
|
@ -2290,3 +2290,8 @@ void LLLineEditor::setContextMenu(LLContextMenu* new_context_menu)
|
|||
else
|
||||
mContextMenuHandle.markDead();
|
||||
}
|
||||
|
||||
void LLLineEditor::setFont(const LLFontGL* font)
|
||||
{
|
||||
mGLFont = font;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -201,6 +201,7 @@ public:
|
|||
const LLColor4& getTentativeFgColor() const { return mTentativeFgColor.get(); }
|
||||
|
||||
const LLFontGL* getFont() const { return mGLFont; }
|
||||
void setFont(const LLFontGL* font);
|
||||
|
||||
void setIgnoreArrowKeys(BOOL b) { mIgnoreArrowKeys = b; }
|
||||
void setIgnoreTab(BOOL b) { mIgnoreTab = b; }
|
||||
|
|
|
|||
|
|
@ -3105,9 +3105,6 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
|
|||
CURSOR_HEIGHT + MOUSE_CURSOR_PADDING * 2);
|
||||
menu->translateIntoRectWithExclusion( menu_region_rect, mouse_rect, FALSE );
|
||||
menu->getParent()->sendChildToFront(menu);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
///============================================================================
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@
|
|||
// for XUIParse
|
||||
#include "llquaternion.h"
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <boost/algorithm/string/find_iterator.hpp>
|
||||
#include <boost/algorithm/string/finder.hpp>
|
||||
|
||||
//
|
||||
// Globals
|
||||
|
|
@ -2020,6 +2022,53 @@ void LLUI::positionViewNearMouse(LLView* view, S32 spawn_x, S32 spawn_y)
|
|||
view->translateIntoRectWithExclusion( virtual_window_rect, mouse_rect, FALSE );
|
||||
}
|
||||
|
||||
LLView* LLUI::resolvePath(LLView* context, const std::string& path)
|
||||
{
|
||||
// Nothing about resolvePath() should require non-const LLView*. If caller
|
||||
// wants non-const, call the const flavor and then cast away const-ness.
|
||||
return const_cast<LLView*>(resolvePath(const_cast<const LLView*>(context), path));
|
||||
}
|
||||
|
||||
const LLView* LLUI::resolvePath(const LLView* context, const std::string& path)
|
||||
{
|
||||
// Create an iterator over slash-separated parts of 'path'. Dereferencing
|
||||
// this iterator returns an iterator_range over the substring. Unlike
|
||||
// LLStringUtil::getTokens(), this split_iterator doesn't combine adjacent
|
||||
// delimiters: leading/trailing slash produces an empty substring, double
|
||||
// slash produces an empty substring. That's what we need.
|
||||
boost::split_iterator<std::string::const_iterator> ti(path, boost::first_finder("/")), tend;
|
||||
|
||||
if (ti == tend)
|
||||
{
|
||||
// 'path' is completely empty, no navigation
|
||||
return context;
|
||||
}
|
||||
|
||||
// leading / means "start at root"
|
||||
if (ti->empty())
|
||||
{
|
||||
context = getRootView();
|
||||
++ti;
|
||||
}
|
||||
|
||||
bool recurse = false;
|
||||
for (; ti != tend && context; ++ti)
|
||||
{
|
||||
if (ti->empty())
|
||||
{
|
||||
recurse = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string part(ti->begin(), ti->end());
|
||||
context = context->findChildView(part, recurse);
|
||||
recurse = false;
|
||||
}
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
// LLLocalClipRect and LLScreenClipRect moved to lllocalcliprect.h/cpp
|
||||
|
||||
|
|
|
|||
|
|
@ -185,6 +185,33 @@ public:
|
|||
//helper functions (should probably move free standing rendering helper functions here)
|
||||
static LLView* getRootView() { return sRootView; }
|
||||
static void setRootView(LLView* view) { sRootView = view; }
|
||||
/**
|
||||
* Walk the LLView tree to resolve a path
|
||||
* Paths can be discovered using Develop > XUI > Show XUI Paths
|
||||
*
|
||||
* A leading "/" indicates the root of the tree is the starting
|
||||
* position of the search, (otherwise the context node is used)
|
||||
*
|
||||
* Adjacent "//" mean that the next level of the search is done
|
||||
* recursively ("descendant" rather than "child").
|
||||
*
|
||||
* Return values: If no match is found, NULL is returned,
|
||||
* otherwise the matching LLView* is returned.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* "/" -> return the root view
|
||||
* "/foo" -> find "foo" as a direct child of the root
|
||||
* "foo" -> find "foo" as a direct child of the context node
|
||||
* "//foo" -> find the first "foo" child anywhere in the tree
|
||||
* "/foo/bar" -> find "foo" as direct child of the root, and
|
||||
* "bar" as a direct child of "foo"
|
||||
* "//foo//bar/baz" -> find the first "foo" anywhere in the
|
||||
* tree, the first "bar" anywhere under it, and "baz"
|
||||
* as a direct child of that
|
||||
*/
|
||||
static const LLView* resolvePath(const LLView* context, const std::string& path);
|
||||
static LLView* resolvePath(LLView* context, const std::string& path);
|
||||
static std::string locateSkin(const std::string& filename);
|
||||
static void setMousePositionScreen(S32 x, S32 y);
|
||||
static void getMousePositionScreen(S32 *x, S32 *y);
|
||||
|
|
|
|||
|
|
@ -35,16 +35,20 @@ include_directories(
|
|||
|
||||
set(llwindow_SOURCE_FILES
|
||||
llkeyboard.cpp
|
||||
llkeyboardheadless.cpp
|
||||
llwindowheadless.cpp
|
||||
llwindowcallbacks.cpp
|
||||
llwindowlistener.cpp
|
||||
)
|
||||
|
||||
set(llwindow_HEADER_FILES
|
||||
CMakeLists.txt
|
||||
|
||||
llkeyboard.h
|
||||
llkeyboardheadless.h
|
||||
llwindowheadless.h
|
||||
llwindowcallbacks.h
|
||||
llwindowlistener.h
|
||||
)
|
||||
|
||||
set(viewer_SOURCE_FILES
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* @file llkeyboardheadless.cpp
|
||||
* @brief Handler for assignable key bindings
|
||||
*
|
||||
* $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$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llkeyboardheadless.h"
|
||||
#include "llwindowcallbacks.h"
|
||||
|
||||
LLKeyboardHeadless::LLKeyboardHeadless()
|
||||
{ }
|
||||
|
||||
void LLKeyboardHeadless::resetMaskKeys()
|
||||
{ }
|
||||
|
||||
|
||||
BOOL LLKeyboardHeadless::handleKeyDown(const U16 key, const U32 mask)
|
||||
{ return FALSE; }
|
||||
|
||||
|
||||
BOOL LLKeyboardHeadless::handleKeyUp(const U16 key, const U32 mask)
|
||||
{ return FALSE; }
|
||||
|
||||
MASK LLKeyboardHeadless::currentMask(BOOL for_mouse_event)
|
||||
{ return MASK_NONE; }
|
||||
|
||||
void LLKeyboardHeadless::scanKeyboard()
|
||||
{ }
|
||||
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* @file llkeyboardheadless.h
|
||||
* @brief Handler for assignable key bindings
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&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_LLKEYBOARDHEADLESS_H
|
||||
#define LL_LLKEYBOARDHEADLESS_H
|
||||
|
||||
#include "llkeyboard.h"
|
||||
|
||||
class LLKeyboardHeadless : public LLKeyboard
|
||||
{
|
||||
public:
|
||||
LLKeyboardHeadless();
|
||||
/*virtual*/ ~LLKeyboardHeadless() {};
|
||||
|
||||
/*virtual*/ BOOL handleKeyUp(const U16 key, MASK mask);
|
||||
/*virtual*/ BOOL handleKeyDown(const U16 key, MASK mask);
|
||||
/*virtual*/ void resetMaskKeys();
|
||||
/*virtual*/ MASK currentMask(BOOL for_mouse_event);
|
||||
/*virtual*/ void scanKeyboard();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -41,6 +41,8 @@
|
|||
#include "llkeyboard.h"
|
||||
#include "linked_lists.h"
|
||||
#include "llwindowcallbacks.h"
|
||||
#include "llwindowlistener.h"
|
||||
#include <boost/lambda/core.hpp>
|
||||
|
||||
|
||||
//
|
||||
|
|
@ -115,10 +117,19 @@ LLWindow::LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags)
|
|||
mHideCursorPermanent(FALSE),
|
||||
mFlags(flags),
|
||||
mHighSurrogate(0)
|
||||
{ }
|
||||
{
|
||||
// gKeyboard is still NULL, so it doesn't do LLWindowListener any good to
|
||||
// pass its value right now. Instead, pass it a nullary function that
|
||||
// will, when we later need it, return the value of gKeyboard.
|
||||
// boost::lambda::var() constructs such a functor on the fly.
|
||||
mListener = new LLWindowListener(callbacks, boost::lambda::var(gKeyboard));
|
||||
}
|
||||
|
||||
LLWindow::~LLWindow()
|
||||
{ }
|
||||
{
|
||||
delete mListener;
|
||||
mListener = NULL;
|
||||
}
|
||||
|
||||
//virtual
|
||||
BOOL LLWindow::isValid()
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
class LLSplashScreen;
|
||||
class LLPreeditor;
|
||||
class LLWindowCallbacks;
|
||||
class LLWindowListener;
|
||||
|
||||
// Refer to llwindow_test in test/common/llwindow for usage example
|
||||
|
||||
|
|
@ -188,6 +189,7 @@ protected:
|
|||
BOOL mHideCursorPermanent;
|
||||
U32 mFlags;
|
||||
U16 mHighSurrogate;
|
||||
LLWindowListener* mListener;
|
||||
|
||||
// Handle a UTF-16 encoding unit received from keyboard.
|
||||
// Converting the series of UTF-16 encoding units to UTF-32 data,
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "indra_constants.h"
|
||||
|
||||
#include "llwindowheadless.h"
|
||||
#include "llkeyboardheadless.h"
|
||||
|
||||
//
|
||||
// LLWindowHeadless
|
||||
|
|
@ -37,6 +38,9 @@ LLWindowHeadless::LLWindowHeadless(LLWindowCallbacks* callbacks, const std::stri
|
|||
BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth)
|
||||
: LLWindow(callbacks, fullscreen, flags)
|
||||
{
|
||||
// Initialize a headless keyboard.
|
||||
gKeyboard = new LLKeyboardHeadless();
|
||||
gKeyboard->setCallbacks(callbacks);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,307 @@
|
|||
/**
|
||||
* @file llwindowlistener.cpp
|
||||
* @brief EventAPI interface for injecting input into LLWindow
|
||||
*
|
||||
* $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$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llwindowlistener.h"
|
||||
|
||||
#include "llcoord.h"
|
||||
#include "llkeyboard.h"
|
||||
#include "llwindowcallbacks.h"
|
||||
#include <map>
|
||||
|
||||
LLWindowListener::LLWindowListener(LLWindowCallbacks *window, const KeyboardGetter& kbgetter)
|
||||
: LLEventAPI("LLWindow", "Inject input events into the LLWindow instance"),
|
||||
mWindow(window),
|
||||
mKbGetter(kbgetter)
|
||||
{
|
||||
std::string keySomething =
|
||||
"Given [\"keysym\"], [\"keycode\"] or [\"char\"], inject the specified ";
|
||||
std::string keyExplain =
|
||||
"(integer keycode values, or keysym \"XXXX\" from any KEY_XXXX, in\n"
|
||||
"http://hg.secondlife.com/viewer-development/src/tip/indra/llcommon/indra_constants.h )";
|
||||
std::string mask =
|
||||
"Specify optional [\"mask\"] as an array containing any of \"CONTROL\", \"ALT\",\n"
|
||||
"\"SHIFT\" or \"MAC_CONTROL\"; the corresponding modifier bits will be combined\n"
|
||||
"to form the mask used with the event.";
|
||||
|
||||
std::string mouseSomething =
|
||||
"Given [\"button\"], [\"x\"] and [\"y\"], inject the given mouse ";
|
||||
std::string mouseExplain =
|
||||
"(button values \"LEFT\", \"MIDDLE\", \"RIGHT\")";
|
||||
|
||||
add("keyDown",
|
||||
keySomething + "keypress event.\n" + keyExplain + '\n' + mask,
|
||||
&LLWindowListener::keyDown);
|
||||
add("keyUp",
|
||||
keySomething + "key release event.\n" + keyExplain + '\n' + mask,
|
||||
&LLWindowListener::keyUp);
|
||||
add("mouseDown",
|
||||
mouseSomething + "click event.\n" + mouseExplain + '\n' + mask,
|
||||
&LLWindowListener::mouseDown);
|
||||
add("mouseUp",
|
||||
mouseSomething + "release event.\n" + mouseExplain + '\n' + mask,
|
||||
&LLWindowListener::mouseUp);
|
||||
add("mouseMove",
|
||||
std::string("Given [\"x\"] and [\"y\"], inject the given mouse movement event.\n") +
|
||||
mask,
|
||||
&LLWindowListener::mouseMove);
|
||||
add("mouseScroll",
|
||||
"Given an integer number of [\"clicks\"], inject the given mouse scroll event.\n"
|
||||
"(positive clicks moves downward through typical content)",
|
||||
&LLWindowListener::mouseScroll);
|
||||
}
|
||||
|
||||
template <typename MAPPED>
|
||||
class StringLookup
|
||||
{
|
||||
private:
|
||||
std::string mDesc;
|
||||
typedef std::map<std::string, MAPPED> Map;
|
||||
Map mMap;
|
||||
|
||||
public:
|
||||
StringLookup(const std::string& desc): mDesc(desc) {}
|
||||
|
||||
MAPPED lookup(const typename Map::key_type& key) const
|
||||
{
|
||||
typename Map::const_iterator found = mMap.find(key);
|
||||
if (found == mMap.end())
|
||||
{
|
||||
LL_WARNS("LLWindowListener") << "Unknown " << mDesc << " '" << key << "'" << LL_ENDL;
|
||||
return MAPPED();
|
||||
}
|
||||
return found->second;
|
||||
}
|
||||
|
||||
protected:
|
||||
void add(const typename Map::key_type& key, const typename Map::mapped_type& value)
|
||||
{
|
||||
mMap.insert(typename Map::value_type(key, value));
|
||||
}
|
||||
};
|
||||
|
||||
// for WhichKeysym. KeyProxy is like the typedef KEY, except that KeyProxy()
|
||||
// (default-constructed) is guaranteed to have the value KEY_NONE.
|
||||
class KeyProxy
|
||||
{
|
||||
public:
|
||||
KeyProxy(KEY k): mKey(k) {}
|
||||
KeyProxy(): mKey(KEY_NONE) {}
|
||||
operator KEY() const { return mKey; }
|
||||
|
||||
private:
|
||||
KEY mKey;
|
||||
};
|
||||
|
||||
struct WhichKeysym: public StringLookup<KeyProxy>
|
||||
{
|
||||
WhichKeysym(): StringLookup<KeyProxy>("keysym")
|
||||
{
|
||||
add("RETURN", KEY_RETURN);
|
||||
add("LEFT", KEY_LEFT);
|
||||
add("RIGHT", KEY_RIGHT);
|
||||
add("UP", KEY_UP);
|
||||
add("DOWN", KEY_DOWN);
|
||||
add("ESCAPE", KEY_ESCAPE);
|
||||
add("BACKSPACE", KEY_BACKSPACE);
|
||||
add("DELETE", KEY_DELETE);
|
||||
add("SHIFT", KEY_SHIFT);
|
||||
add("CONTROL", KEY_CONTROL);
|
||||
add("ALT", KEY_ALT);
|
||||
add("HOME", KEY_HOME);
|
||||
add("END", KEY_END);
|
||||
add("PAGE_UP", KEY_PAGE_UP);
|
||||
add("PAGE_DOWN", KEY_PAGE_DOWN);
|
||||
add("HYPHEN", KEY_HYPHEN);
|
||||
add("EQUALS", KEY_EQUALS);
|
||||
add("INSERT", KEY_INSERT);
|
||||
add("CAPSLOCK", KEY_CAPSLOCK);
|
||||
add("TAB", KEY_TAB);
|
||||
add("ADD", KEY_ADD);
|
||||
add("SUBTRACT", KEY_SUBTRACT);
|
||||
add("MULTIPLY", KEY_MULTIPLY);
|
||||
add("DIVIDE", KEY_DIVIDE);
|
||||
add("F1", KEY_F1);
|
||||
add("F2", KEY_F2);
|
||||
add("F3", KEY_F3);
|
||||
add("F4", KEY_F4);
|
||||
add("F5", KEY_F5);
|
||||
add("F6", KEY_F6);
|
||||
add("F7", KEY_F7);
|
||||
add("F8", KEY_F8);
|
||||
add("F9", KEY_F9);
|
||||
add("F10", KEY_F10);
|
||||
add("F11", KEY_F11);
|
||||
add("F12", KEY_F12);
|
||||
|
||||
add("PAD_UP", KEY_PAD_UP);
|
||||
add("PAD_DOWN", KEY_PAD_DOWN);
|
||||
add("PAD_LEFT", KEY_PAD_LEFT);
|
||||
add("PAD_RIGHT", KEY_PAD_RIGHT);
|
||||
add("PAD_HOME", KEY_PAD_HOME);
|
||||
add("PAD_END", KEY_PAD_END);
|
||||
add("PAD_PGUP", KEY_PAD_PGUP);
|
||||
add("PAD_PGDN", KEY_PAD_PGDN);
|
||||
add("PAD_CENTER", KEY_PAD_CENTER); // the 5 in the middle
|
||||
add("PAD_INS", KEY_PAD_INS);
|
||||
add("PAD_DEL", KEY_PAD_DEL);
|
||||
add("PAD_RETURN", KEY_PAD_RETURN);
|
||||
add("PAD_ADD", KEY_PAD_ADD); // not used
|
||||
add("PAD_SUBTRACT", KEY_PAD_SUBTRACT); // not used
|
||||
add("PAD_MULTIPLY", KEY_PAD_MULTIPLY); // not used
|
||||
add("PAD_DIVIDE", KEY_PAD_DIVIDE); // not used
|
||||
|
||||
add("BUTTON0", KEY_BUTTON0);
|
||||
add("BUTTON1", KEY_BUTTON1);
|
||||
add("BUTTON2", KEY_BUTTON2);
|
||||
add("BUTTON3", KEY_BUTTON3);
|
||||
add("BUTTON4", KEY_BUTTON4);
|
||||
add("BUTTON5", KEY_BUTTON5);
|
||||
add("BUTTON6", KEY_BUTTON6);
|
||||
add("BUTTON7", KEY_BUTTON7);
|
||||
add("BUTTON8", KEY_BUTTON8);
|
||||
add("BUTTON9", KEY_BUTTON9);
|
||||
add("BUTTON10", KEY_BUTTON10);
|
||||
add("BUTTON11", KEY_BUTTON11);
|
||||
add("BUTTON12", KEY_BUTTON12);
|
||||
add("BUTTON13", KEY_BUTTON13);
|
||||
add("BUTTON14", KEY_BUTTON14);
|
||||
add("BUTTON15", KEY_BUTTON15);
|
||||
}
|
||||
};
|
||||
static WhichKeysym keysyms;
|
||||
|
||||
struct WhichMask: public StringLookup<MASK>
|
||||
{
|
||||
WhichMask(): StringLookup<MASK>("shift mask")
|
||||
{
|
||||
add("NONE", MASK_NONE);
|
||||
add("CONTROL", MASK_CONTROL); // Mapped to cmd on Macs
|
||||
add("ALT", MASK_ALT);
|
||||
add("SHIFT", MASK_SHIFT);
|
||||
add("MAC_CONTROL", MASK_MAC_CONTROL); // Un-mapped Ctrl key on Macs, not used on Windows
|
||||
}
|
||||
};
|
||||
static WhichMask masks;
|
||||
|
||||
static MASK getMask(const LLSD& event)
|
||||
{
|
||||
MASK mask(MASK_NONE);
|
||||
LLSD masknames(event["mask"]);
|
||||
for (LLSD::array_const_iterator ai(masknames.beginArray()), aend(masknames.endArray());
|
||||
ai != aend; ++ai)
|
||||
{
|
||||
mask |= masks.lookup(*ai);
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
static KEY getKEY(const LLSD& event)
|
||||
{
|
||||
if (event.has("keysym"))
|
||||
{
|
||||
return keysyms.lookup(event["keysym"]);
|
||||
}
|
||||
else if (event.has("keycode"))
|
||||
{
|
||||
return KEY(event["keycode"].asInteger());
|
||||
}
|
||||
else
|
||||
{
|
||||
return KEY(event["char"].asString()[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void LLWindowListener::keyDown(LLSD const & evt)
|
||||
{
|
||||
mKbGetter()->handleTranslatedKeyDown(getKEY(evt), getMask(evt));
|
||||
}
|
||||
|
||||
void LLWindowListener::keyUp(LLSD const & evt)
|
||||
{
|
||||
mKbGetter()->handleTranslatedKeyUp(getKEY(evt), getMask(evt));
|
||||
}
|
||||
|
||||
// for WhichButton
|
||||
typedef BOOL (LLWindowCallbacks::*MouseFunc)(LLWindow *, LLCoordGL, MASK);
|
||||
struct Actions
|
||||
{
|
||||
Actions(const MouseFunc& d, const MouseFunc& u): down(d), up(u), valid(true) {}
|
||||
Actions(): valid(false) {}
|
||||
MouseFunc down, up;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
struct WhichButton: public StringLookup<Actions>
|
||||
{
|
||||
WhichButton(): StringLookup<Actions>("mouse button")
|
||||
{
|
||||
add("LEFT", Actions(&LLWindowCallbacks::handleMouseDown,
|
||||
&LLWindowCallbacks::handleMouseUp));
|
||||
add("RIGHT", Actions(&LLWindowCallbacks::handleRightMouseDown,
|
||||
&LLWindowCallbacks::handleRightMouseUp));
|
||||
add("MIDDLE", Actions(&LLWindowCallbacks::handleMiddleMouseDown,
|
||||
&LLWindowCallbacks::handleMiddleMouseUp));
|
||||
}
|
||||
};
|
||||
static WhichButton buttons;
|
||||
|
||||
static LLCoordGL getPos(const LLSD& event)
|
||||
{
|
||||
return LLCoordGL(event["x"].asInteger(), event["y"].asInteger());
|
||||
}
|
||||
|
||||
void LLWindowListener::mouseDown(LLSD const & evt)
|
||||
{
|
||||
Actions actions(buttons.lookup(evt["button"]));
|
||||
if (actions.valid)
|
||||
{
|
||||
(mWindow->*(actions.down))(NULL, getPos(evt), getMask(evt));
|
||||
}
|
||||
}
|
||||
|
||||
void LLWindowListener::mouseUp(LLSD const & evt)
|
||||
{
|
||||
Actions actions(buttons.lookup(evt["button"]));
|
||||
if (actions.valid)
|
||||
{
|
||||
(mWindow->*(actions.up))(NULL, getPos(evt), getMask(evt));
|
||||
}
|
||||
}
|
||||
|
||||
void LLWindowListener::mouseMove(LLSD const & evt)
|
||||
{
|
||||
mWindow->handleMouseMove(NULL, getPos(evt), getMask(evt));
|
||||
}
|
||||
|
||||
void LLWindowListener::mouseScroll(LLSD const & evt)
|
||||
{
|
||||
S32 clicks = evt["clicks"].asInteger();
|
||||
|
||||
mWindow->handleScrollWheel(NULL, clicks);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* @file llwindowlistener.h
|
||||
* @brief EventAPI interface for injecting input into LLWindow
|
||||
*
|
||||
* $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_LLWINDOWLISTENER_H
|
||||
#define LL_LLWINDOWLISTENER_H
|
||||
|
||||
#include "lleventapi.h"
|
||||
#include <boost/function.hpp>
|
||||
|
||||
class LLKeyboard;
|
||||
class LLWindowCallbacks;
|
||||
|
||||
class LLWindowListener : public LLEventAPI
|
||||
{
|
||||
public:
|
||||
typedef boost::function<LLKeyboard*()> KeyboardGetter;
|
||||
LLWindowListener(LLWindowCallbacks * window, const KeyboardGetter& kbgetter);
|
||||
|
||||
void keyDown(LLSD const & evt);
|
||||
void keyUp(LLSD const & evt);
|
||||
void mouseDown(LLSD const & evt);
|
||||
void mouseUp(LLSD const & evt);
|
||||
void mouseMove(LLSD const & evt);
|
||||
void mouseScroll(LLSD const & evt);
|
||||
|
||||
private:
|
||||
LLWindowCallbacks * mWindow;
|
||||
KeyboardGetter mKbGetter;
|
||||
};
|
||||
|
||||
|
||||
#endif // LL_LLWINDOWLISTENER_H
|
||||
|
|
@ -500,6 +500,8 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
|
|||
//-----------------------------------------------------------------------
|
||||
|
||||
DEVMODE dev_mode;
|
||||
::ZeroMemory(&dev_mode, sizeof(DEVMODE));
|
||||
dev_mode.dmSize = sizeof(DEVMODE);
|
||||
DWORD current_refresh;
|
||||
if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode))
|
||||
{
|
||||
|
|
@ -878,6 +880,8 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
|
|||
{
|
||||
GLuint pixel_format;
|
||||
DEVMODE dev_mode;
|
||||
::ZeroMemory(&dev_mode, sizeof(DEVMODE));
|
||||
dev_mode.dmSize = sizeof(DEVMODE);
|
||||
DWORD current_refresh;
|
||||
DWORD dw_ex_style;
|
||||
DWORD dw_style;
|
||||
|
|
@ -2711,6 +2715,8 @@ LLWindow::LLWindowResolution* LLWindowWin32::getSupportedResolutions(S32 &num_re
|
|||
{
|
||||
mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS];
|
||||
DEVMODE dev_mode;
|
||||
::ZeroMemory(&dev_mode, sizeof(DEVMODE));
|
||||
dev_mode.dmSize = sizeof(DEVMODE);
|
||||
|
||||
mNumSupportedResolutions = 0;
|
||||
for (S32 mode_num = 0; mNumSupportedResolutions < MAX_NUM_RESOLUTIONS; mode_num++)
|
||||
|
|
@ -2786,7 +2792,8 @@ F32 LLWindowWin32::getPixelAspectRatio()
|
|||
BOOL LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh)
|
||||
{
|
||||
DEVMODE dev_mode;
|
||||
dev_mode.dmSize = sizeof(dev_mode);
|
||||
::ZeroMemory(&dev_mode, sizeof(DEVMODE));
|
||||
dev_mode.dmSize = sizeof(DEVMODE);
|
||||
BOOL success = FALSE;
|
||||
|
||||
// Don't change anything if we don't have to
|
||||
|
|
|
|||
|
|
@ -490,6 +490,15 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// virtual
|
||||
void onNavigateErrorPage(const EventType& event)
|
||||
{
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_error_page");
|
||||
message.setValueS32("status_code", event.getIntValue());
|
||||
sendMessage(message);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// virtual
|
||||
void onLocationChange(const EventType& event)
|
||||
|
|
@ -519,6 +528,11 @@ private:
|
|||
{
|
||||
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_nofollow");
|
||||
message.setValue("uri", event.getEventUri());
|
||||
#if LLQTWEBKIT_API_VERSION >= 7
|
||||
message.setValue("nav_type", event.getNavigationType());
|
||||
#else
|
||||
message.setValue("nav_type", "clicked");
|
||||
#endif
|
||||
sendMessage(message);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -417,6 +417,7 @@ set(viewer_SOURCE_FILES
|
|||
llsidepaneliteminfo.cpp
|
||||
llsidepaneltaskinfo.cpp
|
||||
llsidetray.cpp
|
||||
llsidetraylistener.cpp
|
||||
llsidetraypanelcontainer.cpp
|
||||
llsky.cpp
|
||||
llslurl.cpp
|
||||
|
|
@ -957,6 +958,7 @@ set(viewer_HEADER_FILES
|
|||
llsidepaneliteminfo.h
|
||||
llsidepaneltaskinfo.h
|
||||
llsidetray.h
|
||||
llsidetraylistener.h
|
||||
llsidetraypanelcontainer.h
|
||||
llsky.h
|
||||
llslurl.h
|
||||
|
|
|
|||
|
|
@ -2623,10 +2623,10 @@
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>DisableRendering</key>
|
||||
<key>HeadlessClient</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Disable GL rendering and GUI (load testing)</string>
|
||||
<string>Run in headless mode by disabling GL rendering, keyboard, etc</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
|
|
@ -3232,14 +3232,14 @@
|
|||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Specifies that you have not logged in with the viewer since you performed a clean install</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>FirstSelectedDisabledPopups</key>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>FirstSelectedDisabledPopups</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Return false if there is not disabled popup selected in the list of floater preferences popups</string>
|
||||
|
|
@ -12652,5 +12652,27 @@
|
|||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>GenericErrorPageURL</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>URL to set as a property on LLMediaControl to navigate to if the a page completes with a 400-499 HTTP status code</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string>http://common-flash-secondlife-com.s3.amazonaws.com/viewer/v2.6/agni/404.html</string>
|
||||
</map>
|
||||
<key>DestinationsAndAvatarsVisibility</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Whether destination panel or avatar picker are open (0=destination guide, 1=avatar picker, default=nothing)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>S32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
</map>
|
||||
</llsd>
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@
|
|||
<key>Type</key>
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string>http://common-flash-secondlife-com.s3.amazonaws.com/viewer/v2.6/damballah/howto/index.html?topic=[TOPIC]</string>
|
||||
<string>http://common-flash-secondlife-com.s3.amazonaws.com/viewer/v2.6/agni/howto/index.html?topic=[TOPIC]</string>
|
||||
</map>
|
||||
<key>PreferredMaturity</key>
|
||||
<map>
|
||||
|
|
@ -345,7 +345,7 @@
|
|||
<key>Type</key>
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string>http://common-flash-secondlife-com.s3.amazonaws.com/viewer/v2.6/damballah/guide.html</string>
|
||||
<string>http://common-flash-secondlife-com.s3.amazonaws.com/viewer/v2.6/agni/guide.html</string>
|
||||
</map>
|
||||
<key>AvatarPickerURL</key>
|
||||
<map>
|
||||
|
|
@ -356,7 +356,7 @@
|
|||
<key>Type</key>
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string>http://common-flash-secondlife-com.s3.amazonaws.com/viewer/v2.6/damballah/avatars.html</string>
|
||||
<string>http://common-flash-secondlife-com.s3.amazonaws.com/viewer/v2.6/agni/avatars.html</string>
|
||||
</map>
|
||||
<key>LogInventoryDecline</key>
|
||||
<map>
|
||||
|
|
|
|||
|
|
@ -1138,12 +1138,6 @@ void LLAgent::resetControlFlags()
|
|||
//-----------------------------------------------------------------------------
|
||||
void LLAgent::setAFK()
|
||||
{
|
||||
// Drones can't go AFK
|
||||
if (gNoRender)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gAgent.getRegion())
|
||||
{
|
||||
// Don't set AFK if we're not talking to a region yet.
|
||||
|
|
@ -1703,11 +1697,6 @@ void LLAgent::clearRenderState(U8 clearstate)
|
|||
//-----------------------------------------------------------------------------
|
||||
U8 LLAgent::getRenderState()
|
||||
{
|
||||
if (gNoRender || gKeyboard == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// *FIX: don't do stuff in a getter! This is infinite loop city!
|
||||
if ((mTypingTimer.getElapsedTimeF32() > TYPING_TIMEOUT_SECS)
|
||||
&& (mRenderState & AGENT_STATE_TYPING))
|
||||
|
|
|
|||
|
|
@ -282,25 +282,22 @@ void LLAgentCamera::resetView(BOOL reset_camera, BOOL change_camera)
|
|||
gAgent.stopAutoPilot(TRUE);
|
||||
}
|
||||
|
||||
if (!gNoRender)
|
||||
LLSelectMgr::getInstance()->unhighlightAll();
|
||||
|
||||
// By popular request, keep land selection while walking around. JC
|
||||
// LLViewerParcelMgr::getInstance()->deselectLand();
|
||||
|
||||
// force deselect when walking and attachment is selected
|
||||
// this is so people don't wig out when their avatar moves without animating
|
||||
if (LLSelectMgr::getInstance()->getSelection()->isAttachment())
|
||||
{
|
||||
LLSelectMgr::getInstance()->unhighlightAll();
|
||||
LLSelectMgr::getInstance()->deselectAll();
|
||||
}
|
||||
|
||||
// By popular request, keep land selection while walking around. JC
|
||||
// LLViewerParcelMgr::getInstance()->deselectLand();
|
||||
|
||||
// force deselect when walking and attachment is selected
|
||||
// this is so people don't wig out when their avatar moves without animating
|
||||
if (LLSelectMgr::getInstance()->getSelection()->isAttachment())
|
||||
{
|
||||
LLSelectMgr::getInstance()->deselectAll();
|
||||
}
|
||||
|
||||
if (gMenuHolder != NULL)
|
||||
{
|
||||
// Hide all popup menus
|
||||
gMenuHolder->hideMenus();
|
||||
}
|
||||
if (gMenuHolder != NULL)
|
||||
{
|
||||
// Hide all popup menus
|
||||
gMenuHolder->hideMenus();
|
||||
}
|
||||
|
||||
if (change_camera && !gSavedSettings.getBOOL("FreezeTime"))
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@
|
|||
#include "llviewerobject.h"
|
||||
#include "llviewerobjectlist.h"
|
||||
#include "llviewerregion.h"
|
||||
#include "llsdutil.h"
|
||||
#include "llsdutil_math.h"
|
||||
|
||||
LLAgentListener::LLAgentListener(LLAgent &agent)
|
||||
: LLEventAPI("LLAgent",
|
||||
|
|
@ -53,6 +55,15 @@ LLAgentListener::LLAgentListener(LLAgent &agent)
|
|||
add("requestStand",
|
||||
"Ask to stand up",
|
||||
&LLAgentListener::requestStand);
|
||||
add("resetAxes",
|
||||
"Set the agent to a fixed orientation (optionally specify [\"lookat\"] = array of [x, y, z])",
|
||||
&LLAgentListener::resetAxes);
|
||||
add("getAxes",
|
||||
"Send information about the agent's orientation on [\"reply\"]:\n"
|
||||
"[\"euler\"]: map of {roll, pitch, yaw}\n"
|
||||
"[\"quat\"]: array of [x, y, z, w] quaternion values",
|
||||
&LLAgentListener::getAxes,
|
||||
LLSDMap("reply", LLSD()));
|
||||
}
|
||||
|
||||
void LLAgentListener::requestTeleport(LLSD const & event_data) const
|
||||
|
|
@ -64,7 +75,7 @@ void LLAgentListener::requestTeleport(LLSD const & event_data) const
|
|||
params.append(event_data["x"]);
|
||||
params.append(event_data["y"]);
|
||||
params.append(event_data["z"]);
|
||||
LLCommandDispatcher::dispatch("teleport", params, LLSD(), NULL, true);
|
||||
LLCommandDispatcher::dispatch("teleport", params, LLSD(), NULL, "clicked", true);
|
||||
// *TODO - lookup other LLCommandHandlers for "agent", "classified", "event", "group", "floater", "parcel", "login", login_refresh", "balance", "chat"
|
||||
// should we just compose LLCommandHandler and LLDispatchListener?
|
||||
}
|
||||
|
|
@ -74,7 +85,7 @@ void LLAgentListener::requestTeleport(LLSD const & event_data) const
|
|||
LLVector3(event_data["x"].asReal(),
|
||||
event_data["y"].asReal(),
|
||||
event_data["z"].asReal())).getSLURLString();
|
||||
LLURLDispatcher::dispatch(url, NULL, false);
|
||||
LLURLDispatcher::dispatch(url, "clicked", NULL, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -104,3 +115,28 @@ void LLAgentListener::requestStand(LLSD const & event_data) const
|
|||
mAgent.setControlFlags(AGENT_CONTROL_STAND_UP);
|
||||
}
|
||||
|
||||
void LLAgentListener::resetAxes(const LLSD& event) const
|
||||
{
|
||||
if (event.has("lookat"))
|
||||
{
|
||||
mAgent.resetAxes(ll_vector3_from_sd(event["lookat"]));
|
||||
}
|
||||
else
|
||||
{
|
||||
// no "lookat", default call
|
||||
mAgent.resetAxes();
|
||||
}
|
||||
}
|
||||
|
||||
void LLAgentListener::getAxes(const LLSD& event) const
|
||||
{
|
||||
LLQuaternion quat(mAgent.getQuat());
|
||||
F32 roll, pitch, yaw;
|
||||
quat.getEulerAngles(&roll, &pitch, &yaw);
|
||||
// The official query API for LLQuaternion's [x, y, z, w] values is its
|
||||
// public member mQ...
|
||||
sendReply(LLSDMap
|
||||
("quat", llsd_copy_array(boost::begin(quat.mQ), boost::end(quat.mQ)))
|
||||
("euler", LLSDMap("roll", roll)("pitch", pitch)("yaw", yaw)),
|
||||
event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@ private:
|
|||
void requestTeleport(LLSD const & event_data) const;
|
||||
void requestSit(LLSD const & event_data) const;
|
||||
void requestStand(LLSD const & event_data) const;
|
||||
void resetAxes(const LLSD& event) const;
|
||||
void getAxes(const LLSD& event) const;
|
||||
|
||||
private:
|
||||
LLAgent & mAgent;
|
||||
|
|
|
|||
|
|
@ -78,7 +78,6 @@
|
|||
#include "llvoicechannel.h"
|
||||
#include "llvoavatarself.h"
|
||||
#include "llsidetray.h"
|
||||
#include "llfeaturemanager.h"
|
||||
#include "llurlmatch.h"
|
||||
#include "lltextutil.h"
|
||||
#include "lllogininstance.h"
|
||||
|
|
@ -756,7 +755,7 @@ bool LLAppViewer::init()
|
|||
|
||||
//
|
||||
// Various introspection concerning the libs we're using - particularly
|
||||
// the libs involved in getting to a full login screen.
|
||||
// the libs involved in getting to a full login screen.
|
||||
//
|
||||
LL_INFOS("InitInfo") << "J2C Engine is: " << LLImageJ2C::getEngineInfo() << LL_ENDL;
|
||||
LL_INFOS("InitInfo") << "libcurl version is: " << LLCurl::getVersionString() << LL_ENDL;
|
||||
|
|
@ -925,7 +924,7 @@ bool LLAppViewer::init()
|
|||
}
|
||||
|
||||
// If we don't have the right GL requirements, exit.
|
||||
if (!gGLManager.mHasRequirements && !gNoRender)
|
||||
if (!gGLManager.mHasRequirements)
|
||||
{
|
||||
// can't use an alert here since we're exiting and
|
||||
// all hell breaks lose.
|
||||
|
|
@ -1215,7 +1214,8 @@ bool LLAppViewer::mainLoop()
|
|||
}
|
||||
|
||||
// Render scene.
|
||||
if (!LLApp::isExiting())
|
||||
// *TODO: Should we run display() even during gHeadlessClient? DK 2011-02-18
|
||||
if (!LLApp::isExiting() && !gHeadlessClient)
|
||||
{
|
||||
pingMainloopTimeout("Main:Display");
|
||||
gGLActive = TRUE;
|
||||
|
|
@ -1243,8 +1243,7 @@ bool LLAppViewer::mainLoop()
|
|||
}
|
||||
|
||||
// yield cooperatively when not running as foreground window
|
||||
if ( gNoRender
|
||||
|| (gViewerWindow && !gViewerWindow->mWindow->getVisible())
|
||||
if ( (gViewerWindow && !gViewerWindow->mWindow->getVisible())
|
||||
|| !gFocusMgr.getAppHasFocus())
|
||||
{
|
||||
// Sleep if we're not rendering, or the window is minimized.
|
||||
|
|
@ -2730,12 +2729,26 @@ void LLAppViewer::checkForCrash(void)
|
|||
|
||||
}
|
||||
|
||||
//
|
||||
// This function decides whether the client machine meets the minimum requirements to
|
||||
// run in a maximized window, per the consensus of davep, boa and nyx on 3/30/2011.
|
||||
//
|
||||
bool LLAppViewer::meetsRequirementsForMaximizedStart()
|
||||
{
|
||||
bool maximizedOk = (LLFeatureManager::getInstance()->getGPUClass() >= GPU_CLASS_2);
|
||||
|
||||
const U32 one_gigabyte_kb = 1024 * 1024;
|
||||
maximizedOk &= (gSysMemory.getPhysicalMemoryKB() >= one_gigabyte_kb);
|
||||
|
||||
return maximizedOk;
|
||||
}
|
||||
|
||||
bool LLAppViewer::initWindow()
|
||||
{
|
||||
LL_INFOS("AppInit") << "Initializing window..." << LL_ENDL;
|
||||
|
||||
// store setting in a global for easy access and modification
|
||||
gNoRender = gSavedSettings.getBOOL("DisableRendering");
|
||||
gHeadlessClient = gSavedSettings.getBOOL("HeadlessClient");
|
||||
|
||||
// always start windowed
|
||||
BOOL ignorePixelDepth = gSavedSettings.getBOOL("IgnorePixelDepth");
|
||||
|
|
@ -2749,7 +2762,8 @@ bool LLAppViewer::initWindow()
|
|||
const S32 NEVER_SUBMIT_REPORT = 2;
|
||||
bool use_watchdog = false;
|
||||
int watchdog_enabled_setting = gSavedSettings.getS32("WatchdogEnabled");
|
||||
if(watchdog_enabled_setting == -1){
|
||||
if(watchdog_enabled_setting == -1)
|
||||
{
|
||||
use_watchdog = !LLFeatureManager::getInstance()->isFeatureAvailable("WatchdogDisabled");
|
||||
}
|
||||
else
|
||||
|
|
@ -2771,28 +2785,25 @@ bool LLAppViewer::initWindow()
|
|||
gViewerWindow->mWindow->maximize();
|
||||
}
|
||||
|
||||
if (!gNoRender)
|
||||
//
|
||||
// Initialize GL stuff
|
||||
//
|
||||
|
||||
if (mForceGraphicsDetail)
|
||||
{
|
||||
//
|
||||
// Initialize GL stuff
|
||||
//
|
||||
|
||||
if (mForceGraphicsDetail)
|
||||
{
|
||||
LLFeatureManager::getInstance()->setGraphicsLevel(gSavedSettings.getU32("RenderQualityPerformance"), false);
|
||||
}
|
||||
|
||||
// Set this flag in case we crash while initializing GL
|
||||
gSavedSettings.setBOOL("RenderInitError", TRUE);
|
||||
gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
|
||||
|
||||
gPipeline.init();
|
||||
stop_glerror();
|
||||
gViewerWindow->initGLDefaults();
|
||||
|
||||
gSavedSettings.setBOOL("RenderInitError", FALSE);
|
||||
gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
|
||||
LLFeatureManager::getInstance()->setGraphicsLevel(gSavedSettings.getU32("RenderQualityPerformance"), false);
|
||||
}
|
||||
|
||||
// Set this flag in case we crash while initializing GL
|
||||
gSavedSettings.setBOOL("RenderInitError", TRUE);
|
||||
gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
|
||||
|
||||
gPipeline.init();
|
||||
stop_glerror();
|
||||
gViewerWindow->initGLDefaults();
|
||||
|
||||
gSavedSettings.setBOOL("RenderInitError", FALSE);
|
||||
gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
|
||||
|
||||
//If we have a startup crash, it's usually near GL initialization, so simulate that.
|
||||
if(gCrashOnStartup)
|
||||
|
|
@ -2800,6 +2811,21 @@ bool LLAppViewer::initWindow()
|
|||
LLAppViewer::instance()->forceErrorLLError();
|
||||
}
|
||||
|
||||
//
|
||||
// Determine if the window should start maximized on initial run based
|
||||
// on graphics capability
|
||||
//
|
||||
if (gSavedSettings.getBOOL("FirstLoginThisInstall") && meetsRequirementsForMaximizedStart())
|
||||
{
|
||||
LL_INFOS("AppInit") << "This client met the requirements for a maximized initial screen." << LL_ENDL;
|
||||
gSavedSettings.setBOOL("WindowMaximized", TRUE);
|
||||
}
|
||||
|
||||
if (gSavedSettings.getBOOL("WindowMaximized"))
|
||||
{
|
||||
gViewerWindow->mWindow->maximize();
|
||||
}
|
||||
|
||||
LLUI::sWindow = gViewerWindow->getWindow();
|
||||
|
||||
// Show watch cursor
|
||||
|
|
@ -2834,12 +2860,9 @@ void LLAppViewer::cleanupSavedSettings()
|
|||
|
||||
gSavedSettings.setBOOL("ShowObjectUpdates", gShowObjectUpdates);
|
||||
|
||||
if (!gNoRender)
|
||||
if (gDebugView)
|
||||
{
|
||||
if (gDebugView)
|
||||
{
|
||||
gSavedSettings.setBOOL("ShowDebugConsole", gDebugView->mDebugConsolep->getVisible());
|
||||
}
|
||||
gSavedSettings.setBOOL("ShowDebugConsole", gDebugView->mDebugConsolep->getVisible());
|
||||
}
|
||||
|
||||
// save window position if not maximized
|
||||
|
|
@ -3820,7 +3843,7 @@ void LLAppViewer::badNetworkHandler()
|
|||
// is destroyed.
|
||||
void LLAppViewer::saveFinalSnapshot()
|
||||
{
|
||||
if (!mSavedFinalSnapshot && !gNoRender)
|
||||
if (!mSavedFinalSnapshot)
|
||||
{
|
||||
gSavedSettings.setVector3d("FocusPosOnLogout", gAgentCamera.calcFocusPositionTargetGlobal());
|
||||
gSavedSettings.setVector3d("CameraPosOnLogout", gAgentCamera.calcCameraPositionTargetGlobal());
|
||||
|
|
@ -4224,34 +4247,31 @@ void LLAppViewer::idle()
|
|||
//
|
||||
// Update weather effects
|
||||
//
|
||||
if (!gNoRender)
|
||||
LLWorld::getInstance()->updateClouds(gFrameDTClamped);
|
||||
gSky.propagateHeavenlyBodies(gFrameDTClamped); // moves sun, moon, and planets
|
||||
|
||||
// Update wind vector
|
||||
LLVector3 wind_position_region;
|
||||
static LLVector3 average_wind;
|
||||
|
||||
LLViewerRegion *regionp;
|
||||
regionp = LLWorld::getInstance()->resolveRegionGlobal(wind_position_region, gAgent.getPositionGlobal()); // puts agent's local coords into wind_position
|
||||
if (regionp)
|
||||
{
|
||||
LLWorld::getInstance()->updateClouds(gFrameDTClamped);
|
||||
gSky.propagateHeavenlyBodies(gFrameDTClamped); // moves sun, moon, and planets
|
||||
gWindVec = regionp->mWind.getVelocity(wind_position_region);
|
||||
|
||||
// Update wind vector
|
||||
LLVector3 wind_position_region;
|
||||
static LLVector3 average_wind;
|
||||
|
||||
LLViewerRegion *regionp;
|
||||
regionp = LLWorld::getInstance()->resolveRegionGlobal(wind_position_region, gAgent.getPositionGlobal()); // puts agent's local coords into wind_position
|
||||
if (regionp)
|
||||
{
|
||||
gWindVec = regionp->mWind.getVelocity(wind_position_region);
|
||||
|
||||
// Compute average wind and use to drive motion of water
|
||||
|
||||
average_wind = regionp->mWind.getAverage();
|
||||
F32 cloud_density = regionp->mCloudLayer.getDensityRegion(wind_position_region);
|
||||
|
||||
gSky.setCloudDensityAtAgent(cloud_density);
|
||||
gSky.setWind(average_wind);
|
||||
//LLVOWater::setWind(average_wind);
|
||||
}
|
||||
else
|
||||
{
|
||||
gWindVec.setVec(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
// Compute average wind and use to drive motion of water
|
||||
|
||||
average_wind = regionp->mWind.getAverage();
|
||||
F32 cloud_density = regionp->mCloudLayer.getDensityRegion(wind_position_region);
|
||||
|
||||
gSky.setCloudDensityAtAgent(cloud_density);
|
||||
gSky.setWind(average_wind);
|
||||
//LLVOWater::setWind(average_wind);
|
||||
}
|
||||
else
|
||||
{
|
||||
gWindVec.setVec(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
|
@ -4260,13 +4280,10 @@ void LLAppViewer::idle()
|
|||
// Here, particles are updated and drawables are moved.
|
||||
//
|
||||
|
||||
if (!gNoRender)
|
||||
{
|
||||
LLFastTimer t(FTM_WORLD_UPDATE);
|
||||
gPipeline.updateMove();
|
||||
LLFastTimer t(FTM_WORLD_UPDATE);
|
||||
gPipeline.updateMove();
|
||||
|
||||
LLWorld::getInstance()->updateParticles();
|
||||
}
|
||||
LLWorld::getInstance()->updateParticles();
|
||||
|
||||
if (LLViewerJoystick::getInstance()->getOverrideCamera())
|
||||
{
|
||||
|
|
@ -4632,12 +4649,9 @@ void LLAppViewer::disconnectViewer()
|
|||
gSavedSettings.setBOOL("FlyingAtExit", gAgent.getFlying() );
|
||||
|
||||
// Un-minimize all windows so they don't get saved minimized
|
||||
if (!gNoRender)
|
||||
if (gFloaterView)
|
||||
{
|
||||
if (gFloaterView)
|
||||
{
|
||||
gFloaterView->restoreAll();
|
||||
}
|
||||
gFloaterView->restoreAll();
|
||||
}
|
||||
|
||||
if (LLSelectMgr::getInstance())
|
||||
|
|
|
|||
|
|
@ -187,6 +187,7 @@ protected:
|
|||
|
||||
virtual std::string generateSerialNumber() = 0; // Platforms specific classes generate this.
|
||||
|
||||
virtual bool meetsRequirementsForMaximizedStart(); // Used on first login to decide to launch maximized
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ gboolean viewer_app_api_GoSLURL(ViewerAppAPI *obj, gchar *slurl, gboolean **succ
|
|||
std::string url = slurl;
|
||||
LLMediaCtrl* web = NULL;
|
||||
const bool trusted_browser = false;
|
||||
if (LLURLDispatcher::dispatch(url, web, trusted_browser))
|
||||
if (LLURLDispatcher::dispatch(url, "", web, trusted_browser))
|
||||
{
|
||||
// bring window to foreground, as it has just been "launched" from a URL
|
||||
// todo: hmm, how to get there from here?
|
||||
|
|
|
|||
|
|
@ -500,7 +500,7 @@ OSErr AEGURLHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn)
|
|||
|
||||
LLMediaCtrl* web = NULL;
|
||||
const bool trusted_browser = false;
|
||||
LLURLDispatcher::dispatch(url, web, trusted_browser);
|
||||
LLURLDispatcher::dispatch(url, "", web, trusted_browser);
|
||||
}
|
||||
|
||||
return(result);
|
||||
|
|
|
|||
|
|
@ -279,7 +279,7 @@ bool LLAvatarActions::isCalling(const LLUUID &id)
|
|||
//static
|
||||
bool LLAvatarActions::canCall()
|
||||
{
|
||||
return LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking();
|
||||
return LLVoiceClient::getInstance()->voiceEnabled() && LLVoiceClient::getInstance()->isVoiceWorking();
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
@ -300,40 +300,21 @@ void LLAvatarActions::startConference(const uuid_vec_t& ids)
|
|||
make_ui_sound("UISndStartIM");
|
||||
}
|
||||
|
||||
static void on_avatar_name_show_profile(const LLUUID& agent_id, const LLAvatarName& av_name)
|
||||
{
|
||||
llinfos << "opening web profile for " << av_name.mUsername << llendl;
|
||||
std::string url = getProfileURL(av_name.mUsername);
|
||||
|
||||
// PROFILES: open in webkit window
|
||||
LLWeb::loadWebURLInternal(url, "", agent_id.asString());
|
||||
}
|
||||
|
||||
// static
|
||||
void LLAvatarActions::showProfile(const LLUUID& id)
|
||||
{
|
||||
if (id.notNull())
|
||||
{
|
||||
LLSD params;
|
||||
params["id"] = id;
|
||||
params["open_tab_name"] = "panel_profile";
|
||||
|
||||
// PROFILES: open in webkit window
|
||||
std::string full_name;
|
||||
if (gCacheName->getFullName(id,full_name))
|
||||
{
|
||||
std::string agent_name = LLCacheName::buildUsername(full_name);
|
||||
llinfos << "opening web profile for " << agent_name << llendl;
|
||||
std::string url = getProfileURL(agent_name);
|
||||
LLWeb::loadWebURLInternal(url, "", id.asString());
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "no name info for agent id " << id << llendl;
|
||||
}
|
||||
#if 0
|
||||
//Show own profile
|
||||
if(gAgent.getID() == id)
|
||||
{
|
||||
LLSideTray::getInstance()->showPanel("panel_me", params);
|
||||
}
|
||||
//Show other user profile
|
||||
else
|
||||
{
|
||||
LLSideTray::getInstance()->showPanel("panel_profile_view", params);
|
||||
}
|
||||
#endif
|
||||
LLAvatarNameCache::get(id, boost::bind(&on_avatar_name_show_profile, _1, _2));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -160,6 +160,12 @@ void LLAvatarPropertiesProcessor::sendAvatarClassifiedsRequest(const LLUUID& ava
|
|||
|
||||
void LLAvatarPropertiesProcessor::sendAvatarPropertiesUpdate(const LLAvatarData* avatar_props)
|
||||
{
|
||||
if (!gAgent.isInitialized() || (gAgent.getID() == LLUUID::null))
|
||||
{
|
||||
llwarns << "Sending avatarinfo update DENIED - invalid agent" << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
llinfos << "Sending avatarinfo update" << llendl;
|
||||
|
||||
// This value is required by sendAvatarPropertiesUpdate method.
|
||||
|
|
@ -168,20 +174,21 @@ void LLAvatarPropertiesProcessor::sendAvatarPropertiesUpdate(const LLAvatarData*
|
|||
|
||||
LLMessageSystem *msg = gMessageSystem;
|
||||
|
||||
msg->newMessageFast(_PREHASH_AvatarPropertiesUpdate);
|
||||
msg->nextBlockFast(_PREHASH_AgentData);
|
||||
msg->addUUIDFast( _PREHASH_AgentID, gAgent.getID() );
|
||||
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
|
||||
msg->nextBlockFast(_PREHASH_PropertiesData);
|
||||
msg->newMessageFast (_PREHASH_AvatarPropertiesUpdate);
|
||||
msg->nextBlockFast (_PREHASH_AgentData);
|
||||
msg->addUUIDFast (_PREHASH_AgentID, gAgent.getID() );
|
||||
msg->addUUIDFast (_PREHASH_SessionID, gAgent.getSessionID() );
|
||||
msg->nextBlockFast (_PREHASH_PropertiesData);
|
||||
|
||||
msg->addUUIDFast( _PREHASH_ImageID, avatar_props->image_id);
|
||||
msg->addUUIDFast( _PREHASH_FLImageID, avatar_props->fl_image_id);
|
||||
msg->addStringFast( _PREHASH_AboutText, avatar_props->about_text);
|
||||
msg->addStringFast( _PREHASH_FLAboutText, avatar_props->fl_about_text);
|
||||
msg->addUUIDFast (_PREHASH_ImageID, avatar_props->image_id);
|
||||
msg->addUUIDFast (_PREHASH_FLImageID, avatar_props->fl_image_id);
|
||||
msg->addStringFast (_PREHASH_AboutText, avatar_props->about_text);
|
||||
msg->addStringFast (_PREHASH_FLAboutText, avatar_props->fl_about_text);
|
||||
|
||||
msg->addBOOL(_PREHASH_AllowPublish, avatar_props->allow_publish);
|
||||
msg->addBOOL(_PREHASH_MaturePublish, mature);
|
||||
msg->addString(_PREHASH_ProfileURL, avatar_props->profile_url);
|
||||
|
||||
gAgent.sendReliableMessage();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,31 +2,25 @@
|
|||
* @file llbreastmotion.cpp
|
||||
* @brief Implementation of LLBreastMotion class.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2011, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* 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.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* 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.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* 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$
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -2,31 +2,25 @@
|
|||
* @file llbreastmotion.h
|
||||
* @brief Implementation of LLBreastMotion class.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2011, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* 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.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* 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.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* 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$
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ void LLCommandDispatcherListener::dispatch(const LLSD& params) const
|
|||
trusted_browser = params["trusted"].asBoolean();
|
||||
}
|
||||
LLCommandDispatcher::dispatch(params["cmd"], params["params"], params["query"], NULL,
|
||||
trusted_browser);
|
||||
"clicked", trusted_browser);
|
||||
}
|
||||
|
||||
void LLCommandDispatcherListener::enumerate(const LLSD& params) const
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
// system includes
|
||||
#include <boost/tokenizer.hpp>
|
||||
|
||||
#define THROTTLE_PERIOD 5 // required secs between throttled commands
|
||||
#define THROTTLE_PERIOD 5 // required seconds between throttled commands
|
||||
|
||||
static LLCommandDispatcherListener sCommandDispatcherListener;
|
||||
|
||||
|
|
@ -59,6 +59,7 @@ public:
|
|||
const LLSD& params,
|
||||
const LLSD& query_map,
|
||||
LLMediaCtrl* web,
|
||||
const std::string& nav_type,
|
||||
bool trusted_browser);
|
||||
|
||||
private:
|
||||
|
|
@ -91,6 +92,7 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
|
|||
const LLSD& params,
|
||||
const LLSD& query_map,
|
||||
LLMediaCtrl* web,
|
||||
const std::string& nav_type,
|
||||
bool trusted_browser)
|
||||
{
|
||||
static bool slurl_blocked = false;
|
||||
|
|
@ -120,11 +122,19 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
|
|||
return true;
|
||||
|
||||
case LLCommandHandler::UNTRUSTED_THROTTLE:
|
||||
// if users actually click on a link, we don't need to throttle it
|
||||
// (throttling mechanism is used to prevent an avalanche of clicks via
|
||||
// javascript
|
||||
if ( nav_type == "clicked" )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
cur_time = LLTimer::getElapsedSeconds();
|
||||
if (cur_time < last_throttle_time + THROTTLE_PERIOD)
|
||||
{
|
||||
// block request from external browser if it happened
|
||||
// within THROTTLE_PERIOD secs of the last command
|
||||
// within THROTTLE_PERIOD seconds of the last command
|
||||
LL_WARNS_ONCE("SLURL") << "Throttled SLURL command from untrusted browser" << LL_ENDL;
|
||||
if (! slurl_throttled)
|
||||
{
|
||||
|
|
@ -166,10 +176,11 @@ bool LLCommandDispatcher::dispatch(const std::string& cmd,
|
|||
const LLSD& params,
|
||||
const LLSD& query_map,
|
||||
LLMediaCtrl* web,
|
||||
const std::string& nav_type,
|
||||
bool trusted_browser)
|
||||
{
|
||||
return LLCommandHandlerRegistry::instance().dispatch(
|
||||
cmd, params, query_map, web, trusted_browser);
|
||||
cmd, params, query_map, web, nav_type, trusted_browser);
|
||||
}
|
||||
|
||||
static std::string lookup(LLCommandHandler::EUntrustedAccess value);
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ public:
|
|||
const LLSD& params,
|
||||
const LLSD& query_map,
|
||||
LLMediaCtrl* web,
|
||||
const std::string& nav_type,
|
||||
bool trusted_browser);
|
||||
// Execute a command registered via the above mechanism,
|
||||
// passing string parameters.
|
||||
|
|
|
|||
|
|
@ -123,10 +123,7 @@ void LLExpandableTextBox::LLTextBoxEx::reshape(S32 width, S32 height, BOOL calle
|
|||
{
|
||||
LLTextEditor::reshape(width, height, called_from_parent);
|
||||
|
||||
if (getTextPixelHeight() > getRect().getHeight())
|
||||
{
|
||||
showExpandText();
|
||||
}
|
||||
hideOrShowExpandTextAsNeeded();
|
||||
}
|
||||
|
||||
void LLExpandableTextBox::LLTextBoxEx::setText(const LLStringExplicit& text,const LLStyle::Params& input_params)
|
||||
|
|
@ -136,17 +133,7 @@ void LLExpandableTextBox::LLTextBoxEx::setText(const LLStringExplicit& text,cons
|
|||
mExpanderVisible = false;
|
||||
LLTextEditor::setText(text, input_params);
|
||||
|
||||
// text contents have changed, segments are cleared out
|
||||
// so hide the expander and determine if we need it
|
||||
//mExpanderVisible = false;
|
||||
if (getTextPixelHeight() > getRect().getHeight())
|
||||
{
|
||||
showExpandText();
|
||||
}
|
||||
else
|
||||
{
|
||||
hideExpandText();
|
||||
}
|
||||
hideOrShowExpandTextAsNeeded();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -200,6 +187,22 @@ S32 LLExpandableTextBox::LLTextBoxEx::getTextPixelHeight()
|
|||
return getTextBoundingRect().getHeight();
|
||||
}
|
||||
|
||||
void LLExpandableTextBox::LLTextBoxEx::hideOrShowExpandTextAsNeeded()
|
||||
{
|
||||
// Restore the text box contents to calculate the text height properly,
|
||||
// otherwise if a part of the text is hidden under "More" link
|
||||
// getTextPixelHeight() returns only the height of currently visible text
|
||||
// including the "More" link. See STORM-250.
|
||||
hideExpandText();
|
||||
|
||||
// Show the expander a.k.a. "More" link if we need it, depending on text
|
||||
// contents height. If not, keep it hidden.
|
||||
if (getTextPixelHeight() > getRect().getHeight())
|
||||
{
|
||||
showExpandText();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -77,6 +77,12 @@ protected:
|
|||
*/
|
||||
void hideExpandText();
|
||||
|
||||
/**
|
||||
* Shows the "More" link if the text is too high to be completely
|
||||
* visible without expanding the text box. Hides that link otherwise.
|
||||
*/
|
||||
void hideOrShowExpandTextAsNeeded();
|
||||
|
||||
protected:
|
||||
|
||||
LLTextBoxEx(const Params& p);
|
||||
|
|
|
|||
|
|
@ -121,7 +121,11 @@ void LLFirstUse::notMoving(bool enable)
|
|||
{
|
||||
// fire off 2 notifications and rely on filtering to select the relevant one
|
||||
firstUseNotification("FirstNotMoving", enable, "HintMove", LLSD(), LLSD().with("target", "move_btn").with("direction", "top"));
|
||||
firstUseNotification("FirstNotMoving", enable, "HintMoveArrows", LLSD(), LLSD().with("target", "bottom_tray").with("direction", "top").with("hint_image", "arrow_keys.png").with("down_arrow", ""));
|
||||
firstUseNotification("FirstNotMoving", enable, "HintMoveClick", LLSD(), LLSD()
|
||||
.with("target", "nav_bar")
|
||||
.with("direction", "bottom")
|
||||
.with("hint_image", "click_to_move.png")
|
||||
.with("up_arrow", ""));
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
|||
|
|
@ -38,13 +38,11 @@
|
|||
///----------------------------------------------------------------------------
|
||||
/// Class LLFloaterBump
|
||||
///----------------------------------------------------------------------------
|
||||
extern BOOL gNoRender;
|
||||
|
||||
// Default constructor
|
||||
LLFloaterBump::LLFloaterBump(const LLSD& key)
|
||||
: LLFloater(key)
|
||||
{
|
||||
if(gNoRender) return;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ BOOL LLFloaterHelpBrowser::postBuild()
|
|||
{
|
||||
mBrowser = getChild<LLMediaCtrl>("browser");
|
||||
mBrowser->addObserver(this);
|
||||
mBrowser->setErrorPageURL(gSavedSettings.getString("GenericErrorPageURL"));
|
||||
|
||||
childSetAction("open_browser", onClickOpenWebBrowser, this);
|
||||
|
||||
|
|
|
|||
|
|
@ -285,6 +285,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
|
|||
mGotPersonalInfo(false),
|
||||
mOriginalIMViaEmail(false),
|
||||
mLanguageChanged(false),
|
||||
mAvatarDataInitialized(false),
|
||||
mDoubleClickActionDirty(false),
|
||||
mFavoritesRecordMayExist(false)
|
||||
{
|
||||
|
|
@ -343,7 +344,7 @@ void LLFloaterPreference::processProperties( void* pData, EAvatarProcessorType t
|
|||
if ( APT_PROPERTIES == type )
|
||||
{
|
||||
const LLAvatarData* pAvatarData = static_cast<const LLAvatarData*>( pData );
|
||||
if( pAvatarData && gAgent.getID() == pAvatarData->avatar_id )
|
||||
if (pAvatarData && (gAgent.getID() == pAvatarData->avatar_id) && (pAvatarData->avatar_id != LLUUID::null))
|
||||
{
|
||||
storeAvatarProperties( pAvatarData );
|
||||
processProfileProperties( pAvatarData );
|
||||
|
|
@ -353,14 +354,19 @@ void LLFloaterPreference::processProperties( void* pData, EAvatarProcessorType t
|
|||
|
||||
void LLFloaterPreference::storeAvatarProperties( const LLAvatarData* pAvatarData )
|
||||
{
|
||||
mAvatarProperties.avatar_id = gAgent.getID();
|
||||
mAvatarProperties.image_id = pAvatarData->image_id;
|
||||
mAvatarProperties.fl_image_id = pAvatarData->fl_image_id;
|
||||
mAvatarProperties.about_text = pAvatarData->about_text;
|
||||
mAvatarProperties.fl_about_text = pAvatarData->fl_about_text;
|
||||
mAvatarProperties.profile_url = pAvatarData->profile_url;
|
||||
mAvatarProperties.flags = pAvatarData->flags;
|
||||
mAvatarProperties.allow_publish = pAvatarData->flags & AVATAR_ALLOW_PUBLISH;
|
||||
if (LLStartUp::getStartupState() == STATE_STARTED)
|
||||
{
|
||||
mAvatarProperties.avatar_id = pAvatarData->avatar_id;
|
||||
mAvatarProperties.image_id = pAvatarData->image_id;
|
||||
mAvatarProperties.fl_image_id = pAvatarData->fl_image_id;
|
||||
mAvatarProperties.about_text = pAvatarData->about_text;
|
||||
mAvatarProperties.fl_about_text = pAvatarData->fl_about_text;
|
||||
mAvatarProperties.profile_url = pAvatarData->profile_url;
|
||||
mAvatarProperties.flags = pAvatarData->flags;
|
||||
mAvatarProperties.allow_publish = pAvatarData->flags & AVATAR_ALLOW_PUBLISH;
|
||||
|
||||
mAvatarDataInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterPreference::processProfileProperties(const LLAvatarData* pAvatarData )
|
||||
|
|
@ -370,15 +376,31 @@ void LLFloaterPreference::processProfileProperties(const LLAvatarData* pAvatarDa
|
|||
|
||||
void LLFloaterPreference::saveAvatarProperties( void )
|
||||
{
|
||||
mAvatarProperties.allow_publish = getChild<LLUICtrl>("online_searchresults")->getValue();
|
||||
if ( mAvatarProperties.allow_publish )
|
||||
const BOOL allowPublish = getChild<LLUICtrl>("online_searchresults")->getValue();
|
||||
|
||||
if (allowPublish)
|
||||
{
|
||||
mAvatarProperties.flags |= AVATAR_ALLOW_PUBLISH;
|
||||
}
|
||||
|
||||
LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesUpdate( &mAvatarProperties );
|
||||
}
|
||||
|
||||
//
|
||||
// NOTE: We really don't want to send the avatar properties unless we absolutely
|
||||
// need to so we can avoid the accidental profile reset bug, so, if we're
|
||||
// logged in, the avatar data has been initialized and we have a state change
|
||||
// for the "allow publish" flag, then set the flag to its new value and send
|
||||
// the properties update.
|
||||
//
|
||||
// NOTE: The only reason we can not remove this update altogether is because of the
|
||||
// "allow publish" flag, the last remaining profile setting in the viewer
|
||||
// that doesn't exist in the web profile.
|
||||
//
|
||||
if ((LLStartUp::getStartupState() == STATE_STARTED) && mAvatarDataInitialized && (allowPublish != mAvatarProperties.allow_publish))
|
||||
{
|
||||
mAvatarProperties.allow_publish = allowPublish;
|
||||
|
||||
LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesUpdate( &mAvatarProperties );
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LLFloaterPreference::postBuild()
|
||||
{
|
||||
|
|
@ -1355,6 +1377,8 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im
|
|||
mOriginalHideOnlineStatus = true;
|
||||
}
|
||||
|
||||
getChild<LLUICtrl>("online_searchresults")->setEnabled(TRUE);
|
||||
|
||||
getChildView("include_im_in_chat_history")->setEnabled(TRUE);
|
||||
getChildView("show_timestamps_check_im")->setEnabled(TRUE);
|
||||
getChildView("friends_online_notify_checkbox")->setEnabled(TRUE);
|
||||
|
|
@ -1734,7 +1758,6 @@ void LLPanelPreferenceGraphics::draw()
|
|||
bool enable = hasDirtyChilds();
|
||||
|
||||
button_apply->setEnabled(enable);
|
||||
|
||||
}
|
||||
}
|
||||
bool LLPanelPreferenceGraphics::hasDirtyChilds()
|
||||
|
|
|
|||
|
|
@ -169,6 +169,7 @@ private:
|
|||
bool mGotPersonalInfo;
|
||||
bool mOriginalIMViaEmail;
|
||||
bool mLanguageChanged;
|
||||
bool mAvatarDataInitialized;
|
||||
|
||||
bool mOriginalHideOnlineStatus;
|
||||
// Record of current user's favorites may be stored in file on disk.
|
||||
|
|
|
|||
|
|
@ -191,6 +191,8 @@ BOOL LLHintPopup::postBuild()
|
|||
LLRect text_bounds = hint_text.getTextBoundingRect();
|
||||
S32 delta_height = text_bounds.getHeight() - hint_text.getRect().getHeight();
|
||||
reshape(getRect().getWidth(), getRect().getHeight() + delta_height);
|
||||
hint_text.reshape(hint_text.getRect().getWidth(), hint_text.getRect().getHeight() + delta_height);
|
||||
// hint_text.translate(0, -delta_height);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -211,6 +213,24 @@ void LLHintPopup::draw()
|
|||
alpha = clamp_rescale(mFadeTimer.getElapsedTimeF32(), 0.f, mFadeInTime, 0.f, 1.f);
|
||||
}
|
||||
|
||||
LLIconCtrl* hint_icon = findChild<LLIconCtrl>("hint_image");
|
||||
|
||||
if (hint_icon)
|
||||
{
|
||||
LLUIImagePtr hint_image = hint_icon->getImage();
|
||||
S32 image_height = hint_image.isNull() ? 0 : hint_image->getHeight();
|
||||
S32 image_width = hint_image.isNull() ? 0 : hint_image->getWidth();
|
||||
|
||||
LLView* layout_stack = hint_icon->getParent()->getParent();
|
||||
S32 delta_height = image_height - layout_stack->getRect().getHeight();
|
||||
hint_icon->getParent()->reshape(image_width, hint_icon->getParent()->getRect().getHeight());
|
||||
layout_stack->reshape(layout_stack->getRect().getWidth(), image_height);
|
||||
layout_stack->translate(0, -delta_height);
|
||||
|
||||
LLRect hint_rect = getLocalRect();
|
||||
reshape(hint_rect.getWidth(), hint_rect.getHeight() + delta_height);
|
||||
}
|
||||
|
||||
{ LLViewDrawContext context(alpha);
|
||||
|
||||
if (mTarget.empty())
|
||||
|
|
|
|||
|
|
@ -587,11 +587,6 @@ void LLHUDEffectLookAt::update()
|
|||
*/
|
||||
bool LLHUDEffectLookAt::calcTargetPosition()
|
||||
{
|
||||
if (gNoRender)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
LLViewerObject *target_obj = (LLViewerObject *)mTargetObject;
|
||||
LLVector3 local_offset;
|
||||
|
||||
|
|
|
|||
|
|
@ -38,8 +38,6 @@
|
|||
#include "llviewercontrol.h"
|
||||
#include "llviewerobjectlist.h"
|
||||
|
||||
extern BOOL gNoRender;
|
||||
|
||||
// These are loaded from saved settings.
|
||||
LLColor4 LLHUDManager::sParentColor;
|
||||
LLColor4 LLHUDManager::sChildColor;
|
||||
|
|
@ -150,11 +148,6 @@ LLHUDEffect *LLHUDManager::createViewerEffect(const U8 type, BOOL send_to_sim, B
|
|||
//static
|
||||
void LLHUDManager::processViewerEffect(LLMessageSystem *mesgsys, void **user_data)
|
||||
{
|
||||
if (gNoRender)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LLHUDEffect *effectp = NULL;
|
||||
LLUUID effect_id;
|
||||
U8 effect_type = 0;
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@
|
|||
#include "llrootview.h"
|
||||
#include "llspeakers.h"
|
||||
#include "llsidetray.h"
|
||||
#include "llviewerchat.h"
|
||||
|
||||
|
||||
static const S32 RECT_PADDING_NOT_INIT = -1;
|
||||
|
|
@ -266,7 +267,9 @@ BOOL LLIMFloater::postBuild()
|
|||
mInputEditor->setMaxTextLength(1023);
|
||||
// enable line history support for instant message bar
|
||||
mInputEditor->setEnableLineHistory(TRUE);
|
||||
|
||||
|
||||
LLFontGL* font = LLViewerChat::getChatFont();
|
||||
mInputEditor->setFont(font);
|
||||
|
||||
mInputEditor->setFocusReceivedCallback( boost::bind(onInputEditorFocusReceived, _1, this) );
|
||||
mInputEditor->setFocusLostCallback( boost::bind(onInputEditorFocusLost, _1, this) );
|
||||
|
|
@ -891,6 +894,7 @@ void LLIMFloater::updateChatHistoryStyle()
|
|||
|
||||
void LLIMFloater::processChatHistoryStyleUpdate(const LLSD& newvalue)
|
||||
{
|
||||
LLFontGL* font = LLViewerChat::getChatFont();
|
||||
LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("impanel");
|
||||
for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin();
|
||||
iter != inst_list.end(); ++iter)
|
||||
|
|
@ -899,6 +903,7 @@ void LLIMFloater::processChatHistoryStyleUpdate(const LLSD& newvalue)
|
|||
if (floater)
|
||||
{
|
||||
floater->updateChatHistoryStyle();
|
||||
floater->mInputEditor->setFont(font);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3183,10 +3183,6 @@ public:
|
|||
//just like a normal IM
|
||||
//this is just replicated code from process_improved_im
|
||||
//and should really go in it's own function -jwolk
|
||||
if (gNoRender)
|
||||
{
|
||||
return;
|
||||
}
|
||||
LLChat chat;
|
||||
|
||||
std::string message = message_params["message"].asString();
|
||||
|
|
@ -3263,11 +3259,6 @@ public:
|
|||
} //end if invitation has instant message
|
||||
else if ( input["body"].has("voice") )
|
||||
{
|
||||
if (gNoRender)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(!LLVoiceClient::getInstance()->voiceEnabled() || !LLVoiceClient::getInstance()->isVoiceWorking())
|
||||
{
|
||||
// Don't display voice invites unless the user has voice enabled.
|
||||
|
|
|
|||
|
|
@ -4681,7 +4681,7 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
|
|||
if (LLWearableType::getAllowMultiwear(mWearableType))
|
||||
{
|
||||
items.push_back(std::string("Wearable Add"));
|
||||
if (gAgentWearables.getWearableCount(mWearableType) > 0)
|
||||
if (gAgentWearables.getWearableCount(mWearableType) >= LLAgentWearables::MAX_CLOTHING_PER_TYPE)
|
||||
{
|
||||
disabled_items.push_back(std::string("Wearable Add"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -480,10 +480,12 @@ LLLoginInstance::LLLoginInstance() :
|
|||
{
|
||||
mLoginModule->getEventPump().listen("lllogininstance",
|
||||
boost::bind(&LLLoginInstance::handleLoginEvent, this, _1));
|
||||
mDispatcher.add("fail.login", boost::bind(&LLLoginInstance::handleLoginFailure, this, _1));
|
||||
mDispatcher.add("connect", boost::bind(&LLLoginInstance::handleLoginSuccess, this, _1));
|
||||
mDispatcher.add("disconnect", boost::bind(&LLLoginInstance::handleDisconnect, this, _1));
|
||||
mDispatcher.add("indeterminate", boost::bind(&LLLoginInstance::handleIndeterminate, this, _1));
|
||||
// This internal use of LLEventDispatcher doesn't really need
|
||||
// per-function descriptions.
|
||||
mDispatcher.add("fail.login", "", boost::bind(&LLLoginInstance::handleLoginFailure, this, _1));
|
||||
mDispatcher.add("connect", "", boost::bind(&LLLoginInstance::handleLoginSuccess, this, _1));
|
||||
mDispatcher.add("disconnect", "", boost::bind(&LLLoginInstance::handleDisconnect, this, _1));
|
||||
mDispatcher.add("indeterminate", "", boost::bind(&LLLoginInstance::handleIndeterminate, this, _1));
|
||||
}
|
||||
|
||||
LLLoginInstance::~LLLoginInstance()
|
||||
|
|
@ -625,11 +627,7 @@ bool LLLoginInstance::handleLoginEvent(const LLSD& event)
|
|||
|
||||
// Call the method registered in constructor, if any, for more specific
|
||||
// handling
|
||||
LLEventDispatcher::Callable method(mDispatcher.get(event["change"]));
|
||||
if (! method.empty())
|
||||
{
|
||||
method(event);
|
||||
}
|
||||
mDispatcher.try_call(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include "llslurl.h"
|
||||
#include "lluictrlfactory.h" // LLDefaultChildRegistry
|
||||
#include "llkeyboard.h"
|
||||
#include "llviewermenu.h"
|
||||
|
||||
// linden library includes
|
||||
#include "llfocusmgr.h"
|
||||
|
|
@ -73,6 +74,7 @@ LLMediaCtrl::Params::Params()
|
|||
texture_height("texture_height", 1024),
|
||||
caret_color("caret_color"),
|
||||
initial_mime_type("initial_mime_type"),
|
||||
error_page_url("error_page_url"),
|
||||
media_id("media_id"),
|
||||
trusted_content("trusted_content", false),
|
||||
focus_on_click("focus_on_click", true)
|
||||
|
|
@ -102,9 +104,11 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :
|
|||
mTextureHeight ( 1024 ),
|
||||
mClearCache(false),
|
||||
mHomePageMimeType(p.initial_mime_type),
|
||||
mErrorPageURL(p.error_page_url),
|
||||
mTrusted(p.trusted_content),
|
||||
mWindowShade(NULL),
|
||||
mHoverTextChanged(false)
|
||||
mHoverTextChanged(false),
|
||||
mContextMenu(NULL)
|
||||
{
|
||||
{
|
||||
LLColor4 color = p.caret_color().get();
|
||||
|
|
@ -149,7 +153,6 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :
|
|||
|
||||
LLMediaCtrl::~LLMediaCtrl()
|
||||
{
|
||||
|
||||
if (mMediaSource)
|
||||
{
|
||||
mMediaSource->remObserver( this );
|
||||
|
|
@ -304,10 +307,12 @@ BOOL LLMediaCtrl::handleRightMouseUp( S32 x, S32 y, MASK mask )
|
|||
BOOL LLMediaCtrl::handleRightMouseDown( S32 x, S32 y, MASK mask )
|
||||
{
|
||||
if (LLPanel::handleRightMouseDown(x, y, mask)) return TRUE;
|
||||
convertInputCoords(x, y);
|
||||
|
||||
S32 media_x = x, media_y = y;
|
||||
convertInputCoords(media_x, media_y);
|
||||
|
||||
if (mMediaSource)
|
||||
mMediaSource->mouseDown(x, y, mask, 1);
|
||||
mMediaSource->mouseDown(media_x, media_y, mask, 1);
|
||||
|
||||
gFocusMgr.setMouseCapture( this );
|
||||
|
||||
|
|
@ -316,6 +321,12 @@ BOOL LLMediaCtrl::handleRightMouseDown( S32 x, S32 y, MASK mask )
|
|||
setFocus( TRUE );
|
||||
}
|
||||
|
||||
if (mContextMenu)
|
||||
{
|
||||
mContextMenu->show(x, y);
|
||||
LLMenuGL::showPopup(this, mContextMenu, x, y);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -378,6 +389,8 @@ void LLMediaCtrl::onFocusLost()
|
|||
//
|
||||
BOOL LLMediaCtrl::postBuild ()
|
||||
{
|
||||
mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
|
||||
"menu_media_ctrl.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
|
||||
setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChange, this, _2));
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -501,22 +514,6 @@ bool LLMediaCtrl::canNavigateForward()
|
|||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void LLMediaCtrl::set404RedirectUrl( std::string redirect_url )
|
||||
{
|
||||
if(mMediaSource && mMediaSource->hasMedia())
|
||||
mMediaSource->getMediaPlugin()->set_status_redirect( 404, redirect_url );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void LLMediaCtrl::clr404RedirectUrl()
|
||||
{
|
||||
if(mMediaSource && mMediaSource->hasMedia())
|
||||
mMediaSource->getMediaPlugin()->set_status_redirect(404, "");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
void LLMediaCtrl::clearCache()
|
||||
|
|
@ -626,6 +623,16 @@ void LLMediaCtrl::setTarget(const std::string& target)
|
|||
}
|
||||
}
|
||||
|
||||
void LLMediaCtrl::setErrorPageURL(const std::string& url)
|
||||
{
|
||||
mErrorPageURL = url;
|
||||
}
|
||||
|
||||
const std::string& LLMediaCtrl::getErrorPageURL()
|
||||
{
|
||||
return mErrorPageURL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
bool LLMediaCtrl::setCaretColor(unsigned int red, unsigned int green, unsigned int blue)
|
||||
|
|
@ -976,6 +983,16 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
|
|||
};
|
||||
break;
|
||||
|
||||
case MEDIA_EVENT_NAVIGATE_ERROR_PAGE:
|
||||
{
|
||||
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_ERROR_PAGE" << LL_ENDL;
|
||||
if ( mErrorPageURL.length() > 0 )
|
||||
{
|
||||
navigateTo(mErrorPageURL, "text/html");
|
||||
};
|
||||
};
|
||||
break;
|
||||
|
||||
case MEDIA_EVENT_CLICK_LINK_HREF:
|
||||
{
|
||||
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << self->getClickTarget() << "\", uri is " << self->getClickURL() << LL_ENDL;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
class LLViewBorder;
|
||||
class LLUICtrlFactory;
|
||||
class LLContextMenu;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
|
@ -63,6 +64,7 @@ public:
|
|||
|
||||
Optional<std::string> initial_mime_type;
|
||||
Optional<std::string> media_id;
|
||||
Optional<std::string> error_page_url;
|
||||
|
||||
Params();
|
||||
};
|
||||
|
|
@ -113,10 +115,9 @@ public:
|
|||
|
||||
void setTarget(const std::string& target);
|
||||
|
||||
// set/clear URL to visit when a 404 page is reached
|
||||
void set404RedirectUrl( std::string redirect_url );
|
||||
void clr404RedirectUrl();
|
||||
|
||||
void setErrorPageURL(const std::string& url);
|
||||
const std::string& getErrorPageURL();
|
||||
|
||||
// Clear the browser cache when the instance gets loaded
|
||||
void clearCache();
|
||||
|
||||
|
|
@ -179,6 +180,7 @@ public:
|
|||
std::string mHomePageUrl;
|
||||
std::string mHomePageMimeType;
|
||||
std::string mCurrentNavUrl;
|
||||
std::string mErrorPageURL;
|
||||
std::string mTarget;
|
||||
bool mIgnoreUIScale;
|
||||
bool mAlwaysRefresh;
|
||||
|
|
@ -194,6 +196,7 @@ public:
|
|||
bool mClearCache;
|
||||
class LLWindowShade* mWindowShade;
|
||||
bool mHoverTextChanged;
|
||||
LLContextMenu* mContextMenu;
|
||||
};
|
||||
|
||||
#endif // LL_LLMediaCtrl_H
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@
|
|||
#include "llviewercontrol.h"
|
||||
#include "llfloatermediabrowser.h"
|
||||
#include "llweb.h"
|
||||
#include "llhints.h"
|
||||
|
||||
#include "llinventorymodel.h"
|
||||
#include "lllandmarkactions.h"
|
||||
|
|
@ -324,6 +325,8 @@ BOOL LLNavigationBar::postBuild()
|
|||
LLTeleportHistory::getInstance()->setHistoryChangedCallback(
|
||||
boost::bind(&LLNavigationBar::onTeleportHistoryChanged, this));
|
||||
|
||||
LLHints::registerHintTarget("nav_bar", LLView::getHandle());
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1196,6 +1196,12 @@ void LLPanelEditWearable::onTabExpandedCollapsed(const LLSD& param, U8 index)
|
|||
|
||||
void LLPanelEditWearable::changeCamera(U8 subpart)
|
||||
{
|
||||
// Don't change the camera if this type doesn't have a camera switch.
|
||||
// Useful for wearables like physics that don't have an associated physical body part.
|
||||
if (LLWearableType::getDisableCameraSwitch(mWearablePtr->getType()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
const LLEditWearableDictionary::WearableEntry *wearable_entry = LLEditWearableDictionary::getInstance()->getWearable(mWearablePtr->getType());
|
||||
if (!wearable_entry)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -214,7 +214,9 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
|
|||
}
|
||||
updateLocationCombo(false);
|
||||
|
||||
gSavedSettings.getControl("SessionSettingsFile")->getSignal()->connect(boost::bind(&onModeChange));
|
||||
LLUICtrl& mode_combo = getChildRef<LLUICtrl>("mode_combo");
|
||||
mode_combo.setValue(gSavedSettings.getString("SessionSettingsFile"));
|
||||
mode_combo.setCommitCallback(boost::bind(&LLPanelLogin::onModeChange, this, getChild<LLUICtrl>("mode_combo")->getValue(), _2));
|
||||
|
||||
LLComboBox* server_choice_combo = sInstance->getChild<LLComboBox>("server_combo");
|
||||
server_choice_combo->setCommitCallback(onSelectServer, NULL);
|
||||
|
|
@ -1159,23 +1161,26 @@ void LLPanelLogin::updateLoginPanelLinks()
|
|||
sInstance->getChildView("forgot_password_text")->setVisible( system_grid);
|
||||
}
|
||||
|
||||
//static
|
||||
void LLPanelLogin::onModeChange()
|
||||
void LLPanelLogin::onModeChange(const LLSD& original_value, const LLSD& new_value)
|
||||
{
|
||||
LLNotificationsUtil::add("ModeChange", LLSD(), LLSD(), boost::bind(&onModeChangeConfirm, _1, _2));
|
||||
if (original_value.asString() != new_value.asString())
|
||||
{
|
||||
LLNotificationsUtil::add("ModeChange", LLSD(), LLSD(), boost::bind(&LLPanelLogin::onModeChangeConfirm, this, original_value, new_value, _1, _2));
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLPanelLogin::onModeChangeConfirm(const LLSD& notification, const LLSD& response)
|
||||
void LLPanelLogin::onModeChangeConfirm(const LLSD& original_value, const LLSD& new_value, const LLSD& notification, const LLSD& response)
|
||||
{
|
||||
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
|
||||
switch (option)
|
||||
{
|
||||
case 0:
|
||||
LLAppViewer::instance()->requestQuit();
|
||||
gSavedSettings.getControl("SessionSettingsFile")->set(new_value);
|
||||
LLAppViewer::instance()->forceQuit();
|
||||
break;
|
||||
case 1:
|
||||
// do nothing
|
||||
// revert to original value
|
||||
getChild<LLUICtrl>("mode_combo")->setValue(original_value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -98,8 +98,8 @@ private:
|
|||
static void onServerComboLostFocus(LLFocusableElement*);
|
||||
static void updateServerCombo();
|
||||
static void updateStartSLURL();
|
||||
static void onModeChange();
|
||||
static void onModeChangeConfirm(const LLSD& notification, const LLSD& response);
|
||||
void onModeChange(const LLSD& original_value, const LLSD& new_value);
|
||||
void onModeChangeConfirm(const LLSD& original_value, const LLSD& new_value, const LLSD& notification, const LLSD& response);
|
||||
|
||||
static void updateLoginPanelLinks();
|
||||
|
||||
|
|
|
|||
|
|
@ -67,8 +67,6 @@ BOOL LLPanelMe::postBuild()
|
|||
{
|
||||
LLPanelProfile::postBuild();
|
||||
|
||||
getTabContainer()[PANEL_PROFILE]->childSetAction("edit_profile_btn", boost::bind(&LLPanelMe::onEditProfileClicked, this), this);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -135,7 +133,11 @@ void LLPanelMe::buildEditPanel()
|
|||
if (NULL == mEditPanel)
|
||||
{
|
||||
mEditPanel = new LLPanelMyProfileEdit();
|
||||
mEditPanel->childSetAction("save_btn", boost::bind(&LLPanelMe::onSaveChangesClicked, this), this);
|
||||
|
||||
// Note: Remove support for editing profile through this method.
|
||||
// All profile editing should go through the web.
|
||||
//mEditPanel->childSetAction("save_btn", boost::bind(&LLPanelMe::onSaveChangesClicked, this), this);
|
||||
|
||||
mEditPanel->childSetAction("cancel_btn", boost::bind(&LLPanelMe::onCancelClicked, this), this);
|
||||
}
|
||||
}
|
||||
|
|
@ -147,22 +149,6 @@ void LLPanelMe::onEditProfileClicked()
|
|||
togglePanel(mEditPanel, getAvatarId()); // open
|
||||
}
|
||||
|
||||
void LLPanelMe::onSaveChangesClicked()
|
||||
{
|
||||
LLAvatarData data = LLAvatarData();
|
||||
data.avatar_id = gAgent.getID();
|
||||
data.image_id = mEditPanel->getChild<LLTextureCtrl>(PICKER_SECOND_LIFE)->getImageAssetID();
|
||||
data.fl_image_id = mEditPanel->getChild<LLTextureCtrl>(PICKER_FIRST_LIFE)->getImageAssetID();
|
||||
data.about_text = mEditPanel->getChild<LLUICtrl>("sl_description_edit")->getValue().asString();
|
||||
data.fl_about_text = mEditPanel->getChild<LLUICtrl>("fl_description_edit")->getValue().asString();
|
||||
data.profile_url = mEditPanel->getChild<LLUICtrl>("homepage_edit")->getValue().asString();
|
||||
data.allow_publish = mEditPanel->getChild<LLUICtrl>("show_in_search_checkbox")->getValue();
|
||||
|
||||
LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesUpdate(&data);
|
||||
togglePanel(mEditPanel); // close
|
||||
onOpen(getAvatarId());
|
||||
}
|
||||
|
||||
void LLPanelMe::onCancelClicked()
|
||||
{
|
||||
togglePanel(mEditPanel); // close
|
||||
|
|
|
|||
|
|
@ -58,7 +58,6 @@ private:
|
|||
void buildEditPanel();
|
||||
|
||||
void onEditProfileClicked();
|
||||
void onSaveChangesClicked();
|
||||
void onCancelClicked();
|
||||
|
||||
LLPanelMyProfileEdit * mEditPanel;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,124 +1,118 @@
|
|||
/**
|
||||
* @file llphysicsmotion.h
|
||||
* @brief Implementation of LLPhysicsMotion class.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLPHYSICSMOTIONCONTROLLER_H
|
||||
#define LL_LLPHYSICSMOTIONCONTROLLER_H
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Header files
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "llmotion.h"
|
||||
#include "llframetimer.h"
|
||||
|
||||
#define PHYSICS_MOTION_FADEIN_TIME 1.0f
|
||||
#define PHYSICS_MOTION_FADEOUT_TIME 1.0f
|
||||
|
||||
class LLPhysicsMotion;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// class LLPhysicsMotion
|
||||
//-----------------------------------------------------------------------------
|
||||
class LLPhysicsMotionController :
|
||||
public LLMotion
|
||||
{
|
||||
public:
|
||||
// Constructor
|
||||
LLPhysicsMotionController(const LLUUID &id);
|
||||
|
||||
// Destructor
|
||||
virtual ~LLPhysicsMotionController();
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
// functions to support MotionController and MotionRegistry
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// static constructor
|
||||
// all subclasses must implement such a function and register it
|
||||
static LLMotion *create(const LLUUID &id) { return new LLPhysicsMotionController(id); }
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
// animation callbacks to be implemented by subclasses
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// motions must specify whether or not they loop
|
||||
virtual BOOL getLoop() { return TRUE; }
|
||||
|
||||
// motions must report their total duration
|
||||
virtual F32 getDuration() { return 0.0; }
|
||||
|
||||
// motions must report their "ease in" duration
|
||||
virtual F32 getEaseInDuration() { return PHYSICS_MOTION_FADEIN_TIME; }
|
||||
|
||||
// motions must report their "ease out" duration.
|
||||
virtual F32 getEaseOutDuration() { return PHYSICS_MOTION_FADEOUT_TIME; }
|
||||
|
||||
// called to determine when a motion should be activated/deactivated based on avatar pixel coverage
|
||||
virtual F32 getMinPixelArea();
|
||||
|
||||
// motions must report their priority
|
||||
virtual LLJoint::JointPriority getPriority() { return LLJoint::MEDIUM_PRIORITY; }
|
||||
|
||||
virtual LLMotionBlendType getBlendType() { return ADDITIVE_BLEND; }
|
||||
|
||||
// run-time (post constructor) initialization,
|
||||
// called after parameters have been set
|
||||
// must return true to indicate success and be available for activation
|
||||
virtual LLMotionInitStatus onInitialize(LLCharacter *character);
|
||||
|
||||
// called when a motion is activated
|
||||
// must return TRUE to indicate success, or else
|
||||
// it will be deactivated
|
||||
virtual BOOL onActivate();
|
||||
|
||||
// called per time step
|
||||
// must return TRUE while it is active, and
|
||||
// must return FALSE when the motion is completed.
|
||||
virtual BOOL onUpdate(F32 time, U8* joint_mask);
|
||||
|
||||
// called when a motion is deactivated
|
||||
virtual void onDeactivate();
|
||||
|
||||
LLCharacter* getCharacter() { return mCharacter; }
|
||||
|
||||
protected:
|
||||
void addMotion(LLPhysicsMotion *motion);
|
||||
private:
|
||||
LLCharacter* mCharacter;
|
||||
|
||||
typedef std::vector<LLPhysicsMotion *> motion_vec_t;
|
||||
motion_vec_t mMotions;
|
||||
};
|
||||
|
||||
#endif // LL_LLPHYSICSMOTION_H
|
||||
|
||||
/**
|
||||
* @file llphysicsmotion.h
|
||||
* @brief Implementation of LLPhysicsMotion class.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2011, 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_LLPHYSICSMOTIONCONTROLLER_H
|
||||
#define LL_LLPHYSICSMOTIONCONTROLLER_H
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Header files
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "llmotion.h"
|
||||
#include "llframetimer.h"
|
||||
|
||||
#define PHYSICS_MOTION_FADEIN_TIME 1.0f
|
||||
#define PHYSICS_MOTION_FADEOUT_TIME 1.0f
|
||||
|
||||
class LLPhysicsMotion;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// class LLPhysicsMotion
|
||||
//-----------------------------------------------------------------------------
|
||||
class LLPhysicsMotionController :
|
||||
public LLMotion
|
||||
{
|
||||
public:
|
||||
// Constructor
|
||||
LLPhysicsMotionController(const LLUUID &id);
|
||||
|
||||
// Destructor
|
||||
virtual ~LLPhysicsMotionController();
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
// functions to support MotionController and MotionRegistry
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// static constructor
|
||||
// all subclasses must implement such a function and register it
|
||||
static LLMotion *create(const LLUUID &id) { return new LLPhysicsMotionController(id); }
|
||||
|
||||
public:
|
||||
//-------------------------------------------------------------------------
|
||||
// animation callbacks to be implemented by subclasses
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// motions must specify whether or not they loop
|
||||
virtual BOOL getLoop() { return TRUE; }
|
||||
|
||||
// motions must report their total duration
|
||||
virtual F32 getDuration() { return 0.0; }
|
||||
|
||||
// motions must report their "ease in" duration
|
||||
virtual F32 getEaseInDuration() { return PHYSICS_MOTION_FADEIN_TIME; }
|
||||
|
||||
// motions must report their "ease out" duration.
|
||||
virtual F32 getEaseOutDuration() { return PHYSICS_MOTION_FADEOUT_TIME; }
|
||||
|
||||
// called to determine when a motion should be activated/deactivated based on avatar pixel coverage
|
||||
virtual F32 getMinPixelArea();
|
||||
|
||||
// motions must report their priority
|
||||
virtual LLJoint::JointPriority getPriority() { return LLJoint::MEDIUM_PRIORITY; }
|
||||
|
||||
virtual LLMotionBlendType getBlendType() { return ADDITIVE_BLEND; }
|
||||
|
||||
// run-time (post constructor) initialization,
|
||||
// called after parameters have been set
|
||||
// must return true to indicate success and be available for activation
|
||||
virtual LLMotionInitStatus onInitialize(LLCharacter *character);
|
||||
|
||||
// called when a motion is activated
|
||||
// must return TRUE to indicate success, or else
|
||||
// it will be deactivated
|
||||
virtual BOOL onActivate();
|
||||
|
||||
// called per time step
|
||||
// must return TRUE while it is active, and
|
||||
// must return FALSE when the motion is completed.
|
||||
virtual BOOL onUpdate(F32 time, U8* joint_mask);
|
||||
|
||||
// called when a motion is deactivated
|
||||
virtual void onDeactivate();
|
||||
|
||||
LLCharacter* getCharacter() { return mCharacter; }
|
||||
|
||||
protected:
|
||||
void addMotion(LLPhysicsMotion *motion);
|
||||
private:
|
||||
LLCharacter* mCharacter;
|
||||
|
||||
typedef std::vector<LLPhysicsMotion *> motion_vec_t;
|
||||
motion_vec_t mMotions;
|
||||
};
|
||||
|
||||
#endif // LL_LLPHYSICSMOTION_H
|
||||
|
||||
|
|
|
|||
|
|
@ -490,6 +490,16 @@ void LLPolyMorphTarget::apply( ESex avatar_sex )
|
|||
|
||||
mLastSex = avatar_sex;
|
||||
|
||||
// Check for NaN condition (NaN is detected if a variable doesn't equal itself.
|
||||
if (mCurWeight != mCurWeight)
|
||||
{
|
||||
mCurWeight = 0.0;
|
||||
}
|
||||
if (mLastWeight != mLastWeight)
|
||||
{
|
||||
mLastWeight = mCurWeight+.001;
|
||||
}
|
||||
|
||||
// perform differential update of morph
|
||||
F32 delta_weight = ( getSex() & avatar_sex ) ? (mCurWeight - mLastWeight) : (getDefaultWeight() - mLastWeight);
|
||||
// store last weight
|
||||
|
|
|
|||
|
|
@ -517,17 +517,15 @@ BOOL LLSelectMgr::removeObjectFromSelections(const LLUUID &id)
|
|||
{
|
||||
BOOL object_found = FALSE;
|
||||
LLTool *tool = NULL;
|
||||
if (!gNoRender)
|
||||
{
|
||||
tool = LLToolMgr::getInstance()->getCurrentTool();
|
||||
|
||||
// It's possible that the tool is editing an object that is not selected
|
||||
LLViewerObject* tool_editing_object = tool->getEditingObject();
|
||||
if( tool_editing_object && tool_editing_object->mID == id)
|
||||
{
|
||||
tool->stopEditing();
|
||||
object_found = TRUE;
|
||||
}
|
||||
tool = LLToolMgr::getInstance()->getCurrentTool();
|
||||
|
||||
// It's possible that the tool is editing an object that is not selected
|
||||
LLViewerObject* tool_editing_object = tool->getEditingObject();
|
||||
if( tool_editing_object && tool_editing_object->mID == id)
|
||||
{
|
||||
tool->stopEditing();
|
||||
object_found = TRUE;
|
||||
}
|
||||
|
||||
// Iterate through selected objects list and kill the object
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@
|
|||
|
||||
#include "llsidepanelappearance.h"
|
||||
|
||||
#include "llsidetraylistener.h"
|
||||
|
||||
//#include "llscrollcontainer.h"
|
||||
|
||||
using namespace std;
|
||||
|
|
@ -71,6 +73,8 @@ static const std::string TAB_PANEL_CAPTION_TITLE_BOX = "sidetray_tab_title";
|
|||
|
||||
LLSideTray* LLSideTray::sInstance = 0;
|
||||
|
||||
static LLSideTrayListener sSideTrayListener(LLSideTray::getInstance);
|
||||
|
||||
// static
|
||||
LLSideTray* LLSideTray::getInstance()
|
||||
{
|
||||
|
|
@ -454,6 +458,11 @@ LLSideTrayTab* LLSideTrayTab::createInstance ()
|
|||
return tab;
|
||||
}
|
||||
|
||||
// Now that we know the definition of LLSideTrayTab, we can implement
|
||||
// tab_cast.
|
||||
template <>
|
||||
LLPanel* tab_cast<LLPanel*>(LLSideTrayTab* tab) { return tab; }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// LLSideTrayButton
|
||||
// Side Tray tab button with "tear off" handling.
|
||||
|
|
@ -567,6 +576,8 @@ LLSideTray::LLSideTray(const Params& params)
|
|||
// register handler function to process data from the xml.
|
||||
// panel_name should be specified via "parameter" attribute.
|
||||
commit.add("SideTray.ShowPanel", boost::bind(&LLSideTray::showPanel, this, _2, LLUUID::null));
|
||||
commit.add("SideTray.Toggle", boost::bind(&LLSideTray::onToggleCollapse, this));
|
||||
commit.add("SideTray.Collapse", boost::bind(&LLSideTray::collapseSideBar, this));
|
||||
LLTransientFloaterMgr::getInstance()->addControlView(this);
|
||||
LLView* side_bar_tabs = gViewerWindow->getRootView()->getChildView("side_bar_tabs");
|
||||
if (side_bar_tabs != NULL)
|
||||
|
|
|
|||
|
|
@ -33,6 +33,13 @@
|
|||
class LLAccordionCtrl;
|
||||
class LLSideTrayTab;
|
||||
|
||||
// Deal with LLSideTrayTab being opaque. Generic do-nothing cast...
|
||||
template <class T>
|
||||
T tab_cast(LLSideTrayTab* tab) { return tab; }
|
||||
// specialized for implementation in presence of LLSideTrayTab definition
|
||||
template <>
|
||||
LLPanel* tab_cast<LLPanel*>(LLSideTrayTab* tab);
|
||||
|
||||
// added inheritance from LLDestroyClass<LLSideTray> to enable Side Tray perform necessary actions
|
||||
// while disconnecting viewer in LLAppViewer::disconnectViewer().
|
||||
// LLDestroyClassList::instance().fireCallbacks() calls destroyClass method. See EXT-245.
|
||||
|
|
@ -221,6 +228,9 @@ private:
|
|||
}
|
||||
|
||||
private:
|
||||
// Since we provide no public way to query mTabs and mDetachedTabs, give
|
||||
// LLSideTrayListener friend access.
|
||||
friend class LLSideTrayListener;
|
||||
LLPanel* mButtonsPanel;
|
||||
typedef std::map<std::string,LLButton*> button_map_t;
|
||||
button_map_t mTabButtons;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,162 @@
|
|||
/**
|
||||
* @file llsidetraylistener.cpp
|
||||
* @author Nat Goodspeed
|
||||
* @date 2011-02-15
|
||||
* @brief Implementation for llsidetraylistener.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2011&license=lgpl$
|
||||
* Copyright (c) 2011, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
// Precompiled header
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
// associated header
|
||||
#include "llsidetraylistener.h"
|
||||
// STL headers
|
||||
// std headers
|
||||
// external library headers
|
||||
// other Linden headers
|
||||
#include "llsidetray.h"
|
||||
#include "llsdutil.h"
|
||||
|
||||
LLSideTrayListener::LLSideTrayListener(const Getter& getter):
|
||||
LLEventAPI("LLSideTray",
|
||||
"Operations on side tray (e.g. query state, query tabs)"),
|
||||
mGetter(getter)
|
||||
{
|
||||
add("getCollapsed", "Send on [\"reply\"] an [\"open\"] Boolean",
|
||||
&LLSideTrayListener::getCollapsed, LLSDMap("reply", LLSD()));
|
||||
add("getTabs",
|
||||
"Send on [\"reply\"] a map of tab names and info about them",
|
||||
&LLSideTrayListener::getTabs, LLSDMap("reply", LLSD()));
|
||||
add("getPanels",
|
||||
"Send on [\"reply\"] data about panels available with SideTray.ShowPanel",
|
||||
&LLSideTrayListener::getPanels, LLSDMap("reply", LLSD()));
|
||||
}
|
||||
|
||||
void LLSideTrayListener::getCollapsed(const LLSD& event) const
|
||||
{
|
||||
sendReply(LLSDMap("open", ! mGetter()->getCollapsed()), event);
|
||||
}
|
||||
|
||||
void LLSideTrayListener::getTabs(const LLSD& event) const
|
||||
{
|
||||
LLSD reply;
|
||||
|
||||
LLSideTray* tray = mGetter();
|
||||
LLSD::Integer ord(0);
|
||||
for (LLSideTray::child_list_const_iter_t chi(tray->beginChild()), chend(tray->endChild());
|
||||
chi != chend; ++chi, ++ord)
|
||||
{
|
||||
LLView* child = *chi;
|
||||
// How much info is important? Toss in as much as seems reasonable for
|
||||
// each tab. But to me, at least for the moment, the most important
|
||||
// item is the tab name.
|
||||
LLSD info;
|
||||
// I like the idea of returning a map keyed by tab name. But as
|
||||
// compared to an array of maps, that loses sequence information.
|
||||
// Address that by indicating the original order in each map entry.
|
||||
info["ord"] = ord;
|
||||
info["visible"] = bool(child->getVisible());
|
||||
info["enabled"] = bool(child->getEnabled());
|
||||
info["available"] = child->isAvailable();
|
||||
reply[child->getName()] = info;
|
||||
}
|
||||
|
||||
sendReply(reply, event);
|
||||
}
|
||||
|
||||
static LLSD getTabInfo(LLPanel* tab)
|
||||
{
|
||||
LLSD panels;
|
||||
for (LLPanel::tree_iterator_t ti(tab->beginTreeDFS()), tend(tab->endTreeDFS());
|
||||
ti != tend; ++ti)
|
||||
{
|
||||
// *ti is actually an LLView*, which had better not be NULL
|
||||
LLView* view(*ti);
|
||||
if (! view)
|
||||
{
|
||||
LL_ERRS("LLSideTrayListener") << "LLSideTrayTab '" << tab->getName()
|
||||
<< "' has a NULL child LLView*" << LL_ENDL;
|
||||
}
|
||||
|
||||
// The logic we use to decide what "panel" names to return is heavily
|
||||
// based on LLSideTray::showPanel(): the function that actually
|
||||
// implements the "SideTray.ShowPanel" operation. showPanel(), in
|
||||
// turn, depends on LLSideTray::openChildPanel(): when
|
||||
// openChildPanel() returns non-NULL, showPanel() stops searching
|
||||
// attached and detached LLSideTrayTab tabs.
|
||||
|
||||
// For each LLSideTrayTab, openChildPanel() first calls
|
||||
// findChildView(panel_name, true). In other words, panel_name need
|
||||
// not be a direct LLSideTrayTab child, it's sought recursively.
|
||||
// That's why we use (begin|end)TreeDFS() in this loop.
|
||||
|
||||
// But this tree_iterator_t loop will actually traverse every widget
|
||||
// in every panel. Returning all those names will not help our caller:
|
||||
// passing most such names to openChildPanel() would not do what we
|
||||
// want. Even though the code suggests that passing ANY valid
|
||||
// side-panel widget name to openChildPanel() will open the tab
|
||||
// containing that widget, results could get confusing since followup
|
||||
// (onOpen()) logic wouldn't be invoked, and showPanel() wouldn't stop
|
||||
// searching because openChildPanel() would return NULL.
|
||||
|
||||
// We must filter these LLView items, using logic that (sigh!) mirrors
|
||||
// openChildPanel()'s own.
|
||||
|
||||
// openChildPanel() returns a non-NULL LLPanel* when either:
|
||||
// - the LLView is a direct child of an LLSideTrayPanelContainer
|
||||
// - the LLView is itself an LLPanel.
|
||||
// But as LLSideTrayPanelContainer can directly contain LLView items
|
||||
// that are NOT themselves LLPanels (e.g. "sidebar_me" contains an
|
||||
// LLButton called "Jump Right Arrow"), we'd better focus only on
|
||||
// LLSideTrayPanelContainer children that are themselves LLPanel
|
||||
// items. Which means that the second test completely subsumes the
|
||||
// first.
|
||||
LLPanel* panel(dynamic_cast<LLPanel*>(view));
|
||||
if (panel)
|
||||
{
|
||||
// Maybe it's overkill to construct an LLSD::Map for each panel, but
|
||||
// the possibility remains that we might want to deliver more info
|
||||
// about each panel than just its name.
|
||||
panels.append(LLSDMap("name", panel->getName()));
|
||||
}
|
||||
}
|
||||
|
||||
return LLSDMap("panels", panels);
|
||||
}
|
||||
|
||||
void LLSideTrayListener::getPanels(const LLSD& event) const
|
||||
{
|
||||
LLSD reply;
|
||||
|
||||
LLSideTray* tray = mGetter();
|
||||
// Iterate through the attached tabs.
|
||||
LLSD::Integer ord(0);
|
||||
for (LLSideTray::child_vector_t::const_iterator
|
||||
ati(tray->mTabs.begin()), atend(tray->mTabs.end());
|
||||
ati != atend; ++ati)
|
||||
{
|
||||
// We don't have access to LLSideTrayTab: the class definition is
|
||||
// hidden in llsidetray.cpp. But as LLSideTrayTab isa LLPanel, use the
|
||||
// LLPanel API. Unfortunately, without the LLSideTrayTab definition,
|
||||
// the compiler doesn't even know this LLSideTrayTab* is an LLPanel*.
|
||||
// Persuade it.
|
||||
LLPanel* tab(tab_cast<LLPanel*>(*ati));
|
||||
reply[tab->getName()] = getTabInfo(tab).with("attached", true).with("ord", ord);
|
||||
}
|
||||
|
||||
// Now iterate over the detached tabs. These can also be opened via
|
||||
// SideTray.ShowPanel.
|
||||
ord = 0;
|
||||
for (LLSideTray::child_vector_t::const_iterator
|
||||
dti(tray->mDetachedTabs.begin()), dtend(tray->mDetachedTabs.end());
|
||||
dti != dtend; ++dti)
|
||||
{
|
||||
LLPanel* tab(tab_cast<LLPanel*>(*dti));
|
||||
reply[tab->getName()] = getTabInfo(tab).with("attached", false).with("ord", ord);
|
||||
}
|
||||
|
||||
sendReply(reply, event);
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* @file llsidetraylistener.h
|
||||
* @author Nat Goodspeed
|
||||
* @date 2011-02-15
|
||||
* @brief
|
||||
*
|
||||
* $LicenseInfo:firstyear=2011&license=lgpl$
|
||||
* Copyright (c) 2011, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#if ! defined(LL_LLSIDETRAYLISTENER_H)
|
||||
#define LL_LLSIDETRAYLISTENER_H
|
||||
|
||||
#include "lleventapi.h"
|
||||
#include <boost/function.hpp>
|
||||
|
||||
class LLSideTray;
|
||||
class LLSD;
|
||||
|
||||
class LLSideTrayListener: public LLEventAPI
|
||||
{
|
||||
typedef boost::function<LLSideTray*()> Getter;
|
||||
|
||||
public:
|
||||
LLSideTrayListener(const Getter& getter);
|
||||
|
||||
private:
|
||||
void getCollapsed(const LLSD& event) const;
|
||||
void getTabs(const LLSD& event) const;
|
||||
void getPanels(const LLSD& event) const;
|
||||
|
||||
Getter mGetter;
|
||||
};
|
||||
|
||||
#endif /* ! defined(LL_LLSIDETRAYLISTENER_H) */
|
||||
|
|
@ -354,11 +354,8 @@ bool idle_startup()
|
|||
|
||||
LLStringUtil::setLocale (LLTrans::getString(system));
|
||||
|
||||
if (!gNoRender)
|
||||
{
|
||||
//note: Removing this line will cause incorrect button size in the login screen. -- bao.
|
||||
gTextureList.updateImages(0.01f) ;
|
||||
}
|
||||
//note: Removing this line will cause incorrect button size in the login screen. -- bao.
|
||||
gTextureList.updateImages(0.01f) ;
|
||||
|
||||
if ( STATE_FIRST == LLStartUp::getStartupState() )
|
||||
{
|
||||
|
|
@ -673,6 +670,7 @@ bool idle_startup()
|
|||
{
|
||||
gUserCredential = gLoginHandler.initializeLoginInfo();
|
||||
}
|
||||
// Previous initializeLoginInfo may have generated user credentials. Re-check them.
|
||||
if (gUserCredential.isNull())
|
||||
{
|
||||
show_connect_box = TRUE;
|
||||
|
|
@ -731,9 +729,9 @@ bool idle_startup()
|
|||
{
|
||||
gUserCredential = gLoginHandler.initializeLoginInfo();
|
||||
}
|
||||
if (gNoRender)
|
||||
if (gHeadlessClient)
|
||||
{
|
||||
LL_ERRS("AppInit") << "Need to autologin or use command line with norender!" << LL_ENDL;
|
||||
LL_WARNS("AppInit") << "Waiting at connection box in headless client. Did you mean to add autologin params?" << LL_ENDL;
|
||||
}
|
||||
// Make sure the process dialog doesn't hide things
|
||||
gViewerWindow->setShowProgress(FALSE);
|
||||
|
|
@ -940,10 +938,7 @@ bool idle_startup()
|
|||
|
||||
gViewerWindow->getWindow()->setCursor(UI_CURSOR_WAIT);
|
||||
|
||||
if (!gNoRender)
|
||||
{
|
||||
init_start_screen(agent_location_id);
|
||||
}
|
||||
init_start_screen(agent_location_id);
|
||||
|
||||
// Display the startup progress bar.
|
||||
gViewerWindow->setShowProgress(TRUE);
|
||||
|
|
@ -974,11 +969,6 @@ bool idle_startup()
|
|||
// Setting initial values...
|
||||
LLLoginInstance* login = LLLoginInstance::getInstance();
|
||||
login->setNotificationsInterface(LLNotifications::getInstance());
|
||||
if(gNoRender)
|
||||
{
|
||||
// HACK, skip optional updates if you're running drones
|
||||
login->setSkipOptionalUpdate(true);
|
||||
}
|
||||
|
||||
login->setSerialNumber(LLAppViewer::instance()->getSerialNumber());
|
||||
login->setLastExecEvent(gLastExecEvent);
|
||||
|
|
@ -1262,14 +1252,11 @@ bool idle_startup()
|
|||
gLoginMenuBarView->setVisible( FALSE );
|
||||
gLoginMenuBarView->setEnabled( FALSE );
|
||||
|
||||
if (!gNoRender)
|
||||
{
|
||||
// direct logging to the debug console's line buffer
|
||||
LLError::logToFixedBuffer(gDebugView->mDebugConsolep);
|
||||
|
||||
// set initial visibility of debug console
|
||||
gDebugView->mDebugConsolep->setVisible(gSavedSettings.getBOOL("ShowDebugConsole"));
|
||||
}
|
||||
// direct logging to the debug console's line buffer
|
||||
LLError::logToFixedBuffer(gDebugView->mDebugConsolep);
|
||||
|
||||
// set initial visibility of debug console
|
||||
gDebugView->mDebugConsolep->setVisible(gSavedSettings.getBOOL("ShowDebugConsole"));
|
||||
|
||||
//
|
||||
// Set message handlers
|
||||
|
|
@ -1297,7 +1284,7 @@ bool idle_startup()
|
|||
|
||||
//gCacheName is required for nearby chat history loading
|
||||
//so I just moved nearby history loading a few states further
|
||||
if (!gNoRender && gSavedPerAccountSettings.getBOOL("LogShowHistory"))
|
||||
if (gSavedPerAccountSettings.getBOOL("LogShowHistory"))
|
||||
{
|
||||
LLNearbyChat* nearby_chat = LLNearbyChat::getInstance();
|
||||
if (nearby_chat) nearby_chat->loadHistory();
|
||||
|
|
@ -1349,18 +1336,15 @@ bool idle_startup()
|
|||
gAgentCamera.resetCamera();
|
||||
|
||||
// Initialize global class data needed for surfaces (i.e. textures)
|
||||
if (!gNoRender)
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "Initializing sky..." << LL_ENDL;
|
||||
// Initialize all of the viewer object classes for the first time (doing things like texture fetches.
|
||||
LLGLState::checkStates();
|
||||
LLGLState::checkTextureChannels();
|
||||
LL_DEBUGS("AppInit") << "Initializing sky..." << LL_ENDL;
|
||||
// Initialize all of the viewer object classes for the first time (doing things like texture fetches.
|
||||
LLGLState::checkStates();
|
||||
LLGLState::checkTextureChannels();
|
||||
|
||||
gSky.init(initial_sun_direction);
|
||||
gSky.init(initial_sun_direction);
|
||||
|
||||
LLGLState::checkStates();
|
||||
LLGLState::checkTextureChannels();
|
||||
}
|
||||
LLGLState::checkStates();
|
||||
LLGLState::checkTextureChannels();
|
||||
|
||||
LL_DEBUGS("AppInit") << "Decoding images..." << LL_ENDL;
|
||||
// For all images pre-loaded into viewer cache, decode them.
|
||||
|
|
@ -1720,46 +1704,43 @@ bool idle_startup()
|
|||
LLUIColorTable::instance().saveUserSettings();
|
||||
};
|
||||
|
||||
if (!gNoRender)
|
||||
// JC: Initializing audio requests many sounds for download.
|
||||
init_audio();
|
||||
|
||||
// JC: Initialize "active" gestures. This may also trigger
|
||||
// many gesture downloads, if this is the user's first
|
||||
// time on this machine or -purge has been run.
|
||||
LLSD gesture_options
|
||||
= LLLoginInstance::getInstance()->getResponse("gestures");
|
||||
if (gesture_options.isDefined())
|
||||
{
|
||||
// JC: Initializing audio requests many sounds for download.
|
||||
init_audio();
|
||||
|
||||
// JC: Initialize "active" gestures. This may also trigger
|
||||
// many gesture downloads, if this is the user's first
|
||||
// time on this machine or -purge has been run.
|
||||
LLSD gesture_options
|
||||
= LLLoginInstance::getInstance()->getResponse("gestures");
|
||||
if (gesture_options.isDefined())
|
||||
LL_DEBUGS("AppInit") << "Gesture Manager loading " << gesture_options.size()
|
||||
<< LL_ENDL;
|
||||
uuid_vec_t item_ids;
|
||||
for(LLSD::array_const_iterator resp_it = gesture_options.beginArray(),
|
||||
end = gesture_options.endArray(); resp_it != end; ++resp_it)
|
||||
{
|
||||
LL_DEBUGS("AppInit") << "Gesture Manager loading " << gesture_options.size()
|
||||
<< LL_ENDL;
|
||||
uuid_vec_t item_ids;
|
||||
for(LLSD::array_const_iterator resp_it = gesture_options.beginArray(),
|
||||
end = gesture_options.endArray(); resp_it != end; ++resp_it)
|
||||
{
|
||||
// If the id is not specifed in the LLSD,
|
||||
// the LLSD operator[]() will return a null LLUUID.
|
||||
LLUUID item_id = (*resp_it)["item_id"];
|
||||
LLUUID asset_id = (*resp_it)["asset_id"];
|
||||
// If the id is not specifed in the LLSD,
|
||||
// the LLSD operator[]() will return a null LLUUID.
|
||||
LLUUID item_id = (*resp_it)["item_id"];
|
||||
LLUUID asset_id = (*resp_it)["asset_id"];
|
||||
|
||||
if (item_id.notNull() && asset_id.notNull())
|
||||
{
|
||||
// Could schedule and delay these for later.
|
||||
const BOOL no_inform_server = FALSE;
|
||||
const BOOL no_deactivate_similar = FALSE;
|
||||
LLGestureMgr::instance().activateGestureWithAsset(item_id, asset_id,
|
||||
no_inform_server,
|
||||
no_deactivate_similar);
|
||||
// We need to fetch the inventory items for these gestures
|
||||
// so we have the names to populate the UI.
|
||||
item_ids.push_back(item_id);
|
||||
}
|
||||
if (item_id.notNull() && asset_id.notNull())
|
||||
{
|
||||
// Could schedule and delay these for later.
|
||||
const BOOL no_inform_server = FALSE;
|
||||
const BOOL no_deactivate_similar = FALSE;
|
||||
LLGestureMgr::instance().activateGestureWithAsset(item_id, asset_id,
|
||||
no_inform_server,
|
||||
no_deactivate_similar);
|
||||
// We need to fetch the inventory items for these gestures
|
||||
// so we have the names to populate the UI.
|
||||
item_ids.push_back(item_id);
|
||||
}
|
||||
// no need to add gesture to inventory observer, it's already made in constructor
|
||||
LLGestureMgr::instance().setFetchIDs(item_ids);
|
||||
LLGestureMgr::instance().startFetch();
|
||||
}
|
||||
// no need to add gesture to inventory observer, it's already made in constructor
|
||||
LLGestureMgr::instance().setFetchIDs(item_ids);
|
||||
LLGestureMgr::instance().startFetch();
|
||||
}
|
||||
gDisplaySwapBuffers = TRUE;
|
||||
|
||||
|
|
@ -1780,13 +1761,6 @@ bool idle_startup()
|
|||
// JC - 7/20/2002
|
||||
gViewerWindow->sendShapeToSim();
|
||||
|
||||
|
||||
// Ignore stipend information for now. Money history is on the web site.
|
||||
// if needed, show the L$ history window
|
||||
//if (stipend_since_login && !gNoRender)
|
||||
//{
|
||||
//}
|
||||
|
||||
// The reason we show the alert is because we want to
|
||||
// reduce confusion for when you log in and your provided
|
||||
// location is not your expected location. So, if this is
|
||||
|
|
@ -2715,7 +2689,7 @@ bool LLStartUp::dispatchURL()
|
|||
|| (dx*dx > SLOP*SLOP)
|
||||
|| (dy*dy > SLOP*SLOP) )
|
||||
{
|
||||
LLURLDispatcher::dispatch(getStartSLURL().getSLURLString(),
|
||||
LLURLDispatcher::dispatch(getStartSLURL().getSLURLString(), "clicked",
|
||||
NULL, false);
|
||||
}
|
||||
return true;
|
||||
|
|
@ -3212,7 +3186,7 @@ bool process_login_success_response()
|
|||
|
||||
void transition_back_to_login_panel(const std::string& emsg)
|
||||
{
|
||||
if (gNoRender)
|
||||
if (gHeadlessClient && gSavedSettings.getBOOL("AutoLogin"))
|
||||
{
|
||||
LL_WARNS("AppInit") << "Failed to login!" << LL_ENDL;
|
||||
LL_WARNS("AppInit") << emsg << LL_ENDL;
|
||||
|
|
|
|||
|
|
@ -340,11 +340,6 @@ void LLSurface::connectNeighbor(LLSurface *neighborp, U32 direction)
|
|||
S32 i;
|
||||
LLSurfacePatch *patchp, *neighbor_patchp;
|
||||
|
||||
if (gNoRender)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mNeighbors[direction] = neighborp;
|
||||
neighborp->mNeighbors[gDirOpposite[direction]] = this;
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ void send_texture_stats_to_sim(const LLSD &texture_stats)
|
|||
{
|
||||
LLSD texture_stats_report;
|
||||
// Only send stats if the agent is connected to a region.
|
||||
if (!gAgent.getRegion() || gNoRender)
|
||||
if (!gAgent.getRegion())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
#include "llavatarnamecache.h"
|
||||
#include "llviewercontrol.h"
|
||||
#include "llfocusmgr.h"
|
||||
//#include "llfirstuse.h"
|
||||
#include "llfirstuse.h"
|
||||
#include "llfloaterland.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llfloaterscriptdebug.h"
|
||||
|
|
@ -528,7 +528,26 @@ void LLToolPie::selectionPropertiesReceived()
|
|||
|
||||
BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
if (!mMouseOutsideSlop
|
||||
mHoverPick = gViewerWindow->pickImmediate(x, y, FALSE);
|
||||
LLViewerObject *parent = NULL;
|
||||
LLViewerObject *object = mHoverPick.getObject();
|
||||
if (object)
|
||||
{
|
||||
parent = object->getRootEdit();
|
||||
}
|
||||
|
||||
// Show screen-space highlight glow effect
|
||||
bool show_highlight = false;
|
||||
|
||||
if (handleMediaHover(mHoverPick))
|
||||
{
|
||||
// *NOTE: If you think the hover glow conflicts with the media outline, you
|
||||
// could disable it here.
|
||||
show_highlight = true;
|
||||
// cursor set by media object
|
||||
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
|
||||
}
|
||||
else if (!mMouseOutsideSlop
|
||||
&& mMouseButtonDown
|
||||
&& gSavedSettings.getBOOL("ClickToWalk"))
|
||||
{
|
||||
|
|
@ -538,71 +557,58 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
|
|||
if (delta_x * delta_x + delta_y * delta_y > threshold * threshold)
|
||||
{
|
||||
startCameraSteering();
|
||||
steerCameraWithMouse(x, y);
|
||||
gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB);
|
||||
}
|
||||
else
|
||||
{
|
||||
gViewerWindow->setCursor(UI_CURSOR_ARROW);
|
||||
}
|
||||
}
|
||||
|
||||
mHoverPick = gViewerWindow->pickImmediate(x, y, FALSE);
|
||||
|
||||
if (inCameraSteerMode())
|
||||
else if (inCameraSteerMode())
|
||||
{
|
||||
steerCameraWithMouse(x, y);
|
||||
gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// perform a separate pick that detects transparent objects since they respond to 1-click actions
|
||||
LLPickInfo click_action_pick = gViewerWindow->pickImmediate(x, y, TRUE);
|
||||
|
||||
// Show screen-space highlight glow effect
|
||||
bool show_highlight = false;
|
||||
LLViewerObject *parent = NULL;
|
||||
LLViewerObject *object = mHoverPick.getObject();
|
||||
|
||||
if (object)
|
||||
{
|
||||
parent = object->getRootEdit();
|
||||
}
|
||||
|
||||
LLViewerObject* click_action_object = click_action_pick.getObject();
|
||||
if (handleMediaHover(mHoverPick))
|
||||
{
|
||||
// *NOTE: If you think the hover glow conflicts with the media outline, you
|
||||
// could disable it here.
|
||||
show_highlight = true;
|
||||
// cursor set by media object
|
||||
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
|
||||
}
|
||||
else if (click_action_object && useClickAction(mask, click_action_object, click_action_object->getRootEdit()))
|
||||
{
|
||||
show_highlight = true;
|
||||
ECursorType cursor = cursorFromObject(click_action_object);
|
||||
gViewerWindow->setCursor(cursor);
|
||||
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
|
||||
}
|
||||
|
||||
else if ((object && !object->isAvatar() && object->usePhysics())
|
||||
|| (parent && !parent->isAvatar() && parent->usePhysics()))
|
||||
{
|
||||
show_highlight = true;
|
||||
gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB);
|
||||
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
|
||||
}
|
||||
else if ( (object && object->flagHandleTouch())
|
||||
|| (parent && parent->flagHandleTouch()))
|
||||
{
|
||||
show_highlight = true;
|
||||
gViewerWindow->setCursor(UI_CURSOR_HAND);
|
||||
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
|
||||
}
|
||||
else
|
||||
{
|
||||
gViewerWindow->setCursor(UI_CURSOR_ARROW);
|
||||
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
|
||||
// perform a separate pick that detects transparent objects since they respond to 1-click actions
|
||||
LLPickInfo click_action_pick = gViewerWindow->pickImmediate(x, y, TRUE);
|
||||
|
||||
if(!object)
|
||||
LLViewerObject* click_action_object = click_action_pick.getObject();
|
||||
|
||||
if (click_action_object && useClickAction(mask, click_action_object, click_action_object->getRootEdit()))
|
||||
{
|
||||
LLViewerMediaFocus::getInstance()->clearHover();
|
||||
show_highlight = true;
|
||||
ECursorType cursor = cursorFromObject(click_action_object);
|
||||
gViewerWindow->setCursor(cursor);
|
||||
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
|
||||
}
|
||||
|
||||
else if ((object && !object->isAvatar() && object->usePhysics())
|
||||
|| (parent && !parent->isAvatar() && parent->usePhysics()))
|
||||
{
|
||||
show_highlight = true;
|
||||
gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB);
|
||||
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
|
||||
}
|
||||
else if ( (object && object->flagHandleTouch())
|
||||
|| (parent && parent->flagHandleTouch()))
|
||||
{
|
||||
show_highlight = true;
|
||||
gViewerWindow->setCursor(UI_CURSOR_HAND);
|
||||
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
|
||||
}
|
||||
else
|
||||
{
|
||||
gViewerWindow->setCursor(UI_CURSOR_ARROW);
|
||||
lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPie (inactive)" << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
if(!object)
|
||||
{
|
||||
LLViewerMediaFocus::getInstance()->clearHover();
|
||||
}
|
||||
|
||||
static LLCachedControl<bool> enable_highlight(
|
||||
|
|
@ -662,6 +668,8 @@ BOOL LLToolPie::handleMouseUp(S32 x, S32 y, MASK mask)
|
|||
mAutoPilotDestination->setDuration(3.f);
|
||||
|
||||
handle_go_to();
|
||||
LLFirstUse::notMoving(false);
|
||||
|
||||
mBlockClickToWalk = false;
|
||||
|
||||
return TRUE;
|
||||
|
|
@ -1430,6 +1438,7 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick)
|
|||
{
|
||||
// Make sure keyboard focus is set to the media focus object.
|
||||
gFocusMgr.setKeyboardFocus(LLViewerMediaFocus::getInstance());
|
||||
LLEditMenuHandler::gEditMenuHandler = LLViewerMediaFocus::instance().getFocusedMediaImpl();
|
||||
|
||||
media_impl->mouseDown(pick.mUVCoords, gKeyboard->currentMask(TRUE));
|
||||
mMediaMouseCaptureID = mep->getMediaID();
|
||||
|
|
@ -1709,8 +1718,13 @@ void LLToolPie::showVisualContextMenuEffect()
|
|||
effectp->setDuration(0.25f);
|
||||
}
|
||||
|
||||
typedef enum e_near_far
|
||||
{
|
||||
NEAR_INTERSECTION,
|
||||
FAR_INTERSECTION
|
||||
} ENearFar;
|
||||
|
||||
bool intersect_ray_with_sphere( const LLVector3& ray_pt, const LLVector3& ray_dir, const LLVector3& sphere_center, F32 sphere_radius, LLVector3& intersection_pt)
|
||||
bool intersect_ray_with_sphere( const LLVector3& ray_pt, const LLVector3& ray_dir, const LLVector3& sphere_center, F32 sphere_radius, e_near_far near_far, LLVector3& intersection_pt)
|
||||
{
|
||||
// do ray/sphere intersection by solving quadratic equation
|
||||
LLVector3 sphere_to_ray_start_vec = ray_pt - sphere_center;
|
||||
|
|
@ -1718,10 +1732,11 @@ bool intersect_ray_with_sphere( const LLVector3& ray_pt, const LLVector3& ray_di
|
|||
F32 C = sphere_to_ray_start_vec.lengthSquared() - (sphere_radius * sphere_radius);
|
||||
|
||||
F32 discriminant = B*B - 4.f*C;
|
||||
if (discriminant > 0.f)
|
||||
if (discriminant >= 0.f)
|
||||
{ // intersection detected, now find closest one
|
||||
F32 t0 = (-B - sqrtf(discriminant)) / 2.f;
|
||||
if (t0 > 0.f)
|
||||
|
||||
if (t0 > 0.f && near_far == NEAR_INTERSECTION)
|
||||
{
|
||||
intersection_pt = ray_pt + ray_dir * t0;
|
||||
}
|
||||
|
|
@ -1732,12 +1747,15 @@ bool intersect_ray_with_sphere( const LLVector3& ray_pt, const LLVector3& ray_di
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
else
|
||||
{ // no intersection
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void LLToolPie::startCameraSteering()
|
||||
{
|
||||
LLFirstUse::notMoving(false);
|
||||
mMouseOutsideSlop = true;
|
||||
mBlockClickToWalk = true;
|
||||
|
||||
|
|
@ -1786,64 +1804,80 @@ void LLToolPie::startCameraSteering()
|
|||
|
||||
void LLToolPie::steerCameraWithMouse(S32 x, S32 y)
|
||||
{
|
||||
const F32 MIN_ROTATION_RADIUS_FRACTION = 0.2f;
|
||||
|
||||
const LLViewerCamera& camera = LLViewerCamera::instance();
|
||||
const LLCoordFrame& rotation_frame = gAgent.getFrameAgent();
|
||||
const LLVector3 pick_pos = gAgent.getPosAgentFromGlobal(mSteerPick.mPosGlobal);
|
||||
const LLVector3 rotation_center = gAgent.getFrameAgent().getOrigin();
|
||||
// FIXME: get this to work with camera tilt (i.e. sitting on a rotating object)
|
||||
const LLVector3 rotation_up_axis(LLVector3::z_axis);
|
||||
const LLVector3 pick_rotation_center = rotation_frame.getOrigin() + parallel_component(pick_pos - rotation_frame.getOrigin(), rotation_frame.getUpAxis());
|
||||
const F32 MIN_ROTATION_RADIUS_FRACTION = 0.2f;
|
||||
const F32 min_rotation_radius = MIN_ROTATION_RADIUS_FRACTION * dist_vec(pick_rotation_center, camera.getOrigin());;
|
||||
const F32 pick_distance_from_rotation_center = llclamp(dist_vec(pick_pos, pick_rotation_center), min_rotation_radius, F32_MAX);
|
||||
const LLVector3 camera_to_rotation_center = pick_rotation_center - camera.getOrigin();
|
||||
const LLVector3 adjusted_camera_pos = LLViewerCamera::instance().getOrigin() + projected_vec(camera_to_rotation_center, rotation_frame.getUpAxis());
|
||||
const F32 camera_distance_from_rotation_center = dist_vec(adjusted_camera_pos, pick_rotation_center);
|
||||
|
||||
LLVector3 object_rotation_center = rotation_center + parallel_component(pick_pos - rotation_center, rotation_up_axis);
|
||||
F32 min_rotation_radius = MIN_ROTATION_RADIUS_FRACTION * dist_vec(rotation_center, LLViewerCamera::instance().getOrigin());;
|
||||
F32 pick_distance_from_rotation_center = llclamp(dist_vec(pick_pos, object_rotation_center), min_rotation_radius, F32_MAX);
|
||||
|
||||
LLVector3 mouse_ray = orthogonal_component(gViewerWindow->mouseDirectionGlobal(x, y), rotation_up_axis);
|
||||
LLVector3 mouse_ray = orthogonal_component(gViewerWindow->mouseDirectionGlobal(x, y), rotation_frame.getUpAxis());
|
||||
mouse_ray.normalize();
|
||||
|
||||
LLVector3 old_mouse_ray = orthogonal_component(gViewerWindow->mouseDirectionGlobal(mMouseSteerX, mMouseSteerY), rotation_up_axis);
|
||||
LLVector3 old_mouse_ray = orthogonal_component(gViewerWindow->mouseDirectionGlobal(mMouseSteerX, mMouseSteerY), rotation_frame.getUpAxis());
|
||||
old_mouse_ray.normalize();
|
||||
|
||||
LLVector3 camera_pos = gAgentCamera.getCameraPositionAgent();
|
||||
LLVector3 camera_to_rotation_center = object_rotation_center - camera_pos;
|
||||
LLVector3 adjusted_camera_pos = camera_pos + projected_vec(camera_to_rotation_center, rotation_up_axis);
|
||||
LLVector3 rotation_fwd_axis = LLViewerCamera::instance().getAtAxis() - projected_vec(LLViewerCamera::instance().getAtAxis(), rotation_up_axis);
|
||||
rotation_fwd_axis.normalize();
|
||||
F32 pick_dist = dist_vec(pick_pos, adjusted_camera_pos);
|
||||
|
||||
F32 yaw_angle;
|
||||
F32 old_yaw_angle;
|
||||
LLVector3 mouse_on_sphere;
|
||||
bool mouse_hit_sphere = intersect_ray_with_sphere(adjusted_camera_pos + (mouse_ray * pick_dist * 1.1f),
|
||||
-1.f * mouse_ray,
|
||||
object_rotation_center,
|
||||
pick_distance_from_rotation_center,
|
||||
mouse_on_sphere);
|
||||
|
||||
LLVector3 old_mouse_on_sphere;
|
||||
intersect_ray_with_sphere(adjusted_camera_pos + (old_mouse_ray * pick_dist * 1.1f),
|
||||
-1.f * old_mouse_ray,
|
||||
object_rotation_center,
|
||||
pick_distance_from_rotation_center,
|
||||
old_mouse_on_sphere);
|
||||
|
||||
if (mouse_hit_sphere)
|
||||
if (intersect_ray_with_sphere(
|
||||
adjusted_camera_pos,
|
||||
mouse_ray,
|
||||
pick_rotation_center,
|
||||
pick_distance_from_rotation_center,
|
||||
FAR_INTERSECTION,
|
||||
mouse_on_sphere))
|
||||
{
|
||||
// calculate rotation frame in screen space
|
||||
LLVector3 screen_rotation_up_axis = orthogonal_component(rotation_up_axis, LLViewerCamera::instance().getAtAxis());
|
||||
screen_rotation_up_axis.normalize();
|
||||
|
||||
LLVector3 screen_rotation_left_axis = screen_rotation_up_axis % LLViewerCamera::instance().getAtAxis();
|
||||
|
||||
LLVector3 rotation_furthest_pt = object_rotation_center + pick_distance_from_rotation_center * rotation_fwd_axis;
|
||||
F32 mouse_lateral_distance = llclamp(((mouse_on_sphere - rotation_furthest_pt) * screen_rotation_left_axis) / pick_distance_from_rotation_center, -1.f, 1.f);
|
||||
F32 old_mouse_lateral_distance = llclamp(((old_mouse_on_sphere - rotation_furthest_pt) * screen_rotation_left_axis) / pick_distance_from_rotation_center, -1.f, 1.f);
|
||||
|
||||
F32 yaw_angle = asinf(mouse_lateral_distance);
|
||||
F32 old_yaw_angle = asinf(old_mouse_lateral_distance);
|
||||
|
||||
F32 delta_angle = yaw_angle - old_yaw_angle;
|
||||
if (!mClockwise) delta_angle *= -1.f;
|
||||
|
||||
gAgent.yaw(delta_angle);
|
||||
mMouseSteerX = x;
|
||||
mMouseSteerY = y;
|
||||
LLVector3 mouse_sphere_offset = mouse_on_sphere - pick_rotation_center;
|
||||
yaw_angle = atan2f(mouse_sphere_offset * rotation_frame.getLeftAxis(), mouse_sphere_offset * rotation_frame.getAtAxis());
|
||||
}
|
||||
else
|
||||
{
|
||||
yaw_angle = F_PI_BY_TWO + asinf(pick_distance_from_rotation_center / camera_distance_from_rotation_center);
|
||||
if (mouse_ray * rotation_frame.getLeftAxis() < 0.f)
|
||||
{
|
||||
yaw_angle *= -1.f;
|
||||
}
|
||||
}
|
||||
|
||||
if (intersect_ray_with_sphere(
|
||||
adjusted_camera_pos,
|
||||
old_mouse_ray,
|
||||
pick_rotation_center,
|
||||
pick_distance_from_rotation_center,
|
||||
FAR_INTERSECTION,
|
||||
old_mouse_on_sphere))
|
||||
{
|
||||
LLVector3 mouse_sphere_offset = old_mouse_on_sphere - pick_rotation_center;
|
||||
old_yaw_angle = atan2f(mouse_sphere_offset * rotation_frame.getLeftAxis(), mouse_sphere_offset * rotation_frame.getAtAxis());
|
||||
}
|
||||
else
|
||||
{
|
||||
old_yaw_angle = F_PI_BY_TWO + asinf(pick_distance_from_rotation_center / camera_distance_from_rotation_center);
|
||||
|
||||
if (mouse_ray * rotation_frame.getLeftAxis() < 0.f)
|
||||
{
|
||||
old_yaw_angle *= -1.f;
|
||||
}
|
||||
}
|
||||
|
||||
const F32 delta_angle = yaw_angle - old_yaw_angle;
|
||||
|
||||
if (mClockwise)
|
||||
{
|
||||
gAgent.yaw(delta_angle);
|
||||
}
|
||||
else
|
||||
{
|
||||
gAgent.yaw(-delta_angle);
|
||||
}
|
||||
|
||||
mMouseSteerX = x;
|
||||
mMouseSteerY = y;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,9 +34,11 @@
|
|||
// std headers
|
||||
// external library headers
|
||||
// other Linden headers
|
||||
#include "llui.h" // getRootView(), resolvePath()
|
||||
#include "lluictrl.h"
|
||||
#include "llerror.h"
|
||||
|
||||
|
||||
LLUIListener::LLUIListener():
|
||||
LLEventAPI("UI",
|
||||
"LLUICtrl::CommitCallbackRegistry listener.\n"
|
||||
|
|
@ -47,6 +49,12 @@ LLUIListener::LLUIListener():
|
|||
"as if from a user gesture on a menu -- or a button click.",
|
||||
&LLUIListener::call,
|
||||
LLSD().with("function", LLSD()));
|
||||
|
||||
add("getValue",
|
||||
"For the UI control identified by the path in [\"path\"], return the control's\n"
|
||||
"current value as [\"value\"] reply.",
|
||||
&LLUIListener::getValue,
|
||||
LLSDMap("path", LLSD())("reply", LLSD()));
|
||||
}
|
||||
|
||||
void LLUIListener::call(const LLSD& event) const
|
||||
|
|
@ -71,3 +79,23 @@ void LLUIListener::call(const LLSD& event) const
|
|||
(*func)(NULL, event["parameter"]);
|
||||
}
|
||||
}
|
||||
|
||||
void LLUIListener::getValue(const LLSD&event) const
|
||||
{
|
||||
LLSD reply = LLSD::emptyMap();
|
||||
|
||||
const LLView* root = LLUI::getRootView();
|
||||
const LLView* view = LLUI::resolvePath(root, event["path"].asString());
|
||||
const LLUICtrl* ctrl(dynamic_cast<const LLUICtrl*>(view));
|
||||
|
||||
if (ctrl)
|
||||
{
|
||||
reply["value"] = ctrl->getValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
// *TODO: ??? return something indicating failure to resolve
|
||||
}
|
||||
|
||||
sendReply(reply, event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ public:
|
|||
|
||||
private:
|
||||
void call(const LLSD& event) const;
|
||||
void getValue(const LLSD&event) const;
|
||||
};
|
||||
|
||||
#endif /* ! defined(LL_LLUILISTENER_H) */
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ class LLURLDispatcherImpl
|
|||
{
|
||||
public:
|
||||
static bool dispatch(const LLSLURL& slurl,
|
||||
const std::string& nav_type,
|
||||
LLMediaCtrl* web,
|
||||
bool trusted_browser);
|
||||
// returns true if handled or explicitly blocked.
|
||||
|
|
@ -61,6 +62,7 @@ public:
|
|||
|
||||
private:
|
||||
static bool dispatchCore(const LLSLURL& slurl,
|
||||
const std::string& nav_type,
|
||||
bool right_mouse,
|
||||
LLMediaCtrl* web,
|
||||
bool trusted_browser);
|
||||
|
|
@ -71,6 +73,7 @@ private:
|
|||
// Returns true if handled.
|
||||
|
||||
static bool dispatchApp(const LLSLURL& slurl,
|
||||
const std::string& nav_type,
|
||||
bool right_mouse,
|
||||
LLMediaCtrl* web,
|
||||
bool trusted_browser);
|
||||
|
|
@ -78,7 +81,7 @@ private:
|
|||
// by showing panel in Search floater.
|
||||
// Returns true if handled or explicitly blocked.
|
||||
|
||||
static bool dispatchRegion(const LLSLURL& slurl, bool right_mouse);
|
||||
static bool dispatchRegion(const LLSLURL& slurl, const std::string& nav_type, bool right_mouse);
|
||||
// handles secondlife://Ahern/123/45/67/
|
||||
// Returns true if handled.
|
||||
|
||||
|
|
@ -97,6 +100,7 @@ private:
|
|||
|
||||
// static
|
||||
bool LLURLDispatcherImpl::dispatchCore(const LLSLURL& slurl,
|
||||
const std::string& nav_type,
|
||||
bool right_mouse,
|
||||
LLMediaCtrl* web,
|
||||
bool trusted_browser)
|
||||
|
|
@ -105,9 +109,9 @@ bool LLURLDispatcherImpl::dispatchCore(const LLSLURL& slurl,
|
|||
switch(slurl.getType())
|
||||
{
|
||||
case LLSLURL::APP:
|
||||
return dispatchApp(slurl, right_mouse, web, trusted_browser);
|
||||
return dispatchApp(slurl, nav_type, right_mouse, web, trusted_browser);
|
||||
case LLSLURL::LOCATION:
|
||||
return dispatchRegion(slurl, right_mouse);
|
||||
return dispatchRegion(slurl, nav_type, right_mouse);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
@ -122,11 +126,12 @@ bool LLURLDispatcherImpl::dispatchCore(const LLSLURL& slurl,
|
|||
|
||||
// static
|
||||
bool LLURLDispatcherImpl::dispatch(const LLSLURL& slurl,
|
||||
const std::string& nav_type,
|
||||
LLMediaCtrl* web,
|
||||
bool trusted_browser)
|
||||
{
|
||||
const bool right_click = false;
|
||||
return dispatchCore(slurl, right_click, web, trusted_browser);
|
||||
return dispatchCore(slurl, nav_type, right_click, web, trusted_browser);
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
@ -135,11 +140,12 @@ bool LLURLDispatcherImpl::dispatchRightClick(const LLSLURL& slurl)
|
|||
const bool right_click = true;
|
||||
LLMediaCtrl* web = NULL;
|
||||
const bool trusted_browser = false;
|
||||
return dispatchCore(slurl, right_click, web, trusted_browser);
|
||||
return dispatchCore(slurl, "clicked", right_click, web, trusted_browser);
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLURLDispatcherImpl::dispatchApp(const LLSLURL& slurl,
|
||||
const std::string& nav_type,
|
||||
bool right_mouse,
|
||||
LLMediaCtrl* web,
|
||||
bool trusted_browser)
|
||||
|
|
@ -147,7 +153,7 @@ bool LLURLDispatcherImpl::dispatchApp(const LLSLURL& slurl,
|
|||
llinfos << "cmd: " << slurl.getAppCmd() << " path: " << slurl.getAppPath() << " query: " << slurl.getAppQuery() << llendl;
|
||||
const LLSD& query_map = LLURI::queryMap(slurl.getAppQuery());
|
||||
bool handled = LLCommandDispatcher::dispatch(
|
||||
slurl.getAppCmd(), slurl.getAppPath(), query_map, web, trusted_browser);
|
||||
slurl.getAppCmd(), slurl.getAppPath(), query_map, web, nav_type, trusted_browser);
|
||||
|
||||
// alert if we didn't handle this secondlife:///app/ SLURL
|
||||
// (but still return true because it is a valid app SLURL)
|
||||
|
|
@ -159,7 +165,7 @@ bool LLURLDispatcherImpl::dispatchApp(const LLSLURL& slurl,
|
|||
}
|
||||
|
||||
// static
|
||||
bool LLURLDispatcherImpl::dispatchRegion(const LLSLURL& slurl, bool right_mouse)
|
||||
bool LLURLDispatcherImpl::dispatchRegion(const LLSLURL& slurl, const std::string& nav_type, bool right_mouse)
|
||||
{
|
||||
if(slurl.getType() != LLSLURL::LOCATION)
|
||||
{
|
||||
|
|
@ -287,10 +293,11 @@ LLTeleportHandler gTeleportHandler;
|
|||
|
||||
// static
|
||||
bool LLURLDispatcher::dispatch(const std::string& slurl,
|
||||
const std::string& nav_type,
|
||||
LLMediaCtrl* web,
|
||||
bool trusted_browser)
|
||||
{
|
||||
return LLURLDispatcherImpl::dispatch(LLSLURL(slurl), web, trusted_browser);
|
||||
return LLURLDispatcherImpl::dispatch(LLSLURL(slurl), nav_type, web, trusted_browser);
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
@ -310,7 +317,7 @@ bool LLURLDispatcher::dispatchFromTextEditor(const std::string& slurl)
|
|||
// *TODO: Make this trust model more refined. JC
|
||||
const bool trusted_browser = true;
|
||||
LLMediaCtrl* web = NULL;
|
||||
return LLURLDispatcherImpl::dispatch(LLSLURL(slurl), web, trusted_browser);
|
||||
return LLURLDispatcherImpl::dispatch(LLSLURL(slurl), "clicked", web, trusted_browser);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ class LLURLDispatcher
|
|||
public:
|
||||
|
||||
static bool dispatch(const std::string& slurl,
|
||||
const std::string& nav_type,
|
||||
LLMediaCtrl* web,
|
||||
bool trusted_browser);
|
||||
// At startup time and on clicks in internal web browsers,
|
||||
|
|
@ -41,6 +42,8 @@ public:
|
|||
// secondlife://RegionName/123/45/67/
|
||||
// secondlife:///app/agent/3d6181b0-6a4b-97ef-18d8-722652995cf1/show
|
||||
// sl://app/foo/bar
|
||||
// @param nav_type
|
||||
// type of navigation type (see LLQtWebKit::LLWebPage::acceptNavigationRequest)
|
||||
// @param web
|
||||
// Pointer to LLMediaCtrl sending URL, can be NULL
|
||||
// @param trusted_browser
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ void LLURLDispatcherListener::dispatch(const LLSD& params) const
|
|||
// But for testing, allow a caller to specify untrusted.
|
||||
trusted_browser = params["trusted"].asBoolean();
|
||||
}
|
||||
LLURLDispatcher::dispatch(params["url"], NULL, trusted_browser);
|
||||
LLURLDispatcher::dispatch(params["url"], "clicked", NULL, trusted_browser);
|
||||
}
|
||||
|
||||
void LLURLDispatcherListener::dispatchRightClick(const LLSD& params) const
|
||||
|
|
|
|||
|
|
@ -115,8 +115,7 @@ void display_startup()
|
|||
{
|
||||
if ( !gViewerWindow->getActive()
|
||||
|| !gViewerWindow->mWindow->getVisible()
|
||||
|| gViewerWindow->mWindow->getMinimized()
|
||||
|| gNoRender )
|
||||
|| gViewerWindow->mWindow->getMinimized() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -294,7 +293,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
|
|||
// Logic for forcing window updates if we're in drone mode.
|
||||
//
|
||||
|
||||
if (gNoRender)
|
||||
// *TODO: Investigate running display() during gHeadlessClient. See if this early exit is needed DK 2011-02-18
|
||||
if (gHeadlessClient)
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
static F32 last_update_time = 0.f;
|
||||
|
|
@ -1066,8 +1066,8 @@ bool get_hud_matrices(const LLRect& screen_region, glh::matrix4f &proj, glh::mat
|
|||
F32 scale_y = (F32)gViewerWindow->getWorldViewHeightScaled() / (F32)screen_region.getHeight();
|
||||
mat.set_scale(glh::vec3f(scale_x, scale_y, 1.f));
|
||||
mat.set_translate(
|
||||
glh::vec3f(clamp_rescale((F32)screen_region.getCenterX(), 0.f, (F32)gViewerWindow->getWorldViewWidthScaled(), 0.5f * scale_x * aspect_ratio, -0.5f * scale_x * aspect_ratio),
|
||||
clamp_rescale((F32)screen_region.getCenterY(), 0.f, (F32)gViewerWindow->getWorldViewHeightScaled(), 0.5f * scale_y, -0.5f * scale_y),
|
||||
glh::vec3f(clamp_rescale((F32)(screen_region.getCenterX() - screen_region.mLeft), 0.f, (F32)gViewerWindow->getWorldViewWidthScaled(), 0.5f * scale_x * aspect_ratio, -0.5f * scale_x * aspect_ratio),
|
||||
clamp_rescale((F32)(screen_region.getCenterY() - screen_region.mBottom), 0.f, (F32)gViewerWindow->getWorldViewHeightScaled(), 0.5f * scale_y, -0.5f * scale_y),
|
||||
0.f));
|
||||
proj *= mat;
|
||||
|
||||
|
|
|
|||
|
|
@ -2543,23 +2543,7 @@ bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask)
|
|||
// Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it...
|
||||
if( MASK_CONTROL & mask )
|
||||
{
|
||||
if( 'C' == key )
|
||||
{
|
||||
mMediaSource->copy();
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
if( 'V' == key )
|
||||
{
|
||||
mMediaSource->paste();
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
if( 'X' == key )
|
||||
{
|
||||
mMediaSource->cut();
|
||||
result = true;
|
||||
}
|
||||
result = true;
|
||||
}
|
||||
|
||||
if(!result)
|
||||
|
|
@ -3000,7 +2984,8 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
|
|||
{
|
||||
LL_DEBUGS("Media") << "MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is: " << plugin->getClickURL() << LL_ENDL;
|
||||
std::string url = plugin->getClickURL();
|
||||
LLURLDispatcher::dispatch(url, NULL, mTrustedBrowser);
|
||||
std::string nav_type = plugin->getClickNavType();
|
||||
LLURLDispatcher::dispatch(url, nav_type, NULL, mTrustedBrowser);
|
||||
}
|
||||
break;
|
||||
case MEDIA_EVENT_CLICK_LINK_HREF:
|
||||
|
|
|
|||
|
|
@ -113,6 +113,11 @@ void LLViewerMediaFocus::setFocusFace(LLPointer<LLViewerObject> objectp, S32 fac
|
|||
|
||||
media_impl->focus(true);
|
||||
gFocusMgr.setKeyboardFocus(this);
|
||||
LLViewerMediaImpl* impl = getFocusedMediaImpl();
|
||||
if (impl)
|
||||
{
|
||||
LLEditMenuHandler::gEditMenuHandler = impl;
|
||||
}
|
||||
|
||||
// We must do this before processing the media HUD zoom, or it may zoom to the wrong face.
|
||||
update();
|
||||
|
|
@ -139,6 +144,13 @@ void LLViewerMediaFocus::setFocusFace(LLPointer<LLViewerObject> objectp, S32 fac
|
|||
{
|
||||
gFocusMgr.setKeyboardFocus(NULL);
|
||||
}
|
||||
|
||||
LLViewerMediaImpl* impl = getFocusedMediaImpl();
|
||||
if (LLEditMenuHandler::gEditMenuHandler == impl)
|
||||
{
|
||||
LLEditMenuHandler::gEditMenuHandler = NULL;
|
||||
}
|
||||
|
||||
|
||||
mFocusedImplID = LLUUID::null;
|
||||
if (objectp.notNull())
|
||||
|
|
|
|||
|
|
@ -856,40 +856,36 @@ void toggle_destination_and_avatar_picker(const LLSD& show)
|
|||
LLButton* avatar_btn = gViewerWindow->getRootView()->getChildView("bottom_tray")->getChild<LLButton>("avatar_btn");
|
||||
LLButton* destination_btn = gViewerWindow->getRootView()->getChildView("bottom_tray")->getChild<LLButton>("destination_btn");
|
||||
|
||||
switch(panel_idx)
|
||||
{
|
||||
case 0:
|
||||
if (!destinations->getVisible())
|
||||
{
|
||||
container->setVisible(true);
|
||||
destinations->setVisible(true);
|
||||
avatar_picker->setVisible(false);
|
||||
LLFirstUse::notUsingDestinationGuide(false);
|
||||
avatar_btn->setToggleState(false);
|
||||
destination_btn->setToggleState(true);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (!avatar_picker->getVisible())
|
||||
{
|
||||
container->setVisible(true);
|
||||
destinations->setVisible(false);
|
||||
avatar_picker->setVisible(true);
|
||||
avatar_btn->setToggleState(true);
|
||||
destination_btn->setToggleState(false);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (panel_idx == 0
|
||||
&& !destinations->getVisible())
|
||||
{ // opening destinations guide
|
||||
container->setVisible(true);
|
||||
destinations->setVisible(true);
|
||||
avatar_picker->setVisible(false);
|
||||
LLFirstUse::notUsingDestinationGuide(false);
|
||||
avatar_btn->setToggleState(false);
|
||||
destination_btn->setToggleState(true);
|
||||
gSavedSettings.setS32("DestinationsAndAvatarsVisibility", 0);
|
||||
}
|
||||
else if (panel_idx == 1
|
||||
&& !avatar_picker->getVisible())
|
||||
{ // opening avatar picker
|
||||
container->setVisible(true);
|
||||
destinations->setVisible(false);
|
||||
avatar_picker->setVisible(true);
|
||||
avatar_btn->setToggleState(true);
|
||||
destination_btn->setToggleState(false);
|
||||
gSavedSettings.setS32("DestinationsAndAvatarsVisibility", 1);
|
||||
}
|
||||
else
|
||||
{ // toggling off dest guide or avatar picker
|
||||
container->setVisible(false);
|
||||
destinations->setVisible(false);
|
||||
avatar_picker->setVisible(false);
|
||||
avatar_btn->setToggleState(false);
|
||||
destination_btn->setToggleState(false);
|
||||
gSavedSettings.setS32("DestinationsAndAvatarsVisibility", -1);
|
||||
}
|
||||
|
||||
container->setVisible(false);
|
||||
destinations->setVisible(false);
|
||||
avatar_picker->setVisible(false);
|
||||
avatar_btn->setToggleState(false);
|
||||
destination_btn->setToggleState(false);
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -6416,12 +6412,12 @@ class LLToolsSelectedScriptAction : public view_listener_t
|
|||
else if (action == "start")
|
||||
{
|
||||
name = "start_queue";
|
||||
msg = "Running";
|
||||
msg = "SetRunning";
|
||||
}
|
||||
else if (action == "stop")
|
||||
{
|
||||
name = "stop_queue";
|
||||
msg = "RunningNot";
|
||||
msg = "SetRunningNot";
|
||||
}
|
||||
LLUUID id; id.generate();
|
||||
|
||||
|
|
|
|||
|
|
@ -343,12 +343,6 @@ void process_layer_data(LLMessageSystem *mesgsys, void **user_data)
|
|||
{
|
||||
LLViewerRegion *regionp = LLWorld::getInstance()->getRegion(mesgsys->getSender());
|
||||
|
||||
if (!regionp || gNoRender)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
S32 size;
|
||||
S8 type;
|
||||
|
||||
|
|
@ -2168,10 +2162,6 @@ void god_message_name_cb(const LLAvatarName& av_name, LLChat chat, std::string m
|
|||
|
||||
void process_improved_im(LLMessageSystem *msg, void **user_data)
|
||||
{
|
||||
if (gNoRender)
|
||||
{
|
||||
return;
|
||||
}
|
||||
LLUUID from_id;
|
||||
BOOL from_group;
|
||||
LLUUID to_id;
|
||||
|
|
@ -3960,7 +3950,9 @@ void send_agent_update(BOOL force_send, BOOL send_reliable)
|
|||
// LBUTTON and ML_LBUTTON so that using the camera (alt-key) doesn't
|
||||
// trigger a control event.
|
||||
U32 control_flags = gAgent.getControlFlags();
|
||||
|
||||
MASK key_mask = gKeyboard->currentMask(TRUE);
|
||||
|
||||
if (key_mask & MASK_ALT || key_mask & MASK_CONTROL)
|
||||
{
|
||||
control_flags &= ~( AGENT_CONTROL_LBUTTON_DOWN |
|
||||
|
|
@ -4279,7 +4271,7 @@ void process_time_synch(LLMessageSystem *mesgsys, void **user_data)
|
|||
|
||||
gSky.setSunPhase(phase);
|
||||
gSky.setSunTargetDirection(sun_direction, sun_ang_velocity);
|
||||
if (!gNoRender && !(gSavedSettings.getBOOL("SkyOverrideSimSunPosition") || gSky.getOverrideSun()))
|
||||
if ( !(gSavedSettings.getBOOL("SkyOverrideSimSunPosition") || gSky.getOverrideSun()) )
|
||||
{
|
||||
gSky.setSunDirection(sun_direction, sun_ang_velocity);
|
||||
}
|
||||
|
|
@ -5541,21 +5533,12 @@ time_t gLastDisplayedTime = 0;
|
|||
|
||||
void handle_show_mean_events(void *)
|
||||
{
|
||||
if (gNoRender)
|
||||
{
|
||||
return;
|
||||
}
|
||||
LLFloaterReg::showInstance("bumps");
|
||||
//LLFloaterBump::showInstance();
|
||||
}
|
||||
|
||||
void mean_name_callback(const LLUUID &id, const std::string& full_name, bool is_group)
|
||||
{
|
||||
if (gNoRender)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static const U32 max_collision_list_size = 20;
|
||||
if (gMeanCollisionList.size() > max_collision_list_size)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -469,11 +469,6 @@ void LLViewerObject::initVOClasses()
|
|||
// Initialized shared class stuff first.
|
||||
LLVOAvatar::initClass();
|
||||
LLVOTree::initClass();
|
||||
if (gNoRender)
|
||||
{
|
||||
// Don't init anything else in drone mode
|
||||
return;
|
||||
}
|
||||
llinfos << "Viewer Object size: " << sizeof(LLViewerObject) << llendl;
|
||||
LLVOGrass::initClass();
|
||||
LLVOWater::initClass();
|
||||
|
|
@ -2150,12 +2145,6 @@ BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
|
|||
}
|
||||
}
|
||||
|
||||
if (gNoRender)
|
||||
{
|
||||
// Skip drawable stuff if not rendering.
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
updateDrawable(FALSE);
|
||||
|
||||
return TRUE;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue