Skip to content

Commit

Permalink
Sketcher: Constraint icons and fonts in 3D View
Browse files Browse the repository at this point in the history
===============================================

Based on PRs #4146 #4155.

PR #4155 proposes a scaling factor to be used to scale up constraint icons and the subindex font of icons. The
scaling factor is a parameter.

PR #4146 proposes to derive the constraint icon size from the system font size via function of the dpi. The
constraint icon subindex is a factor of the constraint size.

Observations:
- PR #4146 identifies the need for a scaling factor too, but this is a hardcoded 1.25 factor.
- PR #4146 appears to mix font points and font pixels when deriving the sizes.
- PR #4155 deals exclusively with icon size and subindex font, not with constraint label

Useful concepts:
- Font point is a physical distance. There are 72 points in one inch.
- Monitors have pixels with varying pixel densities. The number of pixels in one point varies
with pixel density. Hence the need for a correction based on the dpi of the monitor.

API constraints:
- While QT's configuration can be obtained in points or pixels, coin3D sets the font size in points.

Solution:
- Continue relying on the local font setting from preferences for coin3d font, albeit by converting from pixels to points.
- Introduce a sketcher wide 3D view scaling factor, as per #4155. This factor is however used for geometry, not for fonts.
- Geometry is scaled to compensate for the scaling factor and the monitor pixel density (the scaling factor is the product
of both scaling factors).
- Derive the 3D view icon size to be 80% (hardcoded) of the 3D view font size. Having constraint icons proportional to contraint label
font size gives consistency to the interface, as constraint icons also have subindices. I do not think it is worth to provide this 80%
as a configurable parameter
- The constraint icon subindex, being a special case of font relative to the accompanying icon, is set to be the 80% of the
icon size (hardcoded). I think it is not worth to provide this as a configurable parameter.

Bonus:
- ViewProviderSketch implements an observer of parameter group and tracks view scaling factor parameter and marker size.
- On change of parameter the inventor nodes are updated and the 3D view redrawn.
- Size information is moved to edit structure for consistency with Marker size.
  • Loading branch information
abdullahtahiriyo committed Jan 7, 2021
1 parent 1d970d5 commit 3661ffe
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 55 deletions.
2 changes: 1 addition & 1 deletion src/Mod/Sketcher/Gui/SoDatumLabel.cpp
Expand Up @@ -503,7 +503,7 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action)
const SbColor& t = textColor.getValue();

// Set GL Properties
glLineWidth(2.f);
glLineWidth(this->lineWidth.getValue());
glColor3f(t[0], t[1], t[2]);

if (this->datumtype.getValue() == DISTANCE ||
Expand Down
195 changes: 147 additions & 48 deletions src/Mod/Sketcher/Gui/ViewProviderSketch.cpp
Expand Up @@ -188,6 +188,8 @@ struct EditData {
PreselectCurve(-1),
PreselectCross(-1),
MarkerSize(7),
coinFontSize(11), // default of 11 points (not pixels)
constraintIconSize(15), // 11 points @ 96 ppi where 72 points = 1 inch
blockedPreselection(false),
FullyConstrained(false),
//ActSketch(0), // if you are wondering, it went to SketchObject, accessible via getSolvedSketch() and via SketchObject interface as appropriate
Expand All @@ -208,7 +210,13 @@ struct EditData {
textPos(0),
constrGroup(0),
infoGroup(0),
pickStyleAxes(0)
pickStyleAxes(0),
PointsDrawStyle(0),
CurvesDrawStyle(0),
RootCrossDrawStyle(0),
EditCurvesDrawStyle(0),
ConstraintDrawStyle(0),
InformationDrawStyle(0)
{}

// pointer to the active handler for new sketch objects
Expand All @@ -228,6 +236,9 @@ struct EditData {
int PreselectCurve;
int PreselectCross;
int MarkerSize;
int coinFontSize;
int constraintIconSize;
double pixelScalingFactor;
std::set<int> PreselectConstraintSet;
bool blockedPreselection;
bool FullyConstrained;
Expand Down Expand Up @@ -273,6 +284,13 @@ struct EditData {
SmSwitchboard *constrGroup;
SoGroup *infoGroup;
SoPickStyle *pickStyleAxes;

SoDrawStyle * PointsDrawStyle;
SoDrawStyle * CurvesDrawStyle;
SoDrawStyle * RootCrossDrawStyle;
SoDrawStyle * EditCurvesDrawStyle;
SoDrawStyle * ConstraintDrawStyle;
SoDrawStyle * InformationDrawStyle;
};


Expand Down Expand Up @@ -373,7 +391,8 @@ ViewProviderSketch::ViewProviderSketch()

//rubberband selection
rubberband = new Gui::Rubberband();
InitItemsSizes();

subscribeToParameters();
}

ViewProviderSketch::~ViewProviderSketch()
Expand Down Expand Up @@ -3191,11 +3210,14 @@ QString ViewProviderSketch::getPresentationString(const Constraint *constraint)
}
}
}

if (constraint->Type == Sketcher::Diameter){
userStr.insert(0, QChar(8960)); // Diameter sign
}else if (constraint->Type == Sketcher::Radius){
}
else if (constraint->Type == Sketcher::Radius){
userStr.insert(0, QChar(82)); // Capital letter R
}

return userStr;
}

Expand Down Expand Up @@ -3652,10 +3674,10 @@ QImage ViewProviderSketch::renderConstrIcon(const QString &type,
// Constants to help create constraint icons
QString joinStr = QString::fromLatin1(", ");

QImage icon = Gui::BitmapFactory().pixmapFromSvg(type.toLatin1().data(),QSizeF(constraintIconSize,constraintIconSize)).toImage();
QImage icon = Gui::BitmapFactory().pixmapFromSvg(type.toLatin1().data(),QSizeF(edit->constraintIconSize,edit->constraintIconSize)).toImage();

QFont font = QApplication::font();
font.setPixelSize(static_cast<int>(0.8 * constraintIconSize));
font.setPixelSize(static_cast<int>(0.8 * edit->constraintIconSize));
font.setBold(true);
QFontMetrics qfm = QFontMetrics(font);

Expand Down Expand Up @@ -3754,23 +3776,97 @@ float ViewProviderSketch::getScaleFactor()
}
}

void ViewProviderSketch::InitItemsSizes()
void ViewProviderSketch::OnChange(Base::Subject<const char*> &rCaller, const char * sReason)
{
(void) rCaller;
//ParameterGrp& rclGrp = ((ParameterGrp&)rCaller);
if (strcmp(sReason, "ViewScalingFactor") == 0 ||
strcmp(sReason, "MarkerSize") == 0 ||
strcmp(sReason, "EditSketcherFontSize") == 0 ) {
if(edit) { // only if in edit mode, if not it gets updated when entering edit mode
initItemsSizes();
updateInventorNodeSizes();
rebuildConstraintsVisual();
draw();
}
}
}

void ViewProviderSketch::subscribeToParameters()
{
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
hGrp->Attach(this);
}

void ViewProviderSketch::updateInventorNodeSizes()
{
assert(edit);
edit->PointsDrawStyle->pointSize = std::lround(8 * edit->pixelScalingFactor);
edit->PointSet->markerIndex = Gui::Inventor::MarkerBitmaps::getMarkerIndex("CIRCLE_FILLED", edit->MarkerSize);
edit->CurvesDrawStyle->lineWidth = std::lround(3 * edit->pixelScalingFactor);
edit->RootCrossDrawStyle->lineWidth = std::lround(2 * edit->pixelScalingFactor);
edit->EditCurvesDrawStyle->lineWidth = std::lround(3 * edit->pixelScalingFactor);
edit->ConstraintDrawStyle->lineWidth = std::lround(1 * edit->pixelScalingFactor);
edit->InformationDrawStyle->lineWidth = std::lround(1 * edit->pixelScalingFactor);
}

void ViewProviderSketch::initItemsSizes()
{
//Add scaling to Constraint icons
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/General");
double viewScalingFactor = hGrp->GetFloat("ViewScalingFactor", 1.25);
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
double viewScalingFactor = hGrp->GetFloat("ViewScalingFactor", 1.0);
viewScalingFactor = Base::clamp<double>(viewScalingFactor, 0.5, 5.0);
int markersize = hGrp->GetInt("MarkerSize", 7);

int defaultFontSizePixels = QApplication::fontMetrics().height(); // returns height in pixels, not points
int sketcherfontSize = hGrp->GetInt("EditSketcherFontSize", defaultFontSizePixels);

auto pixelsToPoints = [](int pixels, int dpi) {
return pixels*72/dpi; // definition of point, 72 points = 1 inch
};

// coin takes the font size in points, not pixels
// the coin FontSize in points from the system font, taking into account the application scaling factor is:
// -> pixelsToPoints(defaultFontSizePixels * viewScalingFactor, dpi)

int dpi = QApplication::desktop()->logicalDpiX();

if(edit) {
// simple scaling factor for hardcoded pixel values in the Sketcher
edit->pixelScalingFactor = viewScalingFactor * dpi / 96; // 96 ppi is the standard pixel density for which pixel quantities were calculated

int defaultFontSize = QApplication::fontMetrics().height();
int ldpi = QApplication::desktop()->logicalDpiX();
float virtualdpi = 96.;
float QtPixelRatio = virtualdpi/ldpi;
float coinFontPixelRatio = QtPixelRatio; // this is not absolute exactly, but the ratio is correct
edit->coinFontSize = pixelsToPoints(sketcherfontSize, dpi);
edit->constraintIconSize = std::lround(0.8 * sketcherfontSize);

hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
coinFontSize = hGrp->GetInt("EditSketcherFontSize", defaultFontSize * QtPixelRatio * coinFontPixelRatio * viewScalingFactor);
constraintIconSize = coinFontSize / coinFontPixelRatio;
return;
// The global default is used.
//
// Rationale:
// -> Other WBs use the default value as is
// -> If a user has a HDPI, he will eventually change the value for the other WBs
// -> If we correct the value here in addition, we would get two times a resize

edit->MarkerSize = markersize;

// This commented code would find a the closest supported marker value to a provided value.
// It may be useful if a different global marker size implementation is provided.
//
// Here marker size is used as a ratio to the default of 7 px (as a second scaling factor)
// the default marker size is 30% of the view3dFontPixels
// NOTE: Not all marker sizes are supported, grab the closest supported one.
/*
std::vector<int> supportedsizes {5, 7, 9, 11, 13, 15};
int calculatedmarker = std::lround(0.3*view3dFontPixels*markersize/7.0);
auto pos = std::upper_bound(supportedsizes.begin(), supportedsizes.end(), calculatedmarker);
if(pos == supportedsizes.end())
edit->MarkerSize = *std::prev(supportedsizes.end());
else if(pos == supportedsizes.begin())
edit->MarkerSize = *supportedsizes.begin();
else
edit->MarkerSize = (*pos - calculatedmarker > calculatedmarker - *std::prev(pos))?*std::prev(pos):*pos;
*/
}
}

void ViewProviderSketch::draw(bool temp /*=false*/, bool rebuildinformationlayer /*=true*/)
Expand Down Expand Up @@ -4251,7 +4347,7 @@ void ViewProviderSketch::draw(bool temp /*=false*/, bool rebuildinformationlayer

SoFont *font = new SoFont;
font->name.setValue("Helvetica");
font->size.setValue(coinFontSize);
font->size.setValue(edit->coinFontSize);

SoText2 *degreetext = new SoText2;
degreetext->string = SbString(spline->getDegree());
Expand Down Expand Up @@ -4530,7 +4626,7 @@ void ViewProviderSketch::draw(bool temp /*=false*/, bool rebuildinformationlayer

SoFont *font = new SoFont;
font->name.setValue("Helvetica");
font->size.setValue(coinFontSize);
font->size.setValue(edit->coinFontSize);

SoText2 *degreetext = new SoText2;
degreetext->string = SbString("(") + SbString(*itm) + SbString(")");
Expand Down Expand Up @@ -4597,7 +4693,7 @@ void ViewProviderSketch::draw(bool temp /*=false*/, bool rebuildinformationlayer

SoFont* font = new SoFont;
font->name.setValue("Helvetica");
font->size.setValue(coinFontSize);
font->size.setValue(edit->coinFontSize);

translate->translation.setValue(poleposition.x, poleposition.y, zInfo);

Expand Down Expand Up @@ -5815,7 +5911,8 @@ void ViewProviderSketch::rebuildConstraintsVisual(void)
ConstrDimColor
:NonDrivingConstrDimColor)
:DeactivatedConstrDimColor;
text->size.setValue(coinFontSize);
text->size.setValue(edit->coinFontSize);
text->lineWidth = std::lround(2 * edit->pixelScalingFactor);
text->useAntialiasing = false;
SoAnnotation *anno = new SoAnnotation();
anno->renderCaching = SoSeparator::OFF;
Expand Down Expand Up @@ -5918,6 +6015,7 @@ void ViewProviderSketch::rebuildConstraintsVisual(void)
arrows->norm.setValue(norm);
arrows->string = "";
arrows->textColor = ConstrDimColor;
arrows->lineWidth = std::lround(2 * edit->pixelScalingFactor);

// #define CONSTRAINT_SEPARATOR_INDEX_MATERIAL_OR_DATUMLABEL 0
sep->addChild(arrows);
Expand Down Expand Up @@ -6105,8 +6203,8 @@ bool ViewProviderSketch::setEdit(int ModNum)
assert(!edit);
edit = new EditData();

ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
edit->MarkerSize = hGrp->GetInt("MarkerSize", 7);
// Init icon, font and marker sizes
initItemsSizes();

ParameterGrp::handle hSketch = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher");
edit->handleEscapeButton = !hSketch->GetBool("LeaveSketchWithEscape", true);
Expand Down Expand Up @@ -6161,6 +6259,7 @@ bool ViewProviderSketch::setEdit(int ModNum)

float transparency;

ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
// set the point color
unsigned long color = (unsigned long)(VertexColor.getPackedValue());
color = hGrp->GetUnsigned("EditedVertexColor", color);
Expand Down Expand Up @@ -6424,10 +6523,10 @@ void ViewProviderSketch::createEditInventorNodes(void)
edit->PointsCoordinate->setName("PointsCoordinate");
pointsRoot->addChild(edit->PointsCoordinate);

SoDrawStyle *drawStyle = new SoDrawStyle;
drawStyle->setName("PointsDrawStyle");
drawStyle->pointSize = 8;
pointsRoot->addChild(drawStyle);
edit->PointsDrawStyle = new SoDrawStyle;
edit->PointsDrawStyle->setName("PointsDrawStyle");
edit->PointsDrawStyle->pointSize = std::lround(8 * edit->pixelScalingFactor);
pointsRoot->addChild(edit->PointsDrawStyle);

edit->PointSet = new SoMarkerSet;
edit->PointSet->setName("PointSet");
Expand All @@ -6450,10 +6549,10 @@ void ViewProviderSketch::createEditInventorNodes(void)
edit->CurvesCoordinate->setName("CurvesCoordinate");
curvesRoot->addChild(edit->CurvesCoordinate);

drawStyle = new SoDrawStyle;
drawStyle->setName("CurvesDrawStyle");
drawStyle->lineWidth = 3;
curvesRoot->addChild(drawStyle);
edit->CurvesDrawStyle = new SoDrawStyle;
edit->CurvesDrawStyle->setName("CurvesDrawStyle");
edit->CurvesDrawStyle->lineWidth = std::lround(3 * edit->pixelScalingFactor);
curvesRoot->addChild(edit->CurvesDrawStyle);

edit->CurveSet = new SoLineSet;
edit->CurveSet->setName("CurvesLineSet");
Expand All @@ -6470,10 +6569,10 @@ void ViewProviderSketch::createEditInventorNodes(void)
MtlBind->value = SoMaterialBinding::PER_FACE;
crossRoot->addChild(MtlBind);

drawStyle = new SoDrawStyle;
drawStyle->setName("RootCrossDrawStyle");
drawStyle->lineWidth = 2;
crossRoot->addChild(drawStyle);
edit->RootCrossDrawStyle = new SoDrawStyle;
edit->RootCrossDrawStyle->setName("RootCrossDrawStyle");
edit->RootCrossDrawStyle->lineWidth = std::lround(2 * edit->pixelScalingFactor);
crossRoot->addChild(edit->RootCrossDrawStyle);

edit->RootCrossMaterials = new SoMaterial;
edit->RootCrossMaterials->setName("RootCrossMaterials");
Expand All @@ -6500,10 +6599,10 @@ void ViewProviderSketch::createEditInventorNodes(void)
edit->EditCurvesCoordinate->setName("EditCurvesCoordinate");
editCurvesRoot->addChild(edit->EditCurvesCoordinate);

drawStyle = new SoDrawStyle;
drawStyle->setName("EditCurvesDrawStyle");
drawStyle->lineWidth = 3;
editCurvesRoot->addChild(drawStyle);
edit->EditCurvesDrawStyle = new SoDrawStyle;
edit->EditCurvesDrawStyle->setName("EditCurvesDrawStyle");
edit->EditCurvesDrawStyle->lineWidth = std::lround(3 * edit->pixelScalingFactor);
editCurvesRoot->addChild(edit->EditCurvesDrawStyle);

edit->EditCurveSet = new SoLineSet;
edit->EditCurveSet->setName("EditCurveLineSet");
Expand All @@ -6529,7 +6628,7 @@ void ViewProviderSketch::createEditInventorNodes(void)
Coordsep->addChild(CoordTextMaterials);

SoFont *font = new SoFont();
font->size.setValue(coinFontSize);
font->size.setValue(edit->coinFontSize);

Coordsep->addChild(font);

Expand All @@ -6549,10 +6648,10 @@ void ViewProviderSketch::createEditInventorNodes(void)
edit->EditRoot->addChild(MtlBind);

// use small line width for the Constraints
drawStyle = new SoDrawStyle;
drawStyle->setName("ConstraintDrawStyle");
drawStyle->lineWidth = 1;
edit->EditRoot->addChild(drawStyle);
edit->ConstraintDrawStyle = new SoDrawStyle;
edit->ConstraintDrawStyle->setName("ConstraintDrawStyle");
edit->ConstraintDrawStyle->lineWidth = std::lround(1 * edit->pixelScalingFactor);
edit->EditRoot->addChild(edit->ConstraintDrawStyle);

// add the group where all the constraints has its SoSeparator
edit->constrGroup = new SmSwitchboard();
Expand All @@ -6566,10 +6665,10 @@ void ViewProviderSketch::createEditInventorNodes(void)
edit->EditRoot->addChild(MtlBind);

// use small line width for the information visual
drawStyle = new SoDrawStyle;
drawStyle->setName("InformationDrawStyle");
drawStyle->lineWidth = 1;
edit->EditRoot->addChild(drawStyle);
edit->InformationDrawStyle = new SoDrawStyle;
edit->InformationDrawStyle->setName("InformationDrawStyle");
edit->InformationDrawStyle->lineWidth = std::lround(1 * edit->pixelScalingFactor);
edit->EditRoot->addChild(edit->InformationDrawStyle);

// add the group where all the information entity has its SoSeparator
edit->infoGroup = new SoGroup();
Expand Down

0 comments on commit 3661ffe

Please sign in to comment.