Fix high dpi multimonitor glitch
This commit is contained in:
parent
df568f4d0b
commit
833c1fe5ee
29 changed files with 179 additions and 150 deletions
|
@ -8,6 +8,7 @@
|
|||
#include "tpalette.h"
|
||||
|
||||
class TStroke;
|
||||
class QWidget;
|
||||
|
||||
#undef DVAPI
|
||||
#undef DVVAR
|
||||
|
@ -22,15 +23,17 @@ class TStroke;
|
|||
class DVAPI StylePicker {
|
||||
TImageP m_image;
|
||||
TPaletteP m_palette;
|
||||
const QWidget *m_widget;
|
||||
|
||||
public:
|
||||
StylePicker() {}
|
||||
StylePicker(const QWidget *parent) : m_widget(parent) {}
|
||||
|
||||
// usa come palette la palette dell'immagine
|
||||
StylePicker(const TImageP &image);
|
||||
StylePicker(const QWidget *parent, const TImageP &image);
|
||||
|
||||
// palette esterna (ad es. se image e' di tipo raster)
|
||||
StylePicker(const TImageP &image, const TPaletteP &palette);
|
||||
StylePicker(const QWidget *parent, const TImageP &image,
|
||||
const TPaletteP &palette);
|
||||
|
||||
// pickStyleId(point, radius)
|
||||
//
|
||||
|
|
|
@ -605,9 +605,10 @@ protected:
|
|||
int guidedStrokePickMode = 0;
|
||||
int m_guidedFrontStroke = -1;
|
||||
int m_guidedBackStroke = -1;
|
||||
QWidget *m_viewerWidget = nullptr;
|
||||
|
||||
public:
|
||||
Viewer() {}
|
||||
Viewer(QWidget *widget) : m_viewerWidget(widget) {}
|
||||
virtual ~Viewer() {}
|
||||
|
||||
const ImagePainter::VisualSettings &visualSettings() const {
|
||||
|
@ -717,6 +718,8 @@ public:
|
|||
|
||||
void getGuidedFrameIdx(int *backIdx, int *frontIdx);
|
||||
void doPickGuideStroke(const TPointD &pos);
|
||||
|
||||
QWidget *viewerWidget() { return m_viewerWidget; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,6 +19,7 @@ public:
|
|||
int width() const { return QOpenGLWidget::width() * getDevPixRatio(); }
|
||||
int height() const { return QOpenGLWidget::height() * getDevPixRatio(); }
|
||||
QRect rect() const { return QRect(0, 0, width(), height()); }
|
||||
int getDevPixRatio() const { return getDevicePixelRatio(this); }
|
||||
};
|
||||
|
||||
#endif
|
|
@ -104,7 +104,7 @@ svgToPixmap(const QString &svgFilePath, const QSize &size = QSize(),
|
|||
// returns device-pixel ratio. It is 1 for normal monitors and 2 (or higher
|
||||
// ratio) for high DPI monitors. Setting "Display > Set custom text size(DPI)"
|
||||
// for Windows corresponds to this ratio.
|
||||
int DVAPI getDevPixRatio();
|
||||
int DVAPI getDevicePixelRatio(const QWidget *widget = nullptr);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -1141,7 +1141,7 @@ void EditTool::drawMainHandle() {
|
|||
TAffine parentAff = xsh->getParentPlacement(objId, frame);
|
||||
TAffine aff = xsh->getPlacement(objId, frame);
|
||||
TPointD center = Stage::inch * xsh->getCenter(objId, frame);
|
||||
int devPixRatio = getDevPixRatio();
|
||||
int devPixRatio = getDevicePixelRatio(m_viewer->viewerWidget());
|
||||
// the gadget appears on the center of the level. orientation and dimension
|
||||
// are independent of the movement of the level
|
||||
glPushMatrix();
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "tparamuiconcept.h"
|
||||
|
||||
#include "historytypes.h"
|
||||
#include "toonzqt/gutil.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
|
@ -26,11 +27,6 @@ using namespace EditToolGadgets;
|
|||
GLdouble FxGadget::m_selectedColor[3] = {0.2, 0.8, 0.1};
|
||||
|
||||
namespace {
|
||||
int getDevPixRatio() {
|
||||
static int devPixRatio = QApplication::desktop()->devicePixelRatio();
|
||||
return devPixRatio;
|
||||
}
|
||||
|
||||
TPointD hadamard(const TPointD &v1, const TPointD &v2) {
|
||||
return TPointD(v1.x * v2.x, v1.y * v2.y);
|
||||
}
|
||||
|
@ -199,14 +195,14 @@ void FxGadget::setValue(const TPointParamP ¶m, const TPointD &pos) {
|
|||
//---------------------------------------------------------------------------
|
||||
|
||||
void FxGadget::setPixelSize() {
|
||||
setPixelSize(sqrt(tglGetPixelSize2()) * getDevPixRatio());
|
||||
setPixelSize(sqrt(tglGetPixelSize2()) * m_controller->getDevPixRatio());
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void FxGadget::drawTooltip(const TPointD &tooltipPos,
|
||||
std::string tooltipPosText) {
|
||||
double unit = sqrt(tglGetPixelSize2()) * getDevPixRatio();
|
||||
double unit = sqrt(tglGetPixelSize2()) * m_controller->getDevPixRatio();
|
||||
glPushMatrix();
|
||||
glTranslated(tooltipPos.x, tooltipPos.y, 0.0);
|
||||
double sc = unit * 1.6;
|
||||
|
@ -494,7 +490,7 @@ void AngleFxGadget::draw(bool picking) {
|
|||
else
|
||||
glColor3d(0, 0, 1);
|
||||
glPushName(getId());
|
||||
double pixelSize = sqrt(tglGetPixelSize2()) * getDevPixRatio();
|
||||
double pixelSize = sqrt(tglGetPixelSize2()) * m_controller->getDevPixRatio();
|
||||
double r = pixelSize * 40;
|
||||
double a = pixelSize * 10, b = pixelSize * 5;
|
||||
tglDrawCircle(m_pos, r);
|
||||
|
@ -579,7 +575,7 @@ void AngleRangeFxGadget::draw(bool picking) {
|
|||
glColor3d(0, 0, 1);
|
||||
};
|
||||
|
||||
double pixelSize = sqrt(tglGetPixelSize2()) * getDevPixRatio();
|
||||
double pixelSize = sqrt(tglGetPixelSize2()) * m_controller->getDevPixRatio();
|
||||
double r = pixelSize * 200;
|
||||
double a = pixelSize * 30;
|
||||
|
||||
|
@ -2063,3 +2059,7 @@ int FxGadgetController::getCurrentFrame() const { return m_tool->getFrame(); }
|
|||
//---------------------------------------------------------------------------
|
||||
|
||||
void FxGadgetController::invalidateViewer() { m_tool->invalidate(); }
|
||||
|
||||
int FxGadgetController::getDevPixRatio() {
|
||||
return getDevicePixelRatio(m_tool->getViewer()->viewerWidget());
|
||||
}
|
||||
|
|
|
@ -151,6 +151,8 @@ public:
|
|||
|
||||
bool hasGadget() { return m_gadgets.size() != 0; }
|
||||
|
||||
int getDevPixRatio();
|
||||
|
||||
public slots:
|
||||
|
||||
void onFxSwitched();
|
||||
|
|
|
@ -2578,7 +2578,7 @@ int FillTool::pick(const TImageP &image, const TPointD &pos, const int frame) {
|
|||
TVectorImageP vi = image;
|
||||
if (!ti && !vi) return 0;
|
||||
|
||||
StylePicker picker(image);
|
||||
StylePicker picker(getViewer()->viewerWidget(), image);
|
||||
double scale2 = 1.0;
|
||||
if (vi) {
|
||||
TAffine aff = getViewer()->getViewMatrix() * getCurrentColumnMatrix(frame);
|
||||
|
|
|
@ -561,7 +561,7 @@ void FingerTool::pick(const TPointD &pos) {
|
|||
|
||||
int subsampling = level->getImageSubsampling(getCurrentFid());
|
||||
|
||||
StylePicker picker(image);
|
||||
StylePicker picker(getViewer()->viewerWidget(), image);
|
||||
|
||||
int styleId =
|
||||
picker.pickStyleId(TScale(1.0 / subsampling) * pos + TPointD(-0.5, -0.5),
|
||||
|
|
|
@ -705,7 +705,7 @@ int PaintBrushTool::getStyleUnderCursor(const TPointD &pos) {
|
|||
|
||||
int subsampling = level->getImageSubsampling(getCurrentFid());
|
||||
|
||||
StylePicker picker(image);
|
||||
StylePicker picker(getViewer()->viewerWidget(), image);
|
||||
|
||||
int styleId =
|
||||
picker.pickStyleId(TScale(1.0 / subsampling) * pos,
|
||||
|
|
|
@ -331,12 +331,12 @@ void PerspectivePresetManager::deletePreset(TFilePath presetPath) {
|
|||
|
||||
//----------------------------------------------------------------------------------------------------------
|
||||
|
||||
void PerspectiveControls::drawControls() {
|
||||
void PerspectiveControls::drawControls(SceneViewer *viewer) {
|
||||
if (!m_perspective) return;
|
||||
|
||||
TPointD centerPoint = m_perspective->getCenterPoint();
|
||||
|
||||
m_unit = sqrt(tglGetPixelSize2()) * getDevPixRatio();
|
||||
m_unit = sqrt(tglGetPixelSize2()) * viewer->getDevPixRatio();
|
||||
|
||||
double circleRadius = m_handleRadius * m_unit;
|
||||
double diskRadius = (m_handleRadius - 2) * m_unit;
|
||||
|
@ -707,7 +707,7 @@ void PerspectiveTool::draw(SceneViewer *viewer) {
|
|||
bool drawControls = getApplication()->getCurrentTool()->getTool() == this;
|
||||
if (drawControls) {
|
||||
for (int i = 0; i < m_perspectiveObjs.size(); i++)
|
||||
m_perspectiveObjs[i]->drawControls();
|
||||
m_perspectiveObjs[i]->drawControls(viewer);
|
||||
}
|
||||
|
||||
if (m_selecting) {
|
||||
|
|
|
@ -145,7 +145,7 @@ public:
|
|||
|
||||
void shiftPerspectiveObject(TPointD delta);
|
||||
|
||||
void drawControls();
|
||||
void drawControls(SceneViewer *viewer);
|
||||
|
||||
bool isOverCenterPoint() {
|
||||
TPointD centerPoint = m_perspective->getCenterPoint();
|
||||
|
|
|
@ -430,7 +430,7 @@ void RGBPickerTool::passivePick() {
|
|||
TRectD area = TRectD(m_mousePixelPosition.x, m_mousePixelPosition.y,
|
||||
m_mousePixelPosition.x, m_mousePixelPosition.y);
|
||||
|
||||
StylePicker picker(image);
|
||||
StylePicker picker(getViewer()->viewerWidget(), image);
|
||||
|
||||
if (LutManager::instance()->isValid()) m_viewer->bindFBO();
|
||||
|
||||
|
@ -458,7 +458,7 @@ void RGBPickerTool::pick() {
|
|||
|
||||
TRectD area = TRectD(m_mousePixelPosition.x - 1, m_mousePixelPosition.y - 1,
|
||||
m_mousePixelPosition.x + 1, m_mousePixelPosition.y + 1);
|
||||
StylePicker picker(image, palette);
|
||||
StylePicker picker(getViewer()->viewerWidget(), image, palette);
|
||||
|
||||
if (LutManager::instance()->isValid()) m_viewer->bindFBO();
|
||||
|
||||
|
@ -491,7 +491,7 @@ void RGBPickerTool::pickRect() {
|
|||
}
|
||||
m_selectingRect.empty();
|
||||
if (area.getLx() <= 1 || area.getLy() <= 1) return;
|
||||
StylePicker picker(image, palette);
|
||||
StylePicker picker(getViewer()->viewerWidget(), image, palette);
|
||||
|
||||
if (LutManager::instance()->isValid()) m_viewer->bindFBO();
|
||||
|
||||
|
@ -511,7 +511,7 @@ void RGBPickerTool::pickStroke() {
|
|||
TPalette *palette = ph->getPalette();
|
||||
if (!palette) return;
|
||||
|
||||
StylePicker picker(image, palette);
|
||||
StylePicker picker(getViewer()->viewerWidget(), image, palette);
|
||||
TStroke *stroke = new TStroke(*m_stroke);
|
||||
|
||||
if (LutManager::instance()->isValid()) m_viewer->bindFBO();
|
||||
|
|
|
@ -245,7 +245,7 @@ void ShiftTraceTool::drawControlRect() { // TODO
|
|||
inksOnly);
|
||||
color = (m_ghostIndex == 0) ? backOniColor : frontOniColor;
|
||||
double unit = sqrt(tglGetPixelSize2());
|
||||
unit *= getDevPixRatio();
|
||||
unit *= getDevicePixelRatio(m_viewer->viewerWidget());
|
||||
TRectD coloredBox = box.enlarge(3.0 * unit);
|
||||
tglColor(color);
|
||||
glBegin(GL_LINE_STRIP);
|
||||
|
|
|
@ -17,13 +17,14 @@
|
|||
|
||||
//---------------------------------------------------------
|
||||
|
||||
StylePicker::StylePicker(const TImageP &image)
|
||||
: m_image(image), m_palette(image->getPalette()) {}
|
||||
StylePicker::StylePicker(const QWidget *parent, const TImageP &image)
|
||||
: m_widget(parent), m_image(image), m_palette(image->getPalette()) {}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
StylePicker::StylePicker(const TImageP &image, const TPaletteP &palette)
|
||||
: m_image(image), m_palette(palette) {}
|
||||
StylePicker::StylePicker(const QWidget *parent, const TImageP &image,
|
||||
const TPaletteP &palette)
|
||||
: m_widget(parent), m_image(image), m_palette(palette) {}
|
||||
|
||||
//---------------------------------------------------------
|
||||
|
||||
|
@ -86,7 +87,7 @@ int StylePicker::pickStyleId(const TPointD &pos, double radius, double scale2,
|
|||
// la thickness, cioe' la min distance dalla outline e non dalla centerLine
|
||||
strokeFound = vi->getNearestStroke(pos, w, index, dist2);
|
||||
if (strokeFound) {
|
||||
int devPixRatio = getDevPixRatio();
|
||||
int devPixRatio = getDevicePixelRatio(m_widget);
|
||||
dist2 *= scale2;
|
||||
TStroke *stroke = vi->getStroke(index);
|
||||
thick = stroke->getThickPoint(w).thick;
|
||||
|
|
|
@ -116,7 +116,7 @@ void StylePickerTool::pick(const TPointD &pos, const TMouseEvent &e,
|
|||
TAffine aff =
|
||||
getViewer()->getViewMatrix() * getColumnMatrix(superPickedColumnId);
|
||||
double scale2 = aff.det();
|
||||
StylePicker superPicker(pickedImage);
|
||||
StylePicker superPicker(getViewer()->viewerWidget(), pickedImage);
|
||||
int picked_subsampling =
|
||||
picked_level->getImageSubsampling(pickedCell.getFrameId());
|
||||
int superPicked_StyleId = superPicker.pickStyleId(
|
||||
|
@ -159,7 +159,7 @@ void StylePickerTool::pick(const TPointD &pos, const TMouseEvent &e,
|
|||
TAffine aff = getViewer()->getViewMatrix() * getCurrentColumnMatrix();
|
||||
double scale2 = aff.det();
|
||||
int subsampling = level->getImageSubsampling(getCurrentFid());
|
||||
StylePicker picker(image);
|
||||
StylePicker picker(getViewer()->viewerWidget(), image);
|
||||
int styleId =
|
||||
picker.pickStyleId(TScale(1.0 / subsampling) * pos + TPointD(-0.5, -0.5),
|
||||
10.0, scale2, modeValue);
|
||||
|
@ -215,7 +215,7 @@ void StylePickerTool::mouseMove(const TPointD &pos, const TMouseEvent &e) {
|
|||
TAffine aff = getViewer()->getViewMatrix() * getCurrentColumnMatrix();
|
||||
double scale2 = aff.det();
|
||||
int subsampling = level->getImageSubsampling(getCurrentFid());
|
||||
StylePicker picker(image);
|
||||
StylePicker picker(getViewer()->viewerWidget(), image);
|
||||
TPointD pickPos(TScale(1.0 / subsampling) * pos + TPointD(-0.5, -0.5));
|
||||
int inkStyleId = picker.pickStyleId(pickPos, 10.0, scale2, 1);
|
||||
int paintStyleId = picker.pickStyleId(pickPos, 10.0, scale2, 0);
|
||||
|
|
|
@ -1505,7 +1505,9 @@ void ToolUtils::drawBalloon(const TPointD &pos, std::string text,
|
|||
const TPixel32 &color, TPoint delta,
|
||||
double pixelSize, bool isPicking,
|
||||
std::vector<TRectD> *otherBalloons) {
|
||||
int devPixRatio = getDevPixRatio();
|
||||
TTool::Viewer *viewer =
|
||||
TTool::getApplication()->getCurrentTool()->getTool()->getViewer();
|
||||
int devPixRatio = getDevicePixelRatio(viewer->viewerWidget());
|
||||
QString qText = QString::fromStdString(text);
|
||||
QFont font("Arial"); // ,QFont::Bold);
|
||||
font.setPixelSize(13 * devPixRatio);
|
||||
|
@ -1558,9 +1560,6 @@ void ToolUtils::drawBalloon(const TPointD &pos, std::string text,
|
|||
int y1 = textRect.bottom() + mrg;
|
||||
|
||||
if (isPicking) {
|
||||
TTool::Viewer *viewer =
|
||||
TTool::getApplication()->getCurrentTool()->getTool()->getViewer();
|
||||
|
||||
if (viewer->is3DView()) {
|
||||
double x0 = pos.x + textRect.left() * pixelSize,
|
||||
y0 = pos.y + delta.y * pixelSize;
|
||||
|
@ -1650,7 +1649,9 @@ void ToolUtils::drawBalloon(const TPointD &pos, std::string text,
|
|||
|
||||
void ToolUtils::drawHook(const TPointD &pos, ToolUtils::HookType type,
|
||||
bool highlighted, bool onionSkin) {
|
||||
int devPixRatio = getDevPixRatio();
|
||||
TTool::Viewer *viewer =
|
||||
TTool::getApplication()->getCurrentTool()->getTool()->getViewer();
|
||||
int devPixRatio = getDevicePixelRatio(viewer->viewerWidget());
|
||||
int r = 10, d = r + r;
|
||||
QImage image(d * devPixRatio, d * devPixRatio, QImage::Format_ARGB32);
|
||||
image.fill(Qt::transparent);
|
||||
|
|
|
@ -271,14 +271,16 @@ void ColorModelViewer::contextMenuEvent(QContextMenuEvent *event) {
|
|||
/*! If left button is pressed recall \b pick() in event pos.
|
||||
*/
|
||||
void ColorModelViewer::mousePressEvent(QMouseEvent *event) {
|
||||
if (event->button() == Qt::LeftButton) pick(event->pos() * getDevPixRatio());
|
||||
if (event->button() == Qt::LeftButton)
|
||||
pick(event->pos() * getDevicePixelRatio(this));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/*! If left button is moved recall \b pick() in event pos.
|
||||
*/
|
||||
void ColorModelViewer::mouseMoveEvent(QMouseEvent *event) {
|
||||
if (event->buttons() & Qt::LeftButton) pick(event->pos() * getDevPixRatio());
|
||||
if (event->buttons() & Qt::LeftButton)
|
||||
pick(event->pos() * getDevicePixelRatio(this));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -296,7 +298,7 @@ void ColorModelViewer::pick(const QPoint &p) {
|
|||
/*- 画面外ではPickできない -*/
|
||||
if (!m_imageViewer->rect().contains(p)) return;
|
||||
|
||||
StylePicker picker(img, currentPalette);
|
||||
StylePicker picker(this, img, currentPalette);
|
||||
|
||||
QPoint viewP = m_imageViewer->mapFrom(this, p);
|
||||
TPointD pos = m_imageViewer->getViewAff().inv() *
|
||||
|
|
|
@ -2116,8 +2116,8 @@ void FlipBook::onDoubleClick(QMouseEvent *me) {
|
|||
if (!img) return;
|
||||
|
||||
TAffine toWidgetRef(m_imageViewer->getImgToWidgetAffine());
|
||||
TRectD pixGeomD(TScale(1.0 / (double)getDevPixRatio()) * toWidgetRef *
|
||||
getImageBoundsD(img));
|
||||
TRectD pixGeomD(TScale(1.0 / (double)getDevicePixelRatio(this)) *
|
||||
toWidgetRef * getImageBoundsD(img));
|
||||
// TRectD pixGeomD(toWidgetRef * getImageBoundsD(img));
|
||||
TRect pixGeom(tceil(pixGeomD.x0), tceil(pixGeomD.y0), tfloor(pixGeomD.x1) - 1,
|
||||
tfloor(pixGeomD.y1) - 1);
|
||||
|
|
|
@ -973,7 +973,7 @@ void ImageViewer::pickColor(QMouseEvent *event, bool putValueToStyleEditor) {
|
|||
return;
|
||||
}
|
||||
|
||||
StylePicker picker(img);
|
||||
StylePicker picker(this, img);
|
||||
|
||||
TPointD pos =
|
||||
getViewAff().inv() * TPointD(curPos.x() - (qreal)(width()) / 2,
|
||||
|
@ -1042,7 +1042,7 @@ void ImageViewer::rectPickColor(bool putValueToStyleEditor) {
|
|||
return;
|
||||
}
|
||||
|
||||
StylePicker picker(img);
|
||||
StylePicker picker(this, img);
|
||||
|
||||
if (!img->raster()) { // vector image
|
||||
TPointD pressedWinPos = convert(m_pressedMousePos) + m_winPosMousePosOffset;
|
||||
|
|
|
@ -460,9 +460,7 @@ int main(int argc, char *argv[]) {
|
|||
// splash screen
|
||||
QPixmap splashPixmap =
|
||||
QIcon(":Resources/splash2.svg").pixmap(QSize(344, 344));
|
||||
splashPixmap.setDevicePixelRatio(QApplication::desktop()->devicePixelRatio());
|
||||
|
||||
// QPixmap splashPixmap(":Resources/splash.png");
|
||||
#ifdef _WIN32
|
||||
QFont font("Segoe UI", -1);
|
||||
#else
|
||||
|
|
|
@ -107,10 +107,10 @@ double Ruler::getPan() const {
|
|||
if (m_viewer->is3DView()) // Vertical 3D
|
||||
return m_viewer->getPan3D().y;
|
||||
else // Vertical 2D
|
||||
return aff.a23 / getDevPixRatio();
|
||||
return aff.a23 / m_viewer->getDevPixRatio();
|
||||
else if (m_viewer->is3DView()) // Horizontal 3D
|
||||
return m_viewer->getPan3D().x;
|
||||
return aff.a13 / getDevPixRatio(); // Horizontal 2D
|
||||
return aff.a13 / m_viewer->getDevPixRatio(); // Horizontal 2D
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -137,7 +137,7 @@ void Ruler::drawVertical(QPainter &p) {
|
|||
for (i = 0; i < count; i++) {
|
||||
QColor color = (m_moving && count - 1 == i ? QColor(getHandleDragColor())
|
||||
: QColor(getHandleColor()));
|
||||
double v = guides[i] / (double)getDevPixRatio();
|
||||
double v = guides[i] / (double)m_viewer->getDevPixRatio();
|
||||
int y = (int)(origin - zoom * v);
|
||||
p.fillRect(QRect(x0, y - 1, x1 - x0, 2), QBrush(color));
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ void Ruler::drawHorizontal(QPainter &p) {
|
|||
for (i = 0; i < count; i++) {
|
||||
QColor color = (m_moving && count - 1 == i ? QColor(getHandleDragColor())
|
||||
: QColor(getHandleColor()));
|
||||
double v = guides[i] / (double)getDevPixRatio();
|
||||
double v = guides[i] / (double)m_viewer->getDevPixRatio();
|
||||
int x = (int)(origin + zoom * v);
|
||||
p.fillRect(QRect(x - 1, y0, 2, y1 - y0), QBrush(color));
|
||||
}
|
||||
|
@ -258,7 +258,7 @@ void Ruler::mousePressEvent(QMouseEvent *e) {
|
|||
int i;
|
||||
int count = guides.size();
|
||||
for (i = 0; i < count; i++) {
|
||||
double g = guides[i] / (double)getDevPixRatio();
|
||||
double g = guides[i] / (double)m_viewer->getDevPixRatio();
|
||||
double dist2 = (g - v) * (g - v);
|
||||
if (selected < 0 || dist2 < minDist2) {
|
||||
minDist2 = dist2;
|
||||
|
@ -268,7 +268,7 @@ void Ruler::mousePressEvent(QMouseEvent *e) {
|
|||
if (e->button() == Qt::LeftButton) {
|
||||
if (selected < 0 || minDist2 > 25) {
|
||||
// crea una nuova guida
|
||||
guides.push_back(v * getDevPixRatio());
|
||||
guides.push_back(v * m_viewer->getDevPixRatio());
|
||||
m_viewer->update();
|
||||
// aggiorna sprop!!!!
|
||||
} else if (selected < count - 1)
|
||||
|
@ -294,7 +294,7 @@ void Ruler::mousePressEvent(QMouseEvent *e) {
|
|||
void Ruler::mouseMoveEvent(QMouseEvent *e) {
|
||||
if (m_moving) {
|
||||
m_hiding = m_vertical ? (e->pos().x() < 0) : (e->pos().y() < 0);
|
||||
getGuides().back() = posToValue(e->pos()) * getDevPixRatio();
|
||||
getGuides().back() = posToValue(e->pos()) * m_viewer->getDevPixRatio();
|
||||
// aggiorna sprop!!!!
|
||||
update();
|
||||
m_viewer->update();
|
||||
|
@ -308,7 +308,7 @@ void Ruler::mouseMoveEvent(QMouseEvent *e) {
|
|||
|
||||
int count = guides.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
double g = guides[i] / (double)getDevPixRatio();
|
||||
double g = guides[i] / (double)m_viewer->getDevPixRatio();
|
||||
double dist2 = (g - v) * (g - v);
|
||||
if (dist2 < 25) {
|
||||
setToolTip(tr(
|
||||
|
|
|
@ -757,6 +757,7 @@ public:
|
|||
|
||||
SceneViewer::SceneViewer(ImageUtils::FullScreenWidget *parent)
|
||||
: GLWidgetForHighDpi(parent)
|
||||
, TTool::Viewer(this)
|
||||
, m_pressure(0)
|
||||
, m_lastMousePos(0, 0)
|
||||
, m_mouseButton(Qt::NoButton)
|
||||
|
|
|
@ -31,7 +31,7 @@ inline bool bitwiseContains(UCHAR flag, UCHAR state) {
|
|||
inline bool bitwiseExclude(UCHAR flag, UCHAR state) {
|
||||
return bitwiseContains(~state, flag);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
//********************************************************************************
|
||||
// Classes implementation
|
||||
|
@ -119,7 +119,7 @@ bool PreviewSubCameraManager::mousePressEvent(SceneViewer *viewer,
|
|||
if (viewer->is3DView()) return true;
|
||||
|
||||
m_mousePressed = true;
|
||||
m_mousePressPos = event.mousePos() * getDevPixRatio();
|
||||
m_mousePressPos = event.mousePos() * viewer->getDevPixRatio();
|
||||
m_dragType = getSubCameraDragEnum(viewer, m_mousePressPos);
|
||||
|
||||
if (bitwiseExclude(m_dragType, OUTER))
|
||||
|
@ -133,7 +133,7 @@ bool PreviewSubCameraManager::mousePressEvent(SceneViewer *viewer,
|
|||
bool PreviewSubCameraManager::mouseMoveEvent(SceneViewer *viewer,
|
||||
const TMouseEvent &event) {
|
||||
if (viewer->is3DView()) return true;
|
||||
QPointF curPos(event.mousePos() * getDevPixRatio());
|
||||
QPointF curPos(event.mousePos() * viewer->getDevPixRatio());
|
||||
if (event.buttons() == Qt::LeftButton) {
|
||||
if (!bitwiseContains(m_dragType, INNER)) {
|
||||
if (std::abs(curPos.x() - m_mousePressPos.x()) > 10 ||
|
||||
|
|
|
@ -1239,22 +1239,20 @@ void FxSchematicPort::paint(QPainter *painter,
|
|||
const QStyleOptionGraphicsItem *option,
|
||||
QWidget *widget) {
|
||||
if (m_isPassThrough && getLinkCount() > 0) return;
|
||||
|
||||
int devicePixelRatio = getDevicePixelRatio(widget);
|
||||
// large scaled
|
||||
if (getDock()->getNode()->isNormalIconView()) {
|
||||
switch (getType()) {
|
||||
case eFxInputPort:
|
||||
case eFxGroupedInPort: {
|
||||
QRect sourceRect =
|
||||
QRect targetRect =
|
||||
scene()->views()[0]->matrix().mapRect(boundingRect()).toRect();
|
||||
static QIcon fxPortRedIcon(":Resources/fxport_red.svg");
|
||||
static QIcon fxPortPassThroughRedIcon(":Resources/fxport_pt_red.svg");
|
||||
QPixmap redPm = (m_isPassThrough)
|
||||
? fxPortPassThroughRedIcon.pixmap(sourceRect.size())
|
||||
: fxPortRedIcon.pixmap(sourceRect.size());
|
||||
sourceRect = QRect(0, 0, sourceRect.width() * getDevPixRatio(),
|
||||
sourceRect.height() * getDevPixRatio());
|
||||
painter->drawPixmap(boundingRect(), redPm, sourceRect);
|
||||
? fxPortPassThroughRedIcon.pixmap(targetRect.size())
|
||||
: fxPortRedIcon.pixmap(targetRect.size());
|
||||
painter->drawPixmap(boundingRect().toRect(), redPm);
|
||||
} break;
|
||||
|
||||
case eFxOutputPort:
|
||||
|
@ -1263,8 +1261,7 @@ void FxSchematicPort::paint(QPainter *painter,
|
|||
scene()->views()[0]->matrix().mapRect(boundingRect()).toRect();
|
||||
static QIcon fxPortBlueIcon(":Resources/fxport_blue.svg");
|
||||
QPixmap bluePm = fxPortBlueIcon.pixmap(sourceRect.size());
|
||||
sourceRect = QRect(0, 0, sourceRect.width() * getDevPixRatio(),
|
||||
sourceRect.height() * getDevPixRatio());
|
||||
sourceRect = QRect(0, 0, bluePm.width(), bluePm.height());
|
||||
painter->drawPixmap(boundingRect(), bluePm, sourceRect);
|
||||
FxSchematicDock *parentDock =
|
||||
dynamic_cast<FxSchematicDock *>(parentItem());
|
||||
|
@ -1288,9 +1285,7 @@ void FxSchematicPort::paint(QPainter *painter,
|
|||
scene()->views()[0]->matrix().mapRect(boundingRect()).toRect();
|
||||
QPixmap linkPm =
|
||||
QIcon(":Resources/schematic_link.svg").pixmap(sourceRect.size());
|
||||
sourceRect = QRect(0, 0, sourceRect.width() * getDevPixRatio(),
|
||||
sourceRect.height() * getDevPixRatio());
|
||||
painter->drawPixmap(boundingRect(), linkPm, sourceRect);
|
||||
painter->drawPixmap(boundingRect().toRect(), linkPm);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
@ -1314,9 +1309,7 @@ void FxSchematicPort::paint(QPainter *painter,
|
|||
scene()->views()[0]->matrix().mapRect(boundingRect()).toRect();
|
||||
QPixmap linkPm = QIcon(":Resources/schematic_link_small.svg")
|
||||
.pixmap(sourceRect.size());
|
||||
sourceRect = QRect(0, 0, sourceRect.width() * getDevPixRatio(),
|
||||
sourceRect.height() * getDevPixRatio());
|
||||
painter->drawPixmap(boundingRect(), linkPm, sourceRect);
|
||||
painter->drawPixmap(boundingRect().toRect(), linkPm);
|
||||
} break;
|
||||
}
|
||||
painter->drawRect(boundingRect());
|
||||
|
|
|
@ -31,9 +31,38 @@
|
|||
#include <QFileInfo>
|
||||
#include <QDesktopWidget>
|
||||
#include <QSvgRenderer>
|
||||
#include <QScreen>
|
||||
#include <QWindow>
|
||||
|
||||
using namespace DVGui;
|
||||
|
||||
namespace {
|
||||
inline bool hasScreensWithDifferentDevPixRatio() {
|
||||
static bool ret = false;
|
||||
static bool checked = false;
|
||||
if (!checked) { // check once
|
||||
int dpr = QApplication::desktop()->devicePixelRatio();
|
||||
for (auto screen : QGuiApplication::screens()) {
|
||||
if ((int)screen->devicePixelRatio() != dpr) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
checked = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int getHighestDevicePixelRatio() {
|
||||
static int highestDevPixRatio = 0;
|
||||
if (highestDevPixRatio == 0) {
|
||||
for (auto screen : QGuiApplication::screens())
|
||||
highestDevPixRatio =
|
||||
std::max(highestDevPixRatio, (int)screen->devicePixelRatio());
|
||||
}
|
||||
return highestDevPixRatio;
|
||||
}
|
||||
} // namespace
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
QString fileSizeString(qint64 size, int precision) {
|
||||
|
@ -78,7 +107,7 @@ QPixmap rasterToQPixmap(const TRaster32P &ras, bool premultiplied,
|
|||
bool setDevPixRatio) {
|
||||
QPixmap pixmap = QPixmap::fromImage(rasterToQImage(ras, premultiplied));
|
||||
if (setDevPixRatio) {
|
||||
pixmap.setDevicePixelRatio(getDevPixRatio());
|
||||
pixmap.setDevicePixelRatio(getDevicePixelRatio());
|
||||
}
|
||||
return pixmap;
|
||||
}
|
||||
|
@ -158,7 +187,7 @@ QPixmap scalePixmapKeepingAspectRatio(QPixmap pixmap, QSize size,
|
|||
|
||||
QPixmap svgToPixmap(const QString &svgFilePath, const QSize &size,
|
||||
Qt::AspectRatioMode aspectRatioMode, QColor bgColor) {
|
||||
static int devPixRatio = getDevPixRatio();
|
||||
static int devPixRatio = getHighestDevicePixelRatio();
|
||||
QSvgRenderer svgRenderer(svgFilePath);
|
||||
QSize pixmapSize;
|
||||
QRectF renderRect;
|
||||
|
@ -197,7 +226,16 @@ QPixmap svgToPixmap(const QString &svgFilePath, const QSize &size,
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
int getDevPixRatio() {
|
||||
int getDevicePixelRatio(const QWidget *widget) {
|
||||
if (hasScreensWithDifferentDevPixRatio() && widget) {
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
return widget->screen()->devicePixelRatio();
|
||||
#else
|
||||
if (!widget->windowHandle()) widget->winId();
|
||||
if (widget->windowHandle())
|
||||
return widget->windowHandle()->devicePixelRatio();
|
||||
#endif
|
||||
}
|
||||
static int devPixRatio = QApplication::desktop()->devicePixelRatio();
|
||||
return devPixRatio;
|
||||
}
|
||||
|
@ -224,7 +262,7 @@ QString getIconThemePath(const QString &fileSVGPath) {
|
|||
|
||||
QPixmap compositePixmap(QPixmap pixmap, const qreal &opacity, const QSize &size,
|
||||
const int leftAdj, const int topAdj, QColor bgColor) {
|
||||
static int devPixRatio = getDevPixRatio();
|
||||
static int devPixRatio = getHighestDevicePixelRatio();
|
||||
|
||||
// Sets size of destination pixmap for source to be drawn onto, if size is
|
||||
// empty use source pixmap size, else use custom size.
|
||||
|
@ -269,7 +307,7 @@ QPixmap recolorPixmap(QPixmap pixmap, QColor color) {
|
|||
|
||||
QIcon createQIcon(const char *iconSVGName, bool useFullOpacity,
|
||||
bool isForMenuItem) {
|
||||
static int devPixRatio = getDevPixRatio();
|
||||
static int devPixRatio = getHighestDevicePixelRatio();
|
||||
|
||||
QIcon themeIcon = QIcon::fromTheme(iconSVGName);
|
||||
|
||||
|
|
|
@ -49,16 +49,16 @@ SchematicName::SchematicName(QGraphicsItem *parent, double width, double height)
|
|||
popup = new QMenu();
|
||||
popup->setObjectName(QLatin1String("qt_edit_menu"));
|
||||
|
||||
actionCut = popup->addAction(tr("Cu&t") + ACCEL_KEY(QKeySequence::Cut),
|
||||
this, SLOT(onCut()));
|
||||
actionCut = popup->addAction(tr("Cu&t") + ACCEL_KEY(QKeySequence::Cut), this,
|
||||
SLOT(onCut()));
|
||||
actionCut->setObjectName(QStringLiteral("edit-cut"));
|
||||
|
||||
actionCopy = popup->addAction(tr("&Copy") + ACCEL_KEY(QKeySequence::Copy),
|
||||
this, SLOT(onCopy()));
|
||||
actionCopy->setObjectName(QStringLiteral("edit-copy"));
|
||||
|
||||
actionPaste = popup->addAction(
|
||||
tr("&Paste") + ACCEL_KEY(QKeySequence::Paste), this, SLOT(onPaste()));
|
||||
actionPaste = popup->addAction(tr("&Paste") + ACCEL_KEY(QKeySequence::Paste),
|
||||
this, SLOT(onPaste()));
|
||||
actionPaste->setObjectName(QStringLiteral("edit-paste"));
|
||||
|
||||
actionDelete = popup->addAction(
|
||||
|
@ -321,9 +321,7 @@ void SchematicThumbnailToggle::paint(QPainter *painter,
|
|||
pixmap = offIcon.pixmap(sourceRect.size());
|
||||
else
|
||||
pixmap = onIcon.pixmap(sourceRect.size());
|
||||
sourceRect = QRect(0, 0, sourceRect.width() * getDevPixRatio(),
|
||||
sourceRect.height() * getDevPixRatio());
|
||||
painter->drawPixmap(rect, pixmap, sourceRect);
|
||||
painter->drawPixmap(rect, pixmap);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
@ -441,9 +439,7 @@ void SchematicToggle::paint(QPainter *painter,
|
|||
QRect sourceRect =
|
||||
scene()->views()[0]->matrix().mapRect(QRect(0, 0, 18, 17));
|
||||
QPixmap redPm = pix.pixmap(sourceRect.size());
|
||||
QRect newRect = QRect(0, 0, sourceRect.width() * getDevPixRatio(),
|
||||
sourceRect.height() * getDevPixRatio());
|
||||
painter->drawPixmap(rect, redPm, newRect);
|
||||
painter->drawPixmap(rect, redPm);
|
||||
} else if (!m_imageOff.isNull()) {
|
||||
QPen pen(m_colorOn);
|
||||
pen.setWidthF(0.5);
|
||||
|
@ -454,9 +450,7 @@ void SchematicToggle::paint(QPainter *painter,
|
|||
QRect sourceRect =
|
||||
scene()->views()[0]->matrix().mapRect(QRect(0, 0, 18, 17));
|
||||
QPixmap redPm = m_imageOff.pixmap(sourceRect.size());
|
||||
QRect newRect = QRect(0, 0, sourceRect.width() * getDevPixRatio(),
|
||||
sourceRect.height() * getDevPixRatio());
|
||||
painter->drawPixmap(rect, redPm, newRect);
|
||||
painter->drawPixmap(rect, redPm);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -521,9 +515,7 @@ void SchematicToggle_SplineOptions::paint(
|
|||
(m_state == 2 && !m_imageOn2.isNull()) ? m_imageOn2 : m_imageOn;
|
||||
QRect sourceRect = scene()->views()[0]->matrix().mapRect(rect.toRect());
|
||||
QPixmap redPm = pix.pixmap(sourceRect.size());
|
||||
QRect newRect = QRect(0, 0, sourceRect.width() * getDevPixRatio(),
|
||||
sourceRect.height() * getDevPixRatio());
|
||||
painter->drawPixmap(rect, redPm, newRect);
|
||||
painter->drawPixmap(rect.toRect(), redPm);
|
||||
}
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->setPen(QColor(180, 180, 180, 255));
|
||||
|
|
|
@ -246,7 +246,7 @@ void SchematicSceneViewer::mousePressEvent(QMouseEvent *me) {
|
|||
if (m_cursorMode == CursorMode::Hand || m_panningArmed) {
|
||||
m_mousePanPoint = m_touchDevice == QTouchDevice::TouchScreen
|
||||
? mapToScene(me->pos())
|
||||
: me->pos() * getDevPixRatio();
|
||||
: me->pos() * getDevicePixelRatio(this);
|
||||
m_panning = true;
|
||||
return;
|
||||
} else if (m_cursorMode == CursorMode::Zoom) {
|
||||
|
@ -257,7 +257,7 @@ void SchematicSceneViewer::mousePressEvent(QMouseEvent *me) {
|
|||
} else if (m_buttonState == Qt::MidButton) {
|
||||
m_mousePanPoint = m_touchDevice == QTouchDevice::TouchScreen
|
||||
? mapToScene(me->pos())
|
||||
: me->pos() * getDevPixRatio();
|
||||
: me->pos() * getDevicePixelRatio(this);
|
||||
}
|
||||
bool drawRect = true;
|
||||
QList<QGraphicsItem *> pointedItems = items(me->pos());
|
||||
|
@ -292,12 +292,12 @@ void SchematicSceneViewer::mouseMoveEvent(QMouseEvent *me) {
|
|||
m_buttonState == Qt::MidButton) {
|
||||
QPointF usePos = m_touchDevice == QTouchDevice::TouchScreen
|
||||
? mapToScene(me->pos())
|
||||
: me->pos() * getDevPixRatio();
|
||||
: me->pos() * getDevicePixelRatio(this);
|
||||
QPointF deltaPoint = usePos - m_mousePanPoint;
|
||||
panQt(deltaPoint);
|
||||
m_mousePanPoint = m_touchDevice == QTouchDevice::TouchScreen
|
||||
? mapToScene(me->pos())
|
||||
: me->pos() * getDevPixRatio();
|
||||
: me->pos() * getDevicePixelRatio(this);
|
||||
} else {
|
||||
if (m_cursorMode == CursorMode::Zoom && m_zooming) {
|
||||
int deltaY = (m_oldWinPos.y() - me->pos().y()) * 10;
|
||||
|
@ -605,8 +605,9 @@ void SchematicSceneViewer::gestureEvent(QGestureEvent *e) {
|
|||
}
|
||||
|
||||
if (changeFlags & QPinchGesture::CenterPointChanged) {
|
||||
QPointF centerDelta = (gesture->centerPoint() * getDevPixRatio()) -
|
||||
(gesture->lastCenterPoint() * getDevPixRatio());
|
||||
QPointF centerDelta =
|
||||
(gesture->centerPoint() * getDevicePixelRatio(this)) -
|
||||
(gesture->lastCenterPoint() * getDevicePixelRatio(this));
|
||||
if (centerDelta.manhattanLength() > 1) {
|
||||
// panQt(centerDelta.toPoint());
|
||||
}
|
||||
|
@ -641,14 +642,14 @@ void SchematicSceneViewer::touchEvent(QTouchEvent *e, int type) {
|
|||
}
|
||||
}
|
||||
if (m_panning) {
|
||||
QPointF curPos =
|
||||
m_touchDevice == QTouchDevice::TouchScreen
|
||||
QPointF curPos = m_touchDevice == QTouchDevice::TouchScreen
|
||||
? mapToScene(panPoint.pos().toPoint())
|
||||
: mapToScene(panPoint.pos().toPoint()) * getDevPixRatio();
|
||||
QPointF lastPos =
|
||||
m_touchDevice == QTouchDevice::TouchScreen
|
||||
: mapToScene(panPoint.pos().toPoint()) *
|
||||
getDevicePixelRatio(this);
|
||||
QPointF lastPos = m_touchDevice == QTouchDevice::TouchScreen
|
||||
? mapToScene(panPoint.lastPos().toPoint())
|
||||
: mapToScene(panPoint.lastPos().toPoint()) * getDevPixRatio();
|
||||
: mapToScene(panPoint.lastPos().toPoint()) *
|
||||
getDevicePixelRatio(this);
|
||||
QPointF centerDelta = curPos - lastPos;
|
||||
panQt(centerDelta);
|
||||
}
|
||||
|
|
|
@ -769,9 +769,7 @@ void StageSchematicNodePort::paint(QPainter *painter,
|
|||
else
|
||||
pixmap = QIcon(":Resources/port_red.svg").pixmap(sourceRect.size());
|
||||
}
|
||||
sourceRect = QRect(0, 0, sourceRect.width() * getDevPixRatio(),
|
||||
sourceRect.height() * getDevPixRatio());
|
||||
painter->drawPixmap(imgRect, pixmap, sourceRect);
|
||||
painter->drawPixmap(imgRect, pixmap);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -910,8 +908,8 @@ QRectF StageSchematicSplinePort::boundingRect() const {
|
|||
void StageSchematicSplinePort::paint(QPainter *painter,
|
||||
const QStyleOptionGraphicsItem *option,
|
||||
QWidget *widget) {
|
||||
QRect rect(0, 0, 16, 8);
|
||||
QRect sourceRect = scene()->views()[0]->matrix().mapRect(rect);
|
||||
QRect sourceRect =
|
||||
scene()->views()[0]->matrix().mapRect(boundingRect().toRect());
|
||||
QPixmap pixmap;
|
||||
|
||||
if (!m_parent->isParentPort()) {
|
||||
|
@ -927,9 +925,7 @@ void StageSchematicSplinePort::paint(QPainter *painter,
|
|||
static QIcon splineParentIcon(":Resources/spline_parent_port.svg");
|
||||
pixmap = splineParentIcon.pixmap(sourceRect.size());
|
||||
}
|
||||
sourceRect = QRect(0, 0, sourceRect.width() * getDevPixRatio(),
|
||||
sourceRect.height() * getDevPixRatio());
|
||||
painter->drawPixmap(rect, pixmap, sourceRect);
|
||||
painter->drawPixmap(boundingRect().toRect(), pixmap);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
|
@ -1584,7 +1580,6 @@ StageSchematicPegbarNode::StageSchematicPegbarNode(StageSchematicScene *scene,
|
|||
TStageObject *pegbar)
|
||||
: StageSchematicNode(scene, pegbar, 90, 18, false, false) {
|
||||
SchematicViewer *viewer = scene->getSchematicViewer();
|
||||
|
||||
std::string name = m_stageObject->getFullName();
|
||||
std::string id = m_stageObject->getId().toString();
|
||||
m_name = QString::fromStdString(name);
|
||||
|
@ -2032,7 +2027,6 @@ StageSchematicCameraNode::StageSchematicCameraNode(StageSchematicScene *scene,
|
|||
TStageObject *pegbar)
|
||||
: StageSchematicNode(scene, pegbar, 90, 18, false, false) {
|
||||
SchematicViewer *viewer = scene->getSchematicViewer();
|
||||
|
||||
std::string name = m_stageObject->getFullName();
|
||||
m_name = QString::fromStdString(name);
|
||||
|
||||
|
@ -2114,7 +2108,6 @@ StageSchematicSplineNode::StageSchematicSplineNode(StageSchematicScene *scene,
|
|||
TStageObjectSpline *spline)
|
||||
: SchematicNode(scene), m_spline(spline), m_isOpened(false) {
|
||||
SchematicViewer *viewer = scene->getSchematicViewer();
|
||||
|
||||
m_width = 90;
|
||||
m_height = 18;
|
||||
assert(spline);
|
||||
|
|
Loading…
Reference in a new issue