Extend autohide pie menu function to also work with sub menus and not only slices
parent
4646b6dd4a
commit
298f16b235
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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<PieSlice*>(item);
|
||||
PieMenu* currentSubmenu = dynamic_cast<PieMenu*>(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<PieSlice*>(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<PieMenu*>(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<PieSlice*>(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<PieSlice*>(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<PieMenu*>(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;
|
||||
|
|
|
|||
|
|
@ -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<PieChildRegistry>
|
|||
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<Params, LLMenuGL::Params>
|
||||
{
|
||||
Optional<std::string> name;
|
||||
// autohide feature to hide a disabled pie slice
|
||||
Optional<bool> start_autohide;
|
||||
// next item in an autohide chain
|
||||
Optional<bool> 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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue