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

时间:2021-03-06 23:29:29
前面介绍按钮可以显示在窗口里,以及这个类的声明,现在来仔细地分析一下它是怎么样实现名称显示的。
在构造函数里先保存传送入来的名称,如下:
#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处理的字体类来显示字符串,实现按钮的名称显示。