Remove hardcoded var passing between LLPostProcess and its floater. Now driven through the xml file.
This commit is contained in:
@@ -43,7 +43,11 @@
|
||||
#include "llcombobox.h"
|
||||
#include "lllineeditor.h"
|
||||
#include "llviewerwindow.h"
|
||||
|
||||
#if LL_MSVC
|
||||
// disable boost::lexical_cast warning
|
||||
#pragma warning (disable:4702)
|
||||
#endif
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
LLFloaterPostProcess* LLFloaterPostProcess::sPostProcess = NULL;
|
||||
|
||||
@@ -52,27 +56,31 @@ LLFloaterPostProcess::LLFloaterPostProcess() : LLFloater(std::string("Post-Proce
|
||||
{
|
||||
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_post_process.xml");
|
||||
|
||||
/// Color Filter Callbacks
|
||||
childSetCommitCallback("ColorFilterToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_color_filter");
|
||||
childSetCommitCallback("ColorFilterGamma", &LLFloaterPostProcess::onFloatControlMoved, (char*)"gamma");
|
||||
childSetCommitCallback("ColorFilterBrightness", &LLFloaterPostProcess::onFloatControlMoved, (char*)"brightness");
|
||||
childSetCommitCallback("ColorFilterSaturation", &LLFloaterPostProcess::onFloatControlMoved, (char*)"saturation");
|
||||
childSetCommitCallback("ColorFilterContrast", &LLFloaterPostProcess::onFloatControlMoved, (char*)"contrast");
|
||||
LLTabContainer *panel_list = getChild<LLTabContainer>("Post-Process Tabs",false,false); //Contains a tab for each shader
|
||||
if(panel_list)
|
||||
{
|
||||
//Iterate down tabs to access each panel
|
||||
for(S32 i = 0; i<panel_list->getTabCount(); ++i)
|
||||
{
|
||||
//Get the panel via index
|
||||
LLPanel *shader_panel = panel_list->getPanelByIndex(i);
|
||||
|
||||
childSetCommitCallback("ColorFilterBaseR", &LLFloaterPostProcess::onColorControlRMoved, (char*)"contrast_base");
|
||||
childSetCommitCallback("ColorFilterBaseG", &LLFloaterPostProcess::onColorControlGMoved, (char*)"contrast_base");
|
||||
childSetCommitCallback("ColorFilterBaseB", &LLFloaterPostProcess::onColorControlBMoved, (char*)"contrast_base");
|
||||
childSetCommitCallback("ColorFilterBaseI", &LLFloaterPostProcess::onColorControlIMoved, (char*)"contrast_base");
|
||||
//'Extra' panel controls loading/saving. No uniforms should be altered in this panel.
|
||||
if(shader_panel->getName() == "Extras")
|
||||
continue;
|
||||
|
||||
/// Night Vision Callbacks
|
||||
childSetCommitCallback("NightVisionToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_night_vision");
|
||||
childSetCommitCallback("NightVisionBrightMult", &LLFloaterPostProcess::onFloatControlMoved, (char*)"brightness_multiplier");
|
||||
childSetCommitCallback("NightVisionNoiseSize", &LLFloaterPostProcess::onFloatControlMoved, (char*)"noise_size");
|
||||
childSetCommitCallback("NightVisionNoiseStrength", &LLFloaterPostProcess::onFloatControlMoved, (char*)"noise_strength");
|
||||
|
||||
// Gauss Blur Callbacks
|
||||
childSetCommitCallback("GaussBlurToggle", &LLFloaterPostProcess::onBoolToggle, (char*)"enable_gauss_blur");
|
||||
childSetCommitCallback("GaussBlurPasses", &LLFloaterPostProcess::onFloatControlMoved, (char*)"gauss_blur_passes");
|
||||
//Iterate down children elements of each panel.
|
||||
for ( child_list_const_iter_t child_it = shader_panel->getChildList()->begin(); child_it != shader_panel->getChildList()->end(); ++child_it)
|
||||
{
|
||||
//Hacky, but for now checkboxes and sliders are assumed to link to shader uniforms.
|
||||
if(dynamic_cast<LLSliderCtrl*>(*child_it) || dynamic_cast<LLCheckBoxCtrl*>(*child_it))
|
||||
{
|
||||
LLUICtrl *ctrl = dynamic_cast<LLUICtrl*>(*child_it);
|
||||
ctrl->setCommitCallback(boost::bind(&LLFloaterPostProcess::onControlChanged, _1, (void*)ctrl->getName().c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Effect loading and saving.
|
||||
LLComboBox* comboBox = getChild<LLComboBox>("PPEffectsCombo");
|
||||
@@ -104,54 +112,20 @@ LLFloaterPostProcess* LLFloaterPostProcess::instance()
|
||||
return sPostProcess;
|
||||
}
|
||||
|
||||
// Bool Toggle
|
||||
void LLFloaterPostProcess::onBoolToggle(LLUICtrl* ctrl, void* userData)
|
||||
{
|
||||
char const * boolVariableName = (char const *)userData;
|
||||
|
||||
// check the bool
|
||||
LLCheckBoxCtrl* cbCtrl = static_cast<LLCheckBoxCtrl*>(ctrl);
|
||||
LLPostProcess::getInstance()->tweaks[boolVariableName] = cbCtrl->getValue();
|
||||
}
|
||||
|
||||
// Float Moved
|
||||
void LLFloaterPostProcess::onFloatControlMoved(LLUICtrl* ctrl, void* userData)
|
||||
void LLFloaterPostProcess::onControlChanged(LLUICtrl* ctrl, void* userData)
|
||||
{
|
||||
char const * floatVariableName = (char const *)userData;
|
||||
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
|
||||
LLPostProcess::getInstance()->tweaks[floatVariableName] = sldrCtrl->getValue();
|
||||
}
|
||||
|
||||
// Color Moved
|
||||
void LLFloaterPostProcess::onColorControlRMoved(LLUICtrl* ctrl, void* userData)
|
||||
{
|
||||
char const * floatVariableName = (char const *)userData;
|
||||
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
|
||||
LLPostProcess::getInstance()->tweaks[floatVariableName][0] = sldrCtrl->getValue();
|
||||
}
|
||||
|
||||
// Color Moved
|
||||
void LLFloaterPostProcess::onColorControlGMoved(LLUICtrl* ctrl, void* userData)
|
||||
{
|
||||
char const * floatVariableName = (char const *)userData;
|
||||
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
|
||||
LLPostProcess::getInstance()->tweaks[floatVariableName][1] = sldrCtrl->getValue();
|
||||
}
|
||||
|
||||
// Color Moved
|
||||
void LLFloaterPostProcess::onColorControlBMoved(LLUICtrl* ctrl, void* userData)
|
||||
{
|
||||
char const * floatVariableName = (char const *)userData;
|
||||
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
|
||||
LLPostProcess::getInstance()->tweaks[floatVariableName][2] = sldrCtrl->getValue();
|
||||
}
|
||||
|
||||
// Color Moved
|
||||
void LLFloaterPostProcess::onColorControlIMoved(LLUICtrl* ctrl, void* userData)
|
||||
{
|
||||
char const * floatVariableName = (char const *)userData;
|
||||
LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl);
|
||||
LLPostProcess::getInstance()->tweaks[floatVariableName][3] = sldrCtrl->getValue();
|
||||
char const *VariableName = (char const *)userData;
|
||||
char buf[256];
|
||||
S32 elem=0;
|
||||
if(sscanf(VariableName,"%255[^[][%d]", buf, &elem) == 2)
|
||||
{
|
||||
LLPostProcess::getInstance()->tweaks[buf][elem] = ctrl->getValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
LLPostProcess::getInstance()->tweaks[VariableName] = ctrl->getValue();
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterPostProcess::onLoadEffect(void* userData)
|
||||
@@ -245,24 +219,23 @@ void LLFloaterPostProcess::syncMenu()
|
||||
// set the current effect as selected.
|
||||
comboBox->selectByValue(LLPostProcess::getInstance()->getSelectedEffect());
|
||||
|
||||
/// Sync Color Filter Menu
|
||||
childSetValue("ColorFilterToggle", LLPostProcess::getInstance()->tweaks.useColorFilter());
|
||||
childSetValue("ColorFilterGamma", LLPostProcess::getInstance()->tweaks.getGamma());
|
||||
childSetValue("ColorFilterBrightness", LLPostProcess::getInstance()->tweaks.brightness());
|
||||
childSetValue("ColorFilterSaturation", LLPostProcess::getInstance()->tweaks.saturation());
|
||||
childSetValue("ColorFilterContrast", LLPostProcess::getInstance()->tweaks.contrast());
|
||||
childSetValue("ColorFilterBaseR", LLPostProcess::getInstance()->tweaks.contrastBaseR());
|
||||
childSetValue("ColorFilterBaseG", LLPostProcess::getInstance()->tweaks.contrastBaseG());
|
||||
childSetValue("ColorFilterBaseB", LLPostProcess::getInstance()->tweaks.contrastBaseB());
|
||||
childSetValue("ColorFilterBaseI", LLPostProcess::getInstance()->tweaks.contrastBaseIntensity());
|
||||
|
||||
/// Sync Night Vision Menu
|
||||
childSetValue("NightVisionToggle", LLPostProcess::getInstance()->tweaks.useNightVisionShader());
|
||||
childSetValue("NightVisionBrightMult", LLPostProcess::getInstance()->tweaks.brightMult());
|
||||
childSetValue("NightVisionNoiseSize", LLPostProcess::getInstance()->tweaks.noiseSize());
|
||||
childSetValue("NightVisionNoiseStrength", LLPostProcess::getInstance()->tweaks.noiseStrength());
|
||||
|
||||
/// Sync Gaussian Blur Menu
|
||||
childSetValue("GaussBlurToggle", LLPostProcess::getInstance()->tweaks.useGaussBlurFilter());
|
||||
childSetValue("GaussBlurPasses", LLPostProcess::getInstance()->tweaks.getGaussBlurPasses());
|
||||
LLSD &tweaks = LLPostProcess::getInstance()->tweaks;
|
||||
//Iterate down all uniforms handled by post-process shaders. Update any linked ui elements.
|
||||
for (LLSD::map_const_iterator it = tweaks.beginMap(); it != tweaks.endMap(); ++it)
|
||||
{
|
||||
if(it->second.isArray())
|
||||
{
|
||||
//llsd["uniform"][0]=>"uniform[0]"
|
||||
//llsd["uniform"][1]=>"uniform[1]"
|
||||
for(S32 i=0;i<it->second.size();++i)
|
||||
{
|
||||
childSetValue(it->first+"["+boost::lexical_cast<std::string>(i)+"]",it->second[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//llsd["uniform"]=>"uniform"
|
||||
childSetValue(it->first,it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,12 +58,7 @@ public:
|
||||
static LLFloaterPostProcess* instance();
|
||||
|
||||
/// post process callbacks
|
||||
static void onBoolToggle(LLUICtrl* ctrl, void* userData);
|
||||
static void onFloatControlMoved(LLUICtrl* ctrl, void* userData);
|
||||
static void onColorControlRMoved(LLUICtrl* ctrl, void* userData);
|
||||
static void onColorControlGMoved(LLUICtrl* ctrl, void* userData);
|
||||
static void onColorControlBMoved(LLUICtrl* ctrl, void* userData);
|
||||
static void onColorControlIMoved(LLUICtrl* ctrl, void* userData);
|
||||
static void onControlChanged(LLUICtrl* ctrl, void* userData);
|
||||
static void onLoadEffect(void* userData);
|
||||
static void onSaveEffect(void* userData);
|
||||
static void onChangeEffectName(LLUICtrl* ctrl, void * userData);
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
<panel border="true" bottom="-400" follows="left|top|right|bottom" height="400"
|
||||
label="Color Filter" left="1" mouse_opaque="false"
|
||||
name="ColorFilterPanel" width="398">
|
||||
<check_box bottom="-20" control_name="ColorFilterToggle" follows="left|top"
|
||||
<check_box bottom="-20" follows="left|top"
|
||||
font="SansSerifSmall" height="16" initial_value="false" label="Enable"
|
||||
left="14" mouse_opaque="true" name="ColorFilterToggle" width="200" />
|
||||
left="14" mouse_opaque="true" name="enable_color_filter" width="200" />
|
||||
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
|
||||
bottom_delta="-20" drop_shadow_visible="true" follows="left|top|right"
|
||||
font="SansSerif" h_pad="0" halign="left" height="16"
|
||||
@@ -19,10 +19,9 @@
|
||||
width="355">
|
||||
Gamma
|
||||
</text>
|
||||
<slider bottom_delta="-30" can_edit_text="true"
|
||||
control_name="ColorFilterGamma" decimal_digits="2" follows="left"
|
||||
<slider bottom_delta="-30" can_edit_text="true" decimal_digits="2" follows="left"
|
||||
height="18" increment="0.01" initial_val="1.0" label="" left="14"
|
||||
max_val="10" min_val="-.25" mouse_opaque="true" name="ColorFilterGamma"
|
||||
max_val="10" min_val="-.25" mouse_opaque="true" name="gamma"
|
||||
show_text="true" value="1.0" width="200" />
|
||||
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
|
||||
bottom_delta="-20" drop_shadow_visible="true" follows="left|top|right"
|
||||
@@ -31,10 +30,9 @@
|
||||
width="355">
|
||||
Brightness
|
||||
</text>
|
||||
<slider bottom_delta="-30" can_edit_text="true"
|
||||
control_name="ColorFilterBrightness" decimal_digits="2" follows="left"
|
||||
<slider bottom_delta="-30" can_edit_text="true" decimal_digits="2" follows="left"
|
||||
height="18" increment="0.01" initial_val="1.0" label="" left="14"
|
||||
max_val="4" min_val="0" mouse_opaque="true" name="ColorFilterBrightness"
|
||||
max_val="4" min_val="0" mouse_opaque="true" name="brightness"
|
||||
show_text="true" value="1.0" width="200" />
|
||||
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
|
||||
bottom_delta="-20" drop_shadow_visible="true" follows="left|top|right"
|
||||
@@ -43,11 +41,10 @@
|
||||
width="355">
|
||||
Saturation
|
||||
</text>
|
||||
<slider bottom_delta="-30" can_edit_text="true"
|
||||
control_name="ColorFilterSaturation" decimal_digits="2" follows="left"
|
||||
<slider bottom_delta="-30" can_edit_text="true" decimal_digits="2" follows="left"
|
||||
height="18" increment="0.01" initial_val="1.0" label="" left="14"
|
||||
max_val="2" min_val="-1" mouse_opaque="true"
|
||||
name="ColorFilterSaturation" show_text="true" value="1.0" width="200" />
|
||||
name="saturation" show_text="true" value="1.0" width="200" />
|
||||
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
|
||||
bottom_delta="-20" drop_shadow_visible="true" follows="left|top|right"
|
||||
font="SansSerif" h_pad="0" halign="left" height="16"
|
||||
@@ -55,45 +52,45 @@
|
||||
width="355">
|
||||
Contrast
|
||||
</text>
|
||||
<slider bottom_delta="-30" can_edit_text="true" control_name="ColorFilterContrast"
|
||||
<slider bottom_delta="-30" can_edit_text="true"
|
||||
decimal_digits="2" follows="left" height="18" increment="0.01"
|
||||
initial_val="1.0" label="" left="14" max_val="4" min_val="0"
|
||||
mouse_opaque="true" name="ColorFilterContrast" show_text="true"
|
||||
mouse_opaque="true" name="contrast" show_text="true"
|
||||
value="1.0" width="200" />
|
||||
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
|
||||
bottom_delta="-20" drop_shadow_visible="true" follows="left|top|right"
|
||||
font="SansSerif" h_pad="0" halign="left" height="16"
|
||||
left="10" mouse_opaque="true" name="ColorFilterBaseText" v_pad="0"
|
||||
width="355">
|
||||
Contrast Base Color
|
||||
Contrast Base Colora
|
||||
</text>
|
||||
<slider bottom_delta="-30" can_edit_text="true" control_name="ColorFilterBaseR"
|
||||
<slider bottom_delta="-30" can_edit_text="true"
|
||||
decimal_digits="3" follows="left" height="18" increment="0.01"
|
||||
initial_val="1.0" label="R" left="14" max_val="1" min_val="0"
|
||||
mouse_opaque="true" name="ColorFilterBaseR" show_text="true" value="1.0"
|
||||
mouse_opaque="true" name="contrast_base[0]" show_text="true" value="1.0"
|
||||
width="200" />
|
||||
<slider bottom_delta="-20" can_edit_text="true" control_name="ColorFilterBaseG"
|
||||
<slider bottom_delta="-20" can_edit_text="true"
|
||||
decimal_digits="3" follows="left" height="18" increment="0.01"
|
||||
initial_val="1.0" label="G" left="14" max_val="1" min_val="0"
|
||||
mouse_opaque="true" name="ColorFilterBaseG" show_text="true" value="1.0"
|
||||
mouse_opaque="true" name="contrast_base[1]" show_text="true" value="1.0"
|
||||
width="200" />
|
||||
<slider bottom_delta="-20" can_edit_text="true" control_name="ColorFilterBaseB"
|
||||
<slider bottom_delta="-20" can_edit_text="true"
|
||||
decimal_digits="3" follows="left" height="18" increment="0.01"
|
||||
initial_val="1.0" label="B" left="14" max_val="1" min_val="0"
|
||||
mouse_opaque="true" name="ColorFilterBaseB" show_text="true" value="1.0"
|
||||
mouse_opaque="true" name="contrast_base[2]" show_text="true" value="1.0"
|
||||
width="200" />
|
||||
<slider bottom_delta="-20" can_edit_text="true" control_name="ColorFilterBaseI"
|
||||
<slider bottom_delta="-20" can_edit_text="true"
|
||||
decimal_digits="3" follows="left" height="18" increment="0.01"
|
||||
initial_val="0.5" label="I" left="14" max_val="1" min_val="0"
|
||||
mouse_opaque="true" name="ColorFilterBaseI" show_text="true" value="1.0"
|
||||
mouse_opaque="true" name="contrast_base[3]" show_text="true" value="1.0"
|
||||
width="200" />
|
||||
</panel>
|
||||
<panel border="true" bottom="-180" follows="left|top|right|bottom" height="400"
|
||||
label="Gauss Blur" left="1" mouse_opaque="false"
|
||||
name="GaussBlurPanel" width="398">
|
||||
<check_box bottom="-20" control_name="GaussBlurToggle" follows="left|top"
|
||||
<check_box bottom="-20" follows="left|top"
|
||||
font="SansSerifSmall" height="16" initial_value="false" label="Enable"
|
||||
left="14" mouse_opaque="true" name="GaussBlurToggle" width="200" />
|
||||
left="14" mouse_opaque="true" name="enable_gauss_blur" width="200" />
|
||||
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
|
||||
bottom_delta="-21" drop_shadow_visible="true" follows="left|top|right"
|
||||
font="SansSerif" h_pad="0" halign="left" height="16"
|
||||
@@ -102,17 +99,17 @@
|
||||
Passes to apply
|
||||
</text>
|
||||
<slider bottom_delta="-30" can_edit_text="true"
|
||||
control_name="GaussBlurPasses" decimal_digits="0" follows="left"
|
||||
decimal_digits="0" follows="left"
|
||||
height="18" increment="1" initial_val="9" label="" left="14"
|
||||
max_val="25" min_val="1" mouse_opaque="true"
|
||||
name="GaussBlurPasses" show_text="true" value="0.7" width="200" />
|
||||
name="gauss_blur_passes" show_text="true" value="0.7" width="200" />
|
||||
</panel>
|
||||
<panel border="true" bottom="-180" follows="left|top|right|bottom" height="400"
|
||||
label="Night Vision" left="1" mouse_opaque="false"
|
||||
name="NightVisionPanel" width="398">
|
||||
<check_box bottom="-20" control_name="NightVisionToggle" follows="left|top"
|
||||
<check_box bottom="-20" follows="left|top"
|
||||
font="SansSerifSmall" height="16" initial_value="false" label="Enable"
|
||||
left="14" mouse_opaque="true" name="NightVisionToggle" width="200" />
|
||||
left="14" mouse_opaque="true" name="enable_night_vision" width="200" />
|
||||
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
|
||||
bottom_delta="-21" drop_shadow_visible="true" follows="left|top|right"
|
||||
font="SansSerif" h_pad="0" halign="left" height="16"
|
||||
@@ -121,10 +118,10 @@
|
||||
Light Amplification Multiple
|
||||
</text>
|
||||
<slider bottom_delta="-30" can_edit_text="true"
|
||||
control_name="NightVisionBrightMult" decimal_digits="3" follows="left"
|
||||
decimal_digits="3" follows="left"
|
||||
height="18" increment="0.01" initial_val="3.0" label="" left="14"
|
||||
max_val="10" min_val="1" mouse_opaque="true"
|
||||
name="NightVisionBrightMult" show_text="true" value="0.7" width="200" />
|
||||
name="brightness_multiplier" show_text="true" value="0.7" width="200" />
|
||||
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
|
||||
bottom_delta="-20" drop_shadow_visible="true" follows="left|top|right"
|
||||
font="SansSerif" h_pad="0" halign="left" height="16"
|
||||
@@ -132,10 +129,10 @@
|
||||
width="355">
|
||||
Noise Size
|
||||
</text>
|
||||
<slider bottom_delta="-30" can_edit_text="true" control_name="NightVisionNoiseSize"
|
||||
<slider bottom_delta="-30" can_edit_text="true"
|
||||
decimal_digits="3" follows="left" height="18" increment="0.1"
|
||||
initial_val="1" label="" left="14" max_val="100" min_val=".1"
|
||||
mouse_opaque="true" name="NightVisionNoiseSize" show_text="true"
|
||||
initial_val="1" label="" left="14" max_val="100" min_val="1"
|
||||
mouse_opaque="true" name="noise_size" show_text="true"
|
||||
value="1.0" width="200" />
|
||||
<text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false"
|
||||
bottom_delta="-20" drop_shadow_visible="true" follows="left|top|right"
|
||||
@@ -144,11 +141,10 @@
|
||||
v_pad="0" width="355">
|
||||
Noise Strength
|
||||
</text>
|
||||
<slider bottom_delta="-30" can_edit_text="true"
|
||||
control_name="NightVisionNoiseStrength" decimal_digits="3"
|
||||
<slider bottom_delta="-30" can_edit_text="true" decimal_digits="3"
|
||||
follows="left" height="18" increment="0.01" initial_val="0.3" label=""
|
||||
left="14" max_val="1" min_val="0" mouse_opaque="true"
|
||||
name="NightVisionNoiseStrength" show_text="true" value="1.0" width="200" />
|
||||
name="noise_strength" show_text="true" value="1.0" width="200" />
|
||||
</panel>
|
||||
<!--<panel border="true" bottom="-180" follows="left|top|right|bottom" height="400"
|
||||
label="Bloom" left="1" mouse_opaque="true"
|
||||
|
||||
Reference in New Issue
Block a user