diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 402350233c..f8300069ac 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -845,6 +845,7 @@ set(viewer_SOURCE_FILES noise.cpp particleeditor.cpp permissionstracker.cpp + pieautohide.cpp piemenu.cpp pieseparator.cpp pieslice.cpp @@ -1646,6 +1647,7 @@ set(viewer_HEADER_FILES noise.h particleeditor.h permissionstracker.h + pieautohide.h piemenu.h pieseparator.h pieslice.h diff --git a/indra/newview/pieautohide.cpp b/indra/newview/pieautohide.cpp new file mode 100644 index 0000000000..c8d64f822d --- /dev/null +++ b/indra/newview/pieautohide.cpp @@ -0,0 +1,45 @@ +/** + * @file pieautohide.cpp + * @brief Pie menu autohide base class + * + * $LicenseInfo:firstyear=2024&license=fsviewerlgpl$ + * Phoenix Firestorm Viewer Source Code + * Copyright (C) 2024, The Phoenix Firestorm Project, 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 + * + * The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA + * http://www.firestormviewer.org + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "pieautohide.h" + + +PieAutohide::PieAutohide(bool autohide, bool startAutohide) : mAutohide(autohide), mStartAutohide(startAutohide) {} + +// accessor +bool PieAutohide::getStartAutohide() const +{ + return mStartAutohide; +} + +// accessor +bool PieAutohide::getAutohide() const +{ + return mStartAutohide || mAutohide; +} diff --git a/indra/newview/pieautohide.h b/indra/newview/pieautohide.h new file mode 100644 index 0000000000..041df6d32d --- /dev/null +++ b/indra/newview/pieautohide.h @@ -0,0 +1,48 @@ +/** + * @file pieautohide.h + * @brief Pie menu autohide base class + * + * $LicenseInfo:firstyear=2024&license=fsviewerlgpl$ + * Phoenix Firestorm Viewer Source Code + * Copyright (C) 2024, The Phoenix Firestorm Project, 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 + * + * The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA + * http://www.firestormviewer.org + * $/LicenseInfo$ + */ + +#ifndef PIEAUTOHIDE_H +#define PIEAUTOHIDE_H + +#include "lluictrl.h" + +// A slice in the pie that supports the auto-hide function. +class PieAutohide +{ +public: + PieAutohide(bool autohide, bool startAutohide); + + // accessor to expose the autohide feature + bool getStartAutohide() const; + bool getAutohide() const; + +protected: + bool mStartAutohide{ false }; + bool mAutohide{ false }; +}; + +#endif // PIEAUTOHIDE_H diff --git a/indra/newview/piemenu.cpp b/indra/newview/piemenu.cpp index a8d62c180d..1147cd13a4 100644 --- a/indra/newview/piemenu.cpp +++ b/indra/newview/piemenu.cpp @@ -56,8 +56,9 @@ constexpr F32 PIE_OUTER_SHADE_FACTOR = 1.09f; // size factor of the outer shad constexpr F32 PIE_SLICE_DIVIDER_WIDTH = 0.04f; // width of a slice divider in radians constexpr F32 PIE_MAX_SLICES_F = F32(PIE_MAX_SLICES); -PieMenu::PieMenu(const LLMenuGL::Params& p) : +PieMenu::PieMenu(const Params& p) : LLMenuGL(p), + PieAutohide(p.autohide, p.start_autohide), mCurrentSegment(-1), mOldSlice(nullptr), mSlice(nullptr), @@ -305,22 +306,21 @@ void PieMenu::draw() gl_washer_2d(PIE_OUTER_SIZE * factor, PIE_INNER_SIZE, steps, bgColor, borderColor); // set up an item list iterator to point at the beginning of the item list - slice_list_t::iterator cur_item_iter; - cur_item_iter = mSlices->begin(); + slice_list_t::iterator cur_item_iter{ mSlices->begin() }; // clear current slice pointer mSlice = nullptr; // current slice number is 0 - S32 num = 0; - bool wasAutohide = false; + S32 num{ 0 }; + bool wasAutohide{ false }; do { // standard item text color LLColor4 itemColor = textColor; // clear the label and set up the starting angle to draw in - std::string label(""); + std::string label{ "" }; F32 segmentStart = F_PI / (PIE_MAX_SLICES_F / 2.f) * (F32)num - F_PI / PIE_MAX_SLICES_F; // iterate through the list of slices @@ -328,16 +328,76 @@ void PieMenu::draw() { // get current slice item LLView* item = (*cur_item_iter); - - // check if this is a submenu or a normal click slice - PieSlice* currentSlice = dynamic_cast(item); - PieMenu* currentSubmenu = dynamic_cast(item); - // advance internally to the next slice item cur_item_iter++; + bool isSliceOrSubmenu{ false }; + + auto checkAutohide = [&](PieAutohide* autohideSlice) + { + // if the current slice is the start of an autohide chain, clear out previous chains + if (autohideSlice->getStartAutohide()) + { + wasAutohide = false; + } + + // check if the current slice is part of an autohide chain + if (autohideSlice->getAutohide()) + { + // if the previous item already won the autohide, skip this item + if (wasAutohide) + { + return true; + } + + // look at the next item in the pie + LLView* lookAhead = (*cur_item_iter); + // check if this is a normal click slice + if (PieSlice* lookSlice = dynamic_cast(lookAhead)) + { + // if the next item is part of the current autohide chain as well ... + if (lookSlice->getAutohide() && !lookSlice->getStartAutohide()) + { + // ... it's visible and it's enabled, skip the current one. + // the first visible and enabled item in autohide chains wins + // this is useful for Sit/Stand toggles + lookSlice->updateEnabled(); + lookSlice->updateVisible(); + if (lookSlice->getVisible() && lookSlice->getEnabled()) + { + return true; + } + + // this item won the autohide contest + wasAutohide = true; + } + } + else if (PieMenu* lookSlice = dynamic_cast(lookAhead)) + { + if (lookSlice->getAutohide() && !lookSlice->getStartAutohide()) + { + if (/*lookSlice->getVisible() &&*/ lookSlice->getEnabled()) // Menu is somehow always set to not visible... + { + return true; + } + + // this item won the autohide contest + wasAutohide = true; + } + } + } + else + { + // reset autohide chain + wasAutohide = false; + } + + return false; + }; // in case it is regular click slice - if (currentSlice) + if (PieSlice* currentSlice = dynamic_cast(item)) { + isSliceOrSubmenu = true; + // get the slice label and tell the slice to check if it's supposed to be visible label = currentSlice->getLabel(); currentSlice->updateVisible(); @@ -350,50 +410,8 @@ void PieMenu::draw() label = ""; } - // if the current slice is the start of an autohide chain, clear out previous chains - if (currentSlice->getStartAutohide()) - { - wasAutohide = false; - } - - // check if the current slice is part of an autohide chain - if (currentSlice->getAutohide()) - { - // if the previous item already won the autohide, skip this item - if (wasAutohide) - { - continue; - } - - // look at the next item in the pie - LLView* lookAhead = (*cur_item_iter); - // check if this is a normal click slice - PieSlice* lookSlice = dynamic_cast(lookAhead); - if (lookSlice) - { - // if the next item is part of the current autohide chain as well ... - if (lookSlice->getAutohide() && !lookSlice->getStartAutohide()) - { - // ... it's visible and it's enabled, skip the current one. - // the first visible and enabled item in autohide chains wins - // this is useful for Sit/Stand toggles - lookSlice->updateEnabled(); - lookSlice->updateVisible(); - if (lookSlice->getVisible() && lookSlice->getEnabled()) - { - continue; - } - - // this item won the autohide contest - wasAutohide = true; - } - } - } - else - { - // reset autohide chain - wasAutohide = false; - } + if (checkAutohide(currentSlice)) + continue; // check if the slice is currently enabled currentSlice->updateEnabled(); @@ -404,9 +422,14 @@ void PieMenu::draw() itemColor %= 0.3f; } } - // if it's a submenu just get the label - else if (currentSubmenu) + // if it's a submenu + else if (PieMenu* currentSubmenu = dynamic_cast(item)) { + isSliceOrSubmenu = true; + + if (checkAutohide(currentSubmenu)) + continue; + label = currentSubmenu->getLabel(); if (sPieMenuOuterRingShade) { @@ -415,7 +438,7 @@ void PieMenu::draw() } // if it's a slice or submenu, the mouse pointer is over the same segment as our counter and the item is enabled - if ((currentSlice || currentSubmenu) && (mCurrentSegment == num) && item->getEnabled()) + if (isSliceOrSubmenu && (mCurrentSegment == num) && item->getEnabled()) { // memorize the currently highlighted slice for later mSlice = item; diff --git a/indra/newview/piemenu.h b/indra/newview/piemenu.h index 40a0f0dbbe..55e2c5f70a 100644 --- a/indra/newview/piemenu.h +++ b/indra/newview/piemenu.h @@ -30,6 +30,7 @@ #include "llmenugl.h" #include "llframetimer.h" +#include "pieautohide.h" constexpr S32 PIE_MAX_SLICES = 8; @@ -39,15 +40,21 @@ struct PieChildRegistry : public LLChildRegistry LLSINGLETON_EMPTY_CTOR(PieChildRegistry); }; -class PieMenu : public LLMenuGL +class PieMenu : public LLMenuGL, public PieAutohide { public: // parameter block for the XUI factory struct Params : public LLInitParam::Block { Optional name; + // autohide feature to hide a disabled pie slice + Optional start_autohide; + // next item in an autohide chain + Optional autohide; - Params() + Params() : + start_autohide("start_autohide", false), + autohide("autohide", false) { visible = false; } @@ -56,7 +63,7 @@ public: // PieChildRegistry contains a list of allowed child types for the XUI definition typedef PieChildRegistry child_registry_t; - PieMenu(const LLMenuGL::Params& p); + PieMenu(const Params& p); /*virtual*/ void setVisible(bool visible); diff --git a/indra/newview/pieslice.cpp b/indra/newview/pieslice.cpp index 77ab4f1b96..83a037aa08 100644 --- a/indra/newview/pieslice.cpp +++ b/indra/newview/pieslice.cpp @@ -43,9 +43,8 @@ PieSlice::Params::Params() : // create a new slice and memorize the XUI parameters PieSlice::PieSlice(const PieSlice::Params& p) : LLUICtrl(p), + PieAutohide(p.autohide, p.start_autohide), mLabel(p.label), - mStartAutohide(p.start_autohide), - mAutohide(p.autohide), mCheckEnableOnce(p.check_enable_once), mDoUpdateEnabled(true) { @@ -140,18 +139,6 @@ void PieSlice::setLabel(std::string_view newLabel) mLabel = newLabel; } -// accessor -bool PieSlice::getStartAutohide() const -{ - return mStartAutohide; -} - -// accessor -bool PieSlice::getAutohide() const -{ - return mStartAutohide || mAutohide; -} - void PieSlice::resetUpdateEnabledCheck() { mDoUpdateEnabled = true; diff --git a/indra/newview/pieslice.h b/indra/newview/pieslice.h index 0643119a53..2f36447d35 100644 --- a/indra/newview/pieslice.h +++ b/indra/newview/pieslice.h @@ -29,10 +29,11 @@ #define PIESLICE_H #include "lluictrl.h" +#include "pieautohide.h" // A slice in the pie. Does nothing by itself, just stores the function and // parameter to be execued when the user clicks on this item -class PieSlice : public LLUICtrl +class PieSlice : public LLUICtrl, public PieAutohide { public: // parameter block for the XUI factory @@ -70,10 +71,6 @@ public: LLSD getValue() const; void setValue(const LLSD& value); - // accessor to expose the autohide feature - bool getStartAutohide() const; - bool getAutohide() const; - // callback connection for the onCommit method to launch the specified function boost::signals2::connection setClickCallback(const commit_signal_t::slot_type& cb) { @@ -91,8 +88,6 @@ public: protected: // accessor store std::string mLabel; - bool mStartAutohide; - bool mAutohide; bool mCheckEnableOnce; bool mDoUpdateEnabled;