summaryrefslogtreecommitdiff
path: root/indra/newview/llpanelface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llpanelface.cpp')
-rw-r--r--indra/newview/llpanelface.cpp10996
1 files changed, 5498 insertions, 5498 deletions
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 9761c6ae10..4d5fed9e70 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -1,5498 +1,5498 @@
-/**
- * @file llpanelface.cpp
- * @brief Panel in the tools floater for editing face textures, colors, etc.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-// file include
-#include "llpanelface.h"
-
-// library includes
-#include "llcalc.h"
-#include "llerror.h"
-#include "llrect.h"
-#include "llstring.h"
-#include "llfontgl.h"
-
-// project includes
-#include "llagent.h"
-#include "llagentdata.h"
-#include "llbutton.h"
-#include "llcheckboxctrl.h"
-#include "llcolorswatch.h"
-#include "llcombobox.h"
-#include "lldrawpoolbump.h"
-#include "llface.h"
-#include "llgltfmateriallist.h"
-#include "llinventoryfunctions.h"
-#include "llinventorymodel.h" // gInventory
-#include "llinventorymodelbackgroundfetch.h"
-#include "llfloatermediasettings.h"
-#include "llfloaterreg.h"
-#include "llfloatertools.h"
-#include "lllineeditor.h"
-#include "llmaterialmgr.h"
-#include "llmaterialeditor.h"
-#include "llmediactrl.h"
-#include "llmediaentry.h"
-#include "llmenubutton.h"
-#include "llnotificationsutil.h"
-#include "llpanelcontents.h"
-#include "llradiogroup.h"
-#include "llresmgr.h"
-#include "llselectmgr.h"
-#include "llspinctrl.h"
-#include "lltextbox.h"
-#include "lltexturectrl.h"
-#include "lltextureentry.h"
-#include "lltooldraganddrop.h"
-#include "lltoolface.h"
-#include "lltoolmgr.h"
-#include "lltrans.h"
-#include "llui.h"
-#include "llviewercontrol.h"
-#include "llviewermedia.h"
-#include "llviewerobject.h"
-#include "llviewerregion.h"
-#include "llviewerstats.h"
-#include "llvovolume.h"
-#include "llvoinventorylistener.h"
-#include "lluictrlfactory.h"
-#include "llpluginclassmedia.h"
-#include "llviewertexturelist.h"// Update sel manager as to which channel we're editing so it can reflect the correct overlay UI
-
-
-
-#include "llagent.h"
-#include "llfilesystem.h"
-#include "llviewerassetupload.h"
-#include "llviewermenufile.h"
-#include "llsd.h"
-#include "llsdutil.h"
-#include "llsdserialize.h"
-#include "llinventorymodel.h"
-
-using namespace std::literals;
-
-LLPanelFace::Selection LLPanelFace::sMaterialOverrideSelection;
-
-//
-// Constant definitions for comboboxes
-// Must match the commbobox definitions in panel_tools_texture.xml
-//
-const S32 MATMEDIA_MATERIAL = 0; // Material
-const S32 MATMEDIA_PBR = 1; // PBR
-const S32 MATMEDIA_MEDIA = 2; // Media
-const S32 MATTYPE_DIFFUSE = 0; // Diffuse material texture
-const S32 MATTYPE_NORMAL = 1; // Normal map
-const S32 MATTYPE_SPECULAR = 2; // Specular map
-const S32 ALPHAMODE_MASK = 2; // Alpha masking mode
-const S32 BUMPY_TEXTURE = 18; // use supplied normal map
-const S32 SHINY_TEXTURE = 4; // use supplied specular map
-const S32 PBRTYPE_RENDER_MATERIAL_ID = 0; // Render Material ID
-const S32 PBRTYPE_BASE_COLOR = 1; // PBR Base Color
-const S32 PBRTYPE_METALLIC_ROUGHNESS = 2; // PBR Metallic
-const S32 PBRTYPE_EMISSIVE = 3; // PBR Emissive
-const S32 PBRTYPE_NORMAL = 4; // PBR Normal
-
-LLGLTFMaterial::TextureInfo texture_info_from_pbrtype(S32 pbr_type)
-{
- switch (pbr_type)
- {
- case PBRTYPE_BASE_COLOR:
- return LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR;
- break;
- case PBRTYPE_NORMAL:
- return LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL;
- break;
- case PBRTYPE_METALLIC_ROUGHNESS:
- return LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS;
- break;
- case PBRTYPE_EMISSIVE:
- return LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE;
- break;
- default:
- return LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT;
- break;
- }
-}
-
-void LLPanelFace::updateSelectedGLTFMaterials(std::function<void(LLGLTFMaterial*)> func)
-{
- struct LLSelectedTEGLTFMaterialFunctor : public LLSelectedTEFunctor
- {
- LLSelectedTEGLTFMaterialFunctor(std::function<void(LLGLTFMaterial*)> func) : mFunc(func) {}
- virtual ~LLSelectedTEGLTFMaterialFunctor() {};
- bool apply(LLViewerObject* object, S32 face) override
- {
- LLGLTFMaterial new_override;
- const LLTextureEntry* tep = object->getTE(face);
- if (tep->getGLTFMaterialOverride())
- {
- new_override = *tep->getGLTFMaterialOverride();
- }
- mFunc(&new_override);
- LLGLTFMaterialList::queueModify(object, face, &new_override);
-
- return true;
- }
-
- std::function<void(LLGLTFMaterial*)> mFunc;
- } select_func(func);
-
- LLSelectMgr::getInstance()->getSelection()->applyToTEs(&select_func);
-}
-
-template<typename T>
-void readSelectedGLTFMaterial(std::function<T(const LLGLTFMaterial*)> func, T& value, bool& identical, bool has_tolerance, T tolerance)
-{
- struct LLSelectedTEGetGLTFMaterialFunctor : public LLSelectedTEGetFunctor<T>
- {
- LLSelectedTEGetGLTFMaterialFunctor(std::function<T(const LLGLTFMaterial*)> func) : mFunc(func) {}
- virtual ~LLSelectedTEGetGLTFMaterialFunctor() {};
- T get(LLViewerObject* object, S32 face) override
- {
- const LLTextureEntry* tep = object->getTE(face);
- const LLGLTFMaterial* render_material = tep->getGLTFRenderMaterial();
-
- return mFunc(render_material);
- }
-
- std::function<T(const LLGLTFMaterial*)> mFunc;
- } select_func(func);
- identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&select_func, value, has_tolerance, tolerance);
-}
-
-BOOST_STATIC_ASSERT(MATTYPE_DIFFUSE == LLRender::DIFFUSE_MAP && MATTYPE_NORMAL == LLRender::NORMAL_MAP && MATTYPE_SPECULAR == LLRender::SPECULAR_MAP);
-
-//
-// "Use texture" label for normal/specular type comboboxes
-// Filled in at initialization from translated strings
-//
-std::string USE_TEXTURE;
-
-LLRender::eTexIndex LLPanelFace::getTextureChannelToEdit()
-{
- LLRender::eTexIndex channel_to_edit = LLRender::DIFFUSE_MAP;
- if (mComboMatMedia)
- {
- U32 matmedia_selection = mComboMatMedia->getCurrentIndex();
- if (matmedia_selection == MATMEDIA_MATERIAL)
- {
- LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type");
- channel_to_edit = (LLRender::eTexIndex)radio_mat_type->getSelectedIndex();
- }
- if (matmedia_selection == MATMEDIA_PBR)
- {
- LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_pbr_type");
- channel_to_edit = (LLRender::eTexIndex)radio_mat_type->getSelectedIndex();
- }
- }
-
- channel_to_edit = (channel_to_edit == LLRender::NORMAL_MAP) ? (getCurrentNormalMap().isNull() ? LLRender::DIFFUSE_MAP : channel_to_edit) : channel_to_edit;
- channel_to_edit = (channel_to_edit == LLRender::SPECULAR_MAP) ? (getCurrentSpecularMap().isNull() ? LLRender::DIFFUSE_MAP : channel_to_edit) : channel_to_edit;
- return channel_to_edit;
-}
-
-LLRender::eTexIndex LLPanelFace::getTextureDropChannel()
-{
- if (mComboMatMedia && mComboMatMedia->getCurrentIndex() == MATMEDIA_MATERIAL)
- {
- LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type");
- return LLRender::eTexIndex(radio_mat_type->getSelectedIndex());
- }
-
- return LLRender::eTexIndex(MATTYPE_DIFFUSE);
-}
-
-LLGLTFMaterial::TextureInfo LLPanelFace::getPBRDropChannel()
-{
- if (mComboMatMedia && mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR)
- {
- LLRadioGroup* radio_pbr_type = getChild<LLRadioGroup>("radio_pbr_type");
- return texture_info_from_pbrtype(radio_pbr_type->getSelectedIndex());
- }
-
- return texture_info_from_pbrtype(PBRTYPE_BASE_COLOR);
-}
-
-// Things the UI provides...
-//
-LLUUID LLPanelFace::getCurrentNormalMap() { return getChild<LLTextureCtrl>("bumpytexture control")->getImageAssetID(); }
-LLUUID LLPanelFace::getCurrentSpecularMap() { return getChild<LLTextureCtrl>("shinytexture control")->getImageAssetID(); }
-U32 LLPanelFace::getCurrentShininess() { return getChild<LLComboBox>("combobox shininess")->getCurrentIndex(); }
-U32 LLPanelFace::getCurrentBumpiness() { return getChild<LLComboBox>("combobox bumpiness")->getCurrentIndex(); }
-U8 LLPanelFace::getCurrentDiffuseAlphaMode() { return (U8)getChild<LLComboBox>("combobox alphamode")->getCurrentIndex(); }
-U8 LLPanelFace::getCurrentAlphaMaskCutoff() { return (U8)getChild<LLUICtrl>("maskcutoff")->getValue().asInteger(); }
-U8 LLPanelFace::getCurrentEnvIntensity() { return (U8)getChild<LLUICtrl>("environment")->getValue().asInteger(); }
-U8 LLPanelFace::getCurrentGlossiness() { return (U8)getChild<LLUICtrl>("glossiness")->getValue().asInteger(); }
-F32 LLPanelFace::getCurrentBumpyRot() { return getChild<LLUICtrl>("bumpyRot")->getValue().asReal(); }
-F32 LLPanelFace::getCurrentBumpyScaleU() { return getChild<LLUICtrl>("bumpyScaleU")->getValue().asReal(); }
-F32 LLPanelFace::getCurrentBumpyScaleV() { return getChild<LLUICtrl>("bumpyScaleV")->getValue().asReal(); }
-F32 LLPanelFace::getCurrentBumpyOffsetU() { return getChild<LLUICtrl>("bumpyOffsetU")->getValue().asReal(); }
-F32 LLPanelFace::getCurrentBumpyOffsetV() { return getChild<LLUICtrl>("bumpyOffsetV")->getValue().asReal(); }
-F32 LLPanelFace::getCurrentShinyRot() { return getChild<LLUICtrl>("shinyRot")->getValue().asReal(); }
-F32 LLPanelFace::getCurrentShinyScaleU() { return getChild<LLUICtrl>("shinyScaleU")->getValue().asReal(); }
-F32 LLPanelFace::getCurrentShinyScaleV() { return getChild<LLUICtrl>("shinyScaleV")->getValue().asReal(); }
-F32 LLPanelFace::getCurrentShinyOffsetU() { return getChild<LLUICtrl>("shinyOffsetU")->getValue().asReal(); }
-F32 LLPanelFace::getCurrentShinyOffsetV() { return getChild<LLUICtrl>("shinyOffsetV")->getValue().asReal(); }
-
-//
-// Methods
-//
-
-BOOL LLPanelFace::postBuild()
-{
- childSetCommitCallback("combobox shininess",&LLPanelFace::onCommitShiny,this);
- childSetCommitCallback("combobox bumpiness",&LLPanelFace::onCommitBump,this);
- childSetCommitCallback("combobox alphamode",&LLPanelFace::onCommitAlphaMode,this);
- childSetCommitCallback("TexScaleU",&LLPanelFace::onCommitTextureScaleX, this);
- childSetCommitCallback("TexScaleV",&LLPanelFace::onCommitTextureScaleY, this);
- childSetCommitCallback("TexRot",&LLPanelFace::onCommitTextureRot, this);
- childSetCommitCallback("rptctrl",&LLPanelFace::onCommitRepeatsPerMeter, this);
- childSetCommitCallback("checkbox planar align",&LLPanelFace::onCommitPlanarAlign, this);
- childSetCommitCallback("TexOffsetU",LLPanelFace::onCommitTextureOffsetX, this);
- childSetCommitCallback("TexOffsetV",LLPanelFace::onCommitTextureOffsetY, this);
-
- childSetCommitCallback("bumpyScaleU",&LLPanelFace::onCommitMaterialBumpyScaleX, this);
- childSetCommitCallback("bumpyScaleV",&LLPanelFace::onCommitMaterialBumpyScaleY, this);
- childSetCommitCallback("bumpyRot",&LLPanelFace::onCommitMaterialBumpyRot, this);
- childSetCommitCallback("bumpyOffsetU",&LLPanelFace::onCommitMaterialBumpyOffsetX, this);
- childSetCommitCallback("bumpyOffsetV",&LLPanelFace::onCommitMaterialBumpyOffsetY, this);
- childSetCommitCallback("shinyScaleU",&LLPanelFace::onCommitMaterialShinyScaleX, this);
- childSetCommitCallback("shinyScaleV",&LLPanelFace::onCommitMaterialShinyScaleY, this);
- childSetCommitCallback("shinyRot",&LLPanelFace::onCommitMaterialShinyRot, this);
- childSetCommitCallback("shinyOffsetU",&LLPanelFace::onCommitMaterialShinyOffsetX, this);
- childSetCommitCallback("shinyOffsetV",&LLPanelFace::onCommitMaterialShinyOffsetY, this);
- childSetCommitCallback("glossiness",&LLPanelFace::onCommitMaterialGloss, this);
- childSetCommitCallback("environment",&LLPanelFace::onCommitMaterialEnv, this);
- childSetCommitCallback("maskcutoff",&LLPanelFace::onCommitMaterialMaskCutoff, this);
- childSetCommitCallback("add_media", &LLPanelFace::onClickBtnAddMedia, this);
- childSetCommitCallback("delete_media", &LLPanelFace::onClickBtnDeleteMedia, this);
-
- getChild<LLUICtrl>("gltfTextureScaleU")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFTextureScaleU, this, _1), nullptr);
- getChild<LLUICtrl>("gltfTextureScaleV")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFTextureScaleV, this, _1), nullptr);
- getChild<LLUICtrl>("gltfTextureRotation")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFRotation, this, _1), nullptr);
- getChild<LLUICtrl>("gltfTextureOffsetU")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFTextureOffsetU, this, _1), nullptr);
- getChild<LLUICtrl>("gltfTextureOffsetV")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFTextureOffsetV, this, _1), nullptr);
-
- LLGLTFMaterialList::addSelectionUpdateCallback(&LLPanelFace::onMaterialOverrideReceived);
- sMaterialOverrideSelection.connect();
-
- childSetAction("button align",&LLPanelFace::onClickAutoFix,this);
- childSetAction("button align textures", &LLPanelFace::onAlignTexture, this);
- childSetAction("pbr_from_inventory", &LLPanelFace::onClickBtnLoadInvPBR, this);
- childSetAction("edit_selected_pbr", &LLPanelFace::onClickBtnEditPBR, this);
- childSetAction("save_selected_pbr", &LLPanelFace::onClickBtnSavePBR, this);
-
- LLTextureCtrl* mTextureCtrl;
- LLTextureCtrl* mShinyTextureCtrl;
- LLTextureCtrl* mBumpyTextureCtrl;
- LLColorSwatchCtrl* mColorSwatch;
- LLColorSwatchCtrl* mShinyColorSwatch;
-
- LLComboBox* mComboTexGen;
-
- LLCheckBoxCtrl *mCheckFullbright;
-
- LLTextBox* mLabelColorTransp;
- LLSpinCtrl* mCtrlColorTransp; // transparency = 1 - alpha
-
- LLSpinCtrl* mCtrlGlow;
-
- setMouseOpaque(FALSE);
-
- LLTextureCtrl* pbr_ctrl = findChild<LLTextureCtrl>("pbr_control");
- if (pbr_ctrl)
- {
- pbr_ctrl->setDefaultImageAssetID(LLUUID::null);
- pbr_ctrl->setBlankImageAssetID(LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID);
- pbr_ctrl->setCommitCallback(boost::bind(&LLPanelFace::onCommitPbr, this, _2));
- pbr_ctrl->setOnCancelCallback(boost::bind(&LLPanelFace::onCancelPbr, this, _2));
- pbr_ctrl->setOnSelectCallback(boost::bind(&LLPanelFace::onSelectPbr, this, _2));
- pbr_ctrl->setDragCallback(boost::bind(&LLPanelFace::onDragPbr, this, _2));
- pbr_ctrl->setOnTextureSelectedCallback(boost::bind(&LLPanelFace::onPbrSelectionChanged, this, _1));
- pbr_ctrl->setOnCloseCallback(boost::bind(&LLPanelFace::onCloseTexturePicker, this, _2));
-
- pbr_ctrl->setFollowsTop();
- pbr_ctrl->setFollowsLeft();
- pbr_ctrl->setImmediateFilterPermMask(PERM_NONE);
- pbr_ctrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER);
- pbr_ctrl->setBakeTextureEnabled(false);
- pbr_ctrl->setInventoryPickType(PICK_MATERIAL);
- }
-
- mTextureCtrl = getChild<LLTextureCtrl>("texture control");
- if(mTextureCtrl)
- {
- mTextureCtrl->setDefaultImageAssetID(DEFAULT_OBJECT_TEXTURE);
- mTextureCtrl->setCommitCallback( boost::bind(&LLPanelFace::onCommitTexture, this, _2) );
- mTextureCtrl->setOnCancelCallback( boost::bind(&LLPanelFace::onCancelTexture, this, _2) );
- mTextureCtrl->setOnSelectCallback( boost::bind(&LLPanelFace::onSelectTexture, this, _2) );
- mTextureCtrl->setDragCallback(boost::bind(&LLPanelFace::onDragTexture, this, _2));
- mTextureCtrl->setOnTextureSelectedCallback(boost::bind(&LLPanelFace::onTextureSelectionChanged, this, _1));
- mTextureCtrl->setOnCloseCallback( boost::bind(&LLPanelFace::onCloseTexturePicker, this, _2) );
-
- mTextureCtrl->setFollowsTop();
- mTextureCtrl->setFollowsLeft();
- mTextureCtrl->setImmediateFilterPermMask(PERM_NONE);
- mTextureCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER);
- }
-
- mShinyTextureCtrl = getChild<LLTextureCtrl>("shinytexture control");
- if(mShinyTextureCtrl)
- {
- mShinyTextureCtrl->setDefaultImageAssetID(DEFAULT_OBJECT_SPECULAR);
- mShinyTextureCtrl->setCommitCallback( boost::bind(&LLPanelFace::onCommitSpecularTexture, this, _2) );
- mShinyTextureCtrl->setOnCancelCallback( boost::bind(&LLPanelFace::onCancelSpecularTexture, this, _2) );
- mShinyTextureCtrl->setOnSelectCallback( boost::bind(&LLPanelFace::onSelectSpecularTexture, this, _2) );
- mShinyTextureCtrl->setOnCloseCallback( boost::bind(&LLPanelFace::onCloseTexturePicker, this, _2) );
-
- mShinyTextureCtrl->setDragCallback(boost::bind(&LLPanelFace::onDragTexture, this, _2));
- mShinyTextureCtrl->setOnTextureSelectedCallback(boost::bind(&LLPanelFace::onTextureSelectionChanged, this, _1));
- mShinyTextureCtrl->setFollowsTop();
- mShinyTextureCtrl->setFollowsLeft();
- mShinyTextureCtrl->setImmediateFilterPermMask(PERM_NONE);
- mShinyTextureCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER);
- }
-
- mBumpyTextureCtrl = getChild<LLTextureCtrl>("bumpytexture control");
- if(mBumpyTextureCtrl)
- {
- mBumpyTextureCtrl->setDefaultImageAssetID(DEFAULT_OBJECT_NORMAL);
- mBumpyTextureCtrl->setBlankImageAssetID(BLANK_OBJECT_NORMAL);
- mBumpyTextureCtrl->setCommitCallback( boost::bind(&LLPanelFace::onCommitNormalTexture, this, _2) );
- mBumpyTextureCtrl->setOnCancelCallback( boost::bind(&LLPanelFace::onCancelNormalTexture, this, _2) );
- mBumpyTextureCtrl->setOnSelectCallback( boost::bind(&LLPanelFace::onSelectNormalTexture, this, _2) );
- mBumpyTextureCtrl->setOnCloseCallback( boost::bind(&LLPanelFace::onCloseTexturePicker, this, _2) );
-
- mBumpyTextureCtrl->setDragCallback(boost::bind(&LLPanelFace::onDragTexture, this, _2));
- mBumpyTextureCtrl->setOnTextureSelectedCallback(boost::bind(&LLPanelFace::onTextureSelectionChanged, this, _1));
- mBumpyTextureCtrl->setFollowsTop();
- mBumpyTextureCtrl->setFollowsLeft();
- mBumpyTextureCtrl->setImmediateFilterPermMask(PERM_NONE);
- mBumpyTextureCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER);
- }
-
- mColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
- if(mColorSwatch)
- {
- mColorSwatch->setCommitCallback(boost::bind(&LLPanelFace::onCommitColor, this, _2));
- mColorSwatch->setOnCancelCallback(boost::bind(&LLPanelFace::onCancelColor, this, _2));
- mColorSwatch->setOnSelectCallback(boost::bind(&LLPanelFace::onSelectColor, this, _2));
- mColorSwatch->setFollowsTop();
- mColorSwatch->setFollowsLeft();
- mColorSwatch->setCanApplyImmediately(TRUE);
- }
-
- mShinyColorSwatch = getChild<LLColorSwatchCtrl>("shinycolorswatch");
- if(mShinyColorSwatch)
- {
- mShinyColorSwatch->setCommitCallback(boost::bind(&LLPanelFace::onCommitShinyColor, this, _2));
- mShinyColorSwatch->setOnCancelCallback(boost::bind(&LLPanelFace::onCancelShinyColor, this, _2));
- mShinyColorSwatch->setOnSelectCallback(boost::bind(&LLPanelFace::onSelectShinyColor, this, _2));
- mShinyColorSwatch->setFollowsTop();
- mShinyColorSwatch->setFollowsLeft();
- mShinyColorSwatch->setCanApplyImmediately(TRUE);
- }
-
- mLabelColorTransp = getChild<LLTextBox>("color trans");
- if(mLabelColorTransp)
- {
- mLabelColorTransp->setFollowsTop();
- mLabelColorTransp->setFollowsLeft();
- }
-
- mCtrlColorTransp = getChild<LLSpinCtrl>("ColorTrans");
- if(mCtrlColorTransp)
- {
- mCtrlColorTransp->setCommitCallback(boost::bind(&LLPanelFace::onCommitAlpha, this, _2));
- mCtrlColorTransp->setPrecision(0);
- mCtrlColorTransp->setFollowsTop();
- mCtrlColorTransp->setFollowsLeft();
- }
-
- mCheckFullbright = getChild<LLCheckBoxCtrl>("checkbox fullbright");
- if (mCheckFullbright)
- {
- mCheckFullbright->setCommitCallback(LLPanelFace::onCommitFullbright, this);
- }
-
- mComboTexGen = getChild<LLComboBox>("combobox texgen");
- if(mComboTexGen)
- {
- mComboTexGen->setCommitCallback(LLPanelFace::onCommitTexGen, this);
- mComboTexGen->setFollows(FOLLOWS_LEFT | FOLLOWS_TOP);
- }
-
- mComboMatMedia = getChild<LLComboBox>("combobox matmedia");
- if(mComboMatMedia)
- {
- mComboMatMedia->setCommitCallback(LLPanelFace::onCommitMaterialsMedia,this);
- mComboMatMedia->selectNthItem(MATMEDIA_MATERIAL);
- }
-
- LLRadioGroup* radio_mat_type = findChild<LLRadioGroup>("radio_material_type");
- if(radio_mat_type)
- {
- radio_mat_type->setCommitCallback(LLPanelFace::onCommitMaterialType, this);
- radio_mat_type->selectNthItem(MATTYPE_DIFFUSE);
- }
-
- LLRadioGroup* radio_pbr_type = findChild<LLRadioGroup>("radio_pbr_type");
- if (radio_pbr_type)
- {
- radio_pbr_type->setCommitCallback(LLPanelFace::onCommitPbrType, this);
- radio_pbr_type->selectNthItem(PBRTYPE_RENDER_MATERIAL_ID);
- }
-
- mCtrlGlow = getChild<LLSpinCtrl>("glow");
- if(mCtrlGlow)
- {
- mCtrlGlow->setCommitCallback(LLPanelFace::onCommitGlow, this);
- }
-
- mMenuClipboardColor = getChild<LLMenuButton>("clipboard_color_params_btn");
- mMenuClipboardTexture = getChild<LLMenuButton>("clipboard_texture_params_btn");
-
- mTitleMedia = getChild<LLMediaCtrl>("title_media");
- mTitleMediaText = getChild<LLTextBox>("media_info");
-
- clearCtrls();
-
- return TRUE;
-}
-
-LLPanelFace::LLPanelFace()
-: LLPanel(),
- mIsAlpha(false),
- mComboMatMedia(NULL),
- mTitleMedia(NULL),
- mTitleMediaText(NULL),
- mNeedMediaTitle(true)
-{
- USE_TEXTURE = LLTrans::getString("use_texture");
- mCommitCallbackRegistrar.add("PanelFace.menuDoToSelected", boost::bind(&LLPanelFace::menuDoToSelected, this, _2));
- mEnableCallbackRegistrar.add("PanelFace.menuEnable", boost::bind(&LLPanelFace::menuEnableItem, this, _2));
-}
-
-LLPanelFace::~LLPanelFace()
-{
- unloadMedia();
-}
-
-void LLPanelFace::onVisibilityChange(BOOL new_visibility)
-{
- if (new_visibility)
- {
- gAgent.showLatestFeatureNotification("gltf");
- }
- LLPanel::onVisibilityChange(new_visibility);
-}
-
-void LLPanelFace::draw()
-{
- updateCopyTexButton();
-
- // grab media name/title and update the UI widget
- // Todo: move it, it's preferable not to update
- // labels inside draw
- updateMediaTitle();
-
- LLPanel::draw();
-
- if (sMaterialOverrideSelection.update())
- {
- setMaterialOverridesFromSelection();
- LLMaterialEditor::updateLive();
- }
-}
-
-void LLPanelFace::sendTexture()
-{
- LLTextureCtrl* mTextureCtrl = getChild<LLTextureCtrl>("texture control");
- if(!mTextureCtrl) return;
- if( !mTextureCtrl->getTentative() )
- {
- // we grab the item id first, because we want to do a
- // permissions check in the selection manager. ARGH!
- LLUUID id = mTextureCtrl->getImageItemID();
- if(id.isNull())
- {
- id = mTextureCtrl->getImageAssetID();
- }
- if (!LLSelectMgr::getInstance()->selectionSetImage(id))
- {
- // need to refresh value in texture ctrl
- refresh();
- }
- }
-}
-
-void LLPanelFace::sendBump(U32 bumpiness)
-{
- LLTextureCtrl* bumpytexture_ctrl = getChild<LLTextureCtrl>("bumpytexture control");
- if (bumpiness < BUMPY_TEXTURE)
-{
- LL_DEBUGS("Materials") << "clearing bumptexture control" << LL_ENDL;
- bumpytexture_ctrl->clear();
- bumpytexture_ctrl->setImageAssetID(LLUUID());
- }
-
- updateBumpyControls(bumpiness == BUMPY_TEXTURE, true);
-
- LLUUID current_normal_map = bumpytexture_ctrl->getImageAssetID();
-
- U8 bump = (U8) bumpiness & TEM_BUMP_MASK;
-
- // Clear legacy bump to None when using an actual normal map
- //
- if (!current_normal_map.isNull())
- bump = 0;
-
- // Set the normal map or reset it to null as appropriate
- //
- LLSelectedTEMaterial::setNormalID(this, current_normal_map);
-
- LLSelectMgr::getInstance()->selectionSetBumpmap( bump, bumpytexture_ctrl->getImageItemID() );
-}
-
-void LLPanelFace::sendTexGen()
-{
- LLComboBox* mComboTexGen = getChild<LLComboBox>("combobox texgen");
- if(!mComboTexGen)return;
- U8 tex_gen = (U8) mComboTexGen->getCurrentIndex() << TEM_TEX_GEN_SHIFT;
- LLSelectMgr::getInstance()->selectionSetTexGen( tex_gen );
-}
-
-void LLPanelFace::sendShiny(U32 shininess)
-{
- LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>("shinytexture control");
-
- if (shininess < SHINY_TEXTURE)
-{
- texture_ctrl->clear();
- texture_ctrl->setImageAssetID(LLUUID());
- }
-
- LLUUID specmap = getCurrentSpecularMap();
-
- U8 shiny = (U8) shininess & TEM_SHINY_MASK;
- if (!specmap.isNull())
- shiny = 0;
-
- LLSelectedTEMaterial::setSpecularID(this, specmap);
-
- LLSelectMgr::getInstance()->selectionSetShiny( shiny, texture_ctrl->getImageItemID() );
-
- updateShinyControls(!specmap.isNull(), true);
-
-}
-
-void LLPanelFace::sendFullbright()
-{
- LLCheckBoxCtrl* mCheckFullbright = getChild<LLCheckBoxCtrl>("checkbox fullbright");
- if(!mCheckFullbright)return;
- U8 fullbright = mCheckFullbright->get() ? TEM_FULLBRIGHT_MASK : 0;
- LLSelectMgr::getInstance()->selectionSetFullbright( fullbright );
-}
-
-void LLPanelFace::sendColor()
-{
-
- LLColorSwatchCtrl* mColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
- if(!mColorSwatch)return;
- LLColor4 color = mColorSwatch->get();
-
- LLSelectMgr::getInstance()->selectionSetColorOnly( color );
-}
-
-void LLPanelFace::sendAlpha()
-{
- LLSpinCtrl* mCtrlColorTransp = getChild<LLSpinCtrl>("ColorTrans");
- if(!mCtrlColorTransp)return;
- F32 alpha = (100.f - mCtrlColorTransp->get()) / 100.f;
-
- LLSelectMgr::getInstance()->selectionSetAlphaOnly( alpha );
-}
-
-
-void LLPanelFace::sendGlow()
-{
- LLSpinCtrl* mCtrlGlow = getChild<LLSpinCtrl>("glow");
- llassert(mCtrlGlow);
- if (mCtrlGlow)
- {
- F32 glow = mCtrlGlow->get();
- LLSelectMgr::getInstance()->selectionSetGlow( glow );
- }
-}
-
-struct LLPanelFaceSetTEFunctor : public LLSelectedTEFunctor
-{
- LLPanelFaceSetTEFunctor(LLPanelFace* panel) : mPanel(panel) {}
- virtual bool apply(LLViewerObject* object, S32 te)
- {
- BOOL valid;
- F32 value;
- std::string prefix;
-
- // Effectively the same as MATMEDIA_PBR sans using different radio,
- // separate for the sake of clarity
- LLRadioGroup * radio_mat_type = mPanel->getChild<LLRadioGroup>("radio_material_type");
- switch (radio_mat_type->getSelectedIndex())
- {
- case MATTYPE_DIFFUSE:
- prefix = "Tex";
- break;
- case MATTYPE_NORMAL:
- prefix = "bumpy";
- break;
- case MATTYPE_SPECULAR:
- prefix = "shiny";
- break;
- }
-
- LLSpinCtrl * ctrlTexScaleS = mPanel->getChild<LLSpinCtrl>(prefix + "ScaleU");
- LLSpinCtrl * ctrlTexScaleT = mPanel->getChild<LLSpinCtrl>(prefix + "ScaleV");
- LLSpinCtrl * ctrlTexOffsetS = mPanel->getChild<LLSpinCtrl>(prefix + "OffsetU");
- LLSpinCtrl * ctrlTexOffsetT = mPanel->getChild<LLSpinCtrl>(prefix + "OffsetV");
- LLSpinCtrl * ctrlTexRotation = mPanel->getChild<LLSpinCtrl>(prefix + "Rot");
-
- LLComboBox* comboTexGen = mPanel->getChild<LLComboBox>("combobox texgen");
- LLCheckBoxCtrl* cb_planar_align = mPanel->getChild<LLCheckBoxCtrl>("checkbox planar align");
- bool align_planar = (cb_planar_align && cb_planar_align->get());
-
- llassert(comboTexGen);
- llassert(object);
-
- if (ctrlTexScaleS)
- {
- valid = !ctrlTexScaleS->getTentative(); // || !checkFlipScaleS->getTentative();
- if (valid || align_planar)
- {
- value = ctrlTexScaleS->get();
- if (comboTexGen &&
- comboTexGen->getCurrentIndex() == 1)
- {
- value *= 0.5f;
- }
- object->setTEScaleS( te, value );
-
- if (align_planar)
- {
- LLPanelFace::LLSelectedTEMaterial::setNormalRepeatX(mPanel, value, te, object->getID());
- LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatX(mPanel, value, te, object->getID());
- }
- }
- }
-
- if (ctrlTexScaleT)
- {
- valid = !ctrlTexScaleT->getTentative(); // || !checkFlipScaleT->getTentative();
- if (valid || align_planar)
- {
- value = ctrlTexScaleT->get();
- //if( checkFlipScaleT->get() )
- //{
- // value = -value;
- //}
- if (comboTexGen &&
- comboTexGen->getCurrentIndex() == 1)
- {
- value *= 0.5f;
- }
- object->setTEScaleT( te, value );
-
- if (align_planar)
- {
- LLPanelFace::LLSelectedTEMaterial::setNormalRepeatY(mPanel, value, te, object->getID());
- LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatY(mPanel, value, te, object->getID());
- }
- }
- }
-
- if (ctrlTexOffsetS)
- {
- valid = !ctrlTexOffsetS->getTentative();
- if (valid || align_planar)
- {
- value = ctrlTexOffsetS->get();
- object->setTEOffsetS( te, value );
-
- if (align_planar)
- {
- LLPanelFace::LLSelectedTEMaterial::setNormalOffsetX(mPanel, value, te, object->getID());
- LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetX(mPanel, value, te, object->getID());
- }
- }
- }
-
- if (ctrlTexOffsetT)
- {
- valid = !ctrlTexOffsetT->getTentative();
- if (valid || align_planar)
- {
- value = ctrlTexOffsetT->get();
- object->setTEOffsetT( te, value );
-
- if (align_planar)
- {
- LLPanelFace::LLSelectedTEMaterial::setNormalOffsetY(mPanel, value, te, object->getID());
- LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetY(mPanel, value, te, object->getID());
- }
- }
- }
-
- if (ctrlTexRotation)
- {
- valid = !ctrlTexRotation->getTentative();
- if (valid || align_planar)
- {
- value = ctrlTexRotation->get() * DEG_TO_RAD;
- object->setTERotation( te, value );
-
- if (align_planar)
- {
- LLPanelFace::LLSelectedTEMaterial::setNormalRotation(mPanel, value, te, object->getID());
- LLPanelFace::LLSelectedTEMaterial::setSpecularRotation(mPanel, value, te, object->getID());
- }
- }
- }
- return true;
- }
-private:
- LLPanelFace* mPanel;
-};
-
-// Functor that aligns a face to mCenterFace
-struct LLPanelFaceSetAlignedTEFunctor : public LLSelectedTEFunctor
-{
- LLPanelFaceSetAlignedTEFunctor(LLPanelFace* panel, LLFace* center_face) :
- mPanel(panel),
- mCenterFace(center_face) {}
-
- virtual bool apply(LLViewerObject* object, S32 te)
- {
- LLFace* facep = object->mDrawable->getFace(te);
- if (!facep)
- {
- return true;
- }
-
- if (facep->getViewerObject()->getVolume()->getNumVolumeFaces() <= te)
- {
- return true;
- }
-
- bool set_aligned = true;
- if (facep == mCenterFace)
- {
- set_aligned = false;
- }
- if (set_aligned)
- {
- LLVector2 uv_offset, uv_scale;
- F32 uv_rot;
- set_aligned = facep->calcAlignedPlanarTE(mCenterFace, &uv_offset, &uv_scale, &uv_rot);
- if (set_aligned)
- {
- object->setTEOffset(te, uv_offset.mV[VX], uv_offset.mV[VY]);
- object->setTEScale(te, uv_scale.mV[VX], uv_scale.mV[VY]);
- object->setTERotation(te, uv_rot);
-
- LLPanelFace::LLSelectedTEMaterial::setNormalRotation(mPanel, uv_rot, te, object->getID());
- LLPanelFace::LLSelectedTEMaterial::setSpecularRotation(mPanel, uv_rot, te, object->getID());
-
- LLPanelFace::LLSelectedTEMaterial::setNormalOffsetX(mPanel, uv_offset.mV[VX], te, object->getID());
- LLPanelFace::LLSelectedTEMaterial::setNormalOffsetY(mPanel, uv_offset.mV[VY], te, object->getID());
- LLPanelFace::LLSelectedTEMaterial::setNormalRepeatX(mPanel, uv_scale.mV[VX], te, object->getID());
- LLPanelFace::LLSelectedTEMaterial::setNormalRepeatY(mPanel, uv_scale.mV[VY], te, object->getID());
-
- LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetX(mPanel, uv_offset.mV[VX], te, object->getID());
- LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetY(mPanel, uv_offset.mV[VY], te, object->getID());
- LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatX(mPanel, uv_scale.mV[VX], te, object->getID());
- LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatY(mPanel, uv_scale.mV[VY], te, object->getID());
- }
- }
- if (!set_aligned)
- {
- LLPanelFaceSetTEFunctor setfunc(mPanel);
- setfunc.apply(object, te);
- }
- return true;
- }
-private:
- LLPanelFace* mPanel;
- LLFace* mCenterFace;
-};
-
-struct LLPanelFaceSetAlignedConcreteTEFunctor : public LLSelectedTEFunctor
-{
- LLPanelFaceSetAlignedConcreteTEFunctor(LLPanelFace* panel, LLFace* center_face, LLRender::eTexIndex map) :
- mPanel(panel),
- mChefFace(center_face),
- mMap(map)
- {}
-
- virtual bool apply(LLViewerObject* object, S32 te)
- {
- LLFace* facep = object->mDrawable->getFace(te);
- if (!facep)
- {
- return true;
- }
-
- if (facep->getViewerObject()->getVolume()->getNumVolumeFaces() <= te)
- {
- return true;
- }
-
- if (mChefFace != facep)
- {
- LLVector2 uv_offset, uv_scale;
- F32 uv_rot;
- if (facep->calcAlignedPlanarTE(mChefFace, &uv_offset, &uv_scale, &uv_rot, mMap))
- {
- switch (mMap)
- {
- case LLRender::DIFFUSE_MAP:
- object->setTEOffset(te, uv_offset.mV[VX], uv_offset.mV[VY]);
- object->setTEScale(te, uv_scale.mV[VX], uv_scale.mV[VY]);
- object->setTERotation(te, uv_rot);
- break;
- case LLRender::NORMAL_MAP:
- LLPanelFace::LLSelectedTEMaterial::setNormalRotation(mPanel, uv_rot, te, object->getID());
- LLPanelFace::LLSelectedTEMaterial::setNormalOffsetX(mPanel, uv_offset.mV[VX], te, object->getID());
- LLPanelFace::LLSelectedTEMaterial::setNormalOffsetY(mPanel, uv_offset.mV[VY], te, object->getID());
- LLPanelFace::LLSelectedTEMaterial::setNormalRepeatX(mPanel, uv_scale.mV[VX], te, object->getID());
- LLPanelFace::LLSelectedTEMaterial::setNormalRepeatY(mPanel, uv_scale.mV[VY], te, object->getID());
- break;
- case LLRender::SPECULAR_MAP:
- LLPanelFace::LLSelectedTEMaterial::setSpecularRotation(mPanel, uv_rot, te, object->getID());
- LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetX(mPanel, uv_offset.mV[VX], te, object->getID());
- LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetY(mPanel, uv_offset.mV[VY], te, object->getID());
- LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatX(mPanel, uv_scale.mV[VX], te, object->getID());
- LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatY(mPanel, uv_scale.mV[VY], te, object->getID());
- break;
- default: /*make compiler happy*/
- break;
- }
- }
- }
-
- return true;
- }
-private:
- LLPanelFace* mPanel;
- LLFace* mChefFace;
- LLRender::eTexIndex mMap;
-};
-
-// Functor that tests if a face is aligned to mCenterFace
-struct LLPanelFaceGetIsAlignedTEFunctor : public LLSelectedTEFunctor
-{
- LLPanelFaceGetIsAlignedTEFunctor(LLFace* center_face) :
- mCenterFace(center_face) {}
-
- virtual bool apply(LLViewerObject* object, S32 te)
- {
- LLFace* facep = object->mDrawable->getFace(te);
- if (!facep)
- {
- return false;
- }
-
- if (facep->getViewerObject()->getVolume()->getNumVolumeFaces() <= te)
- { //volume face does not exist, can't be aligned
- return false;
- }
-
- if (facep == mCenterFace)
- {
- return true;
- }
-
- LLVector2 aligned_st_offset, aligned_st_scale;
- F32 aligned_st_rot;
- if ( facep->calcAlignedPlanarTE(mCenterFace, &aligned_st_offset, &aligned_st_scale, &aligned_st_rot) )
- {
- const LLTextureEntry* tep = facep->getTextureEntry();
- LLVector2 st_offset, st_scale;
- tep->getOffset(&st_offset.mV[VX], &st_offset.mV[VY]);
- tep->getScale(&st_scale.mV[VX], &st_scale.mV[VY]);
- F32 st_rot = tep->getRotation();
-
- bool eq_offset_x = is_approx_equal_fraction(st_offset.mV[VX], aligned_st_offset.mV[VX], 12);
- bool eq_offset_y = is_approx_equal_fraction(st_offset.mV[VY], aligned_st_offset.mV[VY], 12);
- bool eq_scale_x = is_approx_equal_fraction(st_scale.mV[VX], aligned_st_scale.mV[VX], 12);
- bool eq_scale_y = is_approx_equal_fraction(st_scale.mV[VY], aligned_st_scale.mV[VY], 12);
- bool eq_rot = is_approx_equal_fraction(st_rot, aligned_st_rot, 6);
-
- // needs a fuzzy comparison, because of fp errors
- if (eq_offset_x &&
- eq_offset_y &&
- eq_scale_x &&
- eq_scale_y &&
- eq_rot)
- {
- return true;
- }
- }
- return false;
- }
-private:
- LLFace* mCenterFace;
-};
-
-struct LLPanelFaceSendFunctor : public LLSelectedObjectFunctor
-{
- virtual bool apply(LLViewerObject* object)
- {
- object->sendTEUpdate();
- return true;
- }
-};
-
-void LLPanelFace::sendTextureInfo()
-{
- if ((bool)childGetValue("checkbox planar align").asBoolean())
- {
- LLFace* last_face = NULL;
- bool identical_face =false;
- LLSelectedTE::getFace(last_face, identical_face);
- LLPanelFaceSetAlignedTEFunctor setfunc(this, last_face);
- LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
- }
- else
- {
- LLPanelFaceSetTEFunctor setfunc(this);
- LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
- }
-
- LLPanelFaceSendFunctor sendfunc;
- LLSelectMgr::getInstance()->getSelection()->applyToObjects(&sendfunc);
-}
-
-void LLPanelFace::alignTestureLayer()
-{
- LLFace* last_face = NULL;
- bool identical_face = false;
- LLSelectedTE::getFace(last_face, identical_face);
-
- LLRadioGroup * radio_mat_type = getChild<LLRadioGroup>("radio_material_type");
- LLPanelFaceSetAlignedConcreteTEFunctor setfunc(this, last_face, static_cast<LLRender::eTexIndex>(radio_mat_type->getSelectedIndex()));
- LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
-}
-
-void LLPanelFace::getState()
-{
- updateUI();
-}
-
-void LLPanelFace::updateUI(bool force_set_values /*false*/)
-{ //set state of UI to match state of texture entry(ies) (calls setEnabled, setValue, etc, but NOT setVisible)
- LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode();
- LLViewerObject* objectp = node ? node->getObject() : NULL;
-
- if (objectp
- && objectp->getPCode() == LL_PCODE_VOLUME
- && objectp->permModify())
- {
- BOOL editable = objectp->permModify() && !objectp->isPermanentEnforced();
- BOOL attachment = objectp->isAttachment();
-
- bool has_pbr_material;
- bool has_faces_without_pbr;
- updateUIGLTF(objectp, has_pbr_material, has_faces_without_pbr, force_set_values);
-
- const bool has_material = !has_pbr_material;
-
- // only turn on auto-adjust button if there is a media renderer and the media is loaded
- childSetEnabled("button align", editable);
-
- if (mComboMatMedia->getCurrentIndex() < MATMEDIA_MATERIAL)
- {
- // When selecting an object with a pbr and UI combo is not set,
- // set to pbr option, otherwise to a texture (material)
- if (has_pbr_material)
- {
- mComboMatMedia->selectNthItem(MATMEDIA_PBR);
- }
- else
- {
- mComboMatMedia->selectNthItem(MATMEDIA_MATERIAL);
- }
- }
-
- // *NOTE: The "identical" variable is currently only used to decide if
- // the texgen control should be tentative - this is not used by GLTF
- // materials. -Cosmic;2022-11-09
- bool identical = true; // true because it is anded below
- bool identical_diffuse = false;
- bool identical_norm = false;
- bool identical_spec = false;
-
- LLTextureCtrl *texture_ctrl = getChild<LLTextureCtrl>("texture control");
- LLTextureCtrl *shinytexture_ctrl = getChild<LLTextureCtrl>("shinytexture control");
- LLTextureCtrl *bumpytexture_ctrl = getChild<LLTextureCtrl>("bumpytexture control");
-
- LLUUID id;
- LLUUID normmap_id;
- LLUUID specmap_id;
-
- LLSelectedTE::getTexId(id, identical_diffuse);
- LLSelectedTEMaterial::getNormalID(normmap_id, identical_norm);
- LLSelectedTEMaterial::getSpecularID(specmap_id, identical_spec);
-
- static S32 selected_te = -1;
- static LLUUID prev_obj_id;
- if ((LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool()) &&
- !LLSelectMgr::getInstance()->getSelection()->isMultipleTESelected())
- {
- S32 new_selection = -1; // Don't use getLastSelectedTE, it could have been deselected
- S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces());
- for (S32 te = 0; te < num_tes; ++te)
- {
- if (node->isTESelected(te))
- {
- new_selection = te;
- break;
- }
- }
-
- if ((new_selection != selected_te)
- || (prev_obj_id != objectp->getID()))
- {
- bool te_has_media = objectp->getTE(new_selection) && objectp->getTE(new_selection)->hasMedia();
- bool te_has_pbr = objectp->getRenderMaterialID(new_selection).notNull();
-
- if (te_has_pbr && !((mComboMatMedia->getCurrentIndex() == MATMEDIA_MEDIA) && te_has_media))
- {
- mComboMatMedia->selectNthItem(MATMEDIA_PBR);
- }
- else if (te_has_media)
- {
- mComboMatMedia->selectNthItem(MATMEDIA_MEDIA);
- }
- else if (id.notNull() || normmap_id.notNull() || specmap_id.notNull())
- {
- mComboMatMedia->selectNthItem(MATMEDIA_MATERIAL);
- }
- selected_te = new_selection;
- prev_obj_id = objectp->getID();
- }
- }
- else
- {
- if (prev_obj_id != objectp->getID())
- {
- if (has_pbr_material && (mComboMatMedia->getCurrentIndex() == MATMEDIA_MATERIAL))
- {
- mComboMatMedia->selectNthItem(MATMEDIA_PBR);
- }
- else if (!has_pbr_material && (mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR))
- {
- mComboMatMedia->selectNthItem(MATMEDIA_MATERIAL);
- }
- prev_obj_id = objectp->getID();
- }
- }
- mComboMatMedia->setEnabled(editable);
-
- LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type");
- if (radio_mat_type->getSelectedIndex() < MATTYPE_DIFFUSE)
- {
- radio_mat_type->selectNthItem(MATTYPE_DIFFUSE);
- }
- radio_mat_type->setEnabled(editable);
-
- LLRadioGroup* radio_pbr_type = getChild<LLRadioGroup>("radio_pbr_type");
- if (radio_pbr_type->getSelectedIndex() < PBRTYPE_RENDER_MATERIAL_ID)
- {
- radio_pbr_type->selectNthItem(PBRTYPE_RENDER_MATERIAL_ID);
- }
- radio_pbr_type->setEnabled(editable);
- const bool pbr_selected = mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR;
- const bool texture_info_selected = pbr_selected && radio_pbr_type->getSelectedIndex() != PBRTYPE_RENDER_MATERIAL_ID;
-
- getChildView("checkbox_sync_settings")->setEnabled(editable);
- childSetValue("checkbox_sync_settings", gSavedSettings.getBOOL("SyncMaterialSettings"));
-
- updateVisibility(objectp);
-
- // Color swatch
- {
- getChildView("color label")->setEnabled(editable);
- }
- LLColorSwatchCtrl* color_swatch = findChild<LLColorSwatchCtrl>("colorswatch");
-
- LLColor4 color = LLColor4::white;
- bool identical_color = false;
-
- if (color_swatch)
- {
- LLSelectedTE::getColor(color, identical_color);
- LLColor4 prev_color = color_swatch->get();
-
- color_swatch->setOriginal(color);
- color_swatch->set(color, force_set_values || (prev_color != color) || !editable);
-
- color_swatch->setValid(editable && !has_pbr_material);
- color_swatch->setEnabled( editable && !has_pbr_material);
- color_swatch->setCanApplyImmediately( editable && !has_pbr_material);
- }
-
- // Color transparency
- getChildView("color trans")->setEnabled(editable);
-
- F32 transparency = (1.f - color.mV[VALPHA]) * 100.f;
- getChild<LLUICtrl>("ColorTrans")->setValue(editable ? transparency : 0);
- getChildView("ColorTrans")->setEnabled(editable && has_material);
-
- U8 shiny = 0;
- bool identical_shiny = false;
-
- // Shiny
- LLSelectedTE::getShiny(shiny, identical_shiny);
- identical = identical && identical_shiny;
-
- shiny = specmap_id.isNull() ? shiny : SHINY_TEXTURE;
-
- LLCtrlSelectionInterface* combobox_shininess = childGetSelectionInterface("combobox shininess");
- if (combobox_shininess)
- {
- combobox_shininess->selectNthItem((S32)shiny);
- }
-
- getChildView("label shininess")->setEnabled(editable);
- getChildView("combobox shininess")->setEnabled(editable);
-
- getChildView("label glossiness")->setEnabled(editable);
- getChildView("glossiness")->setEnabled(editable);
-
- getChildView("label environment")->setEnabled(editable);
- getChildView("environment")->setEnabled(editable);
- getChildView("label shinycolor")->setEnabled(editable);
-
- getChild<LLUICtrl>("combobox shininess")->setTentative(!identical_spec);
- getChild<LLUICtrl>("glossiness")->setTentative(!identical_spec);
- getChild<LLUICtrl>("environment")->setTentative(!identical_spec);
- getChild<LLUICtrl>("shinycolorswatch")->setTentative(!identical_spec);
-
- LLColorSwatchCtrl* mShinyColorSwatch = getChild<LLColorSwatchCtrl>("shinycolorswatch");
- if (mShinyColorSwatch)
- {
- mShinyColorSwatch->setValid(editable);
- mShinyColorSwatch->setEnabled( editable );
- mShinyColorSwatch->setCanApplyImmediately( editable );
- }
-
- U8 bumpy = 0;
- // Bumpy
- {
- bool identical_bumpy = false;
- LLSelectedTE::getBumpmap(bumpy,identical_bumpy);
-
- LLUUID norm_map_id = getCurrentNormalMap();
- LLCtrlSelectionInterface* combobox_bumpiness = childGetSelectionInterface("combobox bumpiness");
-
- bumpy = norm_map_id.isNull() ? bumpy : BUMPY_TEXTURE;
-
- if (combobox_bumpiness)
- {
- combobox_bumpiness->selectNthItem((S32)bumpy);
- }
- else
- {
- LL_WARNS() << "failed childGetSelectionInterface for 'combobox bumpiness'" << LL_ENDL;
- }
-
- getChildView("combobox bumpiness")->setEnabled(editable);
- getChild<LLUICtrl>("combobox bumpiness")->setTentative(!identical_bumpy);
- getChildView("label bumpiness")->setEnabled(editable);
- }
-
- // Texture
- {
- mIsAlpha = FALSE;
- LLGLenum image_format = GL_RGB;
- bool identical_image_format = false;
- LLSelectedTE::getImageFormat(image_format, identical_image_format);
-
- mIsAlpha = FALSE;
- switch (image_format)
- {
- case GL_RGBA:
- case GL_ALPHA:
- {
- mIsAlpha = TRUE;
- }
- break;
-
- case GL_RGB: break;
- default:
- {
- LL_WARNS() << "Unexpected tex format in LLPanelFace...resorting to no alpha" << LL_ENDL;
- }
- break;
- }
-
- if (LLViewerMedia::getInstance()->textureHasMedia(id))
- {
- getChildView("button align")->setEnabled(editable);
- }
-
- // Diffuse Alpha Mode
-
- // Init to the default that is appropriate for the alpha content of the asset
- //
- U8 alpha_mode = mIsAlpha ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : LLMaterial::DIFFUSE_ALPHA_MODE_NONE;
-
- bool identical_alpha_mode = false;
-
- // See if that's been overridden by a material setting for same...
- //
- LLSelectedTEMaterial::getCurrentDiffuseAlphaMode(alpha_mode, identical_alpha_mode, mIsAlpha);
-
- LLCtrlSelectionInterface* combobox_alphamode = childGetSelectionInterface("combobox alphamode");
- if (combobox_alphamode)
- {
- //it is invalid to have any alpha mode other than blend if transparency is greater than zero ...
- // Want masking? Want emissive? Tough! You get BLEND!
- alpha_mode = (transparency > 0.f) ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : alpha_mode;
-
- // ... unless there is no alpha channel in the texture, in which case alpha mode MUST be none
- alpha_mode = mIsAlpha ? alpha_mode : LLMaterial::DIFFUSE_ALPHA_MODE_NONE;
-
- combobox_alphamode->selectNthItem(alpha_mode);
- }
- else
- {
- LL_WARNS() << "failed childGetSelectionInterface for 'combobox alphamode'" << LL_ENDL;
- }
-
- updateAlphaControls();
-
- if (texture_ctrl)
- {
- if (identical_diffuse)
- {
- texture_ctrl->setTentative(FALSE);
- texture_ctrl->setEnabled(editable && !has_pbr_material);
- texture_ctrl->setImageAssetID(id);
- getChildView("combobox alphamode")->setEnabled(editable && mIsAlpha && transparency <= 0.f && !has_pbr_material);
- getChildView("label alphamode")->setEnabled(editable && mIsAlpha && !has_pbr_material);
- getChildView("maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material);
- getChildView("label maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material);
-
- texture_ctrl->setBakeTextureEnabled(TRUE);
- }
- else if (id.isNull())
- {
- // None selected
- texture_ctrl->setTentative(FALSE);
- texture_ctrl->setEnabled(FALSE);
- texture_ctrl->setImageAssetID(LLUUID::null);
- getChildView("combobox alphamode")->setEnabled(FALSE);
- getChildView("label alphamode")->setEnabled(FALSE);
- getChildView("maskcutoff")->setEnabled(FALSE);
- getChildView("label maskcutoff")->setEnabled(FALSE);
-
- texture_ctrl->setBakeTextureEnabled(false);
- }
- else
- {
- // Tentative: multiple selected with different textures
- texture_ctrl->setTentative(TRUE);
- texture_ctrl->setEnabled(editable && !has_pbr_material);
- texture_ctrl->setImageAssetID(id);
- getChildView("combobox alphamode")->setEnabled(editable && mIsAlpha && transparency <= 0.f && !has_pbr_material);
- getChildView("label alphamode")->setEnabled(editable && mIsAlpha && !has_pbr_material);
- getChildView("maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material);
- getChildView("label maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material);
-
- texture_ctrl->setBakeTextureEnabled(TRUE);
- }
-
- if (attachment)
- {
- // attachments are in world and in inventory,
- // server doesn't support changing permissions
- // in such case
- texture_ctrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
- }
- else
- {
- texture_ctrl->setImmediateFilterPermMask(PERM_NONE);
- }
- }
-
- if (shinytexture_ctrl)
- {
- shinytexture_ctrl->setTentative( !identical_spec );
- shinytexture_ctrl->setEnabled( editable && !has_pbr_material);
- shinytexture_ctrl->setImageAssetID( specmap_id );
-
- if (attachment)
- {
- shinytexture_ctrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
- }
- else
- {
- shinytexture_ctrl->setImmediateFilterPermMask(PERM_NONE);
- }
- }
-
- if (bumpytexture_ctrl)
- {
- bumpytexture_ctrl->setTentative( !identical_norm );
- bumpytexture_ctrl->setEnabled( editable && !has_pbr_material);
- bumpytexture_ctrl->setImageAssetID( normmap_id );
-
- if (attachment)
- {
- bumpytexture_ctrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
- }
- else
- {
- bumpytexture_ctrl->setImmediateFilterPermMask(PERM_NONE);
- }
- }
- }
-
- // planar align
- bool align_planar = false;
- bool identical_planar_aligned = false;
- {
- LLCheckBoxCtrl* cb_planar_align = getChild<LLCheckBoxCtrl>("checkbox planar align");
- align_planar = (cb_planar_align && cb_planar_align->get());
-
- bool enabled = (editable && isIdenticalPlanarTexgen() && !texture_info_selected);
- childSetValue("checkbox planar align", align_planar && enabled);
- childSetVisible("checkbox planar align", enabled);
- childSetEnabled("checkbox planar align", enabled);
- childSetEnabled("button align textures", enabled && LLSelectMgr::getInstance()->getSelection()->getObjectCount() > 1);
-
- if (align_planar && enabled)
- {
- LLFace* last_face = NULL;
- bool identical_face = false;
- LLSelectedTE::getFace(last_face, identical_face);
-
- LLPanelFaceGetIsAlignedTEFunctor get_is_aligend_func(last_face);
- // this will determine if the texture param controls are tentative:
- identical_planar_aligned = LLSelectMgr::getInstance()->getSelection()->applyToTEs(&get_is_aligend_func);
- }
- }
-
- // Needs to be public and before tex scale settings below to properly reflect
- // behavior when in planar vs default texgen modes in the
- // NORSPEC-84 et al
- //
- LLTextureEntry::e_texgen selected_texgen = LLTextureEntry::TEX_GEN_DEFAULT;
- bool identical_texgen = true;
- bool identical_planar_texgen = false;
-
- {
- LLSelectedTE::getTexGen(selected_texgen, identical_texgen);
- identical_planar_texgen = (identical_texgen && (selected_texgen == LLTextureEntry::TEX_GEN_PLANAR));
- }
-
- // Texture scale
- {
- bool identical_diff_scale_s = false;
- bool identical_spec_scale_s = false;
- bool identical_norm_scale_s = false;
-
- identical = align_planar ? identical_planar_aligned : identical;
-
- F32 diff_scale_s = 1.f;
- F32 spec_scale_s = 1.f;
- F32 norm_scale_s = 1.f;
-
- LLSelectedTE::getScaleS(diff_scale_s, identical_diff_scale_s);
- LLSelectedTEMaterial::getSpecularRepeatX(spec_scale_s, identical_spec_scale_s);
- LLSelectedTEMaterial::getNormalRepeatX(norm_scale_s, identical_norm_scale_s);
-
- diff_scale_s = editable ? diff_scale_s : 1.0f;
- diff_scale_s *= identical_planar_texgen ? 2.0f : 1.0f;
-
- norm_scale_s = editable ? norm_scale_s : 1.0f;
- norm_scale_s *= identical_planar_texgen ? 2.0f : 1.0f;
-
- spec_scale_s = editable ? spec_scale_s : 1.0f;
- spec_scale_s *= identical_planar_texgen ? 2.0f : 1.0f;
-
- getChild<LLUICtrl>("TexScaleU")->setValue(diff_scale_s);
- getChild<LLUICtrl>("shinyScaleU")->setValue(spec_scale_s);
- getChild<LLUICtrl>("bumpyScaleU")->setValue(norm_scale_s);
-
- getChildView("TexScaleU")->setEnabled(editable && has_material);
- getChildView("shinyScaleU")->setEnabled(editable && has_material && specmap_id.notNull());
- getChildView("bumpyScaleU")->setEnabled(editable && has_material && normmap_id.notNull());
-
- BOOL diff_scale_tentative = !(identical && identical_diff_scale_s);
- BOOL norm_scale_tentative = !(identical && identical_norm_scale_s);
- BOOL spec_scale_tentative = !(identical && identical_spec_scale_s);
-
- getChild<LLUICtrl>("TexScaleU")->setTentative( LLSD(diff_scale_tentative));
- getChild<LLUICtrl>("shinyScaleU")->setTentative(LLSD(spec_scale_tentative));
- getChild<LLUICtrl>("bumpyScaleU")->setTentative(LLSD(norm_scale_tentative));
- }
-
- {
- bool identical_diff_scale_t = false;
- bool identical_spec_scale_t = false;
- bool identical_norm_scale_t = false;
-
- F32 diff_scale_t = 1.f;
- F32 spec_scale_t = 1.f;
- F32 norm_scale_t = 1.f;
-
- LLSelectedTE::getScaleT(diff_scale_t, identical_diff_scale_t);
- LLSelectedTEMaterial::getSpecularRepeatY(spec_scale_t, identical_spec_scale_t);
- LLSelectedTEMaterial::getNormalRepeatY(norm_scale_t, identical_norm_scale_t);
-
- diff_scale_t = editable ? diff_scale_t : 1.0f;
- diff_scale_t *= identical_planar_texgen ? 2.0f : 1.0f;
-
- norm_scale_t = editable ? norm_scale_t : 1.0f;
- norm_scale_t *= identical_planar_texgen ? 2.0f : 1.0f;
-
- spec_scale_t = editable ? spec_scale_t : 1.0f;
- spec_scale_t *= identical_planar_texgen ? 2.0f : 1.0f;
-
- BOOL diff_scale_tentative = !identical_diff_scale_t;
- BOOL norm_scale_tentative = !identical_norm_scale_t;
- BOOL spec_scale_tentative = !identical_spec_scale_t;
-
- getChildView("TexScaleV")->setEnabled(editable && has_material);
- getChildView("shinyScaleV")->setEnabled(editable && has_material && specmap_id.notNull());
- getChildView("bumpyScaleV")->setEnabled(editable && has_material && normmap_id.notNull());
-
- if (force_set_values)
- {
- getChild<LLSpinCtrl>("TexScaleV")->forceSetValue(diff_scale_t);
- }
- else
- {
- getChild<LLSpinCtrl>("TexScaleV")->setValue(diff_scale_t);
- }
- getChild<LLUICtrl>("shinyScaleV")->setValue(norm_scale_t);
- getChild<LLUICtrl>("bumpyScaleV")->setValue(spec_scale_t);
-
- getChild<LLUICtrl>("TexScaleV")->setTentative(LLSD(diff_scale_tentative));
- getChild<LLUICtrl>("shinyScaleV")->setTentative(LLSD(norm_scale_tentative));
- getChild<LLUICtrl>("bumpyScaleV")->setTentative(LLSD(spec_scale_tentative));
- }
-
- // Texture offset
- {
- bool identical_diff_offset_s = false;
- bool identical_norm_offset_s = false;
- bool identical_spec_offset_s = false;
-
- F32 diff_offset_s = 0.0f;
- F32 norm_offset_s = 0.0f;
- F32 spec_offset_s = 0.0f;
-
- LLSelectedTE::getOffsetS(diff_offset_s, identical_diff_offset_s);
- LLSelectedTEMaterial::getNormalOffsetX(norm_offset_s, identical_norm_offset_s);
- LLSelectedTEMaterial::getSpecularOffsetX(spec_offset_s, identical_spec_offset_s);
-
- BOOL diff_offset_u_tentative = !(align_planar ? identical_planar_aligned : identical_diff_offset_s);
- BOOL norm_offset_u_tentative = !(align_planar ? identical_planar_aligned : identical_norm_offset_s);
- BOOL spec_offset_u_tentative = !(align_planar ? identical_planar_aligned : identical_spec_offset_s);
-
- getChild<LLUICtrl>("TexOffsetU")->setValue( editable ? diff_offset_s : 0.0f);
- getChild<LLUICtrl>("bumpyOffsetU")->setValue(editable ? norm_offset_s : 0.0f);
- getChild<LLUICtrl>("shinyOffsetU")->setValue(editable ? spec_offset_s : 0.0f);
-
- getChild<LLUICtrl>("TexOffsetU")->setTentative(LLSD(diff_offset_u_tentative));
- getChild<LLUICtrl>("shinyOffsetU")->setTentative(LLSD(norm_offset_u_tentative));
- getChild<LLUICtrl>("bumpyOffsetU")->setTentative(LLSD(spec_offset_u_tentative));
-
- getChildView("TexOffsetU")->setEnabled(editable && has_material);
- getChildView("shinyOffsetU")->setEnabled(editable && has_material && specmap_id.notNull());
- getChildView("bumpyOffsetU")->setEnabled(editable && has_material && normmap_id.notNull());
- }
-
- {
- bool identical_diff_offset_t = false;
- bool identical_norm_offset_t = false;
- bool identical_spec_offset_t = false;
-
- F32 diff_offset_t = 0.0f;
- F32 norm_offset_t = 0.0f;
- F32 spec_offset_t = 0.0f;
-
- LLSelectedTE::getOffsetT(diff_offset_t, identical_diff_offset_t);
- LLSelectedTEMaterial::getNormalOffsetY(norm_offset_t, identical_norm_offset_t);
- LLSelectedTEMaterial::getSpecularOffsetY(spec_offset_t, identical_spec_offset_t);
-
- BOOL diff_offset_v_tentative = !(align_planar ? identical_planar_aligned : identical_diff_offset_t);
- BOOL norm_offset_v_tentative = !(align_planar ? identical_planar_aligned : identical_norm_offset_t);
- BOOL spec_offset_v_tentative = !(align_planar ? identical_planar_aligned : identical_spec_offset_t);
-
- getChild<LLUICtrl>("TexOffsetV")->setValue( editable ? diff_offset_t : 0.0f);
- getChild<LLUICtrl>("bumpyOffsetV")->setValue(editable ? norm_offset_t : 0.0f);
- getChild<LLUICtrl>("shinyOffsetV")->setValue(editable ? spec_offset_t : 0.0f);
-
- getChild<LLUICtrl>("TexOffsetV")->setTentative(LLSD(diff_offset_v_tentative));
- getChild<LLUICtrl>("shinyOffsetV")->setTentative(LLSD(norm_offset_v_tentative));
- getChild<LLUICtrl>("bumpyOffsetV")->setTentative(LLSD(spec_offset_v_tentative));
-
- getChildView("TexOffsetV")->setEnabled(editable && has_material);
- getChildView("shinyOffsetV")->setEnabled(editable && has_material && specmap_id.notNull());
- getChildView("bumpyOffsetV")->setEnabled(editable && has_material && normmap_id.notNull());
- }
-
- // Texture rotation
- {
- bool identical_diff_rotation = false;
- bool identical_norm_rotation = false;
- bool identical_spec_rotation = false;
-
- F32 diff_rotation = 0.f;
- F32 norm_rotation = 0.f;
- F32 spec_rotation = 0.f;
-
- LLSelectedTE::getRotation(diff_rotation,identical_diff_rotation);
- LLSelectedTEMaterial::getSpecularRotation(spec_rotation,identical_spec_rotation);
- LLSelectedTEMaterial::getNormalRotation(norm_rotation,identical_norm_rotation);
-
- BOOL diff_rot_tentative = !(align_planar ? identical_planar_aligned : identical_diff_rotation);
- BOOL norm_rot_tentative = !(align_planar ? identical_planar_aligned : identical_norm_rotation);
- BOOL spec_rot_tentative = !(align_planar ? identical_planar_aligned : identical_spec_rotation);
-
- F32 diff_rot_deg = diff_rotation * RAD_TO_DEG;
- F32 norm_rot_deg = norm_rotation * RAD_TO_DEG;
- F32 spec_rot_deg = spec_rotation * RAD_TO_DEG;
-
- getChildView("TexRot")->setEnabled(editable && has_material);
- getChildView("shinyRot")->setEnabled(editable && has_material && specmap_id.notNull());
- getChildView("bumpyRot")->setEnabled(editable && has_material && normmap_id.notNull());
-
- getChild<LLUICtrl>("TexRot")->setTentative(diff_rot_tentative);
- getChild<LLUICtrl>("shinyRot")->setTentative(LLSD(norm_rot_tentative));
- getChild<LLUICtrl>("bumpyRot")->setTentative(LLSD(spec_rot_tentative));
-
- getChild<LLUICtrl>("TexRot")->setValue( editable ? diff_rot_deg : 0.0f);
- getChild<LLUICtrl>("shinyRot")->setValue(editable ? spec_rot_deg : 0.0f);
- getChild<LLUICtrl>("bumpyRot")->setValue(editable ? norm_rot_deg : 0.0f);
- }
-
- {
- F32 glow = 0.f;
- bool identical_glow = false;
- LLSelectedTE::getGlow(glow,identical_glow);
- getChild<LLUICtrl>("glow")->setValue(glow);
- getChild<LLUICtrl>("glow")->setTentative(!identical_glow);
- getChildView("glow")->setEnabled(editable);
- getChildView("glow label")->setEnabled(editable);
- }
-
- {
- LLCtrlSelectionInterface* combobox_texgen = childGetSelectionInterface("combobox texgen");
- if (combobox_texgen)
- {
- // Maps from enum to combobox entry index
- combobox_texgen->selectNthItem(((S32)selected_texgen) >> 1);
- }
- else
- {
- LL_WARNS() << "failed childGetSelectionInterface for 'combobox texgen'" << LL_ENDL;
- }
-
- getChildView("combobox texgen")->setEnabled(editable);
- getChild<LLUICtrl>("combobox texgen")->setTentative(!identical);
- getChildView("tex gen")->setEnabled(editable);
- }
-
- {
- U8 fullbright_flag = 0;
- bool identical_fullbright = false;
-
- LLSelectedTE::getFullbright(fullbright_flag,identical_fullbright);
-
- getChild<LLUICtrl>("checkbox fullbright")->setValue((S32)(fullbright_flag != 0));
- getChildView("checkbox fullbright")->setEnabled(editable && !has_pbr_material);
- getChild<LLUICtrl>("checkbox fullbright")->setTentative(!identical_fullbright);
- mComboMatMedia->setEnabledByValue("Materials", !has_pbr_material);
- }
-
- // Repeats per meter
- {
- F32 repeats_diff = 1.f;
- F32 repeats_norm = 1.f;
- F32 repeats_spec = 1.f;
-
- bool identical_diff_repeats = false;
- bool identical_norm_repeats = false;
- bool identical_spec_repeats = false;
-
- LLSelectedTE::getMaxDiffuseRepeats(repeats_diff, identical_diff_repeats);
- LLSelectedTEMaterial::getMaxNormalRepeats(repeats_norm, identical_norm_repeats);
- LLSelectedTEMaterial::getMaxSpecularRepeats(repeats_spec, identical_spec_repeats);
-
- LLComboBox* mComboTexGen = getChild<LLComboBox>("combobox texgen");
- if (mComboTexGen)
- {
- S32 index = mComboTexGen ? mComboTexGen->getCurrentIndex() : 0;
- bool enabled = editable && (index != 1);
- bool identical_repeats = true;
- S32 material_selection = mComboMatMedia->getCurrentIndex();
- F32 repeats = 1.0f;
-
- U32 material_type = MATTYPE_DIFFUSE;
- if (material_selection == MATMEDIA_MATERIAL)
- {
- material_type = radio_mat_type->getSelectedIndex();
- }
- else if (material_selection == MATMEDIA_PBR)
- {
- enabled = editable && has_pbr_material;
- material_type = radio_pbr_type->getSelectedIndex();
- }
-
- switch (material_type)
- {
- default:
- case MATTYPE_DIFFUSE:
- {
- if (material_selection != MATMEDIA_PBR)
- {
- enabled = editable && !id.isNull();
- }
- identical_repeats = identical_diff_repeats;
- repeats = repeats_diff;
- }
- break;
-
- case MATTYPE_SPECULAR:
- {
- if (material_selection != MATMEDIA_PBR)
- {
- enabled = (editable && ((shiny == SHINY_TEXTURE) && !specmap_id.isNull()));
- }
- identical_repeats = identical_spec_repeats;
- repeats = repeats_spec;
- }
- break;
-
- case MATTYPE_NORMAL:
- {
- if (material_selection != MATMEDIA_PBR)
- {
- enabled = (editable && ((bumpy == BUMPY_TEXTURE) && !normmap_id.isNull()));
- }
- identical_repeats = identical_norm_repeats;
- repeats = repeats_norm;
- }
- break;
- }
-
- BOOL repeats_tentative = !identical_repeats;
-
- LLSpinCtrl* rpt_ctrl = getChild<LLSpinCtrl>("rptctrl");
- if (force_set_values)
- {
- //onCommit, previosly edited element updates related ones
- rpt_ctrl->forceSetValue(editable ? repeats : 1.0f);
- }
- else
- {
- rpt_ctrl->setValue(editable ? repeats : 1.0f);
- }
- rpt_ctrl->setTentative(LLSD(repeats_tentative));
- rpt_ctrl->setEnabled(has_material && !identical_planar_texgen && enabled);
- }
- }
-
- // Materials
- {
- LLMaterialPtr material;
- LLSelectedTEMaterial::getCurrent(material, identical);
-
- if (material && editable)
- {
- LL_DEBUGS("Materials") << material->asLLSD() << LL_ENDL;
-
- // Alpha
- LLCtrlSelectionInterface* combobox_alphamode =
- childGetSelectionInterface("combobox alphamode");
- if (combobox_alphamode)
- {
- U32 alpha_mode = material->getDiffuseAlphaMode();
-
- if (transparency > 0.f)
- { //it is invalid to have any alpha mode other than blend if transparency is greater than zero ...
- alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND;
- }
-
- if (!mIsAlpha)
- { // ... unless there is no alpha channel in the texture, in which case alpha mode MUST ebe none
- alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_NONE;
- }
-
- combobox_alphamode->selectNthItem(alpha_mode);
- }
- else
- {
- LL_WARNS() << "failed childGetSelectionInterface for 'combobox alphamode'" << LL_ENDL;
- }
- getChild<LLUICtrl>("maskcutoff")->setValue(material->getAlphaMaskCutoff());
- updateAlphaControls();
-
- identical_planar_texgen = isIdenticalPlanarTexgen();
-
- // Shiny (specular)
- F32 offset_x, offset_y, repeat_x, repeat_y, rot;
- LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>("shinytexture control");
- texture_ctrl->setImageAssetID(material->getSpecularID());
-
- if (!material->getSpecularID().isNull() && (shiny == SHINY_TEXTURE))
- {
- material->getSpecularOffset(offset_x,offset_y);
- material->getSpecularRepeat(repeat_x,repeat_y);
-
- if (identical_planar_texgen)
- {
- repeat_x *= 2.0f;
- repeat_y *= 2.0f;
- }
-
- rot = material->getSpecularRotation();
- getChild<LLUICtrl>("shinyScaleU")->setValue(repeat_x);
- getChild<LLUICtrl>("shinyScaleV")->setValue(repeat_y);
- getChild<LLUICtrl>("shinyRot")->setValue(rot*RAD_TO_DEG);
- getChild<LLUICtrl>("shinyOffsetU")->setValue(offset_x);
- getChild<LLUICtrl>("shinyOffsetV")->setValue(offset_y);
- getChild<LLUICtrl>("glossiness")->setValue(material->getSpecularLightExponent());
- getChild<LLUICtrl>("environment")->setValue(material->getEnvironmentIntensity());
-
- updateShinyControls(!material->getSpecularID().isNull(), true);
- }
-
- // Assert desired colorswatch color to match material AFTER updateShinyControls
- // to avoid getting overwritten with the default on some UI state changes.
- //
- if (!material->getSpecularID().isNull())
- {
- LLColorSwatchCtrl* shiny_swatch = getChild<LLColorSwatchCtrl>("shinycolorswatch");
- LLColor4 new_color = material->getSpecularLightColor();
- LLColor4 old_color = shiny_swatch->get();
-
- shiny_swatch->setOriginal(new_color);
- shiny_swatch->set(new_color, force_set_values || old_color != new_color || !editable);
- }
-
- // Bumpy (normal)
- texture_ctrl = getChild<LLTextureCtrl>("bumpytexture control");
- texture_ctrl->setImageAssetID(material->getNormalID());
-
- if (!material->getNormalID().isNull())
- {
- material->getNormalOffset(offset_x,offset_y);
- material->getNormalRepeat(repeat_x,repeat_y);
-
- if (identical_planar_texgen)
- {
- repeat_x *= 2.0f;
- repeat_y *= 2.0f;
- }
-
- rot = material->getNormalRotation();
- getChild<LLUICtrl>("bumpyScaleU")->setValue(repeat_x);
- getChild<LLUICtrl>("bumpyScaleV")->setValue(repeat_y);
- getChild<LLUICtrl>("bumpyRot")->setValue(rot*RAD_TO_DEG);
- getChild<LLUICtrl>("bumpyOffsetU")->setValue(offset_x);
- getChild<LLUICtrl>("bumpyOffsetV")->setValue(offset_y);
-
- updateBumpyControls(!material->getNormalID().isNull(), true);
- }
- }
- }
- S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
- BOOL single_volume = (selected_count == 1);
- mMenuClipboardColor->setEnabled(editable && single_volume);
-
- // Set variable values for numeric expressions
- LLCalc* calcp = LLCalc::getInstance();
- calcp->setVar(LLCalc::TEX_U_SCALE, childGetValue("TexScaleU").asReal());
- calcp->setVar(LLCalc::TEX_V_SCALE, childGetValue("TexScaleV").asReal());
- calcp->setVar(LLCalc::TEX_U_OFFSET, childGetValue("TexOffsetU").asReal());
- calcp->setVar(LLCalc::TEX_V_OFFSET, childGetValue("TexOffsetV").asReal());
- calcp->setVar(LLCalc::TEX_ROTATION, childGetValue("TexRot").asReal());
- calcp->setVar(LLCalc::TEX_TRANSPARENCY, childGetValue("ColorTrans").asReal());
- calcp->setVar(LLCalc::TEX_GLOW, childGetValue("glow").asReal());
- }
- else
- {
- // Disable all UICtrls
- clearCtrls();
-
- // Disable non-UICtrls
- LLTextureCtrl* pbr_ctrl = findChild<LLTextureCtrl>("pbr_control");
- if (pbr_ctrl)
- {
- pbr_ctrl->setImageAssetID(LLUUID::null);
- pbr_ctrl->setEnabled(FALSE);
- }
- LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>("texture control");
- if (texture_ctrl)
- {
- texture_ctrl->setImageAssetID( LLUUID::null );
- texture_ctrl->setEnabled( FALSE ); // this is a LLUICtrl, but we don't want it to have keyboard focus so we add it as a child, not a ctrl.
-// texture_ctrl->setValid(FALSE);
- }
- LLColorSwatchCtrl* mColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
- if (mColorSwatch)
- {
- mColorSwatch->setEnabled( FALSE );
- mColorSwatch->setFallbackImage(LLUI::getUIImage("locked_image.j2c") );
- mColorSwatch->setValid(FALSE);
- }
- LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type");
- if (radio_mat_type)
- {
- radio_mat_type->setSelectedIndex(0);
- }
- getChildView("color trans")->setEnabled(FALSE);
- getChildView("rptctrl")->setEnabled(FALSE);
- getChildView("tex gen")->setEnabled(FALSE);
- getChildView("label shininess")->setEnabled(FALSE);
- getChildView("label bumpiness")->setEnabled(FALSE);
- getChildView("button align")->setEnabled(FALSE);
- getChildView("pbr_from_inventory")->setEnabled(FALSE);
- getChildView("edit_selected_pbr")->setEnabled(FALSE);
- getChildView("save_selected_pbr")->setEnabled(FALSE);
-
- updateVisibility();
-
- // Set variable values for numeric expressions
- LLCalc* calcp = LLCalc::getInstance();
- calcp->clearVar(LLCalc::TEX_U_SCALE);
- calcp->clearVar(LLCalc::TEX_V_SCALE);
- calcp->clearVar(LLCalc::TEX_U_OFFSET);
- calcp->clearVar(LLCalc::TEX_V_OFFSET);
- calcp->clearVar(LLCalc::TEX_ROTATION);
- calcp->clearVar(LLCalc::TEX_TRANSPARENCY);
- calcp->clearVar(LLCalc::TEX_GLOW);
- }
-}
-
-// One-off listener that updates the build floater UI when the agent inventory adds or removes an item
-class PBRPickerAgentListener : public LLInventoryObserver
-{
-protected:
- bool mChangePending = true;
-public:
- PBRPickerAgentListener() : LLInventoryObserver()
- {
- gInventory.addObserver(this);
- }
-
- const bool isListening()
- {
- return mChangePending;
- }
-
- void changed(U32 mask) override
- {
- if (!(mask & (ADD | REMOVE)))
- {
- return;
- }
-
- if (gFloaterTools)
- {
- gFloaterTools->dirty();
- }
- gInventory.removeObserver(this);
- mChangePending = false;
- }
-
- ~PBRPickerAgentListener() override
- {
- gInventory.removeObserver(this);
- mChangePending = false;
- }
-};
-
-// One-off listener that updates the build floater UI when the prim inventory updates
-class PBRPickerObjectListener : public LLVOInventoryListener
-{
-protected:
- LLViewerObject* mObjectp;
- bool mChangePending = true;
-public:
-
- PBRPickerObjectListener(LLViewerObject* object)
- : mObjectp(object)
- {
- registerVOInventoryListener(mObjectp, nullptr);
- }
-
- const bool isListeningFor(const LLViewerObject* objectp) const
- {
- return mChangePending && (objectp == mObjectp);
- }
-
- void inventoryChanged(LLViewerObject* object,
- LLInventoryObject::object_list_t* inventory,
- S32 serial_num,
- void* user_data) override
- {
- if (gFloaterTools)
- {
- gFloaterTools->dirty();
- }
- removeVOInventoryListener();
- mChangePending = false;
- }
-
- ~PBRPickerObjectListener()
- {
- removeVOInventoryListener();
- mChangePending = false;
- }
-};
-
-void LLPanelFace::updateUIGLTF(LLViewerObject* objectp, bool& has_pbr_material, bool& has_faces_without_pbr, bool force_set_values)
-{
- has_pbr_material = false;
-
- bool has_pbr_capabilities = LLMaterialEditor::capabilitiesAvailable();
- bool identical_pbr = true;
- const bool settable = has_pbr_capabilities && objectp->permModify() && !objectp->isPermanentEnforced();
- const bool editable = LLMaterialEditor::canModifyObjectsMaterial();
- const bool saveable = LLMaterialEditor::canSaveObjectsMaterial();
-
- // pbr material
- LLTextureCtrl* pbr_ctrl = findChild<LLTextureCtrl>("pbr_control");
- LLUUID pbr_id;
- if (pbr_ctrl)
- {
- LLSelectedTE::getPbrMaterialId(pbr_id, identical_pbr, has_pbr_material, has_faces_without_pbr);
-
- pbr_ctrl->setTentative(identical_pbr ? FALSE : TRUE);
- pbr_ctrl->setEnabled(settable);
- pbr_ctrl->setImageAssetID(pbr_id);
-
- if (objectp->isAttachment())
- {
- pbr_ctrl->setFilterPermissionMasks(PERM_COPY | PERM_TRANSFER | PERM_MODIFY);
- }
- else
- {
- pbr_ctrl->setImmediateFilterPermMask(PERM_NONE);
- }
- }
-
- getChildView("pbr_from_inventory")->setEnabled(settable);
- getChildView("edit_selected_pbr")->setEnabled(editable && !has_faces_without_pbr);
- getChildView("save_selected_pbr")->setEnabled(saveable && identical_pbr);
- if (objectp->isInventoryPending())
- {
- // Reuse the same listener when possible
- if (!mVOInventoryListener || !mVOInventoryListener->isListeningFor(objectp))
- {
- mVOInventoryListener = std::make_unique<PBRPickerObjectListener>(objectp);
- }
- }
- else
- {
- mVOInventoryListener = nullptr;
- }
- if (!identical_pbr || pbr_id.isNull() || pbr_id == LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID)
- {
- mAgentInventoryListener = nullptr;
- }
- else
- {
- if (!mAgentInventoryListener || !mAgentInventoryListener->isListening())
- {
- mAgentInventoryListener = std::make_unique<PBRPickerAgentListener>();
- }
- }
-
- const bool show_pbr = mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR && mComboMatMedia->getEnabled();
- if (show_pbr)
- {
- const bool new_state = has_pbr_capabilities && has_pbr_material && !has_faces_without_pbr;
-
- LLUICtrl* gltfCtrlTextureScaleU = getChild<LLUICtrl>("gltfTextureScaleU");
- LLUICtrl* gltfCtrlTextureScaleV = getChild<LLUICtrl>("gltfTextureScaleV");
- LLUICtrl* gltfCtrlTextureRotation = getChild<LLUICtrl>("gltfTextureRotation");
- LLUICtrl* gltfCtrlTextureOffsetU = getChild<LLUICtrl>("gltfTextureOffsetU");
- LLUICtrl* gltfCtrlTextureOffsetV = getChild<LLUICtrl>("gltfTextureOffsetV");
-
- gltfCtrlTextureScaleU->setEnabled(new_state);
- gltfCtrlTextureScaleV->setEnabled(new_state);
- gltfCtrlTextureRotation->setEnabled(new_state);
- gltfCtrlTextureOffsetU->setEnabled(new_state);
- gltfCtrlTextureOffsetV->setEnabled(new_state);
-
- // Control values will be set once per frame in
- // setMaterialOverridesFromSelection
- sMaterialOverrideSelection.setDirty();
- }
-}
-
-void LLPanelFace::updateVisibilityGLTF(LLViewerObject* objectp /*= nullptr */)
-{
- const bool show_pbr = mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR && mComboMatMedia->getEnabled();
- const bool inventory_pending = objectp && objectp->isInventoryPending();
-
- LLRadioGroup* radio_pbr_type = findChild<LLRadioGroup>("radio_pbr_type");
- radio_pbr_type->setVisible(show_pbr);
-
- const U32 pbr_type = radio_pbr_type->getSelectedIndex();
- const bool show_pbr_render_material_id = show_pbr && (pbr_type == PBRTYPE_RENDER_MATERIAL_ID);
-
- getChildView("pbr_control")->setVisible(show_pbr_render_material_id);
-
- getChildView("pbr_from_inventory")->setVisible(show_pbr_render_material_id);
- getChildView("edit_selected_pbr")->setVisible(show_pbr_render_material_id && !inventory_pending);
- getChildView("save_selected_pbr")->setVisible(show_pbr_render_material_id && !inventory_pending);
- getChildView("material_permissions_loading_label")->setVisible(show_pbr_render_material_id && inventory_pending);
-
- getChildView("gltfTextureScaleU")->setVisible(show_pbr);
- getChildView("gltfTextureScaleV")->setVisible(show_pbr);
- getChildView("gltfTextureRotation")->setVisible(show_pbr);
- getChildView("gltfTextureOffsetU")->setVisible(show_pbr);
- getChildView("gltfTextureOffsetV")->setVisible(show_pbr);
-}
-
-void LLPanelFace::updateCopyTexButton()
-{
- LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
- mMenuClipboardTexture->setEnabled(objectp && objectp->getPCode() == LL_PCODE_VOLUME && objectp->permModify()
- && !objectp->isPermanentEnforced() && !objectp->isInventoryPending()
- && (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1)
- && LLMaterialEditor::canClipboardObjectsMaterial());
- std::string tooltip = (objectp && objectp->isInventoryPending()) ? LLTrans::getString("LoadingContents") : getString("paste_options");
- mMenuClipboardTexture->setToolTip(tooltip);
-}
-
-void LLPanelFace::refresh()
-{
- LL_DEBUGS("Materials") << LL_ENDL;
- getState();
-}
-
-void LLPanelFace::refreshMedia()
-{
- LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection();
- LLViewerObject* first_object = selected_objects->getFirstObject();
-
- if (!(first_object
- && first_object->getPCode() == LL_PCODE_VOLUME
- && first_object->permModify()
- ))
- {
- getChildView("add_media")->setEnabled(FALSE);
- mTitleMediaText->clear();
- clearMediaSettings();
- return;
- }
-
- std::string url = first_object->getRegion()->getCapability("ObjectMedia");
- bool has_media_capability = (!url.empty());
-
- if (!has_media_capability)
- {
- getChildView("add_media")->setEnabled(FALSE);
- LL_WARNS("LLFloaterToolsMedia") << "Media not enabled (no capability) in this region!" << LL_ENDL;
- clearMediaSettings();
- return;
- }
-
- BOOL is_nonpermanent_enforced = (LLSelectMgr::getInstance()->getSelection()->getFirstRootNode()
- && LLSelectMgr::getInstance()->selectGetRootsNonPermanentEnforced())
- || LLSelectMgr::getInstance()->selectGetNonPermanentEnforced();
- bool editable = is_nonpermanent_enforced && (first_object->permModify() || selectedMediaEditable());
-
- // Check modify permissions and whether any selected objects are in
- // the process of being fetched. If they are, then we're not editable
- if (editable)
- {
- LLObjectSelection::iterator iter = selected_objects->begin();
- LLObjectSelection::iterator end = selected_objects->end();
- for (; iter != end; ++iter)
- {
- LLSelectNode* node = *iter;
- LLVOVolume* object = dynamic_cast<LLVOVolume*>(node->getObject());
- if (NULL != object)
- {
- if (!object->permModify())
- {
- LL_INFOS("LLFloaterToolsMedia")
- << "Selection not editable due to lack of modify permissions on object id "
- << object->getID() << LL_ENDL;
-
- editable = false;
- break;
- }
- }
- }
- }
-
- // Media settings
- bool bool_has_media = false;
- struct media_functor : public LLSelectedTEGetFunctor<bool>
- {
- bool get(LLViewerObject* object, S32 face)
- {
- LLTextureEntry *te = object->getTE(face);
- if (te)
- {
- return te->hasMedia();
- }
- return false;
- }
- } func;
-
-
- // check if all faces have media(or, all dont have media)
- LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo = selected_objects->getSelectedTEValue(&func, bool_has_media);
-
- const LLMediaEntry default_media_data;
-
- struct functor_getter_media_data : public LLSelectedTEGetFunctor< LLMediaEntry>
- {
- functor_getter_media_data(const LLMediaEntry& entry) : mMediaEntry(entry) {}
-
- LLMediaEntry get(LLViewerObject* object, S32 face)
- {
- if (object)
- if (object->getTE(face))
- if (object->getTE(face)->getMediaData())
- return *(object->getTE(face)->getMediaData());
- return mMediaEntry;
- };
-
- const LLMediaEntry& mMediaEntry;
-
- } func_media_data(default_media_data);
-
- LLMediaEntry media_data_get;
- LLFloaterMediaSettings::getInstance()->mMultipleMedia = !(selected_objects->getSelectedTEValue(&func_media_data, media_data_get));
-
- std::string multi_media_info_str = LLTrans::getString("Multiple Media");
- std::string media_title = "";
- // update UI depending on whether "object" (prim or face) has media
- // and whether or not you are allowed to edit it.
-
- getChildView("add_media")->setEnabled(editable);
- // IF all the faces have media (or all dont have media)
- if (LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo)
- {
- // TODO: get media title and set it.
- mTitleMediaText->clear();
- // if identical is set, all faces are same (whether all empty or has the same media)
- if (!(LLFloaterMediaSettings::getInstance()->mMultipleMedia))
- {
- // Media data is valid
- if (media_data_get != default_media_data)
- {
- // initial media title is the media URL (until we get the name)
- media_title = media_data_get.getHomeURL();
- }
- // else all faces might be empty.
- }
- else // there' re Different Medias' been set on on the faces.
- {
- media_title = multi_media_info_str;
- }
-
- getChildView("delete_media")->setEnabled(bool_has_media && editable);
- // TODO: display a list of all media on the face - use 'identical' flag
- }
- else // not all face has media but at least one does.
- {
- // seleted faces have not identical value
- LLFloaterMediaSettings::getInstance()->mMultipleValidMedia = selected_objects->isMultipleTEValue(&func_media_data, default_media_data);
-
- if (LLFloaterMediaSettings::getInstance()->mMultipleValidMedia)
- {
- media_title = multi_media_info_str;
- }
- else
- {
- // Media data is valid
- if (media_data_get != default_media_data)
- {
- // initial media title is the media URL (until we get the name)
- media_title = media_data_get.getHomeURL();
- }
- }
-
- getChildView("delete_media")->setEnabled(TRUE);
- }
-
- U32 materials_media = mComboMatMedia->getCurrentIndex();
- if (materials_media == MATMEDIA_MEDIA)
- {
- // currently displaying media info, navigateTo and update title
- navigateToTitleMedia(media_title);
- }
- else
- {
- // Media can be heavy, don't keep it around
- // MAC specific: MAC doesn't support setVolume(0) so if not
- // unloaded, it might keep playing audio until user closes editor
- unloadMedia();
- mNeedMediaTitle = false;
- }
-
- mTitleMediaText->setText(media_title);
-
- // load values for media settings
- updateMediaSettings();
-
- LLFloaterMediaSettings::initValues(mMediaSettings, editable);
-}
-
-void LLPanelFace::unloadMedia()
-{
- // destroy media source used to grab media title
- if (mTitleMedia)
- mTitleMedia->unloadMediaSource();
-}
-
-// static
-void LLPanelFace::onMaterialOverrideReceived(const LLUUID& object_id, S32 side)
-{
- sMaterialOverrideSelection.onSelectedObjectUpdated(object_id, side);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-void LLPanelFace::navigateToTitleMedia( const std::string url )
-{
- std::string multi_media_info_str = LLTrans::getString("Multiple Media");
- if (url.empty() || multi_media_info_str == url)
- {
- // nothing to show
- mNeedMediaTitle = false;
- }
- else if (mTitleMedia)
- {
- LLPluginClassMedia* media_plugin = mTitleMedia->getMediaPlugin();
- // check if url changed or if we need a new media source
- if (mTitleMedia->getCurrentNavUrl() != url || media_plugin == NULL)
- {
- mTitleMedia->navigateTo( url );
-
- LLViewerMediaImpl* impl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(mTitleMedia->getTextureID());
- if (impl)
- {
- // if it's a page with a movie, we don't want to hear it
- impl->setVolume(0);
- };
- }
-
- // flag that we need to update the title (even if no request were made)
- mNeedMediaTitle = true;
- }
-}
-
-bool LLPanelFace::selectedMediaEditable()
-{
- U32 owner_mask_on;
- U32 owner_mask_off;
- U32 valid_owner_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_OWNER,
- &owner_mask_on, &owner_mask_off);
- U32 group_mask_on;
- U32 group_mask_off;
- U32 valid_group_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_GROUP,
- &group_mask_on, &group_mask_off);
- U32 everyone_mask_on;
- U32 everyone_mask_off;
- S32 valid_everyone_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_EVERYONE,
- &everyone_mask_on, &everyone_mask_off);
-
- bool selected_Media_editable = false;
-
- // if perms we got back are valid
- if (valid_owner_perms &&
- valid_group_perms &&
- valid_everyone_perms)
- {
-
- if ((owner_mask_on & PERM_MODIFY) ||
- (group_mask_on & PERM_MODIFY) ||
- (everyone_mask_on & PERM_MODIFY))
- {
- selected_Media_editable = true;
- }
- else
- // user is NOT allowed to press the RESET button
- {
- selected_Media_editable = false;
- };
- };
-
- return selected_Media_editable;
-}
-
-void LLPanelFace::clearMediaSettings()
-{
- LLFloaterMediaSettings::clearValues(false);
-}
-
-void LLPanelFace::updateMediaSettings()
-{
- bool identical(false);
- std::string base_key("");
- std::string value_str("");
- int value_int = 0;
- bool value_bool = false;
- LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection();
- // TODO: (CP) refactor this using something clever or boost or both !!
-
- const LLMediaEntry default_media_data;
-
- // controls
- U8 value_u8 = default_media_data.getControls();
- struct functor_getter_controls : public LLSelectedTEGetFunctor< U8 >
- {
- functor_getter_controls(const LLMediaEntry &entry) : mMediaEntry(entry) {}
-
- U8 get(LLViewerObject* object, S32 face)
- {
- if (object)
- if (object->getTE(face))
- if (object->getTE(face)->getMediaData())
- return object->getTE(face)->getMediaData()->getControls();
- return mMediaEntry.getControls();
- };
-
- const LLMediaEntry &mMediaEntry;
-
- } func_controls(default_media_data);
- identical = selected_objects->getSelectedTEValue(&func_controls, value_u8);
- base_key = std::string(LLMediaEntry::CONTROLS_KEY);
- mMediaSettings[base_key] = value_u8;
- mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
-
- // First click (formerly left click)
- value_bool = default_media_data.getFirstClickInteract();
- struct functor_getter_first_click : public LLSelectedTEGetFunctor< bool >
- {
- functor_getter_first_click(const LLMediaEntry& entry) : mMediaEntry(entry) {}
-
- bool get(LLViewerObject* object, S32 face)
- {
- if (object)
- if (object->getTE(face))
- if (object->getTE(face)->getMediaData())
- return object->getTE(face)->getMediaData()->getFirstClickInteract();
- return mMediaEntry.getFirstClickInteract();
- };
-
- const LLMediaEntry &mMediaEntry;
-
- } func_first_click(default_media_data);
- identical = selected_objects->getSelectedTEValue(&func_first_click, value_bool);
- base_key = std::string(LLMediaEntry::FIRST_CLICK_INTERACT_KEY);
- mMediaSettings[base_key] = value_bool;
- mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
-
- // Home URL
- value_str = default_media_data.getHomeURL();
- struct functor_getter_home_url : public LLSelectedTEGetFunctor< std::string >
- {
- functor_getter_home_url(const LLMediaEntry& entry) : mMediaEntry(entry) {}
-
- std::string get(LLViewerObject* object, S32 face)
- {
- if (object)
- if (object->getTE(face))
- if (object->getTE(face)->getMediaData())
- return object->getTE(face)->getMediaData()->getHomeURL();
- return mMediaEntry.getHomeURL();
- };
-
- const LLMediaEntry &mMediaEntry;
-
- } func_home_url(default_media_data);
- identical = selected_objects->getSelectedTEValue(&func_home_url, value_str);
- base_key = std::string(LLMediaEntry::HOME_URL_KEY);
- mMediaSettings[base_key] = value_str;
- mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
-
- // Current URL
- value_str = default_media_data.getCurrentURL();
- struct functor_getter_current_url : public LLSelectedTEGetFunctor< std::string >
- {
- functor_getter_current_url(const LLMediaEntry& entry) : mMediaEntry(entry) {}
-
- std::string get(LLViewerObject* object, S32 face)
- {
- if (object)
- if (object->getTE(face))
- if (object->getTE(face)->getMediaData())
- return object->getTE(face)->getMediaData()->getCurrentURL();
- return mMediaEntry.getCurrentURL();
- };
-
- const LLMediaEntry &mMediaEntry;
-
- } func_current_url(default_media_data);
- identical = selected_objects->getSelectedTEValue(&func_current_url, value_str);
- base_key = std::string(LLMediaEntry::CURRENT_URL_KEY);
- mMediaSettings[base_key] = value_str;
- mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
-
- // Auto zoom
- value_bool = default_media_data.getAutoZoom();
- struct functor_getter_auto_zoom : public LLSelectedTEGetFunctor< bool >
- {
-
- functor_getter_auto_zoom(const LLMediaEntry& entry) : mMediaEntry(entry) {}
-
- bool get(LLViewerObject* object, S32 face)
- {
- if (object)
- if (object->getTE(face))
- if (object->getTE(face)->getMediaData())
- return object->getTE(face)->getMediaData()->getAutoZoom();
- return mMediaEntry.getAutoZoom();
- };
-
- const LLMediaEntry &mMediaEntry;
-
- } func_auto_zoom(default_media_data);
- identical = selected_objects->getSelectedTEValue(&func_auto_zoom, value_bool);
- base_key = std::string(LLMediaEntry::AUTO_ZOOM_KEY);
- mMediaSettings[base_key] = value_bool;
- mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
-
- // Auto play
- //value_bool = default_media_data.getAutoPlay();
- // set default to auto play TRUE -- angela EXT-5172
- value_bool = true;
- struct functor_getter_auto_play : public LLSelectedTEGetFunctor< bool >
- {
- functor_getter_auto_play(const LLMediaEntry& entry) : mMediaEntry(entry) {}
-
- bool get(LLViewerObject* object, S32 face)
- {
- if (object)
- if (object->getTE(face))
- if (object->getTE(face)->getMediaData())
- return object->getTE(face)->getMediaData()->getAutoPlay();
- //return mMediaEntry.getAutoPlay(); set default to auto play TRUE -- angela EXT-5172
- return true;
- };
-
- const LLMediaEntry &mMediaEntry;
-
- } func_auto_play(default_media_data);
- identical = selected_objects->getSelectedTEValue(&func_auto_play, value_bool);
- base_key = std::string(LLMediaEntry::AUTO_PLAY_KEY);
- mMediaSettings[base_key] = value_bool;
- mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
-
-
- // Auto scale
- // set default to auto scale TRUE -- angela EXT-5172
- //value_bool = default_media_data.getAutoScale();
- value_bool = true;
- struct functor_getter_auto_scale : public LLSelectedTEGetFunctor< bool >
- {
- functor_getter_auto_scale(const LLMediaEntry& entry) : mMediaEntry(entry) {}
-
- bool get(LLViewerObject* object, S32 face)
- {
- if (object)
- if (object->getTE(face))
- if (object->getTE(face)->getMediaData())
- return object->getTE(face)->getMediaData()->getAutoScale();
- // return mMediaEntry.getAutoScale(); set default to auto scale TRUE -- angela EXT-5172
- return true;
- };
-
- const LLMediaEntry &mMediaEntry;
-
- } func_auto_scale(default_media_data);
- identical = selected_objects->getSelectedTEValue(&func_auto_scale, value_bool);
- base_key = std::string(LLMediaEntry::AUTO_SCALE_KEY);
- mMediaSettings[base_key] = value_bool;
- mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
-
- // Auto loop
- value_bool = default_media_data.getAutoLoop();
- struct functor_getter_auto_loop : public LLSelectedTEGetFunctor< bool >
- {
- functor_getter_auto_loop(const LLMediaEntry& entry) : mMediaEntry(entry) {}
-
- bool get(LLViewerObject* object, S32 face)
- {
- if (object)
- if (object->getTE(face))
- if (object->getTE(face)->getMediaData())
- return object->getTE(face)->getMediaData()->getAutoLoop();
- return mMediaEntry.getAutoLoop();
- };
-
- const LLMediaEntry &mMediaEntry;
-
- } func_auto_loop(default_media_data);
- identical = selected_objects->getSelectedTEValue(&func_auto_loop, value_bool);
- base_key = std::string(LLMediaEntry::AUTO_LOOP_KEY);
- mMediaSettings[base_key] = value_bool;
- mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
-
- // width pixels (if not auto scaled)
- value_int = default_media_data.getWidthPixels();
- struct functor_getter_width_pixels : public LLSelectedTEGetFunctor< int >
- {
- functor_getter_width_pixels(const LLMediaEntry& entry) : mMediaEntry(entry) {}
-
- int get(LLViewerObject* object, S32 face)
- {
- if (object)
- if (object->getTE(face))
- if (object->getTE(face)->getMediaData())
- return object->getTE(face)->getMediaData()->getWidthPixels();
- return mMediaEntry.getWidthPixels();
- };
-
- const LLMediaEntry &mMediaEntry;
-
- } func_width_pixels(default_media_data);
- identical = selected_objects->getSelectedTEValue(&func_width_pixels, value_int);
- base_key = std::string(LLMediaEntry::WIDTH_PIXELS_KEY);
- mMediaSettings[base_key] = value_int;
- mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
-
- // height pixels (if not auto scaled)
- value_int = default_media_data.getHeightPixels();
- struct functor_getter_height_pixels : public LLSelectedTEGetFunctor< int >
- {
- functor_getter_height_pixels(const LLMediaEntry& entry) : mMediaEntry(entry) {}
-
- int get(LLViewerObject* object, S32 face)
- {
- if (object)
- if (object->getTE(face))
- if (object->getTE(face)->getMediaData())
- return object->getTE(face)->getMediaData()->getHeightPixels();
- return mMediaEntry.getHeightPixels();
- };
-
- const LLMediaEntry &mMediaEntry;
-
- } func_height_pixels(default_media_data);
- identical = selected_objects->getSelectedTEValue(&func_height_pixels, value_int);
- base_key = std::string(LLMediaEntry::HEIGHT_PIXELS_KEY);
- mMediaSettings[base_key] = value_int;
- mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
-
- // Enable Alt image
- value_bool = default_media_data.getAltImageEnable();
- struct functor_getter_enable_alt_image : public LLSelectedTEGetFunctor< bool >
- {
- functor_getter_enable_alt_image(const LLMediaEntry& entry) : mMediaEntry(entry) {}
-
- bool get(LLViewerObject* object, S32 face)
- {
- if (object)
- if (object->getTE(face))
- if (object->getTE(face)->getMediaData())
- return object->getTE(face)->getMediaData()->getAltImageEnable();
- return mMediaEntry.getAltImageEnable();
- };
-
- const LLMediaEntry &mMediaEntry;
-
- } func_enable_alt_image(default_media_data);
- identical = selected_objects->getSelectedTEValue(&func_enable_alt_image, value_bool);
- base_key = std::string(LLMediaEntry::ALT_IMAGE_ENABLE_KEY);
- mMediaSettings[base_key] = value_bool;
- mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
-
- // Perms - owner interact
- value_bool = 0 != (default_media_data.getPermsInteract() & LLMediaEntry::PERM_OWNER);
- struct functor_getter_perms_owner_interact : public LLSelectedTEGetFunctor< bool >
- {
- functor_getter_perms_owner_interact(const LLMediaEntry& entry) : mMediaEntry(entry) {}
-
- bool get(LLViewerObject* object, S32 face)
- {
- if (object)
- if (object->getTE(face))
- if (object->getTE(face)->getMediaData())
- return (0 != (object->getTE(face)->getMediaData()->getPermsInteract() & LLMediaEntry::PERM_OWNER));
- return 0 != (mMediaEntry.getPermsInteract() & LLMediaEntry::PERM_OWNER);
- };
-
- const LLMediaEntry &mMediaEntry;
-
- } func_perms_owner_interact(default_media_data);
- identical = selected_objects->getSelectedTEValue(&func_perms_owner_interact, value_bool);
- base_key = std::string(LLPanelContents::PERMS_OWNER_INTERACT_KEY);
- mMediaSettings[base_key] = value_bool;
- mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
-
- // Perms - owner control
- value_bool = 0 != (default_media_data.getPermsControl() & LLMediaEntry::PERM_OWNER);
- struct functor_getter_perms_owner_control : public LLSelectedTEGetFunctor< bool >
- {
- functor_getter_perms_owner_control(const LLMediaEntry& entry) : mMediaEntry(entry) {}
-
- bool get(LLViewerObject* object, S32 face)
- {
- if (object)
- if (object->getTE(face))
- if (object->getTE(face)->getMediaData())
- return (0 != (object->getTE(face)->getMediaData()->getPermsControl() & LLMediaEntry::PERM_OWNER));
- return 0 != (mMediaEntry.getPermsControl() & LLMediaEntry::PERM_OWNER);
- };
-
- const LLMediaEntry &mMediaEntry;
-
- } func_perms_owner_control(default_media_data);
- identical = selected_objects->getSelectedTEValue(&func_perms_owner_control, value_bool);
- base_key = std::string(LLPanelContents::PERMS_OWNER_CONTROL_KEY);
- mMediaSettings[base_key] = value_bool;
- mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
-
- // Perms - group interact
- value_bool = 0 != (default_media_data.getPermsInteract() & LLMediaEntry::PERM_GROUP);
- struct functor_getter_perms_group_interact : public LLSelectedTEGetFunctor< bool >
- {
- functor_getter_perms_group_interact(const LLMediaEntry& entry) : mMediaEntry(entry) {}
-
- bool get(LLViewerObject* object, S32 face)
- {
- if (object)
- if (object->getTE(face))
- if (object->getTE(face)->getMediaData())
- return (0 != (object->getTE(face)->getMediaData()->getPermsInteract() & LLMediaEntry::PERM_GROUP));
- return 0 != (mMediaEntry.getPermsInteract() & LLMediaEntry::PERM_GROUP);
- };
-
- const LLMediaEntry &mMediaEntry;
-
- } func_perms_group_interact(default_media_data);
- identical = selected_objects->getSelectedTEValue(&func_perms_group_interact, value_bool);
- base_key = std::string(LLPanelContents::PERMS_GROUP_INTERACT_KEY);
- mMediaSettings[base_key] = value_bool;
- mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
-
- // Perms - group control
- value_bool = 0 != (default_media_data.getPermsControl() & LLMediaEntry::PERM_GROUP);
- struct functor_getter_perms_group_control : public LLSelectedTEGetFunctor< bool >
- {
- functor_getter_perms_group_control(const LLMediaEntry& entry) : mMediaEntry(entry) {}
-
- bool get(LLViewerObject* object, S32 face)
- {
- if (object)
- if (object->getTE(face))
- if (object->getTE(face)->getMediaData())
- return (0 != (object->getTE(face)->getMediaData()->getPermsControl() & LLMediaEntry::PERM_GROUP));
- return 0 != (mMediaEntry.getPermsControl() & LLMediaEntry::PERM_GROUP);
- };
-
- const LLMediaEntry &mMediaEntry;
-
- } func_perms_group_control(default_media_data);
- identical = selected_objects->getSelectedTEValue(&func_perms_group_control, value_bool);
- base_key = std::string(LLPanelContents::PERMS_GROUP_CONTROL_KEY);
- mMediaSettings[base_key] = value_bool;
- mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
-
- // Perms - anyone interact
- value_bool = 0 != (default_media_data.getPermsInteract() & LLMediaEntry::PERM_ANYONE);
- struct functor_getter_perms_anyone_interact : public LLSelectedTEGetFunctor< bool >
- {
- functor_getter_perms_anyone_interact(const LLMediaEntry& entry) : mMediaEntry(entry) {}
-
- bool get(LLViewerObject* object, S32 face)
- {
- if (object)
- if (object->getTE(face))
- if (object->getTE(face)->getMediaData())
- return (0 != (object->getTE(face)->getMediaData()->getPermsInteract() & LLMediaEntry::PERM_ANYONE));
- return 0 != (mMediaEntry.getPermsInteract() & LLMediaEntry::PERM_ANYONE);
- };
-
- const LLMediaEntry &mMediaEntry;
-
- } func_perms_anyone_interact(default_media_data);
- identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&func_perms_anyone_interact, value_bool);
- base_key = std::string(LLPanelContents::PERMS_ANYONE_INTERACT_KEY);
- mMediaSettings[base_key] = value_bool;
- mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
-
- // Perms - anyone control
- value_bool = 0 != (default_media_data.getPermsControl() & LLMediaEntry::PERM_ANYONE);
- struct functor_getter_perms_anyone_control : public LLSelectedTEGetFunctor< bool >
- {
- functor_getter_perms_anyone_control(const LLMediaEntry& entry) : mMediaEntry(entry) {}
-
- bool get(LLViewerObject* object, S32 face)
- {
- if (object)
- if (object->getTE(face))
- if (object->getTE(face)->getMediaData())
- return (0 != (object->getTE(face)->getMediaData()->getPermsControl() & LLMediaEntry::PERM_ANYONE));
- return 0 != (mMediaEntry.getPermsControl() & LLMediaEntry::PERM_ANYONE);
- };
-
- const LLMediaEntry &mMediaEntry;
-
- } func_perms_anyone_control(default_media_data);
- identical = selected_objects->getSelectedTEValue(&func_perms_anyone_control, value_bool);
- base_key = std::string(LLPanelContents::PERMS_ANYONE_CONTROL_KEY);
- mMediaSettings[base_key] = value_bool;
- mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
-
- // security - whitelist enable
- value_bool = default_media_data.getWhiteListEnable();
- struct functor_getter_whitelist_enable : public LLSelectedTEGetFunctor< bool >
- {
- functor_getter_whitelist_enable(const LLMediaEntry& entry) : mMediaEntry(entry) {}
-
- bool get(LLViewerObject* object, S32 face)
- {
- if (object)
- if (object->getTE(face))
- if (object->getTE(face)->getMediaData())
- return object->getTE(face)->getMediaData()->getWhiteListEnable();
- return mMediaEntry.getWhiteListEnable();
- };
-
- const LLMediaEntry &mMediaEntry;
-
- } func_whitelist_enable(default_media_data);
- identical = selected_objects->getSelectedTEValue(&func_whitelist_enable, value_bool);
- base_key = std::string(LLMediaEntry::WHITELIST_ENABLE_KEY);
- mMediaSettings[base_key] = value_bool;
- mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
-
- // security - whitelist URLs
- std::vector<std::string> value_vector_str = default_media_data.getWhiteList();
- struct functor_getter_whitelist_urls : public LLSelectedTEGetFunctor< std::vector<std::string> >
- {
- functor_getter_whitelist_urls(const LLMediaEntry& entry) : mMediaEntry(entry) {}
-
- std::vector<std::string> get(LLViewerObject* object, S32 face)
- {
- if (object)
- if (object->getTE(face))
- if (object->getTE(face)->getMediaData())
- return object->getTE(face)->getMediaData()->getWhiteList();
- return mMediaEntry.getWhiteList();
- };
-
- const LLMediaEntry &mMediaEntry;
-
- } func_whitelist_urls(default_media_data);
- identical = selected_objects->getSelectedTEValue(&func_whitelist_urls, value_vector_str);
- base_key = std::string(LLMediaEntry::WHITELIST_KEY);
- mMediaSettings[base_key].clear();
- std::vector< std::string >::iterator iter = value_vector_str.begin();
- while (iter != value_vector_str.end())
- {
- std::string white_list_url = *iter;
- mMediaSettings[base_key].append(white_list_url);
- ++iter;
- };
-
- mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
-}
-
-void LLPanelFace::updateMediaTitle()
-{
- // only get the media name if we need it
- if (!mNeedMediaTitle)
- return;
-
- // get plugin impl
- LLPluginClassMedia* media_plugin = mTitleMedia->getMediaPlugin();
- if (media_plugin && mTitleMedia->getCurrentNavUrl() == media_plugin->getNavigateURI())
- {
- // get the media name (asynchronous - must call repeatedly)
- std::string media_title = media_plugin->getMediaName();
-
- // only replace the title if what we get contains something
- if (!media_title.empty())
- {
- // update the UI widget
- if (mTitleMediaText)
- {
- mTitleMediaText->setText(media_title);
-
- // stop looking for a title when we get one
- mNeedMediaTitle = false;
- };
- };
- };
-}
-
-//
-// Static functions
-//
-
-// static
-F32 LLPanelFace::valueGlow(LLViewerObject* object, S32 face)
-{
- return (F32)(object->getTE(face)->getGlow());
-}
-
-
-void LLPanelFace::onCommitColor(const LLSD& data)
-{
- sendColor();
-}
-
-void LLPanelFace::onCommitShinyColor(const LLSD& data)
-{
- LLSelectedTEMaterial::setSpecularLightColor(this, getChild<LLColorSwatchCtrl>("shinycolorswatch")->get());
-}
-
-void LLPanelFace::onCommitAlpha(const LLSD& data)
-{
- sendAlpha();
-}
-
-void LLPanelFace::onCancelColor(const LLSD& data)
-{
- LLSelectMgr::getInstance()->selectionRevertColors();
-}
-
-void LLPanelFace::onCancelShinyColor(const LLSD& data)
-{
- LLSelectMgr::getInstance()->selectionRevertShinyColors();
-}
-
-void LLPanelFace::onSelectColor(const LLSD& data)
-{
- LLSelectMgr::getInstance()->saveSelectedObjectColors();
- sendColor();
-}
-
-void LLPanelFace::onSelectShinyColor(const LLSD& data)
-{
- LLSelectedTEMaterial::setSpecularLightColor(this, getChild<LLColorSwatchCtrl>("shinycolorswatch")->get());
- LLSelectMgr::getInstance()->saveSelectedShinyColors();
-}
-
-// static
-void LLPanelFace::onCommitMaterialsMedia(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- // Force to default states to side-step problems with menu contents
- // and generally reflecting old state when switching tabs or objects
- //
- self->updateShinyControls(false,true);
- self->updateBumpyControls(false,true);
- self->updateUI();
- self->refreshMedia();
-}
-
-void LLPanelFace::updateVisibility(LLViewerObject* objectp /* = nullptr */)
-{
- LLRadioGroup* radio_mat_type = findChild<LLRadioGroup>("radio_material_type");
- LLRadioGroup* radio_pbr_type = findChild<LLRadioGroup>("radio_pbr_type");
- LLComboBox* combo_shininess = findChild<LLComboBox>("combobox shininess");
- LLComboBox* combo_bumpiness = findChild<LLComboBox>("combobox bumpiness");
- if (!radio_mat_type || !radio_pbr_type || !mComboMatMedia || !combo_shininess || !combo_bumpiness)
- {
- LL_WARNS("Materials") << "Combo box not found...exiting." << LL_ENDL;
- return;
- }
- U32 materials_media = mComboMatMedia->getCurrentIndex();
- U32 material_type = radio_mat_type->getSelectedIndex();
- bool show_media = (materials_media == MATMEDIA_MEDIA) && mComboMatMedia->getEnabled();
- bool show_material = materials_media == MATMEDIA_MATERIAL;
- bool show_texture = (show_media || (show_material && (material_type == MATTYPE_DIFFUSE) && mComboMatMedia->getEnabled()));
- bool show_bumpiness = show_material && (material_type == MATTYPE_NORMAL) && mComboMatMedia->getEnabled();
- bool show_shininess = show_material && (material_type == MATTYPE_SPECULAR) && mComboMatMedia->getEnabled();
- const bool show_pbr = mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR && mComboMatMedia->getEnabled();
- const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
- const LLGLTFMaterial::TextureInfo texture_info = texture_info_from_pbrtype(pbr_type);
- const bool show_pbr_asset = show_pbr && texture_info == LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT;
-
- radio_mat_type->setVisible(show_material);
-
- // Shared material controls
- getChildView("checkbox_sync_settings")->setVisible(show_material || show_media);
- getChildView("tex gen")->setVisible(show_material || show_media || show_pbr_asset);
- getChildView("combobox texgen")->setVisible(show_material || show_media || show_pbr_asset);
- getChildView("button align textures")->setVisible(show_material || show_media);
-
- // Media controls
- mTitleMediaText->setVisible(show_media);
- getChildView("add_media")->setVisible(show_media);
- getChildView("delete_media")->setVisible(show_media);
- getChildView("button align")->setVisible(show_media);
-
- // Diffuse texture controls
- getChildView("texture control")->setVisible(show_texture && show_material);
- getChildView("label alphamode")->setVisible(show_texture && show_material);
- getChildView("combobox alphamode")->setVisible(show_texture && show_material);
- getChildView("label maskcutoff")->setVisible(false);
- getChildView("maskcutoff")->setVisible(false);
- if (show_texture && show_material)
- {
- updateAlphaControls();
- }
- // texture scale and position controls
- getChildView("TexScaleU")->setVisible(show_texture);
- getChildView("TexScaleV")->setVisible(show_texture);
- getChildView("TexRot")->setVisible(show_texture);
- getChildView("TexOffsetU")->setVisible(show_texture);
- getChildView("TexOffsetV")->setVisible(show_texture);
-
- // Specular map controls
- getChildView("shinytexture control")->setVisible(show_shininess);
- getChildView("combobox shininess")->setVisible(show_shininess);
- getChildView("label shininess")->setVisible(show_shininess);
- getChildView("label glossiness")->setVisible(false);
- getChildView("glossiness")->setVisible(false);
- getChildView("label environment")->setVisible(false);
- getChildView("environment")->setVisible(false);
- getChildView("label shinycolor")->setVisible(false);
- getChildView("shinycolorswatch")->setVisible(false);
- if (show_shininess)
- {
- updateShinyControls();
- }
- getChildView("shinyScaleU")->setVisible(show_shininess);
- getChildView("shinyScaleV")->setVisible(show_shininess);
- getChildView("shinyRot")->setVisible(show_shininess);
- getChildView("shinyOffsetU")->setVisible(show_shininess);
- getChildView("shinyOffsetV")->setVisible(show_shininess);
-
- // Normal map controls
- if (show_bumpiness)
- {
- updateBumpyControls();
- }
- getChildView("bumpytexture control")->setVisible(show_bumpiness);
- getChildView("combobox bumpiness")->setVisible(show_bumpiness);
- getChildView("label bumpiness")->setVisible(show_bumpiness);
- getChildView("bumpyScaleU")->setVisible(show_bumpiness);
- getChildView("bumpyScaleV")->setVisible(show_bumpiness);
- getChildView("bumpyRot")->setVisible(show_bumpiness);
- getChildView("bumpyOffsetU")->setVisible(show_bumpiness);
- getChildView("bumpyOffsetV")->setVisible(show_bumpiness);
-
- getChild<LLSpinCtrl>("rptctrl")->setVisible(show_material || show_media);
-
- // PBR controls
- updateVisibilityGLTF(objectp);
-}
-
-// static
-void LLPanelFace::onCommitMaterialType(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- // Force to default states to side-step problems with menu contents
- // and generally reflecting old state when switching tabs or objects
- //
- self->updateShinyControls(false,true);
- self->updateBumpyControls(false,true);
- self->updateUI();
-}
-
-// static
-void LLPanelFace::onCommitPbrType(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*)userdata;
- // Force to default states to side-step problems with menu contents
- // and generally reflecting old state when switching tabs or objects
- //
- self->updateUI();
-}
-
-// static
-void LLPanelFace::onCommitBump(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
-
- LLComboBox* mComboBumpiness = self->getChild<LLComboBox>("combobox bumpiness");
- if(!mComboBumpiness)
- return;
-
- U32 bumpiness = mComboBumpiness->getCurrentIndex();
-
- self->sendBump(bumpiness);
-}
-
-// static
-void LLPanelFace::onCommitTexGen(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- self->sendTexGen();
-}
-
-// static
-void LLPanelFace::updateShinyControls(bool is_setting_texture, bool mess_with_shiny_combobox)
-{
- LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>("shinytexture control");
- LLUUID shiny_texture_ID = texture_ctrl->getImageAssetID();
- LL_DEBUGS("Materials") << "Shiny texture selected: " << shiny_texture_ID << LL_ENDL;
- LLComboBox* comboShiny = getChild<LLComboBox>("combobox shininess");
-
- if(mess_with_shiny_combobox)
- {
- if (!comboShiny)
- {
- return;
- }
- if (!shiny_texture_ID.isNull() && is_setting_texture)
- {
- if (!comboShiny->itemExists(USE_TEXTURE))
- {
- comboShiny->add(USE_TEXTURE);
- }
- comboShiny->setSimple(USE_TEXTURE);
- }
- else
- {
- if (comboShiny->itemExists(USE_TEXTURE))
- {
- comboShiny->remove(SHINY_TEXTURE);
- comboShiny->selectFirstItem();
- }
- }
- }
- else
- {
- if (shiny_texture_ID.isNull() && comboShiny && comboShiny->itemExists(USE_TEXTURE))
- {
- comboShiny->remove(SHINY_TEXTURE);
- comboShiny->selectFirstItem();
- }
- }
-
-
- LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type");
- U32 materials_media = mComboMatMedia->getCurrentIndex();
- U32 material_type = radio_mat_type->getSelectedIndex();
- bool show_material = (materials_media == MATMEDIA_MATERIAL);
- bool show_shininess = show_material && (material_type == MATTYPE_SPECULAR) && mComboMatMedia->getEnabled();
- U32 shiny_value = comboShiny->getCurrentIndex();
- bool show_shinyctrls = (shiny_value == SHINY_TEXTURE) && show_shininess; // Use texture
- getChildView("label glossiness")->setVisible(show_shinyctrls);
- getChildView("glossiness")->setVisible(show_shinyctrls);
- getChildView("label environment")->setVisible(show_shinyctrls);
- getChildView("environment")->setVisible(show_shinyctrls);
- getChildView("label shinycolor")->setVisible(show_shinyctrls);
- getChildView("shinycolorswatch")->setVisible(show_shinyctrls);
-}
-
-// static
-void LLPanelFace::updateBumpyControls(bool is_setting_texture, bool mess_with_combobox)
-{
- LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>("bumpytexture control");
- LLUUID bumpy_texture_ID = texture_ctrl->getImageAssetID();
- LL_DEBUGS("Materials") << "texture: " << bumpy_texture_ID << (mess_with_combobox ? "" : " do not") << " update combobox" << LL_ENDL;
- LLComboBox* comboBumpy = getChild<LLComboBox>("combobox bumpiness");
- if (!comboBumpy)
- {
- return;
- }
-
- if (mess_with_combobox)
- {
- LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>("bumpytexture control");
- LLUUID bumpy_texture_ID = texture_ctrl->getImageAssetID();
- LL_DEBUGS("Materials") << "texture: " << bumpy_texture_ID << (mess_with_combobox ? "" : " do not") << " update combobox" << LL_ENDL;
-
- if (!bumpy_texture_ID.isNull() && is_setting_texture)
- {
- if (!comboBumpy->itemExists(USE_TEXTURE))
- {
- comboBumpy->add(USE_TEXTURE);
- }
- comboBumpy->setSimple(USE_TEXTURE);
- }
- else
- {
- if (comboBumpy->itemExists(USE_TEXTURE))
- {
- comboBumpy->remove(BUMPY_TEXTURE);
- comboBumpy->selectFirstItem();
- }
- }
- }
-}
-
-// static
-void LLPanelFace::onCommitShiny(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
-
-
- LLComboBox* mComboShininess = self->getChild<LLComboBox>("combobox shininess");
- if(!mComboShininess)
- return;
-
- U32 shininess = mComboShininess->getCurrentIndex();
-
- self->sendShiny(shininess);
-}
-
-// static
-void LLPanelFace::updateAlphaControls()
-{
- LLComboBox* comboAlphaMode = getChild<LLComboBox>("combobox alphamode");
- if (!comboAlphaMode)
- {
- return;
- }
- U32 alpha_value = comboAlphaMode->getCurrentIndex();
- bool show_alphactrls = (alpha_value == ALPHAMODE_MASK); // Alpha masking
-
- U32 mat_media = MATMEDIA_MATERIAL;
- if (mComboMatMedia)
- {
- mat_media = mComboMatMedia->getCurrentIndex();
- }
-
- U32 mat_type = MATTYPE_DIFFUSE;
- LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type");
- if(radio_mat_type)
- {
- mat_type = radio_mat_type->getSelectedIndex();
- }
-
- show_alphactrls = show_alphactrls && (mat_media == MATMEDIA_MATERIAL);
- show_alphactrls = show_alphactrls && (mat_type == MATTYPE_DIFFUSE);
-
- getChildView("label maskcutoff")->setVisible(show_alphactrls);
- getChildView("maskcutoff")->setVisible(show_alphactrls);
-}
-
-// static
-void LLPanelFace::onCommitAlphaMode(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- self->updateAlphaControls();
- LLSelectedTEMaterial::setDiffuseAlphaMode(self,self->getCurrentDiffuseAlphaMode());
-}
-
-// static
-void LLPanelFace::onCommitFullbright(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- self->sendFullbright();
-}
-
-// static
-void LLPanelFace::onCommitGlow(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- self->sendGlow();
-}
-
-// static
-BOOL LLPanelFace::onDragPbr(LLUICtrl*, LLInventoryItem* item)
-{
- BOOL accept = TRUE;
- for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
- iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
- {
- LLSelectNode* node = *iter;
- LLViewerObject* obj = node->getObject();
- if (!LLToolDragAndDrop::isInventoryDropAcceptable(obj, item))
- {
- accept = FALSE;
- break;
- }
- }
- return accept;
-}
-
-void LLPanelFace::onCommitPbr(const LLSD& data)
-{
- LLTextureCtrl* pbr_ctrl = findChild<LLTextureCtrl>("pbr_control");
- if (!pbr_ctrl) return;
- if (!pbr_ctrl->getTentative())
- {
- // we grab the item id first, because we want to do a
- // permissions check in the selection manager. ARGH!
- LLUUID id = pbr_ctrl->getImageItemID();
- if (id.isNull())
- {
- id = pbr_ctrl->getImageAssetID();
- }
- if (!LLSelectMgr::getInstance()->selectionSetGLTFMaterial(id))
- {
- // If failed to set material, refresh pbr_ctrl's value
- refresh();
- }
- }
-}
-
-void LLPanelFace::onCancelPbr(const LLSD& data)
-{
- LLSelectMgr::getInstance()->selectionRevertGLTFMaterials();
-}
-
-void LLPanelFace::onSelectPbr(const LLSD& data)
-{
- LLSelectMgr::getInstance()->saveSelectedObjectTextures();
-
- LLTextureCtrl* pbr_ctrl = findChild<LLTextureCtrl>("pbr_control");
- if (!pbr_ctrl) return;
- if (!pbr_ctrl->getTentative())
- {
- // we grab the item id first, because we want to do a
- // permissions check in the selection manager. ARGH!
- LLUUID id = pbr_ctrl->getImageItemID();
- if (id.isNull())
- {
- id = pbr_ctrl->getImageAssetID();
- }
- if (!LLSelectMgr::getInstance()->selectionSetGLTFMaterial(id))
- {
- refresh();
- }
- }
-}
-
-// static
-BOOL LLPanelFace::onDragTexture(LLUICtrl*, LLInventoryItem* item)
-{
- BOOL accept = TRUE;
- for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
- iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
- {
- LLSelectNode* node = *iter;
- LLViewerObject* obj = node->getObject();
- if (!LLToolDragAndDrop::isInventoryDropAcceptable(obj, item))
- {
- accept = FALSE;
- break;
- }
- }
- return accept;
-}
-
-void LLPanelFace::onCommitTexture( const LLSD& data )
-{
- add(LLStatViewer::EDIT_TEXTURE, 1);
- sendTexture();
-}
-
-void LLPanelFace::onCancelTexture(const LLSD& data)
-{
- LLSelectMgr::getInstance()->selectionRevertTextures();
-}
-
-void LLPanelFace::onSelectTexture(const LLSD& data)
-{
- LLSelectMgr::getInstance()->saveSelectedObjectTextures();
- sendTexture();
-
- LLGLenum image_format;
- bool identical_image_format = false;
- LLSelectedTE::getImageFormat(image_format, identical_image_format);
-
- LLCtrlSelectionInterface* combobox_alphamode =
- childGetSelectionInterface("combobox alphamode");
-
- U32 alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_NONE;
- if (combobox_alphamode)
- {
- switch (image_format)
- {
- case GL_RGBA:
- case GL_ALPHA:
- {
- alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND;
- }
- break;
-
- case GL_RGB: break;
- default:
- {
- LL_WARNS() << "Unexpected tex format in LLPanelFace...resorting to no alpha" << LL_ENDL;
- }
- break;
- }
-
- combobox_alphamode->selectNthItem(alpha_mode);
- }
- LLSelectedTEMaterial::setDiffuseAlphaMode(this, getCurrentDiffuseAlphaMode());
-}
-
-void LLPanelFace::onCloseTexturePicker(const LLSD& data)
-{
- LL_DEBUGS("Materials") << data << LL_ENDL;
- updateUI();
-}
-
-void LLPanelFace::onCommitSpecularTexture( const LLSD& data )
-{
- LL_DEBUGS("Materials") << data << LL_ENDL;
- sendShiny(SHINY_TEXTURE);
-}
-
-void LLPanelFace::onCommitNormalTexture( const LLSD& data )
-{
- LL_DEBUGS("Materials") << data << LL_ENDL;
- LLUUID nmap_id = getCurrentNormalMap();
- sendBump(nmap_id.isNull() ? 0 : BUMPY_TEXTURE);
-}
-
-void LLPanelFace::onCancelSpecularTexture(const LLSD& data)
-{
- U8 shiny = 0;
- bool identical_shiny = false;
- LLSelectedTE::getShiny(shiny, identical_shiny);
- LLUUID spec_map_id = getChild<LLTextureCtrl>("shinytexture control")->getImageAssetID();
- shiny = spec_map_id.isNull() ? shiny : SHINY_TEXTURE;
- sendShiny(shiny);
-}
-
-void LLPanelFace::onCancelNormalTexture(const LLSD& data)
-{
- U8 bumpy = 0;
- bool identical_bumpy = false;
- LLSelectedTE::getBumpmap(bumpy, identical_bumpy);
- LLUUID spec_map_id = getChild<LLTextureCtrl>("bumpytexture control")->getImageAssetID();
- bumpy = spec_map_id.isNull() ? bumpy : BUMPY_TEXTURE;
- sendBump(bumpy);
-}
-
-void LLPanelFace::onSelectSpecularTexture(const LLSD& data)
-{
- LL_DEBUGS("Materials") << data << LL_ENDL;
- sendShiny(SHINY_TEXTURE);
-}
-
-void LLPanelFace::onSelectNormalTexture(const LLSD& data)
-{
- LL_DEBUGS("Materials") << data << LL_ENDL;
- LLUUID nmap_id = getCurrentNormalMap();
- sendBump(nmap_id.isNull() ? 0 : BUMPY_TEXTURE);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// called when a user wants to edit existing media settings on a prim or prim face
-// TODO: test if there is media on the item and only allow editing if present
-void LLPanelFace::onClickBtnEditMedia(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*)userdata;
- self->refreshMedia();
- LLFloaterReg::showInstance("media_settings");
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// called when a user wants to delete media from a prim or prim face
-void LLPanelFace::onClickBtnDeleteMedia(LLUICtrl* ctrl, void* userdata)
-{
- LLNotificationsUtil::add("DeleteMedia", LLSD(), LLSD(), deleteMediaConfirm);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// called when a user wants to add media to a prim or prim face
-void LLPanelFace::onClickBtnAddMedia(LLUICtrl* ctrl, void* userdata)
-{
- // check if multiple faces are selected
- if (LLSelectMgr::getInstance()->getSelection()->isMultipleTESelected())
- {
- LLPanelFace* self = (LLPanelFace*)userdata;
- self->refreshMedia();
- LLNotificationsUtil::add("MultipleFacesSelected", LLSD(), LLSD(), multipleFacesSelectedConfirm);
- }
- else
- {
- onClickBtnEditMedia(ctrl, userdata);
- }
-}
-
-// static
-bool LLPanelFace::deleteMediaConfirm(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- switch (option)
- {
- case 0: // "Yes"
- LLSelectMgr::getInstance()->selectionSetMedia(0, LLSD());
- if (LLFloaterReg::instanceVisible("media_settings"))
- {
- LLFloaterReg::hideInstance("media_settings");
- }
- break;
-
- case 1: // "No"
- default:
- break;
- }
- return false;
-}
-
-// static
-bool LLPanelFace::multipleFacesSelectedConfirm(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
- switch (option)
- {
- case 0: // "Yes"
- LLFloaterReg::showInstance("media_settings");
- break;
- case 1: // "No"
- default:
- break;
- }
- return false;
-}
-
-//static
-void LLPanelFace::syncOffsetX(LLPanelFace* self, F32 offsetU)
-{
- LLSelectedTEMaterial::setNormalOffsetX(self,offsetU);
- LLSelectedTEMaterial::setSpecularOffsetX(self,offsetU);
- self->getChild<LLSpinCtrl>("TexOffsetU")->forceSetValue(offsetU);
- self->sendTextureInfo();
-}
-
-//static
-void LLPanelFace::syncOffsetY(LLPanelFace* self, F32 offsetV)
-{
- LLSelectedTEMaterial::setNormalOffsetY(self,offsetV);
- LLSelectedTEMaterial::setSpecularOffsetY(self,offsetV);
- self->getChild<LLSpinCtrl>("TexOffsetV")->forceSetValue(offsetV);
- self->sendTextureInfo();
-}
-
-//static
-void LLPanelFace::onCommitMaterialBumpyOffsetX(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- llassert_always(self);
-
- if (gSavedSettings.getBOOL("SyncMaterialSettings"))
- {
- syncOffsetX(self,self->getCurrentBumpyOffsetU());
- }
- else
- {
- LLSelectedTEMaterial::setNormalOffsetX(self,self->getCurrentBumpyOffsetU());
- }
-
-}
-
-//static
-void LLPanelFace::onCommitMaterialBumpyOffsetY(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- llassert_always(self);
-
- if (gSavedSettings.getBOOL("SyncMaterialSettings"))
- {
- syncOffsetY(self,self->getCurrentBumpyOffsetV());
- }
- else
- {
- LLSelectedTEMaterial::setNormalOffsetY(self,self->getCurrentBumpyOffsetV());
- }
-}
-
-//static
-void LLPanelFace::onCommitMaterialShinyOffsetX(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- llassert_always(self);
-
- if (gSavedSettings.getBOOL("SyncMaterialSettings"))
- {
- syncOffsetX(self, self->getCurrentShinyOffsetU());
- }
- else
- {
- LLSelectedTEMaterial::setSpecularOffsetX(self,self->getCurrentShinyOffsetU());
- }
-}
-
-//static
-void LLPanelFace::onCommitMaterialShinyOffsetY(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- llassert_always(self);
-
- if (gSavedSettings.getBOOL("SyncMaterialSettings"))
- {
- syncOffsetY(self,self->getCurrentShinyOffsetV());
- }
- else
- {
- LLSelectedTEMaterial::setSpecularOffsetY(self,self->getCurrentShinyOffsetV());
- }
-}
-
-//static
-void LLPanelFace::syncRepeatX(LLPanelFace* self, F32 scaleU)
-{
- LLSelectedTEMaterial::setNormalRepeatX(self,scaleU);
- LLSelectedTEMaterial::setSpecularRepeatX(self,scaleU);
- self->sendTextureInfo();
-}
-
-//static
-void LLPanelFace::syncRepeatY(LLPanelFace* self, F32 scaleV)
-{
- LLSelectedTEMaterial::setNormalRepeatY(self,scaleV);
- LLSelectedTEMaterial::setSpecularRepeatY(self,scaleV);
- self->sendTextureInfo();
-}
-
-//static
-void LLPanelFace::onCommitMaterialBumpyScaleX(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- llassert_always(self);
- F32 bumpy_scale_u = self->getCurrentBumpyScaleU();
- if (self->isIdenticalPlanarTexgen())
- {
- bumpy_scale_u *= 0.5f;
- }
-
- if (gSavedSettings.getBOOL("SyncMaterialSettings"))
- {
- self->getChild<LLSpinCtrl>("TexScaleU")->forceSetValue(self->getCurrentBumpyScaleU());
- syncRepeatX(self, bumpy_scale_u);
- }
- else
- {
- LLSelectedTEMaterial::setNormalRepeatX(self,bumpy_scale_u);
- }
-}
-
-//static
-void LLPanelFace::onCommitMaterialBumpyScaleY(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- llassert_always(self);
- F32 bumpy_scale_v = self->getCurrentBumpyScaleV();
- if (self->isIdenticalPlanarTexgen())
- {
- bumpy_scale_v *= 0.5f;
- }
-
-
- if (gSavedSettings.getBOOL("SyncMaterialSettings"))
- {
- self->getChild<LLSpinCtrl>("TexScaleV")->forceSetValue(self->getCurrentBumpyScaleV());
- syncRepeatY(self, bumpy_scale_v);
- }
- else
- {
- LLSelectedTEMaterial::setNormalRepeatY(self,bumpy_scale_v);
- }
-}
-
-//static
-void LLPanelFace::onCommitMaterialShinyScaleX(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- llassert_always(self);
- F32 shiny_scale_u = self->getCurrentShinyScaleU();
- if (self->isIdenticalPlanarTexgen())
- {
- shiny_scale_u *= 0.5f;
- }
-
- if (gSavedSettings.getBOOL("SyncMaterialSettings"))
- {
- self->getChild<LLSpinCtrl>("TexScaleU")->forceSetValue(self->getCurrentShinyScaleU());
- syncRepeatX(self, shiny_scale_u);
- }
- else
- {
- LLSelectedTEMaterial::setSpecularRepeatX(self,shiny_scale_u);
- }
-}
-
-//static
-void LLPanelFace::onCommitMaterialShinyScaleY(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- llassert_always(self);
- F32 shiny_scale_v = self->getCurrentShinyScaleV();
- if (self->isIdenticalPlanarTexgen())
- {
- shiny_scale_v *= 0.5f;
- }
-
- if (gSavedSettings.getBOOL("SyncMaterialSettings"))
- {
- self->getChild<LLSpinCtrl>("TexScaleV")->forceSetValue(self->getCurrentShinyScaleV());
- syncRepeatY(self, shiny_scale_v);
- }
- else
- {
- LLSelectedTEMaterial::setSpecularRepeatY(self,shiny_scale_v);
- }
-}
-
-//static
-void LLPanelFace::syncMaterialRot(LLPanelFace* self, F32 rot, int te)
-{
- LLSelectedTEMaterial::setNormalRotation(self,rot * DEG_TO_RAD, te);
- LLSelectedTEMaterial::setSpecularRotation(self,rot * DEG_TO_RAD, te);
- self->sendTextureInfo();
-}
-
-//static
-void LLPanelFace::onCommitMaterialBumpyRot(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- llassert_always(self);
-
- if (gSavedSettings.getBOOL("SyncMaterialSettings"))
- {
- self->getChild<LLSpinCtrl>("TexRot")->forceSetValue(self->getCurrentBumpyRot());
- syncMaterialRot(self, self->getCurrentBumpyRot());
- }
- else
- {
- if ((bool)self->childGetValue("checkbox planar align").asBoolean())
- {
- LLFace* last_face = NULL;
- bool identical_face = false;
- LLSelectedTE::getFace(last_face, identical_face);
- LLPanelFaceSetAlignedTEFunctor setfunc(self, last_face);
- LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
- }
- else
- {
- LLSelectedTEMaterial::setNormalRotation(self, self->getCurrentBumpyRot() * DEG_TO_RAD);
- }
- }
-}
-
-//static
-void LLPanelFace::onCommitMaterialShinyRot(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- llassert_always(self);
-
- if (gSavedSettings.getBOOL("SyncMaterialSettings"))
- {
- self->getChild<LLSpinCtrl>("TexRot")->forceSetValue(self->getCurrentShinyRot());
- syncMaterialRot(self, self->getCurrentShinyRot());
- }
- else
- {
- if ((bool)self->childGetValue("checkbox planar align").asBoolean())
- {
- LLFace* last_face = NULL;
- bool identical_face = false;
- LLSelectedTE::getFace(last_face, identical_face);
- LLPanelFaceSetAlignedTEFunctor setfunc(self, last_face);
- LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
- }
- else
- {
- LLSelectedTEMaterial::setSpecularRotation(self, self->getCurrentShinyRot() * DEG_TO_RAD);
- }
- }
-}
-
-//static
-void LLPanelFace::onCommitMaterialGloss(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- llassert_always(self);
- LLSelectedTEMaterial::setSpecularLightExponent(self,self->getCurrentGlossiness());
-}
-
-//static
-void LLPanelFace::onCommitMaterialEnv(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- llassert_always(self);
- LLSelectedTEMaterial::setEnvironmentIntensity(self,self->getCurrentEnvIntensity());
-}
-
-//static
-void LLPanelFace::onCommitMaterialMaskCutoff(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- LLSelectedTEMaterial::setAlphaMaskCutoff(self,self->getCurrentAlphaMaskCutoff());
-}
-
-// static
-void LLPanelFace::onCommitTextureInfo( LLUICtrl* ctrl, void* userdata )
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- self->sendTextureInfo();
- // vertical scale and repeats per meter depends on each other, so force set on changes
- self->updateUI(true);
-}
-
-// static
-void LLPanelFace::onCommitTextureScaleX( LLUICtrl* ctrl, void* userdata )
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- if (gSavedSettings.getBOOL("SyncMaterialSettings"))
- {
- F32 bumpy_scale_u = self->getChild<LLUICtrl>("TexScaleU")->getValue().asReal();
- if (self->isIdenticalPlanarTexgen())
- {
- bumpy_scale_u *= 0.5f;
- }
- syncRepeatX(self, bumpy_scale_u);
- }
- else
- {
- self->sendTextureInfo();
- }
- self->updateUI(true);
-}
-
-// static
-void LLPanelFace::onCommitTextureScaleY( LLUICtrl* ctrl, void* userdata )
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- if (gSavedSettings.getBOOL("SyncMaterialSettings"))
- {
- F32 bumpy_scale_v = self->getChild<LLUICtrl>("TexScaleV")->getValue().asReal();
- if (self->isIdenticalPlanarTexgen())
- {
- bumpy_scale_v *= 0.5f;
- }
- syncRepeatY(self, bumpy_scale_v);
- }
- else
- {
- self->sendTextureInfo();
- }
- self->updateUI(true);
-}
-
-// static
-void LLPanelFace::onCommitTextureRot( LLUICtrl* ctrl, void* userdata )
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
-
- if (gSavedSettings.getBOOL("SyncMaterialSettings"))
- {
- syncMaterialRot(self, self->getChild<LLUICtrl>("TexRot")->getValue().asReal());
- }
- else
- {
- self->sendTextureInfo();
- }
- self->updateUI(true);
-}
-
-// static
-void LLPanelFace::onCommitTextureOffsetX( LLUICtrl* ctrl, void* userdata )
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- if (gSavedSettings.getBOOL("SyncMaterialSettings"))
- {
- syncOffsetX(self, self->getChild<LLUICtrl>("TexOffsetU")->getValue().asReal());
- }
- else
- {
- self->sendTextureInfo();
- }
- self->updateUI(true);
-}
-
-// static
-void LLPanelFace::onCommitTextureOffsetY( LLUICtrl* ctrl, void* userdata )
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- if (gSavedSettings.getBOOL("SyncMaterialSettings"))
- {
- syncOffsetY(self, self->getChild<LLUICtrl>("TexOffsetV")->getValue().asReal());
- }
- else
- {
- self->sendTextureInfo();
- }
- self->updateUI(true);
-}
-
-// Commit the number of repeats per meter
-// static
-void LLPanelFace::onCommitRepeatsPerMeter(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
-
- LLUICtrl* repeats_ctrl = self->getChild<LLUICtrl>("rptctrl");
-
- U32 materials_media = self->mComboMatMedia->getCurrentIndex();
- U32 material_type = 0;
- if (materials_media == MATMEDIA_PBR)
- {
- LLRadioGroup* radio_mat_type = self->getChild<LLRadioGroup>("radio_pbr_type");
- material_type = radio_mat_type->getSelectedIndex();
- }
- if (materials_media == MATMEDIA_MATERIAL)
- {
- LLRadioGroup* radio_mat_type = self->getChild<LLRadioGroup>("radio_material_type");
- material_type = radio_mat_type->getSelectedIndex();
- }
-
- F32 repeats_per_meter = repeats_ctrl->getValue().asReal();
-
- F32 obj_scale_s = 1.0f;
- F32 obj_scale_t = 1.0f;
-
- bool identical_scale_s = false;
- bool identical_scale_t = false;
-
- LLSelectedTE::getObjectScaleS(obj_scale_s, identical_scale_s);
- LLSelectedTE::getObjectScaleS(obj_scale_t, identical_scale_t);
-
- LLUICtrl* bumpy_scale_u = self->getChild<LLUICtrl>("bumpyScaleU");
- LLUICtrl* bumpy_scale_v = self->getChild<LLUICtrl>("bumpyScaleV");
- LLUICtrl* shiny_scale_u = self->getChild<LLUICtrl>("shinyScaleU");
- LLUICtrl* shiny_scale_v = self->getChild<LLUICtrl>("shinyScaleV");
-
- if (gSavedSettings.getBOOL("SyncMaterialSettings"))
- {
- LLSelectMgr::getInstance()->selectionTexScaleAutofit( repeats_per_meter );
-
- bumpy_scale_u->setValue(obj_scale_s * repeats_per_meter);
- bumpy_scale_v->setValue(obj_scale_t * repeats_per_meter);
-
- LLSelectedTEMaterial::setNormalRepeatX(self,obj_scale_s * repeats_per_meter);
- LLSelectedTEMaterial::setNormalRepeatY(self,obj_scale_t * repeats_per_meter);
-
- shiny_scale_u->setValue(obj_scale_s * repeats_per_meter);
- shiny_scale_v->setValue(obj_scale_t * repeats_per_meter);
-
- LLSelectedTEMaterial::setSpecularRepeatX(self,obj_scale_s * repeats_per_meter);
- LLSelectedTEMaterial::setSpecularRepeatY(self,obj_scale_t * repeats_per_meter);
- }
- else
- {
- switch (material_type)
- {
- case MATTYPE_DIFFUSE:
- {
- LLSelectMgr::getInstance()->selectionTexScaleAutofit( repeats_per_meter );
- }
- break;
-
- case MATTYPE_NORMAL:
- {
- bumpy_scale_u->setValue(obj_scale_s * repeats_per_meter);
- bumpy_scale_v->setValue(obj_scale_t * repeats_per_meter);
-
- LLSelectedTEMaterial::setNormalRepeatX(self,obj_scale_s * repeats_per_meter);
- LLSelectedTEMaterial::setNormalRepeatY(self,obj_scale_t * repeats_per_meter);
- }
- break;
-
- case MATTYPE_SPECULAR:
- {
- shiny_scale_u->setValue(obj_scale_s * repeats_per_meter);
- shiny_scale_v->setValue(obj_scale_t * repeats_per_meter);
-
- LLSelectedTEMaterial::setSpecularRepeatX(self,obj_scale_s * repeats_per_meter);
- LLSelectedTEMaterial::setSpecularRepeatY(self,obj_scale_t * repeats_per_meter);
- }
- break;
-
- default:
- llassert(false);
- break;
- }
- }
- // vertical scale and repeats per meter depends on each other, so force set on changes
- self->updateUI(true);
-}
-
-struct LLPanelFaceSetMediaFunctor : public LLSelectedTEFunctor
-{
- virtual bool apply(LLViewerObject* object, S32 te)
- {
- viewer_media_t pMediaImpl;
-
- const LLTextureEntry* tep = object->getTE(te);
- const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
- if ( mep )
- {
- pMediaImpl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(mep->getMediaID());
- }
-
- if ( pMediaImpl.isNull())
- {
- // If we didn't find face media for this face, check whether this face is showing parcel media.
- pMediaImpl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(tep->getID());
- }
-
- if ( pMediaImpl.notNull())
- {
- LLPluginClassMedia *media = pMediaImpl->getMediaPlugin();
- if(media)
- {
- S32 media_width = media->getWidth();
- S32 media_height = media->getHeight();
- S32 texture_width = media->getTextureWidth();
- S32 texture_height = media->getTextureHeight();
- F32 scale_s = (F32)media_width / (F32)texture_width;
- F32 scale_t = (F32)media_height / (F32)texture_height;
-
- // set scale and adjust offset
- object->setTEScaleS( te, scale_s );
- object->setTEScaleT( te, scale_t ); // don't need to flip Y anymore since QT does this for us now.
- object->setTEOffsetS( te, -( 1.0f - scale_s ) / 2.0f );
- object->setTEOffsetT( te, -( 1.0f - scale_t ) / 2.0f );
- }
- }
- return true;
- };
-};
-
-void LLPanelFace::onClickAutoFix(void* userdata)
-{
- LLPanelFaceSetMediaFunctor setfunc;
- LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
-
- LLPanelFaceSendFunctor sendfunc;
- LLSelectMgr::getInstance()->getSelection()->applyToObjects(&sendfunc);
-}
-
-void LLPanelFace::onAlignTexture(void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*)userdata;
- self->alignTestureLayer();
-}
-
-void LLPanelFace::onClickBtnLoadInvPBR(void* userdata)
-{
- // Shouldn't this be "save to inventory?"
- LLPanelFace* self = (LLPanelFace*)userdata;
- LLTextureCtrl* pbr_ctrl = self->findChild<LLTextureCtrl>("pbr_control");
- pbr_ctrl->showPicker(true);
-}
-
-void LLPanelFace::onClickBtnEditPBR(void* userdata)
-{
- LLMaterialEditor::loadLive();
-}
-
-void LLPanelFace::onClickBtnSavePBR(void* userdata)
-{
- LLMaterialEditor::saveObjectsMaterialAs();
-}
-
-enum EPasteMode
-{
- PASTE_COLOR,
- PASTE_TEXTURE
-};
-
-struct LLPanelFacePasteTexFunctor : public LLSelectedTEFunctor
-{
- LLPanelFacePasteTexFunctor(LLPanelFace* panel, EPasteMode mode) :
- mPanelFace(panel), mMode(mode) {}
-
- virtual bool apply(LLViewerObject* objectp, S32 te)
- {
- switch (mMode)
- {
- case PASTE_COLOR:
- mPanelFace->onPasteColor(objectp, te);
- break;
- case PASTE_TEXTURE:
- mPanelFace->onPasteTexture(objectp, te);
- break;
- }
- return true;
- }
-private:
- LLPanelFace *mPanelFace;
- EPasteMode mMode;
-};
-
-struct LLPanelFaceUpdateFunctor : public LLSelectedObjectFunctor
-{
- LLPanelFaceUpdateFunctor(bool update_media)
- : mUpdateMedia(update_media)
- {}
-
- virtual bool apply(LLViewerObject* object)
- {
- object->sendTEUpdate();
-
- if (mUpdateMedia)
- {
- LLVOVolume *vo = dynamic_cast<LLVOVolume*>(object);
- if (vo && vo->hasMedia())
- {
- vo->sendMediaDataUpdate();
- }
- }
- return true;
- }
-private:
- bool mUpdateMedia;
-};
-
-struct LLPanelFaceNavigateHomeFunctor : public LLSelectedTEFunctor
-{
- virtual bool apply(LLViewerObject* objectp, S32 te)
- {
- if (objectp && objectp->getTE(te))
- {
- LLTextureEntry* tep = objectp->getTE(te);
- const LLMediaEntry *media_data = tep->getMediaData();
- if (media_data)
- {
- if (media_data->getCurrentURL().empty() && media_data->getAutoPlay())
- {
- viewer_media_t media_impl =
- LLViewerMedia::getInstance()->getMediaImplFromTextureID(tep->getMediaData()->getMediaID());
- if (media_impl)
- {
- media_impl->navigateHome();
- }
- }
- }
- }
- return true;
- }
-};
-
-void LLPanelFace::onCopyColor()
-{
- LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
- LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode();
- S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
- if (!objectp || !node
- || objectp->getPCode() != LL_PCODE_VOLUME
- || !objectp->permModify()
- || objectp->isPermanentEnforced()
- || selected_count > 1)
- {
- return;
- }
-
- if (mClipboardParams.has("color"))
- {
- mClipboardParams["color"].clear();
- }
- else
- {
- mClipboardParams["color"] = LLSD::emptyArray();
- }
-
- std::map<LLUUID, LLUUID> asset_item_map;
-
- // a way to resolve situations where source and target have different amount of faces
- S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces());
- mClipboardParams["color_all_tes"] = (num_tes != 1) || (LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool());
- for (S32 te = 0; te < num_tes; ++te)
- {
- if (node->isTESelected(te))
- {
- LLTextureEntry* tep = objectp->getTE(te);
- if (tep)
- {
- LLSD te_data;
-
- // asLLSD() includes media
- te_data["te"] = tep->asLLSD(); // Note: includes a lot more than just color/alpha/glow
-
- mClipboardParams["color"].append(te_data);
- }
- }
- }
-}
-
-void LLPanelFace::onPasteColor()
-{
- if (!mClipboardParams.has("color"))
- {
- return;
- }
-
- LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
- LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode();
- S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
- if (!objectp || !node
- || objectp->getPCode() != LL_PCODE_VOLUME
- || !objectp->permModify()
- || objectp->isPermanentEnforced()
- || selected_count > 1)
- {
- // not supposed to happen
- LL_WARNS() << "Failed to paste color due to missing or wrong selection" << LL_ENDL;
- return;
- }
-
- bool face_selection_mode = LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool();
- LLSD &clipboard = mClipboardParams["color"]; // array
- S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces());
- S32 compare_tes = num_tes;
-
- if (face_selection_mode)
- {
- compare_tes = 0;
- for (S32 te = 0; te < num_tes; ++te)
- {
- if (node->isTESelected(te))
- {
- compare_tes++;
- }
- }
- }
-
- // we can copy if single face was copied in edit face mode or if face count matches
- if (!((clipboard.size() == 1) && mClipboardParams["color_all_tes"].asBoolean())
- && compare_tes != clipboard.size())
- {
- LLSD notif_args;
- if (face_selection_mode)
- {
- static std::string reason = getString("paste_error_face_selection_mismatch");
- notif_args["REASON"] = reason;
- }
- else
- {
- static std::string reason = getString("paste_error_object_face_count_mismatch");
- notif_args["REASON"] = reason;
- }
- LLNotificationsUtil::add("FacePasteFailed", notif_args);
- return;
- }
-
- LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection();
-
- LLPanelFacePasteTexFunctor paste_func(this, PASTE_COLOR);
- selected_objects->applyToTEs(&paste_func);
-
- LLPanelFaceUpdateFunctor sendfunc(false);
- selected_objects->applyToObjects(&sendfunc);
-}
-
-void LLPanelFace::onPasteColor(LLViewerObject* objectp, S32 te)
-{
- LLSD te_data;
- LLSD &clipboard = mClipboardParams["color"]; // array
- if ((clipboard.size() == 1) && mClipboardParams["color_all_tes"].asBoolean())
- {
- te_data = *(clipboard.beginArray());
- }
- else if (clipboard[te])
- {
- te_data = clipboard[te];
- }
- else
- {
- return;
- }
-
- LLTextureEntry* tep = objectp->getTE(te);
- if (tep)
- {
- if (te_data.has("te"))
- {
- // Color / Alpha
- if (te_data["te"].has("colors"))
- {
- LLColor4 color = tep->getColor();
-
- LLColor4 clip_color;
- clip_color.setValue(te_data["te"]["colors"]);
-
- // Color
- color.mV[VRED] = clip_color.mV[VRED];
- color.mV[VGREEN] = clip_color.mV[VGREEN];
- color.mV[VBLUE] = clip_color.mV[VBLUE];
-
- // Alpha
- color.mV[VALPHA] = clip_color.mV[VALPHA];
-
- objectp->setTEColor(te, color);
- }
-
- // Color/fullbright
- if (te_data["te"].has("fullbright"))
- {
- objectp->setTEFullbright(te, te_data["te"]["fullbright"].asInteger());
- }
-
- // Glow
- if (te_data["te"].has("glow"))
- {
- objectp->setTEGlow(te, (F32)te_data["te"]["glow"].asReal());
- }
- }
- }
-}
-
-void LLPanelFace::onCopyTexture()
-{
- LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
- LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode();
- S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
- if (!objectp || !node
- || objectp->getPCode() != LL_PCODE_VOLUME
- || !objectp->permModify()
- || objectp->isPermanentEnforced()
- || selected_count > 1
- || !LLMaterialEditor::canClipboardObjectsMaterial())
- {
- return;
- }
-
- if (mClipboardParams.has("texture"))
- {
- mClipboardParams["texture"].clear();
- }
- else
- {
- mClipboardParams["texture"] = LLSD::emptyArray();
- }
-
- std::map<LLUUID, LLUUID> asset_item_map;
-
- // a way to resolve situations where source and target have different amount of faces
- S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces());
- mClipboardParams["texture_all_tes"] = (num_tes != 1) || (LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool());
- for (S32 te = 0; te < num_tes; ++te)
- {
- if (node->isTESelected(te))
- {
- LLTextureEntry* tep = objectp->getTE(te);
- if (tep)
- {
- LLSD te_data;
-
- // asLLSD() includes media
- te_data["te"] = tep->asLLSD();
- te_data["te"]["shiny"] = tep->getShiny();
- te_data["te"]["bumpmap"] = tep->getBumpmap();
- te_data["te"]["bumpshiny"] = tep->getBumpShiny();
- te_data["te"]["bumpfullbright"] = tep->getBumpShinyFullbright();
- te_data["te"]["texgen"] = tep->getTexGen();
- te_data["te"]["pbr"] = objectp->getRenderMaterialID(te);
- if (tep->getGLTFMaterialOverride() != nullptr)
- {
- te_data["te"]["pbr_override"] = tep->getGLTFMaterialOverride()->asJSON();
- }
-
- if (te_data["te"].has("imageid"))
- {
- LLUUID item_id;
- LLUUID id = te_data["te"]["imageid"].asUUID();
- bool from_library = get_is_predefined_texture(id);
- bool full_perm = from_library;
-
- if (!full_perm
- && objectp->permCopy()
- && objectp->permTransfer()
- && objectp->permModify())
- {
- // If agent created this object and nothing is limiting permissions, mark as full perm
- // If agent was granted permission to edit objects owned and created by somebody else, mark full perm
- // This check is not perfect since we can't figure out whom textures belong to so this ended up restrictive
- std::string creator_app_link;
- LLUUID creator_id;
- LLSelectMgr::getInstance()->selectGetCreator(creator_id, creator_app_link);
- full_perm = objectp->mOwnerID == creator_id;
- }
-
- if (id.notNull() && !full_perm)
- {
- std::map<LLUUID, LLUUID>::iterator iter = asset_item_map.find(id);
- if (iter != asset_item_map.end())
- {
- item_id = iter->second;
- }
- else
- {
- // What this does is simply searches inventory for item with same asset id,
- // as result it is Hightly unreliable, leaves little control to user, borderline hack
- // but there are little options to preserve permissions - multiple inventory
- // items might reference same asset and inventory search is expensive.
- bool no_transfer = false;
- if (objectp->getInventoryItemByAsset(id))
- {
- no_transfer = !objectp->getInventoryItemByAsset(id)->getIsFullPerm();
- }
- item_id = get_copy_free_item_by_asset_id(id, no_transfer);
- // record value to avoid repeating inventory search when possible
- asset_item_map[id] = item_id;
- }
- }
-
- if (item_id.notNull() && gInventory.isObjectDescendentOf(item_id, gInventory.getLibraryRootFolderID()))
- {
- full_perm = true;
- from_library = true;
- }
-
- {
- te_data["te"]["itemfullperm"] = full_perm;
- te_data["te"]["fromlibrary"] = from_library;
-
- // If full permission object, texture is free to copy,
- // but otherwise we need to check inventory and extract permissions
- //
- // Normally we care only about restrictions for current user and objects
- // don't inherit any 'next owner' permissions from texture, so there is
- // no need to record item id if full_perm==true
- if (!full_perm && !from_library && item_id.notNull())
- {
- LLViewerInventoryItem* itemp = gInventory.getItem(item_id);
- if (itemp)
- {
- LLPermissions item_permissions = itemp->getPermissions();
- if (item_permissions.allowOperationBy(PERM_COPY,
- gAgent.getID(),
- gAgent.getGroupID()))
- {
- te_data["te"]["imageitemid"] = item_id;
- te_data["te"]["itemfullperm"] = itemp->getIsFullPerm();
- if (!itemp->isFinished())
- {
- // needed for dropTextureAllFaces
- LLInventoryModelBackgroundFetch::instance().start(item_id, false);
- }
- }
- }
- }
- }
- }
-
- LLMaterialPtr material_ptr = tep->getMaterialParams();
- if (!material_ptr.isNull())
- {
- LLSD mat_data;
-
- mat_data["NormMap"] = material_ptr->getNormalID();
- mat_data["SpecMap"] = material_ptr->getSpecularID();
-
- mat_data["NormRepX"] = material_ptr->getNormalRepeatX();
- mat_data["NormRepY"] = material_ptr->getNormalRepeatY();
- mat_data["NormOffX"] = material_ptr->getNormalOffsetX();
- mat_data["NormOffY"] = material_ptr->getNormalOffsetY();
- mat_data["NormRot"] = material_ptr->getNormalRotation();
-
- mat_data["SpecRepX"] = material_ptr->getSpecularRepeatX();
- mat_data["SpecRepY"] = material_ptr->getSpecularRepeatY();
- mat_data["SpecOffX"] = material_ptr->getSpecularOffsetX();
- mat_data["SpecOffY"] = material_ptr->getSpecularOffsetY();
- mat_data["SpecRot"] = material_ptr->getSpecularRotation();
-
- mat_data["SpecColor"] = material_ptr->getSpecularLightColor().getValue();
- mat_data["SpecExp"] = material_ptr->getSpecularLightExponent();
- mat_data["EnvIntensity"] = material_ptr->getEnvironmentIntensity();
- mat_data["AlphaMaskCutoff"] = material_ptr->getAlphaMaskCutoff();
- mat_data["DiffuseAlphaMode"] = material_ptr->getDiffuseAlphaMode();
-
- // Replace no-copy textures, destination texture will get used instead if available
- if (mat_data.has("NormMap"))
- {
- LLUUID id = mat_data["NormMap"].asUUID();
- if (id.notNull() && !get_can_copy_texture(id))
- {
- mat_data["NormMap"] = DEFAULT_OBJECT_TEXTURE;
- mat_data["NormMapNoCopy"] = true;
- }
-
- }
- if (mat_data.has("SpecMap"))
- {
- LLUUID id = mat_data["SpecMap"].asUUID();
- if (id.notNull() && !get_can_copy_texture(id))
- {
- mat_data["SpecMap"] = DEFAULT_OBJECT_TEXTURE;
- mat_data["SpecMapNoCopy"] = true;
- }
-
- }
-
- te_data["material"] = mat_data;
- }
-
- mClipboardParams["texture"].append(te_data);
- }
- }
- }
-}
-
-void LLPanelFace::onPasteTexture()
-{
- if (!mClipboardParams.has("texture"))
- {
- return;
- }
-
- LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
- LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode();
- S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
- if (!objectp || !node
- || objectp->getPCode() != LL_PCODE_VOLUME
- || !objectp->permModify()
- || objectp->isPermanentEnforced()
- || selected_count > 1
- || !LLMaterialEditor::canClipboardObjectsMaterial())
- {
- // not supposed to happen
- LL_WARNS() << "Failed to paste texture due to missing or wrong selection" << LL_ENDL;
- return;
- }
-
- bool face_selection_mode = LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool();
- LLSD &clipboard = mClipboardParams["texture"]; // array
- S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces());
- S32 compare_tes = num_tes;
-
- if (face_selection_mode)
- {
- compare_tes = 0;
- for (S32 te = 0; te < num_tes; ++te)
- {
- if (node->isTESelected(te))
- {
- compare_tes++;
- }
- }
- }
-
- // we can copy if single face was copied in edit face mode or if face count matches
- if (!((clipboard.size() == 1) && mClipboardParams["texture_all_tes"].asBoolean())
- && compare_tes != clipboard.size())
- {
- LLSD notif_args;
- if (face_selection_mode)
- {
- static std::string reason = getString("paste_error_face_selection_mismatch");
- notif_args["REASON"] = reason;
- }
- else
- {
- static std::string reason = getString("paste_error_object_face_count_mismatch");
- notif_args["REASON"] = reason;
- }
- LLNotificationsUtil::add("FacePasteFailed", notif_args);
- return;
- }
-
- bool full_perm_object = true;
- LLSD::array_const_iterator iter = clipboard.beginArray();
- LLSD::array_const_iterator end = clipboard.endArray();
- for (; iter != end; ++iter)
- {
- const LLSD& te_data = *iter;
- if (te_data.has("te") && te_data["te"].has("imageid"))
- {
- bool full_perm = te_data["te"].has("itemfullperm") && te_data["te"]["itemfullperm"].asBoolean();
- full_perm_object &= full_perm;
- if (!full_perm)
- {
- if (te_data["te"].has("imageitemid"))
- {
- LLUUID item_id = te_data["te"]["imageitemid"].asUUID();
- if (item_id.notNull())
- {
- LLViewerInventoryItem* itemp = gInventory.getItem(item_id);
- if (!itemp)
- {
- // image might be in object's inventory, but it can be not up to date
- LLSD notif_args;
- static std::string reason = getString("paste_error_inventory_not_found");
- notif_args["REASON"] = reason;
- LLNotificationsUtil::add("FacePasteFailed", notif_args);
- return;
- }
- }
- }
- else
- {
- // Item was not found on 'copy' stage
- // Since this happened at copy, might be better to either show this
- // at copy stage or to drop clipboard here
- LLSD notif_args;
- static std::string reason = getString("paste_error_inventory_not_found");
- notif_args["REASON"] = reason;
- LLNotificationsUtil::add("FacePasteFailed", notif_args);
- return;
- }
- }
- }
- }
-
- if (!full_perm_object)
- {
- LLNotificationsUtil::add("FacePasteTexturePermissions");
- }
-
- LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection();
-
- LLPanelFacePasteTexFunctor paste_func(this, PASTE_TEXTURE);
- selected_objects->applyToTEs(&paste_func);
-
- LLPanelFaceUpdateFunctor sendfunc(true);
- selected_objects->applyToObjects(&sendfunc);
-
- LLGLTFMaterialList::flushUpdates();
-
- LLPanelFaceNavigateHomeFunctor navigate_home_func;
- selected_objects->applyToTEs(&navigate_home_func);
-}
-
-void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te)
-{
- LLSD te_data;
- LLSD &clipboard = mClipboardParams["texture"]; // array
- if ((clipboard.size() == 1) && mClipboardParams["texture_all_tes"].asBoolean())
- {
- te_data = *(clipboard.beginArray());
- }
- else if (clipboard[te])
- {
- te_data = clipboard[te];
- }
- else
- {
- return;
- }
-
- LLTextureEntry* tep = objectp->getTE(te);
- if (tep)
- {
- if (te_data.has("te"))
- {
- // Texture
- bool full_perm = te_data["te"].has("itemfullperm") && te_data["te"]["itemfullperm"].asBoolean();
- bool from_library = te_data["te"].has("fromlibrary") && te_data["te"]["fromlibrary"].asBoolean();
- if (te_data["te"].has("imageid"))
- {
- const LLUUID& imageid = te_data["te"]["imageid"].asUUID(); //texture or asset id
- LLViewerInventoryItem* itemp_res = NULL;
-
- if (te_data["te"].has("imageitemid"))
- {
- LLUUID item_id = te_data["te"]["imageitemid"].asUUID();
- if (item_id.notNull())
- {
- LLViewerInventoryItem* itemp = gInventory.getItem(item_id);
- if (itemp && itemp->isFinished())
- {
- // dropTextureAllFaces will fail if incomplete
- itemp_res = itemp;
- }
- else
- {
- // Theoretically shouldn't happend, but if it does happen, we
- // might need to add a notification to user that paste will fail
- // since inventory isn't fully loaded
- LL_WARNS() << "Item " << item_id << " is incomplete, paste might fail silently." << LL_ENDL;
- }
- }
- }
- // for case when item got removed from inventory after we pressed 'copy'
- // or texture got pasted into previous object
- if (!itemp_res && !full_perm)
- {
- // Due to checks for imageitemid in LLPanelFace::onPasteTexture() this should no longer be reachable.
- LL_INFOS() << "Item " << te_data["te"]["imageitemid"].asUUID() << " no longer in inventory." << LL_ENDL;
- // Todo: fix this, we are often searching same texture multiple times (equal to number of faces)
- // Perhaps just mPanelFace->onPasteTexture(objectp, te, &asset_to_item_id_map); ? Not pretty, but will work
- LLViewerInventoryCategory::cat_array_t cats;
- LLViewerInventoryItem::item_array_t items;
- LLAssetIDMatches asset_id_matches(imageid);
- gInventory.collectDescendentsIf(LLUUID::null,
- cats,
- items,
- LLInventoryModel::INCLUDE_TRASH,
- asset_id_matches);
-
- // Extremely unreliable and perfomance unfriendly.
- // But we need this to check permissions and it is how texture control finds items
- for (S32 i = 0; i < items.size(); i++)
- {
- LLViewerInventoryItem* itemp = items[i];
- if (itemp && itemp->isFinished())
- {
- // dropTextureAllFaces will fail if incomplete
- LLPermissions item_permissions = itemp->getPermissions();
- if (item_permissions.allowOperationBy(PERM_COPY,
- gAgent.getID(),
- gAgent.getGroupID()))
- {
- itemp_res = itemp;
- break; // first match
- }
- }
- }
- }
-
- if (itemp_res)
- {
- if (te == -1) // all faces
- {
- LLToolDragAndDrop::dropTextureAllFaces(objectp,
- itemp_res,
- from_library ? LLToolDragAndDrop::SOURCE_LIBRARY : LLToolDragAndDrop::SOURCE_AGENT,
- LLUUID::null,
- false);
- }
- else // one face
- {
- LLToolDragAndDrop::dropTextureOneFace(objectp,
- te,
- itemp_res,
- from_library ? LLToolDragAndDrop::SOURCE_LIBRARY : LLToolDragAndDrop::SOURCE_AGENT,
- LLUUID::null,
- false,
- 0);
- }
- }
- // not an inventory item or no complete items
- else if (full_perm)
- {
- // Either library, local or existed as fullperm when user made a copy
- LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(imageid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
- objectp->setTEImage(U8(te), image);
- }
- }
-
- if (te_data["te"].has("bumpmap"))
- {
- objectp->setTEBumpmap(te, (U8)te_data["te"]["bumpmap"].asInteger());
- }
- if (te_data["te"].has("bumpshiny"))
- {
- objectp->setTEBumpShiny(te, (U8)te_data["te"]["bumpshiny"].asInteger());
- }
- if (te_data["te"].has("bumpfullbright"))
- {
- objectp->setTEBumpShinyFullbright(te, (U8)te_data["te"]["bumpfullbright"].asInteger());
- }
- if (te_data["te"].has("texgen"))
- {
- objectp->setTETexGen(te, (U8)te_data["te"]["texgen"].asInteger());
- }
-
- // PBR/GLTF
- if (te_data["te"].has("pbr"))
- {
- objectp->setRenderMaterialID(te, te_data["te"]["pbr"].asUUID(), false /*managing our own update*/);
- tep->setGLTFRenderMaterial(nullptr);
- tep->setGLTFMaterialOverride(nullptr);
-
- LLSD override_data;
- override_data["object_id"] = objectp->getID();
- override_data["side"] = te;
- if (te_data["te"].has("pbr_override"))
- {
- override_data["gltf_json"] = te_data["te"]["pbr_override"];
- }
- else
- {
- override_data["gltf_json"] = "";
- }
-
- override_data["asset_id"] = te_data["te"]["pbr"].asUUID();
-
- LLGLTFMaterialList::queueUpdate(override_data);
- }
- else
- {
- objectp->setRenderMaterialID(te, LLUUID::null, false /*send in bulk later*/ );
- tep->setGLTFRenderMaterial(nullptr);
- tep->setGLTFMaterialOverride(nullptr);
-
- // blank out most override data on the server
- LLGLTFMaterialList::queueApply(objectp, te, LLUUID::null);
- }
-
- // Texture map
- if (te_data["te"].has("scales") && te_data["te"].has("scalet"))
- {
- objectp->setTEScale(te, (F32)te_data["te"]["scales"].asReal(), (F32)te_data["te"]["scalet"].asReal());
- }
- if (te_data["te"].has("offsets") && te_data["te"].has("offsett"))
- {
- objectp->setTEOffset(te, (F32)te_data["te"]["offsets"].asReal(), (F32)te_data["te"]["offsett"].asReal());
- }
- if (te_data["te"].has("imagerot"))
- {
- objectp->setTERotation(te, (F32)te_data["te"]["imagerot"].asReal());
- }
-
- // Media
- if (te_data["te"].has("media_flags"))
- {
- U8 media_flags = te_data["te"]["media_flags"].asInteger();
- objectp->setTEMediaFlags(te, media_flags);
- LLVOVolume *vo = dynamic_cast<LLVOVolume*>(objectp);
- if (vo && te_data["te"].has(LLTextureEntry::TEXTURE_MEDIA_DATA_KEY))
- {
- vo->syncMediaData(te, te_data["te"][LLTextureEntry::TEXTURE_MEDIA_DATA_KEY], true/*merge*/, true/*ignore_agent*/);
- }
- }
- else
- {
- // Keep media flags on destination unchanged
- }
- }
-
- if (te_data.has("material"))
- {
- LLUUID object_id = objectp->getID();
-
- // Normal
- // Replace placeholders with target's
- if (te_data["material"].has("NormMapNoCopy"))
- {
- LLMaterialPtr material = tep->getMaterialParams();
- if (material.notNull())
- {
- LLUUID id = material->getNormalID();
- if (id.notNull())
- {
- te_data["material"]["NormMap"] = id;
- }
- }
- }
- LLSelectedTEMaterial::setNormalID(this, te_data["material"]["NormMap"].asUUID(), te, object_id);
- LLSelectedTEMaterial::setNormalRepeatX(this, (F32)te_data["material"]["NormRepX"].asReal(), te, object_id);
- LLSelectedTEMaterial::setNormalRepeatY(this, (F32)te_data["material"]["NormRepY"].asReal(), te, object_id);
- LLSelectedTEMaterial::setNormalOffsetX(this, (F32)te_data["material"]["NormOffX"].asReal(), te, object_id);
- LLSelectedTEMaterial::setNormalOffsetY(this, (F32)te_data["material"]["NormOffY"].asReal(), te, object_id);
- LLSelectedTEMaterial::setNormalRotation(this, (F32)te_data["material"]["NormRot"].asReal(), te, object_id);
-
- // Specular
- // Replace placeholders with target's
- if (te_data["material"].has("SpecMapNoCopy"))
- {
- LLMaterialPtr material = tep->getMaterialParams();
- if (material.notNull())
- {
- LLUUID id = material->getSpecularID();
- if (id.notNull())
- {
- te_data["material"]["SpecMap"] = id;
- }
- }
- }
- LLSelectedTEMaterial::setSpecularID(this, te_data["material"]["SpecMap"].asUUID(), te, object_id);
- LLSelectedTEMaterial::setSpecularRepeatX(this, (F32)te_data["material"]["SpecRepX"].asReal(), te, object_id);
- LLSelectedTEMaterial::setSpecularRepeatY(this, (F32)te_data["material"]["SpecRepY"].asReal(), te, object_id);
- LLSelectedTEMaterial::setSpecularOffsetX(this, (F32)te_data["material"]["SpecOffX"].asReal(), te, object_id);
- LLSelectedTEMaterial::setSpecularOffsetY(this, (F32)te_data["material"]["SpecOffY"].asReal(), te, object_id);
- LLSelectedTEMaterial::setSpecularRotation(this, (F32)te_data["material"]["SpecRot"].asReal(), te, object_id);
- LLColor4U spec_color(te_data["material"]["SpecColor"]);
- LLSelectedTEMaterial::setSpecularLightColor(this, spec_color, te);
- LLSelectedTEMaterial::setSpecularLightExponent(this, (U8)te_data["material"]["SpecExp"].asInteger(), te, object_id);
- LLSelectedTEMaterial::setEnvironmentIntensity(this, (U8)te_data["material"]["EnvIntensity"].asInteger(), te, object_id);
- LLSelectedTEMaterial::setDiffuseAlphaMode(this, (U8)te_data["material"]["DiffuseAlphaMode"].asInteger(), te, object_id);
- LLSelectedTEMaterial::setAlphaMaskCutoff(this, (U8)te_data["material"]["AlphaMaskCutoff"].asInteger(), te, object_id);
- if (te_data.has("te") && te_data["te"].has("shiny"))
- {
- objectp->setTEShiny(te, (U8)te_data["te"]["shiny"].asInteger());
- }
- }
- }
-}
-
-void LLPanelFace::menuDoToSelected(const LLSD& userdata)
-{
- std::string command = userdata.asString();
-
- // paste
- if (command == "color_paste")
- {
- onPasteColor();
- }
- else if (command == "texture_paste")
- {
- onPasteTexture();
- }
- // copy
- else if (command == "color_copy")
- {
- onCopyColor();
- }
- else if (command == "texture_copy")
- {
- onCopyTexture();
- }
-}
-
-bool LLPanelFace::menuEnableItem(const LLSD& userdata)
-{
- std::string command = userdata.asString();
-
- // paste options
- if (command == "color_paste")
- {
- return mClipboardParams.has("color");
- }
- else if (command == "texture_paste")
- {
- return mClipboardParams.has("texture");
- }
- return false;
-}
-
-
-// static
-void LLPanelFace::onCommitPlanarAlign(LLUICtrl* ctrl, void* userdata)
-{
- LLPanelFace* self = (LLPanelFace*) userdata;
- self->getState();
- self->sendTextureInfo();
-}
-
-void LLPanelFace::updateGLTFTextureTransform(float value, U32 pbr_type, std::function<void(LLGLTFMaterial::TextureTransform*)> edit)
-{
- U32 texture_info_start;
- U32 texture_info_end;
- const LLGLTFMaterial::TextureInfo texture_info = texture_info_from_pbrtype(pbr_type);
- if (texture_info == LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT)
- {
- texture_info_start = 0;
- texture_info_end = LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT;
- }
- else
- {
- texture_info_start = texture_info_from_pbrtype(pbr_type);
- texture_info_end = texture_info_start + 1;
- }
- updateSelectedGLTFMaterials([&](LLGLTFMaterial* new_override)
- {
- for (U32 ti = texture_info_start; ti < texture_info_end; ++ti)
- {
- LLGLTFMaterial::TextureTransform& new_transform = new_override->mTextureTransform[(LLGLTFMaterial::TextureInfo)ti];
- edit(&new_transform);
- }
- });
-}
-
-void LLPanelFace::setMaterialOverridesFromSelection()
-{
- const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
- const LLGLTFMaterial::TextureInfo texture_info = texture_info_from_pbrtype(pbr_type);
- U32 texture_info_start;
- U32 texture_info_end;
- if (texture_info == LLGLTFMaterial::TextureInfo::GLTF_TEXTURE_INFO_COUNT)
- {
- texture_info_start = 0;
- texture_info_end = LLGLTFMaterial::TextureInfo::GLTF_TEXTURE_INFO_COUNT;
- }
- else
- {
- texture_info_start = texture_info;
- texture_info_end = texture_info + 1;
- }
-
- bool read_transform = true;
- LLGLTFMaterial::TextureTransform transform;
- bool scale_u_same = true;
- bool scale_v_same = true;
- bool rotation_same = true;
- bool offset_u_same = true;
- bool offset_v_same = true;
-
- for (U32 i = texture_info_start; i < texture_info_end; ++i)
- {
- LLGLTFMaterial::TextureTransform this_transform;
- bool this_scale_u_same = true;
- bool this_scale_v_same = true;
- bool this_rotation_same = true;
- bool this_offset_u_same = true;
- bool this_offset_v_same = true;
-
- readSelectedGLTFMaterial<float>([&](const LLGLTFMaterial* mat)
- {
- return mat ? mat->mTextureTransform[i].mScale[VX] : 0.f;
- }, this_transform.mScale[VX], this_scale_u_same, true, 1e-3f);
- readSelectedGLTFMaterial<float>([&](const LLGLTFMaterial* mat)
- {
- return mat ? mat->mTextureTransform[i].mScale[VY] : 0.f;
- }, this_transform.mScale[VY], this_scale_v_same, true, 1e-3f);
- readSelectedGLTFMaterial<float>([&](const LLGLTFMaterial* mat)
- {
- return mat ? mat->mTextureTransform[i].mRotation : 0.f;
- }, this_transform.mRotation, this_rotation_same, true, 1e-3f);
- readSelectedGLTFMaterial<float>([&](const LLGLTFMaterial* mat)
- {
- return mat ? mat->mTextureTransform[i].mOffset[VX] : 0.f;
- }, this_transform.mOffset[VX], this_offset_u_same, true, 1e-3f);
- readSelectedGLTFMaterial<float>([&](const LLGLTFMaterial* mat)
- {
- return mat ? mat->mTextureTransform[i].mOffset[VY] : 0.f;
- }, this_transform.mOffset[VY], this_offset_v_same, true, 1e-3f);
-
- scale_u_same = scale_u_same && this_scale_u_same;
- scale_v_same = scale_v_same && this_scale_v_same;
- rotation_same = rotation_same && this_rotation_same;
- offset_u_same = offset_u_same && this_offset_u_same;
- offset_v_same = offset_v_same && this_offset_v_same;
-
- if (read_transform)
- {
- read_transform = false;
- transform = this_transform;
- }
- else
- {
- scale_u_same = scale_u_same && (this_transform.mScale[VX] == transform.mScale[VX]);
- scale_v_same = scale_v_same && (this_transform.mScale[VY] == transform.mScale[VY]);
- rotation_same = rotation_same && (this_transform.mRotation == transform.mRotation);
- offset_u_same = offset_u_same && (this_transform.mOffset[VX] == transform.mOffset[VX]);
- offset_v_same = offset_v_same && (this_transform.mOffset[VY] == transform.mOffset[VY]);
- }
- }
-
- LLUICtrl* gltfCtrlTextureScaleU = getChild<LLUICtrl>("gltfTextureScaleU");
- LLUICtrl* gltfCtrlTextureScaleV = getChild<LLUICtrl>("gltfTextureScaleV");
- LLUICtrl* gltfCtrlTextureRotation = getChild<LLUICtrl>("gltfTextureRotation");
- LLUICtrl* gltfCtrlTextureOffsetU = getChild<LLUICtrl>("gltfTextureOffsetU");
- LLUICtrl* gltfCtrlTextureOffsetV = getChild<LLUICtrl>("gltfTextureOffsetV");
-
- gltfCtrlTextureScaleU->setValue(transform.mScale[VX]);
- gltfCtrlTextureScaleV->setValue(transform.mScale[VY]);
- gltfCtrlTextureRotation->setValue(transform.mRotation * RAD_TO_DEG);
- gltfCtrlTextureOffsetU->setValue(transform.mOffset[VX]);
- gltfCtrlTextureOffsetV->setValue(transform.mOffset[VY]);
-
- gltfCtrlTextureScaleU->setTentative(!scale_u_same);
- gltfCtrlTextureScaleV->setTentative(!scale_v_same);
- gltfCtrlTextureRotation->setTentative(!rotation_same);
- gltfCtrlTextureOffsetU->setTentative(!offset_u_same);
- gltfCtrlTextureOffsetV->setTentative(!offset_v_same);
-}
-
-void LLPanelFace::Selection::connect()
-{
- if (!mSelectConnection.connected())
- {
- mSelectConnection = LLSelectMgr::instance().mUpdateSignal.connect(boost::bind(&LLPanelFace::Selection::onSelectionChanged, this));
- }
-}
-
-bool LLPanelFace::Selection::update()
-{
- const bool changed = mChanged || compareSelection();
- mChanged = false;
- return changed;
-}
-
-void LLPanelFace::Selection::onSelectedObjectUpdated(const LLUUID& object_id, S32 side)
-{
- if (object_id == mSelectedObjectID)
- {
- if (side == mLastSelectedSide)
- {
- mChanged = true;
- }
- else if (mLastSelectedSide == -1) // if last selected face was deselected
- {
- LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode();
- if (node && node->isTESelected(side))
- {
- mChanged = true;
- }
- }
- }
-}
-
-bool LLPanelFace::Selection::compareSelection()
-{
- if (!mNeedsSelectionCheck)
- {
- return false;
- }
- mNeedsSelectionCheck = false;
-
- const S32 old_object_count = mSelectedObjectCount;
- const S32 old_te_count = mSelectedTECount;
- const LLUUID old_object_id = mSelectedObjectID;
- const S32 old_side = mLastSelectedSide;
-
- LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
- LLSelectNode* node = selection->getFirstNode();
- if (node)
- {
- LLViewerObject* object = node->getObject();
- mSelectedObjectCount = selection->getObjectCount();
- mSelectedTECount = selection->getTECount();
- mSelectedObjectID = object->getID();
- mLastSelectedSide = node->getLastSelectedTE();
- }
- else
- {
- mSelectedObjectCount = 0;
- mSelectedTECount = 0;
- mSelectedObjectID = LLUUID::null;
- mLastSelectedSide = -1;
- }
-
- const bool selection_changed =
- old_object_count != mSelectedObjectCount
- || old_te_count != mSelectedTECount
- || old_object_id != mSelectedObjectID
- || old_side != mLastSelectedSide;
- mChanged = mChanged || selection_changed;
- return selection_changed;
-}
-
-void LLPanelFace::onCommitGLTFTextureScaleU(LLUICtrl* ctrl)
-{
- const float value = ctrl->getValue().asReal();
- const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
- updateGLTFTextureTransform(value, pbr_type, [&](LLGLTFMaterial::TextureTransform* new_transform)
- {
- new_transform->mScale.mV[VX] = value;
- });
-}
-
-void LLPanelFace::onCommitGLTFTextureScaleV(LLUICtrl* ctrl)
-{
- const float value = ctrl->getValue().asReal();
- const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
- updateGLTFTextureTransform(value, pbr_type, [&](LLGLTFMaterial::TextureTransform* new_transform)
- {
- new_transform->mScale.mV[VY] = value;
- });
-}
-
-void LLPanelFace::onCommitGLTFRotation(LLUICtrl* ctrl)
-{
- const float value = ctrl->getValue().asReal() * DEG_TO_RAD;
- const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
- updateGLTFTextureTransform(value, pbr_type, [&](LLGLTFMaterial::TextureTransform* new_transform)
- {
- new_transform->mRotation = value;
- });
-}
-
-void LLPanelFace::onCommitGLTFTextureOffsetU(LLUICtrl* ctrl)
-{
- const float value = ctrl->getValue().asReal();
- const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
- updateGLTFTextureTransform(value, pbr_type, [&](LLGLTFMaterial::TextureTransform* new_transform)
- {
- new_transform->mOffset.mV[VX] = value;
- });
-}
-
-void LLPanelFace::onCommitGLTFTextureOffsetV(LLUICtrl* ctrl)
-{
- const float value = ctrl->getValue().asReal();
- const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
- updateGLTFTextureTransform(value, pbr_type, [&](LLGLTFMaterial::TextureTransform* new_transform)
- {
- new_transform->mOffset.mV[VY] = value;
- });
-}
-
-void LLPanelFace::onTextureSelectionChanged(LLInventoryItem* itemp)
-{
- LL_DEBUGS("Materials") << "item asset " << itemp->getAssetUUID() << LL_ENDL;
- LLRadioGroup* radio_mat_type = findChild<LLRadioGroup>("radio_material_type");
- if(!radio_mat_type)
- {
- return;
- }
- U32 mattype = radio_mat_type->getSelectedIndex();
- std::string which_control="texture control";
- switch (mattype)
- {
- case MATTYPE_SPECULAR:
- which_control = "shinytexture control";
- break;
- case MATTYPE_NORMAL:
- which_control = "bumpytexture control";
- break;
- // no default needed
- }
- LL_DEBUGS("Materials") << "control " << which_control << LL_ENDL;
- LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>(which_control);
- if (texture_ctrl)
- {
- LLUUID obj_owner_id;
- std::string obj_owner_name;
- LLSelectMgr::instance().selectGetOwner(obj_owner_id, obj_owner_name);
-
- LLSaleInfo sale_info;
- LLSelectMgr::instance().selectGetSaleInfo(sale_info);
-
- bool can_copy = itemp->getPermissions().allowCopyBy(gAgentID); // do we have perm to copy this texture?
- bool can_transfer = itemp->getPermissions().allowOperationBy(PERM_TRANSFER, gAgentID); // do we have perm to transfer this texture?
- bool is_object_owner = gAgentID == obj_owner_id; // does object for which we are going to apply texture belong to the agent?
- bool not_for_sale = !sale_info.isForSale(); // is object for which we are going to apply texture not for sale?
-
- if (can_copy && can_transfer)
- {
- texture_ctrl->setCanApply(true, true);
- return;
- }
-
- // if texture has (no-transfer) attribute it can be applied only for object which we own and is not for sale
- texture_ctrl->setCanApply(false, can_transfer ? true : is_object_owner && not_for_sale);
-
- if (gSavedSettings.getBOOL("TextureLivePreview"))
- {
- LLNotificationsUtil::add("LivePreviewUnavailable");
- }
- }
-}
-
-void LLPanelFace::onPbrSelectionChanged(LLInventoryItem* itemp)
-{
- LLTextureCtrl* pbr_ctrl = findChild<LLTextureCtrl>("pbr_control");
- if (pbr_ctrl)
- {
- LLUUID obj_owner_id;
- std::string obj_owner_name;
- LLSelectMgr::instance().selectGetOwner(obj_owner_id, obj_owner_name);
-
- LLSaleInfo sale_info;
- LLSelectMgr::instance().selectGetSaleInfo(sale_info);
-
- bool can_copy = itemp->getPermissions().allowCopyBy(gAgentID); // do we have perm to copy this material?
- bool can_transfer = itemp->getPermissions().allowOperationBy(PERM_TRANSFER, gAgentID); // do we have perm to transfer this material?
- bool can_modify = itemp->getPermissions().allowOperationBy(PERM_MODIFY, gAgentID); // do we have perm to transfer this material?
- bool is_object_owner = gAgentID == obj_owner_id; // does object for which we are going to apply material belong to the agent?
- bool not_for_sale = !sale_info.isForSale(); // is object for which we are going to apply material not for sale?
- bool from_library = ALEXANDRIA_LINDEN_ID == itemp->getPermissions().getOwner();
-
- if ((can_copy && can_transfer && can_modify) || from_library)
- {
- pbr_ctrl->setCanApply(true, true);
- return;
- }
-
- // if material has (no-transfer) attribute it can be applied only for object which we own and is not for sale
- pbr_ctrl->setCanApply(false, can_transfer ? true : is_object_owner && not_for_sale);
-
- if (gSavedSettings.getBOOL("TextureLivePreview"))
- {
- LLNotificationsUtil::add("LivePreviewUnavailablePBR");
- }
- }
-}
-
-bool LLPanelFace::isIdenticalPlanarTexgen()
-{
- LLTextureEntry::e_texgen selected_texgen = LLTextureEntry::TEX_GEN_DEFAULT;
- bool identical_texgen = false;
- LLSelectedTE::getTexGen(selected_texgen, identical_texgen);
- return (identical_texgen && (selected_texgen == LLTextureEntry::TEX_GEN_PLANAR));
-}
-
-void LLPanelFace::LLSelectedTE::getFace(LLFace*& face_to_return, bool& identical_face)
-{
- struct LLSelectedTEGetFace : public LLSelectedTEGetFunctor<LLFace *>
- {
- LLFace* get(LLViewerObject* object, S32 te)
- {
- return (object->mDrawable) ? object->mDrawable->getFace(te): NULL;
- }
- } get_te_face_func;
- identical_face = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&get_te_face_func, face_to_return, false, (LLFace*)nullptr);
-}
-
-void LLPanelFace::LLSelectedTE::getImageFormat(LLGLenum& image_format_to_return, bool& identical_face)
-{
- LLGLenum image_format;
- struct LLSelectedTEGetImageFormat : public LLSelectedTEGetFunctor<LLGLenum>
- {
- LLGLenum get(LLViewerObject* object, S32 te_index)
- {
- LLViewerTexture* image = object->getTEImage(te_index);
- return image ? image->getPrimaryFormat() : GL_RGB;
- }
- } get_glenum;
- identical_face = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&get_glenum, image_format);
- image_format_to_return = image_format;
-}
-
-void LLPanelFace::LLSelectedTE::getTexId(LLUUID& id, bool& identical)
-{
- struct LLSelectedTEGetTexId : public LLSelectedTEGetFunctor<LLUUID>
- {
- LLUUID get(LLViewerObject* object, S32 te_index)
- {
- LLTextureEntry *te = object->getTE(te_index);
- if (te)
- {
- if ((te->getID() == IMG_USE_BAKED_EYES) || (te->getID() == IMG_USE_BAKED_HAIR) || (te->getID() == IMG_USE_BAKED_HEAD) || (te->getID() == IMG_USE_BAKED_LOWER) || (te->getID() == IMG_USE_BAKED_SKIRT) || (te->getID() == IMG_USE_BAKED_UPPER)
- || (te->getID() == IMG_USE_BAKED_LEFTARM) || (te->getID() == IMG_USE_BAKED_LEFTLEG) || (te->getID() == IMG_USE_BAKED_AUX1) || (te->getID() == IMG_USE_BAKED_AUX2) || (te->getID() == IMG_USE_BAKED_AUX3))
- {
- return te->getID();
- }
- }
-
- LLUUID id;
- LLViewerTexture* image = object->getTEImage(te_index);
- if (image)
- {
- id = image->getID();
- }
-
- if (!id.isNull() && LLViewerMedia::getInstance()->textureHasMedia(id))
- {
- if (te)
- {
- LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID(), TEX_LIST_STANDARD) : NULL;
- if(!tex)
- {
- tex = LLViewerFetchedTexture::sDefaultImagep;
- }
- if (tex)
- {
- id = tex->getID();
- }
- }
- }
- return id;
- }
- } func;
- identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, id );
-}
-
-void LLPanelFace::LLSelectedTE::getPbrMaterialId(LLUUID& id, bool& identical, bool& has_faces_with_pbr, bool& has_faces_without_pbr)
-{
- struct LLSelectedTEGetmatId : public LLSelectedTEFunctor
- {
- LLSelectedTEGetmatId()
- : mHasFacesWithoutPBR(false)
- , mHasFacesWithPBR(false)
- , mIdenticalId(true)
- , mIdenticalOverride(true)
- , mInitialized(false)
- , mMaterialOverride(LLGLTFMaterial::sDefault)
- {
- }
- bool apply(LLViewerObject* object, S32 te_index) override
- {
- LLUUID pbr_id = object->getRenderMaterialID(te_index);
- if (pbr_id.isNull())
- {
- mHasFacesWithoutPBR = true;
- }
- else
- {
- mHasFacesWithPBR = true;
- }
- if (mInitialized)
- {
- if (mPBRId != pbr_id)
- {
- mIdenticalId = false;
- }
-
- LLGLTFMaterial* te_override = object->getTE(te_index)->getGLTFMaterialOverride();
- if (te_override)
- {
- LLGLTFMaterial override = *te_override;
- override.sanitizeAssetMaterial();
- mIdenticalOverride &= (override == mMaterialOverride);
- }
- else
- {
- mIdenticalOverride &= (mMaterialOverride == LLGLTFMaterial::sDefault);
- }
- }
- else
- {
- mInitialized = true;
- mPBRId = pbr_id;
- LLGLTFMaterial* override = object->getTE(te_index)->getGLTFMaterialOverride();
- if (override)
- {
- mMaterialOverride = *override;
- mMaterialOverride.sanitizeAssetMaterial();
- }
- }
- return true;
- }
- bool mHasFacesWithoutPBR;
- bool mHasFacesWithPBR;
- bool mIdenticalId;
- bool mIdenticalOverride;
- bool mInitialized;
- LLGLTFMaterial mMaterialOverride;
- LLUUID mPBRId;
- } func;
- LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func);
- id = func.mPBRId;
- identical = func.mIdenticalId && func.mIdenticalOverride;
- has_faces_with_pbr = func.mHasFacesWithPBR;
- has_faces_without_pbr = func.mHasFacesWithoutPBR;
-}
-
-void LLPanelFace::LLSelectedTEMaterial::getCurrent(LLMaterialPtr& material_ptr, bool& identical_material)
-{
- struct MaterialFunctor : public LLSelectedTEGetFunctor<LLMaterialPtr>
- {
- LLMaterialPtr get(LLViewerObject* object, S32 te_index)
- {
- return object->getTE(te_index)->getMaterialParams();
- }
- } func;
- identical_material = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, material_ptr);
-}
-
-void LLPanelFace::LLSelectedTEMaterial::getMaxSpecularRepeats(F32& repeats, bool& identical)
-{
- struct LLSelectedTEGetMaxSpecRepeats : public LLSelectedTEGetFunctor<F32>
- {
- F32 get(LLViewerObject* object, S32 face)
- {
- LLMaterial* mat = object->getTE(face)->getMaterialParams().get();
- U32 s_axis = VX;
- U32 t_axis = VY;
- F32 repeats_s = 1.0f;
- F32 repeats_t = 1.0f;
- if (mat)
- {
- mat->getSpecularRepeat(repeats_s, repeats_t);
- repeats_s /= object->getScale().mV[s_axis];
- repeats_t /= object->getScale().mV[t_axis];
- }
- return llmax(repeats_s, repeats_t);
- }
-
- } max_spec_repeats_func;
- identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_spec_repeats_func, repeats);
-}
-
-void LLPanelFace::LLSelectedTEMaterial::getMaxNormalRepeats(F32& repeats, bool& identical)
-{
- struct LLSelectedTEGetMaxNormRepeats : public LLSelectedTEGetFunctor<F32>
- {
- F32 get(LLViewerObject* object, S32 face)
- {
- LLMaterial* mat = object->getTE(face)->getMaterialParams().get();
- U32 s_axis = VX;
- U32 t_axis = VY;
- F32 repeats_s = 1.0f;
- F32 repeats_t = 1.0f;
- if (mat)
- {
- mat->getNormalRepeat(repeats_s, repeats_t);
- repeats_s /= object->getScale().mV[s_axis];
- repeats_t /= object->getScale().mV[t_axis];
- }
- return llmax(repeats_s, repeats_t);
- }
-
- } max_norm_repeats_func;
- identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_norm_repeats_func, repeats);
-}
-
-void LLPanelFace::LLSelectedTEMaterial::getCurrentDiffuseAlphaMode(U8& diffuse_alpha_mode, bool& identical, bool diffuse_texture_has_alpha)
-{
- struct LLSelectedTEGetDiffuseAlphaMode : public LLSelectedTEGetFunctor<U8>
- {
- LLSelectedTEGetDiffuseAlphaMode() : _isAlpha(false) {}
- LLSelectedTEGetDiffuseAlphaMode(bool diffuse_texture_has_alpha) : _isAlpha(diffuse_texture_has_alpha) {}
- virtual ~LLSelectedTEGetDiffuseAlphaMode() {}
-
- U8 get(LLViewerObject* object, S32 face)
- {
- U8 diffuse_mode = _isAlpha ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : LLMaterial::DIFFUSE_ALPHA_MODE_NONE;
-
- LLTextureEntry* tep = object->getTE(face);
- if (tep)
- {
- LLMaterial* mat = tep->getMaterialParams().get();
- if (mat)
- {
- diffuse_mode = mat->getDiffuseAlphaMode();
- }
- }
-
- return diffuse_mode;
- }
- bool _isAlpha; // whether or not the diffuse texture selected contains alpha information
- } get_diff_mode(diffuse_texture_has_alpha);
- identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &get_diff_mode, diffuse_alpha_mode);
-}
-
-void LLPanelFace::LLSelectedTE::getObjectScaleS(F32& scale_s, bool& identical)
-{
- struct LLSelectedTEGetObjectScaleS : public LLSelectedTEGetFunctor<F32>
- {
- F32 get(LLViewerObject* object, S32 face)
- {
- U32 s_axis = VX;
- U32 t_axis = VY;
- LLPrimitive::getTESTAxes(face, &s_axis, &t_axis);
- return object->getScale().mV[s_axis];
- }
-
- } scale_s_func;
- identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &scale_s_func, scale_s );
-}
-
-void LLPanelFace::LLSelectedTE::getObjectScaleT(F32& scale_t, bool& identical)
-{
- struct LLSelectedTEGetObjectScaleS : public LLSelectedTEGetFunctor<F32>
- {
- F32 get(LLViewerObject* object, S32 face)
- {
- U32 s_axis = VX;
- U32 t_axis = VY;
- LLPrimitive::getTESTAxes(face, &s_axis, &t_axis);
- return object->getScale().mV[t_axis];
- }
-
- } scale_t_func;
- identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &scale_t_func, scale_t );
-}
-
-void LLPanelFace::LLSelectedTE::getMaxDiffuseRepeats(F32& repeats, bool& identical)
-{
- struct LLSelectedTEGetMaxDiffuseRepeats : public LLSelectedTEGetFunctor<F32>
- {
- F32 get(LLViewerObject* object, S32 face)
- {
- U32 s_axis = VX;
- U32 t_axis = VY;
- LLPrimitive::getTESTAxes(face, &s_axis, &t_axis);
- F32 repeats_s = object->getTE(face)->mScaleS / object->getScale().mV[s_axis];
- F32 repeats_t = object->getTE(face)->mScaleT / object->getScale().mV[t_axis];
- return llmax(repeats_s, repeats_t);
- }
-
- } max_diff_repeats_func;
- identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_diff_repeats_func, repeats );
-}
-
+/**
+ * @file llpanelface.cpp
+ * @brief Panel in the tools floater for editing face textures, colors, etc.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+// file include
+#include "llpanelface.h"
+
+// library includes
+#include "llcalc.h"
+#include "llerror.h"
+#include "llrect.h"
+#include "llstring.h"
+#include "llfontgl.h"
+
+// project includes
+#include "llagent.h"
+#include "llagentdata.h"
+#include "llbutton.h"
+#include "llcheckboxctrl.h"
+#include "llcolorswatch.h"
+#include "llcombobox.h"
+#include "lldrawpoolbump.h"
+#include "llface.h"
+#include "llgltfmateriallist.h"
+#include "llinventoryfunctions.h"
+#include "llinventorymodel.h" // gInventory
+#include "llinventorymodelbackgroundfetch.h"
+#include "llfloatermediasettings.h"
+#include "llfloaterreg.h"
+#include "llfloatertools.h"
+#include "lllineeditor.h"
+#include "llmaterialmgr.h"
+#include "llmaterialeditor.h"
+#include "llmediactrl.h"
+#include "llmediaentry.h"
+#include "llmenubutton.h"
+#include "llnotificationsutil.h"
+#include "llpanelcontents.h"
+#include "llradiogroup.h"
+#include "llresmgr.h"
+#include "llselectmgr.h"
+#include "llspinctrl.h"
+#include "lltextbox.h"
+#include "lltexturectrl.h"
+#include "lltextureentry.h"
+#include "lltooldraganddrop.h"
+#include "lltoolface.h"
+#include "lltoolmgr.h"
+#include "lltrans.h"
+#include "llui.h"
+#include "llviewercontrol.h"
+#include "llviewermedia.h"
+#include "llviewerobject.h"
+#include "llviewerregion.h"
+#include "llviewerstats.h"
+#include "llvovolume.h"
+#include "llvoinventorylistener.h"
+#include "lluictrlfactory.h"
+#include "llpluginclassmedia.h"
+#include "llviewertexturelist.h"// Update sel manager as to which channel we're editing so it can reflect the correct overlay UI
+
+
+
+#include "llagent.h"
+#include "llfilesystem.h"
+#include "llviewerassetupload.h"
+#include "llviewermenufile.h"
+#include "llsd.h"
+#include "llsdutil.h"
+#include "llsdserialize.h"
+#include "llinventorymodel.h"
+
+using namespace std::literals;
+
+LLPanelFace::Selection LLPanelFace::sMaterialOverrideSelection;
+
+//
+// Constant definitions for comboboxes
+// Must match the commbobox definitions in panel_tools_texture.xml
+//
+const S32 MATMEDIA_MATERIAL = 0; // Material
+const S32 MATMEDIA_PBR = 1; // PBR
+const S32 MATMEDIA_MEDIA = 2; // Media
+const S32 MATTYPE_DIFFUSE = 0; // Diffuse material texture
+const S32 MATTYPE_NORMAL = 1; // Normal map
+const S32 MATTYPE_SPECULAR = 2; // Specular map
+const S32 ALPHAMODE_MASK = 2; // Alpha masking mode
+const S32 BUMPY_TEXTURE = 18; // use supplied normal map
+const S32 SHINY_TEXTURE = 4; // use supplied specular map
+const S32 PBRTYPE_RENDER_MATERIAL_ID = 0; // Render Material ID
+const S32 PBRTYPE_BASE_COLOR = 1; // PBR Base Color
+const S32 PBRTYPE_METALLIC_ROUGHNESS = 2; // PBR Metallic
+const S32 PBRTYPE_EMISSIVE = 3; // PBR Emissive
+const S32 PBRTYPE_NORMAL = 4; // PBR Normal
+
+LLGLTFMaterial::TextureInfo texture_info_from_pbrtype(S32 pbr_type)
+{
+ switch (pbr_type)
+ {
+ case PBRTYPE_BASE_COLOR:
+ return LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR;
+ break;
+ case PBRTYPE_NORMAL:
+ return LLGLTFMaterial::GLTF_TEXTURE_INFO_NORMAL;
+ break;
+ case PBRTYPE_METALLIC_ROUGHNESS:
+ return LLGLTFMaterial::GLTF_TEXTURE_INFO_METALLIC_ROUGHNESS;
+ break;
+ case PBRTYPE_EMISSIVE:
+ return LLGLTFMaterial::GLTF_TEXTURE_INFO_EMISSIVE;
+ break;
+ default:
+ return LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT;
+ break;
+ }
+}
+
+void LLPanelFace::updateSelectedGLTFMaterials(std::function<void(LLGLTFMaterial*)> func)
+{
+ struct LLSelectedTEGLTFMaterialFunctor : public LLSelectedTEFunctor
+ {
+ LLSelectedTEGLTFMaterialFunctor(std::function<void(LLGLTFMaterial*)> func) : mFunc(func) {}
+ virtual ~LLSelectedTEGLTFMaterialFunctor() {};
+ bool apply(LLViewerObject* object, S32 face) override
+ {
+ LLGLTFMaterial new_override;
+ const LLTextureEntry* tep = object->getTE(face);
+ if (tep->getGLTFMaterialOverride())
+ {
+ new_override = *tep->getGLTFMaterialOverride();
+ }
+ mFunc(&new_override);
+ LLGLTFMaterialList::queueModify(object, face, &new_override);
+
+ return true;
+ }
+
+ std::function<void(LLGLTFMaterial*)> mFunc;
+ } select_func(func);
+
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&select_func);
+}
+
+template<typename T>
+void readSelectedGLTFMaterial(std::function<T(const LLGLTFMaterial*)> func, T& value, bool& identical, bool has_tolerance, T tolerance)
+{
+ struct LLSelectedTEGetGLTFMaterialFunctor : public LLSelectedTEGetFunctor<T>
+ {
+ LLSelectedTEGetGLTFMaterialFunctor(std::function<T(const LLGLTFMaterial*)> func) : mFunc(func) {}
+ virtual ~LLSelectedTEGetGLTFMaterialFunctor() {};
+ T get(LLViewerObject* object, S32 face) override
+ {
+ const LLTextureEntry* tep = object->getTE(face);
+ const LLGLTFMaterial* render_material = tep->getGLTFRenderMaterial();
+
+ return mFunc(render_material);
+ }
+
+ std::function<T(const LLGLTFMaterial*)> mFunc;
+ } select_func(func);
+ identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&select_func, value, has_tolerance, tolerance);
+}
+
+BOOST_STATIC_ASSERT(MATTYPE_DIFFUSE == LLRender::DIFFUSE_MAP && MATTYPE_NORMAL == LLRender::NORMAL_MAP && MATTYPE_SPECULAR == LLRender::SPECULAR_MAP);
+
+//
+// "Use texture" label for normal/specular type comboboxes
+// Filled in at initialization from translated strings
+//
+std::string USE_TEXTURE;
+
+LLRender::eTexIndex LLPanelFace::getTextureChannelToEdit()
+{
+ LLRender::eTexIndex channel_to_edit = LLRender::DIFFUSE_MAP;
+ if (mComboMatMedia)
+ {
+ U32 matmedia_selection = mComboMatMedia->getCurrentIndex();
+ if (matmedia_selection == MATMEDIA_MATERIAL)
+ {
+ LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type");
+ channel_to_edit = (LLRender::eTexIndex)radio_mat_type->getSelectedIndex();
+ }
+ if (matmedia_selection == MATMEDIA_PBR)
+ {
+ LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_pbr_type");
+ channel_to_edit = (LLRender::eTexIndex)radio_mat_type->getSelectedIndex();
+ }
+ }
+
+ channel_to_edit = (channel_to_edit == LLRender::NORMAL_MAP) ? (getCurrentNormalMap().isNull() ? LLRender::DIFFUSE_MAP : channel_to_edit) : channel_to_edit;
+ channel_to_edit = (channel_to_edit == LLRender::SPECULAR_MAP) ? (getCurrentSpecularMap().isNull() ? LLRender::DIFFUSE_MAP : channel_to_edit) : channel_to_edit;
+ return channel_to_edit;
+}
+
+LLRender::eTexIndex LLPanelFace::getTextureDropChannel()
+{
+ if (mComboMatMedia && mComboMatMedia->getCurrentIndex() == MATMEDIA_MATERIAL)
+ {
+ LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type");
+ return LLRender::eTexIndex(radio_mat_type->getSelectedIndex());
+ }
+
+ return LLRender::eTexIndex(MATTYPE_DIFFUSE);
+}
+
+LLGLTFMaterial::TextureInfo LLPanelFace::getPBRDropChannel()
+{
+ if (mComboMatMedia && mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR)
+ {
+ LLRadioGroup* radio_pbr_type = getChild<LLRadioGroup>("radio_pbr_type");
+ return texture_info_from_pbrtype(radio_pbr_type->getSelectedIndex());
+ }
+
+ return texture_info_from_pbrtype(PBRTYPE_BASE_COLOR);
+}
+
+// Things the UI provides...
+//
+LLUUID LLPanelFace::getCurrentNormalMap() { return getChild<LLTextureCtrl>("bumpytexture control")->getImageAssetID(); }
+LLUUID LLPanelFace::getCurrentSpecularMap() { return getChild<LLTextureCtrl>("shinytexture control")->getImageAssetID(); }
+U32 LLPanelFace::getCurrentShininess() { return getChild<LLComboBox>("combobox shininess")->getCurrentIndex(); }
+U32 LLPanelFace::getCurrentBumpiness() { return getChild<LLComboBox>("combobox bumpiness")->getCurrentIndex(); }
+U8 LLPanelFace::getCurrentDiffuseAlphaMode() { return (U8)getChild<LLComboBox>("combobox alphamode")->getCurrentIndex(); }
+U8 LLPanelFace::getCurrentAlphaMaskCutoff() { return (U8)getChild<LLUICtrl>("maskcutoff")->getValue().asInteger(); }
+U8 LLPanelFace::getCurrentEnvIntensity() { return (U8)getChild<LLUICtrl>("environment")->getValue().asInteger(); }
+U8 LLPanelFace::getCurrentGlossiness() { return (U8)getChild<LLUICtrl>("glossiness")->getValue().asInteger(); }
+F32 LLPanelFace::getCurrentBumpyRot() { return getChild<LLUICtrl>("bumpyRot")->getValue().asReal(); }
+F32 LLPanelFace::getCurrentBumpyScaleU() { return getChild<LLUICtrl>("bumpyScaleU")->getValue().asReal(); }
+F32 LLPanelFace::getCurrentBumpyScaleV() { return getChild<LLUICtrl>("bumpyScaleV")->getValue().asReal(); }
+F32 LLPanelFace::getCurrentBumpyOffsetU() { return getChild<LLUICtrl>("bumpyOffsetU")->getValue().asReal(); }
+F32 LLPanelFace::getCurrentBumpyOffsetV() { return getChild<LLUICtrl>("bumpyOffsetV")->getValue().asReal(); }
+F32 LLPanelFace::getCurrentShinyRot() { return getChild<LLUICtrl>("shinyRot")->getValue().asReal(); }
+F32 LLPanelFace::getCurrentShinyScaleU() { return getChild<LLUICtrl>("shinyScaleU")->getValue().asReal(); }
+F32 LLPanelFace::getCurrentShinyScaleV() { return getChild<LLUICtrl>("shinyScaleV")->getValue().asReal(); }
+F32 LLPanelFace::getCurrentShinyOffsetU() { return getChild<LLUICtrl>("shinyOffsetU")->getValue().asReal(); }
+F32 LLPanelFace::getCurrentShinyOffsetV() { return getChild<LLUICtrl>("shinyOffsetV")->getValue().asReal(); }
+
+//
+// Methods
+//
+
+bool LLPanelFace::postBuild()
+{
+ childSetCommitCallback("combobox shininess",&LLPanelFace::onCommitShiny,this);
+ childSetCommitCallback("combobox bumpiness",&LLPanelFace::onCommitBump,this);
+ childSetCommitCallback("combobox alphamode",&LLPanelFace::onCommitAlphaMode,this);
+ childSetCommitCallback("TexScaleU",&LLPanelFace::onCommitTextureScaleX, this);
+ childSetCommitCallback("TexScaleV",&LLPanelFace::onCommitTextureScaleY, this);
+ childSetCommitCallback("TexRot",&LLPanelFace::onCommitTextureRot, this);
+ childSetCommitCallback("rptctrl",&LLPanelFace::onCommitRepeatsPerMeter, this);
+ childSetCommitCallback("checkbox planar align",&LLPanelFace::onCommitPlanarAlign, this);
+ childSetCommitCallback("TexOffsetU",LLPanelFace::onCommitTextureOffsetX, this);
+ childSetCommitCallback("TexOffsetV",LLPanelFace::onCommitTextureOffsetY, this);
+
+ childSetCommitCallback("bumpyScaleU",&LLPanelFace::onCommitMaterialBumpyScaleX, this);
+ childSetCommitCallback("bumpyScaleV",&LLPanelFace::onCommitMaterialBumpyScaleY, this);
+ childSetCommitCallback("bumpyRot",&LLPanelFace::onCommitMaterialBumpyRot, this);
+ childSetCommitCallback("bumpyOffsetU",&LLPanelFace::onCommitMaterialBumpyOffsetX, this);
+ childSetCommitCallback("bumpyOffsetV",&LLPanelFace::onCommitMaterialBumpyOffsetY, this);
+ childSetCommitCallback("shinyScaleU",&LLPanelFace::onCommitMaterialShinyScaleX, this);
+ childSetCommitCallback("shinyScaleV",&LLPanelFace::onCommitMaterialShinyScaleY, this);
+ childSetCommitCallback("shinyRot",&LLPanelFace::onCommitMaterialShinyRot, this);
+ childSetCommitCallback("shinyOffsetU",&LLPanelFace::onCommitMaterialShinyOffsetX, this);
+ childSetCommitCallback("shinyOffsetV",&LLPanelFace::onCommitMaterialShinyOffsetY, this);
+ childSetCommitCallback("glossiness",&LLPanelFace::onCommitMaterialGloss, this);
+ childSetCommitCallback("environment",&LLPanelFace::onCommitMaterialEnv, this);
+ childSetCommitCallback("maskcutoff",&LLPanelFace::onCommitMaterialMaskCutoff, this);
+ childSetCommitCallback("add_media", &LLPanelFace::onClickBtnAddMedia, this);
+ childSetCommitCallback("delete_media", &LLPanelFace::onClickBtnDeleteMedia, this);
+
+ getChild<LLUICtrl>("gltfTextureScaleU")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFTextureScaleU, this, _1), nullptr);
+ getChild<LLUICtrl>("gltfTextureScaleV")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFTextureScaleV, this, _1), nullptr);
+ getChild<LLUICtrl>("gltfTextureRotation")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFRotation, this, _1), nullptr);
+ getChild<LLUICtrl>("gltfTextureOffsetU")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFTextureOffsetU, this, _1), nullptr);
+ getChild<LLUICtrl>("gltfTextureOffsetV")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFTextureOffsetV, this, _1), nullptr);
+
+ LLGLTFMaterialList::addSelectionUpdateCallback(&LLPanelFace::onMaterialOverrideReceived);
+ sMaterialOverrideSelection.connect();
+
+ childSetAction("button align",&LLPanelFace::onClickAutoFix,this);
+ childSetAction("button align textures", &LLPanelFace::onAlignTexture, this);
+ childSetAction("pbr_from_inventory", &LLPanelFace::onClickBtnLoadInvPBR, this);
+ childSetAction("edit_selected_pbr", &LLPanelFace::onClickBtnEditPBR, this);
+ childSetAction("save_selected_pbr", &LLPanelFace::onClickBtnSavePBR, this);
+
+ LLTextureCtrl* mTextureCtrl;
+ LLTextureCtrl* mShinyTextureCtrl;
+ LLTextureCtrl* mBumpyTextureCtrl;
+ LLColorSwatchCtrl* mColorSwatch;
+ LLColorSwatchCtrl* mShinyColorSwatch;
+
+ LLComboBox* mComboTexGen;
+
+ LLCheckBoxCtrl *mCheckFullbright;
+
+ LLTextBox* mLabelColorTransp;
+ LLSpinCtrl* mCtrlColorTransp; // transparency = 1 - alpha
+
+ LLSpinCtrl* mCtrlGlow;
+
+ setMouseOpaque(false);
+
+ LLTextureCtrl* pbr_ctrl = findChild<LLTextureCtrl>("pbr_control");
+ if (pbr_ctrl)
+ {
+ pbr_ctrl->setDefaultImageAssetID(LLUUID::null);
+ pbr_ctrl->setBlankImageAssetID(LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID);
+ pbr_ctrl->setCommitCallback(boost::bind(&LLPanelFace::onCommitPbr, this, _2));
+ pbr_ctrl->setOnCancelCallback(boost::bind(&LLPanelFace::onCancelPbr, this, _2));
+ pbr_ctrl->setOnSelectCallback(boost::bind(&LLPanelFace::onSelectPbr, this, _2));
+ pbr_ctrl->setDragCallback(boost::bind(&LLPanelFace::onDragPbr, this, _2));
+ pbr_ctrl->setOnTextureSelectedCallback(boost::bind(&LLPanelFace::onPbrSelectionChanged, this, _1));
+ pbr_ctrl->setOnCloseCallback(boost::bind(&LLPanelFace::onCloseTexturePicker, this, _2));
+
+ pbr_ctrl->setFollowsTop();
+ pbr_ctrl->setFollowsLeft();
+ pbr_ctrl->setImmediateFilterPermMask(PERM_NONE);
+ pbr_ctrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER);
+ pbr_ctrl->setBakeTextureEnabled(false);
+ pbr_ctrl->setInventoryPickType(PICK_MATERIAL);
+ }
+
+ mTextureCtrl = getChild<LLTextureCtrl>("texture control");
+ if(mTextureCtrl)
+ {
+ mTextureCtrl->setDefaultImageAssetID(DEFAULT_OBJECT_TEXTURE);
+ mTextureCtrl->setCommitCallback( boost::bind(&LLPanelFace::onCommitTexture, this, _2) );
+ mTextureCtrl->setOnCancelCallback( boost::bind(&LLPanelFace::onCancelTexture, this, _2) );
+ mTextureCtrl->setOnSelectCallback( boost::bind(&LLPanelFace::onSelectTexture, this, _2) );
+ mTextureCtrl->setDragCallback(boost::bind(&LLPanelFace::onDragTexture, this, _2));
+ mTextureCtrl->setOnTextureSelectedCallback(boost::bind(&LLPanelFace::onTextureSelectionChanged, this, _1));
+ mTextureCtrl->setOnCloseCallback( boost::bind(&LLPanelFace::onCloseTexturePicker, this, _2) );
+
+ mTextureCtrl->setFollowsTop();
+ mTextureCtrl->setFollowsLeft();
+ mTextureCtrl->setImmediateFilterPermMask(PERM_NONE);
+ mTextureCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER);
+ }
+
+ mShinyTextureCtrl = getChild<LLTextureCtrl>("shinytexture control");
+ if(mShinyTextureCtrl)
+ {
+ mShinyTextureCtrl->setDefaultImageAssetID(DEFAULT_OBJECT_SPECULAR);
+ mShinyTextureCtrl->setCommitCallback( boost::bind(&LLPanelFace::onCommitSpecularTexture, this, _2) );
+ mShinyTextureCtrl->setOnCancelCallback( boost::bind(&LLPanelFace::onCancelSpecularTexture, this, _2) );
+ mShinyTextureCtrl->setOnSelectCallback( boost::bind(&LLPanelFace::onSelectSpecularTexture, this, _2) );
+ mShinyTextureCtrl->setOnCloseCallback( boost::bind(&LLPanelFace::onCloseTexturePicker, this, _2) );
+
+ mShinyTextureCtrl->setDragCallback(boost::bind(&LLPanelFace::onDragTexture, this, _2));
+ mShinyTextureCtrl->setOnTextureSelectedCallback(boost::bind(&LLPanelFace::onTextureSelectionChanged, this, _1));
+ mShinyTextureCtrl->setFollowsTop();
+ mShinyTextureCtrl->setFollowsLeft();
+ mShinyTextureCtrl->setImmediateFilterPermMask(PERM_NONE);
+ mShinyTextureCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER);
+ }
+
+ mBumpyTextureCtrl = getChild<LLTextureCtrl>("bumpytexture control");
+ if(mBumpyTextureCtrl)
+ {
+ mBumpyTextureCtrl->setDefaultImageAssetID(DEFAULT_OBJECT_NORMAL);
+ mBumpyTextureCtrl->setBlankImageAssetID(BLANK_OBJECT_NORMAL);
+ mBumpyTextureCtrl->setCommitCallback( boost::bind(&LLPanelFace::onCommitNormalTexture, this, _2) );
+ mBumpyTextureCtrl->setOnCancelCallback( boost::bind(&LLPanelFace::onCancelNormalTexture, this, _2) );
+ mBumpyTextureCtrl->setOnSelectCallback( boost::bind(&LLPanelFace::onSelectNormalTexture, this, _2) );
+ mBumpyTextureCtrl->setOnCloseCallback( boost::bind(&LLPanelFace::onCloseTexturePicker, this, _2) );
+
+ mBumpyTextureCtrl->setDragCallback(boost::bind(&LLPanelFace::onDragTexture, this, _2));
+ mBumpyTextureCtrl->setOnTextureSelectedCallback(boost::bind(&LLPanelFace::onTextureSelectionChanged, this, _1));
+ mBumpyTextureCtrl->setFollowsTop();
+ mBumpyTextureCtrl->setFollowsLeft();
+ mBumpyTextureCtrl->setImmediateFilterPermMask(PERM_NONE);
+ mBumpyTextureCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER);
+ }
+
+ mColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
+ if(mColorSwatch)
+ {
+ mColorSwatch->setCommitCallback(boost::bind(&LLPanelFace::onCommitColor, this, _2));
+ mColorSwatch->setOnCancelCallback(boost::bind(&LLPanelFace::onCancelColor, this, _2));
+ mColorSwatch->setOnSelectCallback(boost::bind(&LLPanelFace::onSelectColor, this, _2));
+ mColorSwatch->setFollowsTop();
+ mColorSwatch->setFollowsLeft();
+ mColorSwatch->setCanApplyImmediately(true);
+ }
+
+ mShinyColorSwatch = getChild<LLColorSwatchCtrl>("shinycolorswatch");
+ if(mShinyColorSwatch)
+ {
+ mShinyColorSwatch->setCommitCallback(boost::bind(&LLPanelFace::onCommitShinyColor, this, _2));
+ mShinyColorSwatch->setOnCancelCallback(boost::bind(&LLPanelFace::onCancelShinyColor, this, _2));
+ mShinyColorSwatch->setOnSelectCallback(boost::bind(&LLPanelFace::onSelectShinyColor, this, _2));
+ mShinyColorSwatch->setFollowsTop();
+ mShinyColorSwatch->setFollowsLeft();
+ mShinyColorSwatch->setCanApplyImmediately(true);
+ }
+
+ mLabelColorTransp = getChild<LLTextBox>("color trans");
+ if(mLabelColorTransp)
+ {
+ mLabelColorTransp->setFollowsTop();
+ mLabelColorTransp->setFollowsLeft();
+ }
+
+ mCtrlColorTransp = getChild<LLSpinCtrl>("ColorTrans");
+ if(mCtrlColorTransp)
+ {
+ mCtrlColorTransp->setCommitCallback(boost::bind(&LLPanelFace::onCommitAlpha, this, _2));
+ mCtrlColorTransp->setPrecision(0);
+ mCtrlColorTransp->setFollowsTop();
+ mCtrlColorTransp->setFollowsLeft();
+ }
+
+ mCheckFullbright = getChild<LLCheckBoxCtrl>("checkbox fullbright");
+ if (mCheckFullbright)
+ {
+ mCheckFullbright->setCommitCallback(LLPanelFace::onCommitFullbright, this);
+ }
+
+ mComboTexGen = getChild<LLComboBox>("combobox texgen");
+ if(mComboTexGen)
+ {
+ mComboTexGen->setCommitCallback(LLPanelFace::onCommitTexGen, this);
+ mComboTexGen->setFollows(FOLLOWS_LEFT | FOLLOWS_TOP);
+ }
+
+ mComboMatMedia = getChild<LLComboBox>("combobox matmedia");
+ if(mComboMatMedia)
+ {
+ mComboMatMedia->setCommitCallback(LLPanelFace::onCommitMaterialsMedia,this);
+ mComboMatMedia->selectNthItem(MATMEDIA_MATERIAL);
+ }
+
+ LLRadioGroup* radio_mat_type = findChild<LLRadioGroup>("radio_material_type");
+ if(radio_mat_type)
+ {
+ radio_mat_type->setCommitCallback(LLPanelFace::onCommitMaterialType, this);
+ radio_mat_type->selectNthItem(MATTYPE_DIFFUSE);
+ }
+
+ LLRadioGroup* radio_pbr_type = findChild<LLRadioGroup>("radio_pbr_type");
+ if (radio_pbr_type)
+ {
+ radio_pbr_type->setCommitCallback(LLPanelFace::onCommitPbrType, this);
+ radio_pbr_type->selectNthItem(PBRTYPE_RENDER_MATERIAL_ID);
+ }
+
+ mCtrlGlow = getChild<LLSpinCtrl>("glow");
+ if(mCtrlGlow)
+ {
+ mCtrlGlow->setCommitCallback(LLPanelFace::onCommitGlow, this);
+ }
+
+ mMenuClipboardColor = getChild<LLMenuButton>("clipboard_color_params_btn");
+ mMenuClipboardTexture = getChild<LLMenuButton>("clipboard_texture_params_btn");
+
+ mTitleMedia = getChild<LLMediaCtrl>("title_media");
+ mTitleMediaText = getChild<LLTextBox>("media_info");
+
+ clearCtrls();
+
+ return true;
+}
+
+LLPanelFace::LLPanelFace()
+: LLPanel(),
+ mIsAlpha(false),
+ mComboMatMedia(NULL),
+ mTitleMedia(NULL),
+ mTitleMediaText(NULL),
+ mNeedMediaTitle(true)
+{
+ USE_TEXTURE = LLTrans::getString("use_texture");
+ mCommitCallbackRegistrar.add("PanelFace.menuDoToSelected", boost::bind(&LLPanelFace::menuDoToSelected, this, _2));
+ mEnableCallbackRegistrar.add("PanelFace.menuEnable", boost::bind(&LLPanelFace::menuEnableItem, this, _2));
+}
+
+LLPanelFace::~LLPanelFace()
+{
+ unloadMedia();
+}
+
+void LLPanelFace::onVisibilityChange(bool new_visibility)
+{
+ if (new_visibility)
+ {
+ gAgent.showLatestFeatureNotification("gltf");
+ }
+ LLPanel::onVisibilityChange(new_visibility);
+}
+
+void LLPanelFace::draw()
+{
+ updateCopyTexButton();
+
+ // grab media name/title and update the UI widget
+ // Todo: move it, it's preferable not to update
+ // labels inside draw
+ updateMediaTitle();
+
+ LLPanel::draw();
+
+ if (sMaterialOverrideSelection.update())
+ {
+ setMaterialOverridesFromSelection();
+ LLMaterialEditor::updateLive();
+ }
+}
+
+void LLPanelFace::sendTexture()
+{
+ LLTextureCtrl* mTextureCtrl = getChild<LLTextureCtrl>("texture control");
+ if(!mTextureCtrl) return;
+ if( !mTextureCtrl->getTentative() )
+ {
+ // we grab the item id first, because we want to do a
+ // permissions check in the selection manager. ARGH!
+ LLUUID id = mTextureCtrl->getImageItemID();
+ if(id.isNull())
+ {
+ id = mTextureCtrl->getImageAssetID();
+ }
+ if (!LLSelectMgr::getInstance()->selectionSetImage(id))
+ {
+ // need to refresh value in texture ctrl
+ refresh();
+ }
+ }
+}
+
+void LLPanelFace::sendBump(U32 bumpiness)
+{
+ LLTextureCtrl* bumpytexture_ctrl = getChild<LLTextureCtrl>("bumpytexture control");
+ if (bumpiness < BUMPY_TEXTURE)
+{
+ LL_DEBUGS("Materials") << "clearing bumptexture control" << LL_ENDL;
+ bumpytexture_ctrl->clear();
+ bumpytexture_ctrl->setImageAssetID(LLUUID());
+ }
+
+ updateBumpyControls(bumpiness == BUMPY_TEXTURE, true);
+
+ LLUUID current_normal_map = bumpytexture_ctrl->getImageAssetID();
+
+ U8 bump = (U8) bumpiness & TEM_BUMP_MASK;
+
+ // Clear legacy bump to None when using an actual normal map
+ //
+ if (!current_normal_map.isNull())
+ bump = 0;
+
+ // Set the normal map or reset it to null as appropriate
+ //
+ LLSelectedTEMaterial::setNormalID(this, current_normal_map);
+
+ LLSelectMgr::getInstance()->selectionSetBumpmap( bump, bumpytexture_ctrl->getImageItemID() );
+}
+
+void LLPanelFace::sendTexGen()
+{
+ LLComboBox* mComboTexGen = getChild<LLComboBox>("combobox texgen");
+ if(!mComboTexGen)return;
+ U8 tex_gen = (U8) mComboTexGen->getCurrentIndex() << TEM_TEX_GEN_SHIFT;
+ LLSelectMgr::getInstance()->selectionSetTexGen( tex_gen );
+}
+
+void LLPanelFace::sendShiny(U32 shininess)
+{
+ LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>("shinytexture control");
+
+ if (shininess < SHINY_TEXTURE)
+{
+ texture_ctrl->clear();
+ texture_ctrl->setImageAssetID(LLUUID());
+ }
+
+ LLUUID specmap = getCurrentSpecularMap();
+
+ U8 shiny = (U8) shininess & TEM_SHINY_MASK;
+ if (!specmap.isNull())
+ shiny = 0;
+
+ LLSelectedTEMaterial::setSpecularID(this, specmap);
+
+ LLSelectMgr::getInstance()->selectionSetShiny( shiny, texture_ctrl->getImageItemID() );
+
+ updateShinyControls(!specmap.isNull(), true);
+
+}
+
+void LLPanelFace::sendFullbright()
+{
+ LLCheckBoxCtrl* mCheckFullbright = getChild<LLCheckBoxCtrl>("checkbox fullbright");
+ if(!mCheckFullbright)return;
+ U8 fullbright = mCheckFullbright->get() ? TEM_FULLBRIGHT_MASK : 0;
+ LLSelectMgr::getInstance()->selectionSetFullbright( fullbright );
+}
+
+void LLPanelFace::sendColor()
+{
+
+ LLColorSwatchCtrl* mColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
+ if(!mColorSwatch)return;
+ LLColor4 color = mColorSwatch->get();
+
+ LLSelectMgr::getInstance()->selectionSetColorOnly( color );
+}
+
+void LLPanelFace::sendAlpha()
+{
+ LLSpinCtrl* mCtrlColorTransp = getChild<LLSpinCtrl>("ColorTrans");
+ if(!mCtrlColorTransp)return;
+ F32 alpha = (100.f - mCtrlColorTransp->get()) / 100.f;
+
+ LLSelectMgr::getInstance()->selectionSetAlphaOnly( alpha );
+}
+
+
+void LLPanelFace::sendGlow()
+{
+ LLSpinCtrl* mCtrlGlow = getChild<LLSpinCtrl>("glow");
+ llassert(mCtrlGlow);
+ if (mCtrlGlow)
+ {
+ F32 glow = mCtrlGlow->get();
+ LLSelectMgr::getInstance()->selectionSetGlow( glow );
+ }
+}
+
+struct LLPanelFaceSetTEFunctor : public LLSelectedTEFunctor
+{
+ LLPanelFaceSetTEFunctor(LLPanelFace* panel) : mPanel(panel) {}
+ virtual bool apply(LLViewerObject* object, S32 te)
+ {
+ bool valid;
+ F32 value;
+ std::string prefix;
+
+ // Effectively the same as MATMEDIA_PBR sans using different radio,
+ // separate for the sake of clarity
+ LLRadioGroup * radio_mat_type = mPanel->getChild<LLRadioGroup>("radio_material_type");
+ switch (radio_mat_type->getSelectedIndex())
+ {
+ case MATTYPE_DIFFUSE:
+ prefix = "Tex";
+ break;
+ case MATTYPE_NORMAL:
+ prefix = "bumpy";
+ break;
+ case MATTYPE_SPECULAR:
+ prefix = "shiny";
+ break;
+ }
+
+ LLSpinCtrl * ctrlTexScaleS = mPanel->getChild<LLSpinCtrl>(prefix + "ScaleU");
+ LLSpinCtrl * ctrlTexScaleT = mPanel->getChild<LLSpinCtrl>(prefix + "ScaleV");
+ LLSpinCtrl * ctrlTexOffsetS = mPanel->getChild<LLSpinCtrl>(prefix + "OffsetU");
+ LLSpinCtrl * ctrlTexOffsetT = mPanel->getChild<LLSpinCtrl>(prefix + "OffsetV");
+ LLSpinCtrl * ctrlTexRotation = mPanel->getChild<LLSpinCtrl>(prefix + "Rot");
+
+ LLComboBox* comboTexGen = mPanel->getChild<LLComboBox>("combobox texgen");
+ LLCheckBoxCtrl* cb_planar_align = mPanel->getChild<LLCheckBoxCtrl>("checkbox planar align");
+ bool align_planar = (cb_planar_align && cb_planar_align->get());
+
+ llassert(comboTexGen);
+ llassert(object);
+
+ if (ctrlTexScaleS)
+ {
+ valid = !ctrlTexScaleS->getTentative(); // || !checkFlipScaleS->getTentative();
+ if (valid || align_planar)
+ {
+ value = ctrlTexScaleS->get();
+ if (comboTexGen &&
+ comboTexGen->getCurrentIndex() == 1)
+ {
+ value *= 0.5f;
+ }
+ object->setTEScaleS( te, value );
+
+ if (align_planar)
+ {
+ LLPanelFace::LLSelectedTEMaterial::setNormalRepeatX(mPanel, value, te, object->getID());
+ LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatX(mPanel, value, te, object->getID());
+ }
+ }
+ }
+
+ if (ctrlTexScaleT)
+ {
+ valid = !ctrlTexScaleT->getTentative(); // || !checkFlipScaleT->getTentative();
+ if (valid || align_planar)
+ {
+ value = ctrlTexScaleT->get();
+ //if( checkFlipScaleT->get() )
+ //{
+ // value = -value;
+ //}
+ if (comboTexGen &&
+ comboTexGen->getCurrentIndex() == 1)
+ {
+ value *= 0.5f;
+ }
+ object->setTEScaleT( te, value );
+
+ if (align_planar)
+ {
+ LLPanelFace::LLSelectedTEMaterial::setNormalRepeatY(mPanel, value, te, object->getID());
+ LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatY(mPanel, value, te, object->getID());
+ }
+ }
+ }
+
+ if (ctrlTexOffsetS)
+ {
+ valid = !ctrlTexOffsetS->getTentative();
+ if (valid || align_planar)
+ {
+ value = ctrlTexOffsetS->get();
+ object->setTEOffsetS( te, value );
+
+ if (align_planar)
+ {
+ LLPanelFace::LLSelectedTEMaterial::setNormalOffsetX(mPanel, value, te, object->getID());
+ LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetX(mPanel, value, te, object->getID());
+ }
+ }
+ }
+
+ if (ctrlTexOffsetT)
+ {
+ valid = !ctrlTexOffsetT->getTentative();
+ if (valid || align_planar)
+ {
+ value = ctrlTexOffsetT->get();
+ object->setTEOffsetT( te, value );
+
+ if (align_planar)
+ {
+ LLPanelFace::LLSelectedTEMaterial::setNormalOffsetY(mPanel, value, te, object->getID());
+ LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetY(mPanel, value, te, object->getID());
+ }
+ }
+ }
+
+ if (ctrlTexRotation)
+ {
+ valid = !ctrlTexRotation->getTentative();
+ if (valid || align_planar)
+ {
+ value = ctrlTexRotation->get() * DEG_TO_RAD;
+ object->setTERotation( te, value );
+
+ if (align_planar)
+ {
+ LLPanelFace::LLSelectedTEMaterial::setNormalRotation(mPanel, value, te, object->getID());
+ LLPanelFace::LLSelectedTEMaterial::setSpecularRotation(mPanel, value, te, object->getID());
+ }
+ }
+ }
+ return true;
+ }
+private:
+ LLPanelFace* mPanel;
+};
+
+// Functor that aligns a face to mCenterFace
+struct LLPanelFaceSetAlignedTEFunctor : public LLSelectedTEFunctor
+{
+ LLPanelFaceSetAlignedTEFunctor(LLPanelFace* panel, LLFace* center_face) :
+ mPanel(panel),
+ mCenterFace(center_face) {}
+
+ virtual bool apply(LLViewerObject* object, S32 te)
+ {
+ LLFace* facep = object->mDrawable->getFace(te);
+ if (!facep)
+ {
+ return true;
+ }
+
+ if (facep->getViewerObject()->getVolume()->getNumVolumeFaces() <= te)
+ {
+ return true;
+ }
+
+ bool set_aligned = true;
+ if (facep == mCenterFace)
+ {
+ set_aligned = false;
+ }
+ if (set_aligned)
+ {
+ LLVector2 uv_offset, uv_scale;
+ F32 uv_rot;
+ set_aligned = facep->calcAlignedPlanarTE(mCenterFace, &uv_offset, &uv_scale, &uv_rot);
+ if (set_aligned)
+ {
+ object->setTEOffset(te, uv_offset.mV[VX], uv_offset.mV[VY]);
+ object->setTEScale(te, uv_scale.mV[VX], uv_scale.mV[VY]);
+ object->setTERotation(te, uv_rot);
+
+ LLPanelFace::LLSelectedTEMaterial::setNormalRotation(mPanel, uv_rot, te, object->getID());
+ LLPanelFace::LLSelectedTEMaterial::setSpecularRotation(mPanel, uv_rot, te, object->getID());
+
+ LLPanelFace::LLSelectedTEMaterial::setNormalOffsetX(mPanel, uv_offset.mV[VX], te, object->getID());
+ LLPanelFace::LLSelectedTEMaterial::setNormalOffsetY(mPanel, uv_offset.mV[VY], te, object->getID());
+ LLPanelFace::LLSelectedTEMaterial::setNormalRepeatX(mPanel, uv_scale.mV[VX], te, object->getID());
+ LLPanelFace::LLSelectedTEMaterial::setNormalRepeatY(mPanel, uv_scale.mV[VY], te, object->getID());
+
+ LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetX(mPanel, uv_offset.mV[VX], te, object->getID());
+ LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetY(mPanel, uv_offset.mV[VY], te, object->getID());
+ LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatX(mPanel, uv_scale.mV[VX], te, object->getID());
+ LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatY(mPanel, uv_scale.mV[VY], te, object->getID());
+ }
+ }
+ if (!set_aligned)
+ {
+ LLPanelFaceSetTEFunctor setfunc(mPanel);
+ setfunc.apply(object, te);
+ }
+ return true;
+ }
+private:
+ LLPanelFace* mPanel;
+ LLFace* mCenterFace;
+};
+
+struct LLPanelFaceSetAlignedConcreteTEFunctor : public LLSelectedTEFunctor
+{
+ LLPanelFaceSetAlignedConcreteTEFunctor(LLPanelFace* panel, LLFace* center_face, LLRender::eTexIndex map) :
+ mPanel(panel),
+ mChefFace(center_face),
+ mMap(map)
+ {}
+
+ virtual bool apply(LLViewerObject* object, S32 te)
+ {
+ LLFace* facep = object->mDrawable->getFace(te);
+ if (!facep)
+ {
+ return true;
+ }
+
+ if (facep->getViewerObject()->getVolume()->getNumVolumeFaces() <= te)
+ {
+ return true;
+ }
+
+ if (mChefFace != facep)
+ {
+ LLVector2 uv_offset, uv_scale;
+ F32 uv_rot;
+ if (facep->calcAlignedPlanarTE(mChefFace, &uv_offset, &uv_scale, &uv_rot, mMap))
+ {
+ switch (mMap)
+ {
+ case LLRender::DIFFUSE_MAP:
+ object->setTEOffset(te, uv_offset.mV[VX], uv_offset.mV[VY]);
+ object->setTEScale(te, uv_scale.mV[VX], uv_scale.mV[VY]);
+ object->setTERotation(te, uv_rot);
+ break;
+ case LLRender::NORMAL_MAP:
+ LLPanelFace::LLSelectedTEMaterial::setNormalRotation(mPanel, uv_rot, te, object->getID());
+ LLPanelFace::LLSelectedTEMaterial::setNormalOffsetX(mPanel, uv_offset.mV[VX], te, object->getID());
+ LLPanelFace::LLSelectedTEMaterial::setNormalOffsetY(mPanel, uv_offset.mV[VY], te, object->getID());
+ LLPanelFace::LLSelectedTEMaterial::setNormalRepeatX(mPanel, uv_scale.mV[VX], te, object->getID());
+ LLPanelFace::LLSelectedTEMaterial::setNormalRepeatY(mPanel, uv_scale.mV[VY], te, object->getID());
+ break;
+ case LLRender::SPECULAR_MAP:
+ LLPanelFace::LLSelectedTEMaterial::setSpecularRotation(mPanel, uv_rot, te, object->getID());
+ LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetX(mPanel, uv_offset.mV[VX], te, object->getID());
+ LLPanelFace::LLSelectedTEMaterial::setSpecularOffsetY(mPanel, uv_offset.mV[VY], te, object->getID());
+ LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatX(mPanel, uv_scale.mV[VX], te, object->getID());
+ LLPanelFace::LLSelectedTEMaterial::setSpecularRepeatY(mPanel, uv_scale.mV[VY], te, object->getID());
+ break;
+ default: /*make compiler happy*/
+ break;
+ }
+ }
+ }
+
+ return true;
+ }
+private:
+ LLPanelFace* mPanel;
+ LLFace* mChefFace;
+ LLRender::eTexIndex mMap;
+};
+
+// Functor that tests if a face is aligned to mCenterFace
+struct LLPanelFaceGetIsAlignedTEFunctor : public LLSelectedTEFunctor
+{
+ LLPanelFaceGetIsAlignedTEFunctor(LLFace* center_face) :
+ mCenterFace(center_face) {}
+
+ virtual bool apply(LLViewerObject* object, S32 te)
+ {
+ LLFace* facep = object->mDrawable->getFace(te);
+ if (!facep)
+ {
+ return false;
+ }
+
+ if (facep->getViewerObject()->getVolume()->getNumVolumeFaces() <= te)
+ { //volume face does not exist, can't be aligned
+ return false;
+ }
+
+ if (facep == mCenterFace)
+ {
+ return true;
+ }
+
+ LLVector2 aligned_st_offset, aligned_st_scale;
+ F32 aligned_st_rot;
+ if ( facep->calcAlignedPlanarTE(mCenterFace, &aligned_st_offset, &aligned_st_scale, &aligned_st_rot) )
+ {
+ const LLTextureEntry* tep = facep->getTextureEntry();
+ LLVector2 st_offset, st_scale;
+ tep->getOffset(&st_offset.mV[VX], &st_offset.mV[VY]);
+ tep->getScale(&st_scale.mV[VX], &st_scale.mV[VY]);
+ F32 st_rot = tep->getRotation();
+
+ bool eq_offset_x = is_approx_equal_fraction(st_offset.mV[VX], aligned_st_offset.mV[VX], 12);
+ bool eq_offset_y = is_approx_equal_fraction(st_offset.mV[VY], aligned_st_offset.mV[VY], 12);
+ bool eq_scale_x = is_approx_equal_fraction(st_scale.mV[VX], aligned_st_scale.mV[VX], 12);
+ bool eq_scale_y = is_approx_equal_fraction(st_scale.mV[VY], aligned_st_scale.mV[VY], 12);
+ bool eq_rot = is_approx_equal_fraction(st_rot, aligned_st_rot, 6);
+
+ // needs a fuzzy comparison, because of fp errors
+ if (eq_offset_x &&
+ eq_offset_y &&
+ eq_scale_x &&
+ eq_scale_y &&
+ eq_rot)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+private:
+ LLFace* mCenterFace;
+};
+
+struct LLPanelFaceSendFunctor : public LLSelectedObjectFunctor
+{
+ virtual bool apply(LLViewerObject* object)
+ {
+ object->sendTEUpdate();
+ return true;
+ }
+};
+
+void LLPanelFace::sendTextureInfo()
+{
+ if ((bool)childGetValue("checkbox planar align").asBoolean())
+ {
+ LLFace* last_face = NULL;
+ bool identical_face =false;
+ LLSelectedTE::getFace(last_face, identical_face);
+ LLPanelFaceSetAlignedTEFunctor setfunc(this, last_face);
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
+ }
+ else
+ {
+ LLPanelFaceSetTEFunctor setfunc(this);
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
+ }
+
+ LLPanelFaceSendFunctor sendfunc;
+ LLSelectMgr::getInstance()->getSelection()->applyToObjects(&sendfunc);
+}
+
+void LLPanelFace::alignTestureLayer()
+{
+ LLFace* last_face = NULL;
+ bool identical_face = false;
+ LLSelectedTE::getFace(last_face, identical_face);
+
+ LLRadioGroup * radio_mat_type = getChild<LLRadioGroup>("radio_material_type");
+ LLPanelFaceSetAlignedConcreteTEFunctor setfunc(this, last_face, static_cast<LLRender::eTexIndex>(radio_mat_type->getSelectedIndex()));
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
+}
+
+void LLPanelFace::getState()
+{
+ updateUI();
+}
+
+void LLPanelFace::updateUI(bool force_set_values /*false*/)
+{ //set state of UI to match state of texture entry(ies) (calls setEnabled, setValue, etc, but NOT setVisible)
+ LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode();
+ LLViewerObject* objectp = node ? node->getObject() : NULL;
+
+ if (objectp
+ && objectp->getPCode() == LL_PCODE_VOLUME
+ && objectp->permModify())
+ {
+ bool editable = objectp->permModify() && !objectp->isPermanentEnforced();
+ bool attachment = objectp->isAttachment();
+
+ bool has_pbr_material;
+ bool has_faces_without_pbr;
+ updateUIGLTF(objectp, has_pbr_material, has_faces_without_pbr, force_set_values);
+
+ const bool has_material = !has_pbr_material;
+
+ // only turn on auto-adjust button if there is a media renderer and the media is loaded
+ childSetEnabled("button align", editable);
+
+ if (mComboMatMedia->getCurrentIndex() < MATMEDIA_MATERIAL)
+ {
+ // When selecting an object with a pbr and UI combo is not set,
+ // set to pbr option, otherwise to a texture (material)
+ if (has_pbr_material)
+ {
+ mComboMatMedia->selectNthItem(MATMEDIA_PBR);
+ }
+ else
+ {
+ mComboMatMedia->selectNthItem(MATMEDIA_MATERIAL);
+ }
+ }
+
+ // *NOTE: The "identical" variable is currently only used to decide if
+ // the texgen control should be tentative - this is not used by GLTF
+ // materials. -Cosmic;2022-11-09
+ bool identical = true; // true because it is anded below
+ bool identical_diffuse = false;
+ bool identical_norm = false;
+ bool identical_spec = false;
+
+ LLTextureCtrl *texture_ctrl = getChild<LLTextureCtrl>("texture control");
+ LLTextureCtrl *shinytexture_ctrl = getChild<LLTextureCtrl>("shinytexture control");
+ LLTextureCtrl *bumpytexture_ctrl = getChild<LLTextureCtrl>("bumpytexture control");
+
+ LLUUID id;
+ LLUUID normmap_id;
+ LLUUID specmap_id;
+
+ LLSelectedTE::getTexId(id, identical_diffuse);
+ LLSelectedTEMaterial::getNormalID(normmap_id, identical_norm);
+ LLSelectedTEMaterial::getSpecularID(specmap_id, identical_spec);
+
+ static S32 selected_te = -1;
+ static LLUUID prev_obj_id;
+ if ((LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool()) &&
+ !LLSelectMgr::getInstance()->getSelection()->isMultipleTESelected())
+ {
+ S32 new_selection = -1; // Don't use getLastSelectedTE, it could have been deselected
+ S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces());
+ for (S32 te = 0; te < num_tes; ++te)
+ {
+ if (node->isTESelected(te))
+ {
+ new_selection = te;
+ break;
+ }
+ }
+
+ if ((new_selection != selected_te)
+ || (prev_obj_id != objectp->getID()))
+ {
+ bool te_has_media = objectp->getTE(new_selection) && objectp->getTE(new_selection)->hasMedia();
+ bool te_has_pbr = objectp->getRenderMaterialID(new_selection).notNull();
+
+ if (te_has_pbr && !((mComboMatMedia->getCurrentIndex() == MATMEDIA_MEDIA) && te_has_media))
+ {
+ mComboMatMedia->selectNthItem(MATMEDIA_PBR);
+ }
+ else if (te_has_media)
+ {
+ mComboMatMedia->selectNthItem(MATMEDIA_MEDIA);
+ }
+ else if (id.notNull() || normmap_id.notNull() || specmap_id.notNull())
+ {
+ mComboMatMedia->selectNthItem(MATMEDIA_MATERIAL);
+ }
+ selected_te = new_selection;
+ prev_obj_id = objectp->getID();
+ }
+ }
+ else
+ {
+ if (prev_obj_id != objectp->getID())
+ {
+ if (has_pbr_material && (mComboMatMedia->getCurrentIndex() == MATMEDIA_MATERIAL))
+ {
+ mComboMatMedia->selectNthItem(MATMEDIA_PBR);
+ }
+ else if (!has_pbr_material && (mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR))
+ {
+ mComboMatMedia->selectNthItem(MATMEDIA_MATERIAL);
+ }
+ prev_obj_id = objectp->getID();
+ }
+ }
+ mComboMatMedia->setEnabled(editable);
+
+ LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type");
+ if (radio_mat_type->getSelectedIndex() < MATTYPE_DIFFUSE)
+ {
+ radio_mat_type->selectNthItem(MATTYPE_DIFFUSE);
+ }
+ radio_mat_type->setEnabled(editable);
+
+ LLRadioGroup* radio_pbr_type = getChild<LLRadioGroup>("radio_pbr_type");
+ if (radio_pbr_type->getSelectedIndex() < PBRTYPE_RENDER_MATERIAL_ID)
+ {
+ radio_pbr_type->selectNthItem(PBRTYPE_RENDER_MATERIAL_ID);
+ }
+ radio_pbr_type->setEnabled(editable);
+ const bool pbr_selected = mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR;
+ const bool texture_info_selected = pbr_selected && radio_pbr_type->getSelectedIndex() != PBRTYPE_RENDER_MATERIAL_ID;
+
+ getChildView("checkbox_sync_settings")->setEnabled(editable);
+ childSetValue("checkbox_sync_settings", gSavedSettings.getBOOL("SyncMaterialSettings"));
+
+ updateVisibility(objectp);
+
+ // Color swatch
+ {
+ getChildView("color label")->setEnabled(editable);
+ }
+ LLColorSwatchCtrl* color_swatch = findChild<LLColorSwatchCtrl>("colorswatch");
+
+ LLColor4 color = LLColor4::white;
+ bool identical_color = false;
+
+ if (color_swatch)
+ {
+ LLSelectedTE::getColor(color, identical_color);
+ LLColor4 prev_color = color_swatch->get();
+
+ color_swatch->setOriginal(color);
+ color_swatch->set(color, force_set_values || (prev_color != color) || !editable);
+
+ color_swatch->setValid(editable && !has_pbr_material);
+ color_swatch->setEnabled( editable && !has_pbr_material);
+ color_swatch->setCanApplyImmediately( editable && !has_pbr_material);
+ }
+
+ // Color transparency
+ getChildView("color trans")->setEnabled(editable);
+
+ F32 transparency = (1.f - color.mV[VALPHA]) * 100.f;
+ getChild<LLUICtrl>("ColorTrans")->setValue(editable ? transparency : 0);
+ getChildView("ColorTrans")->setEnabled(editable && has_material);
+
+ U8 shiny = 0;
+ bool identical_shiny = false;
+
+ // Shiny
+ LLSelectedTE::getShiny(shiny, identical_shiny);
+ identical = identical && identical_shiny;
+
+ shiny = specmap_id.isNull() ? shiny : SHINY_TEXTURE;
+
+ LLCtrlSelectionInterface* combobox_shininess = childGetSelectionInterface("combobox shininess");
+ if (combobox_shininess)
+ {
+ combobox_shininess->selectNthItem((S32)shiny);
+ }
+
+ getChildView("label shininess")->setEnabled(editable);
+ getChildView("combobox shininess")->setEnabled(editable);
+
+ getChildView("label glossiness")->setEnabled(editable);
+ getChildView("glossiness")->setEnabled(editable);
+
+ getChildView("label environment")->setEnabled(editable);
+ getChildView("environment")->setEnabled(editable);
+ getChildView("label shinycolor")->setEnabled(editable);
+
+ getChild<LLUICtrl>("combobox shininess")->setTentative(!identical_spec);
+ getChild<LLUICtrl>("glossiness")->setTentative(!identical_spec);
+ getChild<LLUICtrl>("environment")->setTentative(!identical_spec);
+ getChild<LLUICtrl>("shinycolorswatch")->setTentative(!identical_spec);
+
+ LLColorSwatchCtrl* mShinyColorSwatch = getChild<LLColorSwatchCtrl>("shinycolorswatch");
+ if (mShinyColorSwatch)
+ {
+ mShinyColorSwatch->setValid(editable);
+ mShinyColorSwatch->setEnabled( editable );
+ mShinyColorSwatch->setCanApplyImmediately( editable );
+ }
+
+ U8 bumpy = 0;
+ // Bumpy
+ {
+ bool identical_bumpy = false;
+ LLSelectedTE::getBumpmap(bumpy,identical_bumpy);
+
+ LLUUID norm_map_id = getCurrentNormalMap();
+ LLCtrlSelectionInterface* combobox_bumpiness = childGetSelectionInterface("combobox bumpiness");
+
+ bumpy = norm_map_id.isNull() ? bumpy : BUMPY_TEXTURE;
+
+ if (combobox_bumpiness)
+ {
+ combobox_bumpiness->selectNthItem((S32)bumpy);
+ }
+ else
+ {
+ LL_WARNS() << "failed childGetSelectionInterface for 'combobox bumpiness'" << LL_ENDL;
+ }
+
+ getChildView("combobox bumpiness")->setEnabled(editable);
+ getChild<LLUICtrl>("combobox bumpiness")->setTentative(!identical_bumpy);
+ getChildView("label bumpiness")->setEnabled(editable);
+ }
+
+ // Texture
+ {
+ mIsAlpha = false;
+ LLGLenum image_format = GL_RGB;
+ bool identical_image_format = false;
+ LLSelectedTE::getImageFormat(image_format, identical_image_format);
+
+ mIsAlpha = false;
+ switch (image_format)
+ {
+ case GL_RGBA:
+ case GL_ALPHA:
+ {
+ mIsAlpha = true;
+ }
+ break;
+
+ case GL_RGB: break;
+ default:
+ {
+ LL_WARNS() << "Unexpected tex format in LLPanelFace...resorting to no alpha" << LL_ENDL;
+ }
+ break;
+ }
+
+ if (LLViewerMedia::getInstance()->textureHasMedia(id))
+ {
+ getChildView("button align")->setEnabled(editable);
+ }
+
+ // Diffuse Alpha Mode
+
+ // Init to the default that is appropriate for the alpha content of the asset
+ //
+ U8 alpha_mode = mIsAlpha ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : LLMaterial::DIFFUSE_ALPHA_MODE_NONE;
+
+ bool identical_alpha_mode = false;
+
+ // See if that's been overridden by a material setting for same...
+ //
+ LLSelectedTEMaterial::getCurrentDiffuseAlphaMode(alpha_mode, identical_alpha_mode, mIsAlpha);
+
+ LLCtrlSelectionInterface* combobox_alphamode = childGetSelectionInterface("combobox alphamode");
+ if (combobox_alphamode)
+ {
+ //it is invalid to have any alpha mode other than blend if transparency is greater than zero ...
+ // Want masking? Want emissive? Tough! You get BLEND!
+ alpha_mode = (transparency > 0.f) ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : alpha_mode;
+
+ // ... unless there is no alpha channel in the texture, in which case alpha mode MUST be none
+ alpha_mode = mIsAlpha ? alpha_mode : LLMaterial::DIFFUSE_ALPHA_MODE_NONE;
+
+ combobox_alphamode->selectNthItem(alpha_mode);
+ }
+ else
+ {
+ LL_WARNS() << "failed childGetSelectionInterface for 'combobox alphamode'" << LL_ENDL;
+ }
+
+ updateAlphaControls();
+
+ if (texture_ctrl)
+ {
+ if (identical_diffuse)
+ {
+ texture_ctrl->setTentative(false);
+ texture_ctrl->setEnabled(editable && !has_pbr_material);
+ texture_ctrl->setImageAssetID(id);
+ getChildView("combobox alphamode")->setEnabled(editable && mIsAlpha && transparency <= 0.f && !has_pbr_material);
+ getChildView("label alphamode")->setEnabled(editable && mIsAlpha && !has_pbr_material);
+ getChildView("maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material);
+ getChildView("label maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material);
+
+ texture_ctrl->setBakeTextureEnabled(true);
+ }
+ else if (id.isNull())
+ {
+ // None selected
+ texture_ctrl->setTentative(false);
+ texture_ctrl->setEnabled(false);
+ texture_ctrl->setImageAssetID(LLUUID::null);
+ getChildView("combobox alphamode")->setEnabled(false);
+ getChildView("label alphamode")->setEnabled(false);
+ getChildView("maskcutoff")->setEnabled(false);
+ getChildView("label maskcutoff")->setEnabled(false);
+
+ texture_ctrl->setBakeTextureEnabled(false);
+ }
+ else
+ {
+ // Tentative: multiple selected with different textures
+ texture_ctrl->setTentative(true);
+ texture_ctrl->setEnabled(editable && !has_pbr_material);
+ texture_ctrl->setImageAssetID(id);
+ getChildView("combobox alphamode")->setEnabled(editable && mIsAlpha && transparency <= 0.f && !has_pbr_material);
+ getChildView("label alphamode")->setEnabled(editable && mIsAlpha && !has_pbr_material);
+ getChildView("maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material);
+ getChildView("label maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material);
+
+ texture_ctrl->setBakeTextureEnabled(true);
+ }
+
+ if (attachment)
+ {
+ // attachments are in world and in inventory,
+ // server doesn't support changing permissions
+ // in such case
+ texture_ctrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
+ }
+ else
+ {
+ texture_ctrl->setImmediateFilterPermMask(PERM_NONE);
+ }
+ }
+
+ if (shinytexture_ctrl)
+ {
+ shinytexture_ctrl->setTentative( !identical_spec );
+ shinytexture_ctrl->setEnabled( editable && !has_pbr_material);
+ shinytexture_ctrl->setImageAssetID( specmap_id );
+
+ if (attachment)
+ {
+ shinytexture_ctrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
+ }
+ else
+ {
+ shinytexture_ctrl->setImmediateFilterPermMask(PERM_NONE);
+ }
+ }
+
+ if (bumpytexture_ctrl)
+ {
+ bumpytexture_ctrl->setTentative( !identical_norm );
+ bumpytexture_ctrl->setEnabled( editable && !has_pbr_material);
+ bumpytexture_ctrl->setImageAssetID( normmap_id );
+
+ if (attachment)
+ {
+ bumpytexture_ctrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
+ }
+ else
+ {
+ bumpytexture_ctrl->setImmediateFilterPermMask(PERM_NONE);
+ }
+ }
+ }
+
+ // planar align
+ bool align_planar = false;
+ bool identical_planar_aligned = false;
+ {
+ LLCheckBoxCtrl* cb_planar_align = getChild<LLCheckBoxCtrl>("checkbox planar align");
+ align_planar = (cb_planar_align && cb_planar_align->get());
+
+ bool enabled = (editable && isIdenticalPlanarTexgen() && !texture_info_selected);
+ childSetValue("checkbox planar align", align_planar && enabled);
+ childSetVisible("checkbox planar align", enabled);
+ childSetEnabled("checkbox planar align", enabled);
+ childSetEnabled("button align textures", enabled && LLSelectMgr::getInstance()->getSelection()->getObjectCount() > 1);
+
+ if (align_planar && enabled)
+ {
+ LLFace* last_face = NULL;
+ bool identical_face = false;
+ LLSelectedTE::getFace(last_face, identical_face);
+
+ LLPanelFaceGetIsAlignedTEFunctor get_is_aligend_func(last_face);
+ // this will determine if the texture param controls are tentative:
+ identical_planar_aligned = LLSelectMgr::getInstance()->getSelection()->applyToTEs(&get_is_aligend_func);
+ }
+ }
+
+ // Needs to be public and before tex scale settings below to properly reflect
+ // behavior when in planar vs default texgen modes in the
+ // NORSPEC-84 et al
+ //
+ LLTextureEntry::e_texgen selected_texgen = LLTextureEntry::TEX_GEN_DEFAULT;
+ bool identical_texgen = true;
+ bool identical_planar_texgen = false;
+
+ {
+ LLSelectedTE::getTexGen(selected_texgen, identical_texgen);
+ identical_planar_texgen = (identical_texgen && (selected_texgen == LLTextureEntry::TEX_GEN_PLANAR));
+ }
+
+ // Texture scale
+ {
+ bool identical_diff_scale_s = false;
+ bool identical_spec_scale_s = false;
+ bool identical_norm_scale_s = false;
+
+ identical = align_planar ? identical_planar_aligned : identical;
+
+ F32 diff_scale_s = 1.f;
+ F32 spec_scale_s = 1.f;
+ F32 norm_scale_s = 1.f;
+
+ LLSelectedTE::getScaleS(diff_scale_s, identical_diff_scale_s);
+ LLSelectedTEMaterial::getSpecularRepeatX(spec_scale_s, identical_spec_scale_s);
+ LLSelectedTEMaterial::getNormalRepeatX(norm_scale_s, identical_norm_scale_s);
+
+ diff_scale_s = editable ? diff_scale_s : 1.0f;
+ diff_scale_s *= identical_planar_texgen ? 2.0f : 1.0f;
+
+ norm_scale_s = editable ? norm_scale_s : 1.0f;
+ norm_scale_s *= identical_planar_texgen ? 2.0f : 1.0f;
+
+ spec_scale_s = editable ? spec_scale_s : 1.0f;
+ spec_scale_s *= identical_planar_texgen ? 2.0f : 1.0f;
+
+ getChild<LLUICtrl>("TexScaleU")->setValue(diff_scale_s);
+ getChild<LLUICtrl>("shinyScaleU")->setValue(spec_scale_s);
+ getChild<LLUICtrl>("bumpyScaleU")->setValue(norm_scale_s);
+
+ getChildView("TexScaleU")->setEnabled(editable && has_material);
+ getChildView("shinyScaleU")->setEnabled(editable && has_material && specmap_id.notNull());
+ getChildView("bumpyScaleU")->setEnabled(editable && has_material && normmap_id.notNull());
+
+ bool diff_scale_tentative = !(identical && identical_diff_scale_s);
+ bool norm_scale_tentative = !(identical && identical_norm_scale_s);
+ bool spec_scale_tentative = !(identical && identical_spec_scale_s);
+
+ getChild<LLUICtrl>("TexScaleU")->setTentative( LLSD(diff_scale_tentative));
+ getChild<LLUICtrl>("shinyScaleU")->setTentative(LLSD(spec_scale_tentative));
+ getChild<LLUICtrl>("bumpyScaleU")->setTentative(LLSD(norm_scale_tentative));
+ }
+
+ {
+ bool identical_diff_scale_t = false;
+ bool identical_spec_scale_t = false;
+ bool identical_norm_scale_t = false;
+
+ F32 diff_scale_t = 1.f;
+ F32 spec_scale_t = 1.f;
+ F32 norm_scale_t = 1.f;
+
+ LLSelectedTE::getScaleT(diff_scale_t, identical_diff_scale_t);
+ LLSelectedTEMaterial::getSpecularRepeatY(spec_scale_t, identical_spec_scale_t);
+ LLSelectedTEMaterial::getNormalRepeatY(norm_scale_t, identical_norm_scale_t);
+
+ diff_scale_t = editable ? diff_scale_t : 1.0f;
+ diff_scale_t *= identical_planar_texgen ? 2.0f : 1.0f;
+
+ norm_scale_t = editable ? norm_scale_t : 1.0f;
+ norm_scale_t *= identical_planar_texgen ? 2.0f : 1.0f;
+
+ spec_scale_t = editable ? spec_scale_t : 1.0f;
+ spec_scale_t *= identical_planar_texgen ? 2.0f : 1.0f;
+
+ bool diff_scale_tentative = !identical_diff_scale_t;
+ bool norm_scale_tentative = !identical_norm_scale_t;
+ bool spec_scale_tentative = !identical_spec_scale_t;
+
+ getChildView("TexScaleV")->setEnabled(editable && has_material);
+ getChildView("shinyScaleV")->setEnabled(editable && has_material && specmap_id.notNull());
+ getChildView("bumpyScaleV")->setEnabled(editable && has_material && normmap_id.notNull());
+
+ if (force_set_values)
+ {
+ getChild<LLSpinCtrl>("TexScaleV")->forceSetValue(diff_scale_t);
+ }
+ else
+ {
+ getChild<LLSpinCtrl>("TexScaleV")->setValue(diff_scale_t);
+ }
+ getChild<LLUICtrl>("shinyScaleV")->setValue(norm_scale_t);
+ getChild<LLUICtrl>("bumpyScaleV")->setValue(spec_scale_t);
+
+ getChild<LLUICtrl>("TexScaleV")->setTentative(LLSD(diff_scale_tentative));
+ getChild<LLUICtrl>("shinyScaleV")->setTentative(LLSD(norm_scale_tentative));
+ getChild<LLUICtrl>("bumpyScaleV")->setTentative(LLSD(spec_scale_tentative));
+ }
+
+ // Texture offset
+ {
+ bool identical_diff_offset_s = false;
+ bool identical_norm_offset_s = false;
+ bool identical_spec_offset_s = false;
+
+ F32 diff_offset_s = 0.0f;
+ F32 norm_offset_s = 0.0f;
+ F32 spec_offset_s = 0.0f;
+
+ LLSelectedTE::getOffsetS(diff_offset_s, identical_diff_offset_s);
+ LLSelectedTEMaterial::getNormalOffsetX(norm_offset_s, identical_norm_offset_s);
+ LLSelectedTEMaterial::getSpecularOffsetX(spec_offset_s, identical_spec_offset_s);
+
+ bool diff_offset_u_tentative = !(align_planar ? identical_planar_aligned : identical_diff_offset_s);
+ bool norm_offset_u_tentative = !(align_planar ? identical_planar_aligned : identical_norm_offset_s);
+ bool spec_offset_u_tentative = !(align_planar ? identical_planar_aligned : identical_spec_offset_s);
+
+ getChild<LLUICtrl>("TexOffsetU")->setValue( editable ? diff_offset_s : 0.0f);
+ getChild<LLUICtrl>("bumpyOffsetU")->setValue(editable ? norm_offset_s : 0.0f);
+ getChild<LLUICtrl>("shinyOffsetU")->setValue(editable ? spec_offset_s : 0.0f);
+
+ getChild<LLUICtrl>("TexOffsetU")->setTentative(LLSD(diff_offset_u_tentative));
+ getChild<LLUICtrl>("shinyOffsetU")->setTentative(LLSD(norm_offset_u_tentative));
+ getChild<LLUICtrl>("bumpyOffsetU")->setTentative(LLSD(spec_offset_u_tentative));
+
+ getChildView("TexOffsetU")->setEnabled(editable && has_material);
+ getChildView("shinyOffsetU")->setEnabled(editable && has_material && specmap_id.notNull());
+ getChildView("bumpyOffsetU")->setEnabled(editable && has_material && normmap_id.notNull());
+ }
+
+ {
+ bool identical_diff_offset_t = false;
+ bool identical_norm_offset_t = false;
+ bool identical_spec_offset_t = false;
+
+ F32 diff_offset_t = 0.0f;
+ F32 norm_offset_t = 0.0f;
+ F32 spec_offset_t = 0.0f;
+
+ LLSelectedTE::getOffsetT(diff_offset_t, identical_diff_offset_t);
+ LLSelectedTEMaterial::getNormalOffsetY(norm_offset_t, identical_norm_offset_t);
+ LLSelectedTEMaterial::getSpecularOffsetY(spec_offset_t, identical_spec_offset_t);
+
+ bool diff_offset_v_tentative = !(align_planar ? identical_planar_aligned : identical_diff_offset_t);
+ bool norm_offset_v_tentative = !(align_planar ? identical_planar_aligned : identical_norm_offset_t);
+ bool spec_offset_v_tentative = !(align_planar ? identical_planar_aligned : identical_spec_offset_t);
+
+ getChild<LLUICtrl>("TexOffsetV")->setValue( editable ? diff_offset_t : 0.0f);
+ getChild<LLUICtrl>("bumpyOffsetV")->setValue(editable ? norm_offset_t : 0.0f);
+ getChild<LLUICtrl>("shinyOffsetV")->setValue(editable ? spec_offset_t : 0.0f);
+
+ getChild<LLUICtrl>("TexOffsetV")->setTentative(LLSD(diff_offset_v_tentative));
+ getChild<LLUICtrl>("shinyOffsetV")->setTentative(LLSD(norm_offset_v_tentative));
+ getChild<LLUICtrl>("bumpyOffsetV")->setTentative(LLSD(spec_offset_v_tentative));
+
+ getChildView("TexOffsetV")->setEnabled(editable && has_material);
+ getChildView("shinyOffsetV")->setEnabled(editable && has_material && specmap_id.notNull());
+ getChildView("bumpyOffsetV")->setEnabled(editable && has_material && normmap_id.notNull());
+ }
+
+ // Texture rotation
+ {
+ bool identical_diff_rotation = false;
+ bool identical_norm_rotation = false;
+ bool identical_spec_rotation = false;
+
+ F32 diff_rotation = 0.f;
+ F32 norm_rotation = 0.f;
+ F32 spec_rotation = 0.f;
+
+ LLSelectedTE::getRotation(diff_rotation,identical_diff_rotation);
+ LLSelectedTEMaterial::getSpecularRotation(spec_rotation,identical_spec_rotation);
+ LLSelectedTEMaterial::getNormalRotation(norm_rotation,identical_norm_rotation);
+
+ bool diff_rot_tentative = !(align_planar ? identical_planar_aligned : identical_diff_rotation);
+ bool norm_rot_tentative = !(align_planar ? identical_planar_aligned : identical_norm_rotation);
+ bool spec_rot_tentative = !(align_planar ? identical_planar_aligned : identical_spec_rotation);
+
+ F32 diff_rot_deg = diff_rotation * RAD_TO_DEG;
+ F32 norm_rot_deg = norm_rotation * RAD_TO_DEG;
+ F32 spec_rot_deg = spec_rotation * RAD_TO_DEG;
+
+ getChildView("TexRot")->setEnabled(editable && has_material);
+ getChildView("shinyRot")->setEnabled(editable && has_material && specmap_id.notNull());
+ getChildView("bumpyRot")->setEnabled(editable && has_material && normmap_id.notNull());
+
+ getChild<LLUICtrl>("TexRot")->setTentative(diff_rot_tentative);
+ getChild<LLUICtrl>("shinyRot")->setTentative(LLSD(norm_rot_tentative));
+ getChild<LLUICtrl>("bumpyRot")->setTentative(LLSD(spec_rot_tentative));
+
+ getChild<LLUICtrl>("TexRot")->setValue( editable ? diff_rot_deg : 0.0f);
+ getChild<LLUICtrl>("shinyRot")->setValue(editable ? spec_rot_deg : 0.0f);
+ getChild<LLUICtrl>("bumpyRot")->setValue(editable ? norm_rot_deg : 0.0f);
+ }
+
+ {
+ F32 glow = 0.f;
+ bool identical_glow = false;
+ LLSelectedTE::getGlow(glow,identical_glow);
+ getChild<LLUICtrl>("glow")->setValue(glow);
+ getChild<LLUICtrl>("glow")->setTentative(!identical_glow);
+ getChildView("glow")->setEnabled(editable);
+ getChildView("glow label")->setEnabled(editable);
+ }
+
+ {
+ LLCtrlSelectionInterface* combobox_texgen = childGetSelectionInterface("combobox texgen");
+ if (combobox_texgen)
+ {
+ // Maps from enum to combobox entry index
+ combobox_texgen->selectNthItem(((S32)selected_texgen) >> 1);
+ }
+ else
+ {
+ LL_WARNS() << "failed childGetSelectionInterface for 'combobox texgen'" << LL_ENDL;
+ }
+
+ getChildView("combobox texgen")->setEnabled(editable);
+ getChild<LLUICtrl>("combobox texgen")->setTentative(!identical);
+ getChildView("tex gen")->setEnabled(editable);
+ }
+
+ {
+ U8 fullbright_flag = 0;
+ bool identical_fullbright = false;
+
+ LLSelectedTE::getFullbright(fullbright_flag,identical_fullbright);
+
+ getChild<LLUICtrl>("checkbox fullbright")->setValue((S32)(fullbright_flag != 0));
+ getChildView("checkbox fullbright")->setEnabled(editable && !has_pbr_material);
+ getChild<LLUICtrl>("checkbox fullbright")->setTentative(!identical_fullbright);
+ mComboMatMedia->setEnabledByValue("Materials", !has_pbr_material);
+ }
+
+ // Repeats per meter
+ {
+ F32 repeats_diff = 1.f;
+ F32 repeats_norm = 1.f;
+ F32 repeats_spec = 1.f;
+
+ bool identical_diff_repeats = false;
+ bool identical_norm_repeats = false;
+ bool identical_spec_repeats = false;
+
+ LLSelectedTE::getMaxDiffuseRepeats(repeats_diff, identical_diff_repeats);
+ LLSelectedTEMaterial::getMaxNormalRepeats(repeats_norm, identical_norm_repeats);
+ LLSelectedTEMaterial::getMaxSpecularRepeats(repeats_spec, identical_spec_repeats);
+
+ LLComboBox* mComboTexGen = getChild<LLComboBox>("combobox texgen");
+ if (mComboTexGen)
+ {
+ S32 index = mComboTexGen ? mComboTexGen->getCurrentIndex() : 0;
+ bool enabled = editable && (index != 1);
+ bool identical_repeats = true;
+ S32 material_selection = mComboMatMedia->getCurrentIndex();
+ F32 repeats = 1.0f;
+
+ U32 material_type = MATTYPE_DIFFUSE;
+ if (material_selection == MATMEDIA_MATERIAL)
+ {
+ material_type = radio_mat_type->getSelectedIndex();
+ }
+ else if (material_selection == MATMEDIA_PBR)
+ {
+ enabled = editable && has_pbr_material;
+ material_type = radio_pbr_type->getSelectedIndex();
+ }
+
+ switch (material_type)
+ {
+ default:
+ case MATTYPE_DIFFUSE:
+ {
+ if (material_selection != MATMEDIA_PBR)
+ {
+ enabled = editable && !id.isNull();
+ }
+ identical_repeats = identical_diff_repeats;
+ repeats = repeats_diff;
+ }
+ break;
+
+ case MATTYPE_SPECULAR:
+ {
+ if (material_selection != MATMEDIA_PBR)
+ {
+ enabled = (editable && ((shiny == SHINY_TEXTURE) && !specmap_id.isNull()));
+ }
+ identical_repeats = identical_spec_repeats;
+ repeats = repeats_spec;
+ }
+ break;
+
+ case MATTYPE_NORMAL:
+ {
+ if (material_selection != MATMEDIA_PBR)
+ {
+ enabled = (editable && ((bumpy == BUMPY_TEXTURE) && !normmap_id.isNull()));
+ }
+ identical_repeats = identical_norm_repeats;
+ repeats = repeats_norm;
+ }
+ break;
+ }
+
+ bool repeats_tentative = !identical_repeats;
+
+ LLSpinCtrl* rpt_ctrl = getChild<LLSpinCtrl>("rptctrl");
+ if (force_set_values)
+ {
+ //onCommit, previosly edited element updates related ones
+ rpt_ctrl->forceSetValue(editable ? repeats : 1.0f);
+ }
+ else
+ {
+ rpt_ctrl->setValue(editable ? repeats : 1.0f);
+ }
+ rpt_ctrl->setTentative(LLSD(repeats_tentative));
+ rpt_ctrl->setEnabled(has_material && !identical_planar_texgen && enabled);
+ }
+ }
+
+ // Materials
+ {
+ LLMaterialPtr material;
+ LLSelectedTEMaterial::getCurrent(material, identical);
+
+ if (material && editable)
+ {
+ LL_DEBUGS("Materials") << material->asLLSD() << LL_ENDL;
+
+ // Alpha
+ LLCtrlSelectionInterface* combobox_alphamode =
+ childGetSelectionInterface("combobox alphamode");
+ if (combobox_alphamode)
+ {
+ U32 alpha_mode = material->getDiffuseAlphaMode();
+
+ if (transparency > 0.f)
+ { //it is invalid to have any alpha mode other than blend if transparency is greater than zero ...
+ alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND;
+ }
+
+ if (!mIsAlpha)
+ { // ... unless there is no alpha channel in the texture, in which case alpha mode MUST ebe none
+ alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_NONE;
+ }
+
+ combobox_alphamode->selectNthItem(alpha_mode);
+ }
+ else
+ {
+ LL_WARNS() << "failed childGetSelectionInterface for 'combobox alphamode'" << LL_ENDL;
+ }
+ getChild<LLUICtrl>("maskcutoff")->setValue(material->getAlphaMaskCutoff());
+ updateAlphaControls();
+
+ identical_planar_texgen = isIdenticalPlanarTexgen();
+
+ // Shiny (specular)
+ F32 offset_x, offset_y, repeat_x, repeat_y, rot;
+ LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>("shinytexture control");
+ texture_ctrl->setImageAssetID(material->getSpecularID());
+
+ if (!material->getSpecularID().isNull() && (shiny == SHINY_TEXTURE))
+ {
+ material->getSpecularOffset(offset_x,offset_y);
+ material->getSpecularRepeat(repeat_x,repeat_y);
+
+ if (identical_planar_texgen)
+ {
+ repeat_x *= 2.0f;
+ repeat_y *= 2.0f;
+ }
+
+ rot = material->getSpecularRotation();
+ getChild<LLUICtrl>("shinyScaleU")->setValue(repeat_x);
+ getChild<LLUICtrl>("shinyScaleV")->setValue(repeat_y);
+ getChild<LLUICtrl>("shinyRot")->setValue(rot*RAD_TO_DEG);
+ getChild<LLUICtrl>("shinyOffsetU")->setValue(offset_x);
+ getChild<LLUICtrl>("shinyOffsetV")->setValue(offset_y);
+ getChild<LLUICtrl>("glossiness")->setValue(material->getSpecularLightExponent());
+ getChild<LLUICtrl>("environment")->setValue(material->getEnvironmentIntensity());
+
+ updateShinyControls(!material->getSpecularID().isNull(), true);
+ }
+
+ // Assert desired colorswatch color to match material AFTER updateShinyControls
+ // to avoid getting overwritten with the default on some UI state changes.
+ //
+ if (!material->getSpecularID().isNull())
+ {
+ LLColorSwatchCtrl* shiny_swatch = getChild<LLColorSwatchCtrl>("shinycolorswatch");
+ LLColor4 new_color = material->getSpecularLightColor();
+ LLColor4 old_color = shiny_swatch->get();
+
+ shiny_swatch->setOriginal(new_color);
+ shiny_swatch->set(new_color, force_set_values || old_color != new_color || !editable);
+ }
+
+ // Bumpy (normal)
+ texture_ctrl = getChild<LLTextureCtrl>("bumpytexture control");
+ texture_ctrl->setImageAssetID(material->getNormalID());
+
+ if (!material->getNormalID().isNull())
+ {
+ material->getNormalOffset(offset_x,offset_y);
+ material->getNormalRepeat(repeat_x,repeat_y);
+
+ if (identical_planar_texgen)
+ {
+ repeat_x *= 2.0f;
+ repeat_y *= 2.0f;
+ }
+
+ rot = material->getNormalRotation();
+ getChild<LLUICtrl>("bumpyScaleU")->setValue(repeat_x);
+ getChild<LLUICtrl>("bumpyScaleV")->setValue(repeat_y);
+ getChild<LLUICtrl>("bumpyRot")->setValue(rot*RAD_TO_DEG);
+ getChild<LLUICtrl>("bumpyOffsetU")->setValue(offset_x);
+ getChild<LLUICtrl>("bumpyOffsetV")->setValue(offset_y);
+
+ updateBumpyControls(!material->getNormalID().isNull(), true);
+ }
+ }
+ }
+ S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
+ bool single_volume = (selected_count == 1);
+ mMenuClipboardColor->setEnabled(editable && single_volume);
+
+ // Set variable values for numeric expressions
+ LLCalc* calcp = LLCalc::getInstance();
+ calcp->setVar(LLCalc::TEX_U_SCALE, childGetValue("TexScaleU").asReal());
+ calcp->setVar(LLCalc::TEX_V_SCALE, childGetValue("TexScaleV").asReal());
+ calcp->setVar(LLCalc::TEX_U_OFFSET, childGetValue("TexOffsetU").asReal());
+ calcp->setVar(LLCalc::TEX_V_OFFSET, childGetValue("TexOffsetV").asReal());
+ calcp->setVar(LLCalc::TEX_ROTATION, childGetValue("TexRot").asReal());
+ calcp->setVar(LLCalc::TEX_TRANSPARENCY, childGetValue("ColorTrans").asReal());
+ calcp->setVar(LLCalc::TEX_GLOW, childGetValue("glow").asReal());
+ }
+ else
+ {
+ // Disable all UICtrls
+ clearCtrls();
+
+ // Disable non-UICtrls
+ LLTextureCtrl* pbr_ctrl = findChild<LLTextureCtrl>("pbr_control");
+ if (pbr_ctrl)
+ {
+ pbr_ctrl->setImageAssetID(LLUUID::null);
+ pbr_ctrl->setEnabled(false);
+ }
+ LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>("texture control");
+ if (texture_ctrl)
+ {
+ texture_ctrl->setImageAssetID( LLUUID::null );
+ texture_ctrl->setEnabled( false ); // this is a LLUICtrl, but we don't want it to have keyboard focus so we add it as a child, not a ctrl.
+// texture_ctrl->setValid(false);
+ }
+ LLColorSwatchCtrl* mColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch");
+ if (mColorSwatch)
+ {
+ mColorSwatch->setEnabled( false );
+ mColorSwatch->setFallbackImage(LLUI::getUIImage("locked_image.j2c") );
+ mColorSwatch->setValid(false);
+ }
+ LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type");
+ if (radio_mat_type)
+ {
+ radio_mat_type->setSelectedIndex(0);
+ }
+ getChildView("color trans")->setEnabled(false);
+ getChildView("rptctrl")->setEnabled(false);
+ getChildView("tex gen")->setEnabled(false);
+ getChildView("label shininess")->setEnabled(false);
+ getChildView("label bumpiness")->setEnabled(false);
+ getChildView("button align")->setEnabled(false);
+ getChildView("pbr_from_inventory")->setEnabled(false);
+ getChildView("edit_selected_pbr")->setEnabled(false);
+ getChildView("save_selected_pbr")->setEnabled(false);
+
+ updateVisibility();
+
+ // Set variable values for numeric expressions
+ LLCalc* calcp = LLCalc::getInstance();
+ calcp->clearVar(LLCalc::TEX_U_SCALE);
+ calcp->clearVar(LLCalc::TEX_V_SCALE);
+ calcp->clearVar(LLCalc::TEX_U_OFFSET);
+ calcp->clearVar(LLCalc::TEX_V_OFFSET);
+ calcp->clearVar(LLCalc::TEX_ROTATION);
+ calcp->clearVar(LLCalc::TEX_TRANSPARENCY);
+ calcp->clearVar(LLCalc::TEX_GLOW);
+ }
+}
+
+// One-off listener that updates the build floater UI when the agent inventory adds or removes an item
+class PBRPickerAgentListener : public LLInventoryObserver
+{
+protected:
+ bool mChangePending = true;
+public:
+ PBRPickerAgentListener() : LLInventoryObserver()
+ {
+ gInventory.addObserver(this);
+ }
+
+ const bool isListening()
+ {
+ return mChangePending;
+ }
+
+ void changed(U32 mask) override
+ {
+ if (!(mask & (ADD | REMOVE)))
+ {
+ return;
+ }
+
+ if (gFloaterTools)
+ {
+ gFloaterTools->dirty();
+ }
+ gInventory.removeObserver(this);
+ mChangePending = false;
+ }
+
+ ~PBRPickerAgentListener() override
+ {
+ gInventory.removeObserver(this);
+ mChangePending = false;
+ }
+};
+
+// One-off listener that updates the build floater UI when the prim inventory updates
+class PBRPickerObjectListener : public LLVOInventoryListener
+{
+protected:
+ LLViewerObject* mObjectp;
+ bool mChangePending = true;
+public:
+
+ PBRPickerObjectListener(LLViewerObject* object)
+ : mObjectp(object)
+ {
+ registerVOInventoryListener(mObjectp, nullptr);
+ }
+
+ const bool isListeningFor(const LLViewerObject* objectp) const
+ {
+ return mChangePending && (objectp == mObjectp);
+ }
+
+ void inventoryChanged(LLViewerObject* object,
+ LLInventoryObject::object_list_t* inventory,
+ S32 serial_num,
+ void* user_data) override
+ {
+ if (gFloaterTools)
+ {
+ gFloaterTools->dirty();
+ }
+ removeVOInventoryListener();
+ mChangePending = false;
+ }
+
+ ~PBRPickerObjectListener()
+ {
+ removeVOInventoryListener();
+ mChangePending = false;
+ }
+};
+
+void LLPanelFace::updateUIGLTF(LLViewerObject* objectp, bool& has_pbr_material, bool& has_faces_without_pbr, bool force_set_values)
+{
+ has_pbr_material = false;
+
+ bool has_pbr_capabilities = LLMaterialEditor::capabilitiesAvailable();
+ bool identical_pbr = true;
+ const bool settable = has_pbr_capabilities && objectp->permModify() && !objectp->isPermanentEnforced();
+ const bool editable = LLMaterialEditor::canModifyObjectsMaterial();
+ const bool saveable = LLMaterialEditor::canSaveObjectsMaterial();
+
+ // pbr material
+ LLTextureCtrl* pbr_ctrl = findChild<LLTextureCtrl>("pbr_control");
+ LLUUID pbr_id;
+ if (pbr_ctrl)
+ {
+ LLSelectedTE::getPbrMaterialId(pbr_id, identical_pbr, has_pbr_material, has_faces_without_pbr);
+
+ pbr_ctrl->setTentative(!identical_pbr);
+ pbr_ctrl->setEnabled(settable);
+ pbr_ctrl->setImageAssetID(pbr_id);
+
+ if (objectp->isAttachment())
+ {
+ pbr_ctrl->setFilterPermissionMasks(PERM_COPY | PERM_TRANSFER | PERM_MODIFY);
+ }
+ else
+ {
+ pbr_ctrl->setImmediateFilterPermMask(PERM_NONE);
+ }
+ }
+
+ getChildView("pbr_from_inventory")->setEnabled(settable);
+ getChildView("edit_selected_pbr")->setEnabled(editable && !has_faces_without_pbr);
+ getChildView("save_selected_pbr")->setEnabled(saveable && identical_pbr);
+ if (objectp->isInventoryPending())
+ {
+ // Reuse the same listener when possible
+ if (!mVOInventoryListener || !mVOInventoryListener->isListeningFor(objectp))
+ {
+ mVOInventoryListener = std::make_unique<PBRPickerObjectListener>(objectp);
+ }
+ }
+ else
+ {
+ mVOInventoryListener = nullptr;
+ }
+ if (!identical_pbr || pbr_id.isNull() || pbr_id == LLGLTFMaterialList::BLANK_MATERIAL_ASSET_ID)
+ {
+ mAgentInventoryListener = nullptr;
+ }
+ else
+ {
+ if (!mAgentInventoryListener || !mAgentInventoryListener->isListening())
+ {
+ mAgentInventoryListener = std::make_unique<PBRPickerAgentListener>();
+ }
+ }
+
+ const bool show_pbr = mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR && mComboMatMedia->getEnabled();
+ if (show_pbr)
+ {
+ const bool new_state = has_pbr_capabilities && has_pbr_material && !has_faces_without_pbr;
+
+ LLUICtrl* gltfCtrlTextureScaleU = getChild<LLUICtrl>("gltfTextureScaleU");
+ LLUICtrl* gltfCtrlTextureScaleV = getChild<LLUICtrl>("gltfTextureScaleV");
+ LLUICtrl* gltfCtrlTextureRotation = getChild<LLUICtrl>("gltfTextureRotation");
+ LLUICtrl* gltfCtrlTextureOffsetU = getChild<LLUICtrl>("gltfTextureOffsetU");
+ LLUICtrl* gltfCtrlTextureOffsetV = getChild<LLUICtrl>("gltfTextureOffsetV");
+
+ gltfCtrlTextureScaleU->setEnabled(new_state);
+ gltfCtrlTextureScaleV->setEnabled(new_state);
+ gltfCtrlTextureRotation->setEnabled(new_state);
+ gltfCtrlTextureOffsetU->setEnabled(new_state);
+ gltfCtrlTextureOffsetV->setEnabled(new_state);
+
+ // Control values will be set once per frame in
+ // setMaterialOverridesFromSelection
+ sMaterialOverrideSelection.setDirty();
+ }
+}
+
+void LLPanelFace::updateVisibilityGLTF(LLViewerObject* objectp /*= nullptr */)
+{
+ const bool show_pbr = mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR && mComboMatMedia->getEnabled();
+ const bool inventory_pending = objectp && objectp->isInventoryPending();
+
+ LLRadioGroup* radio_pbr_type = findChild<LLRadioGroup>("radio_pbr_type");
+ radio_pbr_type->setVisible(show_pbr);
+
+ const U32 pbr_type = radio_pbr_type->getSelectedIndex();
+ const bool show_pbr_render_material_id = show_pbr && (pbr_type == PBRTYPE_RENDER_MATERIAL_ID);
+
+ getChildView("pbr_control")->setVisible(show_pbr_render_material_id);
+
+ getChildView("pbr_from_inventory")->setVisible(show_pbr_render_material_id);
+ getChildView("edit_selected_pbr")->setVisible(show_pbr_render_material_id && !inventory_pending);
+ getChildView("save_selected_pbr")->setVisible(show_pbr_render_material_id && !inventory_pending);
+ getChildView("material_permissions_loading_label")->setVisible(show_pbr_render_material_id && inventory_pending);
+
+ getChildView("gltfTextureScaleU")->setVisible(show_pbr);
+ getChildView("gltfTextureScaleV")->setVisible(show_pbr);
+ getChildView("gltfTextureRotation")->setVisible(show_pbr);
+ getChildView("gltfTextureOffsetU")->setVisible(show_pbr);
+ getChildView("gltfTextureOffsetV")->setVisible(show_pbr);
+}
+
+void LLPanelFace::updateCopyTexButton()
+{
+ LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+ mMenuClipboardTexture->setEnabled(objectp && objectp->getPCode() == LL_PCODE_VOLUME && objectp->permModify()
+ && !objectp->isPermanentEnforced() && !objectp->isInventoryPending()
+ && (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 1)
+ && LLMaterialEditor::canClipboardObjectsMaterial());
+ std::string tooltip = (objectp && objectp->isInventoryPending()) ? LLTrans::getString("LoadingContents") : getString("paste_options");
+ mMenuClipboardTexture->setToolTip(tooltip);
+}
+
+void LLPanelFace::refresh()
+{
+ LL_DEBUGS("Materials") << LL_ENDL;
+ getState();
+}
+
+void LLPanelFace::refreshMedia()
+{
+ LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection();
+ LLViewerObject* first_object = selected_objects->getFirstObject();
+
+ if (!(first_object
+ && first_object->getPCode() == LL_PCODE_VOLUME
+ && first_object->permModify()
+ ))
+ {
+ getChildView("add_media")->setEnabled(false);
+ mTitleMediaText->clear();
+ clearMediaSettings();
+ return;
+ }
+
+ std::string url = first_object->getRegion()->getCapability("ObjectMedia");
+ bool has_media_capability = (!url.empty());
+
+ if (!has_media_capability)
+ {
+ getChildView("add_media")->setEnabled(false);
+ LL_WARNS("LLFloaterToolsMedia") << "Media not enabled (no capability) in this region!" << LL_ENDL;
+ clearMediaSettings();
+ return;
+ }
+
+ bool is_nonpermanent_enforced = (LLSelectMgr::getInstance()->getSelection()->getFirstRootNode()
+ && LLSelectMgr::getInstance()->selectGetRootsNonPermanentEnforced())
+ || LLSelectMgr::getInstance()->selectGetNonPermanentEnforced();
+ bool editable = is_nonpermanent_enforced && (first_object->permModify() || selectedMediaEditable());
+
+ // Check modify permissions and whether any selected objects are in
+ // the process of being fetched. If they are, then we're not editable
+ if (editable)
+ {
+ LLObjectSelection::iterator iter = selected_objects->begin();
+ LLObjectSelection::iterator end = selected_objects->end();
+ for (; iter != end; ++iter)
+ {
+ LLSelectNode* node = *iter;
+ LLVOVolume* object = dynamic_cast<LLVOVolume*>(node->getObject());
+ if (NULL != object)
+ {
+ if (!object->permModify())
+ {
+ LL_INFOS("LLFloaterToolsMedia")
+ << "Selection not editable due to lack of modify permissions on object id "
+ << object->getID() << LL_ENDL;
+
+ editable = false;
+ break;
+ }
+ }
+ }
+ }
+
+ // Media settings
+ bool bool_has_media = false;
+ struct media_functor : public LLSelectedTEGetFunctor<bool>
+ {
+ bool get(LLViewerObject* object, S32 face)
+ {
+ LLTextureEntry *te = object->getTE(face);
+ if (te)
+ {
+ return te->hasMedia();
+ }
+ return false;
+ }
+ } func;
+
+
+ // check if all faces have media(or, all dont have media)
+ LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo = selected_objects->getSelectedTEValue(&func, bool_has_media);
+
+ const LLMediaEntry default_media_data;
+
+ struct functor_getter_media_data : public LLSelectedTEGetFunctor< LLMediaEntry>
+ {
+ functor_getter_media_data(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
+ LLMediaEntry get(LLViewerObject* object, S32 face)
+ {
+ if (object)
+ if (object->getTE(face))
+ if (object->getTE(face)->getMediaData())
+ return *(object->getTE(face)->getMediaData());
+ return mMediaEntry;
+ };
+
+ const LLMediaEntry& mMediaEntry;
+
+ } func_media_data(default_media_data);
+
+ LLMediaEntry media_data_get;
+ LLFloaterMediaSettings::getInstance()->mMultipleMedia = !(selected_objects->getSelectedTEValue(&func_media_data, media_data_get));
+
+ std::string multi_media_info_str = LLTrans::getString("Multiple Media");
+ std::string media_title = "";
+ // update UI depending on whether "object" (prim or face) has media
+ // and whether or not you are allowed to edit it.
+
+ getChildView("add_media")->setEnabled(editable);
+ // IF all the faces have media (or all dont have media)
+ if (LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo)
+ {
+ // TODO: get media title and set it.
+ mTitleMediaText->clear();
+ // if identical is set, all faces are same (whether all empty or has the same media)
+ if (!(LLFloaterMediaSettings::getInstance()->mMultipleMedia))
+ {
+ // Media data is valid
+ if (media_data_get != default_media_data)
+ {
+ // initial media title is the media URL (until we get the name)
+ media_title = media_data_get.getHomeURL();
+ }
+ // else all faces might be empty.
+ }
+ else // there' re Different Medias' been set on on the faces.
+ {
+ media_title = multi_media_info_str;
+ }
+
+ getChildView("delete_media")->setEnabled(bool_has_media && editable);
+ // TODO: display a list of all media on the face - use 'identical' flag
+ }
+ else // not all face has media but at least one does.
+ {
+ // seleted faces have not identical value
+ LLFloaterMediaSettings::getInstance()->mMultipleValidMedia = selected_objects->isMultipleTEValue(&func_media_data, default_media_data);
+
+ if (LLFloaterMediaSettings::getInstance()->mMultipleValidMedia)
+ {
+ media_title = multi_media_info_str;
+ }
+ else
+ {
+ // Media data is valid
+ if (media_data_get != default_media_data)
+ {
+ // initial media title is the media URL (until we get the name)
+ media_title = media_data_get.getHomeURL();
+ }
+ }
+
+ getChildView("delete_media")->setEnabled(true);
+ }
+
+ U32 materials_media = mComboMatMedia->getCurrentIndex();
+ if (materials_media == MATMEDIA_MEDIA)
+ {
+ // currently displaying media info, navigateTo and update title
+ navigateToTitleMedia(media_title);
+ }
+ else
+ {
+ // Media can be heavy, don't keep it around
+ // MAC specific: MAC doesn't support setVolume(0) so if not
+ // unloaded, it might keep playing audio until user closes editor
+ unloadMedia();
+ mNeedMediaTitle = false;
+ }
+
+ mTitleMediaText->setText(media_title);
+
+ // load values for media settings
+ updateMediaSettings();
+
+ LLFloaterMediaSettings::initValues(mMediaSettings, editable);
+}
+
+void LLPanelFace::unloadMedia()
+{
+ // destroy media source used to grab media title
+ if (mTitleMedia)
+ mTitleMedia->unloadMediaSource();
+}
+
+// static
+void LLPanelFace::onMaterialOverrideReceived(const LLUUID& object_id, S32 side)
+{
+ sMaterialOverrideSelection.onSelectedObjectUpdated(object_id, side);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelFace::navigateToTitleMedia( const std::string url )
+{
+ std::string multi_media_info_str = LLTrans::getString("Multiple Media");
+ if (url.empty() || multi_media_info_str == url)
+ {
+ // nothing to show
+ mNeedMediaTitle = false;
+ }
+ else if (mTitleMedia)
+ {
+ LLPluginClassMedia* media_plugin = mTitleMedia->getMediaPlugin();
+ // check if url changed or if we need a new media source
+ if (mTitleMedia->getCurrentNavUrl() != url || media_plugin == NULL)
+ {
+ mTitleMedia->navigateTo( url );
+
+ LLViewerMediaImpl* impl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(mTitleMedia->getTextureID());
+ if (impl)
+ {
+ // if it's a page with a movie, we don't want to hear it
+ impl->setVolume(0);
+ };
+ }
+
+ // flag that we need to update the title (even if no request were made)
+ mNeedMediaTitle = true;
+ }
+}
+
+bool LLPanelFace::selectedMediaEditable()
+{
+ U32 owner_mask_on;
+ U32 owner_mask_off;
+ U32 valid_owner_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_OWNER,
+ &owner_mask_on, &owner_mask_off);
+ U32 group_mask_on;
+ U32 group_mask_off;
+ U32 valid_group_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_GROUP,
+ &group_mask_on, &group_mask_off);
+ U32 everyone_mask_on;
+ U32 everyone_mask_off;
+ S32 valid_everyone_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_EVERYONE,
+ &everyone_mask_on, &everyone_mask_off);
+
+ bool selected_Media_editable = false;
+
+ // if perms we got back are valid
+ if (valid_owner_perms &&
+ valid_group_perms &&
+ valid_everyone_perms)
+ {
+
+ if ((owner_mask_on & PERM_MODIFY) ||
+ (group_mask_on & PERM_MODIFY) ||
+ (everyone_mask_on & PERM_MODIFY))
+ {
+ selected_Media_editable = true;
+ }
+ else
+ // user is NOT allowed to press the RESET button
+ {
+ selected_Media_editable = false;
+ };
+ };
+
+ return selected_Media_editable;
+}
+
+void LLPanelFace::clearMediaSettings()
+{
+ LLFloaterMediaSettings::clearValues(false);
+}
+
+void LLPanelFace::updateMediaSettings()
+{
+ bool identical(false);
+ std::string base_key("");
+ std::string value_str("");
+ int value_int = 0;
+ bool value_bool = false;
+ LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection();
+ // TODO: (CP) refactor this using something clever or boost or both !!
+
+ const LLMediaEntry default_media_data;
+
+ // controls
+ U8 value_u8 = default_media_data.getControls();
+ struct functor_getter_controls : public LLSelectedTEGetFunctor< U8 >
+ {
+ functor_getter_controls(const LLMediaEntry &entry) : mMediaEntry(entry) {}
+
+ U8 get(LLViewerObject* object, S32 face)
+ {
+ if (object)
+ if (object->getTE(face))
+ if (object->getTE(face)->getMediaData())
+ return object->getTE(face)->getMediaData()->getControls();
+ return mMediaEntry.getControls();
+ };
+
+ const LLMediaEntry &mMediaEntry;
+
+ } func_controls(default_media_data);
+ identical = selected_objects->getSelectedTEValue(&func_controls, value_u8);
+ base_key = std::string(LLMediaEntry::CONTROLS_KEY);
+ mMediaSettings[base_key] = value_u8;
+ mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
+
+ // First click (formerly left click)
+ value_bool = default_media_data.getFirstClickInteract();
+ struct functor_getter_first_click : public LLSelectedTEGetFunctor< bool >
+ {
+ functor_getter_first_click(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
+ bool get(LLViewerObject* object, S32 face)
+ {
+ if (object)
+ if (object->getTE(face))
+ if (object->getTE(face)->getMediaData())
+ return object->getTE(face)->getMediaData()->getFirstClickInteract();
+ return mMediaEntry.getFirstClickInteract();
+ };
+
+ const LLMediaEntry &mMediaEntry;
+
+ } func_first_click(default_media_data);
+ identical = selected_objects->getSelectedTEValue(&func_first_click, value_bool);
+ base_key = std::string(LLMediaEntry::FIRST_CLICK_INTERACT_KEY);
+ mMediaSettings[base_key] = value_bool;
+ mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
+
+ // Home URL
+ value_str = default_media_data.getHomeURL();
+ struct functor_getter_home_url : public LLSelectedTEGetFunctor< std::string >
+ {
+ functor_getter_home_url(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
+ std::string get(LLViewerObject* object, S32 face)
+ {
+ if (object)
+ if (object->getTE(face))
+ if (object->getTE(face)->getMediaData())
+ return object->getTE(face)->getMediaData()->getHomeURL();
+ return mMediaEntry.getHomeURL();
+ };
+
+ const LLMediaEntry &mMediaEntry;
+
+ } func_home_url(default_media_data);
+ identical = selected_objects->getSelectedTEValue(&func_home_url, value_str);
+ base_key = std::string(LLMediaEntry::HOME_URL_KEY);
+ mMediaSettings[base_key] = value_str;
+ mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
+
+ // Current URL
+ value_str = default_media_data.getCurrentURL();
+ struct functor_getter_current_url : public LLSelectedTEGetFunctor< std::string >
+ {
+ functor_getter_current_url(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
+ std::string get(LLViewerObject* object, S32 face)
+ {
+ if (object)
+ if (object->getTE(face))
+ if (object->getTE(face)->getMediaData())
+ return object->getTE(face)->getMediaData()->getCurrentURL();
+ return mMediaEntry.getCurrentURL();
+ };
+
+ const LLMediaEntry &mMediaEntry;
+
+ } func_current_url(default_media_data);
+ identical = selected_objects->getSelectedTEValue(&func_current_url, value_str);
+ base_key = std::string(LLMediaEntry::CURRENT_URL_KEY);
+ mMediaSettings[base_key] = value_str;
+ mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
+
+ // Auto zoom
+ value_bool = default_media_data.getAutoZoom();
+ struct functor_getter_auto_zoom : public LLSelectedTEGetFunctor< bool >
+ {
+
+ functor_getter_auto_zoom(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
+ bool get(LLViewerObject* object, S32 face)
+ {
+ if (object)
+ if (object->getTE(face))
+ if (object->getTE(face)->getMediaData())
+ return object->getTE(face)->getMediaData()->getAutoZoom();
+ return mMediaEntry.getAutoZoom();
+ };
+
+ const LLMediaEntry &mMediaEntry;
+
+ } func_auto_zoom(default_media_data);
+ identical = selected_objects->getSelectedTEValue(&func_auto_zoom, value_bool);
+ base_key = std::string(LLMediaEntry::AUTO_ZOOM_KEY);
+ mMediaSettings[base_key] = value_bool;
+ mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
+
+ // Auto play
+ //value_bool = default_media_data.getAutoPlay();
+ // set default to auto play true -- angela EXT-5172
+ value_bool = true;
+ struct functor_getter_auto_play : public LLSelectedTEGetFunctor< bool >
+ {
+ functor_getter_auto_play(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
+ bool get(LLViewerObject* object, S32 face)
+ {
+ if (object)
+ if (object->getTE(face))
+ if (object->getTE(face)->getMediaData())
+ return object->getTE(face)->getMediaData()->getAutoPlay();
+ //return mMediaEntry.getAutoPlay(); set default to auto play true -- angela EXT-5172
+ return true;
+ };
+
+ const LLMediaEntry &mMediaEntry;
+
+ } func_auto_play(default_media_data);
+ identical = selected_objects->getSelectedTEValue(&func_auto_play, value_bool);
+ base_key = std::string(LLMediaEntry::AUTO_PLAY_KEY);
+ mMediaSettings[base_key] = value_bool;
+ mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
+
+
+ // Auto scale
+ // set default to auto scale true -- angela EXT-5172
+ //value_bool = default_media_data.getAutoScale();
+ value_bool = true;
+ struct functor_getter_auto_scale : public LLSelectedTEGetFunctor< bool >
+ {
+ functor_getter_auto_scale(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
+ bool get(LLViewerObject* object, S32 face)
+ {
+ if (object)
+ if (object->getTE(face))
+ if (object->getTE(face)->getMediaData())
+ return object->getTE(face)->getMediaData()->getAutoScale();
+ // return mMediaEntry.getAutoScale(); set default to auto scale true -- angela EXT-5172
+ return true;
+ };
+
+ const LLMediaEntry &mMediaEntry;
+
+ } func_auto_scale(default_media_data);
+ identical = selected_objects->getSelectedTEValue(&func_auto_scale, value_bool);
+ base_key = std::string(LLMediaEntry::AUTO_SCALE_KEY);
+ mMediaSettings[base_key] = value_bool;
+ mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
+
+ // Auto loop
+ value_bool = default_media_data.getAutoLoop();
+ struct functor_getter_auto_loop : public LLSelectedTEGetFunctor< bool >
+ {
+ functor_getter_auto_loop(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
+ bool get(LLViewerObject* object, S32 face)
+ {
+ if (object)
+ if (object->getTE(face))
+ if (object->getTE(face)->getMediaData())
+ return object->getTE(face)->getMediaData()->getAutoLoop();
+ return mMediaEntry.getAutoLoop();
+ };
+
+ const LLMediaEntry &mMediaEntry;
+
+ } func_auto_loop(default_media_data);
+ identical = selected_objects->getSelectedTEValue(&func_auto_loop, value_bool);
+ base_key = std::string(LLMediaEntry::AUTO_LOOP_KEY);
+ mMediaSettings[base_key] = value_bool;
+ mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
+
+ // width pixels (if not auto scaled)
+ value_int = default_media_data.getWidthPixels();
+ struct functor_getter_width_pixels : public LLSelectedTEGetFunctor< int >
+ {
+ functor_getter_width_pixels(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
+ int get(LLViewerObject* object, S32 face)
+ {
+ if (object)
+ if (object->getTE(face))
+ if (object->getTE(face)->getMediaData())
+ return object->getTE(face)->getMediaData()->getWidthPixels();
+ return mMediaEntry.getWidthPixels();
+ };
+
+ const LLMediaEntry &mMediaEntry;
+
+ } func_width_pixels(default_media_data);
+ identical = selected_objects->getSelectedTEValue(&func_width_pixels, value_int);
+ base_key = std::string(LLMediaEntry::WIDTH_PIXELS_KEY);
+ mMediaSettings[base_key] = value_int;
+ mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
+
+ // height pixels (if not auto scaled)
+ value_int = default_media_data.getHeightPixels();
+ struct functor_getter_height_pixels : public LLSelectedTEGetFunctor< int >
+ {
+ functor_getter_height_pixels(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
+ int get(LLViewerObject* object, S32 face)
+ {
+ if (object)
+ if (object->getTE(face))
+ if (object->getTE(face)->getMediaData())
+ return object->getTE(face)->getMediaData()->getHeightPixels();
+ return mMediaEntry.getHeightPixels();
+ };
+
+ const LLMediaEntry &mMediaEntry;
+
+ } func_height_pixels(default_media_data);
+ identical = selected_objects->getSelectedTEValue(&func_height_pixels, value_int);
+ base_key = std::string(LLMediaEntry::HEIGHT_PIXELS_KEY);
+ mMediaSettings[base_key] = value_int;
+ mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
+
+ // Enable Alt image
+ value_bool = default_media_data.getAltImageEnable();
+ struct functor_getter_enable_alt_image : public LLSelectedTEGetFunctor< bool >
+ {
+ functor_getter_enable_alt_image(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
+ bool get(LLViewerObject* object, S32 face)
+ {
+ if (object)
+ if (object->getTE(face))
+ if (object->getTE(face)->getMediaData())
+ return object->getTE(face)->getMediaData()->getAltImageEnable();
+ return mMediaEntry.getAltImageEnable();
+ };
+
+ const LLMediaEntry &mMediaEntry;
+
+ } func_enable_alt_image(default_media_data);
+ identical = selected_objects->getSelectedTEValue(&func_enable_alt_image, value_bool);
+ base_key = std::string(LLMediaEntry::ALT_IMAGE_ENABLE_KEY);
+ mMediaSettings[base_key] = value_bool;
+ mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
+
+ // Perms - owner interact
+ value_bool = 0 != (default_media_data.getPermsInteract() & LLMediaEntry::PERM_OWNER);
+ struct functor_getter_perms_owner_interact : public LLSelectedTEGetFunctor< bool >
+ {
+ functor_getter_perms_owner_interact(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
+ bool get(LLViewerObject* object, S32 face)
+ {
+ if (object)
+ if (object->getTE(face))
+ if (object->getTE(face)->getMediaData())
+ return (0 != (object->getTE(face)->getMediaData()->getPermsInteract() & LLMediaEntry::PERM_OWNER));
+ return 0 != (mMediaEntry.getPermsInteract() & LLMediaEntry::PERM_OWNER);
+ };
+
+ const LLMediaEntry &mMediaEntry;
+
+ } func_perms_owner_interact(default_media_data);
+ identical = selected_objects->getSelectedTEValue(&func_perms_owner_interact, value_bool);
+ base_key = std::string(LLPanelContents::PERMS_OWNER_INTERACT_KEY);
+ mMediaSettings[base_key] = value_bool;
+ mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
+
+ // Perms - owner control
+ value_bool = 0 != (default_media_data.getPermsControl() & LLMediaEntry::PERM_OWNER);
+ struct functor_getter_perms_owner_control : public LLSelectedTEGetFunctor< bool >
+ {
+ functor_getter_perms_owner_control(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
+ bool get(LLViewerObject* object, S32 face)
+ {
+ if (object)
+ if (object->getTE(face))
+ if (object->getTE(face)->getMediaData())
+ return (0 != (object->getTE(face)->getMediaData()->getPermsControl() & LLMediaEntry::PERM_OWNER));
+ return 0 != (mMediaEntry.getPermsControl() & LLMediaEntry::PERM_OWNER);
+ };
+
+ const LLMediaEntry &mMediaEntry;
+
+ } func_perms_owner_control(default_media_data);
+ identical = selected_objects->getSelectedTEValue(&func_perms_owner_control, value_bool);
+ base_key = std::string(LLPanelContents::PERMS_OWNER_CONTROL_KEY);
+ mMediaSettings[base_key] = value_bool;
+ mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
+
+ // Perms - group interact
+ value_bool = 0 != (default_media_data.getPermsInteract() & LLMediaEntry::PERM_GROUP);
+ struct functor_getter_perms_group_interact : public LLSelectedTEGetFunctor< bool >
+ {
+ functor_getter_perms_group_interact(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
+ bool get(LLViewerObject* object, S32 face)
+ {
+ if (object)
+ if (object->getTE(face))
+ if (object->getTE(face)->getMediaData())
+ return (0 != (object->getTE(face)->getMediaData()->getPermsInteract() & LLMediaEntry::PERM_GROUP));
+ return 0 != (mMediaEntry.getPermsInteract() & LLMediaEntry::PERM_GROUP);
+ };
+
+ const LLMediaEntry &mMediaEntry;
+
+ } func_perms_group_interact(default_media_data);
+ identical = selected_objects->getSelectedTEValue(&func_perms_group_interact, value_bool);
+ base_key = std::string(LLPanelContents::PERMS_GROUP_INTERACT_KEY);
+ mMediaSettings[base_key] = value_bool;
+ mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
+
+ // Perms - group control
+ value_bool = 0 != (default_media_data.getPermsControl() & LLMediaEntry::PERM_GROUP);
+ struct functor_getter_perms_group_control : public LLSelectedTEGetFunctor< bool >
+ {
+ functor_getter_perms_group_control(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
+ bool get(LLViewerObject* object, S32 face)
+ {
+ if (object)
+ if (object->getTE(face))
+ if (object->getTE(face)->getMediaData())
+ return (0 != (object->getTE(face)->getMediaData()->getPermsControl() & LLMediaEntry::PERM_GROUP));
+ return 0 != (mMediaEntry.getPermsControl() & LLMediaEntry::PERM_GROUP);
+ };
+
+ const LLMediaEntry &mMediaEntry;
+
+ } func_perms_group_control(default_media_data);
+ identical = selected_objects->getSelectedTEValue(&func_perms_group_control, value_bool);
+ base_key = std::string(LLPanelContents::PERMS_GROUP_CONTROL_KEY);
+ mMediaSettings[base_key] = value_bool;
+ mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
+
+ // Perms - anyone interact
+ value_bool = 0 != (default_media_data.getPermsInteract() & LLMediaEntry::PERM_ANYONE);
+ struct functor_getter_perms_anyone_interact : public LLSelectedTEGetFunctor< bool >
+ {
+ functor_getter_perms_anyone_interact(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
+ bool get(LLViewerObject* object, S32 face)
+ {
+ if (object)
+ if (object->getTE(face))
+ if (object->getTE(face)->getMediaData())
+ return (0 != (object->getTE(face)->getMediaData()->getPermsInteract() & LLMediaEntry::PERM_ANYONE));
+ return 0 != (mMediaEntry.getPermsInteract() & LLMediaEntry::PERM_ANYONE);
+ };
+
+ const LLMediaEntry &mMediaEntry;
+
+ } func_perms_anyone_interact(default_media_data);
+ identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&func_perms_anyone_interact, value_bool);
+ base_key = std::string(LLPanelContents::PERMS_ANYONE_INTERACT_KEY);
+ mMediaSettings[base_key] = value_bool;
+ mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
+
+ // Perms - anyone control
+ value_bool = 0 != (default_media_data.getPermsControl() & LLMediaEntry::PERM_ANYONE);
+ struct functor_getter_perms_anyone_control : public LLSelectedTEGetFunctor< bool >
+ {
+ functor_getter_perms_anyone_control(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
+ bool get(LLViewerObject* object, S32 face)
+ {
+ if (object)
+ if (object->getTE(face))
+ if (object->getTE(face)->getMediaData())
+ return (0 != (object->getTE(face)->getMediaData()->getPermsControl() & LLMediaEntry::PERM_ANYONE));
+ return 0 != (mMediaEntry.getPermsControl() & LLMediaEntry::PERM_ANYONE);
+ };
+
+ const LLMediaEntry &mMediaEntry;
+
+ } func_perms_anyone_control(default_media_data);
+ identical = selected_objects->getSelectedTEValue(&func_perms_anyone_control, value_bool);
+ base_key = std::string(LLPanelContents::PERMS_ANYONE_CONTROL_KEY);
+ mMediaSettings[base_key] = value_bool;
+ mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
+
+ // security - whitelist enable
+ value_bool = default_media_data.getWhiteListEnable();
+ struct functor_getter_whitelist_enable : public LLSelectedTEGetFunctor< bool >
+ {
+ functor_getter_whitelist_enable(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
+ bool get(LLViewerObject* object, S32 face)
+ {
+ if (object)
+ if (object->getTE(face))
+ if (object->getTE(face)->getMediaData())
+ return object->getTE(face)->getMediaData()->getWhiteListEnable();
+ return mMediaEntry.getWhiteListEnable();
+ };
+
+ const LLMediaEntry &mMediaEntry;
+
+ } func_whitelist_enable(default_media_data);
+ identical = selected_objects->getSelectedTEValue(&func_whitelist_enable, value_bool);
+ base_key = std::string(LLMediaEntry::WHITELIST_ENABLE_KEY);
+ mMediaSettings[base_key] = value_bool;
+ mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
+
+ // security - whitelist URLs
+ std::vector<std::string> value_vector_str = default_media_data.getWhiteList();
+ struct functor_getter_whitelist_urls : public LLSelectedTEGetFunctor< std::vector<std::string> >
+ {
+ functor_getter_whitelist_urls(const LLMediaEntry& entry) : mMediaEntry(entry) {}
+
+ std::vector<std::string> get(LLViewerObject* object, S32 face)
+ {
+ if (object)
+ if (object->getTE(face))
+ if (object->getTE(face)->getMediaData())
+ return object->getTE(face)->getMediaData()->getWhiteList();
+ return mMediaEntry.getWhiteList();
+ };
+
+ const LLMediaEntry &mMediaEntry;
+
+ } func_whitelist_urls(default_media_data);
+ identical = selected_objects->getSelectedTEValue(&func_whitelist_urls, value_vector_str);
+ base_key = std::string(LLMediaEntry::WHITELIST_KEY);
+ mMediaSettings[base_key].clear();
+ std::vector< std::string >::iterator iter = value_vector_str.begin();
+ while (iter != value_vector_str.end())
+ {
+ std::string white_list_url = *iter;
+ mMediaSettings[base_key].append(white_list_url);
+ ++iter;
+ };
+
+ mMediaSettings[base_key + std::string(LLPanelContents::TENTATIVE_SUFFIX)] = !identical;
+}
+
+void LLPanelFace::updateMediaTitle()
+{
+ // only get the media name if we need it
+ if (!mNeedMediaTitle)
+ return;
+
+ // get plugin impl
+ LLPluginClassMedia* media_plugin = mTitleMedia->getMediaPlugin();
+ if (media_plugin && mTitleMedia->getCurrentNavUrl() == media_plugin->getNavigateURI())
+ {
+ // get the media name (asynchronous - must call repeatedly)
+ std::string media_title = media_plugin->getMediaName();
+
+ // only replace the title if what we get contains something
+ if (!media_title.empty())
+ {
+ // update the UI widget
+ if (mTitleMediaText)
+ {
+ mTitleMediaText->setText(media_title);
+
+ // stop looking for a title when we get one
+ mNeedMediaTitle = false;
+ };
+ };
+ };
+}
+
+//
+// Static functions
+//
+
+// static
+F32 LLPanelFace::valueGlow(LLViewerObject* object, S32 face)
+{
+ return (F32)(object->getTE(face)->getGlow());
+}
+
+
+void LLPanelFace::onCommitColor(const LLSD& data)
+{
+ sendColor();
+}
+
+void LLPanelFace::onCommitShinyColor(const LLSD& data)
+{
+ LLSelectedTEMaterial::setSpecularLightColor(this, getChild<LLColorSwatchCtrl>("shinycolorswatch")->get());
+}
+
+void LLPanelFace::onCommitAlpha(const LLSD& data)
+{
+ sendAlpha();
+}
+
+void LLPanelFace::onCancelColor(const LLSD& data)
+{
+ LLSelectMgr::getInstance()->selectionRevertColors();
+}
+
+void LLPanelFace::onCancelShinyColor(const LLSD& data)
+{
+ LLSelectMgr::getInstance()->selectionRevertShinyColors();
+}
+
+void LLPanelFace::onSelectColor(const LLSD& data)
+{
+ LLSelectMgr::getInstance()->saveSelectedObjectColors();
+ sendColor();
+}
+
+void LLPanelFace::onSelectShinyColor(const LLSD& data)
+{
+ LLSelectedTEMaterial::setSpecularLightColor(this, getChild<LLColorSwatchCtrl>("shinycolorswatch")->get());
+ LLSelectMgr::getInstance()->saveSelectedShinyColors();
+}
+
+// static
+void LLPanelFace::onCommitMaterialsMedia(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ // Force to default states to side-step problems with menu contents
+ // and generally reflecting old state when switching tabs or objects
+ //
+ self->updateShinyControls(false,true);
+ self->updateBumpyControls(false,true);
+ self->updateUI();
+ self->refreshMedia();
+}
+
+void LLPanelFace::updateVisibility(LLViewerObject* objectp /* = nullptr */)
+{
+ LLRadioGroup* radio_mat_type = findChild<LLRadioGroup>("radio_material_type");
+ LLRadioGroup* radio_pbr_type = findChild<LLRadioGroup>("radio_pbr_type");
+ LLComboBox* combo_shininess = findChild<LLComboBox>("combobox shininess");
+ LLComboBox* combo_bumpiness = findChild<LLComboBox>("combobox bumpiness");
+ if (!radio_mat_type || !radio_pbr_type || !mComboMatMedia || !combo_shininess || !combo_bumpiness)
+ {
+ LL_WARNS("Materials") << "Combo box not found...exiting." << LL_ENDL;
+ return;
+ }
+ U32 materials_media = mComboMatMedia->getCurrentIndex();
+ U32 material_type = radio_mat_type->getSelectedIndex();
+ bool show_media = (materials_media == MATMEDIA_MEDIA) && mComboMatMedia->getEnabled();
+ bool show_material = materials_media == MATMEDIA_MATERIAL;
+ bool show_texture = (show_media || (show_material && (material_type == MATTYPE_DIFFUSE) && mComboMatMedia->getEnabled()));
+ bool show_bumpiness = show_material && (material_type == MATTYPE_NORMAL) && mComboMatMedia->getEnabled();
+ bool show_shininess = show_material && (material_type == MATTYPE_SPECULAR) && mComboMatMedia->getEnabled();
+ const bool show_pbr = mComboMatMedia->getCurrentIndex() == MATMEDIA_PBR && mComboMatMedia->getEnabled();
+ const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
+ const LLGLTFMaterial::TextureInfo texture_info = texture_info_from_pbrtype(pbr_type);
+ const bool show_pbr_asset = show_pbr && texture_info == LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT;
+
+ radio_mat_type->setVisible(show_material);
+
+ // Shared material controls
+ getChildView("checkbox_sync_settings")->setVisible(show_material || show_media);
+ getChildView("tex gen")->setVisible(show_material || show_media || show_pbr_asset);
+ getChildView("combobox texgen")->setVisible(show_material || show_media || show_pbr_asset);
+ getChildView("button align textures")->setVisible(show_material || show_media);
+
+ // Media controls
+ mTitleMediaText->setVisible(show_media);
+ getChildView("add_media")->setVisible(show_media);
+ getChildView("delete_media")->setVisible(show_media);
+ getChildView("button align")->setVisible(show_media);
+
+ // Diffuse texture controls
+ getChildView("texture control")->setVisible(show_texture && show_material);
+ getChildView("label alphamode")->setVisible(show_texture && show_material);
+ getChildView("combobox alphamode")->setVisible(show_texture && show_material);
+ getChildView("label maskcutoff")->setVisible(false);
+ getChildView("maskcutoff")->setVisible(false);
+ if (show_texture && show_material)
+ {
+ updateAlphaControls();
+ }
+ // texture scale and position controls
+ getChildView("TexScaleU")->setVisible(show_texture);
+ getChildView("TexScaleV")->setVisible(show_texture);
+ getChildView("TexRot")->setVisible(show_texture);
+ getChildView("TexOffsetU")->setVisible(show_texture);
+ getChildView("TexOffsetV")->setVisible(show_texture);
+
+ // Specular map controls
+ getChildView("shinytexture control")->setVisible(show_shininess);
+ getChildView("combobox shininess")->setVisible(show_shininess);
+ getChildView("label shininess")->setVisible(show_shininess);
+ getChildView("label glossiness")->setVisible(false);
+ getChildView("glossiness")->setVisible(false);
+ getChildView("label environment")->setVisible(false);
+ getChildView("environment")->setVisible(false);
+ getChildView("label shinycolor")->setVisible(false);
+ getChildView("shinycolorswatch")->setVisible(false);
+ if (show_shininess)
+ {
+ updateShinyControls();
+ }
+ getChildView("shinyScaleU")->setVisible(show_shininess);
+ getChildView("shinyScaleV")->setVisible(show_shininess);
+ getChildView("shinyRot")->setVisible(show_shininess);
+ getChildView("shinyOffsetU")->setVisible(show_shininess);
+ getChildView("shinyOffsetV")->setVisible(show_shininess);
+
+ // Normal map controls
+ if (show_bumpiness)
+ {
+ updateBumpyControls();
+ }
+ getChildView("bumpytexture control")->setVisible(show_bumpiness);
+ getChildView("combobox bumpiness")->setVisible(show_bumpiness);
+ getChildView("label bumpiness")->setVisible(show_bumpiness);
+ getChildView("bumpyScaleU")->setVisible(show_bumpiness);
+ getChildView("bumpyScaleV")->setVisible(show_bumpiness);
+ getChildView("bumpyRot")->setVisible(show_bumpiness);
+ getChildView("bumpyOffsetU")->setVisible(show_bumpiness);
+ getChildView("bumpyOffsetV")->setVisible(show_bumpiness);
+
+ getChild<LLSpinCtrl>("rptctrl")->setVisible(show_material || show_media);
+
+ // PBR controls
+ updateVisibilityGLTF(objectp);
+}
+
+// static
+void LLPanelFace::onCommitMaterialType(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ // Force to default states to side-step problems with menu contents
+ // and generally reflecting old state when switching tabs or objects
+ //
+ self->updateShinyControls(false,true);
+ self->updateBumpyControls(false,true);
+ self->updateUI();
+}
+
+// static
+void LLPanelFace::onCommitPbrType(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*)userdata;
+ // Force to default states to side-step problems with menu contents
+ // and generally reflecting old state when switching tabs or objects
+ //
+ self->updateUI();
+}
+
+// static
+void LLPanelFace::onCommitBump(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+
+ LLComboBox* mComboBumpiness = self->getChild<LLComboBox>("combobox bumpiness");
+ if(!mComboBumpiness)
+ return;
+
+ U32 bumpiness = mComboBumpiness->getCurrentIndex();
+
+ self->sendBump(bumpiness);
+}
+
+// static
+void LLPanelFace::onCommitTexGen(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ self->sendTexGen();
+}
+
+// static
+void LLPanelFace::updateShinyControls(bool is_setting_texture, bool mess_with_shiny_combobox)
+{
+ LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>("shinytexture control");
+ LLUUID shiny_texture_ID = texture_ctrl->getImageAssetID();
+ LL_DEBUGS("Materials") << "Shiny texture selected: " << shiny_texture_ID << LL_ENDL;
+ LLComboBox* comboShiny = getChild<LLComboBox>("combobox shininess");
+
+ if(mess_with_shiny_combobox)
+ {
+ if (!comboShiny)
+ {
+ return;
+ }
+ if (!shiny_texture_ID.isNull() && is_setting_texture)
+ {
+ if (!comboShiny->itemExists(USE_TEXTURE))
+ {
+ comboShiny->add(USE_TEXTURE);
+ }
+ comboShiny->setSimple(USE_TEXTURE);
+ }
+ else
+ {
+ if (comboShiny->itemExists(USE_TEXTURE))
+ {
+ comboShiny->remove(SHINY_TEXTURE);
+ comboShiny->selectFirstItem();
+ }
+ }
+ }
+ else
+ {
+ if (shiny_texture_ID.isNull() && comboShiny && comboShiny->itemExists(USE_TEXTURE))
+ {
+ comboShiny->remove(SHINY_TEXTURE);
+ comboShiny->selectFirstItem();
+ }
+ }
+
+
+ LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type");
+ U32 materials_media = mComboMatMedia->getCurrentIndex();
+ U32 material_type = radio_mat_type->getSelectedIndex();
+ bool show_material = (materials_media == MATMEDIA_MATERIAL);
+ bool show_shininess = show_material && (material_type == MATTYPE_SPECULAR) && mComboMatMedia->getEnabled();
+ U32 shiny_value = comboShiny->getCurrentIndex();
+ bool show_shinyctrls = (shiny_value == SHINY_TEXTURE) && show_shininess; // Use texture
+ getChildView("label glossiness")->setVisible(show_shinyctrls);
+ getChildView("glossiness")->setVisible(show_shinyctrls);
+ getChildView("label environment")->setVisible(show_shinyctrls);
+ getChildView("environment")->setVisible(show_shinyctrls);
+ getChildView("label shinycolor")->setVisible(show_shinyctrls);
+ getChildView("shinycolorswatch")->setVisible(show_shinyctrls);
+}
+
+// static
+void LLPanelFace::updateBumpyControls(bool is_setting_texture, bool mess_with_combobox)
+{
+ LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>("bumpytexture control");
+ LLUUID bumpy_texture_ID = texture_ctrl->getImageAssetID();
+ LL_DEBUGS("Materials") << "texture: " << bumpy_texture_ID << (mess_with_combobox ? "" : " do not") << " update combobox" << LL_ENDL;
+ LLComboBox* comboBumpy = getChild<LLComboBox>("combobox bumpiness");
+ if (!comboBumpy)
+ {
+ return;
+ }
+
+ if (mess_with_combobox)
+ {
+ LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>("bumpytexture control");
+ LLUUID bumpy_texture_ID = texture_ctrl->getImageAssetID();
+ LL_DEBUGS("Materials") << "texture: " << bumpy_texture_ID << (mess_with_combobox ? "" : " do not") << " update combobox" << LL_ENDL;
+
+ if (!bumpy_texture_ID.isNull() && is_setting_texture)
+ {
+ if (!comboBumpy->itemExists(USE_TEXTURE))
+ {
+ comboBumpy->add(USE_TEXTURE);
+ }
+ comboBumpy->setSimple(USE_TEXTURE);
+ }
+ else
+ {
+ if (comboBumpy->itemExists(USE_TEXTURE))
+ {
+ comboBumpy->remove(BUMPY_TEXTURE);
+ comboBumpy->selectFirstItem();
+ }
+ }
+ }
+}
+
+// static
+void LLPanelFace::onCommitShiny(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+
+
+ LLComboBox* mComboShininess = self->getChild<LLComboBox>("combobox shininess");
+ if(!mComboShininess)
+ return;
+
+ U32 shininess = mComboShininess->getCurrentIndex();
+
+ self->sendShiny(shininess);
+}
+
+// static
+void LLPanelFace::updateAlphaControls()
+{
+ LLComboBox* comboAlphaMode = getChild<LLComboBox>("combobox alphamode");
+ if (!comboAlphaMode)
+ {
+ return;
+ }
+ U32 alpha_value = comboAlphaMode->getCurrentIndex();
+ bool show_alphactrls = (alpha_value == ALPHAMODE_MASK); // Alpha masking
+
+ U32 mat_media = MATMEDIA_MATERIAL;
+ if (mComboMatMedia)
+ {
+ mat_media = mComboMatMedia->getCurrentIndex();
+ }
+
+ U32 mat_type = MATTYPE_DIFFUSE;
+ LLRadioGroup* radio_mat_type = getChild<LLRadioGroup>("radio_material_type");
+ if(radio_mat_type)
+ {
+ mat_type = radio_mat_type->getSelectedIndex();
+ }
+
+ show_alphactrls = show_alphactrls && (mat_media == MATMEDIA_MATERIAL);
+ show_alphactrls = show_alphactrls && (mat_type == MATTYPE_DIFFUSE);
+
+ getChildView("label maskcutoff")->setVisible(show_alphactrls);
+ getChildView("maskcutoff")->setVisible(show_alphactrls);
+}
+
+// static
+void LLPanelFace::onCommitAlphaMode(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ self->updateAlphaControls();
+ LLSelectedTEMaterial::setDiffuseAlphaMode(self,self->getCurrentDiffuseAlphaMode());
+}
+
+// static
+void LLPanelFace::onCommitFullbright(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ self->sendFullbright();
+}
+
+// static
+void LLPanelFace::onCommitGlow(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ self->sendGlow();
+}
+
+// static
+bool LLPanelFace::onDragPbr(LLUICtrl*, LLInventoryItem* item)
+{
+ bool accept = true;
+ for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
+ iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
+ {
+ LLSelectNode* node = *iter;
+ LLViewerObject* obj = node->getObject();
+ if (!LLToolDragAndDrop::isInventoryDropAcceptable(obj, item))
+ {
+ accept = false;
+ break;
+ }
+ }
+ return accept;
+}
+
+void LLPanelFace::onCommitPbr(const LLSD& data)
+{
+ LLTextureCtrl* pbr_ctrl = findChild<LLTextureCtrl>("pbr_control");
+ if (!pbr_ctrl) return;
+ if (!pbr_ctrl->getTentative())
+ {
+ // we grab the item id first, because we want to do a
+ // permissions check in the selection manager. ARGH!
+ LLUUID id = pbr_ctrl->getImageItemID();
+ if (id.isNull())
+ {
+ id = pbr_ctrl->getImageAssetID();
+ }
+ if (!LLSelectMgr::getInstance()->selectionSetGLTFMaterial(id))
+ {
+ // If failed to set material, refresh pbr_ctrl's value
+ refresh();
+ }
+ }
+}
+
+void LLPanelFace::onCancelPbr(const LLSD& data)
+{
+ LLSelectMgr::getInstance()->selectionRevertGLTFMaterials();
+}
+
+void LLPanelFace::onSelectPbr(const LLSD& data)
+{
+ LLSelectMgr::getInstance()->saveSelectedObjectTextures();
+
+ LLTextureCtrl* pbr_ctrl = findChild<LLTextureCtrl>("pbr_control");
+ if (!pbr_ctrl) return;
+ if (!pbr_ctrl->getTentative())
+ {
+ // we grab the item id first, because we want to do a
+ // permissions check in the selection manager. ARGH!
+ LLUUID id = pbr_ctrl->getImageItemID();
+ if (id.isNull())
+ {
+ id = pbr_ctrl->getImageAssetID();
+ }
+ if (!LLSelectMgr::getInstance()->selectionSetGLTFMaterial(id))
+ {
+ refresh();
+ }
+ }
+}
+
+// static
+bool LLPanelFace::onDragTexture(LLUICtrl*, LLInventoryItem* item)
+{
+ bool accept = true;
+ for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin();
+ iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++)
+ {
+ LLSelectNode* node = *iter;
+ LLViewerObject* obj = node->getObject();
+ if (!LLToolDragAndDrop::isInventoryDropAcceptable(obj, item))
+ {
+ accept = false;
+ break;
+ }
+ }
+ return accept;
+}
+
+void LLPanelFace::onCommitTexture( const LLSD& data )
+{
+ add(LLStatViewer::EDIT_TEXTURE, 1);
+ sendTexture();
+}
+
+void LLPanelFace::onCancelTexture(const LLSD& data)
+{
+ LLSelectMgr::getInstance()->selectionRevertTextures();
+}
+
+void LLPanelFace::onSelectTexture(const LLSD& data)
+{
+ LLSelectMgr::getInstance()->saveSelectedObjectTextures();
+ sendTexture();
+
+ LLGLenum image_format;
+ bool identical_image_format = false;
+ LLSelectedTE::getImageFormat(image_format, identical_image_format);
+
+ LLCtrlSelectionInterface* combobox_alphamode =
+ childGetSelectionInterface("combobox alphamode");
+
+ U32 alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_NONE;
+ if (combobox_alphamode)
+ {
+ switch (image_format)
+ {
+ case GL_RGBA:
+ case GL_ALPHA:
+ {
+ alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND;
+ }
+ break;
+
+ case GL_RGB: break;
+ default:
+ {
+ LL_WARNS() << "Unexpected tex format in LLPanelFace...resorting to no alpha" << LL_ENDL;
+ }
+ break;
+ }
+
+ combobox_alphamode->selectNthItem(alpha_mode);
+ }
+ LLSelectedTEMaterial::setDiffuseAlphaMode(this, getCurrentDiffuseAlphaMode());
+}
+
+void LLPanelFace::onCloseTexturePicker(const LLSD& data)
+{
+ LL_DEBUGS("Materials") << data << LL_ENDL;
+ updateUI();
+}
+
+void LLPanelFace::onCommitSpecularTexture( const LLSD& data )
+{
+ LL_DEBUGS("Materials") << data << LL_ENDL;
+ sendShiny(SHINY_TEXTURE);
+}
+
+void LLPanelFace::onCommitNormalTexture( const LLSD& data )
+{
+ LL_DEBUGS("Materials") << data << LL_ENDL;
+ LLUUID nmap_id = getCurrentNormalMap();
+ sendBump(nmap_id.isNull() ? 0 : BUMPY_TEXTURE);
+}
+
+void LLPanelFace::onCancelSpecularTexture(const LLSD& data)
+{
+ U8 shiny = 0;
+ bool identical_shiny = false;
+ LLSelectedTE::getShiny(shiny, identical_shiny);
+ LLUUID spec_map_id = getChild<LLTextureCtrl>("shinytexture control")->getImageAssetID();
+ shiny = spec_map_id.isNull() ? shiny : SHINY_TEXTURE;
+ sendShiny(shiny);
+}
+
+void LLPanelFace::onCancelNormalTexture(const LLSD& data)
+{
+ U8 bumpy = 0;
+ bool identical_bumpy = false;
+ LLSelectedTE::getBumpmap(bumpy, identical_bumpy);
+ LLUUID spec_map_id = getChild<LLTextureCtrl>("bumpytexture control")->getImageAssetID();
+ bumpy = spec_map_id.isNull() ? bumpy : BUMPY_TEXTURE;
+ sendBump(bumpy);
+}
+
+void LLPanelFace::onSelectSpecularTexture(const LLSD& data)
+{
+ LL_DEBUGS("Materials") << data << LL_ENDL;
+ sendShiny(SHINY_TEXTURE);
+}
+
+void LLPanelFace::onSelectNormalTexture(const LLSD& data)
+{
+ LL_DEBUGS("Materials") << data << LL_ENDL;
+ LLUUID nmap_id = getCurrentNormalMap();
+ sendBump(nmap_id.isNull() ? 0 : BUMPY_TEXTURE);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// called when a user wants to edit existing media settings on a prim or prim face
+// TODO: test if there is media on the item and only allow editing if present
+void LLPanelFace::onClickBtnEditMedia(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*)userdata;
+ self->refreshMedia();
+ LLFloaterReg::showInstance("media_settings");
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// called when a user wants to delete media from a prim or prim face
+void LLPanelFace::onClickBtnDeleteMedia(LLUICtrl* ctrl, void* userdata)
+{
+ LLNotificationsUtil::add("DeleteMedia", LLSD(), LLSD(), deleteMediaConfirm);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// called when a user wants to add media to a prim or prim face
+void LLPanelFace::onClickBtnAddMedia(LLUICtrl* ctrl, void* userdata)
+{
+ // check if multiple faces are selected
+ if (LLSelectMgr::getInstance()->getSelection()->isMultipleTESelected())
+ {
+ LLPanelFace* self = (LLPanelFace*)userdata;
+ self->refreshMedia();
+ LLNotificationsUtil::add("MultipleFacesSelected", LLSD(), LLSD(), multipleFacesSelectedConfirm);
+ }
+ else
+ {
+ onClickBtnEditMedia(ctrl, userdata);
+ }
+}
+
+// static
+bool LLPanelFace::deleteMediaConfirm(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ switch (option)
+ {
+ case 0: // "Yes"
+ LLSelectMgr::getInstance()->selectionSetMedia(0, LLSD());
+ if (LLFloaterReg::instanceVisible("media_settings"))
+ {
+ LLFloaterReg::hideInstance("media_settings");
+ }
+ break;
+
+ case 1: // "No"
+ default:
+ break;
+ }
+ return false;
+}
+
+// static
+bool LLPanelFace::multipleFacesSelectedConfirm(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ switch (option)
+ {
+ case 0: // "Yes"
+ LLFloaterReg::showInstance("media_settings");
+ break;
+ case 1: // "No"
+ default:
+ break;
+ }
+ return false;
+}
+
+//static
+void LLPanelFace::syncOffsetX(LLPanelFace* self, F32 offsetU)
+{
+ LLSelectedTEMaterial::setNormalOffsetX(self,offsetU);
+ LLSelectedTEMaterial::setSpecularOffsetX(self,offsetU);
+ self->getChild<LLSpinCtrl>("TexOffsetU")->forceSetValue(offsetU);
+ self->sendTextureInfo();
+}
+
+//static
+void LLPanelFace::syncOffsetY(LLPanelFace* self, F32 offsetV)
+{
+ LLSelectedTEMaterial::setNormalOffsetY(self,offsetV);
+ LLSelectedTEMaterial::setSpecularOffsetY(self,offsetV);
+ self->getChild<LLSpinCtrl>("TexOffsetV")->forceSetValue(offsetV);
+ self->sendTextureInfo();
+}
+
+//static
+void LLPanelFace::onCommitMaterialBumpyOffsetX(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ llassert_always(self);
+
+ if (gSavedSettings.getBOOL("SyncMaterialSettings"))
+ {
+ syncOffsetX(self,self->getCurrentBumpyOffsetU());
+ }
+ else
+ {
+ LLSelectedTEMaterial::setNormalOffsetX(self,self->getCurrentBumpyOffsetU());
+ }
+
+}
+
+//static
+void LLPanelFace::onCommitMaterialBumpyOffsetY(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ llassert_always(self);
+
+ if (gSavedSettings.getBOOL("SyncMaterialSettings"))
+ {
+ syncOffsetY(self,self->getCurrentBumpyOffsetV());
+ }
+ else
+ {
+ LLSelectedTEMaterial::setNormalOffsetY(self,self->getCurrentBumpyOffsetV());
+ }
+}
+
+//static
+void LLPanelFace::onCommitMaterialShinyOffsetX(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ llassert_always(self);
+
+ if (gSavedSettings.getBOOL("SyncMaterialSettings"))
+ {
+ syncOffsetX(self, self->getCurrentShinyOffsetU());
+ }
+ else
+ {
+ LLSelectedTEMaterial::setSpecularOffsetX(self,self->getCurrentShinyOffsetU());
+ }
+}
+
+//static
+void LLPanelFace::onCommitMaterialShinyOffsetY(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ llassert_always(self);
+
+ if (gSavedSettings.getBOOL("SyncMaterialSettings"))
+ {
+ syncOffsetY(self,self->getCurrentShinyOffsetV());
+ }
+ else
+ {
+ LLSelectedTEMaterial::setSpecularOffsetY(self,self->getCurrentShinyOffsetV());
+ }
+}
+
+//static
+void LLPanelFace::syncRepeatX(LLPanelFace* self, F32 scaleU)
+{
+ LLSelectedTEMaterial::setNormalRepeatX(self,scaleU);
+ LLSelectedTEMaterial::setSpecularRepeatX(self,scaleU);
+ self->sendTextureInfo();
+}
+
+//static
+void LLPanelFace::syncRepeatY(LLPanelFace* self, F32 scaleV)
+{
+ LLSelectedTEMaterial::setNormalRepeatY(self,scaleV);
+ LLSelectedTEMaterial::setSpecularRepeatY(self,scaleV);
+ self->sendTextureInfo();
+}
+
+//static
+void LLPanelFace::onCommitMaterialBumpyScaleX(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ llassert_always(self);
+ F32 bumpy_scale_u = self->getCurrentBumpyScaleU();
+ if (self->isIdenticalPlanarTexgen())
+ {
+ bumpy_scale_u *= 0.5f;
+ }
+
+ if (gSavedSettings.getBOOL("SyncMaterialSettings"))
+ {
+ self->getChild<LLSpinCtrl>("TexScaleU")->forceSetValue(self->getCurrentBumpyScaleU());
+ syncRepeatX(self, bumpy_scale_u);
+ }
+ else
+ {
+ LLSelectedTEMaterial::setNormalRepeatX(self,bumpy_scale_u);
+ }
+}
+
+//static
+void LLPanelFace::onCommitMaterialBumpyScaleY(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ llassert_always(self);
+ F32 bumpy_scale_v = self->getCurrentBumpyScaleV();
+ if (self->isIdenticalPlanarTexgen())
+ {
+ bumpy_scale_v *= 0.5f;
+ }
+
+
+ if (gSavedSettings.getBOOL("SyncMaterialSettings"))
+ {
+ self->getChild<LLSpinCtrl>("TexScaleV")->forceSetValue(self->getCurrentBumpyScaleV());
+ syncRepeatY(self, bumpy_scale_v);
+ }
+ else
+ {
+ LLSelectedTEMaterial::setNormalRepeatY(self,bumpy_scale_v);
+ }
+}
+
+//static
+void LLPanelFace::onCommitMaterialShinyScaleX(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ llassert_always(self);
+ F32 shiny_scale_u = self->getCurrentShinyScaleU();
+ if (self->isIdenticalPlanarTexgen())
+ {
+ shiny_scale_u *= 0.5f;
+ }
+
+ if (gSavedSettings.getBOOL("SyncMaterialSettings"))
+ {
+ self->getChild<LLSpinCtrl>("TexScaleU")->forceSetValue(self->getCurrentShinyScaleU());
+ syncRepeatX(self, shiny_scale_u);
+ }
+ else
+ {
+ LLSelectedTEMaterial::setSpecularRepeatX(self,shiny_scale_u);
+ }
+}
+
+//static
+void LLPanelFace::onCommitMaterialShinyScaleY(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ llassert_always(self);
+ F32 shiny_scale_v = self->getCurrentShinyScaleV();
+ if (self->isIdenticalPlanarTexgen())
+ {
+ shiny_scale_v *= 0.5f;
+ }
+
+ if (gSavedSettings.getBOOL("SyncMaterialSettings"))
+ {
+ self->getChild<LLSpinCtrl>("TexScaleV")->forceSetValue(self->getCurrentShinyScaleV());
+ syncRepeatY(self, shiny_scale_v);
+ }
+ else
+ {
+ LLSelectedTEMaterial::setSpecularRepeatY(self,shiny_scale_v);
+ }
+}
+
+//static
+void LLPanelFace::syncMaterialRot(LLPanelFace* self, F32 rot, int te)
+{
+ LLSelectedTEMaterial::setNormalRotation(self,rot * DEG_TO_RAD, te);
+ LLSelectedTEMaterial::setSpecularRotation(self,rot * DEG_TO_RAD, te);
+ self->sendTextureInfo();
+}
+
+//static
+void LLPanelFace::onCommitMaterialBumpyRot(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ llassert_always(self);
+
+ if (gSavedSettings.getBOOL("SyncMaterialSettings"))
+ {
+ self->getChild<LLSpinCtrl>("TexRot")->forceSetValue(self->getCurrentBumpyRot());
+ syncMaterialRot(self, self->getCurrentBumpyRot());
+ }
+ else
+ {
+ if ((bool)self->childGetValue("checkbox planar align").asBoolean())
+ {
+ LLFace* last_face = NULL;
+ bool identical_face = false;
+ LLSelectedTE::getFace(last_face, identical_face);
+ LLPanelFaceSetAlignedTEFunctor setfunc(self, last_face);
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
+ }
+ else
+ {
+ LLSelectedTEMaterial::setNormalRotation(self, self->getCurrentBumpyRot() * DEG_TO_RAD);
+ }
+ }
+}
+
+//static
+void LLPanelFace::onCommitMaterialShinyRot(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ llassert_always(self);
+
+ if (gSavedSettings.getBOOL("SyncMaterialSettings"))
+ {
+ self->getChild<LLSpinCtrl>("TexRot")->forceSetValue(self->getCurrentShinyRot());
+ syncMaterialRot(self, self->getCurrentShinyRot());
+ }
+ else
+ {
+ if ((bool)self->childGetValue("checkbox planar align").asBoolean())
+ {
+ LLFace* last_face = NULL;
+ bool identical_face = false;
+ LLSelectedTE::getFace(last_face, identical_face);
+ LLPanelFaceSetAlignedTEFunctor setfunc(self, last_face);
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
+ }
+ else
+ {
+ LLSelectedTEMaterial::setSpecularRotation(self, self->getCurrentShinyRot() * DEG_TO_RAD);
+ }
+ }
+}
+
+//static
+void LLPanelFace::onCommitMaterialGloss(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ llassert_always(self);
+ LLSelectedTEMaterial::setSpecularLightExponent(self,self->getCurrentGlossiness());
+}
+
+//static
+void LLPanelFace::onCommitMaterialEnv(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ llassert_always(self);
+ LLSelectedTEMaterial::setEnvironmentIntensity(self,self->getCurrentEnvIntensity());
+}
+
+//static
+void LLPanelFace::onCommitMaterialMaskCutoff(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ LLSelectedTEMaterial::setAlphaMaskCutoff(self,self->getCurrentAlphaMaskCutoff());
+}
+
+// static
+void LLPanelFace::onCommitTextureInfo( LLUICtrl* ctrl, void* userdata )
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ self->sendTextureInfo();
+ // vertical scale and repeats per meter depends on each other, so force set on changes
+ self->updateUI(true);
+}
+
+// static
+void LLPanelFace::onCommitTextureScaleX( LLUICtrl* ctrl, void* userdata )
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ if (gSavedSettings.getBOOL("SyncMaterialSettings"))
+ {
+ F32 bumpy_scale_u = self->getChild<LLUICtrl>("TexScaleU")->getValue().asReal();
+ if (self->isIdenticalPlanarTexgen())
+ {
+ bumpy_scale_u *= 0.5f;
+ }
+ syncRepeatX(self, bumpy_scale_u);
+ }
+ else
+ {
+ self->sendTextureInfo();
+ }
+ self->updateUI(true);
+}
+
+// static
+void LLPanelFace::onCommitTextureScaleY( LLUICtrl* ctrl, void* userdata )
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ if (gSavedSettings.getBOOL("SyncMaterialSettings"))
+ {
+ F32 bumpy_scale_v = self->getChild<LLUICtrl>("TexScaleV")->getValue().asReal();
+ if (self->isIdenticalPlanarTexgen())
+ {
+ bumpy_scale_v *= 0.5f;
+ }
+ syncRepeatY(self, bumpy_scale_v);
+ }
+ else
+ {
+ self->sendTextureInfo();
+ }
+ self->updateUI(true);
+}
+
+// static
+void LLPanelFace::onCommitTextureRot( LLUICtrl* ctrl, void* userdata )
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+
+ if (gSavedSettings.getBOOL("SyncMaterialSettings"))
+ {
+ syncMaterialRot(self, self->getChild<LLUICtrl>("TexRot")->getValue().asReal());
+ }
+ else
+ {
+ self->sendTextureInfo();
+ }
+ self->updateUI(true);
+}
+
+// static
+void LLPanelFace::onCommitTextureOffsetX( LLUICtrl* ctrl, void* userdata )
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ if (gSavedSettings.getBOOL("SyncMaterialSettings"))
+ {
+ syncOffsetX(self, self->getChild<LLUICtrl>("TexOffsetU")->getValue().asReal());
+ }
+ else
+ {
+ self->sendTextureInfo();
+ }
+ self->updateUI(true);
+}
+
+// static
+void LLPanelFace::onCommitTextureOffsetY( LLUICtrl* ctrl, void* userdata )
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ if (gSavedSettings.getBOOL("SyncMaterialSettings"))
+ {
+ syncOffsetY(self, self->getChild<LLUICtrl>("TexOffsetV")->getValue().asReal());
+ }
+ else
+ {
+ self->sendTextureInfo();
+ }
+ self->updateUI(true);
+}
+
+// Commit the number of repeats per meter
+// static
+void LLPanelFace::onCommitRepeatsPerMeter(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+
+ LLUICtrl* repeats_ctrl = self->getChild<LLUICtrl>("rptctrl");
+
+ U32 materials_media = self->mComboMatMedia->getCurrentIndex();
+ U32 material_type = 0;
+ if (materials_media == MATMEDIA_PBR)
+ {
+ LLRadioGroup* radio_mat_type = self->getChild<LLRadioGroup>("radio_pbr_type");
+ material_type = radio_mat_type->getSelectedIndex();
+ }
+ if (materials_media == MATMEDIA_MATERIAL)
+ {
+ LLRadioGroup* radio_mat_type = self->getChild<LLRadioGroup>("radio_material_type");
+ material_type = radio_mat_type->getSelectedIndex();
+ }
+
+ F32 repeats_per_meter = repeats_ctrl->getValue().asReal();
+
+ F32 obj_scale_s = 1.0f;
+ F32 obj_scale_t = 1.0f;
+
+ bool identical_scale_s = false;
+ bool identical_scale_t = false;
+
+ LLSelectedTE::getObjectScaleS(obj_scale_s, identical_scale_s);
+ LLSelectedTE::getObjectScaleS(obj_scale_t, identical_scale_t);
+
+ LLUICtrl* bumpy_scale_u = self->getChild<LLUICtrl>("bumpyScaleU");
+ LLUICtrl* bumpy_scale_v = self->getChild<LLUICtrl>("bumpyScaleV");
+ LLUICtrl* shiny_scale_u = self->getChild<LLUICtrl>("shinyScaleU");
+ LLUICtrl* shiny_scale_v = self->getChild<LLUICtrl>("shinyScaleV");
+
+ if (gSavedSettings.getBOOL("SyncMaterialSettings"))
+ {
+ LLSelectMgr::getInstance()->selectionTexScaleAutofit( repeats_per_meter );
+
+ bumpy_scale_u->setValue(obj_scale_s * repeats_per_meter);
+ bumpy_scale_v->setValue(obj_scale_t * repeats_per_meter);
+
+ LLSelectedTEMaterial::setNormalRepeatX(self,obj_scale_s * repeats_per_meter);
+ LLSelectedTEMaterial::setNormalRepeatY(self,obj_scale_t * repeats_per_meter);
+
+ shiny_scale_u->setValue(obj_scale_s * repeats_per_meter);
+ shiny_scale_v->setValue(obj_scale_t * repeats_per_meter);
+
+ LLSelectedTEMaterial::setSpecularRepeatX(self,obj_scale_s * repeats_per_meter);
+ LLSelectedTEMaterial::setSpecularRepeatY(self,obj_scale_t * repeats_per_meter);
+ }
+ else
+ {
+ switch (material_type)
+ {
+ case MATTYPE_DIFFUSE:
+ {
+ LLSelectMgr::getInstance()->selectionTexScaleAutofit( repeats_per_meter );
+ }
+ break;
+
+ case MATTYPE_NORMAL:
+ {
+ bumpy_scale_u->setValue(obj_scale_s * repeats_per_meter);
+ bumpy_scale_v->setValue(obj_scale_t * repeats_per_meter);
+
+ LLSelectedTEMaterial::setNormalRepeatX(self,obj_scale_s * repeats_per_meter);
+ LLSelectedTEMaterial::setNormalRepeatY(self,obj_scale_t * repeats_per_meter);
+ }
+ break;
+
+ case MATTYPE_SPECULAR:
+ {
+ shiny_scale_u->setValue(obj_scale_s * repeats_per_meter);
+ shiny_scale_v->setValue(obj_scale_t * repeats_per_meter);
+
+ LLSelectedTEMaterial::setSpecularRepeatX(self,obj_scale_s * repeats_per_meter);
+ LLSelectedTEMaterial::setSpecularRepeatY(self,obj_scale_t * repeats_per_meter);
+ }
+ break;
+
+ default:
+ llassert(false);
+ break;
+ }
+ }
+ // vertical scale and repeats per meter depends on each other, so force set on changes
+ self->updateUI(true);
+}
+
+struct LLPanelFaceSetMediaFunctor : public LLSelectedTEFunctor
+{
+ virtual bool apply(LLViewerObject* object, S32 te)
+ {
+ viewer_media_t pMediaImpl;
+
+ const LLTextureEntry* tep = object->getTE(te);
+ const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
+ if ( mep )
+ {
+ pMediaImpl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(mep->getMediaID());
+ }
+
+ if ( pMediaImpl.isNull())
+ {
+ // If we didn't find face media for this face, check whether this face is showing parcel media.
+ pMediaImpl = LLViewerMedia::getInstance()->getMediaImplFromTextureID(tep->getID());
+ }
+
+ if ( pMediaImpl.notNull())
+ {
+ LLPluginClassMedia *media = pMediaImpl->getMediaPlugin();
+ if(media)
+ {
+ S32 media_width = media->getWidth();
+ S32 media_height = media->getHeight();
+ S32 texture_width = media->getTextureWidth();
+ S32 texture_height = media->getTextureHeight();
+ F32 scale_s = (F32)media_width / (F32)texture_width;
+ F32 scale_t = (F32)media_height / (F32)texture_height;
+
+ // set scale and adjust offset
+ object->setTEScaleS( te, scale_s );
+ object->setTEScaleT( te, scale_t ); // don't need to flip Y anymore since QT does this for us now.
+ object->setTEOffsetS( te, -( 1.0f - scale_s ) / 2.0f );
+ object->setTEOffsetT( te, -( 1.0f - scale_t ) / 2.0f );
+ }
+ }
+ return true;
+ };
+};
+
+void LLPanelFace::onClickAutoFix(void* userdata)
+{
+ LLPanelFaceSetMediaFunctor setfunc;
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc);
+
+ LLPanelFaceSendFunctor sendfunc;
+ LLSelectMgr::getInstance()->getSelection()->applyToObjects(&sendfunc);
+}
+
+void LLPanelFace::onAlignTexture(void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*)userdata;
+ self->alignTestureLayer();
+}
+
+void LLPanelFace::onClickBtnLoadInvPBR(void* userdata)
+{
+ // Shouldn't this be "save to inventory?"
+ LLPanelFace* self = (LLPanelFace*)userdata;
+ LLTextureCtrl* pbr_ctrl = self->findChild<LLTextureCtrl>("pbr_control");
+ pbr_ctrl->showPicker(true);
+}
+
+void LLPanelFace::onClickBtnEditPBR(void* userdata)
+{
+ LLMaterialEditor::loadLive();
+}
+
+void LLPanelFace::onClickBtnSavePBR(void* userdata)
+{
+ LLMaterialEditor::saveObjectsMaterialAs();
+}
+
+enum EPasteMode
+{
+ PASTE_COLOR,
+ PASTE_TEXTURE
+};
+
+struct LLPanelFacePasteTexFunctor : public LLSelectedTEFunctor
+{
+ LLPanelFacePasteTexFunctor(LLPanelFace* panel, EPasteMode mode) :
+ mPanelFace(panel), mMode(mode) {}
+
+ virtual bool apply(LLViewerObject* objectp, S32 te)
+ {
+ switch (mMode)
+ {
+ case PASTE_COLOR:
+ mPanelFace->onPasteColor(objectp, te);
+ break;
+ case PASTE_TEXTURE:
+ mPanelFace->onPasteTexture(objectp, te);
+ break;
+ }
+ return true;
+ }
+private:
+ LLPanelFace *mPanelFace;
+ EPasteMode mMode;
+};
+
+struct LLPanelFaceUpdateFunctor : public LLSelectedObjectFunctor
+{
+ LLPanelFaceUpdateFunctor(bool update_media)
+ : mUpdateMedia(update_media)
+ {}
+
+ virtual bool apply(LLViewerObject* object)
+ {
+ object->sendTEUpdate();
+
+ if (mUpdateMedia)
+ {
+ LLVOVolume *vo = dynamic_cast<LLVOVolume*>(object);
+ if (vo && vo->hasMedia())
+ {
+ vo->sendMediaDataUpdate();
+ }
+ }
+ return true;
+ }
+private:
+ bool mUpdateMedia;
+};
+
+struct LLPanelFaceNavigateHomeFunctor : public LLSelectedTEFunctor
+{
+ virtual bool apply(LLViewerObject* objectp, S32 te)
+ {
+ if (objectp && objectp->getTE(te))
+ {
+ LLTextureEntry* tep = objectp->getTE(te);
+ const LLMediaEntry *media_data = tep->getMediaData();
+ if (media_data)
+ {
+ if (media_data->getCurrentURL().empty() && media_data->getAutoPlay())
+ {
+ viewer_media_t media_impl =
+ LLViewerMedia::getInstance()->getMediaImplFromTextureID(tep->getMediaData()->getMediaID());
+ if (media_impl)
+ {
+ media_impl->navigateHome();
+ }
+ }
+ }
+ }
+ return true;
+ }
+};
+
+void LLPanelFace::onCopyColor()
+{
+ LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+ LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode();
+ S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
+ if (!objectp || !node
+ || objectp->getPCode() != LL_PCODE_VOLUME
+ || !objectp->permModify()
+ || objectp->isPermanentEnforced()
+ || selected_count > 1)
+ {
+ return;
+ }
+
+ if (mClipboardParams.has("color"))
+ {
+ mClipboardParams["color"].clear();
+ }
+ else
+ {
+ mClipboardParams["color"] = LLSD::emptyArray();
+ }
+
+ std::map<LLUUID, LLUUID> asset_item_map;
+
+ // a way to resolve situations where source and target have different amount of faces
+ S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces());
+ mClipboardParams["color_all_tes"] = (num_tes != 1) || (LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool());
+ for (S32 te = 0; te < num_tes; ++te)
+ {
+ if (node->isTESelected(te))
+ {
+ LLTextureEntry* tep = objectp->getTE(te);
+ if (tep)
+ {
+ LLSD te_data;
+
+ // asLLSD() includes media
+ te_data["te"] = tep->asLLSD(); // Note: includes a lot more than just color/alpha/glow
+
+ mClipboardParams["color"].append(te_data);
+ }
+ }
+ }
+}
+
+void LLPanelFace::onPasteColor()
+{
+ if (!mClipboardParams.has("color"))
+ {
+ return;
+ }
+
+ LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+ LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode();
+ S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
+ if (!objectp || !node
+ || objectp->getPCode() != LL_PCODE_VOLUME
+ || !objectp->permModify()
+ || objectp->isPermanentEnforced()
+ || selected_count > 1)
+ {
+ // not supposed to happen
+ LL_WARNS() << "Failed to paste color due to missing or wrong selection" << LL_ENDL;
+ return;
+ }
+
+ bool face_selection_mode = LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool();
+ LLSD &clipboard = mClipboardParams["color"]; // array
+ S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces());
+ S32 compare_tes = num_tes;
+
+ if (face_selection_mode)
+ {
+ compare_tes = 0;
+ for (S32 te = 0; te < num_tes; ++te)
+ {
+ if (node->isTESelected(te))
+ {
+ compare_tes++;
+ }
+ }
+ }
+
+ // we can copy if single face was copied in edit face mode or if face count matches
+ if (!((clipboard.size() == 1) && mClipboardParams["color_all_tes"].asBoolean())
+ && compare_tes != clipboard.size())
+ {
+ LLSD notif_args;
+ if (face_selection_mode)
+ {
+ static std::string reason = getString("paste_error_face_selection_mismatch");
+ notif_args["REASON"] = reason;
+ }
+ else
+ {
+ static std::string reason = getString("paste_error_object_face_count_mismatch");
+ notif_args["REASON"] = reason;
+ }
+ LLNotificationsUtil::add("FacePasteFailed", notif_args);
+ return;
+ }
+
+ LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection();
+
+ LLPanelFacePasteTexFunctor paste_func(this, PASTE_COLOR);
+ selected_objects->applyToTEs(&paste_func);
+
+ LLPanelFaceUpdateFunctor sendfunc(false);
+ selected_objects->applyToObjects(&sendfunc);
+}
+
+void LLPanelFace::onPasteColor(LLViewerObject* objectp, S32 te)
+{
+ LLSD te_data;
+ LLSD &clipboard = mClipboardParams["color"]; // array
+ if ((clipboard.size() == 1) && mClipboardParams["color_all_tes"].asBoolean())
+ {
+ te_data = *(clipboard.beginArray());
+ }
+ else if (clipboard[te])
+ {
+ te_data = clipboard[te];
+ }
+ else
+ {
+ return;
+ }
+
+ LLTextureEntry* tep = objectp->getTE(te);
+ if (tep)
+ {
+ if (te_data.has("te"))
+ {
+ // Color / Alpha
+ if (te_data["te"].has("colors"))
+ {
+ LLColor4 color = tep->getColor();
+
+ LLColor4 clip_color;
+ clip_color.setValue(te_data["te"]["colors"]);
+
+ // Color
+ color.mV[VRED] = clip_color.mV[VRED];
+ color.mV[VGREEN] = clip_color.mV[VGREEN];
+ color.mV[VBLUE] = clip_color.mV[VBLUE];
+
+ // Alpha
+ color.mV[VALPHA] = clip_color.mV[VALPHA];
+
+ objectp->setTEColor(te, color);
+ }
+
+ // Color/fullbright
+ if (te_data["te"].has("fullbright"))
+ {
+ objectp->setTEFullbright(te, te_data["te"]["fullbright"].asInteger());
+ }
+
+ // Glow
+ if (te_data["te"].has("glow"))
+ {
+ objectp->setTEGlow(te, (F32)te_data["te"]["glow"].asReal());
+ }
+ }
+ }
+}
+
+void LLPanelFace::onCopyTexture()
+{
+ LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+ LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode();
+ S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
+ if (!objectp || !node
+ || objectp->getPCode() != LL_PCODE_VOLUME
+ || !objectp->permModify()
+ || objectp->isPermanentEnforced()
+ || selected_count > 1
+ || !LLMaterialEditor::canClipboardObjectsMaterial())
+ {
+ return;
+ }
+
+ if (mClipboardParams.has("texture"))
+ {
+ mClipboardParams["texture"].clear();
+ }
+ else
+ {
+ mClipboardParams["texture"] = LLSD::emptyArray();
+ }
+
+ std::map<LLUUID, LLUUID> asset_item_map;
+
+ // a way to resolve situations where source and target have different amount of faces
+ S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces());
+ mClipboardParams["texture_all_tes"] = (num_tes != 1) || (LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool());
+ for (S32 te = 0; te < num_tes; ++te)
+ {
+ if (node->isTESelected(te))
+ {
+ LLTextureEntry* tep = objectp->getTE(te);
+ if (tep)
+ {
+ LLSD te_data;
+
+ // asLLSD() includes media
+ te_data["te"] = tep->asLLSD();
+ te_data["te"]["shiny"] = tep->getShiny();
+ te_data["te"]["bumpmap"] = tep->getBumpmap();
+ te_data["te"]["bumpshiny"] = tep->getBumpShiny();
+ te_data["te"]["bumpfullbright"] = tep->getBumpShinyFullbright();
+ te_data["te"]["texgen"] = tep->getTexGen();
+ te_data["te"]["pbr"] = objectp->getRenderMaterialID(te);
+ if (tep->getGLTFMaterialOverride() != nullptr)
+ {
+ te_data["te"]["pbr_override"] = tep->getGLTFMaterialOverride()->asJSON();
+ }
+
+ if (te_data["te"].has("imageid"))
+ {
+ LLUUID item_id;
+ LLUUID id = te_data["te"]["imageid"].asUUID();
+ bool from_library = get_is_predefined_texture(id);
+ bool full_perm = from_library;
+
+ if (!full_perm
+ && objectp->permCopy()
+ && objectp->permTransfer()
+ && objectp->permModify())
+ {
+ // If agent created this object and nothing is limiting permissions, mark as full perm
+ // If agent was granted permission to edit objects owned and created by somebody else, mark full perm
+ // This check is not perfect since we can't figure out whom textures belong to so this ended up restrictive
+ std::string creator_app_link;
+ LLUUID creator_id;
+ LLSelectMgr::getInstance()->selectGetCreator(creator_id, creator_app_link);
+ full_perm = objectp->mOwnerID == creator_id;
+ }
+
+ if (id.notNull() && !full_perm)
+ {
+ std::map<LLUUID, LLUUID>::iterator iter = asset_item_map.find(id);
+ if (iter != asset_item_map.end())
+ {
+ item_id = iter->second;
+ }
+ else
+ {
+ // What this does is simply searches inventory for item with same asset id,
+ // as result it is Hightly unreliable, leaves little control to user, borderline hack
+ // but there are little options to preserve permissions - multiple inventory
+ // items might reference same asset and inventory search is expensive.
+ bool no_transfer = false;
+ if (objectp->getInventoryItemByAsset(id))
+ {
+ no_transfer = !objectp->getInventoryItemByAsset(id)->getIsFullPerm();
+ }
+ item_id = get_copy_free_item_by_asset_id(id, no_transfer);
+ // record value to avoid repeating inventory search when possible
+ asset_item_map[id] = item_id;
+ }
+ }
+
+ if (item_id.notNull() && gInventory.isObjectDescendentOf(item_id, gInventory.getLibraryRootFolderID()))
+ {
+ full_perm = true;
+ from_library = true;
+ }
+
+ {
+ te_data["te"]["itemfullperm"] = full_perm;
+ te_data["te"]["fromlibrary"] = from_library;
+
+ // If full permission object, texture is free to copy,
+ // but otherwise we need to check inventory and extract permissions
+ //
+ // Normally we care only about restrictions for current user and objects
+ // don't inherit any 'next owner' permissions from texture, so there is
+ // no need to record item id if full_perm==true
+ if (!full_perm && !from_library && item_id.notNull())
+ {
+ LLViewerInventoryItem* itemp = gInventory.getItem(item_id);
+ if (itemp)
+ {
+ LLPermissions item_permissions = itemp->getPermissions();
+ if (item_permissions.allowOperationBy(PERM_COPY,
+ gAgent.getID(),
+ gAgent.getGroupID()))
+ {
+ te_data["te"]["imageitemid"] = item_id;
+ te_data["te"]["itemfullperm"] = itemp->getIsFullPerm();
+ if (!itemp->isFinished())
+ {
+ // needed for dropTextureAllFaces
+ LLInventoryModelBackgroundFetch::instance().start(item_id, false);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ LLMaterialPtr material_ptr = tep->getMaterialParams();
+ if (!material_ptr.isNull())
+ {
+ LLSD mat_data;
+
+ mat_data["NormMap"] = material_ptr->getNormalID();
+ mat_data["SpecMap"] = material_ptr->getSpecularID();
+
+ mat_data["NormRepX"] = material_ptr->getNormalRepeatX();
+ mat_data["NormRepY"] = material_ptr->getNormalRepeatY();
+ mat_data["NormOffX"] = material_ptr->getNormalOffsetX();
+ mat_data["NormOffY"] = material_ptr->getNormalOffsetY();
+ mat_data["NormRot"] = material_ptr->getNormalRotation();
+
+ mat_data["SpecRepX"] = material_ptr->getSpecularRepeatX();
+ mat_data["SpecRepY"] = material_ptr->getSpecularRepeatY();
+ mat_data["SpecOffX"] = material_ptr->getSpecularOffsetX();
+ mat_data["SpecOffY"] = material_ptr->getSpecularOffsetY();
+ mat_data["SpecRot"] = material_ptr->getSpecularRotation();
+
+ mat_data["SpecColor"] = material_ptr->getSpecularLightColor().getValue();
+ mat_data["SpecExp"] = material_ptr->getSpecularLightExponent();
+ mat_data["EnvIntensity"] = material_ptr->getEnvironmentIntensity();
+ mat_data["AlphaMaskCutoff"] = material_ptr->getAlphaMaskCutoff();
+ mat_data["DiffuseAlphaMode"] = material_ptr->getDiffuseAlphaMode();
+
+ // Replace no-copy textures, destination texture will get used instead if available
+ if (mat_data.has("NormMap"))
+ {
+ LLUUID id = mat_data["NormMap"].asUUID();
+ if (id.notNull() && !get_can_copy_texture(id))
+ {
+ mat_data["NormMap"] = DEFAULT_OBJECT_TEXTURE;
+ mat_data["NormMapNoCopy"] = true;
+ }
+
+ }
+ if (mat_data.has("SpecMap"))
+ {
+ LLUUID id = mat_data["SpecMap"].asUUID();
+ if (id.notNull() && !get_can_copy_texture(id))
+ {
+ mat_data["SpecMap"] = DEFAULT_OBJECT_TEXTURE;
+ mat_data["SpecMapNoCopy"] = true;
+ }
+
+ }
+
+ te_data["material"] = mat_data;
+ }
+
+ mClipboardParams["texture"].append(te_data);
+ }
+ }
+ }
+}
+
+void LLPanelFace::onPasteTexture()
+{
+ if (!mClipboardParams.has("texture"))
+ {
+ return;
+ }
+
+ LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+ LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode();
+ S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
+ if (!objectp || !node
+ || objectp->getPCode() != LL_PCODE_VOLUME
+ || !objectp->permModify()
+ || objectp->isPermanentEnforced()
+ || selected_count > 1
+ || !LLMaterialEditor::canClipboardObjectsMaterial())
+ {
+ // not supposed to happen
+ LL_WARNS() << "Failed to paste texture due to missing or wrong selection" << LL_ENDL;
+ return;
+ }
+
+ bool face_selection_mode = LLToolFace::getInstance() == LLToolMgr::getInstance()->getCurrentTool();
+ LLSD &clipboard = mClipboardParams["texture"]; // array
+ S32 num_tes = llmin((S32)objectp->getNumTEs(), (S32)objectp->getNumFaces());
+ S32 compare_tes = num_tes;
+
+ if (face_selection_mode)
+ {
+ compare_tes = 0;
+ for (S32 te = 0; te < num_tes; ++te)
+ {
+ if (node->isTESelected(te))
+ {
+ compare_tes++;
+ }
+ }
+ }
+
+ // we can copy if single face was copied in edit face mode or if face count matches
+ if (!((clipboard.size() == 1) && mClipboardParams["texture_all_tes"].asBoolean())
+ && compare_tes != clipboard.size())
+ {
+ LLSD notif_args;
+ if (face_selection_mode)
+ {
+ static std::string reason = getString("paste_error_face_selection_mismatch");
+ notif_args["REASON"] = reason;
+ }
+ else
+ {
+ static std::string reason = getString("paste_error_object_face_count_mismatch");
+ notif_args["REASON"] = reason;
+ }
+ LLNotificationsUtil::add("FacePasteFailed", notif_args);
+ return;
+ }
+
+ bool full_perm_object = true;
+ LLSD::array_const_iterator iter = clipboard.beginArray();
+ LLSD::array_const_iterator end = clipboard.endArray();
+ for (; iter != end; ++iter)
+ {
+ const LLSD& te_data = *iter;
+ if (te_data.has("te") && te_data["te"].has("imageid"))
+ {
+ bool full_perm = te_data["te"].has("itemfullperm") && te_data["te"]["itemfullperm"].asBoolean();
+ full_perm_object &= full_perm;
+ if (!full_perm)
+ {
+ if (te_data["te"].has("imageitemid"))
+ {
+ LLUUID item_id = te_data["te"]["imageitemid"].asUUID();
+ if (item_id.notNull())
+ {
+ LLViewerInventoryItem* itemp = gInventory.getItem(item_id);
+ if (!itemp)
+ {
+ // image might be in object's inventory, but it can be not up to date
+ LLSD notif_args;
+ static std::string reason = getString("paste_error_inventory_not_found");
+ notif_args["REASON"] = reason;
+ LLNotificationsUtil::add("FacePasteFailed", notif_args);
+ return;
+ }
+ }
+ }
+ else
+ {
+ // Item was not found on 'copy' stage
+ // Since this happened at copy, might be better to either show this
+ // at copy stage or to drop clipboard here
+ LLSD notif_args;
+ static std::string reason = getString("paste_error_inventory_not_found");
+ notif_args["REASON"] = reason;
+ LLNotificationsUtil::add("FacePasteFailed", notif_args);
+ return;
+ }
+ }
+ }
+ }
+
+ if (!full_perm_object)
+ {
+ LLNotificationsUtil::add("FacePasteTexturePermissions");
+ }
+
+ LLObjectSelectionHandle selected_objects = LLSelectMgr::getInstance()->getSelection();
+
+ LLPanelFacePasteTexFunctor paste_func(this, PASTE_TEXTURE);
+ selected_objects->applyToTEs(&paste_func);
+
+ LLPanelFaceUpdateFunctor sendfunc(true);
+ selected_objects->applyToObjects(&sendfunc);
+
+ LLGLTFMaterialList::flushUpdates();
+
+ LLPanelFaceNavigateHomeFunctor navigate_home_func;
+ selected_objects->applyToTEs(&navigate_home_func);
+}
+
+void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te)
+{
+ LLSD te_data;
+ LLSD &clipboard = mClipboardParams["texture"]; // array
+ if ((clipboard.size() == 1) && mClipboardParams["texture_all_tes"].asBoolean())
+ {
+ te_data = *(clipboard.beginArray());
+ }
+ else if (clipboard[te])
+ {
+ te_data = clipboard[te];
+ }
+ else
+ {
+ return;
+ }
+
+ LLTextureEntry* tep = objectp->getTE(te);
+ if (tep)
+ {
+ if (te_data.has("te"))
+ {
+ // Texture
+ bool full_perm = te_data["te"].has("itemfullperm") && te_data["te"]["itemfullperm"].asBoolean();
+ bool from_library = te_data["te"].has("fromlibrary") && te_data["te"]["fromlibrary"].asBoolean();
+ if (te_data["te"].has("imageid"))
+ {
+ const LLUUID& imageid = te_data["te"]["imageid"].asUUID(); //texture or asset id
+ LLViewerInventoryItem* itemp_res = NULL;
+
+ if (te_data["te"].has("imageitemid"))
+ {
+ LLUUID item_id = te_data["te"]["imageitemid"].asUUID();
+ if (item_id.notNull())
+ {
+ LLViewerInventoryItem* itemp = gInventory.getItem(item_id);
+ if (itemp && itemp->isFinished())
+ {
+ // dropTextureAllFaces will fail if incomplete
+ itemp_res = itemp;
+ }
+ else
+ {
+ // Theoretically shouldn't happend, but if it does happen, we
+ // might need to add a notification to user that paste will fail
+ // since inventory isn't fully loaded
+ LL_WARNS() << "Item " << item_id << " is incomplete, paste might fail silently." << LL_ENDL;
+ }
+ }
+ }
+ // for case when item got removed from inventory after we pressed 'copy'
+ // or texture got pasted into previous object
+ if (!itemp_res && !full_perm)
+ {
+ // Due to checks for imageitemid in LLPanelFace::onPasteTexture() this should no longer be reachable.
+ LL_INFOS() << "Item " << te_data["te"]["imageitemid"].asUUID() << " no longer in inventory." << LL_ENDL;
+ // Todo: fix this, we are often searching same texture multiple times (equal to number of faces)
+ // Perhaps just mPanelFace->onPasteTexture(objectp, te, &asset_to_item_id_map); ? Not pretty, but will work
+ LLViewerInventoryCategory::cat_array_t cats;
+ LLViewerInventoryItem::item_array_t items;
+ LLAssetIDMatches asset_id_matches(imageid);
+ gInventory.collectDescendentsIf(LLUUID::null,
+ cats,
+ items,
+ LLInventoryModel::INCLUDE_TRASH,
+ asset_id_matches);
+
+ // Extremely unreliable and perfomance unfriendly.
+ // But we need this to check permissions and it is how texture control finds items
+ for (S32 i = 0; i < items.size(); i++)
+ {
+ LLViewerInventoryItem* itemp = items[i];
+ if (itemp && itemp->isFinished())
+ {
+ // dropTextureAllFaces will fail if incomplete
+ LLPermissions item_permissions = itemp->getPermissions();
+ if (item_permissions.allowOperationBy(PERM_COPY,
+ gAgent.getID(),
+ gAgent.getGroupID()))
+ {
+ itemp_res = itemp;
+ break; // first match
+ }
+ }
+ }
+ }
+
+ if (itemp_res)
+ {
+ if (te == -1) // all faces
+ {
+ LLToolDragAndDrop::dropTextureAllFaces(objectp,
+ itemp_res,
+ from_library ? LLToolDragAndDrop::SOURCE_LIBRARY : LLToolDragAndDrop::SOURCE_AGENT,
+ LLUUID::null,
+ false);
+ }
+ else // one face
+ {
+ LLToolDragAndDrop::dropTextureOneFace(objectp,
+ te,
+ itemp_res,
+ from_library ? LLToolDragAndDrop::SOURCE_LIBRARY : LLToolDragAndDrop::SOURCE_AGENT,
+ LLUUID::null,
+ false,
+ 0);
+ }
+ }
+ // not an inventory item or no complete items
+ else if (full_perm)
+ {
+ // Either library, local or existed as fullperm when user made a copy
+ LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(imageid, FTT_DEFAULT, true, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+ objectp->setTEImage(U8(te), image);
+ }
+ }
+
+ if (te_data["te"].has("bumpmap"))
+ {
+ objectp->setTEBumpmap(te, (U8)te_data["te"]["bumpmap"].asInteger());
+ }
+ if (te_data["te"].has("bumpshiny"))
+ {
+ objectp->setTEBumpShiny(te, (U8)te_data["te"]["bumpshiny"].asInteger());
+ }
+ if (te_data["te"].has("bumpfullbright"))
+ {
+ objectp->setTEBumpShinyFullbright(te, (U8)te_data["te"]["bumpfullbright"].asInteger());
+ }
+ if (te_data["te"].has("texgen"))
+ {
+ objectp->setTETexGen(te, (U8)te_data["te"]["texgen"].asInteger());
+ }
+
+ // PBR/GLTF
+ if (te_data["te"].has("pbr"))
+ {
+ objectp->setRenderMaterialID(te, te_data["te"]["pbr"].asUUID(), false /*managing our own update*/);
+ tep->setGLTFRenderMaterial(nullptr);
+ tep->setGLTFMaterialOverride(nullptr);
+
+ LLSD override_data;
+ override_data["object_id"] = objectp->getID();
+ override_data["side"] = te;
+ if (te_data["te"].has("pbr_override"))
+ {
+ override_data["gltf_json"] = te_data["te"]["pbr_override"];
+ }
+ else
+ {
+ override_data["gltf_json"] = "";
+ }
+
+ override_data["asset_id"] = te_data["te"]["pbr"].asUUID();
+
+ LLGLTFMaterialList::queueUpdate(override_data);
+ }
+ else
+ {
+ objectp->setRenderMaterialID(te, LLUUID::null, false /*send in bulk later*/ );
+ tep->setGLTFRenderMaterial(nullptr);
+ tep->setGLTFMaterialOverride(nullptr);
+
+ // blank out most override data on the server
+ LLGLTFMaterialList::queueApply(objectp, te, LLUUID::null);
+ }
+
+ // Texture map
+ if (te_data["te"].has("scales") && te_data["te"].has("scalet"))
+ {
+ objectp->setTEScale(te, (F32)te_data["te"]["scales"].asReal(), (F32)te_data["te"]["scalet"].asReal());
+ }
+ if (te_data["te"].has("offsets") && te_data["te"].has("offsett"))
+ {
+ objectp->setTEOffset(te, (F32)te_data["te"]["offsets"].asReal(), (F32)te_data["te"]["offsett"].asReal());
+ }
+ if (te_data["te"].has("imagerot"))
+ {
+ objectp->setTERotation(te, (F32)te_data["te"]["imagerot"].asReal());
+ }
+
+ // Media
+ if (te_data["te"].has("media_flags"))
+ {
+ U8 media_flags = te_data["te"]["media_flags"].asInteger();
+ objectp->setTEMediaFlags(te, media_flags);
+ LLVOVolume *vo = dynamic_cast<LLVOVolume*>(objectp);
+ if (vo && te_data["te"].has(LLTextureEntry::TEXTURE_MEDIA_DATA_KEY))
+ {
+ vo->syncMediaData(te, te_data["te"][LLTextureEntry::TEXTURE_MEDIA_DATA_KEY], true/*merge*/, true/*ignore_agent*/);
+ }
+ }
+ else
+ {
+ // Keep media flags on destination unchanged
+ }
+ }
+
+ if (te_data.has("material"))
+ {
+ LLUUID object_id = objectp->getID();
+
+ // Normal
+ // Replace placeholders with target's
+ if (te_data["material"].has("NormMapNoCopy"))
+ {
+ LLMaterialPtr material = tep->getMaterialParams();
+ if (material.notNull())
+ {
+ LLUUID id = material->getNormalID();
+ if (id.notNull())
+ {
+ te_data["material"]["NormMap"] = id;
+ }
+ }
+ }
+ LLSelectedTEMaterial::setNormalID(this, te_data["material"]["NormMap"].asUUID(), te, object_id);
+ LLSelectedTEMaterial::setNormalRepeatX(this, (F32)te_data["material"]["NormRepX"].asReal(), te, object_id);
+ LLSelectedTEMaterial::setNormalRepeatY(this, (F32)te_data["material"]["NormRepY"].asReal(), te, object_id);
+ LLSelectedTEMaterial::setNormalOffsetX(this, (F32)te_data["material"]["NormOffX"].asReal(), te, object_id);
+ LLSelectedTEMaterial::setNormalOffsetY(this, (F32)te_data["material"]["NormOffY"].asReal(), te, object_id);
+ LLSelectedTEMaterial::setNormalRotation(this, (F32)te_data["material"]["NormRot"].asReal(), te, object_id);
+
+ // Specular
+ // Replace placeholders with target's
+ if (te_data["material"].has("SpecMapNoCopy"))
+ {
+ LLMaterialPtr material = tep->getMaterialParams();
+ if (material.notNull())
+ {
+ LLUUID id = material->getSpecularID();
+ if (id.notNull())
+ {
+ te_data["material"]["SpecMap"] = id;
+ }
+ }
+ }
+ LLSelectedTEMaterial::setSpecularID(this, te_data["material"]["SpecMap"].asUUID(), te, object_id);
+ LLSelectedTEMaterial::setSpecularRepeatX(this, (F32)te_data["material"]["SpecRepX"].asReal(), te, object_id);
+ LLSelectedTEMaterial::setSpecularRepeatY(this, (F32)te_data["material"]["SpecRepY"].asReal(), te, object_id);
+ LLSelectedTEMaterial::setSpecularOffsetX(this, (F32)te_data["material"]["SpecOffX"].asReal(), te, object_id);
+ LLSelectedTEMaterial::setSpecularOffsetY(this, (F32)te_data["material"]["SpecOffY"].asReal(), te, object_id);
+ LLSelectedTEMaterial::setSpecularRotation(this, (F32)te_data["material"]["SpecRot"].asReal(), te, object_id);
+ LLColor4U spec_color(te_data["material"]["SpecColor"]);
+ LLSelectedTEMaterial::setSpecularLightColor(this, spec_color, te);
+ LLSelectedTEMaterial::setSpecularLightExponent(this, (U8)te_data["material"]["SpecExp"].asInteger(), te, object_id);
+ LLSelectedTEMaterial::setEnvironmentIntensity(this, (U8)te_data["material"]["EnvIntensity"].asInteger(), te, object_id);
+ LLSelectedTEMaterial::setDiffuseAlphaMode(this, (U8)te_data["material"]["DiffuseAlphaMode"].asInteger(), te, object_id);
+ LLSelectedTEMaterial::setAlphaMaskCutoff(this, (U8)te_data["material"]["AlphaMaskCutoff"].asInteger(), te, object_id);
+ if (te_data.has("te") && te_data["te"].has("shiny"))
+ {
+ objectp->setTEShiny(te, (U8)te_data["te"]["shiny"].asInteger());
+ }
+ }
+ }
+}
+
+void LLPanelFace::menuDoToSelected(const LLSD& userdata)
+{
+ std::string command = userdata.asString();
+
+ // paste
+ if (command == "color_paste")
+ {
+ onPasteColor();
+ }
+ else if (command == "texture_paste")
+ {
+ onPasteTexture();
+ }
+ // copy
+ else if (command == "color_copy")
+ {
+ onCopyColor();
+ }
+ else if (command == "texture_copy")
+ {
+ onCopyTexture();
+ }
+}
+
+bool LLPanelFace::menuEnableItem(const LLSD& userdata)
+{
+ std::string command = userdata.asString();
+
+ // paste options
+ if (command == "color_paste")
+ {
+ return mClipboardParams.has("color");
+ }
+ else if (command == "texture_paste")
+ {
+ return mClipboardParams.has("texture");
+ }
+ return false;
+}
+
+
+// static
+void LLPanelFace::onCommitPlanarAlign(LLUICtrl* ctrl, void* userdata)
+{
+ LLPanelFace* self = (LLPanelFace*) userdata;
+ self->getState();
+ self->sendTextureInfo();
+}
+
+void LLPanelFace::updateGLTFTextureTransform(float value, U32 pbr_type, std::function<void(LLGLTFMaterial::TextureTransform*)> edit)
+{
+ U32 texture_info_start;
+ U32 texture_info_end;
+ const LLGLTFMaterial::TextureInfo texture_info = texture_info_from_pbrtype(pbr_type);
+ if (texture_info == LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT)
+ {
+ texture_info_start = 0;
+ texture_info_end = LLGLTFMaterial::GLTF_TEXTURE_INFO_COUNT;
+ }
+ else
+ {
+ texture_info_start = texture_info_from_pbrtype(pbr_type);
+ texture_info_end = texture_info_start + 1;
+ }
+ updateSelectedGLTFMaterials([&](LLGLTFMaterial* new_override)
+ {
+ for (U32 ti = texture_info_start; ti < texture_info_end; ++ti)
+ {
+ LLGLTFMaterial::TextureTransform& new_transform = new_override->mTextureTransform[(LLGLTFMaterial::TextureInfo)ti];
+ edit(&new_transform);
+ }
+ });
+}
+
+void LLPanelFace::setMaterialOverridesFromSelection()
+{
+ const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
+ const LLGLTFMaterial::TextureInfo texture_info = texture_info_from_pbrtype(pbr_type);
+ U32 texture_info_start;
+ U32 texture_info_end;
+ if (texture_info == LLGLTFMaterial::TextureInfo::GLTF_TEXTURE_INFO_COUNT)
+ {
+ texture_info_start = 0;
+ texture_info_end = LLGLTFMaterial::TextureInfo::GLTF_TEXTURE_INFO_COUNT;
+ }
+ else
+ {
+ texture_info_start = texture_info;
+ texture_info_end = texture_info + 1;
+ }
+
+ bool read_transform = true;
+ LLGLTFMaterial::TextureTransform transform;
+ bool scale_u_same = true;
+ bool scale_v_same = true;
+ bool rotation_same = true;
+ bool offset_u_same = true;
+ bool offset_v_same = true;
+
+ for (U32 i = texture_info_start; i < texture_info_end; ++i)
+ {
+ LLGLTFMaterial::TextureTransform this_transform;
+ bool this_scale_u_same = true;
+ bool this_scale_v_same = true;
+ bool this_rotation_same = true;
+ bool this_offset_u_same = true;
+ bool this_offset_v_same = true;
+
+ readSelectedGLTFMaterial<float>([&](const LLGLTFMaterial* mat)
+ {
+ return mat ? mat->mTextureTransform[i].mScale[VX] : 0.f;
+ }, this_transform.mScale[VX], this_scale_u_same, true, 1e-3f);
+ readSelectedGLTFMaterial<float>([&](const LLGLTFMaterial* mat)
+ {
+ return mat ? mat->mTextureTransform[i].mScale[VY] : 0.f;
+ }, this_transform.mScale[VY], this_scale_v_same, true, 1e-3f);
+ readSelectedGLTFMaterial<float>([&](const LLGLTFMaterial* mat)
+ {
+ return mat ? mat->mTextureTransform[i].mRotation : 0.f;
+ }, this_transform.mRotation, this_rotation_same, true, 1e-3f);
+ readSelectedGLTFMaterial<float>([&](const LLGLTFMaterial* mat)
+ {
+ return mat ? mat->mTextureTransform[i].mOffset[VX] : 0.f;
+ }, this_transform.mOffset[VX], this_offset_u_same, true, 1e-3f);
+ readSelectedGLTFMaterial<float>([&](const LLGLTFMaterial* mat)
+ {
+ return mat ? mat->mTextureTransform[i].mOffset[VY] : 0.f;
+ }, this_transform.mOffset[VY], this_offset_v_same, true, 1e-3f);
+
+ scale_u_same = scale_u_same && this_scale_u_same;
+ scale_v_same = scale_v_same && this_scale_v_same;
+ rotation_same = rotation_same && this_rotation_same;
+ offset_u_same = offset_u_same && this_offset_u_same;
+ offset_v_same = offset_v_same && this_offset_v_same;
+
+ if (read_transform)
+ {
+ read_transform = false;
+ transform = this_transform;
+ }
+ else
+ {
+ scale_u_same = scale_u_same && (this_transform.mScale[VX] == transform.mScale[VX]);
+ scale_v_same = scale_v_same && (this_transform.mScale[VY] == transform.mScale[VY]);
+ rotation_same = rotation_same && (this_transform.mRotation == transform.mRotation);
+ offset_u_same = offset_u_same && (this_transform.mOffset[VX] == transform.mOffset[VX]);
+ offset_v_same = offset_v_same && (this_transform.mOffset[VY] == transform.mOffset[VY]);
+ }
+ }
+
+ LLUICtrl* gltfCtrlTextureScaleU = getChild<LLUICtrl>("gltfTextureScaleU");
+ LLUICtrl* gltfCtrlTextureScaleV = getChild<LLUICtrl>("gltfTextureScaleV");
+ LLUICtrl* gltfCtrlTextureRotation = getChild<LLUICtrl>("gltfTextureRotation");
+ LLUICtrl* gltfCtrlTextureOffsetU = getChild<LLUICtrl>("gltfTextureOffsetU");
+ LLUICtrl* gltfCtrlTextureOffsetV = getChild<LLUICtrl>("gltfTextureOffsetV");
+
+ gltfCtrlTextureScaleU->setValue(transform.mScale[VX]);
+ gltfCtrlTextureScaleV->setValue(transform.mScale[VY]);
+ gltfCtrlTextureRotation->setValue(transform.mRotation * RAD_TO_DEG);
+ gltfCtrlTextureOffsetU->setValue(transform.mOffset[VX]);
+ gltfCtrlTextureOffsetV->setValue(transform.mOffset[VY]);
+
+ gltfCtrlTextureScaleU->setTentative(!scale_u_same);
+ gltfCtrlTextureScaleV->setTentative(!scale_v_same);
+ gltfCtrlTextureRotation->setTentative(!rotation_same);
+ gltfCtrlTextureOffsetU->setTentative(!offset_u_same);
+ gltfCtrlTextureOffsetV->setTentative(!offset_v_same);
+}
+
+void LLPanelFace::Selection::connect()
+{
+ if (!mSelectConnection.connected())
+ {
+ mSelectConnection = LLSelectMgr::instance().mUpdateSignal.connect(boost::bind(&LLPanelFace::Selection::onSelectionChanged, this));
+ }
+}
+
+bool LLPanelFace::Selection::update()
+{
+ const bool changed = mChanged || compareSelection();
+ mChanged = false;
+ return changed;
+}
+
+void LLPanelFace::Selection::onSelectedObjectUpdated(const LLUUID& object_id, S32 side)
+{
+ if (object_id == mSelectedObjectID)
+ {
+ if (side == mLastSelectedSide)
+ {
+ mChanged = true;
+ }
+ else if (mLastSelectedSide == -1) // if last selected face was deselected
+ {
+ LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode();
+ if (node && node->isTESelected(side))
+ {
+ mChanged = true;
+ }
+ }
+ }
+}
+
+bool LLPanelFace::Selection::compareSelection()
+{
+ if (!mNeedsSelectionCheck)
+ {
+ return false;
+ }
+ mNeedsSelectionCheck = false;
+
+ const S32 old_object_count = mSelectedObjectCount;
+ const S32 old_te_count = mSelectedTECount;
+ const LLUUID old_object_id = mSelectedObjectID;
+ const S32 old_side = mLastSelectedSide;
+
+ LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+ LLSelectNode* node = selection->getFirstNode();
+ if (node)
+ {
+ LLViewerObject* object = node->getObject();
+ mSelectedObjectCount = selection->getObjectCount();
+ mSelectedTECount = selection->getTECount();
+ mSelectedObjectID = object->getID();
+ mLastSelectedSide = node->getLastSelectedTE();
+ }
+ else
+ {
+ mSelectedObjectCount = 0;
+ mSelectedTECount = 0;
+ mSelectedObjectID = LLUUID::null;
+ mLastSelectedSide = -1;
+ }
+
+ const bool selection_changed =
+ old_object_count != mSelectedObjectCount
+ || old_te_count != mSelectedTECount
+ || old_object_id != mSelectedObjectID
+ || old_side != mLastSelectedSide;
+ mChanged = mChanged || selection_changed;
+ return selection_changed;
+}
+
+void LLPanelFace::onCommitGLTFTextureScaleU(LLUICtrl* ctrl)
+{
+ const float value = ctrl->getValue().asReal();
+ const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
+ updateGLTFTextureTransform(value, pbr_type, [&](LLGLTFMaterial::TextureTransform* new_transform)
+ {
+ new_transform->mScale.mV[VX] = value;
+ });
+}
+
+void LLPanelFace::onCommitGLTFTextureScaleV(LLUICtrl* ctrl)
+{
+ const float value = ctrl->getValue().asReal();
+ const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
+ updateGLTFTextureTransform(value, pbr_type, [&](LLGLTFMaterial::TextureTransform* new_transform)
+ {
+ new_transform->mScale.mV[VY] = value;
+ });
+}
+
+void LLPanelFace::onCommitGLTFRotation(LLUICtrl* ctrl)
+{
+ const float value = ctrl->getValue().asReal() * DEG_TO_RAD;
+ const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
+ updateGLTFTextureTransform(value, pbr_type, [&](LLGLTFMaterial::TextureTransform* new_transform)
+ {
+ new_transform->mRotation = value;
+ });
+}
+
+void LLPanelFace::onCommitGLTFTextureOffsetU(LLUICtrl* ctrl)
+{
+ const float value = ctrl->getValue().asReal();
+ const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
+ updateGLTFTextureTransform(value, pbr_type, [&](LLGLTFMaterial::TextureTransform* new_transform)
+ {
+ new_transform->mOffset.mV[VX] = value;
+ });
+}
+
+void LLPanelFace::onCommitGLTFTextureOffsetV(LLUICtrl* ctrl)
+{
+ const float value = ctrl->getValue().asReal();
+ const U32 pbr_type = findChild<LLRadioGroup>("radio_pbr_type")->getSelectedIndex();
+ updateGLTFTextureTransform(value, pbr_type, [&](LLGLTFMaterial::TextureTransform* new_transform)
+ {
+ new_transform->mOffset.mV[VY] = value;
+ });
+}
+
+void LLPanelFace::onTextureSelectionChanged(LLInventoryItem* itemp)
+{
+ LL_DEBUGS("Materials") << "item asset " << itemp->getAssetUUID() << LL_ENDL;
+ LLRadioGroup* radio_mat_type = findChild<LLRadioGroup>("radio_material_type");
+ if(!radio_mat_type)
+ {
+ return;
+ }
+ U32 mattype = radio_mat_type->getSelectedIndex();
+ std::string which_control="texture control";
+ switch (mattype)
+ {
+ case MATTYPE_SPECULAR:
+ which_control = "shinytexture control";
+ break;
+ case MATTYPE_NORMAL:
+ which_control = "bumpytexture control";
+ break;
+ // no default needed
+ }
+ LL_DEBUGS("Materials") << "control " << which_control << LL_ENDL;
+ LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>(which_control);
+ if (texture_ctrl)
+ {
+ LLUUID obj_owner_id;
+ std::string obj_owner_name;
+ LLSelectMgr::instance().selectGetOwner(obj_owner_id, obj_owner_name);
+
+ LLSaleInfo sale_info;
+ LLSelectMgr::instance().selectGetSaleInfo(sale_info);
+
+ bool can_copy = itemp->getPermissions().allowCopyBy(gAgentID); // do we have perm to copy this texture?
+ bool can_transfer = itemp->getPermissions().allowOperationBy(PERM_TRANSFER, gAgentID); // do we have perm to transfer this texture?
+ bool is_object_owner = gAgentID == obj_owner_id; // does object for which we are going to apply texture belong to the agent?
+ bool not_for_sale = !sale_info.isForSale(); // is object for which we are going to apply texture not for sale?
+
+ if (can_copy && can_transfer)
+ {
+ texture_ctrl->setCanApply(true, true);
+ return;
+ }
+
+ // if texture has (no-transfer) attribute it can be applied only for object which we own and is not for sale
+ texture_ctrl->setCanApply(false, can_transfer ? true : is_object_owner && not_for_sale);
+
+ if (gSavedSettings.getBOOL("TextureLivePreview"))
+ {
+ LLNotificationsUtil::add("LivePreviewUnavailable");
+ }
+ }
+}
+
+void LLPanelFace::onPbrSelectionChanged(LLInventoryItem* itemp)
+{
+ LLTextureCtrl* pbr_ctrl = findChild<LLTextureCtrl>("pbr_control");
+ if (pbr_ctrl)
+ {
+ LLUUID obj_owner_id;
+ std::string obj_owner_name;
+ LLSelectMgr::instance().selectGetOwner(obj_owner_id, obj_owner_name);
+
+ LLSaleInfo sale_info;
+ LLSelectMgr::instance().selectGetSaleInfo(sale_info);
+
+ bool can_copy = itemp->getPermissions().allowCopyBy(gAgentID); // do we have perm to copy this material?
+ bool can_transfer = itemp->getPermissions().allowOperationBy(PERM_TRANSFER, gAgentID); // do we have perm to transfer this material?
+ bool can_modify = itemp->getPermissions().allowOperationBy(PERM_MODIFY, gAgentID); // do we have perm to transfer this material?
+ bool is_object_owner = gAgentID == obj_owner_id; // does object for which we are going to apply material belong to the agent?
+ bool not_for_sale = !sale_info.isForSale(); // is object for which we are going to apply material not for sale?
+ bool from_library = ALEXANDRIA_LINDEN_ID == itemp->getPermissions().getOwner();
+
+ if ((can_copy && can_transfer && can_modify) || from_library)
+ {
+ pbr_ctrl->setCanApply(true, true);
+ return;
+ }
+
+ // if material has (no-transfer) attribute it can be applied only for object which we own and is not for sale
+ pbr_ctrl->setCanApply(false, can_transfer ? true : is_object_owner && not_for_sale);
+
+ if (gSavedSettings.getBOOL("TextureLivePreview"))
+ {
+ LLNotificationsUtil::add("LivePreviewUnavailablePBR");
+ }
+ }
+}
+
+bool LLPanelFace::isIdenticalPlanarTexgen()
+{
+ LLTextureEntry::e_texgen selected_texgen = LLTextureEntry::TEX_GEN_DEFAULT;
+ bool identical_texgen = false;
+ LLSelectedTE::getTexGen(selected_texgen, identical_texgen);
+ return (identical_texgen && (selected_texgen == LLTextureEntry::TEX_GEN_PLANAR));
+}
+
+void LLPanelFace::LLSelectedTE::getFace(LLFace*& face_to_return, bool& identical_face)
+{
+ struct LLSelectedTEGetFace : public LLSelectedTEGetFunctor<LLFace *>
+ {
+ LLFace* get(LLViewerObject* object, S32 te)
+ {
+ return (object->mDrawable) ? object->mDrawable->getFace(te): NULL;
+ }
+ } get_te_face_func;
+ identical_face = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&get_te_face_func, face_to_return, false, (LLFace*)nullptr);
+}
+
+void LLPanelFace::LLSelectedTE::getImageFormat(LLGLenum& image_format_to_return, bool& identical_face)
+{
+ LLGLenum image_format;
+ struct LLSelectedTEGetImageFormat : public LLSelectedTEGetFunctor<LLGLenum>
+ {
+ LLGLenum get(LLViewerObject* object, S32 te_index)
+ {
+ LLViewerTexture* image = object->getTEImage(te_index);
+ return image ? image->getPrimaryFormat() : GL_RGB;
+ }
+ } get_glenum;
+ identical_face = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&get_glenum, image_format);
+ image_format_to_return = image_format;
+}
+
+void LLPanelFace::LLSelectedTE::getTexId(LLUUID& id, bool& identical)
+{
+ struct LLSelectedTEGetTexId : public LLSelectedTEGetFunctor<LLUUID>
+ {
+ LLUUID get(LLViewerObject* object, S32 te_index)
+ {
+ LLTextureEntry *te = object->getTE(te_index);
+ if (te)
+ {
+ if ((te->getID() == IMG_USE_BAKED_EYES) || (te->getID() == IMG_USE_BAKED_HAIR) || (te->getID() == IMG_USE_BAKED_HEAD) || (te->getID() == IMG_USE_BAKED_LOWER) || (te->getID() == IMG_USE_BAKED_SKIRT) || (te->getID() == IMG_USE_BAKED_UPPER)
+ || (te->getID() == IMG_USE_BAKED_LEFTARM) || (te->getID() == IMG_USE_BAKED_LEFTLEG) || (te->getID() == IMG_USE_BAKED_AUX1) || (te->getID() == IMG_USE_BAKED_AUX2) || (te->getID() == IMG_USE_BAKED_AUX3))
+ {
+ return te->getID();
+ }
+ }
+
+ LLUUID id;
+ LLViewerTexture* image = object->getTEImage(te_index);
+ if (image)
+ {
+ id = image->getID();
+ }
+
+ if (!id.isNull() && LLViewerMedia::getInstance()->textureHasMedia(id))
+ {
+ if (te)
+ {
+ LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID(), TEX_LIST_STANDARD) : NULL;
+ if(!tex)
+ {
+ tex = LLViewerFetchedTexture::sDefaultImagep;
+ }
+ if (tex)
+ {
+ id = tex->getID();
+ }
+ }
+ }
+ return id;
+ }
+ } func;
+ identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, id );
+}
+
+void LLPanelFace::LLSelectedTE::getPbrMaterialId(LLUUID& id, bool& identical, bool& has_faces_with_pbr, bool& has_faces_without_pbr)
+{
+ struct LLSelectedTEGetmatId : public LLSelectedTEFunctor
+ {
+ LLSelectedTEGetmatId()
+ : mHasFacesWithoutPBR(false)
+ , mHasFacesWithPBR(false)
+ , mIdenticalId(true)
+ , mIdenticalOverride(true)
+ , mInitialized(false)
+ , mMaterialOverride(LLGLTFMaterial::sDefault)
+ {
+ }
+ bool apply(LLViewerObject* object, S32 te_index) override
+ {
+ LLUUID pbr_id = object->getRenderMaterialID(te_index);
+ if (pbr_id.isNull())
+ {
+ mHasFacesWithoutPBR = true;
+ }
+ else
+ {
+ mHasFacesWithPBR = true;
+ }
+ if (mInitialized)
+ {
+ if (mPBRId != pbr_id)
+ {
+ mIdenticalId = false;
+ }
+
+ LLGLTFMaterial* te_override = object->getTE(te_index)->getGLTFMaterialOverride();
+ if (te_override)
+ {
+ LLGLTFMaterial override = *te_override;
+ override.sanitizeAssetMaterial();
+ mIdenticalOverride &= (override == mMaterialOverride);
+ }
+ else
+ {
+ mIdenticalOverride &= (mMaterialOverride == LLGLTFMaterial::sDefault);
+ }
+ }
+ else
+ {
+ mInitialized = true;
+ mPBRId = pbr_id;
+ LLGLTFMaterial* override = object->getTE(te_index)->getGLTFMaterialOverride();
+ if (override)
+ {
+ mMaterialOverride = *override;
+ mMaterialOverride.sanitizeAssetMaterial();
+ }
+ }
+ return true;
+ }
+ bool mHasFacesWithoutPBR;
+ bool mHasFacesWithPBR;
+ bool mIdenticalId;
+ bool mIdenticalOverride;
+ bool mInitialized;
+ LLGLTFMaterial mMaterialOverride;
+ LLUUID mPBRId;
+ } func;
+ LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func);
+ id = func.mPBRId;
+ identical = func.mIdenticalId && func.mIdenticalOverride;
+ has_faces_with_pbr = func.mHasFacesWithPBR;
+ has_faces_without_pbr = func.mHasFacesWithoutPBR;
+}
+
+void LLPanelFace::LLSelectedTEMaterial::getCurrent(LLMaterialPtr& material_ptr, bool& identical_material)
+{
+ struct MaterialFunctor : public LLSelectedTEGetFunctor<LLMaterialPtr>
+ {
+ LLMaterialPtr get(LLViewerObject* object, S32 te_index)
+ {
+ return object->getTE(te_index)->getMaterialParams();
+ }
+ } func;
+ identical_material = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, material_ptr);
+}
+
+void LLPanelFace::LLSelectedTEMaterial::getMaxSpecularRepeats(F32& repeats, bool& identical)
+{
+ struct LLSelectedTEGetMaxSpecRepeats : public LLSelectedTEGetFunctor<F32>
+ {
+ F32 get(LLViewerObject* object, S32 face)
+ {
+ LLMaterial* mat = object->getTE(face)->getMaterialParams().get();
+ U32 s_axis = VX;
+ U32 t_axis = VY;
+ F32 repeats_s = 1.0f;
+ F32 repeats_t = 1.0f;
+ if (mat)
+ {
+ mat->getSpecularRepeat(repeats_s, repeats_t);
+ repeats_s /= object->getScale().mV[s_axis];
+ repeats_t /= object->getScale().mV[t_axis];
+ }
+ return llmax(repeats_s, repeats_t);
+ }
+
+ } max_spec_repeats_func;
+ identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_spec_repeats_func, repeats);
+}
+
+void LLPanelFace::LLSelectedTEMaterial::getMaxNormalRepeats(F32& repeats, bool& identical)
+{
+ struct LLSelectedTEGetMaxNormRepeats : public LLSelectedTEGetFunctor<F32>
+ {
+ F32 get(LLViewerObject* object, S32 face)
+ {
+ LLMaterial* mat = object->getTE(face)->getMaterialParams().get();
+ U32 s_axis = VX;
+ U32 t_axis = VY;
+ F32 repeats_s = 1.0f;
+ F32 repeats_t = 1.0f;
+ if (mat)
+ {
+ mat->getNormalRepeat(repeats_s, repeats_t);
+ repeats_s /= object->getScale().mV[s_axis];
+ repeats_t /= object->getScale().mV[t_axis];
+ }
+ return llmax(repeats_s, repeats_t);
+ }
+
+ } max_norm_repeats_func;
+ identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_norm_repeats_func, repeats);
+}
+
+void LLPanelFace::LLSelectedTEMaterial::getCurrentDiffuseAlphaMode(U8& diffuse_alpha_mode, bool& identical, bool diffuse_texture_has_alpha)
+{
+ struct LLSelectedTEGetDiffuseAlphaMode : public LLSelectedTEGetFunctor<U8>
+ {
+ LLSelectedTEGetDiffuseAlphaMode() : _isAlpha(false) {}
+ LLSelectedTEGetDiffuseAlphaMode(bool diffuse_texture_has_alpha) : _isAlpha(diffuse_texture_has_alpha) {}
+ virtual ~LLSelectedTEGetDiffuseAlphaMode() {}
+
+ U8 get(LLViewerObject* object, S32 face)
+ {
+ U8 diffuse_mode = _isAlpha ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : LLMaterial::DIFFUSE_ALPHA_MODE_NONE;
+
+ LLTextureEntry* tep = object->getTE(face);
+ if (tep)
+ {
+ LLMaterial* mat = tep->getMaterialParams().get();
+ if (mat)
+ {
+ diffuse_mode = mat->getDiffuseAlphaMode();
+ }
+ }
+
+ return diffuse_mode;
+ }
+ bool _isAlpha; // whether or not the diffuse texture selected contains alpha information
+ } get_diff_mode(diffuse_texture_has_alpha);
+ identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &get_diff_mode, diffuse_alpha_mode);
+}
+
+void LLPanelFace::LLSelectedTE::getObjectScaleS(F32& scale_s, bool& identical)
+{
+ struct LLSelectedTEGetObjectScaleS : public LLSelectedTEGetFunctor<F32>
+ {
+ F32 get(LLViewerObject* object, S32 face)
+ {
+ U32 s_axis = VX;
+ U32 t_axis = VY;
+ LLPrimitive::getTESTAxes(face, &s_axis, &t_axis);
+ return object->getScale().mV[s_axis];
+ }
+
+ } scale_s_func;
+ identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &scale_s_func, scale_s );
+}
+
+void LLPanelFace::LLSelectedTE::getObjectScaleT(F32& scale_t, bool& identical)
+{
+ struct LLSelectedTEGetObjectScaleS : public LLSelectedTEGetFunctor<F32>
+ {
+ F32 get(LLViewerObject* object, S32 face)
+ {
+ U32 s_axis = VX;
+ U32 t_axis = VY;
+ LLPrimitive::getTESTAxes(face, &s_axis, &t_axis);
+ return object->getScale().mV[t_axis];
+ }
+
+ } scale_t_func;
+ identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &scale_t_func, scale_t );
+}
+
+void LLPanelFace::LLSelectedTE::getMaxDiffuseRepeats(F32& repeats, bool& identical)
+{
+ struct LLSelectedTEGetMaxDiffuseRepeats : public LLSelectedTEGetFunctor<F32>
+ {
+ F32 get(LLViewerObject* object, S32 face)
+ {
+ U32 s_axis = VX;
+ U32 t_axis = VY;
+ LLPrimitive::getTESTAxes(face, &s_axis, &t_axis);
+ F32 repeats_s = object->getTE(face)->mScaleS / object->getScale().mV[s_axis];
+ F32 repeats_t = object->getTE(face)->mScaleT / object->getScale().mV[t_axis];
+ return llmax(repeats_s, repeats_t);
+ }
+
+ } max_diff_repeats_func;
+ identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &max_diff_repeats_func, repeats );
+}
+