svn merge -r 59234:60086 svn+ssh://svn/svn/linden/branches/live_lsl_help2 -> release

master
Richard Nelson 2007-04-05 00:59:55 +00:00
parent fd5608a3e7
commit 2ce0fc5f18
16 changed files with 564 additions and 151 deletions

View File

@ -42,3 +42,52 @@ std::ostream& operator<<(std::ostream& s, const LLColor3 &a)
s << "{ " << a.mV[VX] << ", " << a.mV[VY] << ", " << a.mV[VZ] << " }";
return s;
}
void LLColor3::calcHSL(F32* hue, F32* saturation, F32* luminance) const
{
F32 var_R = mV[VRED];
F32 var_G = mV[VGREEN];
F32 var_B = mV[VBLUE];
F32 var_Min = ( var_R < ( var_G < var_B ? var_G : var_B ) ? var_R : ( var_G < var_B ? var_G : var_B ) );
F32 var_Max = ( var_R > ( var_G > var_B ? var_G : var_B ) ? var_R : ( var_G > var_B ? var_G : var_B ) );
F32 del_Max = var_Max - var_Min;
F32 L = ( var_Max + var_Min ) / 2.0f;
F32 H = 0.0f;
F32 S = 0.0f;
if ( del_Max == 0.0f )
{
H = 0.0f;
S = 0.0f;
}
else
{
if ( L < 0.5 )
S = del_Max / ( var_Max + var_Min );
else
S = del_Max / ( 2.0f - var_Max - var_Min );
F32 del_R = ( ( ( var_Max - var_R ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
F32 del_G = ( ( ( var_Max - var_G ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
F32 del_B = ( ( ( var_Max - var_B ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
if ( var_R >= var_Max )
H = del_B - del_G;
else
if ( var_G >= var_Max )
H = ( 1.0f / 3.0f ) + del_R - del_B;
else
if ( var_B >= var_Max )
H = ( 2.0f / 3.0f ) + del_G - del_R;
if ( H < 0.0f ) H += 1.0f;
if ( H > 1.0f ) H -= 1.0f;
}
if (hue) *hue = H;
if (saturation) *saturation = S;
if (luminance) *luminance = L;
}

View File

@ -52,6 +52,8 @@ public:
mV[1] = (F32) sd[1].asReal();;
mV[2] = (F32) sd[2].asReal();;
}
void calcHSL(F32* hue, F32* saturation, F32* luminance) const;
const LLColor3& setToBlack(); // Clears LLColor3 to (0, 0, 0)
const LLColor3& setToWhite(); // Zero LLColor3 to (0, 0, 0)

View File

@ -205,6 +205,55 @@ LLColor4 vec3to4(const LLColor3 &vec)
return temp;
}
void LLColor4::calcHSL(F32* hue, F32* saturation, F32* luminance) const
{
F32 var_R = mV[VRED];
F32 var_G = mV[VGREEN];
F32 var_B = mV[VBLUE];
F32 var_Min = ( var_R < ( var_G < var_B ? var_G : var_B ) ? var_R : ( var_G < var_B ? var_G : var_B ) );
F32 var_Max = ( var_R > ( var_G > var_B ? var_G : var_B ) ? var_R : ( var_G > var_B ? var_G : var_B ) );
F32 del_Max = var_Max - var_Min;
F32 L = ( var_Max + var_Min ) / 2.0f;
F32 H = 0.0f;
F32 S = 0.0f;
if ( del_Max == 0.0f )
{
H = 0.0f;
S = 0.0f;
}
else
{
if ( L < 0.5 )
S = del_Max / ( var_Max + var_Min );
else
S = del_Max / ( 2.0f - var_Max - var_Min );
F32 del_R = ( ( ( var_Max - var_R ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
F32 del_G = ( ( ( var_Max - var_G ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
F32 del_B = ( ( ( var_Max - var_B ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
if ( var_R >= var_Max )
H = del_B - del_G;
else
if ( var_G >= var_Max )
H = ( 1.0f / 3.0f ) + del_R - del_B;
else
if ( var_B >= var_Max )
H = ( 2.0f / 3.0f ) + del_G - del_R;
if ( H < 0.0f ) H += 1.0f;
if ( H > 1.0f ) H -= 1.0f;
}
if (hue) *hue = H;
if (saturation) *saturation = S;
if (luminance) *luminance = L;
}
// static
BOOL LLColor4::parseColor(const char* buf, LLColor4* color)
{

View File

@ -54,6 +54,8 @@ class LLColor4
mV[3] = (F32) sd[3].asReal();
}
void calcHSL(F32* hue, F32* saturation, F32* luminance) const;
const LLColor4& setToBlack(); // zero LLColor4 to (0, 0, 0, 1)
const LLColor4& setToWhite(); // zero LLColor4 to (0, 0, 0, 1)

View File

@ -50,6 +50,7 @@ const F32 PIXEL_BORDER_THRESHOLD = 0.0001f;
const F32 PIXEL_CORRECTION_DISTANCE = 0.01f;
const F32 PAD_AMT = 0.5f;
const F32 DROP_SHADOW_STRENGTH = 0.3f;
F32 llfont_round_x(F32 x)
{
@ -114,7 +115,8 @@ void LLFontGL::init()
mImageGLp = new LLImageGL(FALSE);
//RN: use nearest mipmap filtering to obviate the need to do pixel-accurate positioning
mImageGLp->bind();
mImageGLp->setMipFilterNearest(TRUE, TRUE);
// we allow bilinear filtering to get sub-pixel positioning for drop shadows
//mImageGLp->setMipFilterNearest(TRUE, TRUE);
}
if (mRawImageGLp.isNull())
{
@ -530,28 +532,8 @@ S32 LLFontGL::render(const LLWString &wstr,
return 0;
}
if (style & DROP_SHADOW)
{
LLColor4 shadow_color = sShadowColor;
shadow_color[3] = color[3];
render(wstr, begin_offset,
x + 1.f / sScaleX,
y - 1.f / sScaleY,
shadow_color,
halign,
valign,
style & (~DROP_SHADOW),
max_chars,
max_pixels,
right_x,
use_embedded,
use_ellipses);
}
S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX);
BOOL render_bold = FALSE;
// HACK for better bolding
if (style & BOLD)
{
@ -566,9 +548,17 @@ S32 LLFontGL::render(const LLWString &wstr,
max_chars, max_pixels,
right_x, use_embedded);
}
else
}
F32 drop_shadow_strength = 0.f;
if (style & DROP_SHADOW)
{
F32 luminance;
color.calcHSL(NULL, NULL, &luminance);
drop_shadow_strength = clamp_rescale(luminance, 0.35f, 0.6f, 0.f, DROP_SHADOW_STRENGTH);
if (luminance < 0.35f)
{
render_bold = TRUE;
style = style & ~DROP_SHADOW;
}
}
@ -612,9 +602,6 @@ S32 LLFontGL::render(const LLWString &wstr,
}
F32 cur_x, cur_y, cur_render_x, cur_render_y;
F32 slant_offset;
slant_offset = ((style & ITALIC) ? ( -mAscender * 0.25f) : 0.f);
// Bind the font texture
@ -718,34 +705,13 @@ S32 LLFontGL::render(const LLWString &wstr,
glEnd();
glColor3f(1.f, 1.f, 1.f);
ext_image->bind();
const F32 ext_x = cur_render_x + (EXT_X_BEARING * sScaleX);
const F32 ext_y = cur_render_y + (EXT_Y_BEARING * sScaleY + mAscender - mLineHeight);
glBegin(GL_QUADS);
{
S32 num_passes = render_bold ? 2 : 1;
for (S32 pass = 0; pass < num_passes; pass++)
{
glTexCoord2f(1.f, 1.f);
glVertex2f(llfont_round_x(ext_x + ext_width + (F32)(pass * BOLD_OFFSET)),
llfont_round_y(ext_y + ext_height));
glTexCoord2f(0.f, 1.f);
glVertex2f(llfont_round_x(ext_x + (F32)(pass * BOLD_OFFSET)),
llfont_round_y(ext_y + ext_height));
glTexCoord2f(0.f, 0.f);
glVertex2f(llfont_round_x(ext_x + (F32)(pass * BOLD_OFFSET)), llfont_round_y(ext_y));
glTexCoord2f(1.f, 0.f);
glVertex2f(llfont_round_x(ext_x + ext_width + (F32)(pass * BOLD_OFFSET)),
llfont_round_y(ext_y));
}
}
glEnd();
LLRectf uv_rect(0.f, 1.f, 1.f, 0.f);
LLRectf screen_rect(ext_x, ext_y + ext_height, ext_x + ext_width, ext_y);
drawGlyph(screen_rect, uv_rect, LLColor4::white, style, drop_shadow_strength);
if (!label.empty())
{
@ -798,31 +764,21 @@ S32 LLFontGL::render(const LLWString &wstr,
// Draw the text at the appropriate location
//Specify vertices and texture coordinates
S32 num_passes = render_bold ? 2 : 1;
for (S32 pass = 0; pass < num_passes; pass++)
{
glTexCoord2f((fgi->mXBitmapOffset - PAD_AMT) * inv_width,
(fgi->mYBitmapOffset + fgi->mHeight + PAD_AMT) * inv_height);
glVertex2f(llfont_round_x(cur_render_x + (F32)fgi->mXBearing + (F32)(pass * BOLD_OFFSET) - PAD_AMT),
llfont_round_y(cur_render_y + (F32)fgi->mYBearing + PAD_AMT));
glTexCoord2f((fgi->mXBitmapOffset - PAD_AMT) * inv_width,
(fgi->mYBitmapOffset - PAD_AMT) * inv_height);
glVertex2f(llfont_round_x(cur_render_x + (F32)fgi->mXBearing + slant_offset + (F32)(pass * BOLD_OFFSET) - PAD_AMT),
llfont_round_y(cur_render_y + (F32)fgi->mYBearing - (F32)fgi->mHeight - PAD_AMT));
glTexCoord2f((fgi->mXBitmapOffset + fgi->mWidth + PAD_AMT) * inv_width,
(fgi->mYBitmapOffset - PAD_AMT) * inv_height);
glVertex2f(llfont_round_x(cur_render_x + (F32)fgi->mXBearing + slant_offset + (F32)fgi->mWidth + (F32)(pass * BOLD_OFFSET) + PAD_AMT),
llfont_round_y(cur_render_y + (F32)fgi->mYBearing - (F32)fgi->mHeight - PAD_AMT));
glTexCoord2f((fgi->mXBitmapOffset + fgi->mWidth + PAD_AMT) * inv_width,
(fgi->mYBitmapOffset + fgi->mHeight + PAD_AMT) * inv_height);
glVertex2f(llfont_round_x(cur_render_x + (F32)fgi->mXBearing + (F32)fgi->mWidth + (F32)(pass * BOLD_OFFSET) + PAD_AMT),
llfont_round_y(cur_render_y + (F32)fgi->mYBearing + PAD_AMT));
}
LLRectf uv_rect((fgi->mXBitmapOffset - PAD_AMT) * inv_width,
(fgi->mYBitmapOffset + fgi->mHeight + PAD_AMT) * inv_height,
(fgi->mXBitmapOffset + fgi->mWidth + PAD_AMT) * inv_width,
(fgi->mYBitmapOffset - PAD_AMT) * inv_height);
LLRectf screen_rect(cur_render_x + (F32)fgi->mXBearing - PAD_AMT,
cur_render_y + (F32)fgi->mYBearing + PAD_AMT,
cur_render_x + (F32)fgi->mXBearing + (F32)fgi->mWidth + PAD_AMT,
cur_render_y + (F32)fgi->mYBearing - (F32)fgi->mHeight - PAD_AMT);
drawGlyph(screen_rect, uv_rect, color, style, drop_shadow_strength);
chars_drawn++;
cur_x += fgi->mXAdvance;
cur_y += fgi->mYAdvance;
llwchar next_char = wstr[i+1];
if (next_char && (next_char < LAST_CHARACTER))
{
@ -1328,6 +1284,89 @@ void LLFontGL::removeEmbeddedChar( llwchar wc )
}
}
void LLFontGL::renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const
{
glTexCoord2f(uv_rect.mRight, uv_rect.mTop);
glVertex2f(llfont_round_x(screen_rect.mRight),
llfont_round_y(screen_rect.mTop));
glTexCoord2f(uv_rect.mLeft, uv_rect.mTop);
glVertex2f(llfont_round_x(screen_rect.mLeft),
llfont_round_y(screen_rect.mTop));
glTexCoord2f(uv_rect.mLeft, uv_rect.mBottom);
glVertex2f(llfont_round_x(screen_rect.mLeft + slant_amt),
llfont_round_y(screen_rect.mBottom));
glTexCoord2f(uv_rect.mRight, uv_rect.mBottom);
glVertex2f(llfont_round_x(screen_rect.mRight + slant_amt),
llfont_round_y(screen_rect.mBottom));
}
void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, F32 drop_shadow_strength) const
{
F32 slant_offset;
slant_offset = ((style & ITALIC) ? ( -mAscender * 0.2f) : 0.f);
glBegin(GL_QUADS);
{
//FIXME: bold and drop shadow are mutually exclusive only for convenience
//Allow both when we need them.
if (style & BOLD)
{
glColor4fv(color.mV);
for (S32 pass = 0; pass < 2; pass++)
{
LLRectf screen_rect_offset = screen_rect;
screen_rect_offset.translate((F32)(pass * BOLD_OFFSET), 0.f);
renderQuad(screen_rect_offset, uv_rect, slant_offset);
}
}
else if (style & DROP_SHADOW)
{
LLColor4 shadow_color = LLFontGL::sShadowColor;
shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength;
glColor4fv(shadow_color.mV);
for (S32 pass = 0; pass < 5; pass++)
{
LLRectf screen_rect_offset = screen_rect;
switch(pass)
{
case 0:
screen_rect_offset.translate(-1.f, -1.f);
break;
case 1:
screen_rect_offset.translate(1.f, -1.f);
break;
case 2:
screen_rect_offset.translate(1.f, 1.f);
break;
case 3:
screen_rect_offset.translate(-1.f, 1.f);
break;
case 4:
screen_rect_offset.translate(0, -2.f);
break;
}
renderQuad(screen_rect_offset, uv_rect, slant_offset);
}
glColor4fv(color.mV);
renderQuad(screen_rect, uv_rect, slant_offset);
}
else // normal rendering
{
glColor4fv(color.mV);
renderQuad(screen_rect, uv_rect, slant_offset);
}
}
glEnd();
}
// static
LLString LLFontGL::nameFromFont(const LLFontGL* fontp)
{

View File

@ -14,6 +14,7 @@
#include "llimagegl.h"
#include "v2math.h"
#include "llcoord.h"
#include "llrect.h"
class LLColor4;
@ -187,6 +188,8 @@ protected:
const embedded_data_t* getEmbeddedCharData(const llwchar wch) const;
F32 getEmbeddedCharAdvance(const embedded_data_t* ext_data) const;
void clearEmbeddedChars();
void renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const;
void drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, F32 drop_shadow_fade) const;
public:
static F32 sVertDPI;

View File

@ -782,6 +782,7 @@ void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative
mTextEntry->setCommitOnFocusLost(FALSE);
mTextEntry->setText(cur_label);
mTextEntry->setIgnoreTab(TRUE);
mTextEntry->setFollowsAll();
addChild(mTextEntry);
mMaxChars = max_chars;
}
@ -789,6 +790,8 @@ void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative
{
mTextEntry->setVisible(TRUE);
}
mButton->setFollows(FOLLOWS_BOTTOM | FOLLOWS_TOP | FOLLOWS_RIGHT);
}
else if (!allow && mAllowTextEntry)
{
@ -799,6 +802,7 @@ void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative
{
mTextEntry->setVisible(FALSE);
}
mButton->setFollowsAll();
}
mAllowTextEntry = allow;
mTextEntryTentative = set_tentative;
@ -834,6 +838,7 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor, void* user_data)
else
{
line_editor->setTentative(self->mTextEntryTentative);
self->mList->deselectAllItems();
}
return;
}

View File

@ -38,6 +38,8 @@ extern BOOL gNoRender;
const S32 MINIMIZED_WIDTH = 160;
const S32 CLOSE_BOX_FROM_TOP = 1;
// use this to control "jumping" behavior when Ctrl-Tabbing
const S32 TABBED_FLOATER_OFFSET = 0;
LLString LLFloater::sButtonActiveImageNames[BUTTON_COUNT] =
{
@ -2169,32 +2171,27 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out
void LLFloaterView::draw()
{
if( getVisible() )
refresh();
// hide focused floater if in cycle mode, so that it can be drawn on top
LLFloater* focused_floater = getFocusedFloater();
if (mFocusCycleMode && focused_floater)
{
refresh();
// hide focused floater if in cycle mode, so that it can be drawn on top
LLFloater* focused_floater = getFocusedFloater();
BOOL floater_visible = FALSE;
if (mFocusCycleMode && focused_floater)
child_list_const_iter_t child_it = getChildList()->begin();
for (;child_it != getChildList()->end(); ++child_it)
{
floater_visible = focused_floater->getVisible();
focused_floater->setVisible(FALSE);
}
// And actually do the draw
LLView::draw();
// manually draw focused floater on top when in cycle mode
if (mFocusCycleMode && focused_floater)
{
// draw focused item on top for better feedback
focused_floater->setVisible(floater_visible);
if (floater_visible)
if ((*child_it) != focused_floater)
{
drawChild(focused_floater);
drawChild(*child_it);
}
}
drawChild(focused_floater, -TABBED_FLOATER_OFFSET, TABBED_FLOATER_OFFSET);
}
else
{
LLView::draw();
}
}

View File

@ -135,6 +135,19 @@ BOOL LLScrollListCheck::handleClick()
return TRUE;
}
//
// LLScrollListSeparator
//
LLScrollListSeparator::LLScrollListSeparator(S32 width) : mWidth(width)
{
}
void LLScrollListSeparator::drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const
{
//*FIXME: use dynamic item heights and make separators narrow, and inactive
gl_line_2d(5, 8, llmax(5, width - 5), 8, color);
}
//
// LLScrollListText
//
@ -2750,6 +2763,10 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
LLRect(0, 0, width, width), "label");
new_item->setColumn(index, new LLScrollListCheck(ctrl,width));
}
else if (type == "separator")
{
new_item->setColumn(index, new LLScrollListSeparator(width));
}
else
{
new_item->setColumn(index, new LLScrollListText(value.asString(), font, width, font_style, font_alignment));

View File

@ -48,6 +48,21 @@ public:
virtual void setEnabled(BOOL enable) { }
};
class LLScrollListSeparator : public LLScrollListCell
{
public:
LLScrollListSeparator(S32 width);
virtual ~LLScrollListSeparator() {};
virtual void drawToWidth(S32 width, const LLColor4& color, const LLColor4& highlight_color) const; // truncate to given width, if possible
virtual S32 getWidth() const {return mWidth;}
virtual S32 getHeight() const { return 5; };
virtual void setWidth(S32 width) {mWidth = width; }
virtual BOOL isText() { return FALSE; }
protected:
S32 mWidth;
};
class LLScrollListText : public LLScrollListCell
{
public:

View File

@ -793,6 +793,31 @@ LLWString LLTextEditor::getWSubString(S32 pos, S32 len)
return mWText.substr(pos, len);
}
LLTextSegment* LLTextEditor::getCurrentSegment()
{
return getSegmentAtOffset(mCursorPos);
}
LLTextSegment* LLTextEditor::getPreviousSegment()
{
// find segment index at character to left of cursor (or rightmost edge of selection)
S32 idx = llmax(0, getSegmentIdxAtOffset(mCursorPos) - 1);
return idx >= 0 ? mSegments[idx] : NULL;
}
void LLTextEditor::getSelectedSegments(std::vector<LLTextSegment*>& segments)
{
S32 left = hasSelection() ? llmin(mSelectionStart, mSelectionEnd) : mCursorPos;
S32 right = hasSelection() ? llmax(mSelectionStart, mSelectionEnd) : mCursorPos;
S32 first_idx = llmax(0, getSegmentIdxAtOffset(left));
S32 last_idx = llmax(0, first_idx, getSegmentIdxAtOffset(right));
for (S32 idx = first_idx; idx <= last_idx; ++idx)
{
segments.push_back(mSegments[idx]);
}
}
S32 LLTextEditor::getCursorPosFromLocalCoord( S32 local_x, S32 local_y, BOOL round )
{
// If round is true, if the position is on the right half of a character, the cursor

View File

@ -221,6 +221,10 @@ public:
llwchar getWChar(S32 pos);
LLWString getWSubString(S32 pos, S32 len);
LLTextSegment* getCurrentSegment();
LLTextSegment* getPreviousSegment();
void getSelectedSegments(std::vector<LLTextSegment*>& segments);
protected:
S32 getLength() const;
void getSegmentAndOffset( S32 startpos, S32* segidxp, S32* offsetp );

View File

@ -275,59 +275,6 @@ destroyUI ()
}
}
//////////////////////////////////////////////////////////////////////////////
//
void
LLFloaterColorPicker::
rgbToHsl ( F32 rValIn, F32 gValIn, F32 bValIn, F32& hValOut, F32& sValOut, F32& lValOut )
{
F32 var_R = ( rValIn );
F32 var_G = ( gValIn );
F32 var_B = ( bValIn );
F32 var_Min = ( var_R < ( var_G < var_B ? var_G : var_B ) ? var_R : ( var_G < var_B ? var_G : var_B ) );
F32 var_Max = ( var_R > ( var_G > var_B ? var_G : var_B ) ? var_R : ( var_G > var_B ? var_G : var_B ) );
F32 del_Max = var_Max - var_Min;
F32 L = ( var_Max + var_Min ) / 2.0f;
F32 H = 0.0f;
F32 S = 0.0f;
if ( del_Max == 0.0f )
{
H = 0.0f;
S = 0.0f;
}
else
{
if ( L < 0.5 )
S = del_Max / ( var_Max + var_Min );
else
S = del_Max / ( 2.0f - var_Max - var_Min );
F32 del_R = ( ( ( var_Max - var_R ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
F32 del_G = ( ( ( var_Max - var_G ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
F32 del_B = ( ( ( var_Max - var_B ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
if ( var_R >= var_Max )
H = del_B - del_G;
else
if ( var_G >= var_Max )
H = ( 1.0f / 3.0f ) + del_R - del_B;
else
if ( var_B >= var_Max )
H = ( 2.0f / 3.0f ) + del_G - del_R;
if ( H < 0.0f ) H += 1.0f;
if ( H > 1.0f ) H -= 1.0f;
}
// scale to meet calculation requirements
hValOut = H * 360.0f / 360.0f;
sValOut = S * 100.0f / 100.0f;
lValOut = L * 100.0f / 100.0f;
}
//////////////////////////////////////////////////////////////////////////////
//
@ -407,7 +354,7 @@ setCurRgb ( F32 curRIn, F32 curGIn, F32 curBIn )
curB = curBIn;
// update corresponding HSL values and
rgbToHsl ( curR, curG, curB, curH, curS, curL );
LLColor3(curRIn, curGIn, curBIn).calcHSL(&curH, &curS, &curL);
// color changed so update text fields (fixes SL-16968)
// HACK: turn off the call back wilst we update the text or we recurse ourselves into oblivion
@ -706,7 +653,10 @@ getComplimentaryColor ( LLColor4& backgroundColor )
{
// going to base calculation on luminance
F32 hVal, sVal, lVal;
rgbToHsl ( backgroundColor [ 0 ], backgroundColor [ 1 ], backgroundColor [ 2 ], hVal, sVal, lVal );
backgroundColor.calcHSL(&hVal, &sVal, &lVal);
hVal *= 360.f;
sVal *= 100.f;
lVal *= 100.f;
// fairly simple heuristic for now...!
if ( lVal < 0.5f )

View File

@ -91,7 +91,6 @@ class LLFloaterColorPicker
// convert RGB to HSL and vice-versa
void hslToRgb ( F32 hValIn, F32 sValIn, F32 lValIn, F32& rValOut, F32& gValOut, F32& bValOut );
void rgbToHsl ( F32 rValIn, F32 gValIn, F32 bValIn, F32& hValOut, F32& sValOut, F32& lValOut );
F32 hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn );
void setActive(BOOL active);

View File

@ -57,6 +57,7 @@
#include "llviewertexteditor.h"
#include "llviewerwindow.h"
#include "llvieweruictrlfactory.h"
#include "llwebbrowserctrl.h"
#include "lluictrlfactory.h"
#include "viewer.h"
@ -115,6 +116,9 @@ const S32 SCRIPT_SEARCH_HEIGHT = 120;
const S32 SCRIPT_SEARCH_LABEL_WIDTH = 50;
const S32 SCRIPT_SEARCH_BUTTON_WIDTH = 80;
const S32 TEXT_EDIT_COLUMN_HEIGHT = 16;
const S32 MAX_HISTORY_COUNT = 10;
const F32 LIVE_HELP_REFRESH_TIME = 1.f;
/// ---------------------------------------------------------------------------
/// LLFloaterScriptSearch
/// ---------------------------------------------------------------------------
@ -254,6 +258,7 @@ void LLFloaterScriptSearch::open() /*Flawfinder: ignore*/
LLFloater::open(); /*Flawfinder: ignore*/
childSetFocus("search_text", TRUE);
}
/// ---------------------------------------------------------------------------
/// LLScriptEdCore
/// ---------------------------------------------------------------------------
@ -276,7 +281,9 @@ LLScriptEdCore::LLScriptEdCore(
mLoadCallback( load_callback ),
mSaveCallback( save_callback ),
mUserdata( userdata ),
mForceClose( FALSE )
mForceClose( FALSE ),
mLastHelpToken(NULL),
mLiveHelpHistorySize(0)
{
setFollowsAll();
setBorderVisible(FALSE);
@ -336,14 +343,13 @@ LLScriptEdCore::LLScriptEdCore(
initMenu();
// Do the work that addTabPanel() normally does.
//LLRect tab_panel_rect( 0, mRect.getHeight(), mRect.getWidth(), 0 );
//tab_panel_rect.stretch( -LLPANEL_BORDER_WIDTH );
//mCodePanel->setFollowsAll();
//mCodePanel->translate( tab_panel_rect.mLeft - mCodePanel->getRect().mLeft, tab_panel_rect.mBottom - mCodePanel->getRect().mBottom);
//mCodePanel->reshape( tab_panel_rect.getWidth(), tab_panel_rect.getHeight(), TRUE );
}
LLScriptEdCore::~LLScriptEdCore()
@ -402,6 +408,9 @@ void LLScriptEdCore::initMenu()
menuItem->setMenuCallback(onBtnHelp, this);
menuItem->setEnabledCallback(NULL);
menuItem = LLUICtrlFactory::getMenuItemCallByName(this, "LSL Wiki Help...");
menuItem->setMenuCallback(onBtnDynamicHelp, this);
menuItem->setEnabledCallback(NULL);
}
BOOL LLScriptEdCore::hasChanged(void* userdata)
@ -431,9 +440,135 @@ void LLScriptEdCore::draw()
childSetText("line_col", "");
}
updateDynamicHelp();
LLPanel::draw();
}
void LLScriptEdCore::updateDynamicHelp(BOOL immediate)
{
LLFloater* help_floater = LLFloater::getFloaterByHandle(mLiveHelpHandle);
if (!help_floater) return;
// update back and forward buttons
LLButton* fwd_button = LLUICtrlFactory::getButtonByName(help_floater, "fwd_btn");
LLButton* back_button = LLUICtrlFactory::getButtonByName(help_floater, "back_btn");
LLWebBrowserCtrl* browser = LLUICtrlFactory::getWebBrowserCtrlByName(help_floater, "lsl_guide_html");
back_button->setEnabled(browser->canNavigateBack());
fwd_button->setEnabled(browser->canNavigateForward());
if (!immediate && !gSavedSettings.getBOOL("ScriptHelpFollowsCursor"))
{
return;
}
LLTextSegment* segment = NULL;
std::vector<LLTextSegment*> selected_segments;
mEditor->getSelectedSegments(selected_segments);
// try segments in selection range first
std::vector<LLTextSegment*>::iterator segment_iter;
for (segment_iter = selected_segments.begin(); segment_iter != selected_segments.end(); ++segment_iter)
{
if((*segment_iter)->getToken() && (*segment_iter)->getToken()->getType() == LLKeywordToken::WORD)
{
segment = *segment_iter;
break;
}
}
// then try previous segment in case we just typed it
if (!segment)
{
LLTextSegment* test_segment = mEditor->getPreviousSegment();
if(test_segment->getToken() && test_segment->getToken()->getType() == LLKeywordToken::WORD)
{
segment = test_segment;
}
}
if (segment)
{
if (segment->getToken() != mLastHelpToken)
{
mLastHelpToken = segment->getToken();
mLiveHelpTimer.start();
}
if (immediate || (mLiveHelpTimer.getStarted() && mLiveHelpTimer.getElapsedTimeF32() > LIVE_HELP_REFRESH_TIME))
{
LLString help_string = mEditor->getText().substr(segment->getStart(), segment->getEnd() - segment->getStart());
setHelpPage(help_string);
mLiveHelpTimer.stop();
}
}
else
{
setHelpPage("");
}
}
void LLScriptEdCore::setHelpPage(const LLString& help_string)
{
LLFloater* help_floater = LLFloater::getFloaterByHandle(mLiveHelpHandle);
if (!help_floater) return;
LLWebBrowserCtrl* web_browser = gUICtrlFactory->getWebBrowserCtrlByName(help_floater, "lsl_guide_html");
if (!web_browser) return;
LLComboBox* history_combo = gUICtrlFactory->getComboBoxByName(help_floater, "history_combo");
if (!history_combo) return;
LLUIString url_string = gSavedSettings.getString("LSLHelpURL");
url_string.setArg("[APP_DIRECTORY]", gDirUtilp->getWorkingDir());
url_string.setArg("[LSL_STRING]", help_string);
addHelpItemToHistory(help_string);
web_browser->navigateTo(url_string);
}
void LLScriptEdCore::addHelpItemToHistory(const LLString& help_string)
{
if (help_string.empty()) return;
LLFloater* help_floater = LLFloater::getFloaterByHandle(mLiveHelpHandle);
if (!help_floater) return;
LLComboBox* history_combo = gUICtrlFactory->getComboBoxByName(help_floater, "history_combo");
if (!history_combo) return;
// separate history items from full item list
if (mLiveHelpHistorySize == 0)
{
LLSD row;
row["columns"][0]["type"] = "separator";
history_combo->addElement(row, ADD_TOP);
}
// delete all history items over history limit
while(mLiveHelpHistorySize > MAX_HISTORY_COUNT - 1)
{
history_combo->remove(mLiveHelpHistorySize - 1);
mLiveHelpHistorySize--;
}
history_combo->setSimple(help_string);
S32 index = history_combo->getCurrentIndex();
// if help string exists in the combo box
if (index >= 0)
{
S32 cur_index = history_combo->getCurrentIndex();
if (cur_index < mLiveHelpHistorySize)
{
// item found in history, bubble up to top
history_combo->remove(history_combo->getCurrentIndex());
mLiveHelpHistorySize--;
}
}
history_combo->add(help_string, LLSD(help_string), ADD_TOP);
history_combo->selectFirstItem();
mLiveHelpHistorySize++;
}
BOOL LLScriptEdCore::canClose()
{
if(mForceClose || mEditor->isPristine())
@ -497,6 +632,92 @@ void LLScriptEdCore::onBtnHelp(void* userdata)
userdata);
}
// static
void LLScriptEdCore::onBtnDynamicHelp(void* userdata)
{
LLScriptEdCore* corep = (LLScriptEdCore*)userdata;
LLFloater* live_help_floater = LLFloater::getFloaterByHandle(corep->mLiveHelpHandle);
if (live_help_floater)
{
live_help_floater->setFocus(TRUE);
corep->updateDynamicHelp(TRUE);
return;
}
live_help_floater = new LLFloater("lsl_help");
gUICtrlFactory->buildFloater(live_help_floater, "floater_lsl_guide.xml");
((LLFloater*)corep->getParent())->addDependentFloater(live_help_floater, TRUE);
live_help_floater->childSetCommitCallback("lock_check", onCheckLock, userdata);
live_help_floater->childSetValue("lock_check", gSavedSettings.getBOOL("ScriptHelpFollowsCursor"));
live_help_floater->childSetCommitCallback("history_combo", onHelpComboCommit, userdata);
live_help_floater->childSetAction("back_btn", onClickBack, userdata);
live_help_floater->childSetAction("fwd_btn", onClickForward, userdata);
LLWebBrowserCtrl* browser = LLUICtrlFactory::getWebBrowserCtrlByName(live_help_floater, "lsl_guide_html");
browser->setAlwaysRefresh(TRUE);
LLComboBox* help_combo = LLUICtrlFactory::getComboBoxByName(live_help_floater, "history_combo");
LLKeywordToken *token;
LLKeywords::word_token_map_t::iterator token_it;
for (token_it = corep->mEditor->mKeywords.mWordTokenMap.begin();
token_it != corep->mEditor->mKeywords.mWordTokenMap.end();
++token_it)
{
token = token_it->second;
help_combo->add(wstring_to_utf8str(token->mToken));
}
help_combo->sortByName();
// re-initialize help variables
corep->mLastHelpToken = NULL;
corep->mLiveHelpHandle = live_help_floater->getHandle();
corep->mLiveHelpHistorySize = 0;
corep->updateDynamicHelp(TRUE);
}
//static
void LLScriptEdCore::onClickBack(void* userdata)
{
LLScriptEdCore* corep = (LLScriptEdCore*)userdata;
LLFloater* live_help_floater = LLFloater::getFloaterByHandle(corep->mLiveHelpHandle);
if (live_help_floater)
{
LLWebBrowserCtrl* browserp = LLUICtrlFactory::getWebBrowserCtrlByName(live_help_floater, "lsl_guide_html");
if (browserp)
{
browserp->navigateBack();
}
}
}
//static
void LLScriptEdCore::onClickForward(void* userdata)
{
LLScriptEdCore* corep = (LLScriptEdCore*)userdata;
LLFloater* live_help_floater = LLFloater::getFloaterByHandle(corep->mLiveHelpHandle);
if (live_help_floater)
{
LLWebBrowserCtrl* browserp = LLUICtrlFactory::getWebBrowserCtrlByName(live_help_floater, "lsl_guide_html");
if (browserp)
{
browserp->navigateForward();
}
}
}
// static
void LLScriptEdCore::onCheckLock(LLUICtrl* ctrl, void* userdata)
{
LLScriptEdCore* corep = (LLScriptEdCore*)userdata;
// clear out token any time we lock the frame, so we will refresh web page immediately when unlocked
gSavedSettings.setBOOL("ScriptHelpFollowsCursor", ctrl->getValue().asBoolean());
corep->mLastHelpToken = NULL;
}
// static
void LLScriptEdCore::onBtnInsertSample(void* userdata)
{
@ -508,6 +729,27 @@ void LLScriptEdCore::onBtnInsertSample(void* userdata)
self->mEditor->insertText(self->mSampleText);
}
// static
void LLScriptEdCore::onHelpComboCommit(LLUICtrl* ctrl, void* userdata)
{
LLScriptEdCore* corep = (LLScriptEdCore*)userdata;
LLFloater* live_help_floater = LLFloater::getFloaterByHandle(corep->mLiveHelpHandle);
if (live_help_floater)
{
LLWebBrowserCtrl* web_browser = gUICtrlFactory->getWebBrowserCtrlByName(live_help_floater, "lsl_guide_html");
LLString help_string = ctrl->getValue().asString();
corep->addHelpItemToHistory(help_string);
LLUIString url_string = gSavedSettings.getString("LSLHelpURL");
url_string.setArg("[APP_DIRECTORY]", gDirUtilp->getWorkingDir());
url_string.setArg("[LSL_STRING]", help_string);
web_browser->navigateTo(url_string);
}
}
// static
void LLScriptEdCore::onBtnInsertFunction(LLUICtrl *ui, void* userdata)
{
@ -519,6 +761,7 @@ void LLScriptEdCore::onBtnInsertFunction(LLUICtrl *ui, void* userdata)
self->mEditor->insertText(self->mFunctions->getSimple());
}
self->mEditor->setFocus(TRUE);
self->setHelpPage(self->mFunctions->getSimple());
}
// static

View File

@ -15,6 +15,7 @@
#include "llinventory.h"
#include "llcombobox.h"
#include "lliconctrl.h"
#include "llframetimer.h"
class LLMessageSystem;
@ -26,6 +27,7 @@ class LLViewerObject;
struct LLEntryAndEdCore;
class LLMenuBarGL;
class LLFloaterScriptSearch;
class LLKeywordToken;
// Inner, implementation class. LLPreviewScript and LLLiveScriptEditor each own one of these.
class LLScriptEdCore : public LLPanel
@ -60,6 +62,11 @@ public:
static void onHelpWebDialog(S32 option, void* userdata);
static void onBtnHelp(void* userdata);
static void onBtnDynamicHelp(void* userdata);
static void onCheckLock(LLUICtrl*, void*);
static void onHelpComboCommit(LLUICtrl* ctrl, void* userdata);
static void onClickBack(void* userdata);
static void onClickForward(void* userdata);
static void onBtnInsertSample(void*);
static void onBtnInsertFunction(LLUICtrl*, void*);
static void doSave( void* userdata, BOOL close_after_save );
@ -91,6 +98,9 @@ public:
protected:
void deleteBridges();
void setHelpPage(const LLString& help_string);
void updateDynamicHelp(BOOL immediate = FALSE);
void addHelpItemToHistory(const LLString& help_string);
static void onErrorList(LLUICtrl*, void* user_data);
@ -107,6 +117,10 @@ private:
LLPanel* mCodePanel;
LLScrollListCtrl* mErrorList;
LLDynamicArray<LLEntryAndEdCore*> mBridges;
LLViewHandle mLiveHelpHandle;
LLKeywordToken* mLastHelpToken;
LLFrameTimer mLiveHelpTimer;
S32 mLiveHelpHistorySize;
};