diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h
index eff572b553..ab777d37a5 100644
--- a/indra/llui/llnotificationtemplate.h
+++ b/indra/llui/llnotificationtemplate.h
@@ -88,10 +88,10 @@ struct LLNotificationTemplate
{
private:
// this idiom allows
- //
+ //
// as well as
// ...
- Optional dummy_val;
+ Flag dummy_val;
public:
Multiple contexts;
diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h
index f0ba7fc7d7..d345ad4cd0 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -125,12 +125,12 @@ private:
// base case for recursion, there are NO base classes of LLInitParam::BaseBlock
template
- class ParamDefaults : public LLSingleton >
+ class ParamDefaults : public LLSingleton >
{
public:
- const LLInitParam::BaseBlock& get() { return mBaseBlock; }
+ const LLInitParam::BaseBlockWithFlags& get() { return mBaseBlock; }
private:
- LLInitParam::BaseBlock mBaseBlock;
+ LLInitParam::BaseBlockWithFlags mBaseBlock;
};
public:
diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h
index 9d0fe781ce..fd4482f592 100644
--- a/indra/llxuixml/llinitparam.h
+++ b/indra/llxuixml/llinitparam.h
@@ -289,20 +289,20 @@ namespace LLInitParam
protected:
bool anyProvided() const { return mIsProvided; }
- Param(class BaseBlock* enclosing_block);
+ Param(BaseBlock* enclosing_block);
// store pointer to enclosing block as offset to reduce space and allow for quick copying
- class BaseBlock& enclosingBlock() const
+ 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
+ return *const_cast
+ (reinterpret_cast
(my_addr - (ptrdiff_t)(S32)mEnclosingBlockOffset));
}
private:
- friend class BaseBlock;
+ friend BaseBlock;
U32 mEnclosingBlockOffset:31;
U32 mIsProvided:1;
@@ -367,18 +367,16 @@ namespace LLInitParam
typedef boost::unordered_map param_map_t;
typedef std::vector param_list_t;
- typedef std::list all_params_list_t;
+ typedef std::list all_params_list_t;
typedef std::vector > param_validation_list_t;
param_map_t mNamedParams; // parameters with associated names
param_list_t mUnnamedParams; // parameters with_out_ associated names
param_validation_list_t mValidationList; // parameters that must be validated
all_params_list_t mAllParams; // all parameters, owns descriptors
-
- size_t mMaxParamOffset;
-
- EInitializationState mInitializationState; // whether or not static block data has been initialized
- class BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed
+ size_t mMaxParamOffset;
+ EInitializationState mInitializationState; // whether or not static block data has been initialized
+ BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed
};
class BaseBlock
@@ -499,6 +497,92 @@ namespace LLInitParam
const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const;
};
+ class BaseBlockWithFlags : public BaseBlock
+ {
+ public:
+ class FlagBase : public Param
+ {
+ public:
+ typedef FlagBase self_t;
+
+ FlagBase(const char* name, BaseBlock* enclosing_block) : Param(enclosing_block)
+ {
+ if (LL_UNLIKELY(enclosing_block->mostDerivedBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING))
+ {
+ ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor(
+ enclosing_block->getHandleFromParam(this),
+ &mergeWith,
+ &deserializeParam,
+ &serializeParam,
+ NULL,
+ &inspectParam,
+ 0, 1));
+ BaseBlock::addParam(enclosing_block->mostDerivedBlockDescriptor(), param_descriptor, name);
+ }
+ }
+
+ bool isProvided() const { return anyProvided(); }
+
+ private:
+ static bool mergeWith(Param& dst, const Param& src, bool overwrite)
+ {
+ const self_t& src_typed_param = static_cast(src);
+ self_t& dst_typed_param = static_cast(dst);
+
+ if (src_typed_param.isProvided()
+ && (overwrite || !dst_typed_param.isProvided()))
+ {
+ dst.setProvided(true);
+ return true;
+ }
+ return false;
+ }
+
+ static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation)
+ {
+ self_t& typed_param = static_cast(param);
+
+ // no further names in stack, parse value now
+ if (name_stack.first == name_stack.second)
+ {
+ typed_param.setProvided(true);
+ typed_param.enclosingBlock().paramChanged(param, true);
+ return true;
+ }
+
+ return false;
+ }
+
+ 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);
+ const self_t* typed_diff_param = static_cast(diff_param);
+
+ if (!typed_param.isProvided()) return;
+
+ if (!name_stack.empty())
+ {
+ name_stack.back().second = parser.newParseGeneration();
+ }
+
+ // then try to serialize value directly
+ if (!typed_diff_param || !typed_diff_param->isProvided())
+ {
+ if (!parser.writeValue(NoParamValue(), name_stack))
+ {
+ return;
+ }
+ }
+ }
+
+ static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
+ {
+ // tell parser about our actual type
+ parser.inspectValue(name_stack, min_count, max_count, NULL);
+ }
+ };
+ };
+
// these templates allow us to distinguish between template parameters
// that derive from BaseBlock and those that don't
template
@@ -1424,7 +1508,7 @@ namespace LLInitParam
}
};
- template
+ template
class Block
: public BASE_BLOCK
{
@@ -1520,6 +1604,13 @@ namespace LLInitParam
};
+ class Flag : public FlagBase
+ {
+ public:
+ Flag(const char* name) : FlagBase(name, DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr)
+ {}
+ };
+
template >
class Multiple : public TypedParam
{
diff --git a/indra/llxuixml/llxuiparser.cpp b/indra/llxuixml/llxuiparser.cpp
index 72a7bb7af5..4af077b22c 100644
--- a/indra/llxuixml/llxuiparser.cpp
+++ b/indra/llxuixml/llxuiparser.cpp
@@ -440,12 +440,11 @@ bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block)
&& nodep->mAttributes.empty()
&& nodep->getSanitizedValue().empty())
{
- // empty node, just parse as NoValue
+ // empty node, just parse as flag
mCurReadNode = DUMMY_NODE;
return block.submitValue(mNameStack, *this, silent);
}
-
// submit attributes for current node
values_parsed |= readAttributes(nodep, block);
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 64438fe614..41a90f5984 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -2297,8 +2297,8 @@ Would you be my friend?
icon="alertmodal.tga"
label="Save Outfit"
name="SaveOutfitAs"
- type="alertmodal"
- unique="true">
+ type="alertmodal">
+
Save what I'm wearing as a new Outfit:
confirm
@@ -5645,8 +5646,8 @@ This area does not allow pushing. You can't push others here unless you own
icon="notify.tga"
name="NoVoice"
persist="true"
- type="notify"
- unique="true">
+ type="notify">
+
This area has voice chat disabled. You won't be able to hear anyone talking.
voice
@@ -5655,8 +5656,8 @@ This area has voice chat disabled. You won't be able to hear anyone talking
icon="notify.tga"
name="NoBuild"
persist="true"
- type="notify"
- unique="true">
+ type="notify">
+
This area has building disabled. You can't build or rez objects here.
@@ -5664,8 +5665,8 @@ This area has building disabled. You can't build or rez objects here.
icon="notify.tga"
name="SeeAvatars"
persist="true"
- type="notify"
- unique="true">
+ type="notify">
+
This parcel hides avatars and text chat from another parcel. You can't see other residents outside the parcel, and those outside are not able to see you. Regular text chat on channel 0 is also blocked.
@@ -6553,8 +6554,8 @@ The voice call you are trying to join, [VOICE_CHANNEL_NAME], has reached maximum
+ type="notifytip">
+
We're sorry. This area has reached maximum capacity for voice conversations. Please try to use voice in another area.
fail
voice
@@ -6622,8 +6623,8 @@ Failed to connect to [VOICE_CHANNEL_NAME], please try again later. You will now
duration="10"
icon="notifytip.tga"
name="VoiceLoginRetry"
- type="notifytip"
- unique="true">
+ type="notifytip">
+
We are creating a voice channel for you. This may take up to one minute.
status
voice
@@ -6634,8 +6635,8 @@ We are creating a voice channel for you. This may take up to one minute.
name="VoiceEffectsExpired"
sound="UISndAlert"
persist="true"
- type="notify"
- unique="true">
+ type="notify">
+
One or more of your subscribed Voice Morphs has expired.
[[URL] Click here] to renew your subscription.
fail
@@ -6647,8 +6648,8 @@ One or more of your subscribed Voice Morphs has expired.
name="VoiceEffectsExpiredInUse"
sound="UISndAlert"
persist="true"
- type="notify"
- unique="true">
+ type="notify">
+
The active Voice Morph has expired, your normal voice settings have been applied.
[[URL] Click here] to renew your subscription.
fail
@@ -6660,8 +6661,8 @@ The active Voice Morph has expired, your normal voice settings have been applied
name="VoiceEffectsWillExpire"
sound="UISndAlert"
persist="true"
- type="notify"
- unique="true">
+ type="notify">
+
One or more of your Voice Morphs will expire in less than [INTERVAL] days.
[[URL] Click here] to renew your subscription.
fail
@@ -6673,8 +6674,8 @@ One or more of your Voice Morphs will expire in less than [INTERVAL] days.
name="VoiceEffectsNew"
sound="UISndAlert"
persist="true"
- type="notify"
- unique="true">
+ type="notify">
+
New Voice Morphs are available!
voice
@@ -7075,8 +7076,9 @@ Are you sure you want to leave this call?
ignoretext="Confirm before I leave call"
name="okcancelignore"
notext="No"
- yestext="Yes"
- unique="true"/>
+ yestext="Yes">
+
+
+ notext="Cancel">
+
+
+ type="hint">
+
To join the conversation, type into the chat field below.
+ type="hint">
+
To stand up and exit the sitting position, click the Stand button.
+ type="hint">
+
Click the Speak button to turn your microphone on and off.
Click on the up arrow to see the voice control panel.
@@ -7130,32 +7132,32 @@ Hiding the Speak button will disable the voice feature.
+ type="hint">
+
The Destination Guide contains thousands of new places to discover. Select a location and choose Teleport to start exploring.
+ type="hint">
+
Get quick access to your inventory, outfits, profiles and more in the side panel.
+ type="hint">
+
To walk or run, open the Move Panel and use the directional arrows to navigate. You can also use the directional keys on your keyboard.
+ type="hint">
+
1. Click to Walk
Click anywhere on the ground to walk to that spot.
@@ -7167,8 +7169,8 @@ Click and drag anywhere on the world to rotate your view
+ type="hint">
+
Set your customizable display name here. This is in addition to your unique username, which can't be changed. You can change how you see other people's names in your preferences.
@@ -7176,8 +7178,8 @@ Click and drag anywhere on the world to rotate your view
+ type="hint">
+
To change your camera view, use the Orbit and Pan controls. Reset your view by pressing Escape or walking.
custom_skin
@@ -7185,16 +7187,16 @@ Click and drag anywhere on the world to rotate your view
+ type="hint">
+
Check your inventory to find items. Newest items can be easily found in the Recent tab.
+ type="hint">
+
Here's your current balance of L$. Click Buy L$ to purchase more Linden Dollars.
funds
@@ -7383,8 +7385,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm '
+ type="alertmodal">
+
Changing modes requires you to quit and restart.
confirm
+ type="alertmodal">
+
fail
confirm
Creation and editing of Classifieds is only available in Advanced mode. Would you like to quit and change modes? The mode selector can be found on the login screen.
@@ -7410,8 +7412,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm '
+ type="alertmodal">
+
fail
confirm
Creation and editing of Groups is only available in Advanced mode. Would you like to quit and change modes? The mode selector can be found on the login screen.
@@ -7424,8 +7426,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm '
+ type="alertmodal">
+
fail
confirm
Viewing place profile is only available in Advanced mode. Would you like to quit and change modes? The mode selector can be found on the login screen.
@@ -7438,8 +7440,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm '
+ type="alertmodal">
+
fail
confirm
Creation and editing of Picks is only available in Advanced mode. Would you like to quit and change modes? The mode selector can be found on the login screen.
@@ -7452,8 +7454,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm '
+ type="alertmodal">
+
fail
confirm
Viewing of the world map is only available in Advanced mode. Would you like to quit and change modes? The mode selector can be found on the login screen.
@@ -7466,8 +7468,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm '
+ type="alertmodal">
+
fail
confirm
Voice calls are only available in Advanced mode. Would you like to logout and change modes?
@@ -7480,8 +7482,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm '
+ type="alertmodal">
+
fail
confirm
Sharing is only available in Advanced mode. Would you like to logout and change modes?
@@ -7494,8 +7496,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm '
+ type="alertmodal">
+
fail
confirm
Paying other residents is only available in Advanced mode. Would you like to logout and change modes?
@@ -7508,8 +7510,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm '
+ type="alertmodal">
+
fail
confirm
Viewing inventory is only available in Advanced mode. Would you like to logout and change modes?
@@ -7522,8 +7524,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm '
+ type="alertmodal">
+
fail
confirm
The appearance editor is only available in Advanced mode. Would you like to logout and change modes?
@@ -7536,8 +7538,8 @@ The site at '<nolink>[HOST_NAME]</nolink>' in realm '
+ type="alertmodal">
+
fail
confirm
Search is only available in Advanced mode. Would you like to logout and change modes?