void cc2DLabel::drawMeOnly2D(CC_DRAW_CONTEXT& context) { if (!m_dispIn2D) return; assert(!m_points.empty()); //get the set of OpenGL functions (version 2.1) QOpenGLFunctions_2_1 *glFunc = context.glFunctions<QOpenGLFunctions_2_1>(); assert( glFunc != nullptr ); if ( glFunc == nullptr ) return; //standard case: list names pushing bool pushName = MACRO_DrawEntityNames(context); if (pushName) { glFunc->glPushName(getUniqueID()); } //we should already be in orthoprojective & centered omde //glFunc->glOrtho(-halfW,halfW,-halfH,halfH,-maxS,maxS); //label title const int precision = context.dispNumberPrecision; QString title = getTitle(precision); #define DRAW_CONTENT_AS_TAB #ifdef DRAW_CONTENT_AS_TAB //draw contents as an array Tab tab(4); int rowHeight = 0; #else //simply display the content as text QStringList body; #endif //render zoom int margin = static_cast<int>(c_margin * context.renderZoom); int tabMarginX = static_cast<int>(c_tabMarginX * context.renderZoom); int tabMarginY = static_cast<int>(c_tabMarginY * context.renderZoom); int arrowBaseSize = static_cast<int>(c_arrowBaseSize * context.renderZoom); int titleHeight = 0; GLdouble arrowDestX = -1.0, arrowDestY = -1.0; QFont bodyFont,titleFont; if (!pushName) { /*** line from 2D point to label ***/ //compute arrow head position CCVector3 arrowDest; m_points[0].cloud->getPoint(m_points[0].index,arrowDest); for (unsigned i = 1; i < m_points.size(); ++i) { arrowDest += *m_points[i].cloud->getPointPersistentPtr(m_points[i].index); } arrowDest /= static_cast<PointCoordinateType>(m_points.size()); //project it in 2D screen coordinates { ccGLCameraParameters camera; context.display->getGLCameraParameters(camera); CCVector3d Q2D; camera.project(arrowDest, Q2D); arrowDestX = Q2D.x; arrowDestY = Q2D.y; } /*** label border ***/ bodyFont = context.display->getLabelDisplayFont(); //takes rendering zoom into account! titleFont = bodyFont; //takes rendering zoom into account! //titleFont.setBold(true); QFontMetrics titleFontMetrics(titleFont); titleHeight = titleFontMetrics.height(); QFontMetrics bodyFontMetrics(bodyFont); rowHeight = bodyFontMetrics.height(); //get label box dimension int dx = 100; int dy = 0; //int buttonSize = static_cast<int>(c_buttonSize * context.renderZoom); { //base box dimension dx = std::max(dx,titleFontMetrics.width(title)); dy += margin; //top vertical margin dy += titleHeight; //title if (m_showFullBody) { #ifdef DRAW_CONTENT_AS_TAB try { size_t labelCount = m_points.size(); if (labelCount == 1) { LabelInfo1 info; getLabelInfo1(info); bool isShifted = info.cloud->isShifted(); //1st block: X, Y, Z (local) { int c = tab.add2x3Block(); QChar suffix; if (isShifted) suffix = 'l'; //'l' for local const CCVector3* P = info.cloud->getPoint(info.pointIndex); tab.colContent[c] << QString("X") + suffix; tab.colContent[c+1] << QString::number(P->x,'f',precision); tab.colContent[c] << QString("Y") + suffix; tab.colContent[c+1] << QString::number(P->y,'f',precision); tab.colContent[c] << QString("Z") + suffix; tab.colContent[c+1] << QString::number(P->z,'f',precision); } //next block: X, Y, Z (global) if (isShifted) { int c = tab.add2x3Block(); CCVector3d P = info.cloud->toGlobal3d(*info.cloud->getPoint(info.pointIndex)); tab.colContent[c] << "Xg"; tab.colContent[c+1] << QString::number(P.x,'f',precision); tab.colContent[c] << "Yg"; tab.colContent[c+1] << QString::number(P.y,'f',precision); tab.colContent[c] << "Zg"; tab.colContent[c+1] << QString::number(P.z,'f',precision); } //next block: normal if (info.hasNormal) { int c = tab.add2x3Block(); tab.colContent[c] << "Nx"; tab.colContent[c+1] << QString::number(info.normal.x,'f',precision); tab.colContent[c] << "Ny"; tab.colContent[c+1] << QString::number(info.normal.y,'f',precision); tab.colContent[c] << "Nz"; tab.colContent[c+1] << QString::number(info.normal.z,'f',precision); } //next block: RGB color if (info.hasRGB) { int c = tab.add2x3Block(); tab.colContent[c] <<"R"; tab.colContent[c+1] << QString::number(info.rgb.x); tab.colContent[c] <<"G"; tab.colContent[c+1] << QString::number(info.rgb.y); tab.colContent[c] <<"B"; tab.colContent[c+1] << QString::number(info.rgb.z); } } else if (labelCount == 2) { LabelInfo2 info; getLabelInfo2(info); //1st block: dX, dY, dZ { int c = tab.add2x3Block(); tab.colContent[c] << MathSymbolDelta + QString("X"); tab.colContent[c+1] << QString::number(info.diff.x,'f',precision); tab.colContent[c] << MathSymbolDelta + QString("Y"); tab.colContent[c+1] << QString::number(info.diff.y,'f',precision); tab.colContent[c] << MathSymbolDelta + QString("Z"); tab.colContent[c+1] << QString::number(info.diff.z,'f',precision); } //2nd block: dXY, dXZ, dZY { int c = tab.add2x3Block(); PointCoordinateType dXY = sqrt(info.diff.x*info.diff.x + info.diff.y*info.diff.y); PointCoordinateType dXZ = sqrt(info.diff.x*info.diff.x + info.diff.z*info.diff.z); PointCoordinateType dZY = sqrt(info.diff.z*info.diff.z + info.diff.y*info.diff.y); tab.colContent[c] << MathSymbolDelta + QString("XY"); tab.colContent[c+1] << QString::number(dXY,'f',precision); tab.colContent[c] << MathSymbolDelta + QString("XZ"); tab.colContent[c+1] << QString::number(dXZ,'f',precision); tab.colContent[c] << MathSymbolDelta + QString("ZY"); tab.colContent[c+1] << QString::number(dZY,'f',precision); } } else if (labelCount == 3) { LabelInfo3 info; getLabelInfo3(info); tab.setMaxBlockPerRow(2); //square tab (2x2 blocks) //next block: indexes { int c = tab.add2x3Block(); tab.colContent[c] << "index.A"; tab.colContent[c+1] << QString::number(info.point1Index); tab.colContent[c] << "index.B"; tab.colContent[c+1] << QString::number(info.point2Index); tab.colContent[c] << "index.C"; tab.colContent[c+1] << QString::number(info.point3Index); } //next block: edges length { int c = tab.add2x3Block(); tab.colContent[c] << "AB"; tab.colContent[c+1] << QString::number(info.edges.u[0],'f',precision); tab.colContent[c] << "BC"; tab.colContent[c+1] << QString::number(info.edges.u[1],'f',precision); tab.colContent[c] << "CA"; tab.colContent[c+1] << QString::number(info.edges.u[2],'f',precision); } //next block: angles { int c = tab.add2x3Block(); tab.colContent[c] << "angle.A"; tab.colContent[c+1] << QString::number(info.angles.u[0],'f',precision); tab.colContent[c] << "angle.B"; tab.colContent[c+1] << QString::number(info.angles.u[1],'f',precision); tab.colContent[c] << "angle.C"; tab.colContent[c+1] << QString::number(info.angles.u[2],'f',precision); } //next block: normal { int c = tab.add2x3Block(); tab.colContent[c] << "Nx"; tab.colContent[c+1] << QString::number(info.normal.x,'f',precision); tab.colContent[c] << "Ny"; tab.colContent[c+1] << QString::number(info.normal.y,'f',precision); tab.colContent[c] << "Nz"; tab.colContent[c+1] << QString::number(info.normal.z,'f',precision); } } } catch (const std::bad_alloc&) { //not enough memory return; } //compute min width of each column int totalWidth = tab.updateColumnsWidthTable(bodyFontMetrics); int tabWidth = totalWidth + tab.colCount * (2*tabMarginX); //add inner margins dx = std::max(dx,tabWidth); dy += tab.rowCount * (rowHeight + 2*tabMarginY); //add inner margins //we also add a margin every 3 rows dy += std::max(0,(tab.rowCount/3)-1) * margin; dy += margin; //bottom vertical margin #else body = getLabelContent(precision); if (!body.empty()) { dy += margin; //vertical margin above separator for (int j=0; j<body.size(); ++j) { dx = std::max(dx,bodyFontMetrics.width(body[j])); dy += rowHeight; //body line height } dy += margin; //vertical margin below text } #endif //DRAW_CONTENT_AS_TAB } dx += margin*2; // horizontal margins } //main rectangle m_labelROI = QRect(0,0,dx,dy); //close button //m_closeButtonROI.right() = dx-margin; //m_closeButtonROI.left() = m_closeButtonROI.right()-buttonSize; //m_closeButtonROI.bottom() = margin; //m_closeButtonROI.top() = m_closeButtonROI.bottom()+buttonSize; //automatically elide the title //title = titleFontMetrics.elidedText(title,Qt::ElideRight,m_closeButtonROI[0]-2*margin); } int halfW = (context.glW >> 1); int halfH = (context.glH >> 1); //draw label rectangle int xStart = static_cast<int>(context.glW * m_screenPos[0]); int yStart = static_cast<int>(context.glH * (1.0f - m_screenPos[1])); m_lastScreenPos[0] = xStart; m_lastScreenPos[1] = yStart - m_labelROI.height(); //colors bool highlighted = (!pushName && isSelected()); //default background color unsigned char alpha = static_cast<unsigned char>((context.labelOpacity/100.0) * 255); ccColor::Rgbaub defaultBkgColor(context.labelDefaultBkgCol,alpha); //default border color (mustn't be totally transparent!) ccColor::Rgbaub defaultBorderColor(ccColor::red); if (!highlighted) { //apply only half of the transparency unsigned char halfAlpha = static_cast<unsigned char>((50.0 + context.labelOpacity/200.0) * 255); defaultBorderColor = ccColor::Rgbaub(context.labelDefaultBkgCol,halfAlpha); } glFunc->glPushAttrib(GL_COLOR_BUFFER_BIT); glFunc->glEnable(GL_BLEND); glFunc->glMatrixMode(GL_MODELVIEW); glFunc->glPushMatrix(); glFunc->glTranslatef(static_cast<GLfloat>(-halfW + xStart), static_cast<GLfloat>(-halfH + yStart), 0); if (!pushName) { //compute arrow base position relatively to the label rectangle (for 0 to 8) int arrowBaseConfig = 0; int iArrowDestX = static_cast<int>(arrowDestX)-xStart; int iArrowDestY = static_cast<int>(arrowDestY)-yStart; { if (iArrowDestX < m_labelROI.left()) //left arrowBaseConfig += 0; else if (iArrowDestX > m_labelROI.right()) //Right arrowBaseConfig += 2; else //Middle arrowBaseConfig += 1; if (iArrowDestY > -m_labelROI.top()) //Top arrowBaseConfig += 0; else if (iArrowDestY < -m_labelROI.bottom()) //Bottom arrowBaseConfig += 6; else //Middle arrowBaseConfig += 3; } //we make the arrow base start from the nearest corner if (arrowBaseConfig != 4) //4 = label above point! { glFunc->glColor4ubv(defaultBorderColor.rgba); glFunc->glBegin(GL_TRIANGLE_FAN); glFunc->glVertex2d(arrowDestX - xStart, arrowDestY - yStart); switch(arrowBaseConfig) { case 0: //top-left corner glFunc->glVertex2i(m_labelROI.left(), -m_labelROI.top()-2*arrowBaseSize); glFunc->glVertex2i(m_labelROI.left(), -m_labelROI.top()); glFunc->glVertex2i(m_labelROI.left()+2*arrowBaseSize, -m_labelROI.top()); break; case 1: //top-middle edge glFunc->glVertex2i(std::max(m_labelROI.left(),iArrowDestX-arrowBaseSize), -m_labelROI.top()); glFunc->glVertex2i(std::min(m_labelROI.right(),iArrowDestX+arrowBaseSize), -m_labelROI.top()); break; case 2: //top-right corner glFunc->glVertex2i(m_labelROI.right(), -m_labelROI.top()-2*arrowBaseSize); glFunc->glVertex2i(m_labelROI.right(), -m_labelROI.top()); glFunc->glVertex2i(m_labelROI.right()-2*arrowBaseSize, -m_labelROI.top()); break; case 3: //middle-left edge glFunc->glVertex2i(m_labelROI.left(), std::min(-m_labelROI.top(),iArrowDestY+arrowBaseSize)); glFunc->glVertex2i(m_labelROI.left(), std::max(-m_labelROI.bottom(),iArrowDestY-arrowBaseSize)); break; case 4: //middle of rectangle! break; case 5: //middle-right edge glFunc->glVertex2i(m_labelROI.right(), std::min(-m_labelROI.top(),iArrowDestY+arrowBaseSize)); glFunc->glVertex2i(m_labelROI.right(), std::max(-m_labelROI.bottom(),iArrowDestY-arrowBaseSize)); break; case 6: //bottom-left corner glFunc->glVertex2i(m_labelROI.left(), -m_labelROI.bottom()+2*arrowBaseSize); glFunc->glVertex2i(m_labelROI.left(), -m_labelROI.bottom()); glFunc->glVertex2i(m_labelROI.left()+2*arrowBaseSize, -m_labelROI.bottom()); break; case 7: //bottom-middle edge glFunc->glVertex2i(std::max(m_labelROI.left(),iArrowDestX-arrowBaseSize), -m_labelROI.bottom()); glFunc->glVertex2i(std::min(m_labelROI.right(),iArrowDestX+arrowBaseSize), -m_labelROI.bottom()); break; case 8: //bottom-right corner glFunc->glVertex2i(m_labelROI.right(), -m_labelROI.bottom()+2*arrowBaseSize); glFunc->glVertex2i(m_labelROI.right(), -m_labelROI.bottom()); glFunc->glVertex2i(m_labelROI.right()-2*arrowBaseSize, -m_labelROI.bottom()); break; } glFunc->glEnd(); } } //main rectangle glFunc->glColor4ubv(defaultBkgColor.rgba); glFunc->glBegin(GL_QUADS); glFunc->glVertex2i(m_labelROI.left(), -m_labelROI.top()); glFunc->glVertex2i(m_labelROI.left(), -m_labelROI.bottom()); glFunc->glVertex2i(m_labelROI.right(), -m_labelROI.bottom()); glFunc->glVertex2i(m_labelROI.right(), -m_labelROI.top()); glFunc->glEnd(); //if (highlighted) { glFunc->glPushAttrib(GL_LINE_BIT); glFunc->glLineWidth(3.0f * context.renderZoom); glFunc->glColor4ubv(defaultBorderColor.rgba); glFunc->glBegin(GL_LINE_LOOP); glFunc->glVertex2i(m_labelROI.left(), -m_labelROI.top()); glFunc->glVertex2i(m_labelROI.left(), -m_labelROI.bottom()); glFunc->glVertex2i(m_labelROI.right(), -m_labelROI.bottom()); glFunc->glVertex2i(m_labelROI.right(), -m_labelROI.top()); glFunc->glEnd(); glFunc->glPopAttrib(); } //draw close button //glFunc->glColor3ubv(ccColor::black); //glFunc->glBegin(GL_LINE_LOOP); //glFunc->glVertex2i(m_closeButtonROI.left(),-m_closeButtonROI.top()); //glFunc->glVertex2i(m_closeButtonROI.left(),-m_closeButtonROI.bottom()); //glFunc->glVertex2i(m_closeButtonROI.right(),-m_closeButtonROI.bottom()); //glFunc->glVertex2i(m_closeButtonROI.right(),-m_closeButtonROI.top()); //glFunc->glEnd(); //glFunc->glBegin(GL_LINES); //glFunc->glVertex2i(m_closeButtonROI.left()+2,-m_closeButtonROI.top()+2); //glFunc->glVertex2i(m_closeButtonROI.right()-2,-m_closeButtonROI.bottom()-2); //glFunc->glVertex2i(m_closeButtonROI.right()-2,-m_closeButtonROI.top()+2); //glFunc->glVertex2i(m_closeButtonROI.left()+2,-m_closeButtonROI.bottom()-2); //glFunc->glEnd(); //display text if (!pushName) { int xStartRel = margin; int yStartRel = 0; yStartRel -= titleHeight; ccColor::Rgbub defaultTextColor; if (context.labelOpacity < 40) { //under a given opacity level, we use the default text color instead! defaultTextColor = context.textDefaultCol; } else { defaultTextColor = ccColor::Rgbub( 255 - context.labelDefaultBkgCol.r, 255 - context.labelDefaultBkgCol.g, 255 - context.labelDefaultBkgCol.b); } //label title context.display->displayText( title, xStart+xStartRel, yStart+yStartRel, ccGenericGLDisplay::ALIGN_DEFAULT, 0, defaultTextColor.rgb, &titleFont); yStartRel -= margin; if (m_showFullBody) { #ifdef DRAW_CONTENT_AS_TAB int xCol = xStartRel; for (int c=0; c<tab.colCount; ++c) { int width = tab.colWidth[c] + 2*tabMarginX; int height = rowHeight + 2*tabMarginY; int yRow = yStartRel; int actualRowCount = std::min(tab.rowCount,tab.colContent[c].size()); bool labelCol = ((c & 1) == 0); const unsigned char* textColor = labelCol ? ccColor::white.rgba : defaultTextColor.rgb; for (int r=0; r<actualRowCount; ++r) { if (r && (r % 3) == 0) yRow -= margin; if (labelCol) { //draw background int rgbIndex = (r % 3); if (rgbIndex == 0) glFunc->glColor3ubv(ccColor::red.rgba); else if (rgbIndex == 1) glFunc->glColor3ubv(c_darkGreen.rgba); else if (rgbIndex == 2) glFunc->glColor3ubv(ccColor::blue.rgba); glFunc->glBegin(GL_QUADS); glFunc->glVertex2i(m_labelROI.left() + xCol, -m_labelROI.top() + yRow); glFunc->glVertex2i(m_labelROI.left() + xCol, -m_labelROI.top() + yRow - height); glFunc->glVertex2i(m_labelROI.left() + xCol + width, -m_labelROI.top() + yRow - height); glFunc->glVertex2i(m_labelROI.left() + xCol + width, -m_labelROI.top() + yRow); glFunc->glEnd(); } const QString& str = tab.colContent[c][r]; int xShift = 0; if (labelCol) { //align characters in the middle xShift = (tab.colWidth[c] - QFontMetrics(bodyFont).width(str)) / 2; } else { //align digits on the right xShift = tab.colWidth[c] - QFontMetrics(bodyFont).width(str); } context.display->displayText( str, xStart + xCol + tabMarginX + xShift, yStart + yRow - rowHeight, ccGenericGLDisplay::ALIGN_DEFAULT, 0, textColor, &bodyFont); yRow -= height; } xCol += width; } #else if (!body.empty()) { //display body yStartRel -= margin; for (int i=0; i<body.size(); ++i) { yStartRel -= rowHeight; context.display->displayText(body[i],xStart+xStartRel,yStart+yStartRel,ccGenericGLDisplay::ALIGN_DEFAULT,0,defaultTextColor.rgb,&bodyFont); } } #endif //DRAW_CONTENT_AS_TAB } } glFunc->glPopAttrib(); glFunc->glPopMatrix(); if (pushName) { glFunc->glPopName(); } }
void BlogListDelegate::paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const { BlogListWidget * listWidget = qobject_cast<BlogListWidget *>(this->parent()); if (listWidget == NULL) return; QStyle * style = listWidget->style(); if (style == NULL) return; painter->save(); QFont itemFont(painter->font()); style->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, listWidget); QPixmap pixmap = qvariant_cast<QPixmap>(index.data(IconRole)); QString title = index.data(TitleRole).toString(); QString date = index.data(DateRole).toString(); QString author = index.data(AuthorRole).toString(); QString intro = index.data(IntroRole).toString(); // QRect rect; int imageSpace = ImageSpace + 10; // TITLE painter->setPen(listWidget->titleTextColor()); QFont titleFont(listWidget->titleTextFontFamily()); titleFont.setPixelSize(pixelSize(listWidget->titleTextFontSize())); painter->setFont(titleFont); QRect rect = option.rect.adjusted(imageSpace, TopSpace, 0, 0); style->drawItemText(painter, rect, Qt::AlignLeft, option.palette, true, title); QFontMetrics titleFontMetrics(titleFont); // INTRO painter->setPen(listWidget->introTextColor()); QFont introFont(listWidget->introTextFontFamily()); introFont.setPixelSize(pixelSize(listWidget->introTextFontSize())); painter->setFont(introFont); rect = option.rect.adjusted(imageSpace, TopSpace + titleFontMetrics.lineSpacing() + pixelSize(listWidget->titleTextExtraLeading()) , 0, 0); style->drawItemText(painter, rect, Qt::AlignLeft, option.palette, true, intro); QFontMetrics introFontMetrics(introFont); // DATE painter->setPen(listWidget->dateTextColor()); QFont font(listWidget->dateTextFontFamily()); font.setPixelSize(pixelSize(listWidget->dateTextFontSize())); painter->setFont(font); rect = option.rect.adjusted(imageSpace, TopSpace + titleFontMetrics.lineSpacing() + introFontMetrics.lineSpacing() + pixelSize(listWidget->introTextExtraLeading()), 0, 0); style->drawItemText(painter, rect, Qt::AlignLeft, option.palette, true, date); QFontMetrics dateTextFontMetrics(font); // AUTHOR QRect textRect = style->itemTextRect(dateTextFontMetrics, option.rect, Qt::AlignLeft, true, date); rect = option.rect.adjusted(imageSpace + textRect.width() + 7, TopSpace + titleFontMetrics.lineSpacing() + introFontMetrics.lineSpacing() + pixelSize(listWidget->introTextExtraLeading()), 0, 0); style->drawItemText(painter, rect, Qt::AlignLeft, option.palette, true, author); if (!pixmap.isNull()) { //ic.paint(painter, option.rect, Qt::AlignVCenter|Qt::AlignLeft); style->drawItemPixmap(painter, option.rect.adjusted(0, TopSpace, 0, -TopSpace), Qt::AlignLeft, pixmap); } painter->restore(); }
void cc2DViewportLabel::drawMeOnly(CC_DRAW_CONTEXT& context) { //2D foreground only if (!MACRO_Foreground(context) || !MACRO_Draw2D(context)) return; //test viewport parameters const ccViewportParameters& params = context._win->getViewportParameters(); //in perspective mode, screenPan or zoom cannot be easily compensated if (m_params.perspectiveView && ( params.zoom != m_params.zoom || params.globalZoom != m_params.globalZoom || params.screenPan[0] != m_params.screenPan[0] || params.screenPan[1] != m_params.screenPan[1] || (params.pivotPoint - m_params.pivotPoint).norm() > ZERO_TOLERANCE)) return; //test base view matrix for (unsigned i=0;i<12;++i) if (fabs(params.baseViewMat.data()[i] - m_params.baseViewMat.data()[i])>ZERO_TOLERANCE) return; //general parameters if (params.perspectiveView != m_params.perspectiveView || params.objectCenteredPerspective != m_params.objectCenteredPerspective //|| (params.pivotPoint - m_params.pivotPoint).norm() > ZERO_TOLERANCE || params.aspectRatio != m_params.aspectRatio || params.fov != m_params.fov) return; glPushAttrib(GL_LINE_BIT); //Screen pan & pivot compensation float dx=0.0f,dy=0.0f,relativeZoom=1.0f; if (!m_params.perspectiveView) { float totalZoom = m_params.zoom*m_params.globalZoom; float winTotalZoom = params.zoom*params.globalZoom; relativeZoom = winTotalZoom/totalZoom; dx = m_params.screenPan[0] - params.screenPan[0]; dy = m_params.screenPan[1] - params.screenPan[1]; CCVector3 P = m_params.pivotPoint-params.pivotPoint; m_params.baseViewMat.apply(P); dx += P.x; dy += P.y; dx *= winTotalZoom; dy *= winTotalZoom; } //thick dotted line glLineWidth(2); glLineStipple(1, 0xAAAA); glEnable(GL_LINE_STIPPLE); const colorType* defaultColor = selected ? ccColor::red : context.textDefaultCol; glColor3ubv(defaultColor); glBegin(GL_LINE_LOOP); glVertex2f(dx+m_roi[0]*relativeZoom,dy+m_roi[1]*relativeZoom); glVertex2f(dx+m_roi[2]*relativeZoom,dy+m_roi[1]*relativeZoom); glVertex2f(dx+m_roi[2]*relativeZoom,dy+m_roi[3]*relativeZoom); glVertex2f(dx+m_roi[0]*relativeZoom,dy+m_roi[3]*relativeZoom); glEnd(); glPopAttrib(); //title QString title(getName()); if (!title.isEmpty()) { QFont titleFont(context._win->getTextDisplayFont()); titleFont.setBold(true); QFontMetrics titleFontMetrics(titleFont); int titleHeight = titleFontMetrics.height(); int xStart = (int)(dx+0.5f*(float)context.glW+std::min<float>(m_roi[0],m_roi[2])*relativeZoom); int yStart = (int)(dy+0.5f*(float)context.glH+std::min<float>(m_roi[1],m_roi[3])*relativeZoom); context._win->displayText(title,xStart,yStart-5-titleHeight,false,defaultColor,titleFont); } }
void cc2DLabel::drawMeOnly2D(CC_DRAW_CONTEXT& context) { if (!m_dispIn2D) return; assert(!m_points.empty()); //standard case: list names pushing bool pushName = MACRO_DrawEntityNames(context); if (pushName) glPushName(getUniqueID()); //we should already be in orthoprojective & centered omde //glOrtho(-halfW,halfW,-halfH,halfH,-maxS,maxS); int strHeight = 0; int titleHeight = 0; QString title(getName()); QStringList body; GLdouble arrowDestX=-1.0,arrowDestY=-1.0; QFont bodyFont,titleFont; if (!pushName) { /*** line from 2D point to label ***/ //compute arrow head position CCVector3 arrowDest; m_points[0].cloud->getPoint(m_points[0].index,arrowDest); for (unsigned i=1;i<m_points.size();++i) arrowDest += *m_points[i].cloud->getPointPersistentPtr(m_points[i].index); arrowDest /= (PointCoordinateType)m_points.size(); //project it in 2D screen coordinates int VP[4]; context._win->getViewportArray(VP); const double* MM = context._win->getModelViewMatd(); //viewMat const double* MP = context._win->getProjectionMatd(); //projMat GLdouble zp; gluProject(arrowDest.x,arrowDest.y,arrowDest.z,MM,MP,VP,&arrowDestX,&arrowDestY,&zp); /*** label border ***/ bodyFont = context._win->getTextDisplayFont(); //takes rendering zoom into account! titleFont = QFont(context._win->getTextDisplayFont()); //takes rendering zoom into account! titleFont.setBold(true); QFontMetrics titleFontMetrics(titleFont); QFontMetrics bodyFontMetrics(bodyFont); strHeight = bodyFontMetrics.height(); titleHeight = titleFontMetrics.height(); if (m_showFullBody) body = getLabelContent(context.dispNumberPrecision); //base box dimension int dx = 150; dx = std::max(dx,titleFontMetrics.width(title)); int dy = c_margin; //top vertical margin dy += titleHeight; //title if (!body.empty()) { dy += c_margin; //vertical margin above separator for (int j=0;j<body.size();++j) { dx = std::max(dx,bodyFontMetrics.width(body[j])); dy += (c_margin+strHeight); //margin + body line height } } else { dy += c_margin; // vertical margin (purely for aesthetics) } dy += c_margin; // bottom vertical margin dx += c_margin*2; // horizontal margins //main rectangle m_labelROI[0]=0; m_labelROI[1]=0; m_labelROI[2]=dx; m_labelROI[3]=dy; //close button /*m_closeButtonROI[2]=dx-c_margin; m_closeButtonROI[0]=m_closeButtonROI[2]-c_buttonSize; m_closeButtonROI[3]=c_margin; m_closeButtonROI[1]=m_closeButtonROI[3]+c_buttonSize; //*/ //automatically elide the title //title = titleFontMetrics.elidedText(title,Qt::ElideRight,m_closeButtonROI[0]-2*c_margin); } int halfW = (context.glW>>1); int halfH = (context.glH>>1); //draw label rectangle int xStart = m_lastScreenPos[0] = (int)((float)context.glW * m_screenPos[0]); int yStart = m_lastScreenPos[1] = (int)((float)context.glH * (1.0f-m_screenPos[1])); //colors bool highlighted = (!pushName && isSelected()); //default background color colorType defaultBkgColor[4]; memcpy(defaultBkgColor,context.labelDefaultCol,sizeof(colorType)*3); defaultBkgColor[3] = (colorType)((float)context.labelsTransparency*(float)MAX_COLOR_COMP/100.0f); //default border color (mustn't be totally transparent!) colorType defaultBorderColor[4]; if (highlighted) memcpy(defaultBorderColor,ccColor::red,sizeof(colorType)*3); else memcpy(defaultBorderColor,context.labelDefaultCol,sizeof(colorType)*3); defaultBorderColor[3] = (colorType)((float)(50+context.labelsTransparency/2)*(float)MAX_COLOR_COMP/100.0f); glPushAttrib(GL_COLOR_BUFFER_BIT); glEnable(GL_BLEND); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(static_cast<GLfloat>(-halfW+xStart),static_cast<GLfloat>(-halfH+yStart),0); if (!pushName) { //compute arrow base position relatively to the label rectangle (for 0 to 8) int arrowBaseConfig = 0; int iArrowDestX = (int)arrowDestX-xStart; int iArrowDestY = (int)arrowDestY-yStart; { if (iArrowDestX < m_labelROI[0]) //left arrowBaseConfig += 0; else if (iArrowDestX > m_labelROI[2]) //Right arrowBaseConfig += 2; else //Middle arrowBaseConfig += 1; if (iArrowDestY > -m_labelROI[1]) //Top arrowBaseConfig += 0; else if (iArrowDestY < -m_labelROI[3]) //Bottom arrowBaseConfig += 6; else //Middle arrowBaseConfig += 3; } //we make the arrow base start from the nearest corner if (arrowBaseConfig != 4) //4 = label above point! { glColor4ubv(defaultBorderColor); glBegin(GL_TRIANGLE_FAN); glVertex2d(arrowDestX-xStart,arrowDestY-yStart); switch(arrowBaseConfig) { case 0: //top-left corner glVertex2i(m_labelROI[0], -m_labelROI[1]-2*c_arrowBaseSize); glVertex2i(m_labelROI[0], -m_labelROI[1]); glVertex2i(m_labelROI[0]+2*c_arrowBaseSize, -m_labelROI[1]); break; case 1: //top-middle edge glVertex2i(std::max(m_labelROI[0],iArrowDestX-c_arrowBaseSize), -m_labelROI[1]); glVertex2i(std::min(m_labelROI[2],iArrowDestX+c_arrowBaseSize), -m_labelROI[1]); break; case 2: //top-right corner glVertex2i(m_labelROI[2], -m_labelROI[1]-2*c_arrowBaseSize); glVertex2i(m_labelROI[2], -m_labelROI[1]); glVertex2i(m_labelROI[2]-2*c_arrowBaseSize, -m_labelROI[1]); break; case 3: //middle-left edge glVertex2i(m_labelROI[0], std::min(-m_labelROI[1],iArrowDestY+c_arrowBaseSize)); glVertex2i(m_labelROI[0], std::max(-m_labelROI[3],iArrowDestY-c_arrowBaseSize)); break; case 4: //middle of rectangle! break; case 5: //middle-right edge glVertex2i(m_labelROI[2], std::min(-m_labelROI[1],iArrowDestY+c_arrowBaseSize)); glVertex2i(m_labelROI[2], std::max(-m_labelROI[3],iArrowDestY-c_arrowBaseSize)); break; case 6: //bottom-left corner glVertex2i(m_labelROI[0], -m_labelROI[3]+2*c_arrowBaseSize); glVertex2i(m_labelROI[0], -m_labelROI[3]); glVertex2i(m_labelROI[0]+2*c_arrowBaseSize, -m_labelROI[3]); break; case 7: //bottom-middle edge glVertex2i(std::max(m_labelROI[0],iArrowDestX-c_arrowBaseSize), -m_labelROI[3]); glVertex2i(std::min(m_labelROI[2],iArrowDestX+c_arrowBaseSize), -m_labelROI[3]); break; case 8: //bottom-right corner glVertex2i(m_labelROI[2], -m_labelROI[3]+2*c_arrowBaseSize); glVertex2i(m_labelROI[2], -m_labelROI[3]); glVertex2i(m_labelROI[2]-2*c_arrowBaseSize, -m_labelROI[3]); break; } glEnd(); } } //main rectangle glColor4ubv(defaultBkgColor); glBegin(GL_QUADS); glVertex2i(m_labelROI[0], -m_labelROI[1]); glVertex2i(m_labelROI[0], -m_labelROI[3]); glVertex2i(m_labelROI[2], -m_labelROI[3]); glVertex2i(m_labelROI[2], -m_labelROI[1]); glEnd(); //if (highlighted) { glPushAttrib(GL_LINE_BIT); glLineWidth(3.0f); glColor4ubv(defaultBorderColor); glBegin(GL_LINE_LOOP); glVertex2i(m_labelROI[0], -m_labelROI[1]); glVertex2i(m_labelROI[0], -m_labelROI[3]); glVertex2i(m_labelROI[2], -m_labelROI[3]); glVertex2i(m_labelROI[2], -m_labelROI[1]); glEnd(); glPopAttrib(); } //draw close button /*glColor3ubv(ccColor::black); glBegin(GL_LINE_LOOP); glVertex2i(m_closeButtonROI[0],-m_closeButtonROI[1]); glVertex2i(m_closeButtonROI[0],-m_closeButtonROI[3]); glVertex2i(m_closeButtonROI[2],-m_closeButtonROI[3]); glVertex2i(m_closeButtonROI[2],-m_closeButtonROI[1]); glEnd(); glBegin(GL_LINES); glVertex2i(m_closeButtonROI[0]+2,-m_closeButtonROI[1]+2); glVertex2i(m_closeButtonROI[2]-2,-m_closeButtonROI[3]-2); glVertex2i(m_closeButtonROI[2]-2,-m_closeButtonROI[1]+2); glVertex2i(m_closeButtonROI[0]+2,-m_closeButtonROI[3]-2); glEnd(); //*/ //display text if (!pushName) { int xStartRel = c_margin; int yStartRel = -c_margin; yStartRel -= titleHeight; const colorType* defaultTextColor = (context.labelsTransparency<40 ? context.textDefaultCol : ccColor::darkBlue); context._win->displayText(title,xStart+xStartRel,yStart+yStartRel,ccGenericGLDisplay::ALIGN_DEFAULT,0,defaultTextColor,&titleFont); yStartRel -= c_margin; if (!body.empty()) { //line separation glColor4ubv(defaultBorderColor); glBegin(GL_LINES); glVertex2i(xStartRel,yStartRel); glVertex2i(xStartRel+m_labelROI[2]-m_labelROI[0]-2*c_margin,yStartRel); glEnd(); //display body yStartRel -= c_margin; for (int i=0;i<body.size();++i) { yStartRel -= strHeight; context._win->displayText(body[i],xStart+xStartRel,yStart+yStartRel,ccGenericGLDisplay::ALIGN_DEFAULT,0,defaultTextColor,&bodyFont); } } } glPopAttrib(); glPopMatrix(); if (pushName) glPopName(); }
void cc2DViewportLabel::drawMeOnly(CC_DRAW_CONTEXT& context) { //2D foreground only if (!MACRO_Foreground(context) || !MACRO_Draw2D(context)) return; //get the set of OpenGL functions (version 2.1) QOpenGLFunctions_2_1 *glFunc = context.glFunctions<QOpenGLFunctions_2_1>(); assert( glFunc != nullptr ); if ( glFunc == nullptr ) return; //test viewport parameters const ccViewportParameters& params = context.display->getViewportParameters(); //general parameters if ( params.perspectiveView != m_params.perspectiveView || params.objectCenteredView != m_params.objectCenteredView || params.pixelSize != m_params.pixelSize) { return; } //test base view matrix for (unsigned i = 0; i < 12; ++i) if (fabs(params.viewMat.data()[i] - m_params.viewMat.data()[i]) > ZERO_TOLERANCE) return; if (m_params.perspectiveView) { if (params.fov != m_params.fov || params.perspectiveAspectRatio != m_params.perspectiveAspectRatio) return; if ((params.pivotPoint - m_params.pivotPoint).norm() > ZERO_TOLERANCE || (params.cameraCenter - m_params.cameraCenter).norm() > ZERO_TOLERANCE) return; } else { if (params.orthoAspectRatio != m_params.orthoAspectRatio) return; } glFunc->glPushAttrib(GL_LINE_BIT); float relativeZoom = 1.0f; float dx = 0, dy = 0; if (!m_params.perspectiveView) //ortho mode { //Screen pan & pivot compensation float totalZoom = m_params.zoom / m_params.pixelSize; float winTotalZoom = params.zoom / params.pixelSize; relativeZoom = winTotalZoom / totalZoom; CCVector3d dC = m_params.cameraCenter - params.cameraCenter; CCVector3d P = m_params.pivotPoint - params.pivotPoint; m_params.viewMat.apply(P); dx = static_cast<float>(dC.x + P.x); dy = static_cast<float>(dC.y + P.y); dx *= winTotalZoom; dy *= winTotalZoom; } //thick dotted line glFunc->glLineWidth(2); glFunc->glLineStipple(1, 0xAAAA); glFunc->glEnable(GL_LINE_STIPPLE); const unsigned char* defaultColor = m_selected ? ccColor::red.rgba : context.textDefaultCol.rgb; glFunc->glColor3ubv(defaultColor); glFunc->glBegin(GL_LINE_LOOP); glFunc->glVertex2f(dx + m_roi[0] * relativeZoom, dy + m_roi[1] * relativeZoom); glFunc->glVertex2f(dx + m_roi[2] * relativeZoom, dy + m_roi[1] * relativeZoom); glFunc->glVertex2f(dx + m_roi[2] * relativeZoom, dy + m_roi[3] * relativeZoom); glFunc->glVertex2f(dx + m_roi[0] * relativeZoom, dy + m_roi[3] * relativeZoom); glFunc->glEnd(); glFunc->glPopAttrib(); //title QString title(getName()); if (!title.isEmpty()) { QFont titleFont(context.display->getTextDisplayFont()); //takes rendering zoom into account! titleFont.setBold(true); QFontMetrics titleFontMetrics(titleFont); int titleHeight = titleFontMetrics.height(); int xStart = (int)(dx + 0.5f*(float)context.glW + std::min<float>(m_roi[0], m_roi[2])*relativeZoom); int yStart = (int)(dy + 0.5f*(float)context.glH + std::min<float>(m_roi[1], m_roi[3])*relativeZoom); context.display->displayText(title, xStart, yStart - 5 - titleHeight, ccGenericGLDisplay::ALIGN_DEFAULT, 0, defaultColor, &titleFont); } }