summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorDave Parks <davep@lindenlab.com>2022-11-02 12:17:28 -0500
committerDave Parks <davep@lindenlab.com>2022-11-02 12:17:28 -0500
commit32cc9a71d0e71bba96555558275a684501493e83 (patch)
treeb61f7b91ea7b6a0cee649da734413b265ebab6ac /indra
parentc3f94ab9a1da2c0c5304ff624b54fad6a43506ae (diff)
parent734e3fcb21228d07038da952820fa371e3c8af14 (diff)
Merge branch 'DRTVWR-559' of ssh://bitbucket.org/lindenlab/viewer into DRTVWR-559
Diffstat (limited to 'indra')
-rw-r--r--indra/llui/llfloater.h1
-rw-r--r--indra/newview/lllogininstance.cpp86
-rw-r--r--indra/newview/lllogininstance.h1
-rw-r--r--indra/newview/llmaterialeditor.cpp319
-rw-r--r--indra/newview/llmaterialeditor.h2
-rw-r--r--indra/newview/llpanelface.cpp20
-rw-r--r--indra/newview/llviewerfloaterreg.cpp1
-rw-r--r--indra/newview/skins/default/xui/en/floater_live_material_editor.xml37
-rw-r--r--indra/newview/skins/default/xui/en/floater_material_editor.xml433
-rw-r--r--indra/newview/skins/default/xui/en/panel_gltf_material.xml382
10 files changed, 632 insertions, 650 deletions
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 668cd208a9..3d15708295 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -225,6 +225,7 @@ public:
/*virtual*/ void setIsChrome(BOOL is_chrome);
/*virtual*/ void setRect(const LLRect &rect);
void setIsSingleInstance(BOOL is_single_instance);
+ BOOL getIsSingleInstance() { return mSingleInstance; }
void initFloater(const Params& p);
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
index 82ecfbd4dc..dd8c9b2dde 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -451,26 +451,8 @@ void LLLoginInstance::handleLoginFailure(const LLSD& event)
LLSD args(llsd::map( "MESSAGE", LLTrans::getString(response["message_id"]) ));
LLSD payload;
- LLNotificationsUtil::add("PromptMFAToken", args, payload, [=](LLSD const & notif, LLSD const & response) {
- bool continue_clicked = response["continue"].asBoolean();
- std::string token = response["token"].asString();
- LL_DEBUGS("LLLogin") << "PromptMFAToken: response: " << response << " continue_clicked" << continue_clicked << LL_ENDL;
-
- // strip out whitespace - SL-17034/BUG-231938
- token = boost::regex_replace(token, boost::regex("\\s"), "");
-
- if (continue_clicked && !token.empty())
- {
- LL_INFOS("LLLogin") << "PromptMFAToken: token submitted" << LL_ENDL;
-
- // Set the request data to true and retry login.
- mRequestData["params"]["token"] = token;
- reconnect();
- } else {
- LL_INFOS("LLLogin") << "PromptMFAToken: no token, attemptComplete" << LL_ENDL;
- attemptComplete();
- }
- });
+ LLNotificationsUtil::add("PromptMFAToken", args, payload,
+ boost::bind(&LLLoginInstance::handleMFAChallenge, this, _1, _2));
}
else if( reason_response == "key"
|| reason_response == "presence"
@@ -547,23 +529,59 @@ void LLLoginInstance::handleIndeterminate(const LLSD& event)
bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key)
{
- if(accepted)
- {
- LL_INFOS("LLLogin") << "LLLoginInstance::handleTOSResponse: accepted" << LL_ENDL;
+ if(accepted)
+ {
+ LL_INFOS("LLLogin") << "LLLoginInstance::handleTOSResponse: accepted " << LL_ENDL;
- // Set the request data to true and retry login.
- mRequestData["params"][key] = true;
- reconnect();
- }
- else
- {
- LL_INFOS("LLLogin") << "LLLoginInstance::handleTOSResponse: attemptComplete" << LL_ENDL;
+ // Set the request data to true and retry login.
+ mRequestData["params"][key] = true;
- attemptComplete();
- }
+ if (!mRequestData["params"]["token"].asString().empty())
+ {
+ // SL-18511 this TOS failure happened while we are in the middle of an MFA challenge/response.
+ // the previously entered token is very likely expired, so prompt again
+ LLSD args(llsd::map( "MESSAGE", LLTrans::getString("LoginFailedAuthenticationMFARequired") ));
+ LLSD payload;
+ LLNotificationsUtil::add("PromptMFAToken", args, payload,
+ boost::bind(&LLLoginInstance::handleMFAChallenge, this, _1, _2));
+ }
+ else
+ {
+ reconnect();
+ }
+ }
+ else
+ {
+ LL_INFOS("LLLogin") << "LLLoginInstance::handleTOSResponse: attemptComplete" << LL_ENDL;
+
+ attemptComplete();
+ }
+
+ LLEventPumps::instance().obtain(TOS_REPLY_PUMP).stopListening(TOS_LISTENER_NAME);
+ return true;
+}
- LLEventPumps::instance().obtain(TOS_REPLY_PUMP).stopListening(TOS_LISTENER_NAME);
- return true;
+bool LLLoginInstance::handleMFAChallenge(LLSD const & notif, LLSD const & response)
+{
+ bool continue_clicked = response["continue"].asBoolean();
+ std::string token = response["token"].asString();
+ LL_DEBUGS("LLLogin") << "PromptMFAToken: response: " << response << " continue_clicked" << continue_clicked << LL_ENDL;
+
+ // strip out whitespace - SL-17034/BUG-231938
+ token = boost::regex_replace(token, boost::regex("\\s"), "");
+
+ if (continue_clicked && !token.empty())
+ {
+ LL_INFOS("LLLogin") << "PromptMFAToken: token submitted" << LL_ENDL;
+
+ // Set the request data to true and retry login.
+ mRequestData["params"]["token"] = token;
+ reconnect();
+ } else {
+ LL_INFOS("LLLogin") << "PromptMFAToken: no token, attemptComplete" << LL_ENDL;
+ attemptComplete();
+ }
+ return true;
}
std::string construct_start_string()
diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h
index b759b43474..ee3ef0e4b1 100644
--- a/indra/newview/lllogininstance.h
+++ b/indra/newview/lllogininstance.h
@@ -84,6 +84,7 @@ private:
void syncWithUpdater(ResponsePtr resp, const LLSD& notification, const LLSD& response);
bool handleTOSResponse(bool v, const std::string& key);
+ bool handleMFAChallenge(LLSD const & notif, LLSD const & response);
void attemptComplete() { mAttemptComplete = true; } // In the future an event?
diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp
index 004d61a2ec..792a916e6b 100644
--- a/indra/newview/llmaterialeditor.cpp
+++ b/indra/newview/llmaterialeditor.cpp
@@ -65,9 +65,6 @@ const std::string MATERIAL_NORMAL_DEFAULT_NAME = "Normal";
const std::string MATERIAL_METALLIC_DEFAULT_NAME = "Metallic Roughness";
const std::string MATERIAL_EMISSIVE_DEFAULT_NAME = "Emissive";
-// Don't use ids here, LLPreview will attempt to use it as an inventory item
-static const std::string LIVE_MATERIAL_EDITOR_KEY = "Live Editor";
-
// Dirty flags
static const U32 MATERIAL_BASE_COLOR_DIRTY = 0x1 << 0;
static const U32 MATERIAL_BASE_COLOR_TEX_DIRTY = 0x1 << 1;
@@ -326,8 +323,6 @@ LLMaterialEditor::LLMaterialEditor(const LLSD& key)
{
mAssetID = item->getAssetUUID();
}
- // if this is a 'live editor' instance, it uses live overrides
- mIsOverride = key.asString() == LIVE_MATERIAL_EDITOR_KEY;
}
void LLMaterialEditor::setObjectID(const LLUUID& object_id)
@@ -351,6 +346,10 @@ void LLMaterialEditor::setAuxItem(const LLInventoryItem* item)
BOOL LLMaterialEditor::postBuild()
{
+ // if this is a 'live editor' instance, it is also
+ // single instacne and uses live overrides
+ mIsOverride = getIsSingleInstance();
+
mBaseColorTextureCtrl = getChild<LLTextureCtrl>("base_color_texture");
mMetallicTextureCtrl = getChild<LLTextureCtrl>("metallic_roughness_texture");
mEmissiveTextureCtrl = getChild<LLTextureCtrl>("emissive_texture");
@@ -361,15 +360,28 @@ BOOL LLMaterialEditor::postBuild()
mEmissiveTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitEmissiveTexture, this, _1, _2));
mNormalTextureCtrl->setCommitCallback(boost::bind(&LLMaterialEditor::onCommitNormalTexture, this, _1, _2));
- childSetAction("save", boost::bind(&LLMaterialEditor::onClickSave, this));
- childSetAction("save_as", boost::bind(&LLMaterialEditor::onClickSaveAs, this));
- childSetAction("cancel", boost::bind(&LLMaterialEditor::onClickCancel, this));
+ if (!mIsOverride)
+ {
+ childSetAction("save", boost::bind(&LLMaterialEditor::onClickSave, this));
+ childSetAction("save_as", boost::bind(&LLMaterialEditor::onClickSaveAs, this));
+ childSetAction("cancel", boost::bind(&LLMaterialEditor::onClickCancel, this));
+ }
- S32 upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
- getChild<LLUICtrl>("base_color_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
- getChild<LLUICtrl>("metallic_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
- getChild<LLUICtrl>("emissive_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
- getChild<LLUICtrl>("normal_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
+ if (mIsOverride)
+ {
+ childSetVisible("base_color_upload_fee", FALSE);
+ childSetVisible("metallic_upload_fee", FALSE);
+ childSetVisible("emissive_upload_fee", FALSE);
+ childSetVisible("normal_upload_fee", FALSE);
+ }
+ else
+ {
+ S32 upload_cost = LLAgentBenefitsMgr::current().getTextureUploadCost();
+ getChild<LLUICtrl>("base_color_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
+ getChild<LLUICtrl>("metallic_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
+ getChild<LLUICtrl>("emissive_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
+ getChild<LLUICtrl>("normal_upload_fee")->setTextArg("[FEE]", llformat("%d", upload_cost));
+ }
boost::function<void(LLUICtrl*, void*)> changes_callback = [this](LLUICtrl * ctrl, void* userData)
{
@@ -394,9 +406,14 @@ BOOL LLMaterialEditor::postBuild()
// Emissive
childSetCommitCallback("emissive color", changes_callback, (void*)&MATERIAL_EMISIVE_COLOR_DIRTY);
- childSetVisible("unsaved_changes", mUnsavedChanges && !mIsOverride);
+ if (!mIsOverride)
+ {
+ // "unsaved_changes" doesn't exist in live editor
+ childSetVisible("unsaved_changes", mUnsavedChanges);
- getChild<LLUICtrl>("total_upload_fee")->setTextArg("[FEE]", llformat("%d", 0));
+ // Doesn't exist in live editor
+ getChild<LLUICtrl>("total_upload_fee")->setTextArg("[FEE]", llformat("%d", 0));
+ }
// Todo:
// Disable/enable setCanApplyImmediately() based on
@@ -407,7 +424,7 @@ BOOL LLMaterialEditor::postBuild()
void LLMaterialEditor::onClickCloseBtn(bool app_quitting)
{
- if (app_quitting)
+ if (app_quitting || mIsOverride)
{
closeFloater(app_quitting);
}
@@ -618,18 +635,27 @@ void LLMaterialEditor::setDoubleSided(bool double_sided)
void LLMaterialEditor::resetUnsavedChanges()
{
mUnsavedChanges = 0;
- childSetVisible("unsaved_changes", false);
- setCanSave(false);
+ if (!mIsOverride)
+ {
+ childSetVisible("unsaved_changes", false);
+ setCanSave(false);
- mExpectedUploadCost = 0;
- getChild<LLUICtrl>("total_upload_fee")->setTextArg("[FEE]", llformat("%d", mExpectedUploadCost));
+ mExpectedUploadCost = 0;
+ getChild<LLUICtrl>("total_upload_fee")->setTextArg("[FEE]", llformat("%d", mExpectedUploadCost));
+ }
}
void LLMaterialEditor::markChangesUnsaved(U32 dirty_flag)
{
mUnsavedChanges |= dirty_flag;
- // at the moment live editing (mIsOverride) applies everything 'live'
- childSetVisible("unsaved_changes", mUnsavedChanges && !mIsOverride);
+ if (!mIsOverride)
+ {
+ // at the moment live editing (mIsOverride) applies everything 'live'
+ // and "unsaved_changes", save/cancel buttons don't exist there
+ return;
+ }
+
+ childSetVisible("unsaved_changes", mUnsavedChanges);
if (mUnsavedChanges)
{
@@ -673,12 +699,18 @@ void LLMaterialEditor::markChangesUnsaved(U32 dirty_flag)
void LLMaterialEditor::setCanSaveAs(bool value)
{
- childSetEnabled("save_as", value);
+ if (!mIsOverride)
+ {
+ childSetEnabled("save_as", value);
+ }
}
void LLMaterialEditor::setCanSave(bool value)
{
- childSetEnabled("save", value);
+ if (!mIsOverride)
+ {
+ childSetEnabled("save", value);
+ }
}
void LLMaterialEditor::setEnableEditing(bool can_modify)
@@ -710,21 +742,24 @@ void LLMaterialEditor::setEnableEditing(bool can_modify)
void LLMaterialEditor::onCommitBaseColorTexture(LLUICtrl * ctrl, const LLSD & data)
{
- // might be better to use arrays, to have a single callback
- // and not to repeat the same thing for each tecture control
- LLUUID new_val = mBaseColorTextureCtrl->getValue().asUUID();
- if (new_val == mBaseColorTextureUploadId && mBaseColorTextureUploadId.notNull())
- {
- childSetValue("base_color_upload_fee", getString("upload_fee_string"));
- }
- else
+ if (!mIsOverride)
{
- // Texture picker has 'apply now' with 'cancel' support.
- // Keep mBaseColorJ2C and mBaseColorFetched, it's our storage in
- // case user decides to cancel changes.
- // Without mBaseColorFetched, viewer will eventually cleanup
- // the texture that is not in use
- childSetValue("base_color_upload_fee", getString("no_upload_fee_string"));
+ // might be better to use arrays, to have a single callback
+ // and not to repeat the same thing for each tecture control
+ LLUUID new_val = mBaseColorTextureCtrl->getValue().asUUID();
+ if (new_val == mBaseColorTextureUploadId && mBaseColorTextureUploadId.notNull())
+ {
+ childSetValue("base_color_upload_fee", getString("upload_fee_string"));
+ }
+ else
+ {
+ // Texture picker has 'apply now' with 'cancel' support.
+ // Keep mBaseColorJ2C and mBaseColorFetched, it's our storage in
+ // case user decides to cancel changes.
+ // Without mBaseColorFetched, viewer will eventually cleanup
+ // the texture that is not in use
+ childSetValue("base_color_upload_fee", getString("no_upload_fee_string"));
+ }
}
markChangesUnsaved(MATERIAL_BASE_COLOR_TEX_DIRTY);
applyToSelection();
@@ -732,14 +767,17 @@ void LLMaterialEditor::onCommitBaseColorTexture(LLUICtrl * ctrl, const LLSD & da
void LLMaterialEditor::onCommitMetallicTexture(LLUICtrl * ctrl, const LLSD & data)
{
- LLUUID new_val = mMetallicTextureCtrl->getValue().asUUID();
- if (new_val == mMetallicTextureUploadId && mMetallicTextureUploadId.notNull())
- {
- childSetValue("metallic_upload_fee", getString("upload_fee_string"));
- }
- else
+ if (!mIsOverride)
{
- childSetValue("metallic_upload_fee", getString("no_upload_fee_string"));
+ LLUUID new_val = mMetallicTextureCtrl->getValue().asUUID();
+ if (new_val == mMetallicTextureUploadId && mMetallicTextureUploadId.notNull())
+ {
+ childSetValue("metallic_upload_fee", getString("upload_fee_string"));
+ }
+ else
+ {
+ childSetValue("metallic_upload_fee", getString("no_upload_fee_string"));
+ }
}
markChangesUnsaved(MATERIAL_METALLIC_ROUGHTNESS_TEX_DIRTY);
applyToSelection();
@@ -747,14 +785,17 @@ void LLMaterialEditor::onCommitMetallicTexture(LLUICtrl * ctrl, const LLSD & dat
void LLMaterialEditor::onCommitEmissiveTexture(LLUICtrl * ctrl, const LLSD & data)
{
- LLUUID new_val = mEmissiveTextureCtrl->getValue().asUUID();
- if (new_val == mEmissiveTextureUploadId && mEmissiveTextureUploadId.notNull())
- {
- childSetValue("emissive_upload_fee", getString("upload_fee_string"));
- }
- else
+ if (!mIsOverride)
{
- childSetValue("emissive_upload_fee", getString("no_upload_fee_string"));
+ LLUUID new_val = mEmissiveTextureCtrl->getValue().asUUID();
+ if (new_val == mEmissiveTextureUploadId && mEmissiveTextureUploadId.notNull())
+ {
+ childSetValue("emissive_upload_fee", getString("upload_fee_string"));
+ }
+ else
+ {
+ childSetValue("emissive_upload_fee", getString("no_upload_fee_string"));
+ }
}
markChangesUnsaved(MATERIAL_EMISIVE_TEX_DIRTY);
applyToSelection();
@@ -762,14 +803,17 @@ void LLMaterialEditor::onCommitEmissiveTexture(LLUICtrl * ctrl, const LLSD & dat
void LLMaterialEditor::onCommitNormalTexture(LLUICtrl * ctrl, const LLSD & data)
{
- LLUUID new_val = mNormalTextureCtrl->getValue().asUUID();
- if (new_val == mNormalTextureUploadId && mNormalTextureUploadId.notNull())
- {
- childSetValue("normal_upload_fee", getString("upload_fee_string"));
- }
- else
+ if (!mIsOverride)
{
- childSetValue("normal_upload_fee", getString("no_upload_fee_string"));
+ LLUUID new_val = mNormalTextureCtrl->getValue().asUUID();
+ if (new_val == mNormalTextureUploadId && mNormalTextureUploadId.notNull())
+ {
+ childSetValue("normal_upload_fee", getString("upload_fee_string"));
+ }
+ else
+ {
+ childSetValue("normal_upload_fee", getString("no_upload_fee_string"));
+ }
}
markChangesUnsaved(MATERIAL_NORMAL_TEX_DIRTY);
applyToSelection();
@@ -1414,73 +1458,6 @@ void LLMaterialEditor::onCancelMsgCallback(const LLSD& notification, const LLSD&
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option)
{
- if (mIsOverride && !mObjectOverridesSavedValues.empty())
- {
- // Reapply ids back onto selection.
- // TODO: monitor selection changes and resave on selection changes
- struct g : public LLSelectedObjectFunctor
- {
- g(LLMaterialEditor* me) : mEditor(me) {}
- virtual bool apply(LLViewerObject* objectp)
- {
- if (!objectp || !objectp->permModify())
- {
- return false;
- }
-
- U32 local_id = objectp->getLocalID();
- if (mEditor->mObjectOverridesSavedValues.find(local_id) == mEditor->mObjectOverridesSavedValues.end())
- {
- return false;
- }
-
- S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces());
- for (U8 te = 0; te < num_tes; te++)
- {
- if (mEditor->mObjectOverridesSavedValues[local_id].size() > te
- && objectp->getTE(te)->isSelected())
- {
- objectp->setRenderMaterialID(
- te,
- mEditor->mObjectOverridesSavedValues[local_id][te],
- false /*wait for bulk update*/);
- }
- }
- return true;
- }
- LLMaterialEditor* mEditor;
- } restorefunc(this);
- LLSelectMgr::getInstance()->getSelection()->applyToObjects(&restorefunc);
-
- struct f : public LLSelectedObjectFunctor
- {
- virtual bool apply(LLViewerObject* object)
- {
- if (object && !object->permModify())
- {
- return false;
- }
-
- LLRenderMaterialParams* param_block = (LLRenderMaterialParams*)object->getParameterEntry(LLNetworkData::PARAMS_RENDER_MATERIAL);
- if (param_block)
- {
- if (param_block->isEmpty())
- {
- object->setHasRenderMaterialParams(false);
- }
- else
- {
- object->parameterChanged(LLNetworkData::PARAMS_RENDER_MATERIAL, true);
- }
- }
-
- object->sendTEUpdate();
- return true;
- }
- } sendfunc;
- LLSelectMgr::getInstance()->getSelection()->applyToObjects(&sendfunc);
- }
-
closeFloater();
}
}
@@ -1630,46 +1607,11 @@ void LLMaterialEditor::onSelectionChanged()
clearTextures();
setFromSelection();
}
-
- // At the moment all cahges are 'live' so don't reset dirty flags
- // saveLiveValues(); todo
-}
-
-void LLMaterialEditor::saveLiveValues()
-{
- // Collect ids to be able to revert overrides.
- // TODO: monitor selection changes and resave on selection changes
- mObjectOverridesSavedValues.clear();
- struct g : public LLSelectedObjectFunctor
- {
- g(LLMaterialEditor* me) : mEditor(me) {}
- virtual bool apply(LLViewerObject* objectp)
- {
- if (!objectp)
- {
- return false;
- }
-
- U32 local_id = objectp->getLocalID();
- S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces());
- for (U8 te = 0; te < num_tes; te++)
- {
- // Todo: fix this, overrides don't care about ids,
- // we will have to save actual values or materials
- LLUUID mat_id = objectp->getRenderMaterialID(te);
- mEditor->mObjectOverridesSavedValues[local_id].push_back(mat_id);
- }
- return true;
- }
- LLMaterialEditor* mEditor;
- } savefunc(this);
- LLSelectMgr::getInstance()->getSelection()->applyToObjects(&savefunc);
}
void LLMaterialEditor::updateLive()
{
- const LLSD floater_key(LIVE_MATERIAL_EDITOR_KEY);
- LLFloater* instance = LLFloaterReg::findInstance("material_editor", floater_key);
+ LLFloater* instance = LLFloaterReg::findInstance("live_material_editor");
if (instance && LLFloater::isVisible(instance))
{
LLMaterialEditor* me = (LLMaterialEditor*)instance;
@@ -1690,8 +1632,7 @@ void LLMaterialEditor::updateLive(const LLUUID &object_id, S32 te)
// Not an update we are waiting for
return;
}
- const LLSD floater_key(LIVE_MATERIAL_EDITOR_KEY);
- LLFloater* instance = LLFloaterReg::findInstance("material_editor", floater_key);
+ LLFloater* instance = LLFloaterReg::findInstance("live_material_editor");
if (instance && LLFloater::isVisible(instance))
{
LLMaterialEditor* me = (LLMaterialEditor*)instance;
@@ -1706,26 +1647,19 @@ void LLMaterialEditor::updateLive(const LLUUID &object_id, S32 te)
void LLMaterialEditor::loadLive()
{
- // Allow only one 'live' instance
- const LLSD floater_key(LIVE_MATERIAL_EDITOR_KEY);
- LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("material_editor", floater_key);
+ LLMaterialEditor* me = (LLMaterialEditor*)LLFloaterReg::getInstance("live_material_editor");
if (me)
{
me->mOverrideInProgress = false;
me->setFromSelection();
- me->setTitle(me->getString("material_override_title"));
- me->childSetVisible("save", false);
- me->childSetVisible("save_as", false);
// Set up for selection changes updates
if (!me->mSelectionUpdateSlot.connected())
{
me->mSelectionUpdateSlot = LLSelectMgr::instance().mUpdateSignal.connect(boost::bind(&LLMaterialEditor::onSelectionChanged, me));
}
- // Collect ids to be able to revert overrides on cancel.
- me->saveLiveValues();
- me->openFloater(floater_key);
+ me->openFloater();
me->setFocus(TRUE);
}
}
@@ -2226,10 +2160,17 @@ private:
class LLRenderMaterialOverrideFunctor : public LLSelectedTEFunctor
{
public:
- LLRenderMaterialOverrideFunctor(LLMaterialEditor * me, std::string const & url)
- : mEditor(me), mCapUrl(url)
+ LLRenderMaterialOverrideFunctor(
+ LLMaterialEditor * me,
+ std::string const & url,
+ const LLUUID &report_on_object_id,
+ S32 report_on_te)
+ : mEditor(me)
+ , mCapUrl(url)
+ , mSuccess(false)
+ , mObjectId(report_on_object_id)
+ , mObjectTE(report_on_te)
{
-
}
bool apply(LLViewerObject* objectp, S32 te) override
@@ -2262,7 +2203,6 @@ public:
// Override object's values with values from editor where appropriate
if (mEditor->getUnsavedChangesFlags() & MATERIAL_BASE_COLOR_DIRTY)
{
- LLColor4 baseColor = mEditor->getBaseColor();
material->setBaseColorFactor(mEditor->getBaseColor(), true);
}
if (mEditor->getUnsavedChangesFlags() & MATERIAL_BASE_COLOR_TEX_DIRTY)
@@ -2324,7 +2264,17 @@ public:
"side", te,
"gltf_json", overrides_json
);
- LLCoros::instance().launch("modifyMaterialCoro", std::bind(&LLGLTFMaterialList::modifyMaterialCoro, mCapUrl, overrides, modifyCallback));
+
+ void(*done_callback)(bool) = nullptr;
+ if (mObjectTE == te
+ && mObjectId == objectp->getID())
+ {
+ mSuccess = true;
+ // We only want callback for face we are displayig material from
+ // even if we are setting all of them
+ done_callback = modifyCallback;
+ }
+ LLCoros::instance().launch("modifyMaterialCoro", std::bind(&LLGLTFMaterialList::modifyMaterialCoro, mCapUrl, overrides, done_callback));
}
return true;
}
@@ -2336,12 +2286,17 @@ public:
// something went wrong update selection
LLMaterialEditor::updateLive();
}
- // else we will get updateLive(obj, id) from aplied overrides
+ // else we will get updateLive(obj, id) from applied overrides
}
+ bool getResult() { return mSuccess; }
+
private:
LLMaterialEditor * mEditor;
std::string mCapUrl;
+ LLUUID mObjectId;
+ S32 mObjectTE;
+ bool mSuccess;
};
void LLMaterialEditor::applyToSelection()
@@ -2365,9 +2320,11 @@ void LLMaterialEditor::applyToSelection()
{
mOverrideInProgress = true;
LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection();
- LLRenderMaterialOverrideFunctor override_func(this, url);
- if (!selected_objects->applyToTEs(&override_func))
+ LLRenderMaterialOverrideFunctor override_func(this, url, mOverrideObjectId, mOverrideObjectTE);
+ selected_objects->applyToTEs(&override_func);
+ if (!override_func.getResult())
{
+ // OverrideFunctor didn't find expected object or face
mOverrideInProgress = false;
}
diff --git a/indra/newview/llmaterialeditor.h b/indra/newview/llmaterialeditor.h
index 49f3baf0c7..0ffad5f54a 100644
--- a/indra/newview/llmaterialeditor.h
+++ b/indra/newview/llmaterialeditor.h
@@ -104,7 +104,6 @@ public:
static void loadMaterialFromFile(const std::string& filename, S32 index = -1);
void onSelectionChanged(); // live overrides selection changes
- void saveLiveValues(); // for restoration on cancel
static void updateLive();
static void updateLive(const LLUUID &object_id, S32 te);
@@ -293,7 +292,6 @@ private:
// for "cancel" support
static LLUUID mOverrideObjectId; // static to avoid searching for the floater
static S32 mOverrideObjectTE;
- std::map<U32, uuid_vec_t> mObjectOverridesSavedValues;
boost::signals2::connection mSelectionUpdateSlot;
};
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index f884cfe842..04957729ed 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -2658,11 +2658,11 @@ void LLPanelFace::updateVisibility()
{
updateShinyControls();
}
- getChildView("shinyScaleU")->setVisible(show_shininess || show_pbr_normal);
- getChildView("shinyScaleV")->setVisible(show_shininess || show_pbr_normal);
- getChildView("shinyRot")->setVisible(show_shininess || show_pbr_normal);
- getChildView("shinyOffsetU")->setVisible(show_shininess || show_pbr_normal);
- getChildView("shinyOffsetV")->setVisible(show_shininess || show_pbr_normal);
+ getChildView("shinyScaleU")->setVisible(show_shininess || show_pbr_metallic);
+ getChildView("shinyScaleV")->setVisible(show_shininess || show_pbr_metallic);
+ getChildView("shinyRot")->setVisible(show_shininess || show_pbr_metallic);
+ getChildView("shinyOffsetU")->setVisible(show_shininess || show_pbr_metallic);
+ getChildView("shinyOffsetV")->setVisible(show_shininess || show_pbr_metallic);
// Normal map controls
if (show_bumpiness)
@@ -2672,11 +2672,11 @@ void LLPanelFace::updateVisibility()
getChildView("bumpytexture control")->setVisible(show_bumpiness);
getChildView("combobox bumpiness")->setVisible(show_bumpiness);
getChildView("label bumpiness")->setVisible(show_bumpiness);
- getChildView("bumpyScaleU")->setVisible(show_bumpiness || show_pbr_metallic);
- getChildView("bumpyScaleV")->setVisible(show_bumpiness || show_pbr_metallic);
- getChildView("bumpyRot")->setVisible(show_bumpiness || show_pbr_metallic);
- getChildView("bumpyOffsetU")->setVisible(show_bumpiness || show_pbr_metallic);
- getChildView("bumpyOffsetV")->setVisible(show_bumpiness || show_pbr_metallic);
+ getChildView("bumpyScaleU")->setVisible(show_bumpiness || show_pbr_normal);
+ getChildView("bumpyScaleV")->setVisible(show_bumpiness || show_pbr_normal);
+ getChildView("bumpyRot")->setVisible(show_bumpiness || show_pbr_normal);
+ getChildView("bumpyOffsetU")->setVisible(show_bumpiness || show_pbr_normal);
+ getChildView("bumpyOffsetV")->setVisible(show_bumpiness || show_pbr_normal);
// PBR controls
getChildView("pbr_control")->setVisible(show_pbr);
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index f5ccc238c0..962e3e2cf0 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -337,6 +337,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("script_colors", "floater_script_ed_prefs.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptEdPrefs>);
LLFloaterReg::add("material_editor", "floater_material_editor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLMaterialEditor>);
+ LLFloaterReg::add("live_material_editor", "floater_live_material_editor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLMaterialEditor>);
LLFloaterReg::add("telehubs", "floater_telehub.xml",&LLFloaterReg::build<LLFloaterTelehub>);
LLFloaterReg::add("test_inspectors", "floater_test_inspectors.xml", &LLFloaterReg::build<LLFloaterTestInspectors>);
diff --git a/indra/newview/skins/default/xui/en/floater_live_material_editor.xml b/indra/newview/skins/default/xui/en/floater_live_material_editor.xml
new file mode 100644
index 0000000000..317783f794
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_live_material_editor.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ default_tab_group="1"
+ height="786"
+ width="256"
+ min_height="500"
+ min_width="256"
+ layout="topleft"
+ name="material editor"
+ help_topic="material_editor"
+ single_instance="true"
+ title="Editing Material">
+ <scroll_container
+ name="materials_scroll"
+ top="14"
+ left="4"
+ height="768"
+ width="247"
+ follows="all"
+ layout="topleft"
+ color="DkGray2"
+ opaque="true"
+ reserve_scroll_corner="false">
+ <panel
+ name="panel_material"
+ filename="panel_gltf_material.xml"
+ border="false"
+ visible="true"
+ layout="topleft"
+ top="0"
+ left="0"
+ height="768"
+ width="247" />
+ </scroll_container>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_material_editor.xml b/indra/newview/skins/default/xui/en/floater_material_editor.xml
index 84264cd2e6..29def9bd53 100644
--- a/indra/newview/skins/default/xui/en/floater_material_editor.xml
+++ b/indra/newview/skins/default/xui/en/floater_material_editor.xml
@@ -27,430 +27,17 @@
layout="topleft"
color="DkGray2"
opaque="true"
- reserve_scroll_corner="false"
- >
+ reserve_scroll_corner="false">
<panel
- border="false"
- name="scroll_panel"
- top="0"
- left="0"
- height="768"
- width="247"
- >
- <check_box
- follows="left|top"
- label="Double Sided"
- left="10"
- top="0"
- name="double sided"
- height="25"
- width="120" />
- <panel
- border="true"
- follows="left|top"
- width="246"
- height="196"
- layout="topleft"
- left="1"
- mouse_opaque="false"
- name="base_color_texture_pnl"
- top_pad="5"
- >
- <text
- type="string"
- font.style="BOLD"
- length="1"
- follows="left|top"
- height="10"
- layout="topleft"
- left="10"
- top="5"
- width="128">
- Base Color:
- </text>
- <texture_picker
- can_apply_immediately="true"
- default_image_name="Default"
- fallback_image="materials_ui_x_24.png"
- allow_no_texture="true"
- follows="left|top"
- top_pad="8"
- height="151"
- layout="topleft"
- left="10"
- name="base_color_texture"
- tool_tip="Base Color map. Alpha channel is optional and used for transparency."
- width="128" />
- <text
- type="string"
- font.style="BOLD"
- length="1"
- follows="left|top"
- height="10"
- width="128"
- layout="topleft"
- left="10"
- top_pad="-17"
- name="base_color_upload_fee"
- >
- No upload fee
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="10"
- layout="topleft"
- left_pad="5"
- top="8"
- >
- Tint
- </text>
- <color_swatch
- can_apply_immediately="true"
- follows="left|top"
- height="40"
- label_height="0"
- layout="topleft"
- left_delta="0"
- top_pad="5"
- name="base color"
- width="40" />
- <text
- type="string"
- length="1"
- follows="left|top"
- height="10"
- layout="topleft"
- left_delta="0"
- top_pad="5"
- width="96"
- >
- Transparency
- </text>
- <spinner
- decimal_digits="3"
- follows="left|top"
- height="19"
- increment="0.01"
- initial_value="1"
- layout="topleft"
- left_delta="0"
- top_pad="5"
- min_val="0"
- max_val="1"
- name="transparency"
- width="64"
- />
- <text
- type="string"
- length="1"
- follows="left|top"
- height="10"
- layout="topleft"
- left_delta="0"
- name="label alphamode"
- text_readonly_color="LabelDisabledColor"
- top_pad="5"
- width="90">
- Alpha mode
- </text>
- <combo_box
- height="23"
- layout="topleft"
- left_delta="0"
- name="alpha mode"
- top_pad="4"
- width="96">
- <combo_box.item
- label="None"
- name="None"
- value="OPAQUE" />
- <combo_box.item
- label="Alpha blending"
- name="Alpha blending"
- value="BLEND" />
- <combo_box.item
- label="Alpha masking"
- name="Alpha masking"
- value="MASK" />
- </combo_box>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="10"
- layout="topleft"
- left_delta="0"
- top_pad="5"
- width="96"
- >
- Alpha Cutoff
- </text>
- <spinner
- decimal_digits="3"
- follows="left|top"
- height="19"
- increment="0.01"
- initial_value="1"
- layout="topleft"
- left_delta="0"
- top_pad="5"
- min_val="0"
- max_val="1"
- name="alpha cutoff"
- width="64"
- />
- </panel>
- <panel
- border="true"
- follows="left|top"
- width="246"
- height="175"
- layout="topleft"
- left="1"
- mouse_opaque="false"
- name="metallic_texture_pnl"
- top_pad="5"
- >
- <text
- type="string"
- font.style="BOLD"
- length="1"
- follows="left|top"
- height="10"
- layout="topleft"
- left="10"
- top="5"
- >
- Metallic-Roughness:
- </text>
- <texture_picker
- can_apply_immediately="true"
- default_image_name="Default"
- fallback_image="materials_ui_x_24.png"
- allow_no_texture="true"
- follows="left|top"
- width="128"
- height="151"
- layout="topleft"
- left="10"
- name="metallic_roughness_texture"
- tool_tip="GLTF metallic-roughness map with optional occlusion. Red channel is occlusion, green channel is roughness, blue channel is metalness."
- top_pad="8"
- />
- <text
- type="string"
- font.style="BOLD"
- length="1"
- follows="left|top"
- height="10"
- width="128"
- layout="topleft"
- left="10"
- top_pad="-17"
- name="metallic_upload_fee"
- >
- No upload fee
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="10"
- layout="topleft"
- left_pad="5"
- top="8"
- >
- Metallic Factor
- </text>
- <spinner
- decimal_digits="3"
- follows="left|top"
- height="19"
- increment="0.01"
- initial_value="0"
- layout="topleft"
- left_delta="0"
- top_pad="5"
- min_val="0"
- max_val="1"
- name="metalness factor"
- width="64"
- />
- <text
- type="string"
- length="1"
- follows="left|top"
- height="10"
- layout="topleft"
- left_delta="0"
- top_pad="5"
- width="96"
- >
- Roughness Factor
- </text>
- <spinner
- decimal_digits="3"
- follows="left|top"
- height="19"
- increment="0.01"
- initial_value="0"
- layout="topleft"
- left_delta="0"
- top_pad="5"
- min_val="0"
- max_val="1"
- name="roughness factor"
- width="64"
- />
- </panel>
- <panel
- border="true"
- follows="left|top"
- width="246"
- height="175"
- layout="topleft"
- left="1"
- mouse_opaque="false"
- name="emissive_texture_pnl"
- top_pad="5"
- >
- <text
- type="string"
- font.style="BOLD"
- length="1"
- follows="left|top"
- height="10"
- layout="topleft"
- left="10"
- top="5"
- width="64">
- Emissive:
- </text>
- <texture_picker
- can_apply_immediately="true"
- default_image_name="Default"
- fallback_image="materials_ui_x_24.png"
- allow_no_texture="true"
- follows="left|top"
- top_pad="8"
- height="151"
- layout="topleft"
- left="10"
- name="emissive_texture"
- width="128" />
- <text
- type="string"
- font.style="BOLD"
- length="1"
- follows="left|top"
- height="10"
- width="128"
- layout="topleft"
- left="10"
- top_pad="-17"
- name="emissive_upload_fee"
- >
- No upload fee
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="10"
- layout="topleft"
- left_pad="5"
- top="8"
- >
- Tint
- </text>
- <color_swatch
- can_apply_immediately="true"
- follows="left|top"
- height="40"
- label_height="0"
- layout="topleft"
- left_delta="0"
- top_pad="5"
- name="emissive color"
- width="40" />
- <!--<text
- type="string"
- length="1"
- follows="left|top"
- height="10"
- width="64"
- layout="topleft"
- left_delta="0"
- top_pad="5"
- >
- Intensity
- </text>
- <spinner
- decimal_digits="3"
- follows="left|top"
- height="19"
- increment="0.01"
- initial_value="0"
- layout="topleft"
- left_delta="0"
- top_pad="5"
- max_val="100"
- width="64"
- />-->
- </panel>
- <panel
- border="true"
- follows="left|top"
- width="246"
- height="175"
- layout="topleft"
- left="1"
- mouse_opaque="false"
- top_pad="5"
- name="normal_texture_pnl"
- >
- <text
- type="string"
- font.style="BOLD"
- length="1"
- follows="left|top"
- height="10"
- layout="topleft"
- left="10"
- top="5"
- width="64">
- Normal:
- </text>
- <texture_picker
- can_apply_immediately="true"
- default_image_name="Default"
- fallback_image="materials_ui_x_24.png"
- allow_no_texture="true"
- follows="left|top"
- top_pad="8"
- height="151"
- layout="topleft"
- left="10"
- name="normal_texture"
- width="128" />
- <text
- type="string"
- font.style="BOLD"
- length="1"
- follows="left|top"
- height="10"
- width="128"
- layout="topleft"
- left="10"
- top_pad="-17"
- name="normal_upload_fee"
- >
- No upload fee
- </text>
- </panel>
- </panel>
+ name="panel_material"
+ filename="panel_gltf_material.xml"
+ border="false"
+ visible="true"
+ layout="topleft"
+ top="0"
+ left="0"
+ height="768"
+ width="247" />
</scroll_container>
<panel
diff --git a/indra/newview/skins/default/xui/en/panel_gltf_material.xml b/indra/newview/skins/default/xui/en/panel_gltf_material.xml
new file mode 100644
index 0000000000..f4060648b9
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_gltf_material.xml
@@ -0,0 +1,382 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ layout="topleft"
+ follows="all"
+ border="false"
+ name="panel_gltf_material"
+ top="0"
+ left="0"
+ height="768"
+ width="247">
+ <check_box
+ follows="left|top"
+ layout="topleft"
+ label="Double Sided"
+ left="10"
+ top="0"
+ name="double sided"
+ height="25"
+ width="120" />
+ <panel
+ border="true"
+ follows="left|top"
+ width="246"
+ height="196"
+ layout="topleft"
+ left="1"
+ mouse_opaque="false"
+ name="base_color_texture_pnl"
+ top_pad="5"
+ >
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ top="5"
+ width="128">
+ Base Color:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ fallback_image="materials_ui_x_24.png"
+ allow_no_texture="true"
+ follows="left|top"
+ top_pad="8"
+ height="151"
+ layout="topleft"
+ left="10"
+ name="base_color_texture"
+ tool_tip="Base Color map. Alpha channel is optional and used for transparency."
+ width="128" />
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ width="128"
+ layout="topleft"
+ left="10"
+ top_pad="-17"
+ name="base_color_upload_fee">
+ No upload fee
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="5"
+ top="8">
+ Tint
+ </text>
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="40"
+ label_height="0"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ name="base color"
+ width="40" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ width="96">
+ Transparency
+ </text>
+ <spinner
+ decimal_digits="3"
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="1"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ min_val="0"
+ max_val="1"
+ name="transparency"
+ width="64"/>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ name="label alphamode"
+ text_readonly_color="LabelDisabledColor"
+ top_pad="5"
+ width="90">
+ Alpha mode
+ </text>
+ <combo_box
+ height="23"
+ layout="topleft"
+ left_delta="0"
+ name="alpha mode"
+ top_pad="4"
+ width="96">
+ <combo_box.item
+ label="Opaque"
+ name="None"
+ value="OPAQUE" />
+ <combo_box.item
+ label="Blend"
+ name="Alpha blending"
+ value="BLEND" />
+ <combo_box.item
+ label="Mask"
+ name="Alpha masking"
+ value="MASK" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ width="96">
+ Alpha Cutoff
+ </text>
+ <spinner
+ decimal_digits="3"
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="1"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ min_val="0"
+ max_val="1"
+ name="alpha cutoff"
+ width="64"/>
+ </panel>
+ <panel
+ border="true"
+ follows="left|top"
+ width="246"
+ height="175"
+ layout="topleft"
+ left="1"
+ mouse_opaque="false"
+ name="metallic_texture_pnl"
+ top_pad="5">
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ top="5">
+ Metallic-Roughness:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ fallback_image="materials_ui_x_24.png"
+ allow_no_texture="true"
+ follows="left|top"
+ width="128"
+ height="151"
+ layout="topleft"
+ left="10"
+ name="metallic_roughness_texture"
+ tool_tip="GLTF metallic-roughness map with optional occlusion. Red channel is occlusion, green channel is roughness, blue channel is metalness."
+ top_pad="8"/>
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ width="128"
+ layout="topleft"
+ left="10"
+ top_pad="-17"
+ name="metallic_upload_fee">
+ No upload fee
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="5"
+ top="8">
+ Metallic Factor
+ </text>
+ <spinner
+ decimal_digits="3"
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ min_val="0"
+ max_val="1"
+ name="metalness factor"
+ width="64"/>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ width="96">
+ Roughness Factor
+ </text>
+ <spinner
+ decimal_digits="3"
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ min_val="0"
+ max_val="1"
+ name="roughness factor"
+ width="64"/>
+ </panel>
+ <panel
+ border="true"
+ follows="left|top"
+ width="246"
+ height="175"
+ layout="topleft"
+ left="1"
+ mouse_opaque="false"
+ name="emissive_texture_pnl"
+ top_pad="5">
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ top="5"
+ width="64">
+ Emissive:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ fallback_image="materials_ui_x_24.png"
+ allow_no_texture="true"
+ follows="left|top"
+ top_pad="8"
+ height="151"
+ layout="topleft"
+ left="10"
+ name="emissive_texture"
+ width="128" />
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ width="128"
+ layout="topleft"
+ left="10"
+ top_pad="-17"
+ name="emissive_upload_fee">
+ No upload fee
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="5"
+ top="8">
+ Tint
+ </text>
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="40"
+ label_height="0"
+ layout="topleft"
+ left_delta="0"
+ top_pad="5"
+ name="emissive color"
+ width="40" />
+ </panel>
+ <panel
+ border="true"
+ follows="left|top"
+ width="246"
+ height="175"
+ layout="topleft"
+ left="1"
+ mouse_opaque="false"
+ top_pad="5"
+ name="normal_texture_pnl">
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ top="5"
+ width="64">
+ Normal:
+ </text>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ fallback_image="materials_ui_x_24.png"
+ allow_no_texture="true"
+ follows="left|top"
+ top_pad="8"
+ height="151"
+ layout="topleft"
+ left="10"
+ name="normal_texture"
+ width="128" />
+ <text
+ type="string"
+ font.style="BOLD"
+ length="1"
+ follows="left|top"
+ height="10"
+ width="128"
+ layout="topleft"
+ left="10"
+ top_pad="-17"
+ name="normal_upload_fee">
+ No upload fee
+ </text>
+ </panel>
+</panel>