|
|
|
|
@ -26,20 +26,18 @@
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "llviewerprecompiledheaders.h"
|
|
|
|
|
#include "linden_common.h"
|
|
|
|
|
|
|
|
|
|
#include "piemenu.h"
|
|
|
|
|
#include "pieslice.h"
|
|
|
|
|
#include "pieseparator.h"
|
|
|
|
|
#include "llviewercontrol.h"
|
|
|
|
|
#include "llviewerwindow.h"
|
|
|
|
|
#include "v2math.h"
|
|
|
|
|
|
|
|
|
|
// copied from LLMenuGL - Remove these lines over there when finished
|
|
|
|
|
const S32 PIE_INNER_SIZE=20; // radius of the inner pie circle
|
|
|
|
|
const F32 PIE_POPUP_FACTOR=(F32)1.7f; // pie menu size factor on popup
|
|
|
|
|
const F32 PIE_POPUP_TIME=(F32)0.25f; // time to shrink from popup size to regular size
|
|
|
|
|
const S32 PIE_OUTER_SIZE=96; // radius of the outer pie circle
|
|
|
|
|
const S32 PIE_INNER_SIZE = 20; // radius of the inner pie circle
|
|
|
|
|
const F32 PIE_POPUP_FACTOR = 1.7f; // pie menu size factor on popup
|
|
|
|
|
const F32 PIE_POPUP_TIME = 0.25f; // time to shrink from popup size to regular size
|
|
|
|
|
const S32 PIE_OUTER_SIZE = 96; // radius of the outer pie circle
|
|
|
|
|
|
|
|
|
|
// register the pie menu globally as child widget
|
|
|
|
|
static LLDefaultChildRegistry::Register<PieMenu> r1("pie_menu");
|
|
|
|
|
@ -53,61 +51,64 @@ static PieChildRegistry::Register<PieSeparator> pie_r3("pie_separator");
|
|
|
|
|
#define PIE_DRAW_BOUNDING_BOX 0 // debug
|
|
|
|
|
|
|
|
|
|
// pie slice label text positioning
|
|
|
|
|
const S32 PIE_X[] = {64,45, 0,-45,-63,-45, 0, 45};
|
|
|
|
|
const S32 PIE_Y[] = { 0,44,73, 44, 0,-44,-73,-44};
|
|
|
|
|
const S32 PIE_X[] = {64, 45, 0, -45, -63, -45, 0, 45};
|
|
|
|
|
const S32 PIE_Y[] = { 0, 44, 73, 44, 0, -44, -73, -44};
|
|
|
|
|
|
|
|
|
|
PieMenu::PieMenu(const LLContextMenu::Params& p) :
|
|
|
|
|
LLContextMenu(p)
|
|
|
|
|
{
|
|
|
|
|
LL_DEBUGS() << "PieMenu::PieMenu()" << LL_ENDL;
|
|
|
|
|
// radius, so we need this *2
|
|
|
|
|
reshape(PIE_OUTER_SIZE*2,PIE_OUTER_SIZE*2,FALSE);
|
|
|
|
|
reshape(PIE_OUTER_SIZE * 2, PIE_OUTER_SIZE * 2, FALSE);
|
|
|
|
|
// set up the font for the menu
|
|
|
|
|
mFont=LLFontGL::getFont(LLFontDescriptor("SansSerif","Pie",LLFontGL::NORMAL));
|
|
|
|
|
if(!mFont)
|
|
|
|
|
mFont = LLFontGL::getFont(LLFontDescriptor("SansSerif", "Pie", LLFontGL::NORMAL));
|
|
|
|
|
if (!mFont)
|
|
|
|
|
{
|
|
|
|
|
LL_WARNS() << "Could not find font size for Pie menu, falling back to Small font." << LL_ENDL;
|
|
|
|
|
mFont=LLFontGL::getFont(LLFontDescriptor("SansSerif","Small",LLFontGL::NORMAL));
|
|
|
|
|
mFont = LLFontGL::getFont(LLFontDescriptor("SansSerif", "Small", LLFontGL::NORMAL));
|
|
|
|
|
}
|
|
|
|
|
// set slices pointer to our own slices
|
|
|
|
|
mSlices=&mMySlices;
|
|
|
|
|
mSlices = &mMySlices;
|
|
|
|
|
// this will be the first click on the menu
|
|
|
|
|
mFirstClick=TRUE;
|
|
|
|
|
mFirstClick = true;
|
|
|
|
|
|
|
|
|
|
// clean initialisation
|
|
|
|
|
mSlice=0;
|
|
|
|
|
mSlice = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool PieMenu::addChild(LLView* child,S32 tab_group)
|
|
|
|
|
bool PieMenu::addChild(LLView* child, S32 tab_group)
|
|
|
|
|
{
|
|
|
|
|
// don't add invalid slices
|
|
|
|
|
if(!child)
|
|
|
|
|
if (!child)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// add a new slice to the menu
|
|
|
|
|
mSlices->push_back(child);
|
|
|
|
|
|
|
|
|
|
// tell the view that our menu has changed and reshape it back to correct size
|
|
|
|
|
LLUICtrl::addChild(child);
|
|
|
|
|
reshape(PIE_OUTER_SIZE*2,PIE_OUTER_SIZE*2,FALSE);
|
|
|
|
|
reshape(PIE_OUTER_SIZE * 2, PIE_OUTER_SIZE * 2, FALSE);
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PieMenu::removeChild(LLView* child)
|
|
|
|
|
{
|
|
|
|
|
// remove a slice from the menu
|
|
|
|
|
slice_list_t::iterator found_it=std::find(mSlices->begin(),mSlices->end(),child);
|
|
|
|
|
if(found_it!=mSlices->end())
|
|
|
|
|
slice_list_t::iterator found_it = std::find(mSlices->begin(), mSlices->end(), child);
|
|
|
|
|
if (found_it != mSlices->end())
|
|
|
|
|
{
|
|
|
|
|
mSlices->erase(found_it);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// tell the view that our menu has changed and reshape it back to correct size
|
|
|
|
|
LLUICtrl::removeChild(child);
|
|
|
|
|
reshape(PIE_OUTER_SIZE*2,PIE_OUTER_SIZE*2,FALSE);
|
|
|
|
|
reshape(PIE_OUTER_SIZE * 2, PIE_OUTER_SIZE * 2, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL PieMenu::handleHover(S32 x,S32 y,MASK mask)
|
|
|
|
|
BOOL PieMenu::handleHover(S32 x, S32 y, MASK mask)
|
|
|
|
|
{
|
|
|
|
|
// do nothing
|
|
|
|
|
return TRUE;
|
|
|
|
|
@ -116,8 +117,10 @@ BOOL PieMenu::handleHover(S32 x,S32 y,MASK mask)
|
|
|
|
|
void PieMenu::show(S32 x, S32 y, LLView* spawning_view)
|
|
|
|
|
{
|
|
|
|
|
// if the menu is already there, do nothing
|
|
|
|
|
if(getVisible())
|
|
|
|
|
if (getVisible())
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// play a sound
|
|
|
|
|
make_ui_sound("UISndPieMenuAppear");
|
|
|
|
|
@ -125,41 +128,49 @@ void PieMenu::show(S32 x, S32 y, LLView* spawning_view)
|
|
|
|
|
LL_DEBUGS() << "PieMenu::show(): " << x << " " << y << LL_ENDL;
|
|
|
|
|
|
|
|
|
|
// make sure the menu is always the correct size
|
|
|
|
|
reshape(PIE_OUTER_SIZE*2,PIE_OUTER_SIZE*2,FALSE);
|
|
|
|
|
reshape(PIE_OUTER_SIZE * 2, PIE_OUTER_SIZE * 2, FALSE);
|
|
|
|
|
|
|
|
|
|
// remember our center point
|
|
|
|
|
mCenterX=x;
|
|
|
|
|
mCenterY=y;
|
|
|
|
|
mCenterX = x;
|
|
|
|
|
mCenterY = y;
|
|
|
|
|
|
|
|
|
|
// get the 3D view rectangle
|
|
|
|
|
LLRect screen=LLMenuGL::sMenuContainer->getMenuRect();
|
|
|
|
|
LLRect screen = LLMenuGL::sMenuContainer->getMenuRect();
|
|
|
|
|
|
|
|
|
|
// check if the pie menu is out of bounds and move it accordingly
|
|
|
|
|
if(x-PIE_OUTER_SIZE<0)
|
|
|
|
|
x=PIE_OUTER_SIZE;
|
|
|
|
|
else if(x+PIE_OUTER_SIZE>screen.getWidth())
|
|
|
|
|
x=screen.getWidth()-PIE_OUTER_SIZE;
|
|
|
|
|
if (x - PIE_OUTER_SIZE < 0)
|
|
|
|
|
{
|
|
|
|
|
x = PIE_OUTER_SIZE;
|
|
|
|
|
}
|
|
|
|
|
else if (x + PIE_OUTER_SIZE > screen.getWidth())
|
|
|
|
|
{
|
|
|
|
|
x = screen.getWidth() - PIE_OUTER_SIZE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(y-PIE_OUTER_SIZE<screen.mBottom)
|
|
|
|
|
y=PIE_OUTER_SIZE+screen.mBottom;
|
|
|
|
|
else if(y+PIE_OUTER_SIZE-screen.mBottom>screen.getHeight())
|
|
|
|
|
y=screen.getHeight()-PIE_OUTER_SIZE+screen.mBottom;
|
|
|
|
|
if (y - PIE_OUTER_SIZE < screen.mBottom)
|
|
|
|
|
{
|
|
|
|
|
y = PIE_OUTER_SIZE + screen.mBottom;
|
|
|
|
|
}
|
|
|
|
|
else if (y + PIE_OUTER_SIZE - screen.mBottom > screen.getHeight())
|
|
|
|
|
{
|
|
|
|
|
y = screen.getHeight() - PIE_OUTER_SIZE + screen.mBottom;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// move the mouse pointer into the center of the menu
|
|
|
|
|
LLUI::setMousePositionLocal(getParent(),x,y);
|
|
|
|
|
LLUI::setMousePositionLocal(getParent(), x, y);
|
|
|
|
|
// set our drawing origin to the center of the menu, taking UI scale into account
|
|
|
|
|
LLVector2 scale=gViewerWindow->getDisplayScale();
|
|
|
|
|
setOrigin(x-PIE_OUTER_SIZE/scale.mV[VX],y-PIE_OUTER_SIZE/scale.mV[VY]);
|
|
|
|
|
LLVector2 scale = gViewerWindow->getDisplayScale();
|
|
|
|
|
setOrigin(x - PIE_OUTER_SIZE / scale.mV[VX], y - PIE_OUTER_SIZE / scale.mV[VY]);
|
|
|
|
|
// grab mouse control
|
|
|
|
|
gFocusMgr.setMouseCapture(this);
|
|
|
|
|
|
|
|
|
|
// this was the first click for the menu
|
|
|
|
|
mFirstClick=TRUE;
|
|
|
|
|
mFirstClick = true;
|
|
|
|
|
// set up the slices pointer to the menu's own slices
|
|
|
|
|
mSlices=&mMySlices;
|
|
|
|
|
mSlices = &mMySlices;
|
|
|
|
|
|
|
|
|
|
// reset enable update checks for slices
|
|
|
|
|
for (slice_list_t::iterator it = mSlices->begin(); it != mSlices->end(); it++)
|
|
|
|
|
for (slice_list_t::iterator it = mSlices->begin(); it != mSlices->end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
PieSlice* resetSlice = dynamic_cast<PieSlice*>(*it);
|
|
|
|
|
if (resetSlice)
|
|
|
|
|
@ -169,8 +180,8 @@ void PieMenu::show(S32 x, S32 y, LLView* spawning_view)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// cleanup
|
|
|
|
|
mSlice=0;
|
|
|
|
|
mOldSlice=0;
|
|
|
|
|
mSlice = NULL;
|
|
|
|
|
mOldSlice = NULL;
|
|
|
|
|
|
|
|
|
|
// draw the menu on screen
|
|
|
|
|
setVisible(TRUE);
|
|
|
|
|
@ -180,15 +191,17 @@ void PieMenu::show(S32 x, S32 y, LLView* spawning_view)
|
|
|
|
|
void PieMenu::hide()
|
|
|
|
|
{
|
|
|
|
|
// if the menu is already hidden, do nothing
|
|
|
|
|
if(!getVisible())
|
|
|
|
|
if (!getVisible())
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// make a sound when hiding
|
|
|
|
|
make_ui_sound("UISndPieMenuHide");
|
|
|
|
|
|
|
|
|
|
LL_DEBUGS() << "Clearing selections" << LL_ENDL;
|
|
|
|
|
|
|
|
|
|
mSlices=&mMySlices;
|
|
|
|
|
mSlices = &mMySlices;
|
|
|
|
|
#if PIE_POPUP_EFFECT
|
|
|
|
|
// safety in case the timer was still running
|
|
|
|
|
mPopupTimer.stop();
|
|
|
|
|
@ -199,7 +212,7 @@ void PieMenu::hide()
|
|
|
|
|
void PieMenu::setVisible(BOOL visible)
|
|
|
|
|
{
|
|
|
|
|
// hide the menu if needed
|
|
|
|
|
if(!visible)
|
|
|
|
|
if (!visible)
|
|
|
|
|
{
|
|
|
|
|
hide();
|
|
|
|
|
// clear all menus and temporary selections
|
|
|
|
|
@ -207,37 +220,37 @@ void PieMenu::setVisible(BOOL visible)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PieMenu::draw( void )
|
|
|
|
|
void PieMenu::draw()
|
|
|
|
|
{
|
|
|
|
|
// save the current OpenGL drawing matrix so we can freely modify it
|
|
|
|
|
gGL.pushMatrix();
|
|
|
|
|
|
|
|
|
|
// save the widget's rectangle for later use
|
|
|
|
|
LLRect r=getRect();
|
|
|
|
|
LLRect r = getRect();
|
|
|
|
|
|
|
|
|
|
// initialize pie scale factor for popup effect
|
|
|
|
|
F32 factor=1.f;
|
|
|
|
|
F32 factor = 1.f;
|
|
|
|
|
|
|
|
|
|
#if PIE_POPUP_EFFECT
|
|
|
|
|
// set the popup size if this was the first click on the menu
|
|
|
|
|
if(mFirstClick)
|
|
|
|
|
if (mFirstClick)
|
|
|
|
|
{
|
|
|
|
|
factor=PIE_POPUP_FACTOR;
|
|
|
|
|
factor = PIE_POPUP_FACTOR;
|
|
|
|
|
}
|
|
|
|
|
// otherwise check if the popup timer is still running
|
|
|
|
|
else if(mPopupTimer.getStarted())
|
|
|
|
|
else if (mPopupTimer.getStarted())
|
|
|
|
|
{
|
|
|
|
|
// if the timer ran past the popup time, stop the timer and set the size to 1.0
|
|
|
|
|
F32 elapsedTime=mPopupTimer.getElapsedTimeF32();
|
|
|
|
|
if(elapsedTime>PIE_POPUP_TIME)
|
|
|
|
|
F32 elapsedTime = mPopupTimer.getElapsedTimeF32();
|
|
|
|
|
if (elapsedTime > PIE_POPUP_TIME)
|
|
|
|
|
{
|
|
|
|
|
factor=1.f;
|
|
|
|
|
factor = 1.f;
|
|
|
|
|
mPopupTimer.stop();
|
|
|
|
|
}
|
|
|
|
|
// otherwise calculate the size factor to make the menu shrink over time
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
factor=PIE_POPUP_FACTOR-(PIE_POPUP_FACTOR-1.f)*elapsedTime/PIE_POPUP_TIME;
|
|
|
|
|
factor = PIE_POPUP_FACTOR - (PIE_POPUP_FACTOR - 1.f) * elapsedTime / PIE_POPUP_TIME;
|
|
|
|
|
}
|
|
|
|
|
// setRect(r); // obsolete?
|
|
|
|
|
}
|
|
|
|
|
@ -245,15 +258,15 @@ void PieMenu::draw( void )
|
|
|
|
|
|
|
|
|
|
#if PIE_DRAW_BOUNDING_BOX
|
|
|
|
|
// draw a bounding box around the menu for debugging purposes
|
|
|
|
|
gl_rect_2d(0,r.getHeight(),r.getWidth(),0,LLColor4::white,FALSE);
|
|
|
|
|
gl_rect_2d(0, r.getHeight(), r.getWidth(), 0, LLColor4::white, FALSE);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// set up pie menu colors
|
|
|
|
|
LLColor4 lineColor=LLUIColorTable::instance().getColor("PieMenuLineColor");
|
|
|
|
|
LLColor4 selectedColor=LLUIColorTable::instance().getColor("PieMenuSelectedColor");
|
|
|
|
|
LLColor4 textColor=LLUIColorTable::instance().getColor("PieMenuTextColor");
|
|
|
|
|
LLColor4 bgColor=LLUIColorTable::instance().getColor("PieMenuBgColor");
|
|
|
|
|
LLColor4 borderColor=bgColor % (F32)0.3f;
|
|
|
|
|
LLColor4 lineColor = LLUIColorTable::instance().getColor("PieMenuLineColor");
|
|
|
|
|
LLColor4 selectedColor = LLUIColorTable::instance().getColor("PieMenuSelectedColor");
|
|
|
|
|
LLColor4 textColor = LLUIColorTable::instance().getColor("PieMenuTextColor");
|
|
|
|
|
LLColor4 bgColor = LLUIColorTable::instance().getColor("PieMenuBgColor");
|
|
|
|
|
LLColor4 borderColor = bgColor % 0.3f;
|
|
|
|
|
|
|
|
|
|
// if the user wants their own colors, apply them here
|
|
|
|
|
static LLCachedControl<bool> sOverridePieColors(gSavedSettings, "OverridePieColors", false);
|
|
|
|
|
@ -261,84 +274,88 @@ void PieMenu::draw( void )
|
|
|
|
|
{
|
|
|
|
|
static LLCachedControl<F32> sPieMenuOpacity(gSavedSettings, "PieMenuOpacity");
|
|
|
|
|
static LLCachedControl<F32> sPieMenuFade(gSavedSettings, "PieMenuFade");
|
|
|
|
|
bgColor=LLUIColorTable::instance().getColor("PieMenuBgColorOverride") % sPieMenuOpacity;
|
|
|
|
|
borderColor=bgColor % (1.f - sPieMenuFade);
|
|
|
|
|
selectedColor=LLUIColorTable::instance().getColor("PieMenuSelectedColorOverride");
|
|
|
|
|
bgColor = LLUIColorTable::instance().getColor("PieMenuBgColorOverride") % sPieMenuOpacity;
|
|
|
|
|
borderColor = bgColor % (1.f - sPieMenuFade);
|
|
|
|
|
selectedColor = LLUIColorTable::instance().getColor("PieMenuSelectedColorOverride");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// on first click, make the menu fade out to indicate "borderless" operation
|
|
|
|
|
if(mFirstClick)
|
|
|
|
|
borderColor%=0.f;
|
|
|
|
|
if (mFirstClick)
|
|
|
|
|
{
|
|
|
|
|
borderColor %= 0.f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// initially, the current segment is marked as invalid
|
|
|
|
|
S32 currentSegment=-1;
|
|
|
|
|
S32 currentSegment = -1;
|
|
|
|
|
|
|
|
|
|
// get the current mouse pointer position local to the pie
|
|
|
|
|
S32 x,y;
|
|
|
|
|
LLUI::getMousePositionLocal(this,&x,&y);
|
|
|
|
|
S32 x, y;
|
|
|
|
|
LLUI::getMousePositionLocal(this, &x, &y);
|
|
|
|
|
// remember to take the UI scaling into account
|
|
|
|
|
LLVector2 scale=gViewerWindow->getDisplayScale();
|
|
|
|
|
LLVector2 scale = gViewerWindow->getDisplayScale();
|
|
|
|
|
// move mouse coordinates to be relative to the pie center
|
|
|
|
|
LLVector2 mouseVector(x-PIE_OUTER_SIZE/scale.mV[VX],y-PIE_OUTER_SIZE/scale.mV[VY]);
|
|
|
|
|
LLVector2 mouseVector(x - PIE_OUTER_SIZE / scale.mV[VX], y - PIE_OUTER_SIZE / scale.mV[VY]);
|
|
|
|
|
|
|
|
|
|
// get the distance from the center point
|
|
|
|
|
F32 distance=mouseVector.length();
|
|
|
|
|
F32 distance = mouseVector.length();
|
|
|
|
|
// check if our mouse pointer is within the pie slice area
|
|
|
|
|
if(distance>PIE_INNER_SIZE && (distance<(PIE_OUTER_SIZE*factor) || mFirstClick))
|
|
|
|
|
if (distance > PIE_INNER_SIZE && (distance < (PIE_OUTER_SIZE * factor) || mFirstClick))
|
|
|
|
|
{
|
|
|
|
|
// get the angle of the mouse pointer from the center in radians
|
|
|
|
|
F32 angle=acos(mouseVector.mV[VX]/distance);
|
|
|
|
|
F32 angle = acos(mouseVector.mV[VX] / distance);
|
|
|
|
|
// if the mouse is below the middle of the pie, reverse the angle
|
|
|
|
|
if(mouseVector.mV[VY]<0)
|
|
|
|
|
angle=F_PI*2-angle;
|
|
|
|
|
if (mouseVector.mV[VY] < 0)
|
|
|
|
|
{
|
|
|
|
|
angle = F_PI * 2 - angle;
|
|
|
|
|
}
|
|
|
|
|
// rotate the angle slightly so the slices' centers are aligned correctly
|
|
|
|
|
angle+=F_PI/8;
|
|
|
|
|
angle += F_PI / 8;
|
|
|
|
|
|
|
|
|
|
// calculate slice number from the angle
|
|
|
|
|
currentSegment=(S32) (8.f*angle/(F_PI*2.f)) % 8;
|
|
|
|
|
currentSegment = (S32) (8.f * angle / (F_PI * 2.f)) % 8;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// move origin point to the center of our rectangle
|
|
|
|
|
gGL.translatef(r.getWidth() / 2, r.getHeight() / 2, 0);
|
|
|
|
|
|
|
|
|
|
// draw the general pie background
|
|
|
|
|
gl_washer_2d(PIE_OUTER_SIZE*factor,PIE_INNER_SIZE,32,bgColor,borderColor);
|
|
|
|
|
gl_washer_2d(PIE_OUTER_SIZE * factor, PIE_INNER_SIZE, 32, 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();
|
|
|
|
|
cur_item_iter = mSlices->begin();
|
|
|
|
|
|
|
|
|
|
// clear current slice pointer
|
|
|
|
|
mSlice=0;
|
|
|
|
|
mSlice = NULL;
|
|
|
|
|
// 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;
|
|
|
|
|
LLColor4 itemColor = textColor;
|
|
|
|
|
|
|
|
|
|
// clear the label and set up the starting angle to draw in
|
|
|
|
|
std::string label("");
|
|
|
|
|
F32 segmentStart = F_PI/4.f * (F32)num - F_PI / 8.f;
|
|
|
|
|
F32 segmentStart = F_PI / 4.f * (F32)num - F_PI / 8.f;
|
|
|
|
|
|
|
|
|
|
// iterate through the list of slices
|
|
|
|
|
if(cur_item_iter!=mSlices->end())
|
|
|
|
|
if (cur_item_iter != mSlices->end())
|
|
|
|
|
{
|
|
|
|
|
// get current slice item
|
|
|
|
|
LLView* item=(*cur_item_iter);
|
|
|
|
|
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);
|
|
|
|
|
PieSlice* currentSlice = dynamic_cast<PieSlice*>(item);
|
|
|
|
|
PieMenu* currentSubmenu = dynamic_cast<PieMenu*>(item);
|
|
|
|
|
// advance internally to the next slice item
|
|
|
|
|
cur_item_iter++;
|
|
|
|
|
|
|
|
|
|
// in case it is regular click slice
|
|
|
|
|
if(currentSlice)
|
|
|
|
|
if (currentSlice)
|
|
|
|
|
{
|
|
|
|
|
// get the slice label and tell the slice to check if it's supposed to be visible
|
|
|
|
|
label=currentSlice->getLabel();
|
|
|
|
|
label = currentSlice->getLabel();
|
|
|
|
|
currentSlice->updateVisible();
|
|
|
|
|
// disable it if it's not visible, pie slices never really disappear
|
|
|
|
|
BOOL slice_visible = currentSlice->getVisible();
|
|
|
|
|
@ -350,68 +367,81 @@ void PieMenu::draw( void )
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if the current slice is the start of an autohide chain, clear out previous chains
|
|
|
|
|
if(currentSlice->getStartAutohide())
|
|
|
|
|
wasAutohide=FALSE;
|
|
|
|
|
if (currentSlice->getStartAutohide())
|
|
|
|
|
{
|
|
|
|
|
wasAutohide = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check if the current slice is part of an autohide chain
|
|
|
|
|
if(currentSlice->getAutohide())
|
|
|
|
|
if (currentSlice->getAutohide())
|
|
|
|
|
{
|
|
|
|
|
// if the previous item already won the autohide, skip this item
|
|
|
|
|
if(wasAutohide)
|
|
|
|
|
if (wasAutohide)
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// look at the next item in the pie
|
|
|
|
|
LLView* lookAhead=(*cur_item_iter);
|
|
|
|
|
LLView* lookAhead = (*cur_item_iter);
|
|
|
|
|
// check if this is a normal click slice
|
|
|
|
|
PieSlice* lookSlice=dynamic_cast<PieSlice*>(lookAhead);
|
|
|
|
|
if(lookSlice)
|
|
|
|
|
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())
|
|
|
|
|
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())
|
|
|
|
|
if (lookSlice->getVisible() && lookSlice->getEnabled())
|
|
|
|
|
{
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// this item won the autohide contest
|
|
|
|
|
wasAutohide=TRUE;
|
|
|
|
|
wasAutohide = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// reset autohide chain
|
|
|
|
|
wasAutohide=FALSE;
|
|
|
|
|
wasAutohide = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check if the slice is currently enabled
|
|
|
|
|
currentSlice->updateEnabled();
|
|
|
|
|
if(!currentSlice->getEnabled())
|
|
|
|
|
if (!currentSlice->getEnabled())
|
|
|
|
|
{
|
|
|
|
|
LL_DEBUGS() << label << " is disabled" << LL_ENDL;
|
|
|
|
|
// fade the item color alpha to mark the item as disabled
|
|
|
|
|
itemColor%=(F32)0.3f;
|
|
|
|
|
itemColor %= 0.3f;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// if it's a submenu just get the label
|
|
|
|
|
else if(currentSubmenu)
|
|
|
|
|
label=currentSubmenu->getLabel();
|
|
|
|
|
else if (currentSubmenu)
|
|
|
|
|
{
|
|
|
|
|
label = currentSubmenu->getLabel();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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) && (currentSegment==num) && item->getEnabled())
|
|
|
|
|
if ((currentSlice || currentSubmenu) && (currentSegment==num) && item->getEnabled())
|
|
|
|
|
{
|
|
|
|
|
// memorize the currently highlighted slice for later
|
|
|
|
|
mSlice=item;
|
|
|
|
|
mSlice = item;
|
|
|
|
|
// if we highlighted a different slice than before, we must play a sound
|
|
|
|
|
if(mOldSlice!=mSlice)
|
|
|
|
|
if (mOldSlice != mSlice)
|
|
|
|
|
{
|
|
|
|
|
// get the appropriate UI sound and play it
|
|
|
|
|
char soundNum='0'+num;
|
|
|
|
|
std::string soundName="UISndPieMenuSliceHighlight";
|
|
|
|
|
soundName+=soundNum;
|
|
|
|
|
char soundNum = '0' + num;
|
|
|
|
|
std::string soundName = "UISndPieMenuSliceHighlight";
|
|
|
|
|
soundName += soundNum;
|
|
|
|
|
|
|
|
|
|
make_ui_sound(soundName.c_str());
|
|
|
|
|
// remember which slice we highlighted last, so we only play the sound once
|
|
|
|
|
mOldSlice=mSlice;
|
|
|
|
|
mOldSlice = mSlice;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// draw the currently highlighted pie slice
|
|
|
|
|
@ -434,12 +464,14 @@ void PieMenu::draw( void )
|
|
|
|
|
// next slice
|
|
|
|
|
num++;
|
|
|
|
|
}
|
|
|
|
|
while(num<8); // do this until the menu is full
|
|
|
|
|
while (num < 8); // do this until the menu is full
|
|
|
|
|
|
|
|
|
|
// draw inner and outer circle, outer only if it was not the first click
|
|
|
|
|
if(!mFirstClick)
|
|
|
|
|
if (!mFirstClick)
|
|
|
|
|
{
|
|
|
|
|
gl_washer_2d(PIE_OUTER_SIZE * factor, PIE_OUTER_SIZE * factor - 2.f, 32, lineColor, borderColor);
|
|
|
|
|
gl_washer_2d(PIE_INNER_SIZE+1,PIE_INNER_SIZE-1,16,borderColor,lineColor);
|
|
|
|
|
}
|
|
|
|
|
gl_washer_2d(PIE_INNER_SIZE + 1, PIE_INNER_SIZE - 1, 16, borderColor, lineColor);
|
|
|
|
|
|
|
|
|
|
// restore OpenGL drawing matrix
|
|
|
|
|
gGL.popMatrix();
|
|
|
|
|
@ -451,8 +483,10 @@ void PieMenu::draw( void )
|
|
|
|
|
BOOL PieMenu::appendContextSubMenu(PieMenu* menu)
|
|
|
|
|
{
|
|
|
|
|
LL_DEBUGS() << "PieMenu::appendContextSubMenu()" << LL_ENDL;
|
|
|
|
|
if(!menu)
|
|
|
|
|
if (!menu)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LL_DEBUGS() << "PieMenu::appendContextSubMenu() appending " << menu->getLabel() << " to " << getLabel() << LL_ENDL;
|
|
|
|
|
|
|
|
|
|
@ -460,28 +494,29 @@ BOOL PieMenu::appendContextSubMenu(PieMenu* menu)
|
|
|
|
|
mSlices->push_back(menu);
|
|
|
|
|
// tell the view that our menu has changed
|
|
|
|
|
LLUICtrl::addChild(menu);
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL PieMenu::handleMouseUp(S32 x,S32 y,MASK mask)
|
|
|
|
|
BOOL PieMenu::handleMouseUp(S32 x, S32 y, MASK mask)
|
|
|
|
|
{
|
|
|
|
|
// left and right mouse buttons both do the same thing currently
|
|
|
|
|
return handleMouseButtonUp(x,y,mask);
|
|
|
|
|
return handleMouseButtonUp(x, y, mask);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL PieMenu::handleRightMouseUp(S32 x,S32 y,MASK mask)
|
|
|
|
|
BOOL PieMenu::handleRightMouseUp(S32 x, S32 y, MASK mask)
|
|
|
|
|
{
|
|
|
|
|
// left and right mouse buttons both do the same thing currently
|
|
|
|
|
return handleMouseButtonUp(x,y,mask);
|
|
|
|
|
return handleMouseButtonUp(x, y, mask);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// left and right mouse buttons both do the same thing currently
|
|
|
|
|
BOOL PieMenu::handleMouseButtonUp(S32 x,S32 y,MASK mask)
|
|
|
|
|
BOOL PieMenu::handleMouseButtonUp(S32 x, S32 y, MASK mask)
|
|
|
|
|
{
|
|
|
|
|
// if this was the first click and no slice is highlighted (no borderless click), start the popup timer
|
|
|
|
|
if(mFirstClick && !mSlice)
|
|
|
|
|
if (mFirstClick && !mSlice)
|
|
|
|
|
{
|
|
|
|
|
mFirstClick=FALSE;
|
|
|
|
|
mFirstClick = false;
|
|
|
|
|
#if PIE_POPUP_EFFECT
|
|
|
|
|
mPopupTimer.start();
|
|
|
|
|
#endif
|
|
|
|
|
@ -489,11 +524,11 @@ BOOL PieMenu::handleMouseButtonUp(S32 x,S32 y,MASK mask)
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// default to invisible
|
|
|
|
|
BOOL visible=FALSE;
|
|
|
|
|
BOOL visible = FALSE;
|
|
|
|
|
|
|
|
|
|
// get the current selected slice and check if this is a regular click slice
|
|
|
|
|
PieSlice* currentSlice=dynamic_cast<PieSlice*>(mSlice);
|
|
|
|
|
if(currentSlice)
|
|
|
|
|
PieSlice* currentSlice = dynamic_cast<PieSlice*>(mSlice);
|
|
|
|
|
if (currentSlice)
|
|
|
|
|
{
|
|
|
|
|
// if so, click it and make a sound
|
|
|
|
|
make_ui_sound("UISndClickRelease");
|
|
|
|
|
@ -502,15 +537,15 @@ BOOL PieMenu::handleMouseButtonUp(S32 x,S32 y,MASK mask)
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// check if this was a submenu
|
|
|
|
|
PieMenu* currentSubmenu=dynamic_cast<PieMenu*>(mSlice);
|
|
|
|
|
if(currentSubmenu)
|
|
|
|
|
PieMenu* currentSubmenu = dynamic_cast<PieMenu*>(mSlice);
|
|
|
|
|
if (currentSubmenu)
|
|
|
|
|
{
|
|
|
|
|
// if so, remember we clicked the menu already at least once
|
|
|
|
|
mFirstClick=FALSE;
|
|
|
|
|
mFirstClick = false;
|
|
|
|
|
// swap out the list of items for the ones in the submenu
|
|
|
|
|
mSlices=¤tSubmenu->mMySlices;
|
|
|
|
|
mSlices = ¤tSubmenu->mMySlices;
|
|
|
|
|
// reset enable update checks for slices
|
|
|
|
|
for (slice_list_t::iterator it = mSlices->begin(); it != mSlices->end(); it++)
|
|
|
|
|
for (slice_list_t::iterator it = mSlices->begin(); it != mSlices->end(); ++it)
|
|
|
|
|
{
|
|
|
|
|
PieSlice* resetSlice = dynamic_cast<PieSlice*>(*it);
|
|
|
|
|
if (resetSlice)
|
|
|
|
|
@ -519,7 +554,7 @@ BOOL PieMenu::handleMouseButtonUp(S32 x,S32 y,MASK mask)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// the menu stays visible
|
|
|
|
|
visible=TRUE;
|
|
|
|
|
visible = TRUE;
|
|
|
|
|
#if PIE_POPUP_EFFECT
|
|
|
|
|
// restart the popup timer
|
|
|
|
|
mPopupTimer.reset();
|
|
|
|
|
@ -533,9 +568,11 @@ BOOL PieMenu::handleMouseButtonUp(S32 x,S32 y,MASK mask)
|
|
|
|
|
setVisible(visible);
|
|
|
|
|
}
|
|
|
|
|
// release mouse capture after the first click if we still have it grabbed
|
|
|
|
|
if(hasMouseCapture())
|
|
|
|
|
if (hasMouseCapture())
|
|
|
|
|
{
|
|
|
|
|
gFocusMgr.setMouseCapture(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// give control back to the system
|
|
|
|
|
return LLView::handleMouseUp(x,y,mask);
|
|
|
|
|
return LLView::handleMouseUp(x, y, mask);
|
|
|
|
|
}
|
|
|
|
|
|