diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index c2458b098..6a6f7c222 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -127,7 +127,7 @@ if (LINUX) -pthread ) - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -D_FORTIFY_SOURCE=2 ") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 ") # Don't catch SIGCHLD in our base application class for the viewer # some of our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp index db72aa19b..89c831d29 100644 --- a/indra/llcommon/llinitparam.cpp +++ b/indra/llcommon/llinitparam.cpp @@ -40,7 +40,9 @@ namespace LLInitParam { const U8* my_addr = reinterpret_cast(this); const U8* block_addr = reinterpret_cast(enclosing_block); - mEnclosingBlockOffset = 0x7FFFffff & (U32)(my_addr - block_addr); + U32 enclosing_block_offset = 0x7FFFffff & (U32)(my_addr - block_addr); + mEnclosingBlockOffsetLow = enclosing_block_offset & 0x0000ffff; + mEnclosingBlockOffsetHigh = (enclosing_block_offset & 0x007f0000) >> 16; } // @@ -112,6 +114,35 @@ namespace LLInitParam std::copy(src_block_data.mAllParams.begin(), src_block_data.mAllParams.end(), std::back_inserter(mAllParams)); } + void BlockDescriptor::addParam(const ParamDescriptorPtr in_param, const char* char_name) + { + // create a copy of the param descriptor in mAllParams + // so other data structures can store a pointer to it + mAllParams.push_back(in_param); + ParamDescriptorPtr param(mAllParams.back()); + + std::string name(char_name); + if ((size_t)param->mParamHandle > mMaxParamOffset) + { + llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block" << llendl; + } + + if (name.empty()) + { + mUnnamedParams.push_back(param); + } + else + { + // don't use insert, since we want to overwrite existing entries + mNamedParams[name] = param; + } + + if (param->mValidationFunc) + { + mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc)); + } + } + BlockDescriptor::BlockDescriptor() : mMaxParamOffset(0), mInitializationState(UNINITIALIZED), @@ -150,7 +181,8 @@ namespace LLInitParam bool BaseBlock::submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent) { - if (!deserializeBlock(p, std::make_pair(name_stack.begin(), name_stack.end()), true)) + Parser::name_stack_range_t range = std::make_pair(name_stack.begin(), name_stack.end()); + if (!deserializeBlock(p, range, true)) { if (!silent) { @@ -196,12 +228,7 @@ namespace LLInitParam if (serialize_func) { const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL; - // each param descriptor remembers its serial number - // so we can inspect the same param under different names - // and see that it has the same number - name_stack.push_back(std::make_pair("", true)); serialize_func(*param, parser, name_stack, diff_param); - name_stack.pop_back(); } } @@ -295,7 +322,7 @@ namespace LLInitParam return true; } - bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool ignored) + bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool ignored) { BlockDescriptor& block_data = mostDerivedBlockDescriptor(); bool names_left = name_stack_range.first != name_stack_range.second; @@ -308,15 +335,12 @@ namespace LLInitParam { const std::string& top_name = name_stack_range.first->first; - ParamDescriptor::deserialize_func_t deserialize_func = NULL; - Param* paramp = NULL; - BlockDescriptor::param_map_t::iterator found_it = block_data.mNamedParams.find(top_name); if (found_it != block_data.mNamedParams.end()) { // find pointer to member parameter from offset table - paramp = getParamFromHandle(found_it->second->mParamHandle); - deserialize_func = found_it->second->mDeserializeFunc; + Param* paramp = getParamFromHandle(found_it->second->mParamHandle); + ParamDescriptor::deserialize_func_t deserialize_func = found_it->second->mDeserializeFunc; Parser::name_stack_range_t new_name_stack(name_stack_range.first, name_stack_range.second); ++new_name_stack.first; @@ -358,36 +382,6 @@ namespace LLInitParam return false; } - //static - void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name) - { - // create a copy of the param descriptor in mAllParams - // so other data structures can store a pointer to it - block_data.mAllParams.push_back(in_param); - ParamDescriptorPtr param(block_data.mAllParams.back()); - - std::string name(char_name); - if ((size_t)param->mParamHandle > block_data.mMaxParamOffset) - { - llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block" << llendl; - } - - if (name.empty()) - { - block_data.mUnnamedParams.push_back(param); - } - else - { - // don't use insert, since we want to overwrite existing entries - block_data.mNamedParams[name] = param; - } - - if (param->mValidationFunc) - { - block_data.mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc)); - } - } - void BaseBlock::addSynonym(Param& param, const std::string& synonym) { BlockDescriptor& block_data = mostDerivedBlockDescriptor(); @@ -460,7 +454,7 @@ namespace LLInitParam if (merge_func) { Param* paramp = getParamFromHandle((*it)->mParamHandle); - llassert(paramp->mEnclosingBlockOffset == (*it)->mParamHandle); + llassert(paramp->getEnclosingBlockOffset() == (*it)->mParamHandle); some_param_changed |= merge_func(*paramp, *other_paramp, overwrite); } } diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h index b79417f96..7870fd750 100644 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -38,6 +38,71 @@ #include "llerror.h" #include "llstl.h" +namespace LLTypeTags +{ + template + struct TypeTagBase + { + typedef void is_tag_t; + typedef INNER_TYPE inner_t; + static const int SORT_ORDER=_SORT_ORDER; + }; + + template + struct GreaterThan + { + static const bool value = VAL1 > VAL2; + }; + + template::value > + struct Swap + { + typedef typename ITEM::template Cons::value_t value_t; + }; + + template + struct Swap + { + typedef typename REST::template Cons::value_t>::value_t value_t; + }; + + template + struct IsSortable + { + static const bool value = false; + }; + + template + struct IsSortable + { + static const bool value = true; + }; + + template::value> + struct InsertInto + { + typedef typename ITEM::template Cons::value_t value_t; + }; + + template + struct InsertInto + { + typedef typename Swap::value_t value_t; + }; + + template::value> + struct Sorted + { + typedef T value_t; + }; + + template + struct Sorted + { + typedef typename InsertInto::value_t>::value_t value_t; + }; +} + namespace LLInitParam { // used to indicate no matching value to a given name when parsing @@ -45,6 +110,8 @@ namespace LLInitParam template const T& defaultValue() { static T value; return value; } + // wraps comparison operator between any 2 values of the same type + // specialize to handle cases where equality isn't defined well, or at all template ::value > struct ParamCompare { @@ -79,24 +146,123 @@ namespace LLInitParam // helper functions and classes typedef ptrdiff_t param_handle_t; + struct IS_A_BLOCK {}; + struct NOT_BLOCK {}; + + // these templates allow us to distinguish between template parameters + // that derive from BaseBlock and those that don't + template + struct IsBlock + { + typedef NOT_BLOCK value_t; + }; + + template + struct IsBlock + { + typedef IS_A_BLOCK value_t; + }; + + // ParamValue class directly manages the wrapped value + // by holding on to a copy (scalar params) + // or deriving from it (blocks) + // has specializations for custom value behavior + // and "tag" values like Lazy and Atomic + template::value_t> + class ParamValue + { + typedef ParamValue self_t; + + public: + typedef T default_value_t; + typedef T value_t; + + ParamValue(): mValue() {} + ParamValue(const default_value_t& other) : mValue(other) {} + + void setValue(const value_t& val) + { + mValue = val; + } + + const value_t& getValue() const + { + return mValue; + } + + T& getValue() + { + return mValue; + } + + protected: + T mValue; + }; + + template + class ParamValue + : public T + { + typedef ParamValue self_t; + public: + typedef T default_value_t; + typedef T value_t; + + ParamValue() + : T(), + mValidated(false) + {} + + ParamValue(const default_value_t& other) + : T(other), + mValidated(false) + {} + + void setValue(const value_t& val) + { + *this = val; + } + + const value_t& getValue() const + { + return *this; + } + + T& getValue() + { + return *this; + } + + protected: + mutable bool mValidated; // lazy validation flag + }; + // empty default implementation of key cache // leverages empty base class optimization template class TypeValues + : public ParamValue::value_t> { private: struct Inaccessable{}; public: typedef std::map value_name_map_t; typedef Inaccessable name_t; + typedef TypeValues type_value_t; + typedef ParamValue::value_t> param_value_t; + typedef typename param_value_t::value_t value_t; + + TypeValues(const typename param_value_t::value_t& val) + : param_value_t(val) + {} void setValueName(const std::string& key) {} std::string getValueName() const { return ""; } - std::string calcValueName(const T& value) const { return ""; } + std::string calcValueName(const value_t& value) const { return ""; } void clearValueName() const {} - static bool getValueFromName(const std::string& name, T& value) + static bool getValueFromName(const std::string& name, value_t& value) { return false; } @@ -111,15 +277,39 @@ namespace LLInitParam return NULL; } + void assignNamedValue(const Inaccessable& name) + {} + + operator const value_t&() const + { + return param_value_t::getValue(); + } + + const value_t& operator()() const + { + return param_value_t::getValue(); + } + static value_name_map_t* getValueNames() {return NULL;} }; - template > + // helper class to implement name value lookups + // and caching of last used name + template , bool IS_SPECIALIZED = true > class TypeValuesHelper + : public ParamValue::value_t> { + typedef TypeValuesHelper self_t; public: typedef typename std::map value_name_map_t; typedef std::string name_t; + typedef self_t type_value_t; + typedef ParamValue::value_t> param_value_t; + typedef typename param_value_t::value_t value_t; + + TypeValuesHelper(const typename param_value_t::value_t& val) + : param_value_t(val) + {} //TODO: cache key by index to save on param block size void setValueName(const std::string& value_name) @@ -132,7 +322,7 @@ namespace LLInitParam return mValueName; } - std::string calcValueName(const T& value) const + std::string calcValueName(const value_t& value) const { value_name_map_t* map = getValueNames(); for (typename value_name_map_t::iterator it = map->begin(), end_it = map->end(); @@ -153,7 +343,7 @@ namespace LLInitParam mValueName.clear(); } - static bool getValueFromName(const std::string& name, T& value) + static bool getValueFromName(const std::string& name, value_t& value) { value_name_map_t* map = getValueNames(); typename value_name_map_t::iterator found_it = map->find(name); @@ -195,24 +385,94 @@ namespace LLInitParam return &sValues; } - static void declare(const std::string& name, const T& value) + static void declare(const std::string& name, const value_t& value) { (*getValueNames())[name] = value; } + void operator ()(const std::string& name) + { + *this = name; + } + + void assignNamedValue(const std::string& name) + { + if (getValueFromName(name, param_value_t::getValue())) + { + setValueName(name); + } + } + + operator const value_t&() const + { + return param_value_t::getValue(); + } + + const value_t& operator()() const + { + return param_value_t::getValue(); + } + protected: - static void getName(const std::string& name, const T& value) + static void getName(const std::string& name, const value_t& value) {} mutable std::string mValueName; }; + // string types can support custom named values, but need + // to disambiguate in code between a string that is a named value + // and a string that is a name + template + class TypeValuesHelper + : public TypeValuesHelper + { + public: + typedef TypeValuesHelper self_t; + typedef TypeValuesHelper base_t; + typedef std::string value_t; + typedef std::string name_t; + typedef self_t type_value_t; + + TypeValuesHelper(const std::string& val) + : base_t(val) + {} + + void operator ()(const std::string& name) + { + *this = name; + } + + self_t& operator =(const std::string& name) + { + if (base_t::getValueFromName(name, ParamValue::getValue())) + { + base_t::setValueName(name); + } + else + { + ParamValue::setValue(name); + } + return *this; + } + + operator const value_t&() const + { + return ParamValue::getValue(); + } + + const value_t& operator()() const + { + return ParamValue::getValue(); + } + + }; + + // parser base class with mechanisms for registering readers/writers/inspectors of different types class LL_COMMON_API Parser { LOG_CLASS(Parser); - public: - typedef std::vector > name_stack_t; typedef std::pair name_stack_range_t; typedef std::vector possible_values_t; @@ -225,62 +485,6 @@ namespace LLInitParam typedef std::map parser_write_func_map_t; typedef std::map parser_inspect_func_map_t; - private: - template::value> - struct ReaderWriter - { - static bool read(T& param, Parser* parser) - { - parser_read_func_map_t::iterator found_it = parser->mParserReadFuncs->find(&typeid(T)); - if (found_it != parser->mParserReadFuncs->end()) - { - return found_it->second(*parser, (void*)¶m); - } - return false; - } - - static bool write(const T& param, Parser* parser, name_stack_t& name_stack) - { - parser_write_func_map_t::iterator found_it = parser->mParserWriteFuncs->find(&typeid(T)); - if (found_it != parser->mParserWriteFuncs->end()) - { - return found_it->second(*parser, (const void*)¶m, name_stack); - } - return false; - } - }; - - // read enums as ints - template - struct ReaderWriter - { - static bool read(T& param, Parser* parser) - { - // read all enums as ints - parser_read_func_map_t::iterator found_it = parser->mParserReadFuncs->find(&typeid(S32)); - if (found_it != parser->mParserReadFuncs->end()) - { - S32 value; - if (found_it->second(*parser, (void*)&value)) - { - param = (T)value; - return true; - } - } - return false; - } - - static bool write(const T& param, Parser* parser, name_stack_t& name_stack) - { - parser_write_func_map_t::iterator found_it = parser->mParserWriteFuncs->find(&typeid(S32)); - if (found_it != parser->mParserWriteFuncs->end()) - { - return found_it->second(*parser, (const void*)¶m, name_stack); - } - return false; - } - }; - public: Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map) @@ -292,15 +496,47 @@ namespace LLInitParam virtual ~Parser(); - template bool readValue(T& param) - { - return ReaderWriter::read(param, this); - } + template bool readValue(T& param, typename boost::disable_if >::type* dummy = 0) + { + parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T)); + if (found_it != mParserReadFuncs->end()) + { + return found_it->second(*this, (void*)¶m); + } + + return false; + } + + template bool readValue(T& param, typename boost::enable_if >::type* dummy = 0) + { + parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T)); + if (found_it != mParserReadFuncs->end()) + { + return found_it->second(*this, (void*)¶m); + } + else + { + found_it = mParserReadFuncs->find(&typeid(S32)); + if (found_it != mParserReadFuncs->end()) + { + S32 int_value; + bool parsed = found_it->second(*this, (void*)&int_value); + param = (T)int_value; + return parsed; + } + } + return false; + } template bool writeValue(const T& param, name_stack_t& name_stack) - { - return ReaderWriter::write(param, this, name_stack); - } + { + parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T)); + if (found_it != mParserWriteFuncs->end()) + { + return found_it->second(*this, (const void*)¶m, name_stack); + } + return false; + } // dispatch inspection to registered inspection functions, for each parameter in a param block template bool inspectValue(name_stack_t& name_stack, S32 min_count, S32 max_count, const possible_values_t* possible_values) @@ -352,7 +588,7 @@ namespace LLInitParam }; typedef bool(*merge_func_t)(Param&, const Param&, bool); - typedef bool(*deserialize_func_t)(Param&, Parser&, const Parser::name_stack_range_t&, bool); + typedef bool(*deserialize_func_t)(Param&, Parser&, Parser::name_stack_range_t&, bool); typedef void(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const Param* diff_param); typedef void(*inspect_func_t)(const Param&, Parser&, Parser::name_stack_t&, S32 min_count, S32 max_count); typedef bool(*validation_func_t)(const Param*); @@ -397,6 +633,7 @@ namespace LLInitParam } EInitializationState; void aggregateBlockData(BlockDescriptor& src_block_data); + void addParam(ParamDescriptorPtr param, const char* name); typedef boost::unordered_map param_map_t; typedef std::vector param_list_t; @@ -412,48 +649,58 @@ namespace LLInitParam class BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed }; - class LL_COMMON_API BaseBlock - { - public: //TODO: implement in terms of owned_ptr template - class Lazy + class LazyValue { public: - Lazy() + LazyValue() : mPtr(NULL) {} - ~Lazy() + ~LazyValue() { delete mPtr; } - Lazy(const Lazy& other) + LazyValue(const T& value) { - if (other.mPtr) - { - mPtr = new T(*other.mPtr); - } - else - { - mPtr = NULL; - } - } + mPtr = new T(value); + } - Lazy& operator = (const Lazy& other) + LazyValue(const LazyValue& other) + : mPtr(NULL) + { + *this = other; + } + + LazyValue& operator = (const LazyValue& other) + { + if (!other.mPtr) { - if (other.mPtr) + delete mPtr; + mPtr = NULL; + } + else + { + if (!mPtr) { mPtr = new T(*other.mPtr); } else { - mPtr = NULL; + *mPtr = *(other.mPtr); + } } return *this; } + bool operator==(const LazyValue& other) const + { + if (empty() || other.empty()) return false; + return *mPtr == *other.mPtr; + } + bool empty() const { return mPtr == NULL; @@ -461,18 +708,29 @@ namespace LLInitParam void set(const T& other) { - delete mPtr; + if (!mPtr) + { mPtr = new T(other); } + else + { + *mPtr = other; + } + } const T& get() const { - return ensureInstance(); + return *ensureInstance(); } T& get() { - return ensureInstance(); + return *ensureInstance(); + } + + operator const T&() const + { + return get(); } private: @@ -487,13 +745,50 @@ namespace LLInitParam } private: - // if you get a compilation error with this, that means you are using a forward declared struct for T - // unfortunately, the type traits we rely on don't work with forward declared typed - //static const int dummy = sizeof(T); mutable T* mPtr; }; + // root class of all parameter blocks + + class LL_COMMON_API BaseBlock + { + public: + // lift block tags into baseblock namespace so derived classes do not need to qualify them + typedef LLInitParam::IS_A_BLOCK IS_A_BLOCK; + typedef LLInitParam::NOT_BLOCK NOT_A_BLOCK; + + template + struct Sequential : public LLTypeTags::TypeTagBase + { + template struct Cons { typedef Sequential > value_t; }; + template struct Cons > { typedef Sequential value_t; }; + }; + + template + struct Atomic : public LLTypeTags::TypeTagBase + { + template struct Cons { typedef Atomic > value_t; }; + template struct Cons > { typedef Atomic value_t; }; + }; + + template::value_t > + struct Lazy : public LLTypeTags::TypeTagBase + { + template struct Cons + { + typedef Lazy, BLOCK_T> value_t; + }; + template struct Cons > + { + typedef Lazy value_t; + }; + template struct Cons > + { + typedef Lazy value_t; + }; + }; + // "Multiple" constraint types, put here in root class to avoid ambiguity during use struct AnyAmount { @@ -559,12 +854,12 @@ namespace LLInitParam // Blocks can override this to do custom tracking of changes virtual void paramChanged(const Param& changed_param, bool user_provided) {} - bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name); + bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name); void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const; bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const; - virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } - virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } + virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } + virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); } // take all provided params from other and apply to self bool overwriteFrom(const BaseBlock& other) @@ -578,10 +873,17 @@ namespace LLInitParam return false; } - static void addParam(BlockDescriptor& block_data, ParamDescriptorPtr param, const char* name); - ParamDescriptorPtr findParamDescriptor(const Param& param); + // take all provided params from other and apply to self + bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite); + + static BlockDescriptor& getBlockDescriptor() + { + static BlockDescriptor sBlockDescriptor; + return sBlockDescriptor; + } + protected: void init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size); @@ -590,25 +892,11 @@ namespace LLInitParam { return mergeBlock(block_data, source, overwrite); } - // take all provided params from other and apply to self - bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite); - - static BlockDescriptor& selfBlockDescriptor() - { - static BlockDescriptor sBlockDescriptor; - return sBlockDescriptor; - } private: const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const; }; - template - struct ParamCompare, false > - { - static bool equals(const BaseBlock::Lazy& a, const BaseBlock::Lazy& b) { return !a.empty() || !b.empty(); } - }; - class LL_COMMON_API Param { public: @@ -632,261 +920,73 @@ namespace LLInitParam // store pointer to enclosing block as offset to reduce space and allow for quick copying BaseBlock& enclosingBlock() const - { + { const U8* my_addr = reinterpret_cast(this); // get address of enclosing BLOCK class using stored offset to enclosing BaseBlock class return *const_cast (reinterpret_cast - (my_addr - (ptrdiff_t)(S32)mEnclosingBlockOffset)); + (my_addr - (ptrdiff_t)getEnclosingBlockOffset())); + } + + U32 getEnclosingBlockOffset() const + { + return ((U32)mEnclosingBlockOffsetHigh << 16) | (U32)mEnclosingBlockOffsetLow; } private: friend class BaseBlock; - U32 mEnclosingBlockOffset:31; - U32 mIsProvided:1; + //24 bits for member offset field and 1 bit for provided flag + U16 mEnclosingBlockOffsetLow; + U8 mEnclosingBlockOffsetHigh:7; + U8 mIsProvided:1; }; - // these templates allow us to distinguish between template parameters - // that derive from BaseBlock and those that don't - template - struct IsBlock - { - static const bool value = false; - struct EmptyBase {}; - typedef EmptyBase base_class_t; - }; - - template - struct IsBlock - { - static const bool value = true; - typedef BaseBlock base_class_t; - }; - - template - struct IsBlock, typename T::baseblock_base_class_t > - { - static const bool value = true; - typedef BaseBlock base_class_t; - }; - - template::value> - class ParamValue : public NAME_VALUE_LOOKUP - { - public: - typedef const T& value_assignment_t; - typedef T value_t; - typedef ParamValue self_t; - - ParamValue(): mValue() {} - ParamValue(value_assignment_t other) : mValue(other) {} - - void setValue(value_assignment_t val) - { - mValue = val; - } - - value_assignment_t getValue() const - { - return mValue; - } - - T& getValue() - { - return mValue; - } - - operator value_assignment_t() const - { - return mValue; - } - - value_assignment_t operator()() const - { - return mValue; - } - - void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name) - { - *this = name; - } - - self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) - { - if (NAME_VALUE_LOOKUP::getValueFromName(name, mValue)) - { - setValueName(name); - } - - return *this; - } - - protected: - T mValue; - }; - - template - class ParamValue - : public T, - public NAME_VALUE_LOOKUP - { - public: - typedef const T& value_assignment_t; - typedef T value_t; - typedef ParamValue self_t; - - ParamValue() - : T(), - mValidated(false) - {} - - ParamValue(value_assignment_t other) - : T(other), - mValidated(false) - {} - - void setValue(value_assignment_t val) - { - *this = val; - } - - value_assignment_t getValue() const - { - return *this; - } - - T& getValue() - { - return *this; - } - - operator value_assignment_t() const - { - return *this; - } - - value_assignment_t operator()() const - { - return *this; - } - - void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name) - { - *this = name; - } - - self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) - { - if (NAME_VALUE_LOOKUP::getValueFromName(name, *this)) - { - setValueName(name); - } - - return *this; - } - - protected: - mutable bool mValidated; // lazy validation flag - }; - - template - class ParamValue - : public NAME_VALUE_LOOKUP - { - public: - typedef const std::string& value_assignment_t; - typedef std::string value_t; - typedef ParamValue self_t; - - ParamValue(): mValue() {} - ParamValue(value_assignment_t other) : mValue(other) {} - - void setValue(value_assignment_t val) - { - if (NAME_VALUE_LOOKUP::getValueFromName(val, mValue)) - { - NAME_VALUE_LOOKUP::setValueName(val); - } - else - { - mValue = val; - } - } - - value_assignment_t getValue() const - { - return mValue; - } - - std::string& getValue() - { - return mValue; - } - - operator value_assignment_t() const - { - return mValue; - } - - value_assignment_t operator()() const - { - return mValue; - } - - protected: - std::string mValue; - }; - - template > struct ParamIterator { - typedef typename std::vector >::const_iterator const_iterator; - typedef typename std::vector >::iterator iterator; + typedef typename std::vector::const_iterator const_iterator; + typedef typename std::vector::iterator iterator; }; - // specialize for custom parsing/decomposition of specific classes - // e.g. TypedParam has left, top, right, bottom, etc... + // wrapper for parameter with a known type + // specialized to handle 4 cases: + // simple "scalar" value + // parameter that is itself a block + // multiple scalar values, stored in a vector + // multiple blocks, stored in a vector template, bool HAS_MULTIPLE_VALUES = false, - bool VALUE_IS_BLOCK = IsBlock >::value> + typename VALUE_IS_BLOCK = typename IsBlock::value_t> >::value_t> class TypedParam : public Param, - public ParamValue + public NAME_VALUE_LOOKUP::type_value_t { + protected: + typedef TypedParam self_t; + typedef ParamValue::value_t> param_value_t; + typedef typename param_value_t::default_value_t default_value_t; + typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; public: - typedef TypedParam self_t; - typedef ParamValue param_value_t; - typedef typename param_value_t::value_assignment_t value_assignment_t; - typedef NAME_VALUE_LOOKUP name_value_lookup_t; + typedef typename param_value_t::value_t value_t; - using param_value_t::operator(); + using named_value_t::operator(); - TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) - : Param(block_descriptor.mCurrentBlockPtr) + TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + : Param(block_descriptor.mCurrentBlockPtr), + named_value_t(value) { if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) { - ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( - block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), - &mergeWith, - &deserializeParam, - &serializeParam, - validate_func, - &inspectParam, - min_count, max_count)); - BaseBlock::addParam(block_descriptor, param_descriptor, name); + init(block_descriptor, validate_func, min_count, max_count, name); } - - this->setValue(value); } bool isProvided() const { return Param::anyProvided(); } - static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) + static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name) { self_t& typed_param = static_cast(param); // no further names in stack, attempt to parse value now @@ -895,9 +995,9 @@ namespace LLInitParam std::string name; // try to parse a known named value - if(name_value_lookup_t::valueNamesExist() + if(named_value_t::valueNamesExist() && parser.readValue(name) - && name_value_lookup_t::getValueFromName(name, typed_param.getValue())) + && named_value_t::getValueFromName(name, typed_param.getValue())) { typed_param.setValueName(name); typed_param.setProvided(); @@ -941,7 +1041,9 @@ namespace LLInitParam if (!parser.writeValue(typed_param.getValue(), name_stack)) { std::string calculated_key = typed_param.calcValueName(typed_param.getValue()); - if (!diff_param || !ParamCompare::equals(static_cast(diff_param)->getValueName(), calculated_key)) + if (calculated_key.size() + && (!diff_param + || !ParamCompare::equals(static_cast(diff_param)->getValueName(), calculated_key))) { parser.writeValue(calculated_key, name_stack); } @@ -954,22 +1056,23 @@ namespace LLInitParam // tell parser about our actual type parser.inspectValue(name_stack, min_count, max_count, NULL); // then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) - if (name_value_lookup_t::getPossibleValues()) + if (named_value_t::getPossibleValues()) { - parser.inspectValue(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues()); + parser.inspectValue(name_stack, min_count, max_count, named_value_t::getPossibleValues()); } } - void set(value_assignment_t val, bool flag_as_provided = true) + void set(const value_t& val, bool flag_as_provided = true) { - param_value_t::clearValueName(); + named_value_t::clearValueName(); this->setValue(val); setProvided(flag_as_provided); } - self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) + self_t& operator =(const typename named_value_t::name_t& name) { - return static_cast(param_value_t::operator =(name)); + named_value_t::assignNamedValue(name); + return *this; } protected: @@ -994,41 +1097,47 @@ namespace LLInitParam } return false; } + private: + void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name ) + { + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + &mergeWith, + &deserializeParam, + &serializeParam, + validate_func, + &inspectParam, + min_count, max_count)); + block_descriptor.addParam(param_descriptor, name); + } }; // parameter that is a block template - class TypedParam + class TypedParam : public Param, - public ParamValue + public NAME_VALUE_LOOKUP::type_value_t { + protected: + typedef ParamValue::value_t> param_value_t; + typedef typename param_value_t::default_value_t default_value_t; + typedef TypedParam self_t; + typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; public: - typedef ParamValue param_value_t; - typedef typename param_value_t::value_assignment_t value_assignment_t; - typedef TypedParam self_t; - typedef NAME_VALUE_LOOKUP name_value_lookup_t; + using named_value_t::operator(); + typedef typename param_value_t::value_t value_t; - using param_value_t::operator(); - - TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr), - param_value_t(value) + named_value_t(value) { if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) { - ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( - block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), - &mergeWith, - &deserializeParam, - &serializeParam, - validate_func, - &inspectParam, - min_count, max_count)); - BaseBlock::addParam(block_descriptor, param_descriptor, name); + init(block_descriptor, validate_func, min_count, max_count, name); } } - static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) + static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name) { self_t& typed_param = static_cast(param); @@ -1036,9 +1145,9 @@ namespace LLInitParam { // try to parse a known named value std::string name; - if(name_value_lookup_t::valueNamesExist() + if(named_value_t::valueNamesExist() && parser.readValue(name) - && name_value_lookup_t::getValueFromName(name, typed_param.getValue())) + && named_value_t::getValueFromName(name, typed_param.getValue())) { typed_param.setValueName(name); typed_param.setProvided(); @@ -1070,9 +1179,9 @@ namespace LLInitParam std::string key = typed_param.getValueName(); if (!key.empty()) { - if (!parser.writeValue(key, name_stack)) + if (!diff_param || !ParamCompare::equals(static_cast(diff_param)->getValueName(), key)) { - return; + parser.writeValue(key, name_stack); } } else @@ -1083,8 +1192,16 @@ namespace LLInitParam static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) { - // I am a param that is also a block, so just recurse into my contents const self_t& typed_param = static_cast(param); + + // tell parser about our actual type + parser.inspectValue(name_stack, min_count, max_count, NULL); + // then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) + if (named_value_t::getPossibleValues()) + { + parser.inspectValue(name_stack, min_count, max_count, named_value_t::getPossibleValues()); + } + typed_param.inspectBlock(parser, name_stack, min_count, max_count); } @@ -1102,32 +1219,34 @@ namespace LLInitParam } // assign block contents to this param-that-is-a-block - void set(value_assignment_t val, bool flag_as_provided = true) + void set(const value_t& val, bool flag_as_provided = true) { this->setValue(val); - param_value_t::clearValueName(); + named_value_t::clearValueName(); // force revalidation of block // next call to isProvided() will update provision status based on validity param_value_t::mValidated = false; setProvided(flag_as_provided); } - self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) + self_t& operator =(const typename named_value_t::name_t& name) { - return static_cast(param_value_t::operator =(name)); + named_value_t::assignNamedValue(name); + return *this; } // propagate changed status up to enclosing block /*virtual*/ void paramChanged(const Param& changed_param, bool user_provided) { param_value_t::paramChanged(changed_param, user_provided); + if (user_provided) { // a child param has been explicitly changed // so *some* aspect of this block is now provided param_value_t::mValidated = false; setProvided(); - param_value_t::clearValueName(); + named_value_t::clearValueName(); } else { @@ -1151,7 +1270,7 @@ namespace LLInitParam if (src_typed_param.anyProvided()) { - if (dst_typed_param.mergeBlockParam(src_typed_param.isProvided(), dst_typed_param.isProvided(), param_value_t::selfBlockDescriptor(), src_typed_param, overwrite)) + if (dst_typed_param.mergeBlockParam(src_typed_param.isProvided(), dst_typed_param.isProvided(), param_value_t::getBlockDescriptor(), src_typed_param, overwrite)) { dst_typed_param.clearValueName(); dst_typed_param.setProvided(true); @@ -1160,56 +1279,72 @@ namespace LLInitParam } return false; } + + private: + void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name ) + { + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + &mergeWith, + &deserializeParam, + &serializeParam, + validate_func, + &inspectParam, + min_count, max_count)); + block_descriptor.addParam(param_descriptor, name); + } }; - // container of non-block parameters + // list of non-block parameters template - class TypedParam + class TypedParam : public Param { - public: - typedef TypedParam self_t; - typedef ParamValue param_value_t; - typedef typename std::vector container_t; - typedef const container_t& value_assignment_t; + protected: + typedef TypedParam self_t; + typedef ParamValue::value_t> param_value_t; + typedef typename std::vector container_t; + typedef container_t default_value_t; + typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; + public: typedef typename param_value_t::value_t value_t; - typedef NAME_VALUE_LOOKUP name_value_lookup_t; - TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr) { std::copy(value.begin(), value.end(), std::back_inserter(mValues)); if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) { - ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( - block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), - &mergeWith, - &deserializeParam, - &serializeParam, - validate_func, - &inspectParam, - min_count, max_count)); - BaseBlock::addParam(block_descriptor, param_descriptor, name); + init(block_descriptor, validate_func, min_count, max_count, name); + } } bool isProvided() const { return Param::anyProvided(); } - static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) + static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name) { + Parser::name_stack_range_t new_name_stack_range(name_stack_range); self_t& typed_param = static_cast(param); value_t value; + + // pop first element if empty string + if (new_name_stack_range.first != new_name_stack_range.second && new_name_stack_range.first->first.empty()) + { + ++new_name_stack_range.first; + } + // no further names in stack, attempt to parse value now if (name_stack_range.first == name_stack_range.second) { std::string name; // try to parse a known named value - if(name_value_lookup_t::valueNamesExist() + if(named_value_t::valueNamesExist() && parser.readValue(name) - && name_value_lookup_t::getValueFromName(name, value)) + && named_value_t::getValueFromName(name, value)) { typed_param.add(value); typed_param.mValues.back().setValueName(name); @@ -1227,14 +1362,14 @@ namespace LLInitParam static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) { const self_t& typed_param = static_cast(param); - if (!typed_param.isProvided() || name_stack.empty()) return; + if (!typed_param.isProvided()) return; for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end(); it != end_it; ++it) { std::string key = it->getValueName(); - name_stack.back().second = true; + name_stack.push_back(std::make_pair(std::string(), true)); if(key.empty()) // not parsed via name values, write out value directly @@ -1256,19 +1391,21 @@ namespace LLInitParam break; } } + + name_stack.pop_back(); } } static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) { parser.inspectValue(name_stack, min_count, max_count, NULL); - if (name_value_lookup_t::getPossibleValues()) + if (named_value_t::getPossibleValues()) { - parser.inspectValue(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues()); + parser.inspectValue(name_stack, min_count, max_count, named_value_t::getPossibleValues()); } } - void set(value_assignment_t val, bool flag_as_provided = true) + void set(const container_t& val, bool flag_as_provided = true) { mValues = val; setProvided(flag_as_provided); @@ -1276,26 +1413,24 @@ namespace LLInitParam param_value_t& add() { - mValues.push_back(param_value_t(value_t())); + mValues.push_back(value_t()); Param::setProvided(); return mValues.back(); } self_t& add(const value_t& item) { - param_value_t param_value; - param_value.setValue(item); - mValues.push_back(param_value); + mValues.push_back(item); setProvided(); return *this; } - self_t& add(const typename name_value_lookup_t::name_t& name) + self_t& add(const typename named_value_t::name_t& name) { value_t value; // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, value)) + if (named_value_t::getValueFromName(name, value)) { add(value); mValues.back().setValueName(name); @@ -1305,9 +1440,9 @@ namespace LLInitParam } // implicit conversion - operator value_assignment_t() const { return mValues; } + operator const container_t&() const { return mValues; } // explicit conversion - value_assignment_t operator()() const { return mValues; } + const container_t& operator()() const { return mValues; } typedef typename container_t::iterator iterator; typedef typename container_t::const_iterator const_iterator; @@ -1348,62 +1483,79 @@ namespace LLInitParam } container_t mValues; + + private: + void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name ) + { + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + &mergeWith, + &deserializeParam, + &serializeParam, + validate_func, + &inspectParam, + min_count, max_count)); + block_descriptor.addParam(param_descriptor, name); + } }; - // container of block parameters + // list of block parameters template - class TypedParam + class TypedParam : public Param { + protected: + typedef TypedParam self_t; + typedef ParamValue::value_t> param_value_t; + typedef typename std::vector container_t; + typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; + typedef container_t default_value_t; + typedef typename container_t::iterator iterator; + typedef typename container_t::const_iterator const_iterator; public: - typedef TypedParam self_t; - typedef ParamValue param_value_t; - typedef typename std::vector container_t; - typedef const container_t& value_assignment_t; typedef typename param_value_t::value_t value_t; - typedef NAME_VALUE_LOOKUP name_value_lookup_t; - TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) + TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr) { std::copy(value.begin(), value.end(), back_inserter(mValues)); if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) { - ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( - block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), - &mergeWith, - &deserializeParam, - &serializeParam, - validate_func, - &inspectParam, - min_count, max_count)); - BaseBlock::addParam(block_descriptor, param_descriptor, name); + init(block_descriptor, validate_func, min_count, max_count, name); } } bool isProvided() const { return Param::anyProvided(); } - static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) + static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name) { + Parser::name_stack_range_t new_name_stack_range(name_stack_range); self_t& typed_param = static_cast(param); bool new_value = false; + bool new_array_value = false; - if (new_name || typed_param.mValues.empty()) + // pop first element if empty string + if (new_name_stack_range.first != new_name_stack_range.second && new_name_stack_range.first->first.empty()) + { + new_array_value = new_name_stack_range.first->second; + ++new_name_stack_range.first; + } + + if (new_name || new_array_value || typed_param.mValues.empty()) { new_value = true; typed_param.mValues.push_back(value_t()); } - param_value_t& value = typed_param.mValues.back(); if (name_stack_range.first == name_stack_range.second) { // try to parse a known named value std::string name; - if(name_value_lookup_t::valueNamesExist() + if(named_value_t::valueNamesExist() && parser.readValue(name) - && name_value_lookup_t::getValueFromName(name, value.getValue())) + && named_value_t::getValueFromName(name, value.getValue())) { typed_param.mValues.back().setValueName(name); typed_param.setProvided(); @@ -1412,9 +1564,13 @@ namespace LLInitParam } // attempt to parse block... - if(value.deserializeBlock(parser, name_stack_range, new_name)) + if(value.deserializeBlock(parser, new_name_stack_range, new_name)) { typed_param.setProvided(); + if (new_array_value) + { + name_stack_range.first->second = false; + } return true; } @@ -1430,13 +1586,13 @@ namespace LLInitParam static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) { const self_t& typed_param = static_cast(param); - if (!typed_param.isProvided() || name_stack.empty()) return; + if (!typed_param.isProvided()) return; for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end(); it != end_it; ++it) { - name_stack.back().second = true; + name_stack.push_back(std::make_pair(std::string(), true)); std::string key = it->getValueName(); if (!key.empty()) @@ -1449,16 +1605,27 @@ namespace LLInitParam { it->serializeBlock(parser, name_stack, NULL); } + + name_stack.pop_back(); } } static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) { - // I am a vector of blocks, so describe my contents recursively - param_value_t(value_t()).inspectBlock(parser, name_stack, min_count, max_count); + const param_value_t& value_param = param_value_t(value_t()); + + // tell parser about our actual type + parser.inspectValue(name_stack, min_count, max_count, NULL); + // then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) + if (named_value_t::getPossibleValues()) + { + parser.inspectValue(name_stack, min_count, max_count, named_value_t::getPossibleValues()); } - void set(value_assignment_t val, bool flag_as_provided = true) + value_param.inspectBlock(parser, name_stack, min_count, max_count); + } + + void set(const container_t& val, bool flag_as_provided = true) { mValues = val; setProvided(flag_as_provided); @@ -1478,12 +1645,12 @@ namespace LLInitParam return *this; } - self_t& add(const typename name_value_lookup_t::name_t& name) + self_t& add(const typename named_value_t::name_t& name) { value_t value; // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, value)) + if (named_value_t::getValueFromName(name, value)) { add(value); mValues.back().setValueName(name); @@ -1492,12 +1659,10 @@ namespace LLInitParam } // implicit conversion - operator value_assignment_t() const { return mValues; } + operator const container_t&() const { return mValues; } // explicit conversion - value_assignment_t operator()() const { return mValues; } + const container_t& operator()() const { return mValues; } - typedef typename container_t::iterator iterator; - typedef typename container_t::const_iterator const_iterator; iterator begin() { return mValues.begin(); } iterator end() { return mValues.end(); } const_iterator begin() const { return mValues.begin(); } @@ -1544,6 +1709,20 @@ namespace LLInitParam } container_t mValues; + + private: + void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name ) + { + ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( + block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), + &mergeWith, + &deserializeParam, + &serializeParam, + validate_func, + &inspectParam, + min_count, max_count)); + block_descriptor.addParam(param_descriptor, name); + } }; template @@ -1558,13 +1737,13 @@ namespace LLInitParam // take all provided params from other and apply to self bool overwriteFrom(const self_t& other) { - return static_cast(this)->mergeBlock(selfBlockDescriptor(), other, true); + return static_cast(this)->mergeBlock(getBlockDescriptor(), other, true); } // take all provided params that are not already provided, and apply to self bool fillFrom(const self_t& other) { - return static_cast(this)->mergeBlock(selfBlockDescriptor(), other, false); + return static_cast(this)->mergeBlock(getBlockDescriptor(), other, false); } bool mergeBlockParam(bool source_provided, bool dest_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) @@ -1582,7 +1761,7 @@ namespace LLInitParam bool mergeBlock(BlockDescriptor& block_data, const self_t& other, bool overwrite) { mCurChoice = other.mCurChoice; - return base_block_t::mergeBlock(selfBlockDescriptor(), other, overwrite); + return base_block_t::mergeBlock(getBlockDescriptor(), other, overwrite); } // clear out old choice when param has changed @@ -1603,38 +1782,38 @@ namespace LLInitParam base_block_t::paramChanged(changed_param, user_provided); } - virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } - virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } + virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } + virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); } protected: ChoiceBlock() : mCurChoice(0) { - BaseBlock::init(selfBlockDescriptor(), base_block_t::selfBlockDescriptor(), sizeof(DERIVED_BLOCK)); + BaseBlock::init(getBlockDescriptor(), base_block_t::getBlockDescriptor(), sizeof(DERIVED_BLOCK)); } // Alternatives are mutually exclusive wrt other Alternatives in the same block. // One alternative in a block will always have isChosen() == true. // At most one alternative in a block will have isProvided() == true. - template > + template ::type_value_t > class Alternative : public TypedParam { + typedef TypedParam super_t; + typedef typename super_t::value_t value_t; + typedef typename super_t::default_value_t default_value_t; + public: friend class ChoiceBlock; - typedef Alternative self_t; - typedef TypedParam >::value> super_t; - typedef typename super_t::value_assignment_t value_assignment_t; - using super_t::operator =; - explicit Alternative(const char* name = "", value_assignment_t val = defaultValue()) - : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1), + explicit Alternative(const char* name = "", const default_value_t& val = defaultValue()) + : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, NULL, 0, 1), mOriginalValue(val) { // assign initial choice to first declared option - DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr); - if (LL_UNLIKELY(DERIVED_BLOCK::selfBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING)) + DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::getBlockDescriptor().mCurrentBlockPtr); + if (LL_UNLIKELY(DERIVED_BLOCK::getBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING)) { if(blockp->mCurChoice == 0) { @@ -1648,31 +1827,31 @@ namespace LLInitParam static_cast(Param::enclosingBlock()).paramChanged(*this, true); } - void chooseAs(value_assignment_t val) + void chooseAs(const value_t& val) { super_t::set(val); } - void operator =(value_assignment_t val) + void operator =(const value_t& val) { super_t::set(val); } - void operator()(typename super_t::value_assignment_t val) + void operator()(const value_t& val) { super_t::set(val); } - operator value_assignment_t() const + operator const value_t&() const { return (*this)(); } - value_assignment_t operator()() const + const value_t& operator()() const { if (static_cast(Param::enclosingBlock()).getCurrentChoice() == this) { - return super_t::getValue(); + return super_t::getValue(); } return mOriginalValue; } @@ -1683,11 +1862,11 @@ namespace LLInitParam } private: - T mOriginalValue; + default_value_t mOriginalValue; }; - protected: - static BlockDescriptor& selfBlockDescriptor() + public: + static BlockDescriptor& getBlockDescriptor() { static BlockDescriptor sBlockDescriptor; return sBlockDescriptor; @@ -1707,6 +1886,8 @@ namespace LLInitParam : public BASE_BLOCK { typedef Block self_t; + + protected: typedef Block block_t; public: @@ -1715,80 +1896,82 @@ namespace LLInitParam // take all provided params from other and apply to self bool overwriteFrom(const self_t& other) { - return static_cast(this)->mergeBlock(selfBlockDescriptor(), other, true); + return static_cast(this)->mergeBlock(getBlockDescriptor(), other, true); } // take all provided params that are not already provided, and apply to self bool fillFrom(const self_t& other) { - return static_cast(this)->mergeBlock(selfBlockDescriptor(), other, false); + return static_cast(this)->mergeBlock(getBlockDescriptor(), other, false); } - virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } - virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } + virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } + virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); } protected: Block() { //#pragma message("Parsing LLInitParam::Block") - BaseBlock::init(selfBlockDescriptor(), BASE_BLOCK::selfBlockDescriptor(), sizeof(DERIVED_BLOCK)); + BaseBlock::init(getBlockDescriptor(), BASE_BLOCK::getBlockDescriptor(), sizeof(DERIVED_BLOCK)); } // // Nested classes for declaring parameters // - template > + template ::type_value_t > class Optional : public TypedParam { - public: - typedef TypedParam >::value> super_t; - typedef typename super_t::value_assignment_t value_assignment_t; + typedef TypedParam super_t; + typedef typename super_t::value_t value_t; + typedef typename super_t::default_value_t default_value_t; + public: using super_t::operator(); using super_t::operator =; - explicit Optional(const char* name = "", value_assignment_t val = defaultValue()) - : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1) + explicit Optional(const char* name = "", const default_value_t& val = defaultValue()) + : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, NULL, 0, 1) { //#pragma message("Parsing LLInitParam::Block::Optional") } - Optional& operator =(value_assignment_t val) + Optional& operator =(const value_t& val) { this->set(val); return *this; } - DERIVED_BLOCK& operator()(value_assignment_t val) + DERIVED_BLOCK& operator()(const value_t& val) { super_t::set(val); return static_cast(Param::enclosingBlock()); } }; - template > + template ::type_value_t > class Mandatory : public TypedParam { - public: - typedef TypedParam >::value> super_t; + typedef TypedParam super_t; typedef Mandatory self_t; - typedef typename super_t::value_assignment_t value_assignment_t; + typedef typename super_t::value_t value_t; + typedef typename super_t::default_value_t default_value_t; + public: using super_t::operator(); using super_t::operator =; // mandatory parameters require a name to be parseable - explicit Mandatory(const char* name = "", value_assignment_t val = defaultValue()) - : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, &validate, 1, 1) + explicit Mandatory(const char* name = "", const default_value_t& val = defaultValue()) + : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, &validate, 1, 1) {} - Mandatory& operator =(value_assignment_t val) + Mandatory& operator =(const value_t& val) { this->set(val); return *this; } - DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val) + DERIVED_BLOCK& operator()(const value_t& val) { super_t::set(val); return static_cast(Param::enclosingBlock()); @@ -1802,28 +1985,29 @@ namespace LLInitParam }; - template > + template ::type_value_t > class Multiple : public TypedParam { - public: - typedef TypedParam >::value> super_t; + typedef TypedParam super_t; typedef Multiple self_t; typedef typename super_t::container_t container_t; - typedef typename super_t::value_assignment_t value_assignment_t; + typedef typename super_t::value_t value_t; + + public: typedef typename super_t::iterator iterator; typedef typename super_t::const_iterator const_iterator; explicit Multiple(const char* name = "") - : super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount) + : super_t(DERIVED_BLOCK::getBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount) {} - Multiple& operator =(value_assignment_t val) + Multiple& operator =(const container_t& val) { set(val); return *this; } - DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val) + DERIVED_BLOCK& operator()(const container_t& val) { super_t::set(val); return static_cast(Param::enclosingBlock()); @@ -1836,13 +2020,15 @@ namespace LLInitParam } }; - class Deprecated : public Param + // can appear in data files, but will ignored during parsing + // cannot read or write in code + class Ignored : public Param { public: - explicit Deprecated(const char* name) - : Param(DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr) + explicit Ignored(const char* name) + : Param(DERIVED_BLOCK::getBlockDescriptor().mCurrentBlockPtr) { - BlockDescriptor& block_descriptor = DERIVED_BLOCK::selfBlockDescriptor(); + BlockDescriptor& block_descriptor = DERIVED_BLOCK::getBlockDescriptor(); if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)) { ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( @@ -1853,11 +2039,11 @@ namespace LLInitParam NULL, NULL, 0, S32_MAX)); - BaseBlock::addParam(block_descriptor, param_descriptor, name); + block_descriptor.addParam(param_descriptor, name); } } - static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) + static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name) { if (name_stack_range.first == name_stack_range.second) { @@ -1870,19 +2056,46 @@ namespace LLInitParam } }; - // different semantics for documentation purposes, but functionally identical - typedef Deprecated Ignored; + // can appear in data files, or be written to in code, but data will be ignored + // cannot be read in code + class Deprecated : public Ignored + { + public: + explicit Deprecated(const char* name) : Ignored(name) {} - protected: - static BlockDescriptor& selfBlockDescriptor() + // dummy writer interfaces + template + Deprecated& operator =(const T& val) + { + // do nothing + return *this; + } + + template + DERIVED_BLOCK& operator()(const T& val) + { + // do nothing + return static_cast(Param::enclosingBlock()); + } + + template + void set(const T& val, bool flag_as_provided = true) + { + // do nothing + } + }; + + public: + static BlockDescriptor& getBlockDescriptor() { static BlockDescriptor sBlockDescriptor; return sBlockDescriptor; } - template + protected: + template void changeDefault(TypedParam& param, - typename TypedParam::value_assignment_t value) + const typename TypedParam::value_t& value) { if (!param.isProvided()) { @@ -1892,204 +2105,420 @@ namespace LLInitParam }; - template - class BatchBlock - : public Block + template + struct IsBlock, BLOCK_T >, void> { - public: - typedef BatchBlock self_t; - typedef Block super_t; + typedef IS_A_BLOCK value_t; + }; - BatchBlock() + template + struct IsBlock, BLOCK_T >, void> + { + typedef NOT_BLOCK value_t; + }; + + template + struct IsBlock, typename IsBlock >::value_t >, BLOCK_IDENTIFIER> + { + typedef typename IsBlock::value_t value_t; + }; + + template + struct IsBlock, typename IsBlock >::value_t >, BLOCK_IDENTIFIER> + { + typedef typename IsBlock::value_t value_t; + }; + + + template + struct InnerMostType + { + typedef T value_t; + }; + + template + struct InnerMostType > + { + typedef typename InnerMostType::value_t value_t; + }; + + template + struct InnerMostType > + { + typedef typename InnerMostType::value_t value_t; + }; + + template + class ParamValue , BLOCK_T> + { + typedef ParamValue , BLOCK_T> self_t; + + public: + typedef typename InnerMostType::value_t value_t; + typedef T default_value_t; + + ParamValue() + : mValue(), + mValidated(false) {} - bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) + ParamValue(const default_value_t& value) + : mValue(value), + mValidated(false) + {} + + void setValue(const value_t& val) + { + mValue.setValue(val); + } + + const value_t& getValue() const + { + return mValue.getValue(); + } + + value_t& getValue() + { + return mValue.getValue(); + } + + bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name) { if (new_name) { - // reset block - *static_cast(this) = defaultBatchValue(); + resetToDefault(); } - return super_t::deserializeBlock(p, name_stack_range, new_name); + return mValue.deserializeBlock(p, name_stack_range, new_name); } - bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) + void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const { - if (overwrite) + const BaseBlock* base_block = diff_block + ? &(diff_block->mValue) + : NULL; + mValue.serializeBlock(p, name_stack, base_block); + } + + bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const + { + return mValue.inspectBlock(p, name_stack, min_count, max_count); + } + + bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) + { + if ((overwrite && source_provided) // new values coming in on top or... + || (!overwrite && !dst_provided)) // values being pushed under with nothing already there { - *static_cast(this) = defaultBatchValue(); - // merge individual parameters into destination - return super_t::mergeBlock(super_t::selfBlockDescriptor(), other, overwrite); + // clear away what is there and take the new stuff as a whole + resetToDefault(); + return mValue.mergeBlock(block_data, source.getValue(), overwrite); } - return false; + + + return mValue.mergeBlock(block_data, source.getValue(), overwrite); } - protected: - static const DERIVED_BLOCK& defaultBatchValue() + + bool validateBlock(bool emit_errors = true) const { - static DERIVED_BLOCK default_value; - return default_value; + return mValue.validateBlock(emit_errors); } + + static BlockDescriptor& getBlockDescriptor() + { + return value_t::getBlockDescriptor(); + } + + + mutable bool mValidated; // lazy validation flag + + private: + void resetToDefault() + { + static T default_value; + mValue = default_value; + } + + T mValue; }; - // FIXME: this specialization is not currently used, as it only matches against the BatchBlock base class - // and not the derived class with the actual params - template - class ParamValue , - NAME_VALUE_LOOKUP, - true> - : public NAME_VALUE_LOOKUP, - protected BatchBlock + template + class ParamValue , IS_A_BLOCK> { + typedef ParamValue , IS_A_BLOCK> self_t; + public: - typedef BatchBlock block_t; - typedef const BatchBlock& value_assignment_t; - typedef block_t value_t; + typedef typename InnerMostType::value_t value_t; + typedef T default_value_t; ParamValue() - : block_t(), + : mValue(), + mValidated(false) + { + mCurParam = getBlockDescriptor().mAllParams.begin(); + } + + ParamValue(const default_value_t& value) + : mValue(value), + mValidated(false) + { + mCurParam = getBlockDescriptor().mAllParams.begin(); + } + + void setValue(const value_t& val) + { + mValue.setValue(val); + } + + const value_t& getValue() const + { + return mValue.getValue(); + } + + value_t& getValue() + { + return mValue.getValue(); + } + + bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name) + { + if (new_name) + { + mCurParam = getBlockDescriptor().mAllParams.begin(); + } + if (name_stack_range.first == name_stack_range.second + && mCurParam != getBlockDescriptor().mAllParams.end()) + { + // deserialize to mCurParam + ParamDescriptor& pd = *(*mCurParam); + ParamDescriptor::deserialize_func_t deserialize_func = pd.mDeserializeFunc; + Param* paramp = mValue.getParamFromHandle(pd.mParamHandle); + + if (deserialize_func + && paramp + && deserialize_func(*paramp, p, name_stack_range, new_name)) + { + ++mCurParam; + return true; + } + else + { + return false; + } + } + else + { + return mValue.deserializeBlock(p, name_stack_range, new_name); + } + } + + void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const + { + const BaseBlock* base_block = diff_block + ? &(diff_block->mValue) + : NULL; + mValue.serializeBlock(p, name_stack, base_block); + } + + bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const + { + return mValue.inspectBlock(p, name_stack, min_count, max_count); + } + + bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) + { + return mValue.mergeBlock(block_data, source.getValue(), overwrite); + } + + bool validateBlock(bool emit_errors = true) const + { + return mValue.validateBlock(emit_errors); + } + + static BlockDescriptor& getBlockDescriptor() + { + return value_t::getBlockDescriptor(); + } + + mutable bool mValidated; // lazy validation flag + + private: + + BlockDescriptor::all_params_list_t::iterator mCurParam; + T mValue; + }; + + template + class ParamValue , NOT_BLOCK> + : public T + { + typedef ParamValue , NOT_BLOCK> self_t; + + public: + typedef typename InnerMostType::value_t value_t; + typedef T default_value_t; + + ParamValue() + : T(), mValidated(false) {} - ParamValue(value_assignment_t other) - : block_t(other), + ParamValue(const default_value_t& value) + : T(value.getValue()), mValidated(false) - { - } + {} - void setValue(value_assignment_t val) - { - *this = val; - } - - value_assignment_t getValue() const - { - return *this; - } - - BatchBlock& getValue() - { - return *this; - } - - operator value_assignment_t() const - { - return *this; - } - - value_assignment_t operator()() const - { - return *this; - } - - protected: mutable bool mValidated; // lazy validation flag }; - template - class ParamValue , - TypeValues, - IS_BLOCK> - : public IsBlock::base_class_t + template + class ParamValue , BLOCK_T> { + typedef ParamValue , BLOCK_T> self_t; + public: - typedef ParamValue , TypeValues, false> self_t; - typedef const T& value_assignment_t; - typedef T value_t; + typedef typename InnerMostType::value_t value_t; + typedef LazyValue default_value_t; ParamValue() : mValue(), mValidated(false) {} - ParamValue(value_assignment_t other) + ParamValue(const default_value_t& other) : mValue(other), mValidated(false) {} - void setValue(value_assignment_t val) + ParamValue(const T& value) + : mValue(value), + mValidated(false) + {} + + void setValue(const value_t& val) { mValue.set(val); } - value_assignment_t getValue() const + const value_t& getValue() const { - return mValue.get(); + return mValue.get().getValue(); } - T& getValue() + value_t& getValue() { - return mValue.get(); + return mValue.get().getValue(); } - operator value_assignment_t() const - { - return mValue.get(); - } - - value_assignment_t operator()() const - { - return mValue.get(); - } - - bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) + bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name) { return mValue.get().deserializeBlock(p, name_stack_range, new_name); } - void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const + void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const { if (mValue.empty()) return; - - mValue.get().serializeBlock(p, name_stack, diff_block); + + const BaseBlock* base_block = (diff_block && !diff_block->mValue.empty()) + ? &(diff_block->mValue.get().getValue()) + : NULL; + mValue.get().serializeBlock(p, name_stack, base_block); } bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const { - if (mValue.empty()) return false; - return mValue.get().inspectBlock(p, name_stack, min_count, max_count); } - protected: + bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) + { + return source.mValue.empty() || mValue.get().mergeBlock(block_data, source.getValue(), overwrite); + } + + bool validateBlock(bool emit_errors = true) const + { + return mValue.empty() || mValue.get().validateBlock(emit_errors); + } + + static BlockDescriptor& getBlockDescriptor() + { + return value_t::getBlockDescriptor(); + } + mutable bool mValidated; // lazy validation flag private: - BaseBlock::Lazy mValue; + LazyValue mValue; + }; + + template + class ParamValue , BLOCK_T> + { + typedef ParamValue , BLOCK_T> self_t; + + public: + typedef typename InnerMostType::value_t value_t; + typedef LazyValue default_value_t; + + ParamValue() + : mValue(), + mValidated(false) + {} + + ParamValue(const default_value_t& other) + : mValue(other), + mValidated(false) + {} + + ParamValue(const T& value) + : mValue(value), + mValidated(false) + {} + + void setValue(const value_t& val) + { + mValue.set(val); + } + + const value_t& getValue() const + { + return mValue.get().getValue(); + } + + value_t& getValue() + { + return mValue.get().getValue(); + } + + mutable bool mValidated; // lazy validation flag + + private: + LazyValue mValue; }; template <> - class ParamValue , - false> - : public TypeValues, - public BaseBlock + class ParamValue + : public BaseBlock { public: - typedef ParamValue, false> self_t; - typedef const LLSD& value_assignment_t; + typedef LLSD value_t; + typedef LLSD default_value_t; ParamValue() : mValidated(false) {} - ParamValue(value_assignment_t other) + ParamValue(const default_value_t& other) : mValue(other), mValidated(false) {} - void setValue(value_assignment_t val) { mValue = val; } + void setValue(const value_t& val) { mValue = val; } - value_assignment_t getValue() const { return mValue; } + const value_t& getValue() const { return mValue; } LLSD& getValue() { return mValue; } - operator value_assignment_t() const { return mValue; } - value_assignment_t operator()() const { return mValue; } - - // block param interface - LL_COMMON_API bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name); + LL_COMMON_API bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name); LL_COMMON_API void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const; bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const { @@ -2108,8 +2537,7 @@ namespace LLInitParam template class CustomParamValue - : public Block > >, - public TypeValues + : public Block > { public: typedef enum e_value_age @@ -2119,20 +2547,21 @@ namespace LLInitParam BLOCK_AUTHORITATIVE // mValue is derived from the block parameters, which are authoritative } EValueAge; - typedef ParamValue > derived_t; + typedef ParamValue derived_t; typedef CustomParamValue self_t; typedef Block block_t; - typedef const T& value_assignment_t; + typedef T default_value_t; typedef T value_t; + typedef void baseblock_base_class_t; - CustomParamValue(const T& value = T()) + CustomParamValue(const default_value_t& value = T()) : mValue(value), mValueAge(VALUE_AUTHORITATIVE), mValidated(false) {} - bool deserializeBlock(Parser& parser, Parser::name_stack_range_t name_stack_range, bool new_name) + bool deserializeBlock(Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name) { derived_t& typed_param = static_cast(*this); // try to parse direct value T @@ -2143,8 +2572,6 @@ namespace LLInitParam typed_param.mValueAge = VALUE_AUTHORITATIVE; typed_param.updateBlockFromValue(false); - typed_param.clearValueName(); - return true; } } @@ -2158,18 +2585,8 @@ namespace LLInitParam const derived_t& typed_param = static_cast(*this); const derived_t* diff_param = static_cast(diff_block); - std::string key = typed_param.getValueName(); - - // first try to write out name of name/value pair - if (!key.empty()) - { - if (!diff_param || !ParamCompare::equals(diff_param->getValueName(), key)) - { - parser.writeValue(key, name_stack); - } - } // then try to serialize value directly - else if (!diff_param || !ParamCompare::equals(typed_param.getValue(), diff_param->getValue())) + if (!diff_param || !ParamCompare::equals(typed_param.getValue(), diff_param->getValue())) { if (!parser.writeValue(typed_param.getValue(), name_stack)) @@ -2199,19 +2616,6 @@ namespace LLInitParam } } - bool inspectBlock(Parser& parser, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const - { - // first, inspect with actual type... - parser.inspectValue(name_stack, min_count, max_count, NULL); - if (TypeValues::getPossibleValues()) - { - //...then inspect with possible string values... - parser.inspectValue(name_stack, min_count, max_count, TypeValues::getPossibleValues()); - } - // then recursively inspect contents... - return block_t::inspectBlock(parser, name_stack, min_count, max_count); - } - bool validateBlock(bool emit_errors = true) const { if (mValueAge == VALUE_NEEDS_UPDATE) @@ -2219,7 +2623,6 @@ namespace LLInitParam if (block_t::validateBlock(emit_errors)) { // clear stale keyword associated with old value - TypeValues::clearValueName(); mValueAge = BLOCK_AUTHORITATIVE; static_cast(const_cast(this))->updateValueFromBlock(); return true; @@ -2249,17 +2652,15 @@ namespace LLInitParam } } - void setValue(value_assignment_t val) + void setValue(const value_t& val) { - derived_t& typed_param = static_cast(*this); // set param version number to be up to date, so we ignore block contents mValueAge = VALUE_AUTHORITATIVE; mValue = val; - typed_param.clearValueName(); static_cast(this)->updateBlockFromValue(false); } - value_assignment_t getValue() const + const value_t& getValue() const { validateBlock(true); return mValue; @@ -2271,20 +2672,10 @@ namespace LLInitParam return mValue; } - operator value_assignment_t() const - { - return getValue(); - } - - value_assignment_t operator()() const - { - return getValue(); - } - protected: // use this from within updateValueFromBlock() to set the value without making it authoritative - void updateValue(value_assignment_t value) + void updateValue(const value_t& value) { mValue = value; } diff --git a/indra/llcommon/llsdparam.cpp b/indra/llcommon/llsdparam.cpp index 0e29873bb..9f4460a98 100644 --- a/indra/llcommon/llsdparam.cpp +++ b/indra/llcommon/llsdparam.cpp @@ -223,10 +223,14 @@ LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser: { bool new_traversal = it->second; - LLSD* child_sd = it->first.empty() ? sd_to_write : &(*sd_to_write)[it->first]; - - if (child_sd->isArray()) + LLSD* child_sd; + if (it->first.empty()) { + child_sd = sd_to_write; + if (child_sd->isUndefined()) + { + *child_sd = LLSD::emptyArray(); + } if (new_traversal) { // write to new element at end @@ -240,22 +244,7 @@ LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser: } else { - if (new_traversal - && child_sd->isDefined() - && !child_sd->isArray()) - { - // copy child contents into first element of an array - LLSD new_array = LLSD::emptyArray(); - new_array.append(*child_sd); - // assign array to slot that previously held the single value - *child_sd = new_array; - // return next element in that array - sd_to_write = &((*child_sd)[1]); - } - else - { - sd_to_write = child_sd; - } + sd_to_write = &(*sd_to_write)[it->first]; } it->second = false; } @@ -283,8 +272,9 @@ void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLI it != sd.endArray(); ++it) { - stack.back().second = true; + stack.push_back(make_pair(std::string(), true)); readSDValues(cb, *it, stack); + stack.pop_back(); } } else if (sd.isUndefined()) @@ -313,8 +303,14 @@ namespace LLInitParam { // LLSD specialization // block param interface - bool ParamValue, false>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name) + bool ParamValue::deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack, bool new_name) { + if (name_stack.first == name_stack.second + && p.readValue(mValue)) + { + return true; + } + LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack); LLSD::String string; @@ -328,15 +324,18 @@ namespace LLInitParam } //static - void ParamValue, false>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack) + void ParamValue::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack) { p.writeValue(sd.asString(), name_stack); } - void ParamValue, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const + void ParamValue::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const { - // read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc) - Parser::name_stack_t stack; - LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, stack); + // attempt to write LLSD out directly + if (!p.writeValue(mValue, name_stack)) + { + // otherwise read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc) + LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, name_stack); + } } } diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 3626c88ea..2c1842a74 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -1112,6 +1112,13 @@ std::string LLFontGL::nameFromFont(const LLFontGL* fontp) return fontp->mFontDescriptor.getName(); } + +// static +std::string LLFontGL::sizeFromFont(const LLFontGL* fontp) +{ + return fontp->getFontDesc().getSize(); +} + // static std::string LLFontGL::nameFromHAlign(LLFontGL::HAlign align) { @@ -1228,6 +1235,41 @@ LLFontGL* LLFontGL::getFont(const LLFontDescriptor& desc) return sFontRegistry->getFont(desc); } +// static +LLFontGL* LLFontGL::getFontByName(const std::string& name) +{ + // check for most common fonts first + if (name == "SANSSERIF") + { + return getFontSansSerif(); + } + else if (name == "SANSSERIF_SMALL") + { + return getFontSansSerifSmall(); + } + else if (name == "SANSSERIF_BIG") + { + return getFontSansSerifBig(); + } + else if (name == "SMALL" || name == "OCRA") + { + // *BUG: Should this be "MONOSPACE"? Do we use "OCRA" anymore? + // Does "SMALL" mean "SERIF"? + return getFontMonospace(); + } + else + { + return NULL; + } +} + +//static +LLFontGL* LLFontGL::getFontDefault() +{ + return getFontSansSerif(); // Fallback to sans serif as default font +} + + // static std::string LLFontGL::getFontPathSystem() { diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index f83a72f73..776727888 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -171,7 +171,9 @@ public: // Takes a string with potentially several flags, i.e. "NORMAL|BOLD|ITALIC" static U8 getStyleFromString(const std::string &style); static std::string getStringFromStyle(U8 style); + static std::string nameFromFont(const LLFontGL* fontp); + static std::string sizeFromFont(const LLFontGL* fontp); static std::string nameFromHAlign(LLFontGL::HAlign align); static LLFontGL::HAlign hAlignFromName(const std::string& name); @@ -201,6 +203,9 @@ public: static LLFontGL* getFontSansSerifBold(); static LLFontGL* getFontExtChar(); static LLFontGL* getFont(const LLFontDescriptor& desc); + // Use with legacy names like "SANSSERIF_SMALL" or "OCRA" + static LLFontGL* getFontByName(const std::string& name); + static LLFontGL* getFontDefault(); // default fallback font static std::string getFontPathLocal(); static std::string getFontPathSystem(); diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp index 90b313d45..fecdce432 100644 --- a/indra/llui/lliconctrl.cpp +++ b/indra/llui/lliconctrl.cpp @@ -40,68 +40,56 @@ #include "llcontrol.h" #include "llui.h" #include "lluictrlfactory.h" - -const F32 RESOLUTION_BUMP = 1.f; +#include "lluiimage.h" static LLRegisterWidget r("icon"); -LLIconCtrl::LLIconCtrl(const std::string& name, const LLRect &rect, const LLUUID &image_id) -: LLUICtrl(name, - rect, - FALSE, // mouse opaque - NULL, - FOLLOWS_LEFT | FOLLOWS_TOP), - mColor( LLColor4::white ) +LLIconCtrl::Params::Params() +: image("image_name"), + color("color"), +// use_draw_context_alpha("use_draw_context_alpha", true), + scale_image("scale_image"), + min_width("min_width", 0), + min_height("min_height", 0) +{} + +LLIconCtrl::LLIconCtrl(const LLIconCtrl::Params& p) +: LLUICtrl(p), + mColor(p.color()), + mImagep(p.image), +// mUseDrawContextAlpha(p.use_draw_context_alpha), + mPriority(0), + mMinWidth(p.min_width), + mMinHeight(p.min_height) { - setImage( image_id ); - setTabStop(FALSE); + if (mImagep.notNull()) + { + LLUICtrl::setValue(mImagep->getName()); + } + setTabStop(false); } -LLIconCtrl::LLIconCtrl(const std::string& name, const LLRect &rect, const std::string &image_name) +LLIconCtrl::LLIconCtrl(const std::string& name, const LLRect &rect, const std::string &image_name, const S32& min_width, const S32& min_height) : LLUICtrl(name, rect, FALSE, // mouse opaque NULL, FOLLOWS_LEFT | FOLLOWS_TOP), mColor( LLColor4::white ), - mImageName(image_name) + mPriority(0), + mMinWidth(min_width), + mMinHeight(min_height) { - setImage( image_name ); + setValue( image_name ); setTabStop(FALSE); } - LLIconCtrl::~LLIconCtrl() { mImagep = NULL; } -void LLIconCtrl::setImage(const std::string& image_name) -{ - //RN: support UUIDs masquerading as strings - if (LLUUID::validate(image_name)) - { - mImageID = LLUUID(image_name); - - setImage(mImageID); - } - else - { - mImageName = image_name; - mImagep = LLUI::getUIImage(image_name); - mImageID.setNull(); - } -} - -void LLIconCtrl::setImage(const LLUUID& image_id) -{ - mImageName.clear(); - mImagep = LLUI::getUIImageByID(image_id); - mImageID = image_id; -} - - void LLIconCtrl::draw() { if( mImagep.notNull() ) @@ -120,23 +108,40 @@ void LLIconCtrl::setAlpha(F32 alpha) } // virtual +// value might be a string or a UUID void LLIconCtrl::setValue(const LLSD& value ) { - if (value.isUUID()) + LLSD tvalue(value); + if (value.isString() && LLUUID::validate(value.asString())) { - setImage(value.asUUID()); + //RN: support UUIDs masquerading as strings + tvalue = LLSD(LLUUID(value.asString())); + } + LLUICtrl::setValue(tvalue); + if (tvalue.isUUID()) + { + mImagep = LLUI::getUIImageByID(tvalue.asUUID(), mPriority); } else { - setImage(value.asString()); + mImagep = LLUI::getUIImage(tvalue.asString(), mPriority); + } + + if (mImagep.notNull() + && mImagep->getImage().notNull() + && mMinWidth + && mMinHeight) + { + mImagep->getImage()->setKnownDrawSize(llmax(mMinWidth, mImagep->getWidth()), llmax(mMinHeight, mImagep->getHeight())); } } -// virtual -LLSD LLIconCtrl::getValue() const +std::string LLIconCtrl::getImageName() const { - LLSD ret = getImage(); - return ret; + if (getValue().isString()) + return getValue().asString(); + else + return std::string(); } // virtual @@ -146,11 +151,14 @@ LLXMLNodePtr LLIconCtrl::getXML(bool save_children) const node->setName(LL_ICON_CTRL_TAG); - if (mImageName != "") + if (!getImageName().empty()) { - node->createChild("image_name", TRUE)->setStringValue(mImageName); + node->createChild("image_name", TRUE)->setStringValue(getImageName()); } + if (mMinWidth) node->createChild("min_width", true)->setIntValue(mMinWidth); + if (mMinHeight) node->createChild("min_height", true)->setIntValue(mMinHeight); + node->createChild("color", TRUE)->setFloatValue(4, mColor.mV); return node; @@ -170,7 +178,18 @@ LLView* LLIconCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory * LLColor4 color(LLColor4::white); LLUICtrlFactory::getAttributeColor(node,"color", color); - LLIconCtrl* icon = new LLIconCtrl("icon", rect, image_name); + S32 min_width = 0, min_height = 0; + if (node->hasAttribute("min_width")) + { + node->getAttributeS32("min_width", min_width); + } + + if (node->hasAttribute("min_height")) + { + node->getAttributeS32("min_height", min_height); + } + + LLIconCtrl* icon = new LLIconCtrl("icon", rect, image_name, min_width, min_height); icon->setColor(color); diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h index 2506fb209..16f4c4238 100644 --- a/indra/llui/lliconctrl.h +++ b/indra/llui/lliconctrl.h @@ -49,33 +49,55 @@ class LLIconCtrl : public LLUICtrl { public: - LLIconCtrl(const std::string& name, const LLRect &rect, const LLUUID &image_id); - LLIconCtrl(const std::string& name, const LLRect &rect, const std::string &image_name); + struct Params : public LLInitParam::Block + { + Optional image; + Optional color; +// Optional use_draw_context_alpha; + Optional min_width, + min_height; + Ignored scale_image; + + Params(); + }; +protected: + LLIconCtrl(const Params&); + friend class LLUICtrlFactory; + +public: + LLIconCtrl(const std::string& name, const LLRect &rect, const std::string &image_name, const S32& min_width = 0, const S32& min_height = 0); virtual ~LLIconCtrl(); // llview overrides virtual void draw(); - void setImage(const std::string& image_name); - void setImage(const LLUUID& image_name); - const LLUUID &getImage() const { return mImageID; } - std::string getImageName() const { return mImageName; } - - // Takes a UUID, wraps get/setImage + // lluictrl overrides virtual void setValue(const LLSD& value ); - virtual LLSD getValue() const; /*virtual*/ void setAlpha(F32 alpha); + std::string getImageName() const; + void setColor(const LLColor4& color) { mColor = color; } + void setImage(LLPointer image) { mImagep = image; } + const LLPointer getImage() { return mImagep; } virtual LLXMLNodePtr getXML(bool save_children = true) const; static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); +protected: + S32 mPriority; + + //the output size of the icon image if set. + S32 mMinWidth, + mMinHeight; + + // If set to true (default), use the draw context transparency. + // If false, will use transparency returned by getCurrentTransparency(). See STORM-698. + //bool mUseDrawContextAlpha; + private: LLColor4 mColor; - std::string mImageName; - LLUUID mImageID; LLPointer mImagep; }; diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 400d80d64..f066ef6dc 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1508,8 +1508,9 @@ LLNotificationPtr LLNotifications::add(AIAlert::Error const& error, int type, un // Allow LLNotifications::add, LLNotifications::cancel and LLNotifications::update // to be called from any thread. -struct UpdateItem +class UpdateItem { +public: char const* sigtype; LLNotificationPtr pNotif; UpdateItem(char const* st, LLNotificationPtr const& np) : sigtype(st), pNotif(np) { } diff --git a/indra/llui/lltrans.cpp b/indra/llui/lltrans.cpp index be15bd406..4fda9d77e 100644 --- a/indra/llui/lltrans.cpp +++ b/indra/llui/lltrans.cpp @@ -96,7 +96,7 @@ int const access_increment = 1000; static void log_sStringTemplates_accesses(void) { - llinfos << "LLTrans::getString/findString called " << sStringTemplates_accesses << " in total." << llendl; + lldebugs << "LLTrans::getString/findString called " << sStringTemplates_accesses << " in total." << llendl; } //static diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 5a68c9efe..aab2df83f 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -313,3 +313,227 @@ void LLUI::setQAMode(BOOL b) LLUI::sQAMode = b; } +namespace LLInitParam +{ + ParamValue::ParamValue(const LLUIColor& color) + : super_t(color), + red("red"), + green("green"), + blue("blue"), + alpha("alpha"), + control("") + { + updateBlockFromValue(false); + } + + void ParamValue::updateValueFromBlock() + { + if (control.isProvided() && !control().empty()) + { + updateValue(LLUI::sColorsGroup->controlExists(control) ? LLUI::sColorsGroup->getColor(control) : LLUI::sConfigGroup->getColor(control)); // Singu Note: Most of our colors will be in sColorsGroup (skin), but some may be moved to settings for users. + } + else + { + updateValue(LLColor4(red, green, blue, alpha)); + } + } + + void ParamValue::updateBlockFromValue(bool make_block_authoritative) + { + LLColor4 color = getValue(); + red.set(color.mV[VRED], make_block_authoritative); + green.set(color.mV[VGREEN], make_block_authoritative); + blue.set(color.mV[VBLUE], make_block_authoritative); + alpha.set(color.mV[VALPHA], make_block_authoritative); + control.set("", make_block_authoritative); + } + + bool ParamCompare::equals(const LLFontGL* a, const LLFontGL* b) + { + return !(a->getFontDesc() < b->getFontDesc()) + && !(b->getFontDesc() < a->getFontDesc()); + } + + ParamValue::ParamValue(const LLFontGL* fontp) + : super_t(fontp), + name("name"), + size("size"), + style("style") + { + if (!fontp) + { + updateValue(LLFontGL::getFontDefault()); + } + addSynonym(name, ""); + updateBlockFromValue(false); + } + + void ParamValue::updateValueFromBlock() + { + const LLFontGL* res_fontp = LLFontGL::getFontByName(name); + if (res_fontp) + { + updateValue(res_fontp); + return; + } + + U8 fontstyle = 0; + fontstyle = LLFontGL::getStyleFromString(style()); + LLFontDescriptor desc(name(), size(), fontstyle); + const LLFontGL* fontp = LLFontGL::getFont(desc); + if (fontp) + { + updateValue(fontp); + } + else + { + updateValue(LLFontGL::getFontDefault()); + } + } + + void ParamValue::updateBlockFromValue(bool make_block_authoritative) + { + if (getValue()) + { + name.set(LLFontGL::nameFromFont(getValue()), make_block_authoritative); + size.set(LLFontGL::sizeFromFont(getValue()), make_block_authoritative); + style.set(LLFontGL::getStringFromStyle(getValue()->getFontDesc().getStyle()), make_block_authoritative); + } + } + + ParamValue::ParamValue(const LLRect& rect) + : super_t(rect), + left("left"), + top("top"), + right("right"), + bottom("bottom"), + width("width"), + height("height") + { + updateBlockFromValue(false); + } + + void ParamValue::updateValueFromBlock() + { + LLRect rect; + + //calculate from params + // prefer explicit left and right + if (left.isProvided() && right.isProvided()) + { + rect.mLeft = left; + rect.mRight = right; + } + // otherwise use width along with specified side, if any + else if (width.isProvided()) + { + // only right + width provided + if (right.isProvided()) + { + rect.mRight = right; + rect.mLeft = right - width; + } + else // left + width, or just width + { + rect.mLeft = left; + rect.mRight = left + width; + } + } + // just left, just right, or none + else + { + rect.mLeft = left; + rect.mRight = right; + } + + // prefer explicit bottom and top + if (bottom.isProvided() && top.isProvided()) + { + rect.mBottom = bottom; + rect.mTop = top; + } + // otherwise height along with specified side, if any + else if (height.isProvided()) + { + // top + height provided + if (top.isProvided()) + { + rect.mTop = top; + rect.mBottom = top - height; + } + // bottom + height or just height + else + { + rect.mBottom = bottom; + rect.mTop = bottom + height; + } + } + // just bottom, just top, or none + else + { + rect.mBottom = bottom; + rect.mTop = top; + } + updateValue(rect); + } + + void ParamValue::updateBlockFromValue(bool make_block_authoritative) + { + // because of the ambiguity in specifying a rect by position and/or dimensions + // we use the lowest priority pairing so that any valid pairing in xui + // will override those calculated from the rect object + // in this case, that is left+width and bottom+height + LLRect& value = getValue(); + + right.set(value.mRight, false); + left.set(value.mLeft, make_block_authoritative); + width.set(value.getWidth(), make_block_authoritative); + + top.set(value.mTop, false); + bottom.set(value.mBottom, make_block_authoritative); + height.set(value.getHeight(), make_block_authoritative); + } + + ParamValue::ParamValue(const LLCoordGL& coord) + : super_t(coord), + x("x"), + y("y") + { + updateBlockFromValue(false); + } + + void ParamValue::updateValueFromBlock() + { + updateValue(LLCoordGL(x, y)); + } + + void ParamValue::updateBlockFromValue(bool make_block_authoritative) + { + x.set(getValue().mX, make_block_authoritative); + y.set(getValue().mY, make_block_authoritative); + } + + + void TypeValues::declareValues() + { + declare("left", LLFontGL::LEFT); + declare("right", LLFontGL::RIGHT); + declare("center", LLFontGL::HCENTER); + } + + void TypeValues::declareValues() + { + declare("top", LLFontGL::TOP); + declare("center", LLFontGL::VCENTER); + declare("baseline", LLFontGL::BASELINE); + declare("bottom", LLFontGL::BOTTOM); + } + + void TypeValues::declareValues() + { + declare("none", LLFontGL::NO_SHADOW); + declare("hard", LLFontGL::DROP_SHADOW); + declare("soft", LLFontGL::DROP_SHADOW_SOFT); + } +} + diff --git a/indra/llui/llui.h b/indra/llui/llui.h index aede0f859..1d3d7b33e 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -32,12 +32,18 @@ #include "llcontrol.h" #include "llcoord.h" #include "v2math.h" +#include "llinitparam.h" #include "llregistry.h" #include "llrender2dutils.h" #include "llpointer.h" +#include "lluicolor.h" #include "lluiimage.h" #include +// for initparam specialization +#include "llfontgl.h" + + // LLUIFactory #include "llsd.h" @@ -504,4 +510,99 @@ protected: template T* LLParamBlock::sBlock = NULL; + +namespace LLInitParam +{ + template<> + class ParamValue + : public CustomParamValue + { + typedef CustomParamValue super_t; + public: + Optional left, + top, + right, + bottom, + width, + height; + + ParamValue(const LLRect& value); + + void updateValueFromBlock(); + void updateBlockFromValue(bool make_block_authoritative); + }; + + template<> + class ParamValue + : public CustomParamValue + { + typedef CustomParamValue super_t; + + public: + Optional red, + green, + blue, + alpha; + Optional control; + + ParamValue(const LLUIColor& color); + void updateValueFromBlock(); + void updateBlockFromValue(bool make_block_authoritative); + }; + + template<> + class ParamValue + : public CustomParamValue + { + typedef CustomParamValue super_t; + public: + Optional name, + size, + style; + + ParamValue(const LLFontGL* value); + void updateValueFromBlock(); + void updateBlockFromValue(bool make_block_authoritative); + }; + + template<> + struct TypeValues : public TypeValuesHelper + { + static void declareValues(); + }; + + template<> + struct TypeValues : public TypeValuesHelper + { + static void declareValues(); + }; + + template<> + struct TypeValues : public TypeValuesHelper + { + static void declareValues(); + }; + + template<> + struct ParamCompare + { + static bool equals(const LLFontGL* a, const LLFontGL* b); + }; + + + template<> + class ParamValue + : public CustomParamValue + { + typedef CustomParamValue super_t; + public: + Optional x, + y; + + ParamValue(const LLCoordGL& val); + void updateValueFromBlock(); + void updateBlockFromValue(bool make_block_authoritative); + }; +} + #endif diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index 56bac0e92..a44367725 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -31,7 +31,6 @@ * $/LicenseInfo$ */ -//#include "llviewerprecompiledheaders.h" #include "linden_common.h" #include "lluictrl.h" #include "llfocusmgr.h" @@ -39,10 +38,69 @@ static LLRegisterWidget r("ui_ctrl"); -// NOTE: the LLFocusableElement implementation has been moved to llfocusmgr.cpp, to mirror the header where the class is defined. +LLUICtrl::CallbackParam::CallbackParam() +: name("name"), + function_name("function"), + parameter("parameter"), + control_name("control") // Shortcut to control -> "control_name" for backwards compatability +{ + addSynonym(parameter, "userdata"); +} -LLUICtrl::LLUICtrl() : - mViewModel(LLViewModelPtr(new LLViewModel)), +LLUICtrl::EnableControls::EnableControls() +: enabled("enabled_control"), + disabled("disabled_control") +{} + +LLUICtrl::ControlVisibility::ControlVisibility() +: visible("visibility_control"), + invisible("invisibility_control") +{ + addSynonym(visible, "visiblity_control"); + addSynonym(invisible, "invisiblity_control"); +} + +LLUICtrl::Params::Params() +: tab_stop("tab_stop", true), + chrome("chrome", false), + requests_front("requests_front", false), + label("label"), + initial_value("value"), + init_callback("init_callback"), + commit_callback("commit_callback"), + validate_callback("validate_callback"), + mouseenter_callback("mouseenter_callback"), + mouseleave_callback("mouseleave_callback"), + control_name("control_name"), + font("font", LLFontGL::getFontSansSerif()), + font_halign("halign"), + font_valign("valign"), + length("length"), // ignore LLXMLNode cruft + type("type") // ignore LLXMLNode cruft +{ + addSynonym(initial_value, "initial_value"); +} + +// NOTE: the LLFocusableElement implementation has been moved from here to llfocusmgr.cpp. + +//static +const LLUICtrl::Params& LLUICtrl::getDefaultParams() +{ + // Singu Note: We diverge here, not using LLUICtrlFactory::getDefaultParams + static const Params p; + return p; +} + + +LLUICtrl::LLUICtrl(const LLUICtrl::Params& p, const LLViewModelPtr& viewmodel) +: LLView(p), + mIsChrome(FALSE), + mRequestsFront(p.requests_front), + mTabStop(TRUE), + mTentative(FALSE), + mViewModel(viewmodel), + mEnabledControlVariable(NULL), + mDisabledControlVariable(NULL), mMakeVisibleControlVariable(NULL), mMakeInvisibleControlVariable(NULL), mCommitSignal(NULL), @@ -54,22 +112,110 @@ LLUICtrl::LLUICtrl() : mRightMouseDownSignal(NULL), mRightMouseUpSignal(NULL), mDoubleClickSignal(NULL), - mTentative(FALSE), - mTabStop(TRUE), - mIsChrome(FALSE), mCommitOnReturn(FALSE) { } +void LLUICtrl::initFromParams(const Params& p) +{ + LLView::initFromParams(p); + + mRequestsFront = p.requests_front; + + setIsChrome(p.chrome); + if(p.enabled_controls.isProvided()) + { + if (p.enabled_controls.enabled.isChosen()) + { + LLControlVariable* control = findControl(p.enabled_controls.enabled); + if (control) + setEnabledControlVariable(control); + } + else if(p.enabled_controls.disabled.isChosen()) + { + LLControlVariable* control = findControl(p.enabled_controls.disabled); + if (control) + setDisabledControlVariable(control); + } + } + if(p.controls_visibility.isProvided()) + { + if (p.controls_visibility.visible.isChosen()) + { + LLControlVariable* control = findControl(p.controls_visibility.visible); + if (control) + setMakeVisibleControlVariable(control); + } + else if (p.controls_visibility.invisible.isChosen()) + { + LLControlVariable* control = findControl(p.controls_visibility.invisible); + if (control) + setMakeInvisibleControlVariable(control); + } + } + + setTabStop(p.tab_stop); + + if (p.initial_value.isProvided() + && !p.control_name.isProvided()) + { + setValue(p.initial_value); + } + + if (p.commit_callback.isProvided()) + { + setCommitCallback(initCommitCallback(p.commit_callback)); + } + + if (p.validate_callback.isProvided()) + { + setValidateCallback(initEnableCallback(p.validate_callback)); + } + + if (p.init_callback.isProvided()) + { + if (p.init_callback.function.isProvided()) + { + p.init_callback.function()(this, p.init_callback.parameter); + } + else + { + commit_callback_t* initfunc = (CommitCallbackRegistry::getValue(p.init_callback.function_name)); + if (initfunc) + { + (*initfunc)(this, p.init_callback.parameter); + } + } + } + + if(p.mouseenter_callback.isProvided()) + { + setMouseEnterCallback(initCommitCallback(p.mouseenter_callback)); + } + + if(p.mouseleave_callback.isProvided()) + { + setMouseLeaveCallback(initCommitCallback(p.mouseleave_callback)); + } +} + LLUICtrl::LLUICtrl(const std::string& name, const LLRect rect, BOOL mouse_opaque, commit_callback_t commit_callback, U32 reshape) : // can't make this automatically follow top and left, breaks lots // of buttons in the UI. JC 7/20/2002 LLView( name, rect, mouse_opaque, reshape ), + mIsChrome(FALSE), + mRequestsFront(false), + mTabStop( TRUE ), + mTentative( FALSE ), + mViewModel(LLViewModelPtr(new LLViewModel)), + mEnabledControlVariable(NULL), + mDisabledControlVariable(NULL), + mMakeVisibleControlVariable(NULL), + mMakeInvisibleControlVariable(NULL), mCommitSignal(NULL), mValidateSignal(NULL), - mViewModel(LLViewModelPtr(new LLViewModel)), mMouseEnterSignal(NULL), mMouseLeaveSignal(NULL), mMouseDownSignal(NULL), @@ -77,9 +223,6 @@ LLUICtrl::LLUICtrl(const std::string& name, const LLRect rect, BOOL mouse_opaque mRightMouseDownSignal(NULL), mRightMouseUpSignal(NULL), mDoubleClickSignal(NULL), - mTentative( FALSE ), - mTabStop( TRUE ), - mIsChrome(FALSE), mCommitOnReturn(FALSE) { if(commit_callback) @@ -107,6 +250,66 @@ LLUICtrl::~LLUICtrl() delete mDoubleClickSignal; } +void default_commit_handler(LLUICtrl* ctrl, const LLSD& param) +{} + +bool default_enable_handler(LLUICtrl* ctrl, const LLSD& param) +{ + return true; +} + + +LLUICtrl::commit_signal_t::slot_type LLUICtrl::initCommitCallback(const CommitCallbackParam& cb) +{ + if (cb.function.isProvided()) + { + if (cb.parameter.isProvided()) + return boost::bind(cb.function(), _1, cb.parameter); + else + return cb.function(); + } + else + { + std::string function_name = cb.function_name; + commit_callback_t* func = (CommitCallbackRegistry::getValue(function_name)); + if (func) + { + if (cb.parameter.isProvided()) + return boost::bind((*func), _1, cb.parameter); + else + return commit_signal_t::slot_type(*func); + } + else if (!function_name.empty()) + { + llwarns << "No callback found for: '" << function_name << "' in control: " << getName() << llendl; + } + } + return default_commit_handler; +} + +LLUICtrl::enable_signal_t::slot_type LLUICtrl::initEnableCallback(const EnableCallbackParam& cb) +{ + // Set the callback function + if (cb.function.isProvided()) + { + if (cb.parameter.isProvided()) + return boost::bind(cb.function(), this, cb.parameter); + else + return cb.function(); + } + else + { + enable_callback_t* func = (EnableCallbackRegistry::getValue(cb.function_name)); + if (func) + { + if (cb.parameter.isProvided()) + return boost::bind((*func), this, cb.parameter); + else + return enable_signal_t::slot_type(*func); + } + } + return default_enable_handler; +} // virtual void LLUICtrl::onMouseEnter(S32 x, S32 y, MASK mask) @@ -130,6 +333,7 @@ void LLUICtrl::onMouseLeave(S32 x, S32 y, MASK mask) BOOL LLUICtrl::handleMouseDown(S32 x, S32 y, MASK mask) { BOOL handled = LLView::handleMouseDown(x,y,mask); + if (mMouseDownSignal) { (*mMouseDownSignal)(this,x,y,mask); @@ -227,6 +431,66 @@ LLViewModel* LLUICtrl::getViewModel() const return mViewModel; } +//virtual +BOOL LLUICtrl::postBuild() +{ + // + // Find all of the children that want to be in front and move them to the front + // + + if (getChildCount() > 0) + { + std::vector childrenToMoveToFront; + + for (LLView::child_list_const_iter_t child_it = beginChild(); child_it != endChild(); ++child_it) + { + LLUICtrl* uictrl = dynamic_cast(*child_it); + + if (uictrl && uictrl->mRequestsFront) + { + childrenToMoveToFront.push_back(uictrl); + } + } + + for (std::vector::iterator it = childrenToMoveToFront.begin(); it != childrenToMoveToFront.end(); ++it) + { + sendChildToFront(*it); + } + } + + return LLView::postBuild(); +} + +void LLUICtrl::setEnabledControlVariable(LLControlVariable* control) +{ + if (mEnabledControlVariable) + { + mEnabledControlConnection.disconnect(); // disconnect current signal + mEnabledControlVariable = NULL; + } + if (control) + { + mEnabledControlVariable = control; + mEnabledControlConnection = mEnabledControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getHandle(), std::string("enabled"))); + setEnabled(mEnabledControlVariable->getValue().asBoolean()); + } +} + +void LLUICtrl::setDisabledControlVariable(LLControlVariable* control) +{ + if (mDisabledControlVariable) + { + mDisabledControlConnection.disconnect(); // disconnect current signal + mDisabledControlVariable = NULL; + } + if (control) + { + mDisabledControlVariable = control; + mDisabledControlConnection = mDisabledControlVariable->getSignal()->connect(boost::bind(&controlListener, _2, getHandle(), std::string("disabled"))); + setEnabled(!(mDisabledControlVariable->getValue().asBoolean())); + } +} + void LLUICtrl::setMakeVisibleControlVariable(LLControlVariable* control) { if (mMakeVisibleControlVariable) @@ -262,7 +526,17 @@ bool LLUICtrl::controlListener(const LLSD& newvalue, LLHandle handle, LLUICtrl* ctrl = handle.get(); if (ctrl) { - if (type == "visible") + if (type == "enabled") + { + ctrl->setEnabled(newvalue.asBoolean()); + return true; + } + else if(type =="disabled") + { + ctrl->setEnabled(!newvalue.asBoolean()); + return true; + } + else if (type == "visible") { ctrl->setVisible(newvalue.asBoolean()); return true; @@ -383,7 +657,6 @@ void LLUICtrl::setIsChrome(BOOL is_chrome) // virtual BOOL LLUICtrl::getIsChrome() const { - LLView* parent_ctrl = getParent(); while(parent_ctrl) { @@ -533,6 +806,7 @@ BOOL LLUICtrl::focusLastItem(BOOL prefer_text_fields) return FALSE; } + BOOL LLUICtrl::focusNextItem(BOOL text_fields_only) { // this assumes that this method is called on the focus root. @@ -618,6 +892,8 @@ void LLUICtrl::initFromXML(LLXMLNodePtr node, LLView* parent) setTabStop(has_tab_stop); + node->getAttributeBOOL("requests_front", mRequestsFront); + std::string str = node->getName()->mString; std::string attrib_str; LLXMLNodePtr child_node; @@ -667,6 +943,20 @@ void LLUICtrl::initFromXML(LLXMLNodePtr node, LLView* parent) } LLView::initFromXML(node, parent); + if (node->getAttributeString("enabled_control", attrib_str)) + { + LLControlVariable* control = findControl(attrib_str); + if (control) + setEnabledControlVariable(control); + } + + if (node->getAttributeString("disabled_control", attrib_str)) + { + LLControlVariable* control = findControl(attrib_str); + if (control) + setDisabledControlVariable(control); + } + if(node->getAttributeString("visibility_control",attrib_str) || node->getAttributeString("visiblity_control",attrib_str)) { LLControlVariable* control = findControl(attrib_str); @@ -727,6 +1017,7 @@ boost::signals2::connection LLUICtrl::setValidateBeforeCommit( boost::functionconnect(boost::bind(cb, _2)); } + // virtual void LLUICtrl::setTentative(BOOL b) { @@ -756,6 +1047,16 @@ void LLUICtrl::setMinValue(LLSD min_value) void LLUICtrl::setMaxValue(LLSD max_value) { } +boost::signals2::connection LLUICtrl::setCommitCallback(const CommitCallbackParam& cb) +{ + return setCommitCallback(initCommitCallback(cb)); +} + +boost::signals2::connection LLUICtrl::setValidateCallback(const EnableCallbackParam& cb) +{ + return setValidateCallback(initEnableCallback(cb)); +} + boost::signals2::connection LLUICtrl::setCommitCallback( const commit_signal_t::slot_type& cb ) { if (!mCommitSignal) mCommitSignal = new commit_signal_t(); diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index ba6acc98e..aae767e1a 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -34,13 +34,13 @@ #ifndef LL_LLUICTRL_H #define LL_LLUICTRL_H -#include "llview.h" #include "llrect.h" #include "llsd.h" #include #include #include "llinitparam.h" +#include "llview.h" #include "llviewmodel.h" // *TODO move dependency to .cpp file class LLUICtrl @@ -49,20 +49,102 @@ class LLUICtrl public: typedef boost::function commit_callback_t; typedef boost::signals2::signal commit_signal_t; + // *TODO: add xml support for this type of signal in the future typedef boost::signals2::signal mouse_signal_t; + typedef boost::function enable_callback_t; typedef boost::signals2::signal enable_signal_t; - LLUICtrl(); + struct CallbackParam : public LLInitParam::Block + { + Ignored name; + + Optional function_name; + Optional parameter; + + Optional control_name; + + CallbackParam(); + }; + + struct CommitCallbackParam : public LLInitParam::Block + { + Optional function; + }; + + // also used for visible callbacks + struct EnableCallbackParam : public LLInitParam::Block + { + Optional function; + }; + + struct EnableControls : public LLInitParam::ChoiceBlock + { + Alternative enabled; + Alternative disabled; + + EnableControls(); + }; + struct ControlVisibility : public LLInitParam::ChoiceBlock + { + Alternative visible; + Alternative invisible; + + ControlVisibility(); + }; + struct Params : public LLInitParam::Block + { + Optional label; + Optional tab_stop, + chrome, + requests_front; + Optional initial_value; + + Optional init_callback, + commit_callback; + Optional validate_callback; + + Optional mouseenter_callback, + mouseleave_callback; + + Optional control_name; + Optional enabled_controls; + Optional controls_visibility; + + // font params + Optional font; + Optional font_halign; + Optional font_valign; + + // cruft from LLXMLNode implementation + Ignored type, + length; + + Params(); + }; + + /*virtual*/ ~LLUICtrl(); + + void initFromParams(const Params& p); + static const Params& getDefaultParams(); + LLUICtrl(const Params& p = getDefaultParams(), + const LLViewModelPtr& viewmodel=LLViewModelPtr(new LLViewModel)); + // Singu Note: This constructor is deprecated: LLUICtrl( const std::string& name, const LLRect rect = LLRect(), BOOL mouse_opaque = TRUE, commit_callback_t commit_callback = NULL, U32 reshape=FOLLOWS_NONE); - /*virtual*/ ~LLUICtrl(); + + commit_signal_t::slot_type initCommitCallback(const CommitCallbackParam& cb); + enable_signal_t::slot_type initEnableCallback(const EnableCallbackParam& cb); // We need this virtual so we can override it with derived versions virtual LLViewModel* getViewModel() const; // We shouldn't ever need to set this directly //virtual void setViewModel(const LLViewModelPtr&); + + virtual BOOL postBuild(); + +public: // LLView interface /*virtual*/ void initFromXML(LLXMLNodePtr node, LLView* parent); /*virtual*/ LLXMLNodePtr getXML(bool save_children = true) const; @@ -87,6 +169,9 @@ public: virtual class LLCtrlSelectionInterface* getSelectionInterface(); virtual class LLCtrlListInterface* getListInterface(); virtual class LLCtrlScrollInterface* getScrollInterface(); + + void setEnabledControlVariable(LLControlVariable* control); + void setDisabledControlVariable(LLControlVariable* control); void setMakeVisibleControlVariable(LLControlVariable* control); void setMakeInvisibleControlVariable(LLControlVariable* control); @@ -113,6 +198,9 @@ public: // Default to no-op: virtual void onTabInto(); + + // Clear any user-provided input (text in a text editor, checked checkbox, + // selected radio button, etc.). Defaults to no-op. virtual void clear(); virtual void setColor(const LLColor4& color); virtual void setAlpha(F32 alpha); @@ -121,7 +209,7 @@ public: BOOL focusNextItem(BOOL text_entry_only); BOOL focusPrevItem(BOOL text_entry_only); - virtual BOOL focusFirstItem(BOOL prefer_text_fields = FALSE, BOOL focus_flash = TRUE ); + BOOL focusFirstItem(BOOL prefer_text_fields = FALSE, BOOL focus_flash = TRUE ); BOOL focusLastItem(BOOL prefer_text_fields = FALSE); // Non Virtuals @@ -136,10 +224,13 @@ public: void setCommitOnReturn(BOOL commit) { mCommitOnReturn = commit; } BOOL getCommitOnReturn() const { return mCommitOnReturn; } + boost::signals2::connection setCommitCallback(const CommitCallbackParam& cb); + boost::signals2::connection setValidateCallback(const EnableCallbackParam& cb); + //Start using these! boost::signals2::connection setCommitCallback( const commit_signal_t::slot_type& cb ); boost::signals2::connection setValidateCallback( const enable_signal_t::slot_type& cb ); - + boost::signals2::connection setMouseEnterCallback( const commit_signal_t::slot_type& cb ); boost::signals2::connection setMouseLeaveCallback( const commit_signal_t::slot_type& cb ); @@ -192,14 +283,19 @@ protected: LLViewModelPtr mViewModel; + LLControlVariable* mEnabledControlVariable; + boost::signals2::connection mEnabledControlConnection; + LLControlVariable* mDisabledControlVariable; + boost::signals2::connection mDisabledControlConnection; LLControlVariable* mMakeVisibleControlVariable; boost::signals2::connection mMakeVisibleControlConnection; LLControlVariable* mMakeInvisibleControlVariable; boost::signals2::connection mMakeInvisibleControlConnection; private: - BOOL mTabStop; BOOL mIsChrome; + BOOL mRequestsFront; + BOOL mTabStop; BOOL mTentative; bool mCommitOnReturn; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 2a70a1c8f..8b3a3524a 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -17,7 +17,7 @@ Type Boolean Value - 1 + 0 PhoenixIMAnnounceStealFocus @@ -223,13 +223,13 @@ zmm_mlfov Comment - 1=Normal, Under 1 Zoom Out, Over 1 Zoom in + Adjusted when scrolling back and forth while holding rightclick in mouselook (Zoomed in < 1.037 < Zoomed out) Persist 1 Type F32 Value - 1 + 0.5 AllowLargeSounds @@ -763,6 +763,39 @@ Value 0 + LiruMouselookHidesFloaters + + Comment + Whether or not floaters open during third person will be hidden while in mouselook + Persist + 1 + Type + Boolean + Value + 1 + + LiruMouselookHidesMenubar + + Comment + Whether or not the main menu bar will be hidden in mouselook + Persist + 1 + Type + Boolean + Value + 1 + + LiruMouselookHidesNotices + + Comment + Whether or not notices will be hidden in mouselook + Persist + 1 + Type + Boolean + Value + 0 + LiruMouselookMenu Comment @@ -6153,6 +6186,28 @@ This should be as low as possible, but too low may break functionality Value 1 + EnableNongestureSounds + + Comment + Play sounds from non-gestures + Persist + 1 + Type + Boolean + Value + 1 + + EnableNongestureSoundsSelf + + Comment + Play sounds from your non-gestures when EnableNongestureSounds is false. (Useless otherwise) + Persist + 1 + Type + Boolean + Value + 1 + EnableMouselook Comment diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 081e3b65f..599ee5496 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -52,6 +52,7 @@ #include "llmoveview.h" #include "llchatbar.h" #include "llnotificationsutil.h" +#include "llnotify.h" // For hiding notices(gNotifyBoxView) in mouselook #include "llparcel.h" #include "llrendersphere.h" #include "llsdmessage.h" @@ -2043,6 +2044,8 @@ void LLAgent::endAnimationUpdateUI() gMenuBarView->setVisible(TRUE); gStatusBar->setVisibleForMouselook(true); + // Show notices + gNotifyBoxView->setVisible(true); LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); @@ -2053,7 +2056,7 @@ void LLAgent::endAnimationUpdateUI() } // Only pop if we have pushed... - if (TRUE == mViewsPushed) + if (mViewsPushed) { LLFloaterView::skip_list_t skip_list; skip_list.insert(LLFloaterMap::getInstance()); @@ -2134,9 +2137,11 @@ void LLAgent::endAnimationUpdateUI() if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK) { // hide menus - gMenuBarView->setVisible(FALSE); + gMenuBarView->setVisible(!gSavedSettings.getBOOL("LiruMouselookHidesMenubar")); gStatusBar->setVisibleForMouselook(false); + if (gSavedSettings.getBOOL("LiruMouselookHidesNotices")) + gNotifyBoxView->setVisible(false); // clear out camera lag effect gAgentCamera.clearCameraLag(); @@ -2146,7 +2151,7 @@ void LLAgent::endAnimationUpdateUI() LLToolMgr::getInstance()->setCurrentToolset(gMouselookToolset); - mViewsPushed = TRUE; + mViewsPushed = gSavedSettings.getBOOL("LiruMouselookHidesFloaters"); if (mMouselookModeInSignal) { @@ -2155,9 +2160,12 @@ void LLAgent::endAnimationUpdateUI() // hide all floaters except the mini map - LLFloaterView::skip_list_t skip_list; - skip_list.insert(LLFloaterMap::getInstance()); - gFloaterView->pushVisibleAll(FALSE, skip_list); + if (mViewsPushed) // Singu Note: Only hide if the setting is true. + { + LLFloaterView::skip_list_t skip_list; + skip_list.insert(LLFloaterMap::getInstance()); + gFloaterView->pushVisibleAll(FALSE, skip_list); + } if( gMorphView ) { diff --git a/indra/newview/llfloateravatarlist.cpp b/indra/newview/llfloateravatarlist.cpp index e6b8167ff..5f1a0f47c 100644 --- a/indra/newview/llfloateravatarlist.cpp +++ b/indra/newview/llfloateravatarlist.cpp @@ -1252,26 +1252,35 @@ void LLFloaterAvatarList::setFocusAvatar(const LLUUID& id) } } +// Simple function to decrement iterators, wrapping back if needed +template +T prev_iter(const T& cur, const T& begin, const T& end) +{ + return ((cur == begin) ? end : cur) - 1; +} + template void decrement_focus_target(T begin, T end, BOOL marked_only) { - T iter = begin; - while(iter != end && !(*iter)->isFocused()) ++iter; - if(iter == end) - return; - T prev_iter = iter; - while(prev_iter != begin) + for (T iter = begin; iter != end; ++iter) { - const LLAvatarListEntry& entry = *((--prev_iter)->get()); - if(entry.isInList() && (entry.isMarked() || !marked_only) && gAgentCamera.lookAtObject(entry.getID(), false)) + LLAvatarListEntry& old = *(iter->get()); + if (!old.isFocused()) continue; + for (T prev = prev_iter(iter, begin, end); prev != iter; prev = prev_iter(prev, begin, end)) { - (*iter)->setFocus(FALSE); - (*prev_iter)->setFocus(TRUE); - gAgentCamera.lookAtObject((*prev_iter)->getID(), false); - return; + LLAvatarListEntry& entry = *(prev->get()); + if (!entry.isInList()) continue; + if (marked_only && !entry.isMarked()) continue; + if (gAgentCamera.lookAtObject(entry.getID(), false)) + { + old.setFocus(false); + entry.setFocus(true); + return; + } } + // Nothing else to focus + break; } - gAgentCamera.lookAtObject((*iter)->getID(), false); } void LLFloaterAvatarList::focusOnPrev(BOOL marked_only) diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp index 095034be9..303b985c7 100644 --- a/indra/newview/llfloaterfriends.cpp +++ b/indra/newview/llfloaterfriends.cpp @@ -418,6 +418,7 @@ BOOL LLPanelFriends::addFriend(const LLUUID& agent_id) std::string fullname; BOOL have_name = LLAvatarNameCache::getPNSName(agent_id, fullname); + if (!have_name) gCacheName->getFullName(agent_id, fullname); LLSD element; element["id"] = agent_id; @@ -426,9 +427,11 @@ BOOL LLPanelFriends::addFriend(const LLUUID& agent_id) friend_column["value"] = fullname; friend_column["font"] = "SANSSERIF"; friend_column["font-style"] = "NORMAL"; + /* Singu TODO: Liru will fix this up to actually work later static const LLCachedControl sDefaultColor(gColors, "DefaultListText"); static const LLCachedControl sMutedColor("AscentMutedColor"); - friend_column["color"] = ll_sd_from_color4(LLAvatarActions::isBlocked(agent_id) ? sMutedColor : sDefaultColor); + friend_column["color"] = LLAvatarActions::isBlocked(agent_id) ? sMutedColor : sDefaultColor; + */ LLSD& online_status_column = element["columns"][LIST_ONLINE_STATUS]; online_status_column["column"] = "icon_online_status"; @@ -503,6 +506,7 @@ BOOL LLPanelFriends::updateFriendItem(const LLUUID& agent_id, const LLRelationsh std::string fullname; BOOL have_name = LLAvatarNameCache::getPNSName(agent_id, fullname); + if (!have_name) gCacheName->getFullName(agent_id, fullname); // Name of the status icon to use std::string statusIcon; diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 1902f115d..16c33c6b5 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -4275,7 +4275,7 @@ void LLModelPreview::updateStatusMessages() std::string img = lod_status_image[upload_status[lod]]; LLIconCtrl* icon = mFMP->getChild(lod_icon_name[lod]); icon->setVisible(true); - icon->setImage(img); + icon->setValue(img); if (upload_status[lod] >= 2) { @@ -4286,7 +4286,7 @@ void LLModelPreview::updateStatusMessages() { mFMP->childSetText("lod_status_message_text", mFMP->getString(message)); icon = mFMP->getChild("lod_status_message_icon"); - icon->setImage(img); + icon->setValue(img); } updateLodControls(lod); diff --git a/indra/newview/llgroupnotify.cpp b/indra/newview/llgroupnotify.cpp index ca9c834f8..5d31f8acb 100644 --- a/indra/newview/llgroupnotify.cpp +++ b/indra/newview/llgroupnotify.cpp @@ -163,7 +163,7 @@ LLGroupNotifyBox::LLGroupNotifyBox(const std::string& subject, { icon = new LLIconCtrl(std::string("icon"), LLRect(x, y, x+ICON_WIDTH, y-ICON_WIDTH), - group_insignia); + group_insignia.asString()); } else { diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index efdafd28e..abae430f6 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -1390,7 +1390,7 @@ void LLFloaterIMPanel::sendTypingState(bool typing) return; // Don't want to send typing indicators to multiple people, potentially too // much network traffic. Only send in person-to-person IMs. - if (mSessionType == P2P_SESSION) return; + if (mSessionType != P2P_SESSION) return; std::string name; gAgent.buildFullname(name); diff --git a/indra/newview/llmediaremotectrl.cpp b/indra/newview/llmediaremotectrl.cpp index b5841d2f4..c044496dc 100644 --- a/indra/newview/llmediaremotectrl.cpp +++ b/indra/newview/llmediaremotectrl.cpp @@ -293,7 +293,7 @@ void LLMediaRemoteCtrl::enableMediaButtons() mMusicIcon->setColor(music_icon_color); if(!media_icon_name.empty()) { - media_icon->setImage(media_icon_name); + media_icon->setValue(media_icon_name); } media_play_btn->setEnabled(play_media_enabled); diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index 39c86e307..74c591f1e 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -310,7 +310,7 @@ void LLPanelGroupNotices::setItem(LLPointer inv_item) inv_item->getFlags(), item_is_multi ); - mCreateInventoryIcon->setImage(icon_name); + mCreateInventoryIcon->setValue(icon_name); mCreateInventoryIcon->setVisible(TRUE); std::stringstream ss; @@ -541,7 +541,7 @@ void LLPanelGroupNotices::showNotice(const std::string& subject, std::string icon_name = LLInventoryIcon::getIconName(mInventoryOffer->mType, LLInventoryType::IT_TEXTURE); - mViewInventoryIcon->setImage(icon_name); + mViewInventoryIcon->setValue(icon_name); mViewInventoryIcon->setVisible(TRUE); std::stringstream ss; diff --git a/indra/newview/llviewchildren.cpp b/indra/newview/llviewchildren.cpp index 1a66b2489..842ffc7f9 100644 --- a/indra/newview/llviewchildren.cpp +++ b/indra/newview/llviewchildren.cpp @@ -94,10 +94,10 @@ void LLViewChildren::setBadge(const std::string& id, Badge badge, bool visible) switch (badge) { default: - case BADGE_OK: child->setImage(std::string("badge_ok.j2c")); break; - case BADGE_NOTE: child->setImage(std::string("badge_note.j2c")); break; - case BADGE_WARN: child->setImage(std::string("badge_warn.j2c")); break; - case BADGE_ERROR: child->setImage(std::string("badge_error.j2c")); break; + case BADGE_OK: child->setValue(std::string("badge_ok.j2c")); break; + case BADGE_NOTE: child->setValue(std::string("badge_note.j2c")); break; + case BADGE_WARN: child->setValue(std::string("badge_warn.j2c")); break; + case BADGE_ERROR: child->setValue(std::string("badge_error.j2c")); break; } } } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 7c2c5a898..a27bbedb4 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -5287,10 +5287,19 @@ void process_sound_trigger(LLMessageSystem *msg, void **) } // Don't play sounds from gestures if they are not enabled. - if (object_id == owner_id && !gSavedSettings.getBOOL("EnableGestureSounds")) + if (object_id == owner_id) { - // Don't mute own gestures, if they're not muted. - if (owner_id != gAgentID || !gSavedSettings.getBOOL("EnableGestureSoundsSelf")) + if (!gSavedSettings.getBOOL("EnableGestureSounds")) + { + // Don't mute own gestures, if they're not muted. + if (owner_id != gAgentID || !gSavedSettings.getBOOL("EnableGestureSoundsSelf")) + return; + } + } + else if (!gSavedSettings.getBOOL("EnableNongestureSounds")) + { + // Don't mute own non-gestures, if they're not muted. + if (owner_id != gAgentID || !gSavedSettings.getBOOL("EnableNongestureSoundsSelf")) return; } diff --git a/indra/newview/llvoiceremotectrl.cpp b/indra/newview/llvoiceremotectrl.cpp index 1863020f9..7566db6b1 100644 --- a/indra/newview/llvoiceremotectrl.cpp +++ b/indra/newview/llvoiceremotectrl.cpp @@ -154,7 +154,7 @@ void LLVoiceRemoteCtrl::draw() LLIconCtrl* icon = mVoiceVolIcon; if (icon) { - icon->setImage(talk_blip_image); + icon->setValue(talk_blip_image); } LLFloater* voice_floater = LLFloaterChatterBox::getInstance()->getCurrentVoiceFloater(); @@ -185,7 +185,7 @@ void LLVoiceRemoteCtrl::draw() LLIconCtrl* voice_channel_icon = findChild("voice_channel_icon"); if (voice_channel_icon && voice_floater) { - voice_channel_icon->setImage(voice_floater->getString("voice_icon")); + voice_channel_icon->setValue(voice_floater->getString("voice_icon")); } if (voice_channel_bg) diff --git a/indra/newview/skins/default/xui/en-us/panel_preferences_input.xml b/indra/newview/skins/default/xui/en-us/panel_preferences_input.xml index 32ad53d84..aadd1526c 100644 --- a/indra/newview/skins/default/xui/en-us/panel_preferences_input.xml +++ b/indra/newview/skins/default/xui/en-us/panel_preferences_input.xml @@ -5,6 +5,10 @@ + UI Hidden in mouselook: + + + Movement Options: @@ -13,7 +17,8 @@ Camera Follow Distance: - + +