/** * @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 "llfocusmgr.h" #include "llrect.h" #include "llstring.h" #include "llfontgl.h" // project includes #include "llagentdata.h" #include "llbutton.h" #include "llcheckboxctrl.h" #include "llcolorswatch.h" #include "llcombobox.h" #include "lldrawpoolbump.h" #include "llface.h" #include "lllineeditor.h" #include "llmediaentry.h" #include "llnotificationsutil.h" #include "llresmgr.h" #include "llselectmgr.h" #include "llspinctrl.h" #include "lltextbox.h" #include "lltexturectrl.h" #include "lltextureentry.h" #include "lltooldraganddrop.h" #include "llui.h" #include "llviewercontrol.h" #include "llviewermedia.h" #include "llviewerobject.h" #include "llviewerstats.h" #include "llvovolume.h" #include "lluictrlfactory.h" #include "llpluginclassmedia.h" #include "llviewertexturelist.h" // // Methods // BOOL LLPanelFace::postBuild() { childSetCommitCallback("combobox shininess",&LLPanelFace::onCommitShiny,this); childSetCommitCallback("combobox bumpiness",&LLPanelFace::onCommitBump,this); childSetCommitCallback("TexScaleU",&LLPanelFace::onCommitTextureInfo, this); childSetCommitCallback("checkbox flip s",&LLPanelFace::onCommitTextureInfo, this); childSetCommitCallback("TexScaleV",&LLPanelFace::onCommitTextureInfo, this); childSetCommitCallback("checkbox flip t",&LLPanelFace::onCommitTextureInfo, this); childSetCommitCallback("TexRot",&LLPanelFace::onCommitTextureInfo, this); childSetAction("button apply",&LLPanelFace::onClickApply,this); childSetCommitCallback("checkbox planar align",&LLPanelFace::onCommitPlanarAlign, this); childSetCommitCallback("TexOffsetU",LLPanelFace::onCommitTextureInfo, this); childSetCommitCallback("TexOffsetV",LLPanelFace::onCommitTextureInfo, this); childSetAction("button align",&LLPanelFace::onClickAutoFix,this); LLRect rect = this->getRect(); LLTextureCtrl* mTextureCtrl; LLColorSwatchCtrl* mColorSwatch; LLComboBox* mComboTexGen; LLCheckBoxCtrl *mCheckFullbright; LLTextBox* mLabelColorTransp; LLSpinCtrl* mCtrlColorTransp; // transparency = 1 - alpha LLSpinCtrl* mCtrlGlow; setMouseOpaque(FALSE); mTextureCtrl = getChild("texture control"); if(mTextureCtrl) { mTextureCtrl->setDefaultImageAssetID(LLUUID( gSavedSettings.getString( "DefaultObjectTexture" ))); 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->setFollowsTop(); mTextureCtrl->setFollowsLeft(); mTextureCtrl->setImmediateFilterPermMask(PERM_NONE); mTextureCtrl->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); } 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); } mCtrlGlow = getChild("glow"); if(mCtrlGlow) { mCtrlGlow->setCommitCallback(LLPanelFace::onCommitGlow, this); } clearCtrls(); return TRUE; } LLPanelFace::LLPanelFace() : LLPanel() { } LLPanelFace::~LLPanelFace() { // Children all cleaned up by default view destructor. } 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(); } LLSelectMgr::getInstance()->selectionSetImage(id); } } void LLPanelFace::sendBump() { LLComboBox* mComboBumpiness = getChild("combobox bumpiness"); if(!mComboBumpiness)return; U8 bump = (U8) mComboBumpiness->getCurrentIndex() & TEM_BUMP_MASK; LLSelectMgr::getInstance()->selectionSetBumpmap( bump ); } 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() { LLComboBox* mComboShininess = getChild("combobox shininess"); if(!mComboShininess)return; U8 shiny = (U8) mComboShininess->getCurrentIndex() & TEM_SHINY_MASK; LLSelectMgr::getInstance()->selectionSetShiny( shiny ); } 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; LLSpinCtrl* ctrlTexScaleS = mPanel->getChild("TexScaleU"); LLSpinCtrl* ctrlTexScaleT = mPanel->getChild("TexScaleV"); LLSpinCtrl* ctrlTexOffsetS = mPanel->getChild("TexOffsetU"); LLSpinCtrl* ctrlTexOffsetT = mPanel->getChild("TexOffsetV"); LLSpinCtrl* ctrlTexRotation = mPanel->getChild("TexRot"); LLCheckBoxCtrl* checkFlipScaleS = mPanel->getChild("checkbox flip s"); LLCheckBoxCtrl* checkFlipScaleT = mPanel->getChild("checkbox flip t"); LLComboBox* comboTexGen = mPanel->getChild("combobox texgen"); llassert(comboTexGen); llassert(object); if (ctrlTexScaleS) { valid = !ctrlTexScaleS->getTentative() || !checkFlipScaleS->getTentative(); if (valid) { value = ctrlTexScaleS->get(); if( checkFlipScaleS->get() ) { value = -value; } if (comboTexGen && comboTexGen->getCurrentIndex() == 1) { value *= 0.5f; } object->setTEScaleS( te, value ); } } if (ctrlTexScaleT) { valid = !ctrlTexScaleT->getTentative() || !checkFlipScaleT->getTentative(); if (valid) { value = ctrlTexScaleT->get(); if( checkFlipScaleT->get() ) { value = -value; } if (comboTexGen && comboTexGen->getCurrentIndex() == 1) { value *= 0.5f; } object->setTEScaleT( te, value ); } } if (ctrlTexOffsetS) { valid = !ctrlTexOffsetS->getTentative(); if (valid) { value = ctrlTexOffsetS->get(); object->setTEOffsetS( te, value ); } } if (ctrlTexOffsetT) { valid = !ctrlTexOffsetT->getTentative(); if (valid) { value = ctrlTexOffsetT->get(); object->setTEOffsetT( te, value ); } } if (ctrlTexRotation) { valid = !ctrlTexRotation->getTentative(); if (valid) { value = ctrlTexRotation->get() * DEG_TO_RAD; object->setTERotation( te, value ); } } 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); } } if (!set_aligned) { LLPanelFaceSetTEFunctor setfunc(mPanel); setfunc.apply(object, te); } return true; } private: LLPanelFace* mPanel; LLFace* mCenterFace; }; // 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(); // needs a fuzzy comparison, because of fp errors if (is_approx_equal_fraction(st_offset.mV[VX], aligned_st_offset.mV[VX], 12) && is_approx_equal_fraction(st_offset.mV[VY], aligned_st_offset.mV[VY], 12) && is_approx_equal_fraction(st_scale.mV[VX], aligned_st_scale.mV[VX], 12) && is_approx_equal_fraction(st_scale.mV[VY], aligned_st_scale.mV[VY], 12) && is_approx_equal_fraction(st_rot, aligned_st_rot, 14)) { 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()) { struct f1 : public LLSelectedTEGetFunctor { LLFace* get(LLViewerObject* object, S32 te) { return (object->mDrawable) ? object->mDrawable->getFace(te): NULL; } } get_last_face_func; LLFace* last_face; LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&get_last_face_func, last_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::getState() { LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); if( objectp && objectp->getPCode() == LL_PCODE_VOLUME && objectp->permModify()) { BOOL editable = objectp->permModify(); // only turn on auto-adjust button if there is a media renderer and the media is loaded getChildView("textbox autofix")->setEnabled(editable); getChildView("button align")->setEnabled(editable); //if ( LLMediaEngine::getInstance()->getMediaRenderer () ) // if ( LLMediaEngine::getInstance()->getMediaRenderer ()->isLoaded () ) // { // // //mLabelTexAutoFix->setEnabled ( editable ); // // //mBtnAutoFix->setEnabled ( editable ); // } getChildView("button apply")->setEnabled(editable); bool identical; LLTextureCtrl* texture_ctrl = getChild("texture control"); // Texture { LLUUID id; struct f1 : public LLSelectedTEGetFunctor { LLUUID get(LLViewerObject* object, S32 te_index) { LLUUID id; LLViewerTexture* image = object->getTEImage(te_index); if (image) id = image->getID(); if (!id.isNull() && LLViewerMedia::textureHasMedia(id)) { LLTextureEntry *te = object->getTE(te_index); if (te) { LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID()) : NULL ; if(!tex) { tex = LLViewerFetchedTexture::sDefaultImagep; } if (tex) { id = tex->getID(); } } } return id; } } func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, id ); if(LLViewerMedia::textureHasMedia(id)) { getChildView("textbox autofix")->setEnabled(editable); getChildView("button align")->setEnabled(editable); } if (identical) { // All selected have the same texture if(texture_ctrl) { texture_ctrl->setTentative( FALSE ); texture_ctrl->setEnabled( editable ); texture_ctrl->setImageAssetID( id ); } } else { if(texture_ctrl) { if( id.isNull() ) { // None selected texture_ctrl->setTentative( FALSE ); texture_ctrl->setEnabled( FALSE ); texture_ctrl->setImageAssetID( LLUUID::null ); } else { // Tentative: multiple selected with different textures texture_ctrl->setTentative( TRUE ); texture_ctrl->setEnabled( editable ); texture_ctrl->setImageAssetID( id ); } } } } // planar align bool align_planar = false; bool identical_planar_aligned = false; bool is_planar = false; { LLCheckBoxCtrl* cb_planar_align = getChild("checkbox planar align"); align_planar = (cb_planar_align && cb_planar_align->get()); struct f1 : public LLSelectedTEGetFunctor { bool get(LLViewerObject* object, S32 face) { return (object->getTE(face)->getTexGen() == LLTextureEntry::TEX_GEN_PLANAR); } } func; bool texgens_identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, is_planar ); bool enabled = (editable && texgens_identical && is_planar); childSetValue("checkbox planar align", align_planar && enabled); childSetEnabled("checkbox planar align", enabled); if (align_planar && enabled) { struct f2 : public LLSelectedTEGetFunctor { LLFace* get(LLViewerObject* object, S32 te) { return (object->mDrawable) ? object->mDrawable->getFace(te): NULL; } } get_te_face_func; LLFace* last_face; LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&get_te_face_func, last_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); } } // Texture scale { F32 scale_s = 1.f; struct f2 : public LLSelectedTEGetFunctor { F32 get(LLViewerObject* object, S32 face) { return object->getTE(face)->mScaleS; } } func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, scale_s ); identical = align_planar ? identical_planar_aligned : identical; getChild("TexScaleU")->setValue(editable ? llabs(scale_s) : 0); getChild("TexScaleU")->setTentative(LLSD((BOOL)(!identical))); getChildView("TexScaleU")->setEnabled(editable); getChild("checkbox flip s")->setValue(LLSD((BOOL)(scale_s < 0 ? TRUE : FALSE ))); getChild("checkbox flip s")->setTentative(LLSD((BOOL)((!identical) ? TRUE : FALSE ))); getChildView("checkbox flip s")->setEnabled(editable); } { F32 scale_t = 1.f; struct f3 : public LLSelectedTEGetFunctor { F32 get(LLViewerObject* object, S32 face) { return object->getTE(face)->mScaleT; } } func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, scale_t ); identical = align_planar ? identical_planar_aligned : identical; getChild("TexScaleV")->setValue(llabs(editable ? llabs(scale_t) : 0)); getChild("TexScaleV")->setTentative(LLSD((BOOL)(!identical))); getChildView("TexScaleV")->setEnabled(editable); getChild("checkbox flip t")->setValue(LLSD((BOOL)(scale_t< 0 ? TRUE : FALSE ))); getChild("checkbox flip t")->setTentative(LLSD((BOOL)((!identical) ? TRUE : FALSE ))); getChildView("checkbox flip t")->setEnabled(editable); } // Texture offset { getChildView("tex offset")->setEnabled(editable); F32 offset_s = 0.f; struct f4 : public LLSelectedTEGetFunctor { F32 get(LLViewerObject* object, S32 face) { return object->getTE(face)->mOffsetS; } } func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, offset_s ); identical = align_planar ? identical_planar_aligned : identical; getChild("TexOffsetU")->setValue(editable ? offset_s : 0); getChild("TexOffsetU")->setTentative(!identical); getChildView("TexOffsetU")->setEnabled(editable); } { F32 offset_t = 0.f; struct f5 : public LLSelectedTEGetFunctor { F32 get(LLViewerObject* object, S32 face) { return object->getTE(face)->mOffsetT; } } func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, offset_t ); identical = align_planar ? identical_planar_aligned : identical; getChild("TexOffsetV")->setValue(editable ? offset_t : 0); getChild("TexOffsetV")->setTentative(!identical); getChildView("TexOffsetV")->setEnabled(editable); } // Texture rotation { F32 rotation = 0.f; struct f6 : public LLSelectedTEGetFunctor { F32 get(LLViewerObject* object, S32 face) { return object->getTE(face)->mRotation; } } func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, rotation ); identical = align_planar ? identical_planar_aligned : identical; getChild("TexRot")->setValue(editable ? rotation * RAD_TO_DEG : 0); getChild("TexRot")->setTentative(!identical); getChildView("TexRot")->setEnabled(editable); } // Color swatch LLColorSwatchCtrl* mColorSwatch = getChild("colorswatch"); LLColor4 color = LLColor4::white; if(mColorSwatch) { struct f7 : public LLSelectedTEGetFunctor { LLColor4 get(LLViewerObject* object, S32 face) { return object->getTE(face)->getColor(); } } func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, color ); mColorSwatch->setOriginal(color); mColorSwatch->set(color, TRUE); mColorSwatch->setValid(editable); mColorSwatch->setEnabled( editable ); mColorSwatch->setCanApplyImmediately( editable ); } // 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); } { F32 glow = 0.f; struct f8 : public LLSelectedTEGetFunctor { F32 get(LLViewerObject* object, S32 face) { return object->getTE(face)->getGlow(); } } func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, glow ); getChild("glow")->setValue(glow); getChildView("glow")->setEnabled(editable); getChild("glow")->setTentative(!identical); getChildView("glow label")->setEnabled(editable); } // Bump { F32 shinyf = 0.f; struct f9 : public LLSelectedTEGetFunctor { F32 get(LLViewerObject* object, S32 face) { return (F32)(object->getTE(face)->getShiny()); } } func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, shinyf ); LLCtrlSelectionInterface* combobox_shininess = childGetSelectionInterface("combobox shininess"); if (combobox_shininess) { combobox_shininess->selectNthItem((S32)shinyf); } else { llwarns << "failed childGetSelectionInterface for 'combobox shininess'" << llendl; } getChildView("combobox shininess")->setEnabled(editable); getChild("combobox shininess")->setTentative(!identical); getChildView("label shininess")->setEnabled(editable); } { F32 bumpf = 0.f; struct f10 : public LLSelectedTEGetFunctor { F32 get(LLViewerObject* object, S32 face) { return (F32)(object->getTE(face)->getBumpmap()); } } func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, bumpf ); LLCtrlSelectionInterface* combobox_bumpiness = childGetSelectionInterface("combobox bumpiness"); if (combobox_bumpiness) { combobox_bumpiness->selectNthItem((S32)bumpf); } else { llwarns << "failed childGetSelectionInterface for 'combobox bumpiness'" << llendl; } getChildView("combobox bumpiness")->setEnabled(editable); getChild("combobox bumpiness")->setTentative(!identical); getChildView("label bumpiness")->setEnabled(editable); } { F32 genf = 0.f; struct f11 : public LLSelectedTEGetFunctor { F32 get(LLViewerObject* object, S32 face) { return (F32)(object->getTE(face)->getTexGen()); } } func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, genf ); S32 selected_texgen = ((S32) genf) >> TEM_TEX_GEN_SHIFT; LLCtrlSelectionInterface* combobox_texgen = childGetSelectionInterface("combobox texgen"); if (combobox_texgen) { combobox_texgen->selectNthItem(selected_texgen); } else { llwarns << "failed childGetSelectionInterface for 'combobox texgen'" << llendl; } getChildView("combobox texgen")->setEnabled(editable); getChild("combobox texgen")->setTentative(!identical); getChildView("tex gen")->setEnabled(editable); if (selected_texgen == 1) { getChild("TexScaleU")->setValue(2.0f * getChild("TexScaleU")->getValue().asReal() ); getChild("TexScaleV")->setValue(2.0f * getChild("TexScaleV")->getValue().asReal() ); // EXP-1507 (change label based on the mapping mode) getChild("rpt")->setValue(getString("string repeats per meter")); } else if (selected_texgen == 0) // FIXME: should not be magic numbers { getChild("rpt")->setValue(getString("string repeats per face")); } } { F32 fullbrightf = 0.f; struct f12 : public LLSelectedTEGetFunctor { F32 get(LLViewerObject* object, S32 face) { return (F32)(object->getTE(face)->getFullbright()); } } func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, fullbrightf ); getChild("checkbox fullbright")->setValue((S32)fullbrightf); getChildView("checkbox fullbright")->setEnabled(editable); getChild("checkbox fullbright")->setTentative(!identical); } // Repeats per meter label { getChildView("rpt")->setEnabled(editable); } // Repeats per meter { F32 repeats = 1.f; struct f13 : public LLSelectedTEGetFunctor { F32 get(LLViewerObject* object, S32 face) { U32 s_axis = VX; U32 t_axis = VY; // BUG: Only repeats along S axis // BUG: Only works for boxes. LLPrimitive::getTESTAxes(face, &s_axis, &t_axis); return object->getTE(face)->mScaleS / object->getScale().mV[s_axis]; } } func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, repeats ); getChild("rptctrl")->setValue(editable ? repeats : 0); getChild("rptctrl")->setTentative(!identical); LLComboBox* mComboTexGen = getChild("combobox texgen"); if (mComboTexGen) { BOOL enabled = editable && (!mComboTexGen || mComboTexGen->getCurrentIndex() != 1); getChildView("rptctrl")->setEnabled(enabled); getChildView("button apply")->setEnabled(enabled); } } // 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* 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->setFallbackImageName("locked_image.j2c" ); mColorSwatch->setValid(FALSE); } getChildView("color trans")->setEnabled(FALSE); getChildView("rpt")->setEnabled(FALSE); getChildView("tex offset")->setEnabled(FALSE); getChildView("tex gen")->setEnabled(FALSE); getChildView("label shininess")->setEnabled(FALSE); getChildView("label bumpiness")->setEnabled(FALSE); getChildView("textbox autofix")->setEnabled(FALSE); getChildView("button align")->setEnabled(FALSE); getChildView("button apply")->setEnabled(FALSE); //getChildView("has media")->setEnabled(FALSE); //getChildView("media info set")->setEnabled(FALSE); // 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); } } void LLPanelFace::refresh() { getState(); } // // 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::onCommitAlpha(const LLSD& data) { sendAlpha(); } void LLPanelFace::onCancelColor(const LLSD& data) { LLSelectMgr::getInstance()->selectionRevertColors(); } void LLPanelFace::onSelectColor(const LLSD& data) { LLSelectMgr::getInstance()->saveSelectedObjectColors(); sendColor(); } // static void LLPanelFace::onCommitBump(LLUICtrl* ctrl, void* userdata) { LLPanelFace* self = (LLPanelFace*) userdata; self->sendBump(); } // static void LLPanelFace::onCommitTexGen(LLUICtrl* ctrl, void* userdata) { LLPanelFace* self = (LLPanelFace*) userdata; self->sendTexGen(); } // static void LLPanelFace::onCommitShiny(LLUICtrl* ctrl, void* userdata) { LLPanelFace* self = (LLPanelFace*) userdata; self->sendShiny(); } // 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::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 ) { LLViewerStats::getInstance()->incStat(LLViewerStats::ST_EDIT_TEXTURE_COUNT ); sendTexture(); } void LLPanelFace::onCancelTexture(const LLSD& data) { LLSelectMgr::getInstance()->selectionRevertTextures(); } void LLPanelFace::onSelectTexture(const LLSD& data) { LLSelectMgr::getInstance()->saveSelectedObjectTextures(); sendTexture(); } // static void LLPanelFace::onCommitTextureInfo( LLUICtrl* ctrl, void* userdata ) { LLPanelFace* self = (LLPanelFace*) userdata; self->sendTextureInfo(); } // Commit the number of repeats per meter // static void LLPanelFace::onClickApply(void* userdata) { LLPanelFace* self = (LLPanelFace*) userdata; gFocusMgr.setKeyboardFocus( NULL ); //F32 repeats_per_meter = self->mCtrlRepeatsPerMeter->get(); F32 repeats_per_meter = (F32)self->getChild("rptctrl")->getValue().asReal();//self->mCtrlRepeatsPerMeter->get(); LLSelectMgr::getInstance()->selectionTexScaleAutofit( repeats_per_meter ); } 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::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::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); } // TODO: I don't know who put these in or what these are for??? void LLPanelFace::setMediaURL(const std::string& url) { } void LLPanelFace::setMediaType(const std::string& mime_type) { } // static void LLPanelFace::onCommitPlanarAlign(LLUICtrl* ctrl, void* userdata) { LLPanelFace* self = (LLPanelFace*) userdata; self->getState(); self->sendTextureInfo(); } void LLPanelFace::onTextureSelectionChanged(LLInventoryItem* itemp) { LLTextureCtrl* texture_ctrl = getChild("texture 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"); } } }