From a5261a5fa8fad810ecb5c260d92c3e771822bf58 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Tue, 20 Feb 2024 23:46:23 +0100 Subject: Convert BOOL to bool in llui --- indra/newview/llpanelface.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/newview/llpanelface.cpp') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 5f8071d3eb..ea1ac602a8 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -252,7 +252,7 @@ F32 LLPanelFace::getCurrentShinyOffsetV() { return getChild("shinyOf // Methods // -BOOL LLPanelFace::postBuild() +bool LLPanelFace::postBuild() { childSetCommitCallback("combobox shininess",&LLPanelFace::onCommitShiny,this); childSetCommitCallback("combobox bumpiness",&LLPanelFace::onCommitBump,this); @@ -311,7 +311,7 @@ BOOL LLPanelFace::postBuild() LLSpinCtrl* mCtrlGlow; - setMouseOpaque(FALSE); + setMouseOpaque(false); LLTextureCtrl* pbr_ctrl = findChild("pbr_control"); if (pbr_ctrl) @@ -471,7 +471,7 @@ BOOL LLPanelFace::postBuild() clearCtrls(); - return TRUE; + return true; } LLPanelFace::LLPanelFace() @@ -492,7 +492,7 @@ LLPanelFace::~LLPanelFace() unloadMedia(); } -void LLPanelFace::onVisibilityChange(BOOL new_visibility) +void LLPanelFace::onVisibilityChange(bool new_visibility) { if (new_visibility) { -- cgit v1.2.3 From 60d3dd98a44230c21803c1606552ee098ed9fa7c Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 21 Feb 2024 21:05:14 +0100 Subject: Convert remaining BOOL to bool --- indra/newview/llpanelface.cpp | 130 +++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 65 deletions(-) (limited to 'indra/newview/llpanelface.cpp') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index ea1ac602a8..030534858f 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -393,7 +393,7 @@ bool LLPanelFace::postBuild() mColorSwatch->setOnSelectCallback(boost::bind(&LLPanelFace::onSelectColor, this, _2)); mColorSwatch->setFollowsTop(); mColorSwatch->setFollowsLeft(); - mColorSwatch->setCanApplyImmediately(TRUE); + mColorSwatch->setCanApplyImmediately(true); } mShinyColorSwatch = getChild("shinycolorswatch"); @@ -404,7 +404,7 @@ bool LLPanelFace::postBuild() mShinyColorSwatch->setOnSelectCallback(boost::bind(&LLPanelFace::onSelectShinyColor, this, _2)); mShinyColorSwatch->setFollowsTop(); mShinyColorSwatch->setFollowsLeft(); - mShinyColorSwatch->setCanApplyImmediately(TRUE); + mShinyColorSwatch->setCanApplyImmediately(true); } mLabelColorTransp = getChild("color trans"); @@ -644,7 +644,7 @@ struct LLPanelFaceSetTEFunctor : public LLSelectedTEFunctor LLPanelFaceSetTEFunctor(LLPanelFace* panel) : mPanel(panel) {} virtual bool apply(LLViewerObject* object, S32 te) { - BOOL valid; + bool valid; F32 value; std::string prefix; @@ -1010,8 +1010,8 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) && objectp->getPCode() == LL_PCODE_VOLUME && objectp->permModify()) { - BOOL editable = objectp->permModify() && !objectp->isPermanentEnforced(); - BOOL attachment = objectp->isAttachment(); + bool editable = objectp->permModify() && !objectp->isPermanentEnforced(); + bool attachment = objectp->isAttachment(); bool has_pbr_material; bool has_faces_without_pbr; @@ -1226,18 +1226,18 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) // Texture { - mIsAlpha = FALSE; + mIsAlpha = false; LLGLenum image_format = GL_RGB; bool identical_image_format = false; LLSelectedTE::getImageFormat(image_format, identical_image_format); - mIsAlpha = FALSE; + mIsAlpha = false; switch (image_format) { case GL_RGBA: case GL_ALPHA: { - mIsAlpha = TRUE; + mIsAlpha = true; } break; @@ -1289,7 +1289,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) { if (identical_diffuse) { - texture_ctrl->setTentative(FALSE); + 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); @@ -1297,25 +1297,25 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) getChildView("maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material); getChildView("label maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material); - texture_ctrl->setBakeTextureEnabled(TRUE); + texture_ctrl->setBakeTextureEnabled(true); } else if (id.isNull()) { // None selected - texture_ctrl->setTentative(FALSE); - texture_ctrl->setEnabled(FALSE); + 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); + 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->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); @@ -1323,7 +1323,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) getChildView("maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material); getChildView("label maskcutoff")->setEnabled(editable && mIsAlpha && !has_pbr_material); - texture_ctrl->setBakeTextureEnabled(TRUE); + texture_ctrl->setBakeTextureEnabled(true); } if (attachment) @@ -1443,9 +1443,9 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) 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); + 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("TexScaleU")->setTentative( LLSD(diff_scale_tentative)); getChild("shinyScaleU")->setTentative(LLSD(spec_scale_tentative)); @@ -1474,9 +1474,9 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) 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; + 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()); @@ -1512,9 +1512,9 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) 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); + 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("TexOffsetU")->setValue( editable ? diff_offset_s : 0.0f); getChild("bumpyOffsetU")->setValue(editable ? norm_offset_s : 0.0f); @@ -1542,9 +1542,9 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) 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); + 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("TexOffsetV")->setValue( editable ? diff_offset_t : 0.0f); getChild("bumpyOffsetV")->setValue(editable ? norm_offset_t : 0.0f); @@ -1573,9 +1573,9 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) 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); + 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; @@ -1704,7 +1704,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) break; } - BOOL repeats_tentative = !identical_repeats; + bool repeats_tentative = !identical_repeats; LLSpinCtrl* rpt_ctrl = getChild("rptctrl"); if (force_set_values) @@ -1826,7 +1826,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) } } S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); - BOOL single_volume = (selected_count == 1); + bool single_volume = (selected_count == 1); mMenuClipboardColor->setEnabled(editable && single_volume); // Set variable values for numeric expressions @@ -1849,36 +1849,36 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) if (pbr_ctrl) { pbr_ctrl->setImageAssetID(LLUUID::null); - pbr_ctrl->setEnabled(FALSE); + pbr_ctrl->setEnabled(false); } LLTextureCtrl* texture_ctrl = getChild("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); + 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("colorswatch"); if (mColorSwatch) { - mColorSwatch->setEnabled( FALSE ); + mColorSwatch->setEnabled( false ); mColorSwatch->setFallbackImage(LLUI::getUIImage("locked_image.j2c") ); - mColorSwatch->setValid(FALSE); + mColorSwatch->setValid(false); } LLRadioGroup* radio_mat_type = getChild("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); + 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(); @@ -1988,7 +1988,7 @@ void LLPanelFace::updateUIGLTF(LLViewerObject* objectp, bool& has_pbr_material, { LLSelectedTE::getPbrMaterialId(pbr_id, identical_pbr, has_pbr_material, has_faces_without_pbr); - pbr_ctrl->setTentative(identical_pbr ? FALSE : TRUE); + pbr_ctrl->setTentative(identical_pbr ? false : true); pbr_ctrl->setEnabled(settable); pbr_ctrl->setImageAssetID(pbr_id); @@ -2104,7 +2104,7 @@ void LLPanelFace::refreshMedia() && first_object->permModify() )) { - getChildView("add_media")->setEnabled(FALSE); + getChildView("add_media")->setEnabled(false); mTitleMediaText->clear(); clearMediaSettings(); return; @@ -2115,13 +2115,13 @@ void LLPanelFace::refreshMedia() if (!has_media_capability) { - getChildView("add_media")->setEnabled(FALSE); + 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() + bool is_nonpermanent_enforced = (LLSelectMgr::getInstance()->getSelection()->getFirstRootNode() && LLSelectMgr::getInstance()->selectGetRootsNonPermanentEnforced()) || LLSelectMgr::getInstance()->selectGetNonPermanentEnforced(); bool editable = is_nonpermanent_enforced && (first_object->permModify() || selectedMediaEditable()); @@ -2241,7 +2241,7 @@ void LLPanelFace::refreshMedia() } } - getChildView("delete_media")->setEnabled(TRUE); + getChildView("delete_media")->setEnabled(true); } U32 materials_media = mComboMatMedia->getCurrentIndex(); @@ -2485,7 +2485,7 @@ void LLPanelFace::updateMediaSettings() // Auto play //value_bool = default_media_data.getAutoPlay(); - // set default to auto play TRUE -- angela EXT-5172 + // set default to auto play true -- angela EXT-5172 value_bool = true; struct functor_getter_auto_play : public LLSelectedTEGetFunctor< bool > { @@ -2497,7 +2497,7 @@ void LLPanelFace::updateMediaSettings() 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 mMediaEntry.getAutoPlay(); set default to auto play true -- angela EXT-5172 return true; }; @@ -2511,7 +2511,7 @@ void LLPanelFace::updateMediaSettings() // Auto scale - // set default to auto scale TRUE -- angela EXT-5172 + // 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 > @@ -2524,7 +2524,7 @@ void LLPanelFace::updateMediaSettings() 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 mMediaEntry.getAutoScale(); set default to auto scale true -- angela EXT-5172 return true; }; @@ -3209,9 +3209,9 @@ void LLPanelFace::onCommitGlow(LLUICtrl* ctrl, void* userdata) } // static -BOOL LLPanelFace::onDragPbr(LLUICtrl*, LLInventoryItem* item) +bool LLPanelFace::onDragPbr(LLUICtrl*, LLInventoryItem* item) { - BOOL accept = TRUE; + bool accept = true; for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++) { @@ -3219,7 +3219,7 @@ BOOL LLPanelFace::onDragPbr(LLUICtrl*, LLInventoryItem* item) LLViewerObject* obj = node->getObject(); if (!LLToolDragAndDrop::isInventoryDropAcceptable(obj, item)) { - accept = FALSE; + accept = false; break; } } @@ -3275,9 +3275,9 @@ void LLPanelFace::onSelectPbr(const LLSD& data) } // static -BOOL LLPanelFace::onDragTexture(LLUICtrl*, LLInventoryItem* item) +bool LLPanelFace::onDragTexture(LLUICtrl*, LLInventoryItem* item) { - BOOL accept = TRUE; + bool accept = true; for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++) { @@ -3285,7 +3285,7 @@ BOOL LLPanelFace::onDragTexture(LLUICtrl*, LLInventoryItem* item) LLViewerObject* obj = node->getObject(); if (!LLToolDragAndDrop::isInventoryDropAcceptable(obj, item)) { - accept = FALSE; + accept = false; break; } } @@ -4669,7 +4669,7 @@ void LLPanelFace::onPasteTexture(LLViewerObject* objectp, S32 te) 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); + LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(imageid, FTT_DEFAULT, true, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); objectp->setTEImage(U8(te), image); } } -- cgit v1.2.3 From f9473e8afcb624cc1b101195bf15943ec372b56f Mon Sep 17 00:00:00 2001 From: Alexander Gavriliuk Date: Mon, 6 May 2024 16:52:34 +0200 Subject: secondlife/viewer#1333 BOOL to bool conversion leftovers: ternaries --- indra/newview/llpanelface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llpanelface.cpp') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 84ee0c326b..cd3cf00b7b 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -1999,7 +1999,7 @@ void LLPanelFace::updateUIGLTF(LLViewerObject* objectp, bool& has_pbr_material, { LLSelectedTE::getPbrMaterialId(pbr_id, identical_pbr, has_pbr_material, has_faces_without_pbr); - pbr_ctrl->setTentative(identical_pbr ? false : true); + pbr_ctrl->setTentative(!identical_pbr); pbr_ctrl->setEnabled(settable); pbr_ctrl->setImageAssetID(pbr_id); -- cgit v1.2.3 From e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 21:25:21 +0200 Subject: Fix line endlings --- indra/newview/llpanelface.cpp | 10996 ++++++++++++++++++++-------------------- 1 file changed, 5498 insertions(+), 5498 deletions(-) (limited to 'indra/newview/llpanelface.cpp') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 4d5fed9e70..8d6cdb4d8d 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 func) -{ - struct LLSelectedTEGLTFMaterialFunctor : public LLSelectedTEFunctor - { - LLSelectedTEGLTFMaterialFunctor(std::function 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 mFunc; - } select_func(func); - - LLSelectMgr::getInstance()->getSelection()->applyToTEs(&select_func); -} - -template -void readSelectedGLTFMaterial(std::function func, T& value, bool& identical, bool has_tolerance, T tolerance) -{ - struct LLSelectedTEGetGLTFMaterialFunctor : public LLSelectedTEGetFunctor - { - LLSelectedTEGetGLTFMaterialFunctor(std::function 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 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("radio_material_type"); - channel_to_edit = (LLRender::eTexIndex)radio_mat_type->getSelectedIndex(); - } - if (matmedia_selection == MATMEDIA_PBR) - { - LLRadioGroup* radio_mat_type = getChild("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("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("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("bumpytexture control")->getImageAssetID(); } -LLUUID LLPanelFace::getCurrentSpecularMap() { return getChild("shinytexture control")->getImageAssetID(); } -U32 LLPanelFace::getCurrentShininess() { return getChild("combobox shininess")->getCurrentIndex(); } -U32 LLPanelFace::getCurrentBumpiness() { return getChild("combobox bumpiness")->getCurrentIndex(); } -U8 LLPanelFace::getCurrentDiffuseAlphaMode() { return (U8)getChild("combobox alphamode")->getCurrentIndex(); } -U8 LLPanelFace::getCurrentAlphaMaskCutoff() { return (U8)getChild("maskcutoff")->getValue().asInteger(); } -U8 LLPanelFace::getCurrentEnvIntensity() { return (U8)getChild("environment")->getValue().asInteger(); } -U8 LLPanelFace::getCurrentGlossiness() { return (U8)getChild("glossiness")->getValue().asInteger(); } -F32 LLPanelFace::getCurrentBumpyRot() { return getChild("bumpyRot")->getValue().asReal(); } -F32 LLPanelFace::getCurrentBumpyScaleU() { return getChild("bumpyScaleU")->getValue().asReal(); } -F32 LLPanelFace::getCurrentBumpyScaleV() { return getChild("bumpyScaleV")->getValue().asReal(); } -F32 LLPanelFace::getCurrentBumpyOffsetU() { return getChild("bumpyOffsetU")->getValue().asReal(); } -F32 LLPanelFace::getCurrentBumpyOffsetV() { return getChild("bumpyOffsetV")->getValue().asReal(); } -F32 LLPanelFace::getCurrentShinyRot() { return getChild("shinyRot")->getValue().asReal(); } -F32 LLPanelFace::getCurrentShinyScaleU() { return getChild("shinyScaleU")->getValue().asReal(); } -F32 LLPanelFace::getCurrentShinyScaleV() { return getChild("shinyScaleV")->getValue().asReal(); } -F32 LLPanelFace::getCurrentShinyOffsetU() { return getChild("shinyOffsetU")->getValue().asReal(); } -F32 LLPanelFace::getCurrentShinyOffsetV() { return getChild("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("gltfTextureScaleU")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFTextureScaleU, this, _1), nullptr); - getChild("gltfTextureScaleV")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFTextureScaleV, this, _1), nullptr); - getChild("gltfTextureRotation")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFRotation, this, _1), nullptr); - getChild("gltfTextureOffsetU")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFTextureOffsetU, this, _1), nullptr); - getChild("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("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("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("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("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("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("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("color trans"); - if(mLabelColorTransp) - { - mLabelColorTransp->setFollowsTop(); - mLabelColorTransp->setFollowsLeft(); - } - - mCtrlColorTransp = getChild("ColorTrans"); - if(mCtrlColorTransp) - { - mCtrlColorTransp->setCommitCallback(boost::bind(&LLPanelFace::onCommitAlpha, this, _2)); - mCtrlColorTransp->setPrecision(0); - mCtrlColorTransp->setFollowsTop(); - mCtrlColorTransp->setFollowsLeft(); - } - - mCheckFullbright = getChild("checkbox fullbright"); - if (mCheckFullbright) - { - mCheckFullbright->setCommitCallback(LLPanelFace::onCommitFullbright, this); - } - - mComboTexGen = getChild("combobox texgen"); - if(mComboTexGen) - { - mComboTexGen->setCommitCallback(LLPanelFace::onCommitTexGen, this); - mComboTexGen->setFollows(FOLLOWS_LEFT | FOLLOWS_TOP); - } - - mComboMatMedia = getChild("combobox matmedia"); - if(mComboMatMedia) - { - mComboMatMedia->setCommitCallback(LLPanelFace::onCommitMaterialsMedia,this); - mComboMatMedia->selectNthItem(MATMEDIA_MATERIAL); - } - - LLRadioGroup* radio_mat_type = findChild("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("radio_pbr_type"); - if (radio_pbr_type) - { - radio_pbr_type->setCommitCallback(LLPanelFace::onCommitPbrType, this); - radio_pbr_type->selectNthItem(PBRTYPE_RENDER_MATERIAL_ID); - } - - mCtrlGlow = getChild("glow"); - if(mCtrlGlow) - { - mCtrlGlow->setCommitCallback(LLPanelFace::onCommitGlow, this); - } - - mMenuClipboardColor = getChild("clipboard_color_params_btn"); - mMenuClipboardTexture = getChild("clipboard_texture_params_btn"); - - mTitleMedia = getChild("title_media"); - mTitleMediaText = getChild("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("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("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("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("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("checkbox fullbright"); - if(!mCheckFullbright)return; - U8 fullbright = mCheckFullbright->get() ? TEM_FULLBRIGHT_MASK : 0; - LLSelectMgr::getInstance()->selectionSetFullbright( fullbright ); -} - -void LLPanelFace::sendColor() -{ - - LLColorSwatchCtrl* mColorSwatch = getChild("colorswatch"); - if(!mColorSwatch)return; - LLColor4 color = mColorSwatch->get(); - - LLSelectMgr::getInstance()->selectionSetColorOnly( color ); -} - -void LLPanelFace::sendAlpha() -{ - LLSpinCtrl* mCtrlColorTransp = getChild("ColorTrans"); - if(!mCtrlColorTransp)return; - F32 alpha = (100.f - mCtrlColorTransp->get()) / 100.f; - - LLSelectMgr::getInstance()->selectionSetAlphaOnly( alpha ); -} - - -void LLPanelFace::sendGlow() -{ - LLSpinCtrl* mCtrlGlow = getChild("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("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(prefix + "ScaleU"); - LLSpinCtrl * ctrlTexScaleT = mPanel->getChild(prefix + "ScaleV"); - LLSpinCtrl * ctrlTexOffsetS = mPanel->getChild(prefix + "OffsetU"); - LLSpinCtrl * ctrlTexOffsetT = mPanel->getChild(prefix + "OffsetV"); - LLSpinCtrl * ctrlTexRotation = mPanel->getChild(prefix + "Rot"); - - LLComboBox* comboTexGen = mPanel->getChild("combobox texgen"); - LLCheckBoxCtrl* cb_planar_align = mPanel->getChild("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("radio_material_type"); - LLPanelFaceSetAlignedConcreteTEFunctor setfunc(this, last_face, static_cast(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("texture control"); - LLTextureCtrl *shinytexture_ctrl = getChild("shinytexture control"); - LLTextureCtrl *bumpytexture_ctrl = getChild("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("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("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("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("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("combobox shininess")->setTentative(!identical_spec); - getChild("glossiness")->setTentative(!identical_spec); - getChild("environment")->setTentative(!identical_spec); - getChild("shinycolorswatch")->setTentative(!identical_spec); - - LLColorSwatchCtrl* mShinyColorSwatch = getChild("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("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("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("TexScaleU")->setValue(diff_scale_s); - getChild("shinyScaleU")->setValue(spec_scale_s); - getChild("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("TexScaleU")->setTentative( LLSD(diff_scale_tentative)); - getChild("shinyScaleU")->setTentative(LLSD(spec_scale_tentative)); - getChild("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("TexScaleV")->forceSetValue(diff_scale_t); - } - else - { - getChild("TexScaleV")->setValue(diff_scale_t); - } - getChild("shinyScaleV")->setValue(norm_scale_t); - getChild("bumpyScaleV")->setValue(spec_scale_t); - - getChild("TexScaleV")->setTentative(LLSD(diff_scale_tentative)); - getChild("shinyScaleV")->setTentative(LLSD(norm_scale_tentative)); - getChild("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("TexOffsetU")->setValue( editable ? diff_offset_s : 0.0f); - getChild("bumpyOffsetU")->setValue(editable ? norm_offset_s : 0.0f); - getChild("shinyOffsetU")->setValue(editable ? spec_offset_s : 0.0f); - - getChild("TexOffsetU")->setTentative(LLSD(diff_offset_u_tentative)); - getChild("shinyOffsetU")->setTentative(LLSD(norm_offset_u_tentative)); - getChild("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("TexOffsetV")->setValue( editable ? diff_offset_t : 0.0f); - getChild("bumpyOffsetV")->setValue(editable ? norm_offset_t : 0.0f); - getChild("shinyOffsetV")->setValue(editable ? spec_offset_t : 0.0f); - - getChild("TexOffsetV")->setTentative(LLSD(diff_offset_v_tentative)); - getChild("shinyOffsetV")->setTentative(LLSD(norm_offset_v_tentative)); - getChild("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("TexRot")->setTentative(diff_rot_tentative); - getChild("shinyRot")->setTentative(LLSD(norm_rot_tentative)); - getChild("bumpyRot")->setTentative(LLSD(spec_rot_tentative)); - - getChild("TexRot")->setValue( editable ? diff_rot_deg : 0.0f); - getChild("shinyRot")->setValue(editable ? spec_rot_deg : 0.0f); - getChild("bumpyRot")->setValue(editable ? norm_rot_deg : 0.0f); - } - - { - F32 glow = 0.f; - bool identical_glow = false; - LLSelectedTE::getGlow(glow,identical_glow); - getChild("glow")->setValue(glow); - getChild("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("combobox texgen")->setTentative(!identical); - getChildView("tex gen")->setEnabled(editable); - } - - { - U8 fullbright_flag = 0; - bool identical_fullbright = false; - - LLSelectedTE::getFullbright(fullbright_flag,identical_fullbright); - - getChild("checkbox fullbright")->setValue((S32)(fullbright_flag != 0)); - getChildView("checkbox fullbright")->setEnabled(editable && !has_pbr_material); - getChild("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("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("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("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("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("shinyScaleU")->setValue(repeat_x); - getChild("shinyScaleV")->setValue(repeat_y); - getChild("shinyRot")->setValue(rot*RAD_TO_DEG); - getChild("shinyOffsetU")->setValue(offset_x); - getChild("shinyOffsetV")->setValue(offset_y); - getChild("glossiness")->setValue(material->getSpecularLightExponent()); - getChild("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("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("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("bumpyScaleU")->setValue(repeat_x); - getChild("bumpyScaleV")->setValue(repeat_y); - getChild("bumpyRot")->setValue(rot*RAD_TO_DEG); - getChild("bumpyOffsetU")->setValue(offset_x); - getChild("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("pbr_control"); - if (pbr_ctrl) - { - pbr_ctrl->setImageAssetID(LLUUID::null); - pbr_ctrl->setEnabled(false); - } - LLTextureCtrl* texture_ctrl = getChild("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("colorswatch"); - if (mColorSwatch) - { - mColorSwatch->setEnabled( false ); - mColorSwatch->setFallbackImage(LLUI::getUIImage("locked_image.j2c") ); - mColorSwatch->setValid(false); - } - LLRadioGroup* radio_mat_type = getChild("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("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(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(); - } - } - - 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("gltfTextureScaleU"); - LLUICtrl* gltfCtrlTextureScaleV = getChild("gltfTextureScaleV"); - LLUICtrl* gltfCtrlTextureRotation = getChild("gltfTextureRotation"); - LLUICtrl* gltfCtrlTextureOffsetU = getChild("gltfTextureOffsetU"); - LLUICtrl* gltfCtrlTextureOffsetV = getChild("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("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(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 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 value_vector_str = default_media_data.getWhiteList(); - struct functor_getter_whitelist_urls : public LLSelectedTEGetFunctor< std::vector > - { - functor_getter_whitelist_urls(const LLMediaEntry& entry) : mMediaEntry(entry) {} - - std::vector 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("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("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("radio_material_type"); - LLRadioGroup* radio_pbr_type = findChild("radio_pbr_type"); - LLComboBox* combo_shininess = findChild("combobox shininess"); - LLComboBox* combo_bumpiness = findChild("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("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("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("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("shinytexture control"); - LLUUID shiny_texture_ID = texture_ctrl->getImageAssetID(); - LL_DEBUGS("Materials") << "Shiny texture selected: " << shiny_texture_ID << LL_ENDL; - LLComboBox* comboShiny = getChild("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("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("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("combobox bumpiness"); - if (!comboBumpy) - { - return; - } - - if (mess_with_combobox) - { - LLTextureCtrl* texture_ctrl = getChild("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("combobox shininess"); - if(!mComboShininess) - return; - - U32 shininess = mComboShininess->getCurrentIndex(); - - self->sendShiny(shininess); -} - -// static -void LLPanelFace::updateAlphaControls() -{ - LLComboBox* comboAlphaMode = getChild("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("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("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("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("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("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("TexOffsetU")->forceSetValue(offsetU); - self->sendTextureInfo(); -} - -//static -void LLPanelFace::syncOffsetY(LLPanelFace* self, F32 offsetV) -{ - LLSelectedTEMaterial::setNormalOffsetY(self,offsetV); - LLSelectedTEMaterial::setSpecularOffsetY(self,offsetV); - self->getChild("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("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("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("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("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("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("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("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("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("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("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("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("rptctrl"); - - U32 materials_media = self->mComboMatMedia->getCurrentIndex(); - U32 material_type = 0; - if (materials_media == MATMEDIA_PBR) - { - LLRadioGroup* radio_mat_type = self->getChild("radio_pbr_type"); - material_type = radio_mat_type->getSelectedIndex(); - } - if (materials_media == MATMEDIA_MATERIAL) - { - LLRadioGroup* radio_mat_type = self->getChild("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("bumpyScaleU"); - LLUICtrl* bumpy_scale_v = self->getChild("bumpyScaleV"); - LLUICtrl* shiny_scale_u = self->getChild("shinyScaleU"); - LLUICtrl* shiny_scale_v = self->getChild("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("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(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 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 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::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(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 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("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([&](const LLGLTFMaterial* mat) - { - return mat ? mat->mTextureTransform[i].mScale[VX] : 0.f; - }, this_transform.mScale[VX], this_scale_u_same, true, 1e-3f); - readSelectedGLTFMaterial([&](const LLGLTFMaterial* mat) - { - return mat ? mat->mTextureTransform[i].mScale[VY] : 0.f; - }, this_transform.mScale[VY], this_scale_v_same, true, 1e-3f); - readSelectedGLTFMaterial([&](const LLGLTFMaterial* mat) - { - return mat ? mat->mTextureTransform[i].mRotation : 0.f; - }, this_transform.mRotation, this_rotation_same, true, 1e-3f); - readSelectedGLTFMaterial([&](const LLGLTFMaterial* mat) - { - return mat ? mat->mTextureTransform[i].mOffset[VX] : 0.f; - }, this_transform.mOffset[VX], this_offset_u_same, true, 1e-3f); - readSelectedGLTFMaterial([&](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("gltfTextureScaleU"); - LLUICtrl* gltfCtrlTextureScaleV = getChild("gltfTextureScaleV"); - LLUICtrl* gltfCtrlTextureRotation = getChild("gltfTextureRotation"); - LLUICtrl* gltfCtrlTextureOffsetU = getChild("gltfTextureOffsetU"); - LLUICtrl* gltfCtrlTextureOffsetV = getChild("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("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("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("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("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("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("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(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("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* 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 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 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 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 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 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 - { - 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 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 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 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 func) +{ + struct LLSelectedTEGLTFMaterialFunctor : public LLSelectedTEFunctor + { + LLSelectedTEGLTFMaterialFunctor(std::function 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 mFunc; + } select_func(func); + + LLSelectMgr::getInstance()->getSelection()->applyToTEs(&select_func); +} + +template +void readSelectedGLTFMaterial(std::function func, T& value, bool& identical, bool has_tolerance, T tolerance) +{ + struct LLSelectedTEGetGLTFMaterialFunctor : public LLSelectedTEGetFunctor + { + LLSelectedTEGetGLTFMaterialFunctor(std::function 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 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("radio_material_type"); + channel_to_edit = (LLRender::eTexIndex)radio_mat_type->getSelectedIndex(); + } + if (matmedia_selection == MATMEDIA_PBR) + { + LLRadioGroup* radio_mat_type = getChild("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("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("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("bumpytexture control")->getImageAssetID(); } +LLUUID LLPanelFace::getCurrentSpecularMap() { return getChild("shinytexture control")->getImageAssetID(); } +U32 LLPanelFace::getCurrentShininess() { return getChild("combobox shininess")->getCurrentIndex(); } +U32 LLPanelFace::getCurrentBumpiness() { return getChild("combobox bumpiness")->getCurrentIndex(); } +U8 LLPanelFace::getCurrentDiffuseAlphaMode() { return (U8)getChild("combobox alphamode")->getCurrentIndex(); } +U8 LLPanelFace::getCurrentAlphaMaskCutoff() { return (U8)getChild("maskcutoff")->getValue().asInteger(); } +U8 LLPanelFace::getCurrentEnvIntensity() { return (U8)getChild("environment")->getValue().asInteger(); } +U8 LLPanelFace::getCurrentGlossiness() { return (U8)getChild("glossiness")->getValue().asInteger(); } +F32 LLPanelFace::getCurrentBumpyRot() { return getChild("bumpyRot")->getValue().asReal(); } +F32 LLPanelFace::getCurrentBumpyScaleU() { return getChild("bumpyScaleU")->getValue().asReal(); } +F32 LLPanelFace::getCurrentBumpyScaleV() { return getChild("bumpyScaleV")->getValue().asReal(); } +F32 LLPanelFace::getCurrentBumpyOffsetU() { return getChild("bumpyOffsetU")->getValue().asReal(); } +F32 LLPanelFace::getCurrentBumpyOffsetV() { return getChild("bumpyOffsetV")->getValue().asReal(); } +F32 LLPanelFace::getCurrentShinyRot() { return getChild("shinyRot")->getValue().asReal(); } +F32 LLPanelFace::getCurrentShinyScaleU() { return getChild("shinyScaleU")->getValue().asReal(); } +F32 LLPanelFace::getCurrentShinyScaleV() { return getChild("shinyScaleV")->getValue().asReal(); } +F32 LLPanelFace::getCurrentShinyOffsetU() { return getChild("shinyOffsetU")->getValue().asReal(); } +F32 LLPanelFace::getCurrentShinyOffsetV() { return getChild("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("gltfTextureScaleU")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFTextureScaleU, this, _1), nullptr); + getChild("gltfTextureScaleV")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFTextureScaleV, this, _1), nullptr); + getChild("gltfTextureRotation")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFRotation, this, _1), nullptr); + getChild("gltfTextureOffsetU")->setCommitCallback(boost::bind(&LLPanelFace::onCommitGLTFTextureOffsetU, this, _1), nullptr); + getChild("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("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("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("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("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("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("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("color trans"); + if(mLabelColorTransp) + { + mLabelColorTransp->setFollowsTop(); + mLabelColorTransp->setFollowsLeft(); + } + + mCtrlColorTransp = getChild("ColorTrans"); + if(mCtrlColorTransp) + { + mCtrlColorTransp->setCommitCallback(boost::bind(&LLPanelFace::onCommitAlpha, this, _2)); + mCtrlColorTransp->setPrecision(0); + mCtrlColorTransp->setFollowsTop(); + mCtrlColorTransp->setFollowsLeft(); + } + + mCheckFullbright = getChild("checkbox fullbright"); + if (mCheckFullbright) + { + mCheckFullbright->setCommitCallback(LLPanelFace::onCommitFullbright, this); + } + + mComboTexGen = getChild("combobox texgen"); + if(mComboTexGen) + { + mComboTexGen->setCommitCallback(LLPanelFace::onCommitTexGen, this); + mComboTexGen->setFollows(FOLLOWS_LEFT | FOLLOWS_TOP); + } + + mComboMatMedia = getChild("combobox matmedia"); + if(mComboMatMedia) + { + mComboMatMedia->setCommitCallback(LLPanelFace::onCommitMaterialsMedia,this); + mComboMatMedia->selectNthItem(MATMEDIA_MATERIAL); + } + + LLRadioGroup* radio_mat_type = findChild("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("radio_pbr_type"); + if (radio_pbr_type) + { + radio_pbr_type->setCommitCallback(LLPanelFace::onCommitPbrType, this); + radio_pbr_type->selectNthItem(PBRTYPE_RENDER_MATERIAL_ID); + } + + mCtrlGlow = getChild("glow"); + if(mCtrlGlow) + { + mCtrlGlow->setCommitCallback(LLPanelFace::onCommitGlow, this); + } + + mMenuClipboardColor = getChild("clipboard_color_params_btn"); + mMenuClipboardTexture = getChild("clipboard_texture_params_btn"); + + mTitleMedia = getChild("title_media"); + mTitleMediaText = getChild("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("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("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("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("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("checkbox fullbright"); + if(!mCheckFullbright)return; + U8 fullbright = mCheckFullbright->get() ? TEM_FULLBRIGHT_MASK : 0; + LLSelectMgr::getInstance()->selectionSetFullbright( fullbright ); +} + +void LLPanelFace::sendColor() +{ + + LLColorSwatchCtrl* mColorSwatch = getChild("colorswatch"); + if(!mColorSwatch)return; + LLColor4 color = mColorSwatch->get(); + + LLSelectMgr::getInstance()->selectionSetColorOnly( color ); +} + +void LLPanelFace::sendAlpha() +{ + LLSpinCtrl* mCtrlColorTransp = getChild("ColorTrans"); + if(!mCtrlColorTransp)return; + F32 alpha = (100.f - mCtrlColorTransp->get()) / 100.f; + + LLSelectMgr::getInstance()->selectionSetAlphaOnly( alpha ); +} + + +void LLPanelFace::sendGlow() +{ + LLSpinCtrl* mCtrlGlow = getChild("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("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(prefix + "ScaleU"); + LLSpinCtrl * ctrlTexScaleT = mPanel->getChild(prefix + "ScaleV"); + LLSpinCtrl * ctrlTexOffsetS = mPanel->getChild(prefix + "OffsetU"); + LLSpinCtrl * ctrlTexOffsetT = mPanel->getChild(prefix + "OffsetV"); + LLSpinCtrl * ctrlTexRotation = mPanel->getChild(prefix + "Rot"); + + LLComboBox* comboTexGen = mPanel->getChild("combobox texgen"); + LLCheckBoxCtrl* cb_planar_align = mPanel->getChild("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("radio_material_type"); + LLPanelFaceSetAlignedConcreteTEFunctor setfunc(this, last_face, static_cast(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("texture control"); + LLTextureCtrl *shinytexture_ctrl = getChild("shinytexture control"); + LLTextureCtrl *bumpytexture_ctrl = getChild("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("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("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("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("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("combobox shininess")->setTentative(!identical_spec); + getChild("glossiness")->setTentative(!identical_spec); + getChild("environment")->setTentative(!identical_spec); + getChild("shinycolorswatch")->setTentative(!identical_spec); + + LLColorSwatchCtrl* mShinyColorSwatch = getChild("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("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("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("TexScaleU")->setValue(diff_scale_s); + getChild("shinyScaleU")->setValue(spec_scale_s); + getChild("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("TexScaleU")->setTentative( LLSD(diff_scale_tentative)); + getChild("shinyScaleU")->setTentative(LLSD(spec_scale_tentative)); + getChild("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("TexScaleV")->forceSetValue(diff_scale_t); + } + else + { + getChild("TexScaleV")->setValue(diff_scale_t); + } + getChild("shinyScaleV")->setValue(norm_scale_t); + getChild("bumpyScaleV")->setValue(spec_scale_t); + + getChild("TexScaleV")->setTentative(LLSD(diff_scale_tentative)); + getChild("shinyScaleV")->setTentative(LLSD(norm_scale_tentative)); + getChild("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("TexOffsetU")->setValue( editable ? diff_offset_s : 0.0f); + getChild("bumpyOffsetU")->setValue(editable ? norm_offset_s : 0.0f); + getChild("shinyOffsetU")->setValue(editable ? spec_offset_s : 0.0f); + + getChild("TexOffsetU")->setTentative(LLSD(diff_offset_u_tentative)); + getChild("shinyOffsetU")->setTentative(LLSD(norm_offset_u_tentative)); + getChild("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("TexOffsetV")->setValue( editable ? diff_offset_t : 0.0f); + getChild("bumpyOffsetV")->setValue(editable ? norm_offset_t : 0.0f); + getChild("shinyOffsetV")->setValue(editable ? spec_offset_t : 0.0f); + + getChild("TexOffsetV")->setTentative(LLSD(diff_offset_v_tentative)); + getChild("shinyOffsetV")->setTentative(LLSD(norm_offset_v_tentative)); + getChild("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("TexRot")->setTentative(diff_rot_tentative); + getChild("shinyRot")->setTentative(LLSD(norm_rot_tentative)); + getChild("bumpyRot")->setTentative(LLSD(spec_rot_tentative)); + + getChild("TexRot")->setValue( editable ? diff_rot_deg : 0.0f); + getChild("shinyRot")->setValue(editable ? spec_rot_deg : 0.0f); + getChild("bumpyRot")->setValue(editable ? norm_rot_deg : 0.0f); + } + + { + F32 glow = 0.f; + bool identical_glow = false; + LLSelectedTE::getGlow(glow,identical_glow); + getChild("glow")->setValue(glow); + getChild("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("combobox texgen")->setTentative(!identical); + getChildView("tex gen")->setEnabled(editable); + } + + { + U8 fullbright_flag = 0; + bool identical_fullbright = false; + + LLSelectedTE::getFullbright(fullbright_flag,identical_fullbright); + + getChild("checkbox fullbright")->setValue((S32)(fullbright_flag != 0)); + getChildView("checkbox fullbright")->setEnabled(editable && !has_pbr_material); + getChild("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("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("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("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("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("shinyScaleU")->setValue(repeat_x); + getChild("shinyScaleV")->setValue(repeat_y); + getChild("shinyRot")->setValue(rot*RAD_TO_DEG); + getChild("shinyOffsetU")->setValue(offset_x); + getChild("shinyOffsetV")->setValue(offset_y); + getChild("glossiness")->setValue(material->getSpecularLightExponent()); + getChild("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("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("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("bumpyScaleU")->setValue(repeat_x); + getChild("bumpyScaleV")->setValue(repeat_y); + getChild("bumpyRot")->setValue(rot*RAD_TO_DEG); + getChild("bumpyOffsetU")->setValue(offset_x); + getChild("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("pbr_control"); + if (pbr_ctrl) + { + pbr_ctrl->setImageAssetID(LLUUID::null); + pbr_ctrl->setEnabled(false); + } + LLTextureCtrl* texture_ctrl = getChild("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("colorswatch"); + if (mColorSwatch) + { + mColorSwatch->setEnabled( false ); + mColorSwatch->setFallbackImage(LLUI::getUIImage("locked_image.j2c") ); + mColorSwatch->setValid(false); + } + LLRadioGroup* radio_mat_type = getChild("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("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(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(); + } + } + + 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("gltfTextureScaleU"); + LLUICtrl* gltfCtrlTextureScaleV = getChild("gltfTextureScaleV"); + LLUICtrl* gltfCtrlTextureRotation = getChild("gltfTextureRotation"); + LLUICtrl* gltfCtrlTextureOffsetU = getChild("gltfTextureOffsetU"); + LLUICtrl* gltfCtrlTextureOffsetV = getChild("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("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(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 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 value_vector_str = default_media_data.getWhiteList(); + struct functor_getter_whitelist_urls : public LLSelectedTEGetFunctor< std::vector > + { + functor_getter_whitelist_urls(const LLMediaEntry& entry) : mMediaEntry(entry) {} + + std::vector 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("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("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("radio_material_type"); + LLRadioGroup* radio_pbr_type = findChild("radio_pbr_type"); + LLComboBox* combo_shininess = findChild("combobox shininess"); + LLComboBox* combo_bumpiness = findChild("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("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("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("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("shinytexture control"); + LLUUID shiny_texture_ID = texture_ctrl->getImageAssetID(); + LL_DEBUGS("Materials") << "Shiny texture selected: " << shiny_texture_ID << LL_ENDL; + LLComboBox* comboShiny = getChild("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("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("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("combobox bumpiness"); + if (!comboBumpy) + { + return; + } + + if (mess_with_combobox) + { + LLTextureCtrl* texture_ctrl = getChild("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("combobox shininess"); + if(!mComboShininess) + return; + + U32 shininess = mComboShininess->getCurrentIndex(); + + self->sendShiny(shininess); +} + +// static +void LLPanelFace::updateAlphaControls() +{ + LLComboBox* comboAlphaMode = getChild("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("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("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("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("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("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("TexOffsetU")->forceSetValue(offsetU); + self->sendTextureInfo(); +} + +//static +void LLPanelFace::syncOffsetY(LLPanelFace* self, F32 offsetV) +{ + LLSelectedTEMaterial::setNormalOffsetY(self,offsetV); + LLSelectedTEMaterial::setSpecularOffsetY(self,offsetV); + self->getChild("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("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("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("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("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("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("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("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("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("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("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("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("rptctrl"); + + U32 materials_media = self->mComboMatMedia->getCurrentIndex(); + U32 material_type = 0; + if (materials_media == MATMEDIA_PBR) + { + LLRadioGroup* radio_mat_type = self->getChild("radio_pbr_type"); + material_type = radio_mat_type->getSelectedIndex(); + } + if (materials_media == MATMEDIA_MATERIAL) + { + LLRadioGroup* radio_mat_type = self->getChild("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("bumpyScaleU"); + LLUICtrl* bumpy_scale_v = self->getChild("bumpyScaleV"); + LLUICtrl* shiny_scale_u = self->getChild("shinyScaleU"); + LLUICtrl* shiny_scale_v = self->getChild("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("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(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 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 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::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(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 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("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([&](const LLGLTFMaterial* mat) + { + return mat ? mat->mTextureTransform[i].mScale[VX] : 0.f; + }, this_transform.mScale[VX], this_scale_u_same, true, 1e-3f); + readSelectedGLTFMaterial([&](const LLGLTFMaterial* mat) + { + return mat ? mat->mTextureTransform[i].mScale[VY] : 0.f; + }, this_transform.mScale[VY], this_scale_v_same, true, 1e-3f); + readSelectedGLTFMaterial([&](const LLGLTFMaterial* mat) + { + return mat ? mat->mTextureTransform[i].mRotation : 0.f; + }, this_transform.mRotation, this_rotation_same, true, 1e-3f); + readSelectedGLTFMaterial([&](const LLGLTFMaterial* mat) + { + return mat ? mat->mTextureTransform[i].mOffset[VX] : 0.f; + }, this_transform.mOffset[VX], this_offset_u_same, true, 1e-3f); + readSelectedGLTFMaterial([&](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("gltfTextureScaleU"); + LLUICtrl* gltfCtrlTextureScaleV = getChild("gltfTextureScaleV"); + LLUICtrl* gltfCtrlTextureRotation = getChild("gltfTextureRotation"); + LLUICtrl* gltfCtrlTextureOffsetU = getChild("gltfTextureOffsetU"); + LLUICtrl* gltfCtrlTextureOffsetV = getChild("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("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("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("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("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("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("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(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("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* 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 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 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 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 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 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 + { + 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 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 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 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 ); +} + -- cgit v1.2.3 From e60adafa3361499a5d903d2c1199567b66ffad23 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 6 Jun 2024 09:21:51 +0300 Subject: viewer#1641 Show accurate Alpha mode if asset is missing --- indra/newview/llpanelface.cpp | 105 ++++++++++++++++++++++++++++++------------ 1 file changed, 75 insertions(+), 30 deletions(-) (limited to 'indra/newview/llpanelface.cpp') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 8d6cdb4d8d..50a1bbc8f3 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -1237,27 +1237,35 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) // Texture { - mIsAlpha = false; LLGLenum image_format = GL_RGB; bool identical_image_format = false; - LLSelectedTE::getImageFormat(image_format, identical_image_format); + bool missing_asset = false; + LLSelectedTE::getImageFormat(image_format, identical_image_format, missing_asset); - mIsAlpha = false; - switch (image_format) + if (!missing_asset) { + mIsAlpha = false; + switch (image_format) + { case GL_RGBA: case GL_ALPHA: - { - mIsAlpha = true; - } - break; + { + mIsAlpha = true; + } + break; case GL_RGB: break; default: - { - LL_WARNS() << "Unexpected tex format in LLPanelFace...resorting to no alpha" << LL_ENDL; + { + LL_WARNS() << "Unexpected tex format in LLPanelFace...resorting to no alpha" << LL_ENDL; + } + break; } - break; + } + else + { + // Don't know image's properties, use material's mode value + mIsAlpha = true; } if (LLViewerMedia::getInstance()->textureHasMedia(id)) @@ -1303,10 +1311,12 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) 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); + + bool can_change_alpha = editable && mIsAlpha && !missing_asset && !has_pbr_material; + getChildView("combobox alphamode")->setEnabled(can_change_alpha && transparency <= 0.f); + getChildView("label alphamode")->setEnabled(can_change_alpha); + getChildView("maskcutoff")->setEnabled(can_change_alpha); + getChildView("label maskcutoff")->setEnabled(can_change_alpha); texture_ctrl->setBakeTextureEnabled(true); } @@ -1329,10 +1339,12 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) 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); + + bool can_change_alpha = editable && mIsAlpha && !missing_asset && !has_pbr_material; + getChildView("combobox alphamode")->setEnabled(can_change_alpha && transparency <= 0.f); + getChildView("label alphamode")->setEnabled(can_change_alpha); + getChildView("maskcutoff")->setEnabled(can_change_alpha); + getChildView("label maskcutoff")->setEnabled(can_change_alpha); texture_ctrl->setBakeTextureEnabled(true); } @@ -3321,13 +3333,14 @@ void LLPanelFace::onSelectTexture(const LLSD& data) LLGLenum image_format; bool identical_image_format = false; - LLSelectedTE::getImageFormat(image_format, identical_image_format); + bool missing_asset = false; + LLSelectedTE::getImageFormat(image_format, identical_image_format, missing_asset); LLCtrlSelectionInterface* combobox_alphamode = childGetSelectionInterface("combobox alphamode"); U32 alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_NONE; - if (combobox_alphamode) + if (combobox_alphamode && !missing_asset) { switch (image_format) { @@ -5227,19 +5240,51 @@ void LLPanelFace::LLSelectedTE::getFace(LLFace*& face_to_return, bool& identical 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) +void LLPanelFace::LLSelectedTE::getImageFormat(LLGLenum& image_format_to_return, bool& identical_face, bool& missing_asset) { - LLGLenum image_format; - struct LLSelectedTEGetImageFormat : public LLSelectedTEGetFunctor + struct LLSelectedTEGetmatId : public LLSelectedTEFunctor { - LLGLenum get(LLViewerObject* object, S32 te_index) + LLSelectedTEGetmatId() + : mImageFormat(GL_RGB) + , mIdentical(true) + , mMissingAsset(false) + , mFirstRun(true) { - 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; + bool apply(LLViewerObject* object, S32 te_index) override + { + LLViewerTexture* image = object ? object->getTEImage(te_index) : nullptr; + LLGLenum format = GL_RGB; + bool missing = false; + if (image) + { + format = image->getPrimaryFormat(); + missing = image->isMissingAsset(); + } + + if (mFirstRun) + { + mFirstRun = false; + mImageFormat = format; + mMissingAsset = missing; + } + else + { + mIdentical &= (mImageFormat == format); + mIdentical &= (mMissingAsset == missing); + } + return true; + } + LLGLenum mImageFormat; + bool mIdentical; + bool mMissingAsset; + bool mFirstRun; + } func; + LLSelectMgr::getInstance()->getSelection()->applyToTEs(&func); + + image_format_to_return = func.mImageFormat; + identical_face = func.mIdentical; + missing_asset = func.mMissingAsset; } void LLPanelFace::LLSelectedTE::getTexId(LLUUID& id, bool& identical) -- cgit v1.2.3 From 15b3c9f1643368fe0c5356ea11288525bbe9fbb3 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Thu, 13 Jun 2024 02:22:03 +0200 Subject: Fix a few merge issues --- indra/newview/llpanelface.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra/newview/llpanelface.cpp') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 226c32c396..89af765bb7 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -1805,7 +1805,6 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/) getChild("shinyOffsetV")->setValue(offset_y); getChild("glossiness")->setValue(material->getSpecularLightExponent()); getChild("environment")->setValue(material->getEnvironmentIntensity()); - getChild("mirror")->setValue(material->getEnvironmentIntensity()); updateShinyControls(!material->getSpecularID().isNull(), true); } -- cgit v1.2.3