第二人生的源码分析(八十八)LLButton类显示按钮的名称

前面介绍按钮可以显示在窗口里,以及这个类的声明,现在来仔细地分析一下它是怎么样实现名称显示的。
在构造函数里先保存传送入来的名称,如下:
#001    mUnselectedLabel = unselected_label;
#002    mSelectedLabel = selected_label;
#003 
 
从类声明里可以看到mSelectedLabel和mUnselectedLabel都是声明为类LLUIString的实例,由于类LLUIString只支持LLString构造函数的名称,因此它不能显示UNICODE的字符串。
 
显示按钮的函数如下:
#001 void LLButton::draw()
#002 {
 
查看这个按键是否可以显示。
#003    if( getVisible() )
#004    {
 
设置动态效果。
#005        BOOL flash = FALSE;
#006        if( mFlashing )
#007        {
#008             F32 elapsed = mFlashingTimer.getElapsedTimeF32();
#009            S32 flash_count = S32(elapsed * LLUI::sConfigGroup->getF32("ButtonFlashRate") * 2.f);
#010            // flash on or off?
#011            flash = (flash_count % 2 == 0) || flash_count > (F32)LLUI::sConfigGroup->getS32("ButtonFlashCount");
#012        }
#013 
 
是否有输入焦点。
#014        BOOL pressed_by_keyboard = FALSE;
#015        if (hasFocus())
#016        {
#017            pressed_by_keyboard = gKeyboard->getKeyDown(' ') || (mCommitOnReturn && gKeyboard->getKeyDown(KEY_RETURN));
#018        }
#019 
 
没有选中的图片显示。
#020        // Unselected image assignments
#021        S32 local_mouse_x;
#022        S32 local_mouse_y;
#023        LLCoordWindow cursor_pos_window;
#024        getWindow()->getCursorPosition(&cursor_pos_window);
#025        LLCoordGL cursor_pos_gl;
#026        getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl);
#027        cursor_pos_gl.mX = llround((F32)cursor_pos_gl.mX / LLUI::sGLScaleFactor.mV[VX]);
#028        cursor_pos_gl.mY = llround((F32)cursor_pos_gl.mY / LLUI::sGLScaleFactor.mV[VY]);
#029        screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &local_mouse_x, &local_mouse_y);
#030 
 
按下显示的处理,主要选择不同的图片。
#031        BOOL pressed = pressed_by_keyboard
#032                        || (hasMouseCapture() && pointInView(local_mouse_x, local_mouse_y))
#033                        || mToggleState;
#034       
#035        BOOL use_glow_effect = FALSE;
#036        if ( mNeedsHighlight || flash )
#037        {
#038            if (pressed)
#039            {
#040                if (mImageHoverSelected)
#041                {
#042                    mImagep = mImageHoverSelected;
#043                }
#044                else
#045                {
#046                    mImagep = mImageSelected;
#047                    use_glow_effect = TRUE;
#048                }
#049            }
#050            else
#051            {
#052                if (mImageHoverUnselected)
#053                {
#054                    mImagep = mImageHoverUnselected;
#055                }
#056                else
#057                {
#058                    mImagep = mImageUnselected;
#059                    use_glow_effect = TRUE;
#060                }
#061            }
#062        }
#063        else if ( pressed )
#064        {
#065            mImagep = mImageSelected;
#066        }
#067        else
#068        {
#069            mImagep = mImageUnselected;
#070         }
#071 
#072        // Override if more data is available
#073        // HACK: Use gray checked state to mean either:
#074        //   enabled and tentative
#075        // or
#076        //   disabled but checked
 
保存选择的显示图片。
#077        if (!mImageDisabledSelected.isNull() && ( (getEnabled() && getTentative()) || (!getEnabled() && pressed ) ) )
#078        {
#079            mImagep = mImageDisabledSelected;
#080        }
#081        else if (!mImageDisabled.isNull() && !getEnabled() && !pressed)
#082        {
#083            mImagep = mImageDisabled;
#084        }
#085 
#086        if (mNeedsHighlight && !mImagep)
#087        {
#088            use_glow_effect = TRUE;
#089        }
#090 
#091        // Figure out appropriate color for the text
#092        LLColor4 label_color;
#093 
 
获取按钮显示的颜色。
#094        // label changes when button state changes, not when pressed
#095        if ( getEnabled() )
#096        {
#097            if ( mToggleState )
#098            {
#099                label_color = mSelectedLabelColor;
#100            }
#101            else
#102            {
#103                label_color = mUnselectedLabelColor;
#104            }
#105        }
#106        else
#107        {
#108            if ( mToggleState )
#109            {
#110                label_color = mDisabledSelectedLabelColor;
#111            }
#112            else
#113            {
#114                label_color = mDisabledLabelColor;
#115            }
#116        }
#117 
 
准备显示的字符串。
#118        // Unselected label assignments
#119        LLWString label;
#120 
#121        if( mToggleState )
#122        {
#123            if( getEnabled() || mDisabledSelectedLabel.empty() )
#124            {
#125                label = mSelectedLabel;
#126            }
#127            else
#128            {
#129                label = mDisabledSelectedLabel;
#130            }
#131        }
#132        else
#133        {
#134            if( getEnabled() || mDisabledLabel.empty() )
#135            {
#136                label = mUnselectedLabel;
#137            }
#138            else
#139            {
#140                label = mDisabledLabel;
#141            }
#142        }
#143 
#144        //测试一下。
#145        //label = L"测试";
#146       
 
显示按钮的边界。
#147        // draw default button border
#148        if (getEnabled() && mBorderEnabled && gFocusMgr.getAppHasFocus()) // because we're the default button in a panel
#149        {
#150            drawBorder(LLUI::sColorsGroup->getColor( "ButtonBorderColor" ), BORDER_SIZE);
#151        }
#152 
#153        // overlay with keyboard focus border
#154        if (hasFocus())
#155        {
#156             F32 lerp_amt = gFocusMgr.getFocusFlashAmt();
#157            drawBorder(gFocusMgr.getFocusColor(), llround(lerp(1.f, 3.f, lerp_amt)));
#158        }
#159       
#160        if (use_glow_effect)
#161        {
#162            mCurGlowStrength = lerp(mCurGlowStrength, mHoverGlowStrength, LLCriticalDamp::getInterpolant(0.05f));
#163        }
#164        else
#165        {
#166            mCurGlowStrength = lerp(mCurGlowStrength, 0.f, LLCriticalDamp::getInterpolant(0.05f));
#167        }
#168 
#169        // Draw button image, if available.
#170        // Otherwise draw basic rectangular button.
#171        if( mImagep.notNull() && !mScaleImage)
#172        {
#173            mImagep->draw(0, 0, getEnabled() ? mImageColor : mDisabledImageColor );
#174            if (mCurGlowStrength > 0.01f)
#175            {
#176                gGL.blendFunc(GL_SRC_ALPHA, GL_ONE);
#177                mImagep->drawSolid(0, 0, LLColor4(1.f, 1.f, 1.f, mCurGlowStrength));
#178                gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
#179            }
#180        }
#181        else
#182        if ( mImagep.notNull() && mScaleImage)
#183        {
#184            mImagep->draw(0, 0, getRect().getWidth(), getRect().getHeight(), getEnabled() ? mImageColor : mDisabledImageColor );
#185            if (mCurGlowStrength > 0.01f)
#186            {
#187                gGL.blendFunc(GL_SRC_ALPHA, GL_ONE);
#188                mImagep->drawSolid(0, 0, getRect().getWidth(), getRect().getHeight(), LLColor4(1.f, 1.f, 1.f, mCurGlowStrength));
#189                gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
#190            }
#191        }
#192        else
#193        {
#194            // no image
#195            llwarns << "No image for button " << getName() << llendl;
#196            // draw it in pink so we can find it
#197            gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4::pink1, FALSE);
#198        }
#199 
 
计算显示字符串的位置。
#200        // let overlay image and text play well together
#201        S32 text_left = mLeftHPad;
#202        S32 text_right = getRect().getWidth() - mRightHPad;
#203        S32 text_width = getRect().getWidth() - mLeftHPad - mRightHPad;
#204 
#205        // draw overlay image
#206        if (mImageOverlay.notNull())
#207        {
#208            // get max width and height (discard level 0)
#209            S32 overlay_width = mImageOverlay->getWidth();
#210            S32 overlay_height = mImageOverlay->getHeight();
#211 
#212             F32 scale_factor = llmin((F32)getRect().getWidth() / (F32)overlay_width, (F32)getRect().getHeight() / (F32)overlay_height, 1.f);
#213            overlay_width = llround((F32)overlay_width * scale_factor);
#214            overlay_height = llround((F32)overlay_height * scale_factor);
#215 
#216            S32 center_x = getLocalRect().getCenterX();
#217            S32 center_y = getLocalRect().getCenterY();
#218 
#219            //FUGLY HACK FOR "DEPRESSED" BUTTONS
#220            if (pressed)
#221            {
#222                center_y--;
#223                center_x++;
#224            }
#225 
#226            // fade out overlay images on disabled buttons
#227            LLColor4 overlay_color = mImageOverlayColor;
#228            if (!getEnabled())
#229            {
#230                overlay_color.mV[VALPHA] = 0.5f;
#231            }
#232 
#233             switch(mImageOverlayAlignment)
#234            {
#235            case LLFontGL::LEFT:
#236                text_left += overlay_width + 1;
#237                text_width -= overlay_width + 1;
#238                mImageOverlay->draw(
#239                    mLeftHPad,
#240                    center_y - (overlay_height / 2),
#241                    overlay_width,
#242                    overlay_height,
#243                    overlay_color);
#244                break;
#245            case LLFontGL::HCENTER:
#246                mImageOverlay->draw(
#247                    center_x - (overlay_width / 2),
#248                    center_y - (overlay_height / 2),
#249                    overlay_width,
#250                    overlay_height,
#251                    overlay_color);
#252                break;
#253            case LLFontGL::RIGHT:
#254                text_right -= overlay_width + 1;               
#255                text_width -= overlay_width + 1;
#256                mImageOverlay->draw(
#257                     getRect().getWidth() - mRightHPad - overlay_width,
#258                    center_y - (overlay_height / 2),
#259                    overlay_width,
#260                    overlay_height,
#261                    overlay_color);
#262                break;
#263            default:
#264                // draw nothing
#265                break;
#266            }
#267        }
#268 
 
显示按钮的字符串。
#269        // Draw label
#270        if( !label.empty() )
#271        {
#272            LLWString::trim(label);
#273 
#274            S32 x;
#275            switch( mHAlign )
#276            {
#277            case LLFontGL::RIGHT:
#278                x = text_right;
#279                break;
#280            case LLFontGL::HCENTER:
#281                x = getRect().getWidth() / 2;
#282                break;
#283            case LLFontGL::LEFT:
#284            default:
#285                x = text_left;
#286                break;
#287            }
#288 
#289            S32 y_offset = 2 + (getRect().getHeight() - 20)/2;
#290       
#291            if (pressed)
#292            {
#293                y_offset--;
#294                x++;
#295            }
#296 
 
主要调用OPENGL里的字体处理类来显示字符串。
#297            mGLFont->render(label, 0, (F32)x, (F32)(LLBUTTON_V_PAD + y_offset),
#298                label_color,
#299                mHAlign, LLFontGL::BOTTOM,
#300                mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NORMAL,
#301                U32_MAX, text_width,
#302                NULL, FALSE, FALSE);
#303        }
#304 
#305        if (sDebugRects
#306            || (LLView::sEditingUI && this == LLView::sEditingUIView))
#307        {
#308            drawDebugRect();
#309        }
#310    }
#311    // reset hover status for next frame
#312    mNeedsHighlight = FALSE;
#313 }
#314 
 
在这个函数里,先要选择按钮背景的图片,然后根据是否选中显示不同的图片,不同的颜色,最后调用OPENGL处理的字体类来显示字符串,实现按钮的名称显示。
 
posted @ 2008-06-12 22:31  ajuanabc  阅读(173)  评论(0)    收藏  举报