diff --git a/indra/llprimitive/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp index 597f07849..0db75a0e8 100644 --- a/indra/llprimitive/lltextureentry.cpp +++ b/indra/llprimitive/lltextureentry.cpp @@ -545,7 +545,7 @@ S32 LLTextureEntry::setMaterialID(const LLMaterialID& pMaterialID) { mMaterialUpdatePending = true; mMaterialID = pMaterialID; - return TEM_CHANGE_NONE; + return TEM_CHANGE_TEXTURE; } mMaterialUpdatePending = false; diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h index cbd8665d3..19edcaa27 100644 --- a/indra/llprimitive/lltextureentry.h +++ b/indra/llprimitive/lltextureentry.h @@ -38,7 +38,7 @@ const S32 TEM_CHANGE_NONE = 0x0; const S32 TEM_CHANGE_COLOR = 0x1; const S32 TEM_CHANGE_TEXTURE = 0x2; -const S32 TEM_CHANGE_MEDIA = 0x4; //Currently doesn't do anything, (not that TEM_CHANGE_TEXTURE either) +const S32 TEM_CHANGE_MEDIA = 0x4; const S32 TEM_INVALID = 0x8; const S32 TEM_BUMPMAP_COUNT = 32; @@ -133,7 +133,13 @@ public: virtual const LLUUID &getID() const { return mID; } const LLColor4 &getColor() const { return mColor; } void getScale(F32 *s, F32 *t) const { *s = mScaleS; *t = mScaleT; } + F32 getScaleS() const { return mScaleS; } + F32 getScaleT() const { return mScaleT; } + void getOffset(F32 *s, F32 *t) const { *s = mOffsetS; *t = mOffsetT; } + F32 getOffsetS() const { return mOffsetS; } + F32 getOffsetT() const { return mOffsetT; } + F32 getRotation() const { return mRotation; } void getRotation(F32 *theta) const { *theta = mRotation; } @@ -144,7 +150,7 @@ public: U8 getBumpShinyFullbright() const { return mBump; } U8 getMediaFlags() const { return mMediaFlags & TEM_MEDIA_MASK; } - U8 getTexGen() const { return mMediaFlags & TEM_TEX_GEN_MASK; } + LLTextureEntry::e_texgen getTexGen() const { return LLTextureEntry::e_texgen(mMediaFlags & TEM_TEX_GEN_MASK); } U8 getMediaTexGen() const { return mMediaFlags; } F32 getGlow() const { return mGlow; } const LLMaterialID& getMaterialID() const { return mMaterialID; }; diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 64d003f0b..7c8e1afeb 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -171,9 +171,10 @@ LLView* LLComboBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory * LLXMLNodePtr child; for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) { - if (child->hasName("combo_item")) + if (child->hasName("combo_item") || child->hasName("combo_box.item")) { std::string label = child->getTextContents(); + child->getAttributeString("label", label); std::string value = label; child->getAttributeString("value", value); diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 7761f5eb8..19f348e9b 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -3306,50 +3306,16 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y) menu->getParent()->sendChildToFront(menu); } -//----------------------------------------------------------------------------- -// class LLPieMenuBranch -// A branch to another pie menu -//----------------------------------------------------------------------------- -class LLPieMenuBranch : public LLMenuItemGL -{ -public: - LLPieMenuBranch(const std::string& name, const std::string& label, LLPieMenu* branch); - - virtual LLXMLNodePtr getXML(bool save_children = true) const; - - // called to rebuild the draw label - virtual void buildDrawLabel( void ); - - virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) - { - LLMenuItemGL::handleMouseUp(x,y,mask); - return TRUE; - } - - // doIt() - do the primary funcationality of the menu item. - virtual void doIt( void ); - - LLPieMenu* getBranch() { return mBranch; } - -protected: - LLPieMenu* mBranch; -}; - -const F32 PIE_MENU_WIDTH = 190; -const F32 PIE_MENU_HEIGHT = 190; - -LLPieMenuBranch::LLPieMenuBranch(const std::string& name, - const std::string& label, - LLPieMenu* branch) +LLContextMenuBranch::LLContextMenuBranch(const std::string& name, const std::string& label, LLContextMenu* branch) : LLMenuItemGL( name, label, KEY_NONE, MASK_NONE ), mBranch( branch ) { - mBranch->hide(FALSE); + mBranch->hide(); mBranch->setParentMenuItem(this); } // virtual -LLXMLNodePtr LLPieMenuBranch::getXML(bool save_children) const +LLXMLNodePtr LLContextMenuBranch::getXML(bool save_children) const { if (mBranch) { @@ -3360,7 +3326,7 @@ LLXMLNodePtr LLPieMenuBranch::getXML(bool save_children) const } // called to rebuild the draw label -void LLPieMenuBranch::buildDrawLabel( void ) +void LLContextMenuBranch::buildDrawLabel( void ) { { // default enablement is this -- if any of the subitems are @@ -3386,62 +3352,72 @@ void LLPieMenuBranch::buildDrawLabel( void ) std::string st = mDrawAccelLabel; appendAcceleratorString( st ); mDrawAccelLabel = st; - - // No special branch suffix - mDrawBranchLabel.clear(); + + // Singu Note: This is meaningless to pies + mDrawBranchLabel = LLMenuGL::BRANCH_SUFFIX; +} + +void LLContextMenuBranch::showSubMenu() +{ + if (getDrawTextDisabled()) return; // Singu Note: Don't open disabled submenus! + S32 center_x; + S32 center_y; + static LLUICachedControl context("LiruUseContextMenus", false); + if (context) // Use the edge of this item + { + localPointToScreen(getRect().getWidth(), getRect().getHeight(), ¢er_x, ¢er_y); + } + else // Use the center of the parent pie menu, and hide it + { + LLContextMenu* parent = static_cast(getParent()); + const LLRect& rect = parent->getRect(); + parent->localPointToScreen(rect.getWidth() / 2, rect.getHeight() / 2, ¢er_x, ¢er_y); + parent->hide(); + } + mBranch->show(center_x, center_y, context); } // doIt() - do the primary funcationality of the menu item. -void LLPieMenuBranch::doIt( void ) +void LLContextMenuBranch::doIt( void ) { - LLPieMenu *parent = (LLPieMenu *)getParent(); - - LLRect rect = parent->getRect(); - S32 center_x; - S32 center_y; - parent->localPointToScreen(rect.getWidth() / 2, rect.getHeight() / 2, ¢er_x, ¢er_y); - - parent->hide(FALSE); - mBranch->show( center_x, center_y, FALSE ); + showSubMenu(); } +void LLContextMenuBranch::setHighlight( BOOL highlight ) +{ + if (highlight == getHighlight()) return; + LLMenuItemGL::setHighlight(highlight); + + // Singu Note: Pie menus show subs only on click + static LLUICachedControl context("LiruUseContextMenus", false); + if (!context) return; + + if (highlight) + { + showSubMenu(); + } + else + { + mBranch->hide(); + } +} + +/////////////////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------------- -// class LLPieMenu -// A circular menu of items, icons, etc. +// class LLContextMenu +// A context menu //----------------------------------------------------------------------------- -LLPieMenu::LLPieMenu(const std::string& name, const std::string& label) -: LLMenuGL(name, label), - mFirstMouseDown(FALSE), - mUseInfiniteRadius(FALSE), - mHoverItem(NULL), - mHoverThisFrame(FALSE), +LLContextMenu::LLContextMenu(const std::string& name, const std::string& label) +: LLMenuGL(name, label.empty() ? name : label), mHoveredAnyItem(FALSE), - mOuterRingAlpha(1.f), - mCurRadius(0.f), - mRightMouseDown(FALSE) -{ - setRect(LLRect(0,PIE_MENU_HEIGHT,PIE_MENU_WIDTH,0)); + mHoverItem(NULL) +{ + //setBackgroundVisible(TRUE); LLMenuGL::setVisible(FALSE); } -LLPieMenu::LLPieMenu(const std::string& name) -: LLMenuGL(name, name), - mFirstMouseDown(FALSE), - mUseInfiniteRadius(FALSE), - mHoverItem(NULL), - mHoverThisFrame(FALSE), - mHoveredAnyItem(FALSE), - mOuterRingAlpha(1.f), - mCurRadius(0.f), - mRightMouseDown(FALSE) -{ - setRect(LLRect(0,PIE_MENU_HEIGHT,PIE_MENU_WIDTH,0)); - LLMenuGL::setVisible(FALSE); -} - - // virtual -LLXMLNodePtr LLPieMenu::getXML(bool save_children) const +LLXMLNodePtr LLContextMenu::getXML(bool save_children) const { LLXMLNodePtr node = LLMenuGL::getXML(); @@ -3450,22 +3426,34 @@ LLXMLNodePtr LLPieMenu::getXML(bool save_children) const return node; } -void LLPieMenu::initXML(LLXMLNodePtr node, LLView *context, LLUICtrlFactory *factory) +void LLContextMenu::initXML(LLXMLNodePtr node, LLView *context, LLUICtrlFactory *factory, bool is_context) { LLXMLNodePtr child; for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) { if (child->hasName(LL_PIE_MENU_TAG)) { - // SUBMENU - std::string name("menu"); - child->getAttributeString("name", name); - std::string label(name); - child->getAttributeString("label", label); + // In context menus, more submenu is just an extension of the parent + bool more(false); + if (is_context && child->getAttribute_bool("more", more) && more) + { + //addSeparator(); // Singu Note: perhaps a separator (above) is in order, too? + initXML(child, context, factory, true); + //addSeparator(); // Singu Note: perhaps a separator (below) is in order, too? + } + else + { + // SUBMENU + std::string name("menu"); + child->getAttributeString("name", name); + std::string label(name); + child->getAttributeString("label", label); - LLPieMenu *submenu = new LLPieMenu(name, label); - appendPieMenu(submenu); - submenu->initXML(child, context, factory); + // Singu Note: Pie Submenus are denoted with >, while context submenus have an obvious arrow at the end + LLContextMenu* submenu = is_context ? new LLContextMenu(name, label) : new LLPieMenu(name, label + " >"); + appendContextSubMenu(submenu); + submenu->initXML(child, context, factory, is_context); + } } else { @@ -3474,51 +3462,132 @@ void LLPieMenu::initXML(LLXMLNodePtr node, LLView *context, LLUICtrlFactory *fac } } -bool LLPieMenu::addChild(LLView* view, S32 tab_group) -{ - if(LLMenuGL::addChild(view, tab_group)) - { - LLMenuItemSeparatorGL* sep = dynamic_cast(view); - if(sep) - sep->setVisible(false); - return true; - } - return false; -} - // virtual -void LLPieMenu::setVisible(BOOL visible) +void LLContextMenu::setVisible(BOOL visible) { if (!visible) { - hide(FALSE); + hide(); } } -BOOL LLPieMenu::handleHover( S32 x, S32 y, MASK mask ) +void LLContextMenu::show(S32 x, S32 y, bool context) { - // This is mostly copied from the llview class, but it continues - // the hover handle code after a hover handler has been found. - BOOL handled = FALSE; - - // If we got a hover event, we've already moved the cursor - // for any menu shifts, so subsequent mouseup messages will be in the - // correct position. No need to correct them. - //mShiftHoriz = 0; - //mShiftVert = 0; - - // release mouse capture after short period of visibility if we're using a finite boundary - // so that right click outside of boundary will trigger new pie menu - if (hasMouseCapture() && - !mRightMouseDown && - mShrinkBorderTimer.getStarted() && - mShrinkBorderTimer.getElapsedTimeF32() >= PIE_SHRINK_TIME) + if (getChildList()->empty()) { - gFocusMgr.setMouseCapture(NULL); - mUseInfiniteRadius = FALSE; + // nothing to show, so abort + return; + } + // Save click point for detecting cursor moves before mouse-up. + // Must be in local coords to compare with mouseUp events. + // If the mouse doesn't move, the menu will stay open ala the Mac. + // See also LLMenuGL::showPopup() + LLMenuHolderGL::sContextMenuSpawnPos.set(x,y); + + arrangeAndClear(); + + S32 width = getRect().getWidth(); + S32 height = getRect().getHeight(); + const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getMenuRect(); + LLView* parent_view = getParent(); + + // Singu TODO: These could probably be combined a bit more. + if (context) // Singu Note: Determine menu repositioning behavior based on menu type + { + // Open upwards if menu extends past bottom + if (y - height < menu_region_rect.mBottom) + { + if (getParentMenuItem()) + { + y += height - getParentMenuItem()->getNominalHeight(); + } + else + { + y += height; + } + } + + // Open out to the left if menu extends past right edge + if (x + width > menu_region_rect.mRight) + { + if (getParentMenuItem()) + { + x -= getParentMenuItem()->getRect().getWidth() + width; + } + else + { + x -= width; + } + } + + S32 local_x, local_y; + parent_view->screenPointToLocal(x, y, &local_x, &local_y); + + LLRect rect; + rect.setLeftTopAndSize(local_x, local_y, width, height); + setRect(rect); + } + else + { + S32 local_x, local_y; + parent_view->screenPointToLocal(x, y, &local_x, &local_y); + + LLRect rect; + rect.setCenterAndSize(local_x, local_y, width, height); + setRect(rect); + if (!menu_region_rect.contains(rect)) // Adjust the pie rectangle to keep it on screen + { + S32 trans[2]={0,0}; + if (rect.mLeft < menu_region_rect.mLeft) + { + trans[0] = menu_region_rect.mLeft - rect.mLeft; + } + else if (rect.mRight > menu_region_rect.mRight) + { + trans[0] = menu_region_rect.mRight - rect.mRight; + } + if (rect.mBottom < menu_region_rect.mBottom) + { + trans[1] = menu_region_rect.mBottom - rect.mBottom; + } + else if (rect.mTop > menu_region_rect.mTop) + { + trans[1] = menu_region_rect.mTop - rect.mTop; + } + setRect(rect.translate(trans[0],trans[1])); + LLUI::setMousePositionLocal(getParent(),rect.getCenterX(), rect.getCenterY()); + } } - LLMenuItemGL *item = pieItemFromXY( x, y ); + arrange(); + LLView::setVisible(TRUE); +} + +void LLContextMenu::hide() +{ + if (!getVisible()) return; + + LLView::setVisible(FALSE); + + if (mHoverItem) + { + mHoverItem->setHighlight( FALSE ); + mHoverItem = NULL; + } +} + +BOOL LLContextMenu::handleHover( S32 x, S32 y, MASK mask ) +{ + LLMenuGL::handleHover(x, y, mask); + + LLMenuItemGL* item = getHighlightedItem(); + + return handleHoverOver(item, x, y); +} + +BOOL LLContextMenu::handleHoverOver(LLMenuItemGL* item, S32 x, S32 y) +{ + BOOL handled = FALSE; if (item && item->getEnabled()) { @@ -3534,37 +3603,6 @@ BOOL LLPieMenu::handleHover( S32 x, S32 y, MASK mask ) } mHoverItem = item; mHoverItem->setHighlight( TRUE ); - - switch(pieItemIndexFromXY(x, y)) - { - case 0: - make_ui_sound("UISndPieMenuSliceHighlight0"); - break; - case 1: - make_ui_sound("UISndPieMenuSliceHighlight1"); - break; - case 2: - make_ui_sound("UISndPieMenuSliceHighlight2"); - break; - case 3: - make_ui_sound("UISndPieMenuSliceHighlight3"); - break; - case 4: - make_ui_sound("UISndPieMenuSliceHighlight4"); - break; - case 5: - make_ui_sound("UISndPieMenuSliceHighlight5"); - break; - case 6: - make_ui_sound("UISndPieMenuSliceHighlight6"); - break; - case 7: - make_ui_sound("UISndPieMenuSliceHighlight7"); - break; - default: - make_ui_sound("UISndPieMenuSliceHighlight0"); - break; - } } mHoveredAnyItem = TRUE; } @@ -3585,11 +3623,170 @@ BOOL LLPieMenu::handleHover( S32 x, S32 y, MASK mask ) handled = TRUE; } - mHoverThisFrame = TRUE; + return handled; +} + +// handleMouseUp and handleMouseDown are handled by LLMenuGL + + +BOOL LLContextMenu::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + BOOL handled = FALSE; + + // The click was somewhere within our rectangle + LLMenuItemGL* item = getHighlightedItem(); + + S32 local_x = x - getRect().mLeft; + S32 local_y = y - getRect().mBottom; + + BOOL clicked_in_menu = pointInView(local_x, local_y); + + // grab mouse if right clicking anywhere within pie (even deadzone in middle), to detect drag outside of pie + if (clicked_in_menu) + { + // capture mouse cursor as if on initial menu show + handled = TRUE; + } + + if (item) + { + // lie to the item about where the click happened + // to make sure it's within the item's rectangle + if (item->handleMouseDown( 0, 0, mask )) + { + handled = TRUE; + } + } return handled; } +BOOL LLContextMenu::handleRightMouseUp( S32 x, S32 y, MASK mask ) +{ + S32 local_x = x - getRect().mLeft; + S32 local_y = y - getRect().mBottom; + + if (!mHoveredAnyItem && !pointInView(local_x, local_y)) + { + sMenuContainer->hideMenus(); + return TRUE; + } + + + BOOL result = handleMouseUp( x, y, mask ); + mHoveredAnyItem = FALSE; + + return result; +} + +bool LLContextMenu::addChild(LLView* view, S32 tab_group) +{ + if (LLContextMenu* context = dynamic_cast(view)) + return appendContextSubMenu(context); + if (LLMenuItemGL* item = dynamic_cast(view)) + return append(item); + if (LLMenuGL* menu = dynamic_cast(view)) + return appendMenu(menu); + return false; +} + + +BOOL LLContextMenu::appendContextSubMenu(LLContextMenu* menu) +{ + if (menu == this) + { + llerrs << "Can't attach a context menu to itself" << llendl; + } + LLContextMenuBranch* item = new LLContextMenuBranch(menu->getName(), menu->getLabel(), menu); + getParent()->addChild(item->getBranch()); + return append(item); +} + +const S32 PIE_MENU_HEIGHT = 190; +const S32 PIE_MENU_WIDTH = 190; + +//----------------------------------------------------------------------------- +// class LLPieMenu +// A circular menu of items, icons, etc. +//----------------------------------------------------------------------------- +LLPieMenu::LLPieMenu(const std::string& name, const std::string& label) +: LLContextMenu(name, label), + mFirstMouseDown(FALSE), + mUseInfiniteRadius(FALSE), + mHoverThisFrame(FALSE), + mOuterRingAlpha(1.f), + mCurRadius(0.f), + mRightMouseDown(FALSE) +{ + setRect(LLRect(0,PIE_MENU_HEIGHT,PIE_MENU_WIDTH,0)); +} + +// Separators on pie menus are invisible +bool LLPieMenu::addChild(LLView* view, S32 tab_group) +{ + if (LLContextMenu::addChild(view, tab_group)) + { + LLMenuItemSeparatorGL* sep = dynamic_cast(view); + if(sep) + sep->setVisible(false); + return true; + } + return false; +} + +BOOL LLPieMenu::handleHover( S32 x, S32 y, MASK mask ) +{ + // release mouse capture after short period of visibility if we're using a finite boundary + // so that right click outside of boundary will trigger new pie menu + if (hasMouseCapture() && + !mRightMouseDown && + mShrinkBorderTimer.getStarted() && + mShrinkBorderTimer.getElapsedTimeF32() >= PIE_SHRINK_TIME) + { + gFocusMgr.setMouseCapture(NULL); + mUseInfiniteRadius = FALSE; + } + + mHoverThisFrame = TRUE; + + LLMenuItemGL* item = pieItemFromXY( x, y ); + + if (item && item->getEnabled() && item != mHoverItem) + { + switch(pieItemIndexFromXY(x, y)) + { + case 0: + make_ui_sound("UISndPieMenuSliceHighlight0"); + break; + case 1: + make_ui_sound("UISndPieMenuSliceHighlight1"); + break; + case 2: + make_ui_sound("UISndPieMenuSliceHighlight2"); + break; + case 3: + make_ui_sound("UISndPieMenuSliceHighlight3"); + break; + case 4: + make_ui_sound("UISndPieMenuSliceHighlight4"); + break; + case 5: + make_ui_sound("UISndPieMenuSliceHighlight5"); + break; + case 6: + make_ui_sound("UISndPieMenuSliceHighlight6"); + break; + case 7: + make_ui_sound("UISndPieMenuSliceHighlight7"); + break; + default: + make_ui_sound("UISndPieMenuSliceHighlight0"); + break; + } + } + return handleHoverOver(item, x, y); +} + BOOL LLPieMenu::handleMouseDown( S32 x, S32 y, MASK mask ) { BOOL handled = FALSE; @@ -3688,7 +3885,7 @@ BOOL LLPieMenu::handleMouseUp( S32 x, S32 y, MASK mask ) if (item->getEnabled()) { handled = item->handleMouseUp( 0, 0, mask ); - hide(TRUE); + hide(); } } else if (!mRightMouseDown) @@ -3853,24 +4050,9 @@ BOOL LLPieMenu::append(LLMenuItemGL *item) BOOL LLPieMenu::addSeparator() { LLMenuItemGL* separator = new LLMenuItemBlankGL(); - separator->setFont( LLFontGL::getFontSansSerifSmall() ); return append( separator ); } - -BOOL LLPieMenu::appendPieMenu(LLPieMenu *menu) -{ - if (menu == this) - { - llerrs << "Can't attach a pie menu to itself" << llendl; - } - LLPieMenuBranch *item; - item = new LLPieMenuBranch(menu->getName(), menu->getLabel(), menu); - getParent()->addChild(item->getBranch()); - item->setFont( LLFontGL::getFontSansSerifSmall() ); - return append( item ); -} - // virtual void LLPieMenu::arrange() { @@ -4006,47 +4188,11 @@ S32 LLPieMenu::pieItemIndexFromXY(S32 x, S32 y) return which; } -void LLPieMenu::show(S32 x, S32 y, BOOL mouse_down) + +// virtual +void LLPieMenu::show(S32 x, S32 y, bool mouse_down) { - S32 width = getRect().getWidth(); - S32 height = getRect().getHeight(); - - const LLRect menu_region_rect = LLMenuGL::sMenuContainer->getMenuRect(); - - LLView* parent_view = getParent(); - - S32 local_x, local_y; - parent_view->screenPointToLocal(x, y, &local_x, &local_y); - - LLRect rect; - rect.setCenterAndSize(local_x, local_y, width, height); - setRect(rect); - - arrange(); - - // Adjust the pie rectangle to keep it on screen - if(!menu_region_rect.contains(rect)) - { - S32 trans[2]={0,0}; - if (rect.mLeft < menu_region_rect.mLeft) - { - trans[0] = menu_region_rect.mLeft - rect.mLeft; - } - else if (rect.mRight > menu_region_rect.mRight) - { - trans[0] = menu_region_rect.mRight - rect.mRight; - } - if (rect.mBottom < menu_region_rect.mBottom) - { - trans[1] = menu_region_rect.mBottom - rect.mBottom; - } - else if (rect.mTop > menu_region_rect.mTop) - { - trans[1] = menu_region_rect.mTop - rect.mTop; - } - setRect(rect.translate(trans[0],trans[1])); - LLUI::setMousePositionLocal(getParent(),rect.getCenterX(), rect.getCenterY()); - } + LLContextMenu::show(x, y, false); // *FIX: what happens when mouse buttons reversed? mRightMouseDown = mouse_down; @@ -4059,8 +4205,6 @@ void LLPieMenu::show(S32 x, S32 y, BOOL mouse_down) make_ui_sound("UISndPieMenuAppear"); } - LLView::setVisible(TRUE); - // we want all mouse events in case user does quick right click again off of pie menu // rectangle, to support gestural menu traversal gFocusMgr.setMouseCapture(this); @@ -4075,16 +4219,10 @@ void LLPieMenu::show(S32 x, S32 y, BOOL mouse_down) } } -void LLPieMenu::hide(BOOL item_selected) +// virtual +void LLPieMenu::hide() { - if (!getVisible()) return; - - if (mHoverItem) - { - mHoverItem->setHighlight( FALSE ); - mHoverItem = NULL; - } - + LLContextMenu::hide(); make_ui_sound("UISndPieMenuHide"); mFirstMouseDown = FALSE; @@ -4092,8 +4230,6 @@ void LLPieMenu::hide(BOOL item_selected) mUseInfiniteRadius = FALSE; mHoveredAnyItem = FALSE; - LLView::setVisible(FALSE); - gFocusMgr.setMouseCapture(NULL); } diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 07effab8d..cac496497 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -685,29 +685,59 @@ private: +//----------------------------------------------------------------------------- +// class LLContextMenu +// A context menu +//----------------------------------------------------------------------------- +class LLContextMenu +: public LLMenuGL +{ +public: + LLContextMenu(const std::string& name, const std::string& label = ""); + + virtual LLXMLNodePtr getXML(bool save_children = true) const; + void initXML(LLXMLNodePtr node, LLView* context, LLUICtrlFactory* factory, bool is_context); + +public: + virtual ~LLContextMenu() {} + + // LLView Functionality + // can't set visibility directly, must call show or hide + virtual void setVisible(BOOL visible); + + virtual void show(S32 x, S32 y, bool context = true); + virtual void hide(); + + virtual BOOL handleHover( S32 x, S32 y, MASK mask ); + BOOL handleHoverOver(LLMenuItemGL* item, S32 x, S32 y); // Singu Note: Unify common functionality between Pie and Context hover behaviors + virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleRightMouseUp( S32 x, S32 y, MASK mask ); + + virtual bool addChild(LLView* view, S32 tab_group = 0); + + BOOL appendContextSubMenu(LLContextMenu* menu); + +protected: + BOOL mHoveredAnyItem; + LLMenuItemGL* mHoverItem; +}; + //----------------------------------------------------------------------------- // class LLPieMenu // A circular menu of items, icons, etc. //----------------------------------------------------------------------------- class LLPieMenu -: public LLMenuGL +: public LLContextMenu { public: - LLPieMenu(const std::string& name, const std::string& label); - LLPieMenu(const std::string& name); + LLPieMenu(const std::string& name, const std::string& label = ""); virtual ~LLPieMenu() {} - virtual LLXMLNodePtr getXML(bool save_children = true) const; - void initXML(LLXMLNodePtr node, LLView *context, LLUICtrlFactory *factory); - // LLView Functionality // hide separators. they are added to 'pad' in empty cells. virtual bool addChild(LLView* view, S32 tab_group = 0); - // can't set visibility directly, must call show or hide - virtual void setVisible(BOOL visible); - virtual BOOL handleHover( S32 x, S32 y, MASK mask ); virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); @@ -721,34 +751,57 @@ private: public: virtual BOOL addSeparator(); - BOOL appendPieMenu(LLPieMenu *menu); - virtual void arrange( void ); // Display the menu centered on this point on the screen. - void show(S32 x, S32 y, BOOL mouse_down); - void hide(BOOL item_selected); + /*virtual*/ void show(S32 x, S32 y, bool mouse_down = true); + /*virtual*/ void hide(); private: LLMenuItemGL *pieItemFromXY(S32 x, S32 y); S32 pieItemIndexFromXY(S32 x, S32 y); - // These cause menu items to be spuriously selected by right-clicks - // near the window edge at low frame rates. I don't think they are - // needed unless you shift the menu position in the draw() function. JC - //S32 mShiftHoriz; // non-zero if menu had to shift this frame - //S32 mShiftVert; // non-zero if menu had to shift this frame BOOL mFirstMouseDown; // true from show until mouse up BOOL mUseInfiniteRadius; // allow picking pie menu items anywhere outside of center circle - LLMenuItemGL* mHoverItem; BOOL mHoverThisFrame; - BOOL mHoveredAnyItem; LLFrameTimer mShrinkBorderTimer; F32 mOuterRingAlpha; // for rendering pie menus as both bounded and unbounded F32 mCurRadius; BOOL mRightMouseDown; }; +//----------------------------------------------------------------------------- +// class LLContextMenuBranch +// A branch to another context menu +//----------------------------------------------------------------------------- +class LLContextMenuBranch : public LLMenuItemGL +{ +public: + LLContextMenuBranch(const std::string& name, const std::string& label, LLContextMenu* branch); + + virtual LLXMLNodePtr getXML(bool save_children = true) const; + + // called to rebuild the draw label + virtual void buildDrawLabel( void ); + + virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask) + { + LLMenuItemGL::handleMouseUp(x,y,mask); + return TRUE; + } + + // doIt() - do the primary funcationality of the menu item. + virtual void doIt( void ); + + LLContextMenu* getBranch() { return mBranch; } + void setHighlight( BOOL highlight ); + +protected: + void showSubMenu(); + + LLContextMenu* mBranch; +}; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLMenuBarGL diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index c6ff2fa03..66d09954d 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -530,11 +530,13 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *f void LLPanel::initChildrenXML(LLXMLNodePtr node, LLUICtrlFactory* factory) { + std::string kidstring(node->getName()->mString); + kidstring += ".string"; LLXMLNodePtr child; for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) { // look for string declarations for programmatic text - if (child->hasName("string")) + if (child->hasName("string") || child->hasName(kidstring)) { std::string string_name; child->getAttributeString("name", string_name); diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index d5bb963d4..9cd8aa9d8 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -446,7 +446,7 @@ LLMenuGL *LLUICtrlFactory::buildMenu(const std::string &filename, LLView* parent //----------------------------------------------------------------------------- // buildMenu() //----------------------------------------------------------------------------- -LLPieMenu *LLUICtrlFactory::buildPieMenu(const std::string &filename, LLView* parentp) +LLContextMenu* LLUICtrlFactory::buildContextMenu(const std::string& filename, LLView* parentp) { LLXMLNodePtr root; @@ -465,9 +465,10 @@ LLPieMenu *LLUICtrlFactory::buildPieMenu(const std::string &filename, LLView* pa std::string name("menu"); root->getAttributeString("name", name); - LLPieMenu *menu = new LLPieMenu(name); + static LLUICachedControl context("LiruUseContextMenus", false); + LLContextMenu* menu = context ? new LLContextMenu(name) : new LLPieMenu(name); parentp->addChild(menu); - menu->initXML(root, parentp, this); + menu->initXML(root, parentp, this, context); if (LLUI::sShowXUINames) { diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index 3fac2bdb5..b3ef3aeeb 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -106,7 +106,7 @@ public: bool builtPanel(LLPanel* panelp) {return mBuiltPanels.find(panelp->getHandle()) != mBuiltPanels.end();} class LLMenuGL *buildMenu(const std::string &filename, LLView* parentp); - class LLPieMenu *buildPieMenu(const std::string &filename, LLView* parentp); + class LLContextMenu* buildContextMenu(const std::string& filename, LLView* parentp); // Does what you want for LLFloaters and LLPanels // Returns 0 on success diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ba914186f..98366cb6e 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -846,6 +846,17 @@ Found in Advanced->Rendering->Info Displays Value 0 + LiruUseContextMenus + + Comment + Use context menus instead of the default pie menus we all know and love. + Persist + 1 + Type + Boolean + Value + 0 + SLBShowFPS Comment @@ -914,6 +925,17 @@ Found in Advanced->Rendering->Info Displays Value 0 + FSSynchronizeTextureMaps + + Comment + Align texture maps (texture, bumpy, shiny) across the faces of a prim + Persist + 1 + Type + Boolean + Value + 1 + InstantMessageLogPathAnyAccount Comment @@ -5681,6 +5703,39 @@ This should be as low as possible, but too low may break functionality Value 0 + DefaultBlankNormalTexture + + Comment + Texture used as 'Blank' in texture picker for normal map. (UUID texture reference) + Persist + 1 + Type + String + Value + 5b53359e-59dd-d8a2-04c3-9e65134da47a + + DefaultObjectNormalTexture + + Comment + Texture used as 'Default' in texture picker for normal map. (UUID texture reference) + Persist + 1 + Type + String + Value + 85f28839-7a1c-b4e3-d71d-967792970a7b + + DefaultObjectSpecularTexture + + Comment + Texture used as 'Default' in texture picker for specular map. (UUID texture reference) + Persist + 1 + Type + String + Value + 87e0e8f7-8729-1ea8-cfc9-8915773009db + DefaultObjectTexture Comment diff --git a/indra/newview/app_settings/shaders/class1/interface/highlightNormV.glsl b/indra/newview/app_settings/shaders/class1/interface/highlightNormV.glsl new file mode 100644 index 000000000..947c2b006 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/highlightNormV.glsl @@ -0,0 +1,42 @@ +/** + * @file highlightV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, 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$ + */ + +uniform mat4 texture_matrix0; +uniform mat4 modelview_projection_matrix; + +ATTRIBUTE vec3 position; +ATTRIBUTE vec2 texcoord0; +ATTRIBUTE vec2 texcoord1; +ATTRIBUTE vec2 texcoord2; + +VARYING vec2 vary_texcoord0; + +void main() +{ + //transform vertex + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + vary_texcoord0 = (texture_matrix0 * vec4(texcoord1,0,1)).xy; +} + diff --git a/indra/newview/app_settings/shaders/class1/interface/highlightSpecV.glsl b/indra/newview/app_settings/shaders/class1/interface/highlightSpecV.glsl new file mode 100644 index 000000000..c5d102b73 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/highlightSpecV.glsl @@ -0,0 +1,42 @@ +/** + * @file highlightV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, 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$ + */ + +uniform mat4 texture_matrix0; +uniform mat4 modelview_projection_matrix; + +ATTRIBUTE vec3 position; +ATTRIBUTE vec2 texcoord0; +ATTRIBUTE vec2 texcoord1; +ATTRIBUTE vec2 texcoord2; + +VARYING vec2 vary_texcoord0; + +void main() +{ + //transform vertex + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + vary_texcoord0 = (texture_matrix0 * vec4(texcoord2,0,1)).xy; +} + diff --git a/indra/newview/ascentprefssys.cpp b/indra/newview/ascentprefssys.cpp index 41e17241e..c287fea3e 100644 --- a/indra/newview/ascentprefssys.cpp +++ b/indra/newview/ascentprefssys.cpp @@ -222,6 +222,7 @@ void LLPrefsAscentSys::refreshValues() mEnableClassicClouds = gSavedSettings.getBOOL("SkyUseClassicClouds"); mSpeedRez = gSavedSettings.getBOOL("SpeedRez"); mSpeedRezInterval = gSavedSettings.getU32("SpeedRezInterval"); + mUseContextMenus = gSavedSettings.getBOOL("LiruUseContextMenus"); mUseWebProfiles = gSavedSettings.getBOOL("UseWebProfiles"); mUseWebSearch = gSavedSettings.getBOOL("UseWebSearch"); @@ -377,6 +378,7 @@ void LLPrefsAscentSys::cancel() gSavedSettings.setBOOL("SkyUseClassicClouds", mEnableClassicClouds); gSavedSettings.setBOOL("SpeedRez", mSpeedRez); gSavedSettings.setU32("SpeedRezInterval", mSpeedRezInterval); + gSavedSettings.setBOOL("LiruUseContextMenus", mUseContextMenus); gSavedSettings.setBOOL("UseWebProfiles", mUseWebProfiles); gSavedSettings.setBOOL("UseWebSearch", mUseWebSearch); diff --git a/indra/newview/ascentprefssys.h b/indra/newview/ascentprefssys.h index a862e9166..785d14940 100644 --- a/indra/newview/ascentprefssys.h +++ b/indra/newview/ascentprefssys.h @@ -73,6 +73,7 @@ private: bool mEnableClassicClouds; bool mSpeedRez; U32 mSpeedRezInterval; + bool mUseContextMenus; bool mUseWebProfiles; bool mUseWebSearch; diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h index fec736819..3a6d2cbfb 100644 --- a/indra/newview/llfloatertools.h +++ b/indra/newview/llfloatertools.h @@ -111,6 +111,8 @@ public: void navigateToTitleMedia( const std::string url ); bool selectedMediaEditable(); + LLPanelFace* getPanelFace() { return mPanelFace; } + private: void refresh(); void refreshMedia(); diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 78ae39dda..b211047bc 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -53,6 +53,7 @@ #include "llface.h" #include "llinventorymodel.h" //Perms check for texture params #include "lllineeditor.h" +#include "llmaterialmgr.h" #include "llmediaentry.h" #include "llnotificationsutil.h" #include "llresmgr.h" @@ -62,6 +63,7 @@ #include "lltexturectrl.h" #include "lltextureentry.h" #include "lltooldraganddrop.h" +#include "lltrans.h" #include "llui.h" #include "llviewercontrol.h" #include "llviewermedia.h" @@ -71,7 +73,62 @@ #include "llvovolume.h" #include "lluictrlfactory.h" #include "llpluginclassmedia.h" -#include "llviewertexturelist.h" +#include "llviewertexturelist.h"// Update sel manager as to which channel we're editing so it can reflect the correct overlay UI + +// +// Constant definitions for comboboxes +// Must match the commbobox definitions in panel_tools_texture.xml +// +const S32 MATMEDIA_MATERIAL = 0; // Material +const S32 MATMEDIA_MEDIA = 1; // 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_NONE = 0; // No alpha mask applied +const S32 ALPHAMODE_BLEND = 1; // Alpha blending mode +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 + +// +// "Use texture" label for normal/specular type comboboxes +// Filled in at initialization from translated strings +// +std::string USE_TEXTURE; + +LLRender::eTexIndex LLPanelFace::getTextureChannelToEdit() +{ + LLComboBox* combobox_matmedia = getChild("combobox matmedia"); + LLComboBox* combobox_mattype = getChild("combobox mattype"); + + LLRender::eTexIndex channel_to_edit = (combobox_matmedia && combobox_matmedia->getCurrentIndex() == MATMEDIA_MATERIAL) ? + (combobox_mattype ? (LLRender::eTexIndex)combobox_mattype->getCurrentIndex() : LLRender::DIFFUSE_MAP) : LLRender::DIFFUSE_MAP; + + 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; +} + +// 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 @@ -81,24 +138,46 @@ BOOL LLPanelFace::postBuild() { childSetCommitCallback("combobox shininess",&LLPanelFace::onCommitShiny,this); childSetCommitCallback("combobox bumpiness",&LLPanelFace::onCommitBump,this); - + childSetCommitCallback("combobox alphamode",&LLPanelFace::onCommitAlphaMode,this); childSetCommitCallback("TexScaleU",&LLPanelFace::onCommitTextureInfo, this); - childSetCommitCallback("checkbox flip s",&LLPanelFace::onCommitTextureInfo, this); + childSetCommitCallback("flipTextureScaleU", boost::bind(&LLPanelFace::onCommitFlip, this, true)); childSetCommitCallback("TexScaleV",&LLPanelFace::onCommitTextureInfo, this); - childSetCommitCallback("checkbox flip t",&LLPanelFace::onCommitTextureInfo, this); + childSetCommitCallback("flipTextureScaleV", boost::bind(&LLPanelFace::onCommitFlip, this, false)); childSetCommitCallback("TexRot",&LLPanelFace::onCommitTextureInfo, this); - childSetAction("button apply",&LLPanelFace::onClickApply,this); + childSetCommitCallback("rptctrl",&LLPanelFace::onCommitRepeatsPerMeter, this); childSetCommitCallback("checkbox planar align",&LLPanelFace::onCommitPlanarAlign, this); childSetCommitCallback("TexOffsetU",LLPanelFace::onCommitTextureInfo, this); childSetCommitCallback("TexOffsetV",LLPanelFace::onCommitTextureInfo, 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); + childSetAction("button align",&LLPanelFace::onClickAutoFix,this); + + childSetCommitCallback("checkbox maps sync", boost::bind(&LLPanelFace::onClickMapsSync, this)); childSetAction("copytextures",&LLPanelFace::onClickCopy,this); childSetAction("pastetextures",&LLPanelFace::onClickPaste,this); - + LLTextureCtrl* mTextureCtrl; + LLTextureCtrl* mShinyTextureCtrl; + LLTextureCtrl* mBumpyTextureCtrl; LLColorSwatchCtrl* mColorSwatch; + LLColorSwatchCtrl* mShinyColorSwatch; LLComboBox* mComboTexGen; + LLComboBox* mComboMatMedia; + LLComboBox* mComboMatType; LLCheckBoxCtrl *mCheckFullbright; @@ -108,6 +187,7 @@ BOOL LLPanelFace::postBuild() LLSpinCtrl* mCtrlGlow; setMouseOpaque(FALSE); + mTextureCtrl = getChild("texture control"); if(mTextureCtrl) { @@ -116,27 +196,48 @@ BOOL LLPanelFace::postBuild() 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(); - // Don't allow (no copy) or (no transfer) textures to be selected during immediate mode - mTextureCtrl->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); - // Allow any texture to be used during non-immediate mode. - mTextureCtrl->setNonImmediateFilterPermMask(PERM_NONE); - LLAggregatePermissions texture_perms; - if (LLSelectMgr::getInstance()->selectGetAggregateTexturePermissions(texture_perms)) - { - BOOL can_copy = - texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_EMPTY || - texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_ALL; - BOOL can_transfer = - texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_EMPTY || - texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_ALL; - mTextureCtrl->setCanApplyImmediately(can_copy && can_transfer); - } - else - { - mTextureCtrl->setCanApplyImmediately(FALSE); - } + mTextureCtrl->setImmediateFilterPermMask(PERM_NONE); + mTextureCtrl->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER); + } + + mShinyTextureCtrl = getChild("shinytexture control"); + if(mShinyTextureCtrl) + { + mShinyTextureCtrl->setDefaultImageAssetID(LLUUID( gSavedSettings.getString( "DefaultObjectSpecularTexture" ))); + 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(LLUUID( gSavedSettings.getString( "DefaultObjectNormalTexture" ))); + mBumpyTextureCtrl->setBlankImageAssetID(LLUUID( gSavedSettings.getString( "DefaultBlankNormalTexture" ))); + 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"); @@ -150,6 +251,15 @@ BOOL LLPanelFace::postBuild() mColorSwatch->setCanApplyImmediately(TRUE); } + mShinyColorSwatch = getChild("shinycolorswatch"); + if(mShinyColorSwatch) + { + mShinyColorSwatch->setCommitCallback(boost::bind(&LLPanelFace::onCommitShinyColor, this, _2)); + mShinyColorSwatch->setFollowsTop(); + mShinyColorSwatch->setFollowsLeft(); + mShinyColorSwatch->setCanApplyImmediately(TRUE); + } + mLabelColorTransp = getChild("color trans"); if(mLabelColorTransp) { @@ -179,12 +289,26 @@ BOOL LLPanelFace::postBuild() mComboTexGen->setFollows(FOLLOWS_LEFT | FOLLOWS_TOP); } + mComboMatMedia = getChild("combobox matmedia"); + if(mComboMatMedia) + { + mComboMatMedia->setCommitCallback(LLPanelFace::onCommitMaterialsMedia,this); + mComboMatMedia->selectNthItem(MATMEDIA_MATERIAL); + } + + mComboMatType = getChild("combobox mattype"); + if(mComboMatType) + { + mComboMatType->setCommitCallback(boost::bind(&LLPanelFace::onCommitMaterialType, this)); + mComboMatType->selectNthItem(MATTYPE_DIFFUSE); + } + mCtrlGlow = getChild("glow"); if(mCtrlGlow) { mCtrlGlow->setCommitCallback(LLPanelFace::onCommitGlow, this); } - + clearCtrls(); @@ -192,8 +316,10 @@ BOOL LLPanelFace::postBuild() } LLPanelFace::LLPanelFace(const std::string& name) -: LLPanel(name) +: LLPanel(name), + mIsAlpha(false) { + USE_TEXTURE = LLTrans::getString("use_texture"); } @@ -220,11 +346,31 @@ void LLPanelFace::sendTexture() } } -void LLPanelFace::sendBump() +void LLPanelFace::sendBump(U32 bumpiness) { - LLComboBox* mComboBumpiness = getChild("combobox bumpiness"); - if(!mComboBumpiness)return; - U8 bump = (U8) mComboBumpiness->getCurrentIndex() & TEM_BUMP_MASK; + 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 ); } @@ -236,12 +382,28 @@ void LLPanelFace::sendTexGen() LLSelectMgr::getInstance()->selectionSetTexGen( tex_gen ); } -void LLPanelFace::sendShiny() +void LLPanelFace::sendShiny(U32 shininess) { - LLComboBox* mComboShininess = getChild("combobox shininess"); - if(!mComboShininess)return; - U8 shiny = (U8) mComboShininess->getCurrentIndex() & TEM_SHINY_MASK; + 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 ); + + updateShinyControls(!specmap.isNull(), true); + } void LLPanelFace::sendFullbright() @@ -254,7 +416,6 @@ void LLPanelFace::sendFullbright() void LLPanelFace::sendColor() { - LLColorSwatchCtrl* mColorSwatch = getChild("colorswatch"); if(!mColorSwatch)return; LLColor4 color = mColorSwatch->get(); @@ -274,7 +435,7 @@ void LLPanelFace::sendAlpha() void LLPanelFace::sendGlow() { - LLSpinCtrl* mCtrlGlow = getChild("glow"); + LLSpinCtrl* mCtrlGlow = getChild("glow"); llassert(mCtrlGlow); if (mCtrlGlow) { @@ -295,21 +456,16 @@ struct LLPanelFaceSetTEFunctor : public LLSelectedTEFunctor 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(); + valid = !ctrlTexScaleS->getTentative(); if (valid) { value = ctrlTexScaleS->get(); - if( checkFlipScaleS->get() ) - { - value = -value; - } if (comboTexGen && comboTexGen->getCurrentIndex() == 1) { @@ -321,14 +477,10 @@ struct LLPanelFaceSetTEFunctor : public LLSelectedTEFunctor if (ctrlTexScaleT) { - valid = !ctrlTexScaleT->getTentative() || !checkFlipScaleT->getTentative(); + valid = !ctrlTexScaleT->getTentative(); if (valid) { value = ctrlTexScaleT->get(); - if( checkFlipScaleT->get() ) - { - value = -value; - } if (comboTexGen && comboTexGen->getCurrentIndex() == 1) { @@ -456,10 +608,10 @@ struct LLPanelFaceGetIsAlignedTEFunctor : public LLSelectedTEFunctor 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], 16) && - is_approx_equal_fraction(st_offset.mV[VY], aligned_st_offset.mV[VY], 16) && - is_approx_equal_fraction(st_scale.mV[VX], aligned_st_scale.mV[VX], 16) && - is_approx_equal_fraction(st_scale.mV[VY], aligned_st_scale.mV[VY], 16) && + 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; @@ -484,16 +636,9 @@ 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(NULL); - LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue(&get_last_face_func, last_face); - + LLFace* last_face = NULL; + bool identical_face = false; + LLSelectedTE::getFace(last_face, identical_face); LLPanelFaceSetAlignedTEFunctor setfunc(this, last_face); LLSelectMgr::getInstance()->getSelection()->applyToTEs(&setfunc); } @@ -509,8 +654,13 @@ void LLPanelFace::sendTextureInfo() void LLPanelFace::getState() { + updateUI(); +} + +void LLPanelFace::updateUI() +{ //set state of UI to match state of texture entry(ies) (calls setEnabled, setValue, etc, but NOT setVisible) LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); - LLCalc* calcp = LLCalc::getInstance(); + if( objectp && objectp->getPCode() == LL_PCODE_VOLUME && objectp->permModify()) @@ -519,268 +669,74 @@ void LLPanelFace::getState() // only turn on auto-adjust button if there is a media renderer and the media is loaded getChildView("button align")->setEnabled(editable); - - //if ( LLMediaEngine::getInstance()->getMediaRenderer () ) - // if ( LLMediaEngine::getInstance()->getMediaRenderer ()->isLoaded () ) - // { - // - // //mLabelTexAutoFix->setEnabled ( editable ); - // - // //mBtnAutoFix->setEnabled ( editable ); - // } + + bool enable_material_controls = (!gSavedSettings.getBOOL("FSSynchronizeTextureMaps")); S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); BOOL single_volume = (LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME )) && (selected_count == 1); - childSetEnabled("copytextures", single_volume && editable); - childSetEnabled("pastetextures", single_volume && editable); - childSetEnabled("textbox params", single_volume && editable); - getChildView("button apply")->setEnabled(editable); + getChildView("copytextures")->setEnabled(single_volume && editable); + getChildView("pastetextures")->setEnabled(editable); + + LLComboBox* combobox_matmedia = getChild("combobox matmedia"); + if (combobox_matmedia) + { + if (combobox_matmedia->getCurrentIndex() < MATMEDIA_MATERIAL) + { + combobox_matmedia->selectNthItem(MATMEDIA_MATERIAL); + } + } + else + { + LL_WARNS("Materials") << "failed getChild for 'combobox matmedia'" << LL_ENDL; + } + getChildView("combobox matmedia")->setEnabled(editable); + + LLComboBox* combobox_mattype = getChild("combobox mattype"); + if (combobox_mattype) + { + if (combobox_mattype->getCurrentIndex() < MATTYPE_DIFFUSE) + { + combobox_mattype->selectNthItem(MATTYPE_DIFFUSE); + } + } + else + { + LL_WARNS("Materials") << "failed getChild for 'combobox mattype'" << LL_ENDL; + } + getChildView("combobox mattype")->setEnabled(editable); + + updateVisibility(); + + bool identical = true; // true because it is anded below + bool identical_diffuse = false; + bool identical_norm = false; + bool identical_spec = false; - bool identical; LLTextureCtrl* texture_ctrl = getChild("texture control"); texture_ctrl->setFallbackImageName( "" ); //Singu Note: Don't show the 'locked' image when the texid is null. - // Texture - { - LLUUID id; - struct f1 : public LLSelectedTEGetFunctor - { - LLUUID get(LLViewerObject* object, S32 te_index) - { - LLUUID id; - //LLViewerTexture* image = object->getTEImage(te); - LLTextureEntry* image = object->getTE(te_index); //Singu Note: Use this instead of the above. - //The above actually returns LLViewerFetchedTexture::sDefaultImagep when - //the texture id is null, which gives us IMG_DEFAULT, not LLUUID::null - //Such behavior prevents the 'None' button from ever greying out in the face panel. - 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 ); + LLTextureCtrl* shinytexture_ctrl = getChild("shinytexture control"); + shinytexture_ctrl->setFallbackImageName( "" ); //Singu Note: Don't show the 'locked' image when the texid is null. + LLTextureCtrl* bumpytexture_ctrl = getChild("bumpytexture control"); + bumpytexture_ctrl->setFallbackImageName( "" ); //Singu Note: Don't show the 'locked' image when the texid is null. - if(LLViewerMedia::textureHasMedia(id)) - { - 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 ); - } - } - } - } - - - LLAggregatePermissions texture_perms; - if(texture_ctrl) - { -// texture_ctrl->setValid( editable ); - - if (LLSelectMgr::getInstance()->selectGetAggregateTexturePermissions(texture_perms)) - { - BOOL can_copy = - texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_EMPTY || - texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_ALL; - BOOL can_transfer = - texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_EMPTY || - texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_ALL; - texture_ctrl->setCanApplyImmediately(can_copy && can_transfer); - } - else - { - texture_ctrl->setCanApplyImmediately(FALSE); - } - } - - - // 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(NULL); - 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 - { - getChildView("tex scale")->setEnabled(editable); - //mLabelTexScale->setEnabled( editable ); - 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 - { - getChildView("tex rotate")->setEnabled(editable); - 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); - } + LLUUID id; + LLUUID normmap_id; + LLUUID specmap_id; // Color swatch + { + getChildView("color label")->setEnabled(editable); + } LLColorSwatchCtrl* mColorSwatch = getChild("colorswatch"); - LLColor4 color = LLColor4::white; + + LLColor4 color = LLColor4::white; + bool identical_color =false; + 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 ); - + LLSelectedTE::getColor(color, identical_color); + mColorSwatch->setOriginal(color); mColorSwatch->set(color, TRUE); @@ -788,176 +744,676 @@ void LLPanelFace::getState() mColorSwatch->setEnabled( editable ); mColorSwatch->setCanApplyImmediately( editable ); } + // Color transparency - { - getChildView("color trans")->setEnabled(editable); - } + getChildView("color trans")->setEnabled(editable); F32 transparency = (1.f - color.mV[VALPHA]) * 100.f; + getChild("ColorTrans")->setValue(editable ? transparency : 0); + getChildView("ColorTrans")->setEnabled(editable); + + // Specular map + LLSelectedTEMaterial::getSpecularID(specmap_id, identical_spec); + + 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) { - getChild("ColorTrans")->setValue(editable ? transparency : 0); - getChildView("ColorTrans")->setEnabled(editable); + 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) { - 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); - + mShinyColorSwatch->setValid(editable); + mShinyColorSwatch->setEnabled( editable ); + mShinyColorSwatch->setCanApplyImmediately( editable ); } - // Bump + U8 bumpy = 0; + // Bumpy { - 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); - } + 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; - { - 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); + combobox_bumpiness->selectNthItem((S32)bumpy); } else { llwarns << "failed childGetSelectionInterface for 'combobox bumpiness'" << llendl; } + getChildView("combobox bumpiness")->setEnabled(editable); - getChild("combobox bumpiness")->setTentative(!identical); + getChild("combobox bumpiness")->setTentative(!identical_bumpy); getChildView("label bumpiness")->setEnabled(editable); } + // Texture { - F32 genf = 0.f; - struct f11 : public LLSelectedTEGetFunctor + LLSelectedTE::getTexId(id,identical_diffuse); + + // Normal map + LLSelectedTEMaterial::getNormalID(normmap_id, identical_norm); + + mIsAlpha = FALSE; + LLGLenum image_format = GL_RGB; + bool identical_image_format = false; + LLSelectedTE::getImageFormat(image_format, identical_image_format); + + mIsAlpha = FALSE; + switch (image_format) { - F32 get(LLViewerObject* object, S32 face) + case GL_RGBA: + case GL_ALPHA: { - return (F32)(object->getTE(face)->getTexGen()); + mIsAlpha = TRUE; } - } func; - identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, genf ); - S32 selected_texgen = ((S32) genf) >> TEM_TEX_GEN_SHIFT; - LLCtrlSelectionInterface* combobox_texgen = - childGetSelectionInterface("combobox texgen"); + break; + + case GL_RGB: break; + default: + { + LL_WARNS("Materials") << "Unexpected tex format in LLPanelFace...resorting to no alpha" << LL_ENDL; + } + break; + } + + if(LLViewerMedia::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("Materials") << "failed childGetSelectionInterface for 'combobox alphamode'" << LL_ENDL; + } + + updateAlphaControls(); + + if (texture_ctrl) + { + if (identical_diffuse) + { + texture_ctrl->setTentative( FALSE ); + texture_ctrl->setEnabled( editable ); + texture_ctrl->setImageAssetID( id ); + getChildView("combobox alphamode")->setEnabled(editable && mIsAlpha && transparency <= 0.f); + getChildView("label alphamode")->setEnabled(editable && mIsAlpha); + getChildView("maskcutoff")->setEnabled(editable && mIsAlpha); + getChildView("label maskcutoff")->setEnabled(editable && mIsAlpha); + } + 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 ); + } + else + { + // Tentative: multiple selected with different textures + texture_ctrl->setTentative( TRUE ); + texture_ctrl->setEnabled( editable ); + texture_ctrl->setImageAssetID( id ); + getChildView("combobox alphamode")->setEnabled(editable && mIsAlpha && transparency <= 0.f); + getChildView("label alphamode")->setEnabled(editable && mIsAlpha); + getChildView("maskcutoff")->setEnabled(editable && mIsAlpha); + getChildView("label maskcutoff")->setEnabled(editable && mIsAlpha); + } + } + + if (shinytexture_ctrl) + { + if (identical_spec && (shiny == SHINY_TEXTURE)) + { + shinytexture_ctrl->setTentative( FALSE ); + shinytexture_ctrl->setEnabled( editable ); + shinytexture_ctrl->setImageAssetID( specmap_id ); + } + else if (specmap_id.isNull()) + { + shinytexture_ctrl->setTentative( FALSE ); + shinytexture_ctrl->setEnabled( editable ); + shinytexture_ctrl->setImageAssetID( LLUUID::null ); + } + else + { + shinytexture_ctrl->setTentative( TRUE ); + shinytexture_ctrl->setEnabled( editable ); + shinytexture_ctrl->setImageAssetID( specmap_id ); + } + } + + if (bumpytexture_ctrl) + { + if (identical_norm && (bumpy == BUMPY_TEXTURE)) + { + bumpytexture_ctrl->setTentative( FALSE ); + bumpytexture_ctrl->setEnabled( editable ); + bumpytexture_ctrl->setImageAssetID( normmap_id ); + } + else if (normmap_id.isNull()) + { + bumpytexture_ctrl->setTentative( FALSE ); + bumpytexture_ctrl->setEnabled( editable ); + bumpytexture_ctrl->setImageAssetID( LLUUID::null ); + } + else + { + bumpytexture_ctrl->setTentative( TRUE ); + bumpytexture_ctrl->setEnabled( editable ); + bumpytexture_ctrl->setImageAssetID( normmap_id ); + } + } + } + + // 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()); + childSetValue("checkbox planar align", align_planar && enabled); + childSetEnabled("checkbox planar align", enabled); + + 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); + getChildView("shinyScaleU")->setEnabled(editable && specmap_id.notNull() + && enable_material_controls); // Materials alignment + getChildView("bumpyScaleU")->setEnabled(editable && normmap_id.notNull() + && enable_material_controls); // Materials alignment + + 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)); + + // FIRE-11407 - Materials alignment + getChildView("checkbox maps sync")->setEnabled(editable && (specmap_id.notNull() || normmap_id.notNull())); + // + } + + { + 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); + getChildView("shinyScaleV")->setEnabled(editable && specmap_id.notNull() + && enable_material_controls); // Materials alignment + getChildView("bumpyScaleV")->setEnabled(editable && normmap_id.notNull() + && enable_material_controls); // Materials alignment + + 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); + getChildView("shinyOffsetU")->setEnabled(editable && specmap_id.notNull() + && enable_material_controls); // Materials alignment + getChildView("bumpyOffsetU")->setEnabled(editable && normmap_id.notNull() + && enable_material_controls); // Materials alignment + } + + { + 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); + getChildView("shinyOffsetV")->setEnabled(editable && specmap_id.notNull() + && enable_material_controls); // Materials alignment + getChildView("bumpyOffsetV")->setEnabled(editable && normmap_id.notNull() + && enable_material_controls); // Materials alignment + } + + // 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); + getChildView("shinyRot")->setEnabled(editable && specmap_id.notNull() + && enable_material_controls); // Materials alignment + getChildView("bumpyRot")->setEnabled(editable && normmap_id.notNull() + && enable_material_controls); // Materials alignment + + 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) { - combobox_texgen->selectNthItem(selected_texgen); + // Maps from enum to combobox entry index + combobox_texgen->selectNthItem(((S32)selected_texgen) >> 1); } 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) + if (selected_texgen == LLTextureEntry::TEX_GEN_PLANAR) { - 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("tex scale")->setValue(getString("string repeats per meter")); + getChild("rpt")->setValue(getString("string repeats per meter")); } else + if (selected_texgen == LLTextureEntry::TEX_GEN_DEFAULT) { - getChild("tex scale")->setValue(getString("string repeats per face")); + 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 ); + U8 fullbright_flag = 0; + bool identical_fullbright = false; - getChild("checkbox fullbright")->setValue((S32)fullbrightf); + LLSelectedTE::getFullbright(fullbright_flag,identical_fullbright); + + getChild("checkbox fullbright")->setValue((S32)(fullbright_flag != 0)); getChildView("checkbox fullbright")->setEnabled(editable); - getChild("checkbox fullbright")->setTentative(!identical); - } - - // Repeats per meter label - { - getChildView("rpt")->setEnabled(editable); + getChild("checkbox fullbright")->setTentative(!identical_fullbright); } + // 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); + 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) { - BOOL enabled = editable && (!mComboTexGen || mComboTexGen->getCurrentIndex() != 1); - getChildView("rptctrl")->setEnabled(enabled); - getChildView("button apply")->setEnabled(enabled); + S32 index = mComboTexGen ? mComboTexGen->getCurrentIndex() : 0; + BOOL enabled = editable && (index != 1); + BOOL identical_repeats = true; + F32 repeats = 1.0f; + + U32 material_type = (combobox_matmedia->getCurrentIndex() == MATMEDIA_MATERIAL) ? combobox_mattype->getCurrentIndex() : MATTYPE_DIFFUSE; + + LLSelectMgr::getInstance()->setTextureChannel(LLRender::eTexIndex(material_type)); + + switch (material_type) + { + default: + case MATTYPE_DIFFUSE: + { + enabled = editable && !id.isNull(); + identical_repeats = identical_diff_repeats; + repeats = repeats_diff; + } + break; + + case MATTYPE_SPECULAR: + { + enabled = (editable && ((shiny == SHINY_TEXTURE) && !specmap_id.isNull()) + && enable_material_controls); // Materials Alignment + identical_repeats = identical_spec_repeats; + repeats = repeats_spec; + } + break; + + case MATTYPE_NORMAL: + { + enabled = (editable && ((bumpy == BUMPY_TEXTURE) && !normmap_id.isNull()) + && enable_material_controls); // Materials Alignment + identical_repeats = identical_norm_repeats; + repeats = repeats_norm; + } + break; + } + + BOOL repeats_tentative = !identical_repeats; + + getChildView("rptctrl")->setEnabled(identical_planar_texgen ? FALSE : enabled); + getChild("rptctrl")->setValue(editable ? repeats : 1.0f); + getChild("rptctrl")->setTentative(LLSD(repeats_tentative)); + + // FIRE-11407 - Flip buttons + getChildView("flipTextureScaleU")->setEnabled(enabled); + getChildView("flipTextureScaleV")->setEnabled(enabled); + // + } + } + + // Materials + { + LLMaterialPtr material; + LLSelectedTEMaterial::getCurrent(material, identical); + + if (material && editable) + { + LL_DEBUGS("Materials: OnMatererialsLoaded:") << 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 + { + llwarns << "failed childGetSelectionInterface for 'combobox alphamode'" << llendl; + } + 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()) + { + getChild("shinycolorswatch")->setOriginal(material->getSpecularLightColor()); + getChild("shinycolorswatch")->set(material->getSpecularLightColor(),TRUE); + } + + // 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); + } } } // 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()); @@ -976,7 +1432,6 @@ void LLPanelFace::getState() if(texture_ctrl) { texture_ctrl->setImageAssetID( LLUUID::null ); - texture_ctrl->setFallbackImageName( "locked_image.j2c" ); 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); } @@ -989,32 +1444,32 @@ void LLPanelFace::getState() } getChildView("color trans")->setEnabled(FALSE); getChildView("rpt")->setEnabled(FALSE); - getChildView("tex scale")->setEnabled(FALSE); getChildView("tex offset")->setEnabled(FALSE); - getChildView("tex rotate")->setEnabled(FALSE); getChildView("tex gen")->setEnabled(FALSE); getChildView("label shininess")->setEnabled(FALSE); getChildView("label bumpiness")->setEnabled(FALSE); getChildView("button align")->setEnabled(FALSE); - getChildView("button apply")->setEnabled(FALSE); //getChildView("has media")->setEnabled(FALSE); //getChildView("media info set")->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); + calcp->clearVar(LLCalc::TEX_GLOW); } } void LLPanelFace::refresh() { + LL_DEBUGS("Materials") << LL_ENDL; getState(); } @@ -1034,6 +1489,11 @@ 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(); @@ -1050,11 +1510,124 @@ void LLPanelFace::onSelectColor(const LLSD& data) sendColor(); } +// 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(); +} + +// static +void LLPanelFace::updateVisibility() +{ + LLComboBox* combo_matmedia = getChild("combobox matmedia"); + LLComboBox* combo_mattype = getChild("combobox mattype"); + LLComboBox* combo_shininess = getChild("combobox shininess"); + LLComboBox* combo_bumpiness = getChild("combobox bumpiness"); + if (!combo_mattype || !combo_matmedia || !combo_shininess || !combo_bumpiness) + { + LL_WARNS("Materials") << "Combo box not found...exiting." << LL_ENDL; + return; + } + U32 materials_media = combo_matmedia->getCurrentIndex(); + U32 material_type = combo_mattype->getCurrentIndex(); + bool show_media = (materials_media == MATMEDIA_MEDIA) && combo_matmedia->getEnabled(); + bool show_texture = (show_media || ((material_type == MATTYPE_DIFFUSE) && combo_matmedia->getEnabled())); + bool show_bumpiness = (!show_media) && (material_type == MATTYPE_NORMAL) && combo_matmedia->getEnabled(); + bool show_shininess = (!show_media) && (material_type == MATTYPE_SPECULAR) && combo_matmedia->getEnabled(); + getChildView("combobox mattype")->setVisible(!show_media); + // FIRE-11407 - Be consistant and hide this with the other controls + //getChildView("rptctrl")->setVisible(true); + getChildView("rptctrl")->setVisible(combo_matmedia->getEnabled()); + // and other additions... + getChildView("flipTextureScaleU")->setVisible(combo_matmedia->getEnabled()); + getChildView("flipTextureScaleV")->setVisible(combo_matmedia->getEnabled()); + // + + // Media controls + getChildView("media_info")->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_media); + getChildView("label alphamode")->setVisible(show_texture && !show_media); + getChildView("combobox alphamode")->setVisible(show_texture && !show_media); + getChildView("label maskcutoff")->setVisible(false); + getChildView("maskcutoff")->setVisible(false); + if (show_texture && !show_media) + { + updateAlphaControls(); + } + 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); +} + +void LLPanelFace::onCommitMaterialType() +{ + // Force to default states to side-step problems with menu contents + // and generally reflecting old state when switching tabs or objects + // + updateShinyControls(false,true); + updateBumpyControls(false,true); + updateUI(); +} + // static void LLPanelFace::onCommitBump(LLUICtrl* ctrl, void* userdata) { LLPanelFace* self = (LLPanelFace*) userdata; - self->sendBump(); + + LLComboBox* mComboBumpiness = self->getChild("combobox bumpiness"); + if(!mComboBumpiness) + return; + + U32 bumpiness = mComboBumpiness->getCurrentIndex(); + + self->sendBump(bumpiness); } // static @@ -1064,11 +1637,142 @@ void LLPanelFace::onCommitTexGen(LLUICtrl* ctrl, void* userdata) self->sendTexGen(); } +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(); + } + } + } + + LLComboBox* combo_matmedia = getChild("combobox matmedia"); + LLComboBox* combo_mattype = getChild("combobox mattype"); + U32 materials_media = combo_matmedia->getCurrentIndex(); + U32 material_type = combo_mattype->getCurrentIndex(); + bool show_media = (materials_media == MATMEDIA_MEDIA) && combo_matmedia->getEnabled(); + bool show_shininess = (!show_media) && (material_type == MATTYPE_SPECULAR) && combo_matmedia->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); +} + +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; - self->sendShiny(); + + + 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 + + LLComboBox* combobox_matmedia = getChild("combobox matmedia"); + U32 mat_media = MATMEDIA_MATERIAL; + if (combobox_matmedia) + { + mat_media = combobox_matmedia->getCurrentIndex(); + } + + LLComboBox* combobox_mattype = getChild("combobox mattype"); + U32 mat_type = MATTYPE_DIFFUSE; + if (combobox_mattype) + { + mat_type = combobox_mattype->getCurrentIndex(); + } + + 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 @@ -1118,27 +1822,288 @@ 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: + { + llwarns << "Unexpected tex format in LLPanelFace...resorting to no alpha" << llendl; + } + 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); + 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); +} + +//static +void LLPanelFace::onCommitMaterialBumpyOffsetX(LLUICtrl* ctrl, void* userdata) +{ + LLPanelFace* self = (LLPanelFace*) userdata; + llassert_always(self); + LLSelectedTEMaterial::setNormalOffsetX(self,self->getCurrentBumpyOffsetU()); +} + +//static +void LLPanelFace::onCommitMaterialBumpyOffsetY(LLUICtrl* ctrl, void* userdata) +{ + LLPanelFace* self = (LLPanelFace*) userdata; + llassert_always(self); + LLSelectedTEMaterial::setNormalOffsetY(self,self->getCurrentBumpyOffsetV()); +} + +//static +void LLPanelFace::onCommitMaterialShinyOffsetX(LLUICtrl* ctrl, void* userdata) +{ + LLPanelFace* self = (LLPanelFace*) userdata; + llassert_always(self); + LLSelectedTEMaterial::setSpecularOffsetX(self,self->getCurrentShinyOffsetU()); +} + +//static +void LLPanelFace::onCommitMaterialShinyOffsetY(LLUICtrl* ctrl, void* userdata) +{ + LLPanelFace* self = (LLPanelFace*) userdata; + llassert_always(self); + LLSelectedTEMaterial::setSpecularOffsetY(self,self->getCurrentShinyOffsetV()); +} + +//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; + } + 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; + } + 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; + } + 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; + } + LLSelectedTEMaterial::setSpecularRepeatY(self,shiny_scale_v); +} + +//static +void LLPanelFace::onCommitMaterialBumpyRot(LLUICtrl* ctrl, void* userdata) +{ + LLPanelFace* self = (LLPanelFace*) userdata; + llassert_always(self); + LLSelectedTEMaterial::setNormalRotation(self,self->getCurrentBumpyRot() * DEG_TO_RAD); +} + +//static +void LLPanelFace::onCommitMaterialShinyRot(LLUICtrl* ctrl, void* userdata) +{ + LLPanelFace* self = (LLPanelFace*) userdata; + llassert_always(self); + 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(); + // Materials alignment + if (gSavedSettings.getBOOL("FSSynchronizeTextureMaps")) + { + self->alignMaterialsProperties(); + } + // } // Commit the number of repeats per meter // static -void LLPanelFace::onClickApply(void* userdata) +void LLPanelFace::onCommitRepeatsPerMeter(LLUICtrl* ctrl, void* userdata) { LLPanelFace* self = (LLPanelFace*) userdata; - gFocusMgr.setKeyboardFocus( NULL ); + LLUICtrl* repeats_ctrl = self->getChild("rptctrl"); + LLComboBox* combo_matmedia = self->getChild("combobox matmedia"); + LLComboBox* combo_mattype = self->getChild("combobox mattype"); - //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 ); + U32 materials_media = combo_matmedia->getCurrentIndex(); + + + U32 material_type = (materials_media == MATMEDIA_MATERIAL) ? combo_mattype->getCurrentIndex() : 0; + 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); + + switch (material_type) + { + case MATTYPE_DIFFUSE: + { + LLSelectMgr::getInstance()->selectionTexScaleAutofit( repeats_per_meter ); + } + break; + + case MATTYPE_NORMAL: + { + LLUICtrl* bumpy_scale_u = self->getChild("bumpyScaleU"); + LLUICtrl* bumpy_scale_v = self->getChild("bumpyScaleV"); + + 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: + { + LLUICtrl* shiny_scale_u = self->getChild("shinyScaleU"); + LLUICtrl* shiny_scale_v = self->getChild("shinyScaleV"); + + 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; + } } struct LLPanelFaceSetMediaFunctor : public LLSelectedTEFunctor @@ -1210,6 +2175,267 @@ void LLPanelFace::onCommitPlanarAlign(LLUICtrl* ctrl, void* userdata) self->sendTextureInfo(); } +void LLPanelFace::onTextureSelectionChanged(LLInventoryItem* itemp) +{ + LL_DEBUGS("Materials") << "item asset " << itemp->getAssetUUID() << LL_ENDL; + LLComboBox* combo_mattype = getChild("combobox mattype"); + if (!combo_mattype) + { + return; + } + U32 mattype = combo_mattype->getCurrentIndex(); + 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("ApplyTextureImmediately")) + { + LLNotificationsUtil::add("LivePreviewUnavailable"); + } + } +} + +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); +} + +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) + { + 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 ); +} + +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 ); +} + static LLSD textures; void LLPanelFace::onClickCopy(void* userdata) @@ -1285,3 +2511,101 @@ void LLPanelFace::onClickPaste(void* userdata) msg->sendReliable(gAgent.getRegion()->getHost()); } + +// Materials alignment +void LLPanelFace::onClickMapsSync() +{ + getState(); + if (gSavedSettings.getBOOL("FSSynchronizeTextureMaps")) + { + alignMaterialsProperties(); + } +} + +void LLPanelFace::alignMaterialsProperties() +{ + F32 tex_scale_u = getChildView("TexScaleU")->getValue().asReal(); + F32 tex_scale_v = getChildView("TexScaleV")->getValue().asReal(); + F32 tex_offset_u = getChildView("TexOffsetU")->getValue().asReal(); + F32 tex_offset_v = getChildView("TexOffsetU")->getValue().asReal(); + F32 tex_rot = getChildView("TexRot")->getValue().asReal(); + + childSetValue("shinyScaleU", tex_scale_u); + childSetValue("shinyScaleV", tex_scale_v); + childSetValue("shinyOffsetU", tex_offset_u); + childSetValue("shinyOffsetV", tex_offset_v); + childSetValue("shinyRot", tex_rot); + + LLSelectedTEMaterial::setSpecularRepeatX(this, tex_scale_u); + LLSelectedTEMaterial::setSpecularRepeatY(this, tex_scale_v); + LLSelectedTEMaterial::setSpecularOffsetX(this, tex_offset_u); + LLSelectedTEMaterial::setSpecularOffsetY(this, tex_offset_v); + LLSelectedTEMaterial::setSpecularRotation(this, tex_rot * DEG_TO_RAD); + + childSetValue("bumpyScaleU", tex_scale_u); + childSetValue("bumpyScaleV", tex_scale_v); + childSetValue("bumpyOffsetU", tex_offset_u); + childSetValue("bumpyOffsetV", tex_offset_v); + childSetValue("bumpyRot", tex_rot); + + LLSelectedTEMaterial::setNormalRepeatX(this, tex_scale_u); + LLSelectedTEMaterial::setNormalRepeatY(this, tex_scale_v); + LLSelectedTEMaterial::setNormalOffsetX(this, tex_offset_u); + LLSelectedTEMaterial::setNormalOffsetY(this, tex_offset_v); + LLSelectedTEMaterial::setNormalRotation(this, tex_rot * DEG_TO_RAD); +} + +// FIRE-11407 - Flip buttons +void LLPanelFace::onCommitFlip(bool flip_x) +{ + std::string control_name = ""; + S32 mattype(getChild("combobox mattype")->getCurrentIndex()); + switch (mattype) + { + case MATTYPE_DIFFUSE: + control_name = "TexScale"; + break; + case MATTYPE_NORMAL: + control_name = "bumpyScale"; + break; + case MATTYPE_SPECULAR: + control_name = "shinyScale"; + break; + default: + //llassert(mattype); + return; + } + + if (LLUICtrl* spinner = getChild(control_name + (flip_x ? "U" : "V"))) + { + F32 value = -(spinner->getValue().asReal()); + spinner->setValue(value); + + switch (mattype) + { + case MATTYPE_DIFFUSE: + sendTextureInfo(); + if (gSavedSettings.getBOOL("FSSyncronizeTextureMaps")) + { + alignMaterialsProperties(); + } + break; + case MATTYPE_NORMAL: + if (flip_x) + LLSelectedTEMaterial::setNormalRepeatX(this, value); + else + LLSelectedTEMaterial::setNormalRepeatY(this, value); + break; + case MATTYPE_SPECULAR: + if (flip_x) + LLSelectedTEMaterial::setSpecularRepeatX(this, value); + else + LLSelectedTEMaterial::setSpecularRepeatY(this, value); + break; + default: + //llassert(mattype); + return; + } + } +} +// diff --git a/indra/newview/llpanelface.h b/indra/newview/llpanelface.h index 52ccbaf10..5ac63c20b 100644 --- a/indra/newview/llpanelface.h +++ b/indra/newview/llpanelface.h @@ -35,6 +35,10 @@ #include "v4color.h" #include "llpanel.h" +#include "llmaterial.h" +#include "llmaterialmgr.h" +#include "lltextureentry.h" +#include "llselectmgr.h" class LLButton; class LLCheckBoxCtrl; @@ -47,6 +51,49 @@ class LLTextBox; class LLTextureCtrl; class LLUICtrl; class LLViewerObject; +class LLFloater; +class LLMaterialID; + +// Represents an edit for use in replicating the op across one or more materials in the selection set. +// +// The apply function optionally performs the edit which it implements +// as a functor taking Data that calls member func MaterialFunc taking SetValueType +// on an instance of the LLMaterial class. +// +// boost who? +// +template< + typename DataType, + typename SetValueType, + void (LLMaterial::*MaterialEditFunc)(SetValueType data) > +class LLMaterialEditFunctor +{ +public: + LLMaterialEditFunctor(const DataType& data) : _data(data) {} + virtual ~LLMaterialEditFunctor() {} + virtual void apply(LLMaterialPtr& material) { (material->*(MaterialEditFunc))(_data); } + DataType _data; +}; + +template< + typename DataType, + DataType (LLMaterial::*MaterialGetFunc)() > +class LLMaterialGetFunctor +{ +public: + LLMaterialGetFunctor() {} + virtual DataType get(LLMaterialPtr& material) { return (material->*(MaterialGetFunc)); } +}; + +template< + typename DataType, + DataType (LLTextureEntry::*TEGetFunc)() > +class LLTEGetFunctor +{ +public: + LLTEGetFunctor() {} + virtual DataType get(LLTextureEntry* entry) { return (entry*(TEGetFunc)); } +}; class LLPanelFace : public LLPanel { @@ -59,6 +106,19 @@ public: void setMediaURL(const std::string& url); void setMediaType(const std::string& mime_type); + LLMaterialPtr createDefaultMaterial(LLMaterialPtr current_material) + { + LLMaterialPtr new_material(!current_material.isNull() ? new LLMaterial(current_material->asLLSD()) : new LLMaterial()); + llassert_always(new_material); + + // Preserve old diffuse alpha mode or assert correct default blend mode as appropriate for the alpha channel content of the diffuse texture + // + new_material->setDiffuseAlphaMode(current_material.isNull() ? (isAlpha() ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : LLMaterial::DIFFUSE_ALPHA_MODE_NONE) : current_material->getDiffuseAlphaMode()); + return new_material; + } + + LLRender::eTexIndex getTextureChannelToEdit(); + protected: void getState(); @@ -66,11 +126,11 @@ protected: void sendTextureInfo(); // applies and sends texture scale, offset, etc. void sendColor(); // applies and sends color void sendAlpha(); // applies and sends transparency - void sendBump(); // applies and sends bump map + void sendBump(U32 bumpiness); // applies and sends bump map void sendTexGen(); // applies and sends bump map - void sendShiny(); // applies and sends shininess + void sendShiny(U32 shininess); // applies and sends shininess void sendFullbright(); // applies and sends full bright - void sendGlow(); + void sendGlow(); void sendMedia(); // this function is to return TRUE if the drag should succeed. @@ -79,23 +139,370 @@ protected: void onCommitTexture(const LLSD& data); void onCancelTexture(const LLSD& data); void onSelectTexture(const LLSD& data); + void onCommitSpecularTexture(const LLSD& data); + void onCancelSpecularTexture(const LLSD& data); + void onSelectSpecularTexture(const LLSD& data); + void onCommitNormalTexture(const LLSD& data); + void onCancelNormalTexture(const LLSD& data); + void onSelectNormalTexture(const LLSD& data); void onCommitColor(const LLSD& data); + void onCommitShinyColor(const LLSD& data); void onCommitAlpha(const LLSD& data); void onCancelColor(const LLSD& data); void onSelectColor(const LLSD& data); + + void onCloseTexturePicker(const LLSD& data); + + // Make UI reflect state of currently selected material (refresh) + // and UI mode (e.g. editing normal map v diffuse map) + // + void updateUI(); + + // Convenience func to determine if all faces in selection have + // identical planar texgen settings during edits + // + bool isIdenticalPlanarTexgen(); + + // Callback funcs for individual controls + // static void onCommitTextureInfo( LLUICtrl* ctrl, void* userdata); + + static void onCommitMaterialBumpyScaleX( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialBumpyScaleY( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialBumpyRot( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialBumpyOffsetX( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialBumpyOffsetY( LLUICtrl* ctrl, void* userdata); + + static void onCommitMaterialShinyScaleX( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialShinyScaleY( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialShinyRot( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialShinyOffsetX( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialShinyOffsetY( LLUICtrl* ctrl, void* userdata); + + static void onCommitMaterialGloss( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialEnv( LLUICtrl* ctrl, void* userdata); + static void onCommitMaterialMaskCutoff( LLUICtrl* ctrl, void* userdata); + + static void onCommitMaterialsMedia( LLUICtrl* ctrl, void* userdata); + void onCommitMaterialType(); static void onCommitBump( LLUICtrl* ctrl, void* userdata); static void onCommitTexGen( LLUICtrl* ctrl, void* userdata); static void onCommitShiny( LLUICtrl* ctrl, void* userdata); + static void onCommitAlphaMode( LLUICtrl* ctrl, void* userdata); static void onCommitFullbright( LLUICtrl* ctrl, void* userdata); static void onCommitGlow( LLUICtrl* ctrl, void *userdata); static void onCommitPlanarAlign( LLUICtrl* ctrl, void* userdata); - static void onClickApply(void*); + static void onCommitRepeatsPerMeter( LLUICtrl* ctrl, void* userinfo); static void onClickAutoFix(void*); - static void onClickCopy(void*); - static void onClickPaste(void*); static F32 valueGlow(LLViewerObject* object, S32 face); + static void onClickCopy(void*); + static void onClickPaste(void*); + // Build tool enhancements + void onClickMapsSync(); + void alignMaterialsProperties(); + void onCommitFlip(bool flip_x); + // + +private: + + bool isAlpha() { return mIsAlpha; } + + // Convenience funcs to keep the visual flack to a minimum + // + LLUUID getCurrentNormalMap(); + LLUUID getCurrentSpecularMap(); + U32 getCurrentShininess(); + U32 getCurrentBumpiness(); + U8 getCurrentDiffuseAlphaMode(); + U8 getCurrentAlphaMaskCutoff(); + U8 getCurrentEnvIntensity(); + U8 getCurrentGlossiness(); + F32 getCurrentBumpyRot(); + F32 getCurrentBumpyScaleU(); + F32 getCurrentBumpyScaleV(); + F32 getCurrentBumpyOffsetU(); + F32 getCurrentBumpyOffsetV(); + F32 getCurrentShinyRot(); + F32 getCurrentShinyScaleU(); + F32 getCurrentShinyScaleV(); + F32 getCurrentShinyOffsetU(); + F32 getCurrentShinyOffsetV(); + + // Update visibility of controls to match current UI mode + // (e.g. materials vs media editing) + // + // Do NOT call updateUI from within this function. + // + void updateVisibility(); + + // Make material(s) reflect current state of UI (apply edit) + // + void updateMaterial(); + + // Hey look everyone, a type-safe alternative to copy and paste! :) + // + + // Update material parameters by applying 'edit_func' to selected TEs + // + template< + typename DataType, + typename SetValueType, + void (LLMaterial::*MaterialEditFunc)(SetValueType data) > + static void edit(LLPanelFace* p, DataType data) + { + LLMaterialEditFunctor< DataType, SetValueType, MaterialEditFunc > edit(data); + struct LLSelectedTEEditMaterial : public LLSelectedTEMaterialFunctor + { + LLSelectedTEEditMaterial(LLPanelFace* panel, LLMaterialEditFunctor< DataType, SetValueType, MaterialEditFunc >* editp) : _panel(panel), _edit(editp) {} + virtual ~LLSelectedTEEditMaterial() {}; + virtual LLMaterialPtr apply(LLViewerObject* object, S32 face, LLTextureEntry* tep, LLMaterialPtr& current_material) + { + if (_edit) + { + LLMaterialPtr new_material = _panel->createDefaultMaterial(current_material); + llassert_always(new_material); + + // Determine correct alpha mode for current diffuse texture + // (i.e. does it have an alpha channel that makes alpha mode useful) + // + // _panel->isAlpha() "lies" when one face has alpha and the rest do not (NORSPEC-329) + // need to get per-face answer to this question for sane alpha mode retention on updates. + // + bool is_alpha_face = object->isImageAlphaBlended(face); + + // need to keep this original answer for valid comparisons in logic below + // + U8 original_default_alpha_mode = is_alpha_face ? LLMaterial::DIFFUSE_ALPHA_MODE_BLEND : LLMaterial::DIFFUSE_ALPHA_MODE_NONE; + + U8 default_alpha_mode = original_default_alpha_mode; + + if (!current_material.isNull()) + { + default_alpha_mode = current_material->getDiffuseAlphaMode(); + } + + // Ensure we don't inherit the default of blend by accident... + // this will be stomped by a legit request to change the alpha mode by the apply() below + // + new_material->setDiffuseAlphaMode(default_alpha_mode); + + // Do "It"! + // + _edit->apply(new_material); + + U32 new_alpha_mode = new_material->getDiffuseAlphaMode(); + LLUUID new_normal_map_id = new_material->getNormalID(); + LLUUID new_spec_map_id = new_material->getSpecularID(); + + if ((new_alpha_mode == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND) && !is_alpha_face) + { + new_alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_NONE; + new_material->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE); + } + + bool is_default_blend_mode = (new_alpha_mode == original_default_alpha_mode); + bool is_need_material = !is_default_blend_mode || !new_normal_map_id.isNull() || !new_spec_map_id.isNull(); + + if (!is_need_material) + { + LL_DEBUGS("Materials") << "Removing material from object " << object->getID() << " face " << face << LL_ENDL; + LLMaterialMgr::getInstance()->remove(object->getID(),face); + new_material = NULL; + } + else + { + LL_DEBUGS("Materials") << "Putting material on object " << object->getID() << " face " << face << ", material: " << new_material->asLLSD() << LL_ENDL; + LLMaterialMgr::getInstance()->put(object->getID(),face,*new_material); + } + + object->setTEMaterialParams(face, new_material); + return new_material; + } + return NULL; + } + LLMaterialEditFunctor< DataType, SetValueType, MaterialEditFunc >* _edit; + LLPanelFace* _panel; + } editor(p, &edit); + LLSelectMgr::getInstance()->selectionSetMaterialParams(&editor); + } + + template< + typename DataType, + typename ReturnType, + ReturnType (LLMaterial::* const MaterialGetFunc)() const > + static void getTEMaterialValue(DataType& data_to_return, bool& identical,DataType default_value) + { + DataType data_value; + struct GetTEMaterialVal : public LLSelectedTEGetFunctor + { + GetTEMaterialVal(DataType default_value) : _default(default_value) {} + virtual ~GetTEMaterialVal() {} + + DataType get(LLViewerObject* object, S32 face) + { + DataType ret = _default; + LLMaterialPtr material_ptr; + LLTextureEntry* tep = object ? object->getTE(face) : NULL; + if (tep) + { + material_ptr = tep->getMaterialParams(); + if (!material_ptr.isNull()) + { + ret = (material_ptr->*(MaterialGetFunc))(); + } + } + return ret; + } + DataType _default; + } GetFunc(default_value); + identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &GetFunc, data_value); + data_to_return = data_value; + } + + template< + typename DataType, + typename ReturnType, // some kids just have to different... + ReturnType (LLTextureEntry::* const TEGetFunc)() const > + static void getTEValue(DataType& data_to_return, bool& identical, DataType default_value) + { + DataType data_value; + struct GetTEVal : public LLSelectedTEGetFunctor + { + GetTEVal(DataType default_value) : _default(default_value) {} + virtual ~GetTEVal() {} + + DataType get(LLViewerObject* object, S32 face) { + LLTextureEntry* tep = object ? object->getTE(face) : NULL; + return tep ? ((tep->*(TEGetFunc))()) : _default; + } + DataType _default; + } GetTEValFunc(default_value); + identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &GetTEValFunc, data_value ); + data_to_return = data_value; + } + + // Update vis and enabling of specific subsets of controls based on material params + // (e.g. hide the spec controls if no spec texture is applied) + // + void updateShinyControls(bool is_setting_texture = false, bool mess_with_combobox = false); + void updateBumpyControls(bool is_setting_texture = false, bool mess_with_combobox = false); + void updateAlphaControls(); + + /* + * Checks whether the selected texture from the LLFloaterTexturePicker can be applied to the currently selected object. + * If agent selects texture which is not allowed to be applied for the currently selected object, + * all controls of the floater texture picker which allow to apply the texture will be disabled. + */ + void onTextureSelectionChanged(LLInventoryItem* itemp); + + bool mIsAlpha; + + + #if defined(DEF_GET_MAT_STATE) + #undef DEF_GET_MAT_STATE + #endif + + #if defined(DEF_GET_TE_STATE) + #undef DEF_GET_TE_STATE + #endif + + #if defined(DEF_EDIT_MAT_STATE) + DEF_EDIT_MAT_STATE + #endif + + // Accessors for selected TE material state + // + #define DEF_GET_MAT_STATE(DataType,ReturnType,MaterialMemberFunc,DefaultValue) \ + static void MaterialMemberFunc(DataType& data, bool& identical) \ + { \ + getTEMaterialValue< DataType, ReturnType, &LLMaterial::MaterialMemberFunc >(data, identical,DefaultValue); \ + } + + // Mutators for selected TE material + // + #define DEF_EDIT_MAT_STATE(DataType,ReturnType,MaterialMemberFunc) \ + static void MaterialMemberFunc(LLPanelFace* p,DataType data) \ + { \ + edit< DataType, ReturnType, &LLMaterial::MaterialMemberFunc >(p,data); \ + } + + // Accessors for selected TE state proper (legacy settings etc) + // + #define DEF_GET_TE_STATE(DataType,ReturnType,TexEntryMemberFunc,DefaultValue) \ + static void TexEntryMemberFunc(DataType& data, bool& identical) \ + { \ + getTEValue< DataType, ReturnType, &LLTextureEntry::TexEntryMemberFunc >(data, identical,DefaultValue); \ + } + + class LLSelectedTEMaterial + { + public: + static void getCurrent(LLMaterialPtr& material_ptr, bool& identical_material); + static void getMaxSpecularRepeats(F32& repeats, bool& identical); + static void getMaxNormalRepeats(F32& repeats, bool& identical); + static void getCurrentDiffuseAlphaMode(U8& diffuse_alpha_mode, bool& identical, bool diffuse_texture_has_alpha); + + DEF_GET_MAT_STATE(LLUUID,const LLUUID&,getNormalID,LLUUID::null) + DEF_GET_MAT_STATE(LLUUID,const LLUUID&,getSpecularID,LLUUID::null) + DEF_GET_MAT_STATE(F32,F32,getSpecularRepeatX,1.0f) + DEF_GET_MAT_STATE(F32,F32,getSpecularRepeatY,1.0f) + DEF_GET_MAT_STATE(F32,F32,getSpecularOffsetX,0.0f) + DEF_GET_MAT_STATE(F32,F32,getSpecularOffsetY,0.0f) + DEF_GET_MAT_STATE(F32,F32,getSpecularRotation,0.0f) + + DEF_GET_MAT_STATE(F32,F32,getNormalRepeatX,1.0f) + DEF_GET_MAT_STATE(F32,F32,getNormalRepeatY,1.0f) + DEF_GET_MAT_STATE(F32,F32,getNormalOffsetX,0.0f) + DEF_GET_MAT_STATE(F32,F32,getNormalOffsetY,0.0f) + DEF_GET_MAT_STATE(F32,F32,getNormalRotation,0.0f) + + DEF_EDIT_MAT_STATE(U8,U8,setDiffuseAlphaMode); + DEF_EDIT_MAT_STATE(U8,U8,setAlphaMaskCutoff); + + DEF_EDIT_MAT_STATE(F32,F32,setNormalOffsetX); + DEF_EDIT_MAT_STATE(F32,F32,setNormalOffsetY); + DEF_EDIT_MAT_STATE(F32,F32,setNormalRepeatX); + DEF_EDIT_MAT_STATE(F32,F32,setNormalRepeatY); + DEF_EDIT_MAT_STATE(F32,F32,setNormalRotation); + + DEF_EDIT_MAT_STATE(F32,F32,setSpecularOffsetX); + DEF_EDIT_MAT_STATE(F32,F32,setSpecularOffsetY); + DEF_EDIT_MAT_STATE(F32,F32,setSpecularRepeatX); + DEF_EDIT_MAT_STATE(F32,F32,setSpecularRepeatY); + DEF_EDIT_MAT_STATE(F32,F32,setSpecularRotation); + + DEF_EDIT_MAT_STATE(U8,U8,setEnvironmentIntensity); + DEF_EDIT_MAT_STATE(U8,U8,setSpecularLightExponent); + + DEF_EDIT_MAT_STATE(LLUUID,const LLUUID&,setNormalID); + DEF_EDIT_MAT_STATE(LLUUID,const LLUUID&,setSpecularID); + DEF_EDIT_MAT_STATE(LLColor4U, const LLColor4U&,setSpecularLightColor); + }; + + class LLSelectedTE + { + public: + + static void getFace(LLFace*& face_to_return, bool& identical_face); + static void getImageFormat(LLGLenum& image_format_to_return, bool& identical_face); + static void getTexId(LLUUID& id, bool& identical); + static void getObjectScaleS(F32& scale_s, bool& identical); + static void getObjectScaleT(F32& scale_t, bool& identical); + static void getMaxDiffuseRepeats(F32& repeats, bool& identical); + + DEF_GET_TE_STATE(U8,U8,getBumpmap,0) + DEF_GET_TE_STATE(U8,U8,getShiny,0) + DEF_GET_TE_STATE(U8,U8,getFullbright,0) + DEF_GET_TE_STATE(F32,F32,getRotation,0.0f) + DEF_GET_TE_STATE(F32,F32,getOffsetS,0.0f) + DEF_GET_TE_STATE(F32,F32,getOffsetT,0.0f) + DEF_GET_TE_STATE(F32,F32,getScaleS,1.0f) + DEF_GET_TE_STATE(F32,F32,getScaleT,1.0f) + DEF_GET_TE_STATE(F32,F32,getGlow,0.0f) + DEF_GET_TE_STATE(LLTextureEntry::e_texgen,LLTextureEntry::e_texgen,getTexGen,LLTextureEntry::TEX_GEN_DEFAULT) + DEF_GET_TE_STATE(LLColor4,const LLColor4&,getColor,LLColor4::white) + }; }; #endif diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp index 42facc56c..f9ad87f55 100644 --- a/indra/newview/llpanelpermissions.cpp +++ b/indra/newview/llpanelpermissions.cpp @@ -1118,16 +1118,17 @@ void LLPanelPermissions::onClickDeedToGroup(void* data) LLNotificationsUtil::add( "DeedObjectToGroup", LLSD(), LLSD(), callback_deed_to_group); } -void LLPanelPermissions::onClickCopyObjKey() +template +std::string gather_keys(iterator iter, iterator end) { //NAMESHORT - Was requested on the forums, was going to integrate a textbox with the ID, but due to lack of room on the floater, //We now have a copy button :> //Madgeek - Hacked together method to copy more than one key, separated by comma. //At some point the separator was changed to read from the xml settings - I'll probably try to make this openly changable from settings. -HgB + //Lirusaito - Tweaked to copy selected prim(s) when EditLinkedParts, main functionality moved into gather_keys std::string output; std::string separator = gSavedSettings.getString("AscentDataSeparator"); - for (LLObjectSelection::root_iterator iter = LLSelectMgr::getInstance()->getSelection()->root_begin(); - iter != LLSelectMgr::getInstance()->getSelection()->root_end(); iter++) + for (; iter != end; ++iter) { LLSelectNode* selectNode = *iter; LLViewerObject* object = selectNode->getObject(); @@ -1137,6 +1138,14 @@ void LLPanelPermissions::onClickCopyObjKey() output.append(object->getID().asString()); } } + return output; +} + +void LLPanelPermissions::onClickCopyObjKey() +{ + bool parts(gSavedSettings.getBOOL("EditLinkedParts")); + LLObjectSelectionHandle selection(LLSelectMgr::getInstance()->getSelection()); + std::string output = parts ? gather_keys(selection->begin(), selection->end()) : gather_keys(selection->root_begin(), selection->root_end()); if (!output.empty()) gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(output)); } diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 84d0e2455..f16409e32 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -29,6 +29,7 @@ // file include #define LLSELECTMGR_CPP #include "llselectmgr.h" +#include "llmaterialmgr.h" // library includes #include "llcachename.h" @@ -64,6 +65,7 @@ #include "llmenugl.h" #include "llmeshrepository.h" #include "llmutelist.h" +#include "llparcel.h" #include "llnotificationsutil.h" #include "llstatusbar.h" #include "llsurface.h" @@ -80,20 +82,18 @@ #include "llviewermenu.h" #include "llviewerobject.h" #include "llviewerobjectlist.h" +#include "llviewerparcelmgr.h" #include "llviewerregion.h" #include "llviewerstats.h" #include "llvoavatarself.h" #include "llvovolume.h" #include "pipeline.h" #include "llviewershadermgr.h" - -#include "llparcel.h" -#include "llviewerparcelmgr.h" - +#include "llpanelface.h" #include "llglheaders.h" #include "hippogridmanager.h" -// [RLVa:KB] +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" // [/RLVa:KB] @@ -191,6 +191,7 @@ LLSelectMgr::LLSelectMgr() mDebugSelectMgr(LLCachedControl( "DebugSelectMgr", false)) { mTEMode = FALSE; + mTextureChannel = LLRender::DIFFUSE_MAP; mLastCameraPos.clearVec(); sHighlightThickness = gSavedSettings.getF32("SelectionHighlightThickness"); @@ -239,6 +240,8 @@ void LLSelectMgr::clearSelections() mHighlightedObjects->deleteAllNodes(); mRectSelectedObjects.clear(); mGridObjects.deleteAllNodes(); + + LLPipeline::setRenderHighlightTextureChannel(LLRender::DIFFUSE_MAP); } void LLSelectMgr::update() @@ -868,6 +871,10 @@ void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoab // check to see if object is already in list LLSelectNode *nodep = mSelectedObjects->findNode(objectp); + // Reset (in anticipation of being set to an appropriate value by panel refresh, if they're up) + // + setTextureChannel(LLRender::DIFFUSE_MAP); + // if not in list, add it if (!nodep) { @@ -2005,6 +2012,76 @@ void LLSelectMgr::selectionSetGlow(F32 glow) mSelectedObjects->applyToObjects( &func2 ); } +void LLSelectMgr::selectionSetMaterialParams(LLSelectedTEMaterialFunctor* material_func) +{ + struct f1 : public LLSelectedTEFunctor + { + LLMaterialPtr mMaterial; + f1(LLSelectedTEMaterialFunctor* material_func) : _material_func(material_func) {} + + bool apply(LLViewerObject* object, S32 face) + { + if (object && object->permModify() && _material_func) + { + LLTextureEntry* tep = object->getTE(face); + if (tep) + { + LLMaterialPtr current_material = tep->getMaterialParams(); + _material_func->apply(object, face, tep, current_material); + } + } + return true; + } + + LLSelectedTEMaterialFunctor* _material_func; + } func1(material_func); + mSelectedObjects->applyToTEs( &func1 ); + + struct f2 : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->sendTEUpdate(); + } + return true; + } + } func2; + mSelectedObjects->applyToObjects( &func2 ); +} + +void LLSelectMgr::selectionRemoveMaterial() +{ + struct f1 : public LLSelectedTEFunctor + { + bool apply(LLViewerObject* object, S32 face) + { + if (object->permModify()) + { + LL_DEBUGS("Materials") << "Removing material from object " << object->getID() << " face " << face << LL_ENDL; + LLMaterialMgr::getInstance()->remove(object->getID(),face); + object->setTEMaterialParams(face, NULL); + } + return true; + } + } func1; + mSelectedObjects->applyToTEs( &func1 ); + + struct f2 : public LLSelectedObjectFunctor + { + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->sendTEUpdate(); + } + return true; + } + } func2; + mSelectedObjects->applyToObjects( &func2 ); +} + //----------------------------------------------------------------------------- // findObjectPermissions() @@ -2045,6 +2122,7 @@ BOOL LLSelectMgr::selectionGetGlow(F32 *glow) return identical; } + void LLSelectMgr::selectionSetPhysicsType(U8 type) { struct f : public LLSelectedObjectFunctor @@ -2140,6 +2218,7 @@ void LLSelectMgr::selectionSetRestitution(F32 restitution) getSelection()->applyToObjects(&sendfunc); } + //----------------------------------------------------------------------------- // selectionSetMaterial() //----------------------------------------------------------------------------- @@ -2424,19 +2503,66 @@ void LLSelectMgr::adjustTexturesByScale(BOOL send_to_sim, BOOL stretch) continue; } - LLVector3 scale_ratio = selectNode->mTextureScaleRatios[te_num]; LLVector3 object_scale = object->getScale(); + LLVector3 diffuse_scale_ratio = selectNode->mTextureScaleRatios[te_num]; + + // We like these to track together. NORSPEC-96 + // + LLVector3 normal_scale_ratio = diffuse_scale_ratio; + LLVector3 specular_scale_ratio = diffuse_scale_ratio; // Apply new scale to face if (planar) { - object->setTEScale(te_num, 1.f/object_scale.mV[s_axis]*scale_ratio.mV[s_axis], - 1.f/object_scale.mV[t_axis]*scale_ratio.mV[t_axis]); + F32 diffuse_scale_s = diffuse_scale_ratio.mV[s_axis]/object_scale.mV[s_axis]; + F32 diffuse_scale_t = diffuse_scale_ratio.mV[t_axis]/object_scale.mV[t_axis]; + + F32 normal_scale_s = normal_scale_ratio.mV[s_axis]/object_scale.mV[s_axis]; + F32 normal_scale_t = normal_scale_ratio.mV[t_axis]/object_scale.mV[t_axis]; + + F32 specular_scale_s = specular_scale_ratio.mV[s_axis]/object_scale.mV[s_axis]; + F32 specular_scale_t = specular_scale_ratio.mV[t_axis]/object_scale.mV[t_axis]; + + object->setTEScale(te_num, diffuse_scale_s, diffuse_scale_t); + + LLTextureEntry* tep = object->getTE(te_num); + + if (tep && !tep->getMaterialParams().isNull()) + { + LLMaterialPtr orig = tep->getMaterialParams(); + LLMaterialPtr p = gFloaterTools->getPanelFace()->createDefaultMaterial(orig); + p->setNormalRepeat(normal_scale_s, normal_scale_t); + p->setSpecularRepeat(specular_scale_s, specular_scale_t); + + LLMaterialMgr::getInstance()->put(object->getID(), te_num, *p); + } } else { - object->setTEScale(te_num, scale_ratio.mV[s_axis]*object_scale.mV[s_axis], - scale_ratio.mV[t_axis]*object_scale.mV[t_axis]); + + F32 diffuse_scale_s = diffuse_scale_ratio.mV[s_axis]*object_scale.mV[s_axis]; + F32 diffuse_scale_t = diffuse_scale_ratio.mV[t_axis]*object_scale.mV[t_axis]; + + F32 normal_scale_s = normal_scale_ratio.mV[s_axis]*object_scale.mV[s_axis]; + F32 normal_scale_t = normal_scale_ratio.mV[t_axis]*object_scale.mV[t_axis]; + + F32 specular_scale_s = specular_scale_ratio.mV[s_axis]*object_scale.mV[s_axis]; + F32 specular_scale_t = specular_scale_ratio.mV[t_axis]*object_scale.mV[t_axis]; + + object->setTEScale(te_num, diffuse_scale_s,diffuse_scale_t); + + LLTextureEntry* tep = object->getTE(te_num); + + if (tep && !tep->getMaterialParams().isNull()) + { + LLMaterialPtr orig = tep->getMaterialParams(); + LLMaterialPtr p = gFloaterTools->getPanelFace()->createDefaultMaterial(orig); + + p->setNormalRepeat(normal_scale_s, normal_scale_t); + p->setSpecularRepeat(specular_scale_s, specular_scale_t); + + LLMaterialMgr::getInstance()->put(object->getID(), te_num, *p); + } } send = send_to_sim; } @@ -2889,7 +3015,6 @@ BOOL LLSelectMgr::selectGetViewableCharacters() return TRUE; } - //----------------------------------------------------------------------------- // selectGetRootsTransfer() - return TRUE if current agent can transfer all // selected root objects. @@ -4473,7 +4598,8 @@ void LLSelectMgr::saveSelectedObjectTransform(EActionType action_type) struct f : public LLSelectedNodeFunctor { EActionType mActionType; - f(EActionType a) : mActionType(a) {} + LLSelectMgr* mManager; + f(EActionType a, LLSelectMgr* p) : mActionType(a), mManager(p) {} virtual bool apply(LLSelectNode* selectNode) { LLViewerObject* object = selectNode->getObject(); @@ -4520,10 +4646,10 @@ void LLSelectMgr::saveSelectedObjectTransform(EActionType action_type) } selectNode->mSavedScale = object->getScale(); - selectNode->saveTextureScaleRatios(); + selectNode->saveTextureScaleRatios(mManager->mTextureChannel); return true; } - } func(action_type); + } func(action_type, this); getSelection()->applyToNodes(&func); mSavedSelectionBBox = getBBoxOfSelection(); @@ -5850,36 +5976,42 @@ void LLSelectNode::saveTextures(const uuid_vec_t& textures) } } -void LLSelectNode::saveTextureScaleRatios() +void LLSelectNode::saveTextureScaleRatios(LLRender::eTexIndex index_to_query) { mTextureScaleRatios.clear(); + if (mObject.notNull()) { + LLVector3 scale = mObject->getScale(); + for (U8 i = 0; i < mObject->getNumTEs(); i++) { - F32 s,t; - const LLTextureEntry* tep = mObject->getTE(i); - tep->getScale(&s,&t); - U32 s_axis = 0; - U32 t_axis = 0; - - LLPrimitive::getTESTAxes(i, &s_axis, &t_axis); + F32 diffuse_s = 1.0f; + F32 diffuse_t = 1.0f; LLVector3 v; - LLVector3 scale = mObject->getScale(); + const LLTextureEntry* tep = mObject->getTE(i); + if (!tep) + continue; + + U32 s_axis = VX; + U32 t_axis = VY; + LLPrimitive::getTESTAxes(i, &s_axis, &t_axis); + + tep->getScale(&diffuse_s,&diffuse_t); if (tep->getTexGen() == LLTextureEntry::TEX_GEN_PLANAR) { - v.mV[s_axis] = s*scale.mV[s_axis]; - v.mV[t_axis] = t*scale.mV[t_axis]; + v.mV[s_axis] = diffuse_s*scale.mV[s_axis]; + v.mV[t_axis] = diffuse_t*scale.mV[t_axis]; + mTextureScaleRatios.push_back(v); } else { - v.mV[s_axis] = s/scale.mV[s_axis]; - v.mV[t_axis] = t/scale.mV[t_axis]; + v.mV[s_axis] = diffuse_s/scale.mV[s_axis]; + v.mV[t_axis] = diffuse_t/scale.mV[t_axis]; + mTextureScaleRatios.push_back(v); } - - mTextureScaleRatios.push_back(v); } } } @@ -6383,7 +6515,23 @@ void LLSelectMgr::updateSelectionCenter() if (mSelectedObjects->mSelectType == SELECT_TYPE_ATTACHMENT && isAgentAvatarValid()) { - mPauseRequest = gAgentAvatarp->requestPause(); + // Singu Note: Chalice Yao's pause agent on attachment selection + if (object->permYouOwner()) + { + mPauseRequest = gAgentAvatarp->requestPause(); + } + else if (LLViewerObject* objectp = mSelectedObjects->getPrimaryObject()) + { + while (objectp && !objectp->isAvatar()) + { + objectp = (LLViewerObject*)objectp->getParent(); + } + + if (objectp) + { + mPauseRequest = objectp->asAvatar()->requestPause(); + } + } } else { @@ -6430,6 +6578,7 @@ void LLSelectMgr::updateSelectionCenter() LLVector3 bbox_center_agent = bbox.getCenterAgent(); mSelectionCenterGlobal = gAgent.getPosGlobalFromAgent(bbox_center_agent); mSelectionBBox = bbox; + } if ( !(gAgentID == LLUUID::null)) diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index dfe3df25f..ce16d0569 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -49,6 +49,7 @@ #include "llpermissions.h" #include "llcontrol.h" #include "llviewerobject.h" // LLObjectSelection::getSelectedTEValue template +#include "llmaterial.h" #include #include @@ -89,6 +90,12 @@ struct LLSelectedTEFunctor virtual bool apply(LLViewerObject* object, S32 face) = 0; }; +struct LLSelectedTEMaterialFunctor +{ + virtual ~LLSelectedTEMaterialFunctor() {}; + virtual LLMaterialPtr apply(LLViewerObject* object, S32 face, LLTextureEntry* tep, LLMaterialPtr& current_material) = 0; +}; + template struct LLSelectedTEGetFunctor { virtual ~LLSelectedTEGetFunctor() {}; @@ -149,7 +156,7 @@ public: // *NOTE: invalidate stored textures and colors when # faces change void saveColors(); void saveTextures(const uuid_vec_t& textures); - void saveTextureScaleRatios(); + void saveTextureScaleRatios(LLRender::eTexIndex index_to_query); BOOL allowOperationOnNode(PermissionBit op, U64 group_proxy_power) const; @@ -272,6 +279,8 @@ public: LLViewerObject* getFirstCopyableObject(BOOL get_parent = FALSE); LLViewerObject* getFirstDeleteableObject(); LLViewerObject* getFirstMoveableObject(BOOL get_parent = FALSE); + + /// Return the object that lead to this selection, possible a child LLViewerObject* getPrimaryObject() { return mPrimaryObject; } // iterate through texture entries @@ -344,6 +353,7 @@ public: static BOOL sRectSelectInclusive; // do we need to surround an object to pick it? static BOOL sRenderHiddenSelections; // do we show selection silhouettes that are occluded? static BOOL sRenderLightRadius; // do we show the radius of selected lights? + static F32 sHighlightThickness; static F32 sHighlightUScale; static F32 sHighlightVScale; @@ -465,11 +475,11 @@ public: //////////////////////////////////////////////////////////////// // Selection accessors //////////////////////////////////////////////////////////////// + LLObjectSelectionHandle getHoverObjects() { return mHoverObjects; } LLObjectSelectionHandle getSelection() { return mSelectedObjects; } // right now this just renders the selection with root/child colors instead of a single color LLObjectSelectionHandle getEditSelection() { convertTransient(); return mSelectedObjects; } LLObjectSelectionHandle getHighlightedObjects() { return mHighlightedObjects; } - LLObjectSelectionHandle getHoverObjects() { return mHoverObjects; } //////////////////////////////////////////////////////////////// // Grid manipulation @@ -502,6 +512,11 @@ public: void saveSelectedObjectColors(); void saveSelectedObjectTextures(); + // Sets which texture channel to query for scale and rot of display + // and depends on UI state of LLPanelFace when editing + void setTextureChannel(LLRender::eTexIndex texIndex) { mTextureChannel = texIndex; } + LLRender::eTexIndex getTextureChannel() { return mTextureChannel; } + void selectionUpdatePhysics(BOOL use_physics); void selectionUpdateTemporary(BOOL is_temporary); void selectionUpdatePhantom(BOOL is_ghost); @@ -532,6 +547,8 @@ public: void selectionSetClickAction(U8 action); void selectionSetIncludeInSearch(bool include_in_search); void selectionSetGlow(const F32 glow); + void selectionSetMaterialParams(LLSelectedTEMaterialFunctor* material_func); + void selectionRemoveMaterial(); void selectionSetObjectPermissions(U8 perm_field, BOOL set, U32 perm_mask, BOOL override = FALSE); void selectionSetObjectName(const std::string& name); @@ -759,8 +776,8 @@ private: LLVector3 mGridScale; EGridMode mGridMode; - BOOL mTEMode; // render te + LLRender::eTexIndex mTextureChannel; // diff, norm, or spec, depending on UI editing mode LLVector3d mSelectionCenterGlobal; LLBBox mSelectionBBox; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 75978675c..0cf590cd8 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -311,7 +311,7 @@ void reset_login(); void apply_udp_blacklist(const std::string& csv); // Aurora Sim //bool process_login_success_response(std::string& password); -bool process_login_success_response(std::string& password, U32& first_sim_size_x); +bool process_login_success_response(std::string& password, U32& first_sim_size_x, U32& first_sim_size_y); // Aurora Sim void transition_back_to_login_panel(const std::string& emsg); @@ -484,6 +484,7 @@ bool idle_startup() // Aurora Sim static U32 first_sim_size_x = 256; + static U32 first_sim_size_y = 256; // Aurora Sim static LLVector3 initial_sun_direction(1.f, 0.f, 0.f); static LLVector3 agent_start_position_region(10.f, 10.f, 10.f); // default for when no space server @@ -1550,7 +1551,7 @@ bool idle_startup() if (successful_login) { // unpack login data needed by the application - if (process_login_success_response(password, first_sim_size_x)) + if (process_login_success_response(password, first_sim_size_x, first_sim_size_y)) { std::string name = firstname; if (!gHippoGridManager->getCurrentGrid()->isSecondLife() || @@ -1670,7 +1671,7 @@ bool idle_startup() display_startup(); // Aurora Sim - LLWorld::getInstance()->setRegionWidth(first_sim_size_x); + LLWorld::getInstance()->setRegionSize(first_sim_size_x, first_sim_size_y); // Aurora Sim LLWorld::getInstance()->addRegion(gFirstSimHandle, gFirstSim); display_startup(); @@ -3856,7 +3857,7 @@ void apply_udp_blacklist(const std::string& csv) } -bool process_login_success_response(std::string& password, U32& first_sim_size_x) +bool process_login_success_response(std::string& password, U32& first_sim_size_x, U32& first_sim_size_y) { LLSD response = LLUserAuth::getInstance()->getResponse(); @@ -4000,6 +4001,9 @@ bool process_login_success_response(std::string& password, U32& first_sim_size_x // Aurora Sim text = response["region_size_x"].asString(); if (!text.empty()) LLViewerParcelMgr::getInstance()->init(first_sim_size_x = atoi(text.c_str())); + // Patrick Sapinski commented here on 2/10/2011 that y is currently unused and major refactor is required - Liru (11/6/2013) + text = response["region_size_y"].asString(); + if (!text.empty()) first_sim_size_y = atoi(text.c_str()); // Aurora Sim const std::string look_at_str = response["look_at"]; diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index ca53a8f6c..d17c6316d 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -141,6 +141,8 @@ public: // New functions void setImageID( const LLUUID& image_asset_id); + const LLUUID& getWhiteImageAssetID() const { return mWhiteImageAssetID; } + void setWhiteImageAssetID(const LLUUID& id) { mWhiteImageAssetID = id; } void updateImageStats(); const LLUUID& getAssetID() { return mImageAssetID; } const LLUUID& findItemID(const LLUUID& asset_id, BOOL copyable_only); @@ -158,6 +160,9 @@ public: void updateFilterPermMask(); void commitIfImmediateSet(); + void setCanApply(bool can_preview, bool can_apply); + void setTextureSelectedCallback(texture_selected_callback cb) {mTextureSelectedCallback = cb;} + static void onBtnSetToDefault( void* userdata ); static void onBtnSelect( void* userdata ); static void onBtnCancel( void* userdata ); @@ -220,6 +225,11 @@ protected: LLSaveFolderState mSavedFolderState; BOOL mSelectedItemPinned; LLScrollListCtrl* mLocalScrollCtrl; // tag: vaa emerald local_asset_browser + +private: + bool mCanApply; + bool mCanPreview; + texture_selected_callback mTextureSelectedCallback; }; LLFloaterTexturePicker::LLFloaterTexturePicker( @@ -254,7 +264,9 @@ LLFloaterTexturePicker::LLFloaterTexturePicker( mDnDFilterPermMask(dnd_filter_perm_mask), mNonImmediateFilterPermMask(non_immediate_filter_perm_mask), mContextConeOpacity(0.f), - mSelectedItemPinned(FALSE) + mSelectedItemPinned(FALSE), + mCanApply(true), + mCanPreview(true) { mCanApplyImmediately = can_apply_immediately; LLUICtrlFactory::getInstance()->buildFloater(this,"floater_texture_ctrl.xml"); @@ -353,7 +365,9 @@ BOOL LLFloaterTexturePicker::handleDragAndDrop( { BOOL handled = FALSE; - if (cargo_type == DAD_TEXTURE) + bool is_mesh = cargo_type == DAD_MESH; + + if ((cargo_type == DAD_TEXTURE) || is_mesh) { LLInventoryItem *item = (LLInventoryItem *)cargo_data; @@ -373,6 +387,9 @@ BOOL LLFloaterTexturePicker::handleDragAndDrop( { if (drop) { + // FIRE-8298: Apply now checkbox has no effect + setCanApply(true, true); + // setImageID( item->getAssetUUID() ); commitIfImmediateSet(); } @@ -607,7 +624,7 @@ void LLFloaterTexturePicker::draw() // if we're inactive, gray out "apply immediate" checkbox getChildView("show_folders_check")->setEnabled(mActive && mCanApplyImmediately && !mNoCopyTextureSelected); - getChildView("Select")->setEnabled(mActive); + getChildView("Select")->setEnabled(mActive && mCanApply); getChildView("Pipette")->setEnabled(mActive); getChild("Pipette")->setValue(LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance()); @@ -768,8 +785,10 @@ PermissionMask LLFloaterTexturePicker::getFilterPermMask() void LLFloaterTexturePicker::commitIfImmediateSet() { - bool apply_immediate = getChild("apply_immediate_check")->getValue().asBoolean(); - if (!mNoCopyTextureSelected && mOwner && apply_immediate) + // FIRE-8298: Apply now checkbox has no effect + //if (!mNoCopyTextureSelected && mOwner && mCanApply) + if (!mNoCopyTextureSelected && mOwner && mCanApply && mCanPreview) + // { mOwner->onFloaterCommit(LLTextureCtrl::TEXTURE_CHANGE); } @@ -779,6 +798,7 @@ void LLFloaterTexturePicker::commitIfImmediateSet() void LLFloaterTexturePicker::onBtnSetToDefault(void* userdata) { LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + self->setCanApply(true, true); if (self->mOwner) { self->setImageID( self->mOwner->getDefaultImageAssetID() ); @@ -790,6 +810,7 @@ void LLFloaterTexturePicker::onBtnSetToDefault(void* userdata) void LLFloaterTexturePicker::onBtnWhite(void* userdata) { LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + self->setCanApply(true, true); self->setImageID( self->mWhiteImageAssetID ); self->commitIfImmediateSet(); } @@ -798,6 +819,7 @@ void LLFloaterTexturePicker::onBtnWhite(void* userdata) void LLFloaterTexturePicker::onBtnNone(void* userdata) { LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + self->setCanApply(true, true); self->setImageID( LLUUID::null ); self->commitIfImmediateSet(); } @@ -806,6 +828,7 @@ void LLFloaterTexturePicker::onBtnNone(void* userdata) void LLFloaterTexturePicker::onBtnInvisible(void* userdata) { LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + self->setCanApply(true, true); self->setImageID(self->mInvisibleImageAssetID); self->commitIfImmediateSet(); } @@ -815,6 +838,7 @@ void LLFloaterTexturePicker::onBtnInvisible(void* userdata) void LLFloaterTexturePicker::onBtnAlpha(void* userdata) { LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata; + self->setCanApply(true, true); self->setImageID(self->mAlphaImageAssetID); self->commitIfImmediateSet(); } @@ -959,6 +983,10 @@ void LLFloaterTexturePicker::onSelectionChange(const std::deque if (itemp->getPermissions().getMaskOwner() & PERM_ALL) childSetValue("texture_uuid", mImageAssetID); @@ -970,9 +998,12 @@ void LLFloaterTexturePicker::onSelectionChange(const std::deque FIRE-8298: Apply now checkbox has no effect + setCanApply(true, true); + // mImageAssetID = itemp->getAssetUUID(); mIsDirty = TRUE; - if (user_action) + if (user_action && mCanPreview) { // only commit intentional selections, not implicit ones commitIfImmediateSet(); @@ -1004,7 +1035,9 @@ void LLFloaterTexturePicker::onApplyImmediateCheck(LLUICtrl* ctrl, void *user_da LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl; gSavedSettings.setBOOL("ApplyTextureImmediately", check_box->get()); - + // FIRE-8298: Apply now checkbox has no effect + picker->setCanApply(true, true); + // picker->updateFilterPermMask(); picker->commitIfImmediateSet(); } @@ -1014,6 +1047,16 @@ void LLFloaterTexturePicker::updateFilterPermMask() //mInventoryPanel->setFilterPermMask( getFilterPermMask() ); Commented out due to no-copy texture loss. } +void LLFloaterTexturePicker::setCanApply(bool can_preview, bool can_apply) +{ + getChildRef("Select").setEnabled(can_apply); + getChildRef("preview_disabled").setVisible(!can_preview); + getChildRef("apply_immediate_check").setVisible(can_preview); + + mCanApply = can_apply; + mCanPreview = can_preview ? gSavedSettings.getBOOL("ApplyTextureImmediately") : false; +} + void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string ) { std::string upper_case_search_string = search_string; @@ -1054,6 +1097,9 @@ void LLFloaterTexturePicker::onTextureSelect( const LLTextureEntry& te ) if (inventory_item_id.notNull()) { LLToolPipette::getInstance()->setResult(TRUE, ""); + // FIRE-8298: Apply now checkbox has no effect + setCanApply(true, true); + // setImageID(te.getID()); mNoCopyTextureSelected = FALSE; @@ -1094,6 +1140,7 @@ LLTextureCtrl::LLTextureCtrl( mDragCallback(NULL), mDropCallback(NULL), mOnCancelCallback(NULL), + mOnCloseCallback(NULL), mOnSelectCallback(NULL), mBorderColor( gColors.getColor("DefaultHighlightLight") ), mImageAssetID( image_id ), @@ -1221,6 +1268,19 @@ void LLTextureCtrl::setShowLoadingPlaceholder(BOOL showLoadingPlaceholder) mShowLoadingPlaceholder = showLoadingPlaceholder; } +// Singu Note: These two functions exist to work like their upstream counterparts +void LLTextureCtrl::setBlankImageAssetID(const LLUUID& id) +{ + if (LLFloaterTexturePicker* floater = dynamic_cast(mFloaterHandle.get())) + floater->setWhiteImageAssetID(id); +} +const LLUUID& LLTextureCtrl::getBlankImageAssetID() const +{ + if (LLFloaterTexturePicker* floater = dynamic_cast(mFloaterHandle.get())) + return floater->getWhiteImageAssetID(); + return LLUUID::null; +} + void LLTextureCtrl::setCaption(const std::string& caption) { mCaption->setText( caption ); @@ -1236,6 +1296,15 @@ void LLTextureCtrl::setCanApplyImmediately(BOOL b) } } +void LLTextureCtrl::setCanApply(bool can_preview, bool can_apply) +{ + LLFloaterTexturePicker* floaterp = dynamic_cast(mFloaterHandle.get()); + if( floaterp ) + { + floaterp->setCanApply(can_preview, can_apply); + } +} + void LLTextureCtrl::setVisible( BOOL visible ) { if( !visible ) @@ -1341,6 +1410,12 @@ void LLTextureCtrl::showPicker(BOOL take_focus) mFloaterHandle = floaterp->getHandle(); + LLFloaterTexturePicker* texture_floaterp = dynamic_cast(floaterp); + if (texture_floaterp && mOnTextureSelectedCallback) + { + texture_floaterp->setTextureSelectedCallback(mOnTextureSelectedCallback); + } + gFloaterView->getParentFloater(this)->addDependentFloater(floaterp); floaterp->open(); /* Flawfinder: ignore */ } @@ -1395,6 +1470,10 @@ void LLTextureCtrl::onFloaterClose() if (floaterp) { + if (mOnCloseCallback) + { + mOnCloseCallback(this,LLSD()); + } floaterp->setOwner(NULL); mLastFloaterLeftTop.set( floaterp->getRect().mLeft, floaterp->getRect().mTop ); } @@ -1466,6 +1545,16 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id) // tag: vaa emerald local_asset_browser [end] +void LLTextureCtrl::setOnTextureSelectedCallback(texture_selected_callback cb) +{ + mOnTextureSelectedCallback = cb; + LLFloaterTexturePicker* floaterp = dynamic_cast(mFloaterHandle.get()); + if (floaterp) + { + floaterp->setTextureSelectedCallback(cb); + } +} + void LLTextureCtrl::setImageAssetID( const LLUUID& asset_id ) { if( mImageAssetID != asset_id ) diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h index 27afeba3d..718aa1106 100644 --- a/indra/newview/lltexturectrl.h +++ b/indra/newview/lltexturectrl.h @@ -48,6 +48,7 @@ class LLViewerFetchedTexture; // used for setting drag & drop callbacks. typedef boost::function drag_n_drop_callback; +typedef boost::function texture_selected_callback; ////////////////////////////////////////////////////////////////////////////////////////// @@ -79,7 +80,6 @@ public: static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, @@ -124,12 +124,17 @@ public: const std::string& getDefaultImageName() const { return mDefaultImageName; } + void setBlankImageAssetID(const LLUUID& id); + const LLUUID& getBlankImageAssetID() const; + void setFallbackImageName( const std::string& name ) { mFallbackImageName = name; } const std::string& getFallbackImageName() const { return mFallbackImageName; } void setCaption(const std::string& caption); void setCanApplyImmediately(BOOL b); + void setCanApply(bool can_preview, bool can_apply); + void setImmediateFilterPermMask(PermissionMask mask) { mImmediateFilterPermMask = mask; } void setDnDFilterPermMask(PermissionMask mask) @@ -155,11 +160,18 @@ public: void setDropCallback(drag_n_drop_callback cb) { mDropCallback = cb; } void setOnCancelCallback(commit_callback_t cb) { mOnCancelCallback = cb; } - + void setOnCloseCallback(commit_callback_t cb) { mOnCloseCallback = cb; } void setOnSelectCallback(commit_callback_t cb) { mOnSelectCallback = cb; } + /* + * callback for changing texture selection in inventory list of texture floater + */ + void setOnTextureSelectedCallback(texture_selected_callback cb); + void setShowLoadingPlaceholder(BOOL showLoadingPlaceholder); + LLViewerFetchedTexture* getTexture() { return mTexturep; } + static void handleClickOpenTexture(void* userdata); static void handleClickCopyAssetID(void* userdata); @@ -172,6 +184,8 @@ private: drag_n_drop_callback mDropCallback; commit_callback_t mOnCancelCallback; commit_callback_t mOnSelectCallback; + commit_callback_t mOnCloseCallback; + texture_selected_callback mOnTextureSelectedCallback; LLPointer mTexturep; LLColor4 mBorderColor; LLUUID mImageItemID; diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index a97711e4e..3b44f27a3 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -31,26 +31,19 @@ */ #include "llviewerprecompiledheaders.h" - -#include "message.h" #include "lltooldraganddrop.h" +// library headers #include "llnotificationsutil.h" - -#include "llinstantmessage.h" -#include "lldir.h" - +// project headers #include "llagent.h" #include "llagentcamera.h" #include "llagentwearables.h" #include "llappearancemgr.h" #include "lldictionary.h" -#include "llviewercontrol.h" #include "llfirstuse.h" -#include "llfloater.h" #include "llfloaterinventory.h" #include "llfloatertools.h" -#include "llfocusmgr.h" #include "llgesturemgr.h" #include "llgiveinventory.h" #include "llhudmanager.h" @@ -66,7 +59,6 @@ #include "llselectmgr.h" #include "lltoolmgr.h" #include "lltrans.h" -#include "llui.h" #include "llviewertexturelist.h" #include "llviewerinventory.h" #include "llviewerobject.h" @@ -77,14 +69,14 @@ #include "llvoavatarself.h" #include "llvolume.h" #include "llworld.h" -#include "object_flags.h" +#include "llpanelface.h" // #include "llappviewer.h" // System Folders #include "llparcel.h" // always rez #include "llviewerparcelmgr.h" // always rez // -// [RLVa:KB] - Checked: 2010-03-04 (RLVa-1.2.0a) +// [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1) #include "rlvhandler.h" #include "rlvlocks.h" // [/RLVa:KB] @@ -388,9 +380,12 @@ void LLToolDragAndDrop::setDragStart(S32 x, S32 y) BOOL LLToolDragAndDrop::isOverThreshold(S32 x,S32 y) { - const S32 MIN_MANHATTAN_DIST = 3; - S32 manhattan_dist = llabs( x - mDragStartX ) + llabs( y - mDragStartY ); - return manhattan_dist >= MIN_MANHATTAN_DIST; + static LLCachedControl drag_and_drop_threshold(gSavedSettings,"DragAndDropDistanceThreshold"); + + S32 mouse_delta_x = x - mDragStartX; + S32 mouse_delta_y = y - mDragStartY; + + return (mouse_delta_x * mouse_delta_x) + (mouse_delta_y * mouse_delta_y) > drag_and_drop_threshold * drag_and_drop_threshold; } void LLToolDragAndDrop::beginDrag(EDragAndDropType type, @@ -1162,10 +1157,56 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj, // update viewer side image in anticipation of update from simulator //LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(asset_id); LLViewerStats::getInstance()->incStat(LLViewerStats::ST_EDIT_TEXTURE_COUNT ); - //hit_obj->setTEImage(hit_face, image); - hit_obj->setTETexture(hit_face, asset_id); //Singu note: setTETexture will allow the real id to be passed to LLPrimitive::setTETexture, - // even if it's null. setTEImage would actually pass down IMG_DEFAULT under such a case, - // which we don't want. + + LLTextureEntry* tep = hit_obj ? (hit_obj->getTE(hit_face)) : NULL; + + LLPanelFace* panel_face = gFloaterTools->getPanelFace(); + + if (gFloaterTools->getVisible() && panel_face) + { + switch (LLSelectMgr::getInstance()->getTextureChannel()) + { + case 0: + default: + { + //hit_obj->setTEImage(hit_face, image); + hit_obj->setTETexture(hit_face, asset_id); //Singu note: setTETexture will allow the real id to be passed to LLPrimitive::setTETexture, + // even if it's null. setTEImage would actually pass down IMG_DEFAULT under such a case, + // which we don't want. + } + break; + + case 1: + { + LLMaterialPtr old_mat = tep->getMaterialParams(); + LLMaterialPtr new_mat = panel_face->createDefaultMaterial(old_mat); + new_mat->setNormalID(asset_id); + tep->setMaterialParams(new_mat); + hit_obj->setTENormalMap(hit_face, asset_id); + LLMaterialMgr::getInstance()->put(hit_obj->getID(), hit_face, *new_mat); + } + break; + + case 2: + { + LLMaterialPtr old_mat = tep->getMaterialParams(); + LLMaterialPtr new_mat = panel_face->createDefaultMaterial(old_mat); + new_mat->setSpecularID(asset_id); + tep->setMaterialParams(new_mat); + hit_obj->setTESpecularMap(hit_face, asset_id); + LLMaterialMgr::getInstance()->put(hit_obj->getID(), hit_face, *new_mat); + } + break; + } + } + else + { + //hit_obj->setTEImage(hit_face, image); + hit_obj->setTETexture(hit_face, asset_id); //Singu note: setTETexture will allow the real id to be passed to LLPrimitive::setTETexture, + // even if it's null. setTEImage would actually pass down IMG_DEFAULT under such a case, + // which we don't want. + } + dialog_refresh_all(); // send the update to the simulator @@ -1619,6 +1660,7 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_ case DAD_ANIMATION: case DAD_GESTURE: case DAD_CALLINGCARD: + case DAD_MESH: { LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data; if(gInventory.getItem(inv_item->getUUID()) @@ -2353,7 +2395,7 @@ EAcceptance LLToolDragAndDrop::dad3dUpdateInventoryCategory( } } - // if every item is accepted, go ahead and send it on. + // If every item is accepted, send it on if(drop && (ACCEPT_YES_COPY_SINGLE <= rv)) { uuid_vec_t ids; @@ -2595,7 +2637,12 @@ LLInventoryObject* LLToolDragAndDrop::locateInventory( { item = NULL; cat = NULL; - if(mCargoIDs.empty()) return NULL; + + if (mCargoIDs.empty()) + { + return NULL; + } + if((mSource == SOURCE_AGENT) || (mSource == SOURCE_LIBRARY)) { // The object should be in user inventory. diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index f1904b312..fa74444ff 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -1101,7 +1101,7 @@ BOOL LLToolPie::handleRightClickPick() { LLParcelSelectionHandle selection = LLViewerParcelMgr::getInstance()->selectParcelAt( mPick.mPosGlobal ); gMenuHolder->setParcelSelection(selection); - gPieLand->show(x, y, true); + gPieLand->show(x, y); showVisualContextMenuEffect(); @@ -1115,7 +1115,7 @@ BOOL LLToolPie::handleRightClickPick() return TRUE ; } - gPieSelf->show(x, y, true); + gPieSelf->show(x, y); } else if (object) { @@ -1159,11 +1159,11 @@ BOOL LLToolPie::handleRightClickPick() // [/RLVa:KB] /*if (is_other_attachment) { - gPieAttachmentOther->show(x, y, true); + gPieAttachmentOther->show(x, y); } else*/ { - gPieAvatar->show(x, y, true); + gPieAvatar->show(x, y); } // [RLVa:KB] - Checked: 2010-04-11 (RLVa-1.2.0e) | Modified: RLVa-1.1.0l } @@ -1175,7 +1175,7 @@ BOOL LLToolPie::handleRightClickPick() } else if (object->isAttachment()) { - gPieAttachment->show(x, y, true); + gPieAttachment->show(x, y); } else { @@ -1204,7 +1204,7 @@ BOOL LLToolPie::handleRightClickPick() { // [/RLVa:KB] gMenuHolder->childSetText("Object Mute", mute_msg); - gPieObject->show(x, y, true); + gPieObject->show(x, y); showVisualContextMenuEffect(); // [RLVa:KB] - Checked: 2010-04-11 (RLVa-1.2.el) | Modified: RLVa-1.1.0l diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index e32525a9d..c009980e1 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -249,11 +249,11 @@ LLMenuGL *gPopupMenuView = NULL; LLMenuBarGL *gLoginMenuBarView = NULL; // Pie menus -LLPieMenu *gPieSelf = NULL; -LLPieMenu *gPieAvatar = NULL; -LLPieMenu *gPieObject = NULL; -LLPieMenu *gPieAttachment = NULL; -LLPieMenu *gPieLand = NULL; +LLContextMenu *gPieSelf = NULL; +LLContextMenu *gPieAvatar = NULL; +LLContextMenu *gPieObject = NULL; +LLContextMenu *gPieAttachment = NULL; +LLContextMenu *gPieLand = NULL; // local constants const std::string CLIENT_MENU_NAME("Advanced"); @@ -266,13 +266,13 @@ LLMenuGL* gAttachSubMenu = NULL; LLMenuGL* gDetachSubMenu = NULL; LLMenuGL* gTakeOffClothes = NULL; LLMenuGL* gMeshesAndMorphsMenu = NULL; -LLPieMenu* gPieRate = NULL; -LLPieMenu* gAttachScreenPieMenu = NULL; -LLPieMenu* gAttachPieMenu = NULL; -LLPieMenu* gAttachBodyPartPieMenus[8]; -LLPieMenu* gDetachPieMenu = NULL; -LLPieMenu* gDetachScreenPieMenu = NULL; -LLPieMenu* gDetachBodyPartPieMenus[8]; +LLContextMenu* gPieRate = NULL; +LLContextMenu* gAttachScreenPieMenu = NULL; +LLContextMenu* gAttachPieMenu = NULL; +LLContextMenu* gAttachBodyPartPieMenus[8]; +LLContextMenu* gDetachPieMenu = NULL; +LLContextMenu* gDetachScreenPieMenu = NULL; +LLContextMenu* gDetachBodyPartPieMenus[8]; LLMenuItemCallGL* gAFKMenu = NULL; LLMenuItemCallGL* gBusyMenu = NULL; @@ -602,6 +602,42 @@ void set_underclothes_menu_options() static std::vector > sMenus; +void build_pie_menus() +{ + if (gPieSelf) delete gPieSelf; + gPieSelf = LLUICtrlFactory::getInstance()->buildContextMenu("menu_pie_self.xml", gMenuHolder); + + // TomY TODO: what shall we do about these? + gDetachScreenPieMenu = gMenuHolder->getChild("Object Detach HUD", true); + gDetachPieMenu = gMenuHolder->getChild("Object Detach", true); + + if (gPieAvatar) delete gPieAvatar; + gPieAvatar = LLUICtrlFactory::getInstance()->buildContextMenu("menu_pie_avatar.xml", gMenuHolder); + + if (gPieObject) delete gPieObject; + gPieObject = LLUICtrlFactory::getInstance()->buildContextMenu("menu_pie_object.xml", gMenuHolder); + + gAttachScreenPieMenu = gMenuHolder->getChild("Object Attach HUD"); + gAttachPieMenu = gMenuHolder->getChild("Object Attach"); + gPieRate = gMenuHolder->getChild("Rate Menu"); + + if (gPieAttachment) delete gPieAttachment; + gPieAttachment = LLUICtrlFactory::getInstance()->buildContextMenu("menu_pie_attachment.xml", gMenuHolder); + + if (gPieLand) delete gPieLand; + gPieLand = LLUICtrlFactory::getInstance()->buildContextMenu("menu_pie_land.xml", gMenuHolder); +} + +void rebuild_context_menus() +{ + llassert_always(gMenuHolder); + if (!gMenuHolder) return; // This should never happen, if it does, don't do anything, menus haven't been built yet or were destroyed. + gMenuHolder->hideMenus(); + build_pie_menus(); + if (!gAgentAvatarp) return; // The agent's avatar isn't here yet, don't bother with the dynamic attach/detach submenus. + gAgentAvatarp->buildContextMenus(); +} + void init_menus() { S32 top = gViewerWindow->getRootView()->getRect().getHeight(); @@ -633,36 +669,15 @@ void init_menus() /// /// Pie menus /// - gPieSelf = LLUICtrlFactory::getInstance()->buildPieMenu("menu_pie_self.xml", gMenuHolder); + build_pie_menus(); + gSavedSettings.getControl("LiruUseContextMenus")->getSignal()->connect(boost::bind(rebuild_context_menus)); - // TomY TODO: what shall we do about these? - gDetachScreenPieMenu = gMenuHolder->getChild("Object Detach HUD", true); - gDetachPieMenu = gMenuHolder->getChild("Object Detach", true); - - gPieAvatar = LLUICtrlFactory::getInstance()->buildPieMenu("menu_pie_avatar.xml", gMenuHolder); - - gPieObject = LLUICtrlFactory::getInstance()->buildPieMenu("menu_pie_object.xml", gMenuHolder); - - gAttachScreenPieMenu = gMenuHolder->getChild("Object Attach HUD"); - gAttachPieMenu = gMenuHolder->getChild("Object Attach"); - gPieRate = gMenuHolder->getChild("Rate Menu"); - - gPieAttachment = LLUICtrlFactory::getInstance()->buildPieMenu("menu_pie_attachment.xml", gMenuHolder); - - gPieLand = LLUICtrlFactory::getInstance()->buildPieMenu("menu_pie_land.xml", gMenuHolder); /// /// set up the colors /// LLColor4 color; - LLColor4 pie_color = gColors.getColor("PieMenuBgColor"); - gPieSelf->setBackgroundColor( pie_color ); - gPieAvatar->setBackgroundColor( pie_color ); - gPieObject->setBackgroundColor( pie_color ); - gPieAttachment->setBackgroundColor( pie_color ); - gPieLand->setBackgroundColor( pie_color ); - color = gColors.getColor( "MenuPopupBgColor" ); gPopupMenuView->setBackgroundColor( color ); @@ -5549,7 +5564,7 @@ class LLEditDelete : public view_listener_t // When deleting an object we may not actually be done // Keep selection so we know what to delete when confirmation is needed about the delete - gPieObject->hide(TRUE); + gPieObject->hide(); return true; } }; @@ -5669,7 +5684,7 @@ void handle_object_delete() // When deleting an object we may not actually be done // Keep selection so we know what to delete when confirmation is needed about the delete - gPieObject->hide(TRUE); + gPieObject->hide(); return; } diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index 6d3c2947f..b45cf7633 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -167,24 +167,24 @@ extern LLViewerMenuHolderGL* gMenuHolder; extern LLMenuBarGL* gLoginMenuBarView; // Pie menus -extern LLPieMenu *gPieSelf; -extern LLPieMenu *gPieAvatar; -extern LLPieMenu *gPieObject; -extern LLPieMenu *gPieAttachment; -extern LLPieMenu *gPieLand; -extern LLPieMenu *gPieRate; +extern LLContextMenu *gPieSelf; +extern LLContextMenu *gPieAvatar; +extern LLContextMenu *gPieObject; +extern LLContextMenu *gPieAttachment; +extern LLContextMenu *gPieLand; +extern LLContextMenu *gPieRate; // Needed to build menus when attachment site list available extern LLMenuGL* gAttachSubMenu; extern LLMenuGL* gDetachSubMenu; extern LLMenuGL* gTakeOffClothes; extern LLMenuGL* gMeshesAndMorphsMenu; -extern LLPieMenu* gAttachScreenPieMenu; -extern LLPieMenu* gDetachScreenPieMenu; -extern LLPieMenu* gAttachPieMenu; -extern LLPieMenu* gDetachPieMenu; -extern LLPieMenu* gAttachBodyPartPieMenus[8]; -extern LLPieMenu* gDetachBodyPartPieMenus[8]; +extern LLContextMenu* gAttachScreenPieMenu; +extern LLContextMenu* gDetachScreenPieMenu; +extern LLContextMenu* gAttachPieMenu; +extern LLContextMenu* gDetachPieMenu; +extern LLContextMenu* gAttachBodyPartPieMenus[8]; +extern LLContextMenu* gDetachBodyPartPieMenus[8]; extern LLMenuItemCallGL* gAFKMenu; extern LLMenuItemCallGL* gBusyMenu; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index fb0264b56..b1523682d 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -4458,7 +4458,9 @@ void process_teleport_finish(LLMessageSystem* msg, void**) // Aurora Sim U32 region_size_x = 256; msg->getU32Fast(_PREHASH_Info, _PREHASH_RegionSizeX, region_size_x); - LLWorld::getInstance()->setRegionWidth(region_size_x); + U32 region_size_y = 256; + msg->getU32Fast(_PREHASH_Info, _PREHASH_RegionSizeY, region_size_y); + LLWorld::getInstance()->setRegionSize(region_size_x, region_size_y); // Aurora Sim LLViewerRegion* regionp = LLWorld::getInstance()->addRegion(region_handle, sim_host); @@ -4788,7 +4790,9 @@ void process_crossed_region(LLMessageSystem* msg, void**) // Aurora Sim U32 region_size_x = 256; msg->getU32(_PREHASH_RegionData, _PREHASH_RegionSizeX, region_size_x); - LLWorld::getInstance()->setRegionWidth(region_size_x); + U32 region_size_y = 256; + msg->getU32(_PREHASH_RegionData, _PREHASH_RegionSizeY, region_size_y); + LLWorld::getInstance()->setRegionSize(region_size_x, region_size_y); // Aurora Sim LLViewerRegion* regionp = LLWorld::getInstance()->addRegion(region_handle, sim_host); regionp->setSeedCapability(seedCap); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 57d7e2cc9..6df2a4f28 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -165,7 +165,8 @@ LLGLSLShader gUnderWaterProgram(LLViewerShaderMgr::SHADER_WATER); //interface shaders LLGLSLShader gHighlightProgram(LLViewerShaderMgr::SHADER_INTERFACE); //Not in mShaderList - +LLGLSLShader gHighlightNormalProgram(LLViewerShaderMgr::SHADER_INTERFACE); +LLGLSLShader gHighlightSpecularProgram(LLViewerShaderMgr::SHADER_INTERFACE); //avatar shader handles LLGLSLShader gAvatarProgram(LLViewerShaderMgr::SHADER_AVATAR); LLGLSLShader gAvatarWaterProgram(LLViewerShaderMgr::SHADER_AVATAR); @@ -2805,6 +2806,26 @@ BOOL LLViewerShaderMgr::loadShadersInterface() success = gHighlightProgram.createShader(NULL, NULL); } + if (success) + { + gHighlightNormalProgram.mName = "Highlight Normals Shader"; + gHighlightNormalProgram.mShaderFiles.clear(); + gHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightNormV.glsl", GL_VERTEX_SHADER_ARB)); + gHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gHighlightNormalProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + success = gHighlightNormalProgram.createShader(NULL, NULL); + } + + if (success) + { + gHighlightSpecularProgram.mName = "Highlight Spec Shader"; + gHighlightSpecularProgram.mShaderFiles.clear(); + gHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightSpecV.glsl", GL_VERTEX_SHADER_ARB)); + gHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gHighlightSpecularProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + success = gHighlightSpecularProgram.createShader(NULL, NULL); + } + if (success) { gUIProgram.mName = "UI Shader"; diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index 8ccd77d4b..320c25828 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -273,6 +273,8 @@ extern LLGLSLShader gGlowExtractProgram; //interface shaders extern LLGLSLShader gHighlightProgram; +extern LLGLSLShader gHighlightNormalProgram; +extern LLGLSLShader gHighlightSpecularProgram; // avatar shader handles extern LLGLSLShader gAvatarProgram; diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 6fdd2c277..ab2833220 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -325,29 +325,55 @@ BOOL LLVOAvatarSelf::buildMenus() //------------------------------------------------------------------------- if(gNoRender) return TRUE; - gAttachBodyPartPieMenus[0] = NULL; - gAttachBodyPartPieMenus[1] = new LLPieMenu(LLTrans::getString("BodyPartsRightArm") + " >"); - gAttachBodyPartPieMenus[2] = new LLPieMenu(LLTrans::getString("BodyPartsHead") + " >"); - gAttachBodyPartPieMenus[3] = new LLPieMenu(LLTrans::getString("BodyPartsLeftArm") + " >"); - gAttachBodyPartPieMenus[4] = NULL; - gAttachBodyPartPieMenus[5] = new LLPieMenu(LLTrans::getString("BodyPartsLeftLeg") + " >"); - gAttachBodyPartPieMenus[6] = new LLPieMenu(LLTrans::getString("BodyPartsTorso") + " >"); - gAttachBodyPartPieMenus[7] = new LLPieMenu(LLTrans::getString("BodyPartsRightLeg") + " >"); + buildContextMenus(); - gDetachBodyPartPieMenus[0] = NULL; - gDetachBodyPartPieMenus[1] = new LLPieMenu(LLTrans::getString("BodyPartsRightArm") + " >"); - gDetachBodyPartPieMenus[2] = new LLPieMenu(LLTrans::getString("BodyPartsHead") + " >"); - gDetachBodyPartPieMenus[3] = new LLPieMenu(LLTrans::getString("BodyPartsLeftArm") + " >"); - gDetachBodyPartPieMenus[4] = NULL; - gDetachBodyPartPieMenus[5] = new LLPieMenu(LLTrans::getString("BodyPartsLeftLeg") + " >"); - gDetachBodyPartPieMenus[6] = new LLPieMenu(LLTrans::getString("BodyPartsTorso") + " >"); - gDetachBodyPartPieMenus[7] = new LLPieMenu(LLTrans::getString("BodyPartsRightLeg") + " >"); + init_meshes_and_morphs_menu(); + + return TRUE; +} + +// Convenience function to create context or pie menu with label +static LLContextMenu* make_part_menu(const std::string& label, bool context) +{ + return context ? new LLContextMenu(label) : new LLPieMenu(label + " >"); +} + +void LLVOAvatarSelf::buildContextMenus() +{ + gAttachBodyPartPieMenus[0] = gDetachBodyPartPieMenus[0] = NULL; + + bool context(gSavedSettings.getBOOL("LiruUseContextMenus")); + std::string label = LLTrans::getString("BodyPartsRightArm"); + gAttachBodyPartPieMenus[1] = make_part_menu(label, context); + gDetachBodyPartPieMenus[1] = make_part_menu(label, context); + + label = LLTrans::getString("BodyPartsHead"); + gAttachBodyPartPieMenus[2] = make_part_menu(label, context); + gDetachBodyPartPieMenus[2] = make_part_menu(label, context); + + label = LLTrans::getString("BodyPartsLeftArm"); + gAttachBodyPartPieMenus[3] = make_part_menu(label, context); + gDetachBodyPartPieMenus[3] = make_part_menu(label, context); + + gAttachBodyPartPieMenus[4] = gDetachBodyPartPieMenus[4] = NULL; + + label = LLTrans::getString("BodyPartsLeftLeg"); + gAttachBodyPartPieMenus[5] = make_part_menu(label, context); + gDetachBodyPartPieMenus[5] = make_part_menu(label, context); + + label = LLTrans::getString("BodyPartsTorso"); + gAttachBodyPartPieMenus[6] = make_part_menu(label, context); + gDetachBodyPartPieMenus[6] = make_part_menu(label, context); + + label = LLTrans::getString("BodyPartsRightLeg"); + gAttachBodyPartPieMenus[7] = make_part_menu(label, context); + gDetachBodyPartPieMenus[7] = make_part_menu(label, context); for (S32 i = 0; i < 8; i++) { if (gAttachBodyPartPieMenus[i]) { - gAttachPieMenu->appendPieMenu( gAttachBodyPartPieMenus[i] ); + gAttachPieMenu->appendContextSubMenu( gAttachBodyPartPieMenus[i] ); } else { @@ -379,7 +405,7 @@ BOOL LLVOAvatarSelf::buildMenus() } } - if (!attachment_found) + if (!context && !attachment_found) { gAttachPieMenu->addSeparator(); } @@ -387,7 +413,7 @@ BOOL LLVOAvatarSelf::buildMenus() if (gDetachBodyPartPieMenus[i]) { - gDetachPieMenu->appendPieMenu( gDetachBodyPartPieMenus[i] ); + gDetachPieMenu->appendContextSubMenu( gDetachBodyPartPieMenus[i] ); } else { @@ -407,7 +433,7 @@ BOOL LLVOAvatarSelf::buildMenus() } } - if (!attachment_found) + if (!context && !attachment_found) { gDetachPieMenu->addSeparator(); } @@ -466,7 +492,7 @@ BOOL LLVOAvatarSelf::buildMenus() &handle_detach_from_avatar, object_attached, &detach_label, attachment)); } - if (pass == 0) + if (!context && pass == 0) { // put separator between non-hud and hud attachments gAttachSubMenu->addSeparator(); @@ -503,14 +529,17 @@ BOOL LLVOAvatarSelf::buildMenus() for (std::multimap::iterator attach_it = attachment_pie_menu_map.begin(); attach_it != attachment_pie_menu_map.end(); ++attach_it) { - S32 requested_pie_slice = attach_it->first; - S32 attach_index = attach_it->second; - while (cur_pie_slice < requested_pie_slice) + if (!context) // Singu Note: Separators are only needed to keep slices of pies from moving { - gAttachBodyPartPieMenus[group]->addSeparator(); - gDetachBodyPartPieMenus[group]->addSeparator(); - cur_pie_slice++; + S32 requested_pie_slice = attach_it->first; + while (cur_pie_slice < requested_pie_slice) + { + gAttachBodyPartPieMenus[group]->addSeparator(); + gDetachBodyPartPieMenus[group]->addSeparator(); + cur_pie_slice++; + } } + S32 attach_index = attach_it->second; LLViewerJointAttachment* attachment = get_if_there(mAttachmentPoints, attach_index, (LLViewerJointAttachment*)NULL); if (attachment) @@ -527,14 +556,10 @@ BOOL LLVOAvatarSelf::buildMenus() gDetachBodyPartPieMenus[group]->addChild(new LLMenuItemCallGL(attachment->getName(), &handle_detach_from_avatar, object_attached, attachment)); - cur_pie_slice++; + if (!context) cur_pie_slice++; } } } - - init_meshes_and_morphs_menu(); - - return TRUE; } void LLVOAvatarSelf::cleanup() diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 99e45bcff..2c9d69b8b 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -63,6 +63,7 @@ public: virtual ~LLVOAvatarSelf(); virtual void markDead(); virtual void initInstance(); // Called after construction to initialize the class. + void buildContextMenus(); void cleanup(); protected: /*virtual*/ BOOL loadAvatar(); diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 84ac30bf8..af93ec553 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -84,6 +84,7 @@ extern LLColor4U MAX_WATER_COLOR; // Aurora Sim //const U32 LLWorld::mWidth = 256; U32 LLWorld::mWidth = 256; +U32 LLWorld::mLength = 256; // Aurora Sim // meters/point, therefore mWidth * mScale = meters per edge @@ -152,9 +153,10 @@ void LLWorld::destroyClass() } } -void LLWorld::setRegionWidth(const U32 width) +void LLWorld::setRegionSize(const U32& width, const U32& length) { mWidth = width ? width : 256; // Width of 0 is really 256 + mLength = length ? length : 256; // Length of 0 is really 256 mWidthInMeters = mWidth * mScale; } @@ -247,7 +249,7 @@ LLViewerRegion* LLWorld::addRegion(const U64 ®ion_handle, const LLHost &host) adj_x = region_x + width * gDirAxes[dir][0]; adj_y = region_y + width * gDirAxes[dir][1]; - if (mWidth == 256) + if (mWidth == 256 && mLength == 256) { to_region_handle(adj_x, adj_y, &adj_handle); neighborp = getRegionFromHandle(adj_handle); @@ -1361,7 +1363,9 @@ void process_enable_simulator(LLMessageSystem *msg, void **user_data) // Aurora Sim U32 region_size_x = 256; msg->getU32Fast(_PREHASH_SimulatorInfo, _PREHASH_RegionSizeX, region_size_x); - LLWorld::getInstance()->setRegionWidth(region_size_x); + U32 region_size_y = 256; + msg->getU32Fast(_PREHASH_SimulatorInfo, _PREHASH_RegionSizeY, region_size_y); + LLWorld::getInstance()->setRegionSize(region_size_x, region_size_y); // Aurora Sim LLWorld::getInstance()->addRegion(handle, sim); diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h index 291159540..b363d0d67 100644 --- a/indra/newview/llworld.h +++ b/indra/newview/llworld.h @@ -115,7 +115,7 @@ public: LLVector3 resolveLandNormalGlobal(const LLVector3d &position); // absolute frame // update region size - void setRegionWidth(const U32 width = 0); + void setRegionSize(const U32& width = 0, const U32& length = 0); U32 getRegionWidthInPoints() const { return mWidth; } F32 getRegionScale() const { return mScale; } @@ -188,6 +188,7 @@ private: // Aurora Sim //static const U32 mWidth; static U32 mWidth; + static U32 mLength; // Aurora Sim // meters/point, therefore mWidth * mScale = meters per edge diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 23192c52a..6931b21d7 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -109,6 +109,8 @@ #include "llwaterparammanager.h" #include "llspatialpartition.h" #include "llmutelist.h" +#include "llfloatertools.h" +#include "llpanelface.h" // [RLVa:KB] - Checked: 2011-05-22 (RLVa-1.3.1a) #include "rlvhandler.h" @@ -319,6 +321,7 @@ BOOL LLPipeline::sRenderParticleBeacons = FALSE; BOOL LLPipeline::sRenderSoundBeacons = FALSE; BOOL LLPipeline::sRenderBeacons = FALSE; BOOL LLPipeline::sRenderHighlight = TRUE; +LLRender::eTexIndex LLPipeline::sRenderHighlightTextureChannel = LLRender::DIFFUSE_MAP; BOOL LLPipeline::sForceOldBakedUpload = FALSE; S32 LLPipeline::sUseOcclusion = 0; BOOL LLPipeline::sDelayVBUpdate = FALSE; @@ -3839,6 +3842,8 @@ void LLPipeline::postSort(LLCamera& camera) { mSelectedFaces.clear(); + LLPipeline::setRenderHighlightTextureChannel(gFloaterTools->getPanelFace()->getTextureChannelToEdit()); + // Draw face highlights for selected faces. if (LLSelectMgr::getInstance()->getTEMode()) { @@ -3938,13 +3943,14 @@ void LLPipeline::renderHighlights() gGL.diffuseColor4f(1,1,1,0.5f); } - if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED)) + if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && !mFaceSelectImagep) + { + mFaceSelectImagep = LLViewerTextureManager::getFetchedTexture(IMG_FACE_SELECT); + } + + if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::DIFFUSE_MAP)) { // Make sure the selection image gets downloaded and decoded - if (!mFaceSelectImagep) - { - mFaceSelectImagep = LLViewerTextureManager::getFetchedTexture(IMG_FACE_SELECT); - } mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); U32 count = mSelectedFaces.size(); @@ -3982,6 +3988,67 @@ void LLPipeline::renderHighlights() { gHighlightProgram.unbind(); } + + + if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::NORMAL_MAP)) + { + color.setVec(1.0f, 0.5f, 0.5f, 0.5f); + if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + { + gHighlightNormalProgram.bind(); + gGL.diffuseColor4f(1,1,1,0.5f); + } + + mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); + + U32 count = mSelectedFaces.size(); + for (U32 i = 0; i < count; i++) + { + LLFace *facep = mSelectedFaces[i]; + if (!facep || facep->getDrawable()->isDead()) + { + llerrs << "Bad face on selection" << llendl; + return; + } + + facep->renderSelected(mFaceSelectImagep, color); + } + + if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + { + gHighlightNormalProgram.unbind(); + } + } + + if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::SPECULAR_MAP)) + { + color.setVec(0.0f, 0.3f, 1.0f, 0.8f); + if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + { + gHighlightSpecularProgram.bind(); + gGL.diffuseColor4f(1,1,1,0.5f); + } + + mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); + + U32 count = mSelectedFaces.size(); + for (U32 i = 0; i < count; i++) + { + LLFace *facep = mSelectedFaces[i]; + if (!facep || facep->getDrawable()->isDead()) + { + llerrs << "Bad face on selection" << llendl; + return; + } + + facep->renderSelected(mFaceSelectImagep, color); + } + + if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)) + { + gHighlightSpecularProgram.unbind(); + } + } } //debug use @@ -6399,6 +6466,12 @@ BOOL LLPipeline::getRenderHighlights(void*) return sRenderHighlight; } +// static +void LLPipeline::setRenderHighlightTextureChannel(LLRender::eTexIndex channel) +{ + sRenderHighlightTextureChannel = channel; +} + LLVOPartGroup* LLPipeline::lineSegmentIntersectParticle(const LLVector4a& start, const LLVector4a& end, LLVector4a* intersection, S32* face_hit) { diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 75f03f52c..453512d80 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -413,6 +413,7 @@ public: static void setRenderHighlights(BOOL val); static void toggleRenderHighlights(void* data); static BOOL getRenderHighlights(void* data); + static void setRenderHighlightTextureChannel(LLRender::eTexIndex channel); // sets which UV setup to display in highlight overlay static void updateRenderDeferred(); static void refreshCachedSettings(); @@ -837,6 +838,10 @@ public: static BOOL sRenderBeacons; static BOOL sRenderHighlight; + // Determines which set of UVs to use in highlight display + // + static LLRender::eTexIndex sRenderHighlightTextureChannel; + //debug use static U32 sCurRenderPoolType ; }; diff --git a/indra/newview/skins/default/textures/Edit_Flip_X.png b/indra/newview/skins/default/textures/Edit_Flip_X.png new file mode 100644 index 000000000..5106b4359 Binary files /dev/null and b/indra/newview/skins/default/textures/Edit_Flip_X.png differ diff --git a/indra/newview/skins/default/textures/materials_ui_x_24.png b/indra/newview/skins/default/textures/materials_ui_x_24.png new file mode 100644 index 000000000..6d8855491 Binary files /dev/null and b/indra/newview/skins/default/textures/materials_ui_x_24.png differ diff --git a/indra/newview/skins/default/xui/de/menu_pie_attachment.xml b/indra/newview/skins/default/xui/de/menu_pie_attachment.xml index da6e10ad0..dd6092c32 100644 --- a/indra/newview/skins/default/xui/de/menu_pie_attachment.xml +++ b/indra/newview/skins/default/xui/de/menu_pie_attachment.xml @@ -5,8 +5,8 @@ - - + + diff --git a/indra/newview/skins/default/xui/de/menu_pie_avatar.xml b/indra/newview/skins/default/xui/de/menu_pie_avatar.xml index 53988dd8d..6288151a6 100644 --- a/indra/newview/skins/default/xui/de/menu_pie_avatar.xml +++ b/indra/newview/skins/default/xui/de/menu_pie_avatar.xml @@ -6,11 +6,11 @@ - + - + diff --git a/indra/newview/skins/default/xui/de/menu_pie_object.xml b/indra/newview/skins/default/xui/de/menu_pie_object.xml index 254eaeb92..bf03eeb99 100644 --- a/indra/newview/skins/default/xui/de/menu_pie_object.xml +++ b/indra/newview/skins/default/xui/de/menu_pie_object.xml @@ -6,16 +6,16 @@ - + - - + + - + - + @@ -29,11 +29,11 @@ - + - + diff --git a/indra/newview/skins/default/xui/de/menu_pie_self.xml b/indra/newview/skins/default/xui/de/menu_pie_self.xml index 7184ae7cd..5f0ad5214 100644 --- a/indra/newview/skins/default/xui/de/menu_pie_self.xml +++ b/indra/newview/skins/default/xui/de/menu_pie_self.xml @@ -2,15 +2,15 @@ - - + + - + @@ -21,13 +21,13 @@ - + - + - + diff --git a/indra/newview/skins/default/xui/en-us/floater_tools.xml b/indra/newview/skins/default/xui/en-us/floater_tools.xml index 73d03d0cb..9568791e7 100644 --- a/indra/newview/skins/default/xui/en-us/floater_tools.xml +++ b/indra/newview/skins/default/xui/en-us/floater_tools.xml @@ -1355,299 +1355,11 @@ bottom_delta="-20" width="118" /> - - - - - - - - Transparency % - - - - Glow - - - - - Mapping - - - - Default - - - Planar - - - - Shininess - - - - None - - - Low - - - Medium - - - High - - - - Bumpiness - - - - None - - - Brightness - - - Darkness - - - woodgrain - - - bark - - - bricks - - - checker - - - concrete - - - crustytile - - - cutstone - - - discs - - - gravel - - - petridish - - - siding - - - stonetile - - - stucco - - - suction - - - weave - - - - - Repeats per Face - - - - - - - Rotation (degrees) - - - - Repeats Per Meter - - - Repeats Per Face - - - Repeats Per Meter - - - - - - - - + +