diff options
Diffstat (limited to 'indra/newview/llpanelface.cpp')
-rw-r--r-- | indra/newview/llpanelface.cpp | 198 |
1 files changed, 175 insertions, 23 deletions
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 36713f65bd..bce496cbad 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -2,31 +2,25 @@ * @file llpanelface.cpp * @brief Panel in the tools floater for editing face textures, colors, etc. * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * 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. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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 * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -48,6 +42,7 @@ #include "llcolorswatch.h" #include "llcombobox.h" #include "lldrawpoolbump.h" +#include "llface.h" #include "lllineeditor.h" #include "llmediaentry.h" #include "llresmgr.h" @@ -81,6 +76,7 @@ BOOL LLPanelFace::postBuild() 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); @@ -365,6 +361,93 @@ 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; + } + + 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 == 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) @@ -376,8 +459,26 @@ struct LLPanelFaceSendFunctor : public LLSelectedObjectFunctor void LLPanelFace::sendTextureInfo() { - LLPanelFaceSetTEFunctor setfunc(this); - LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc); + if ((bool)childGetValue("checkbox planar align").asBoolean()) + { + struct f1 : public LLSelectedTEGetFunctor<LLFace *> + { + 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); @@ -503,6 +604,44 @@ void LLPanelFace::getState() } } + + // planar align + bool align_planar = false; + bool identical_planar_aligned = false; + bool is_planar = false; + { + LLCheckBoxCtrl* cb_planar_align = getChild<LLCheckBoxCtrl>("checkbox planar align"); + align_planar = (cb_planar_align && cb_planar_align->get()); + struct f1 : public LLSelectedTEGetFunctor<bool> + { + 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 *> + { + 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; @@ -514,6 +653,7 @@ void LLPanelFace::getState() } } func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, scale_s ); + identical = align_planar ? identical_planar_aligned : identical; getChild<LLUICtrl>("TexScaleU")->setValue(editable ? llabs(scale_s) : 0); getChild<LLUICtrl>("TexScaleU")->setTentative(LLSD((BOOL)(!identical))); getChildView("TexScaleU")->setEnabled(editable); @@ -532,6 +672,7 @@ void LLPanelFace::getState() } } func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, scale_t ); + identical = align_planar ? identical_planar_aligned : identical; getChild<LLUICtrl>("TexScaleV")->setValue(llabs(editable ? llabs(scale_t) : 0)); getChild<LLUICtrl>("TexScaleV")->setTentative(LLSD((BOOL)(!identical))); @@ -553,6 +694,7 @@ void LLPanelFace::getState() } } func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, offset_s ); + identical = align_planar ? identical_planar_aligned : identical; getChild<LLUICtrl>("TexOffsetU")->setValue(editable ? offset_s : 0); getChild<LLUICtrl>("TexOffsetU")->setTentative(!identical); getChildView("TexOffsetU")->setEnabled(editable); @@ -568,6 +710,7 @@ void LLPanelFace::getState() } } func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, offset_t ); + identical = align_planar ? identical_planar_aligned : identical; getChild<LLUICtrl>("TexOffsetV")->setValue(editable ? offset_t : 0); getChild<LLUICtrl>("TexOffsetV")->setTentative(!identical); getChildView("TexOffsetV")->setEnabled(editable); @@ -584,6 +727,7 @@ void LLPanelFace::getState() } } func; identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, rotation ); + identical = align_planar ? identical_planar_aligned : identical; getChild<LLUICtrl>("TexRot")->setValue(editable ? rotation * RAD_TO_DEG : 0); getChild<LLUICtrl>("TexRot")->setTentative(!identical); getChildView("TexRot")->setEnabled(editable); @@ -999,3 +1143,11 @@ void LLPanelFace::setMediaType(const std::string& mime_type) { } +// static +void LLPanelFace::onCommitPlanarAlign(LLUICtrl* ctrl, void* userdata) +{ + LLPanelFace* self = (LLPanelFace*) userdata; + self->getState(); + self->sendTextureInfo(); +} + |