/* * This file is part of project OpenEmbroidery. It's copyrighted by * the contributors recorded in the version control history of the file. * Original project location https://code.electrolab.fr/openEmbroidery/openEmbroidery_software * * SPDX-License-Identifier: CECILL-2.1 * License-Filename: Licence_CeCILL_V2.1-en.txt */ #include "OE_display.h" #include "OE_utils.h" #include "OE_preferences.h" #include "OE_controller.h" #include #include #include #include #include #include #include #include #include #include #include #include #include OE_display::OE_display(QWidget* parent, Qt::WindowFlags f) : QOpenGLWidget(parent, f), zoom(1.0), pan(false), width(0), height(0) { } OE_display::~OE_display() { } void OE_display::mouseMoveEvent(QMouseEvent* event) { //DEBUG printf("MouseEvent pos %d, %d\n", event->pos().x(), event->pos().y()); fflush(stdout); event->accept(); bool redraw = mouse_Pos(event->pos().x(), event->pos().y()); if (redraw) update(); //TODO ? repaint(); } void OE_display::mousePressEvent(QMouseEvent* event) { event->accept(); bool redraw = mouse_Button(event); if (redraw) update(); } void OE_display::mouseReleaseEvent(QMouseEvent* event) { event->accept(); bool redraw = mouse_Button(event); if (redraw) update(); } void OE_display::wheelEvent(QWheelEvent* event) { event->accept(); OE_display::scroll(0, event->delta()); update(); } static bool endsWith(const std::string& str, const std::string& suffix) { return str.size() >= suffix.size() && 0 == str.compare(str.size()-suffix.size(), suffix.size(), suffix); } static std::vector getAllowedFiles(QDropEvent *event) { std::vector uris; if (event->mimeData()->hasFormat("text/uri-list")) { for (const QUrl& qurl : event->mimeData()->urls()) { if (!qurl.isLocalFile()) continue; std::string url = qurl.toLocalFile().toStdString(); std::string urlLower = url; std::transform(urlLower.begin(), urlLower.end(), urlLower.begin(), ::tolower); if (!(endsWith(urlLower, ".oe") || endsWith(urlLower, ".svg") || endsWith(urlLower, ".pes"))) continue; uris.push_back(url); } } return uris; } void OE_display::dragEnterEvent(QDragEnterEvent *event) { std::vector files = getAllowedFiles(event); if (files.size() != 1) { event->ignore(); return; } event->setDropAction(Qt::MoveAction); event->accept(); } void OE_display::dropEvent(QDropEvent *event) { event->acceptProposedAction(); loadFile(getAllowedFiles(event).front()); } void OE_display::loadFile(std::string file) { std::string fileLower = file; std::transform(fileLower.begin(), fileLower.end(), fileLower.begin(), ::tolower); OE_document* newDoc = nullptr; printf("Importing file from %s\n", file.c_str()); newDoc = new OE_document(); if (!newDoc->loadFromFile(file)) { delete newDoc; newDoc = nullptr; } if (newDoc) { OE_document* oldDoc = document; document = newDoc; if (oldDoc) delete oldDoc; if (controller) { controller->setDocument(newDoc); controller->initNewDocument(); } setDocument(newDoc); showAll(); QTabWidget* tabWidget = dynamic_cast(this->parent()->parent()->parent()); int idx = tabWidget->indexOf(dynamic_cast(this->parent())); tabWidget->setTabText(idx, QString::fromStdString(file.substr(file.rfind('/')+1))); tabWidget->setTabToolTip(idx, QString::fromStdString(file)); } } void OE_display::initializeGL() { initializeOpenGLFunctions(); glEnable(GL_POINT_SMOOTH); glEnable(GL_LINE_SMOOTH); } void OE_display::resizeGL(int w, int h) { resize(w, h); update(); } void OE_display::paintGL() { draw(); } /** \brief draw the document on screen * * \return true if all is ok * */ bool OE_display::setDocument(OE_document* document) { this->document = document; /* if (document) { std::list::iterator curve = document->curves.begin(); while (curve != document->curves.end()) { (*curve)->refresh(zoom/2); curve++; } }*/ refreshAll(); return true; } bool OE_display::setController(OE_controller* controller) { this->controller = controller; return true; } bool OE_display::setDisplayStyle(OE_displayStyle* style) { this->style = style; return true; } bool OE_display::refreshAll() { if (document) { std::list::iterator curve = document->curves.begin(); while (curve != document->curves.end()) { (*curve)->refresh(zoom/2, !changeDpi); curve++; } std::list::iterator stitch = document->stitchs.begin(); while (stitch != document->stitchs.end()) { (*stitch)->refresh(zoom/2, !changeDpi); stitch++; } if (controller) controller->generateInstructions(); changeDpi = false; return true; } return false; } /** \brief draw the move gizmo * * \return true if all is ok * */ bool OE_display::drawSelectionTools(bool select) { vector_2d min = selectionBounds.getMin(); vector_2d max = selectionBounds.getMax(); float crossSize = zoom*OE_preferences::moveCrossSize; float boxOffset = zoom*OE_preferences::moveCrossSize; min.x -= boxOffset; min.y -= boxOffset; max.x += boxOffset; max.y += boxOffset; if (selectionBounds.init) { if (select) { glTranslatef(min.x, min.y, 0); glPushName(MOVETOOLID); //id of the move tool glBegin(GL_QUADS); glColor4fv(OE_preferences::selectionBoundColor.rgba); //glColor4d(1, 0, 0, 1); glVertex2f(crossSize*1.0f, 0); glVertex2f(0, crossSize*1.0f); glVertex2f(-crossSize*1.0f, 0); glVertex2f(0, -crossSize*1.0f); glEnd(); glPopName(); glPushName(SCALETOOLID); //id of the scale tool glBegin(GL_QUADS); glVertex2f(-crossSize*0.5f, -crossSize*0.5f); glVertex2f(-crossSize*0.5f, -crossSize*1.5f); glVertex2f(-crossSize*1.5f, -crossSize*1.5f); glVertex2f(-crossSize*1.5f, -crossSize*0.5f); glEnd(); glPopName(); glTranslatef(-min.x, -min.y, 0); } else { //draw selection bound glLineWidth(1.5); glBegin(GL_LINE_LOOP); glColor4fv(OE_preferences::selectionBoundColor.rgba); glVertex2f(min.x, min.y); glVertex2f(min.x, max.y); glVertex2f(max.x, max.y); glVertex2f(max.x, min.y); glEnd(); glTranslatef(min.x, min.y, 0); //draw move cross glBegin(GL_TRIANGLES); glColor4fv(OE_preferences::transformGizmoColor.rgba); glVertex2f(-crossSize*0.6f, -crossSize*0.1f); glVertex2f(-crossSize*0.6f, crossSize*0.1f); glVertex2f(crossSize*0.6f, crossSize*0.1f); glVertex2f(crossSize*0.6f, crossSize*0.1f); glVertex2f(-crossSize*0.6f, -crossSize*0.1f); glVertex2f(crossSize*0.6f, -crossSize*0.1f); glVertex2f(crossSize*0.6f, crossSize*0.3f); glVertex2f(crossSize*1.0f, 0); glVertex2f(crossSize*0.6f, -crossSize*0.3f); glVertex2f(-crossSize*0.6f, crossSize*0.3f); glVertex2f(-crossSize*1.0f, 0); glVertex2f(-crossSize*0.6f, -crossSize*0.3f); glVertex2f(-crossSize*0.1f, -crossSize*0.6f); glVertex2f(crossSize*0.1f, -crossSize*0.6f); glVertex2f(crossSize*0.1f, crossSize*0.6f); glVertex2f(crossSize*0.1f, crossSize*0.6f); glVertex2f(-crossSize*0.1f, -crossSize*0.6f); glVertex2f(-crossSize*0.1f, crossSize*0.6f); glVertex2f(crossSize*0.3f, crossSize*0.6f); glVertex2f(0, crossSize*1.0f); glVertex2f(-crossSize*0.3f, crossSize*0.6f); glVertex2f(crossSize*0.3f, -crossSize*0.6f); glVertex2f(0, -crossSize*1.0f); glVertex2f(-crossSize*0.3f, -crossSize*0.6f); glEnd(); //draw scale icon glBegin(GL_TRIANGLES); glColor4fv(OE_preferences::transformGizmoColor.rgba); glVertex2f(-crossSize*1.5f, -crossSize*1.2f); glVertex2f(-crossSize*0.6f, -crossSize*0.55f); glVertex2f(-crossSize*0.55f, -crossSize*0.6f); glVertex2f(-crossSize*1.5f, -crossSize*1.2f); glVertex2f(-crossSize*0.5f, -crossSize*0.55f); glVertex2f(-crossSize*1.2f, -crossSize*1.5f); glVertex2f(-crossSize*0.5f, -crossSize*0.5f); glVertex2f(-crossSize*0.85f, -crossSize*0.5f); glVertex2f(-crossSize*0.5f, -crossSize*0.85f); glVertex2f(-crossSize*1.5f, -crossSize*1.5f); glVertex2f(-crossSize*1.5f, -crossSize*0.9f); glVertex2f(-crossSize*0.9f, -crossSize*1.5f); glEnd(); glTranslatef(-min.x, -min.y, 0); } return true; } return false; } /** \brief draw a triangle */ void OE_display::drawTriangle(vector_2d point1, vector_2d point2, float size) { glBegin(GL_TRIANGLE_FAN); vector_2d dir = point2 - point1; dir.normalize(); dir = dir*zoom*size; vector_2d lat = dir; lat.turnRight(); point1 = point1 - dir; vector_2d p1 = dir*2+point1; glVertex2f(p1.x, p1.y); p1 = point1+lat; glVertex2f(p1.x, p1.y); p1 = point1+dir/2; glVertex2f(p1.x, p1.y); p1 = point1-lat; glVertex2f(p1.x, p1.y); glEnd(); } /** \brief draw a stitch on screen * * \return true if all is ok * */ bool OE_display::drawStitch(OE_stitchs* stitch, int curpoint) { //stitch->refresh(zoom/2); if (!stitch->check() || !style->drawStitches || stitch->getNpts()==0) { return false; } const std::vector& points = stitch->getPoints(); unsigned i; // Points if (stitch == higligtedStitch) glPointSize(OE_preferences::stitchPointSize*2); else glPointSize(OE_preferences::stitchPointSize); glBegin(GL_POINTS); if (curpoint>0) { glColor4fv(OE_preferences::stitchPointBeforeCurrentColor.rgba); } else { glColor4fv(OE_preferences::stitchPointAfterCurrentColor.rgba); } for (i = 1; i < points.size(); i++) { if (curpoint==i) { glColor4fv(OE_preferences::stitchPointAfterCurrentColor.rgba); } glVertex2f(points[i].x, points[i].y); } glEnd(); //draw lines if (stitch == higligtedStitch) glLineWidth(OE_preferences::stitchLineWidth*2); else glLineWidth(OE_preferences::stitchLineWidth); glBegin(GL_LINE_STRIP); OE_thread* thread = stitch->getThread(); if (thread) { glColor4fv(thread->getColor().rgba); } else { glColor4fv(OE_preferences::stitchLineBeforeCurrentColor.rgba); } for (i = 0; i < points.size(); i++) { glVertex2f(points.at(i).x, points.at(i).y); } glEnd(); // start point glColor4fv(OE_preferences::stitchStartPointColor.rgba); glPointSize(OE_preferences::stitchStartPointSize); glBegin(GL_POINTS); glVertex2f(points.at(0).x, points.at(0).y); glEnd(); return true; } /** \brief draw a curve on screen * * \return true if all is ok * */ bool OE_display::drawCurve(OE_curve* curve) { if (!curve->check() || !style->drawCurves) { return false; } if (curve->getNeedRefresh()) { curve->refresh(zoom/2); } unsigned i; //draw curves glLineWidth(OE_preferences::curveWidth); glBegin(GL_LINE_STRIP); glColor4fv(OE_preferences::curveColor.rgba); for (i = 0; i < curve->discPts.size(); i++) { glVertex2f(curve->discPts.at(i).v.x, curve->discPts.at(i).v.y); } if (curve->getClosed()) { glVertex2f(curve->discPts.at(0).v.x, curve->discPts.at(0).v.y); } glEnd(); if (!curve->getClosed()) { glPointSize(OE_preferences::curveStartPointSize); glBegin(GL_POINTS); glVertex2f(curve->discPts.at(0).v.x, curve->discPts.at(0).v.y); glVertex2f(curve->discPts.at(curve->discPts.size()-1).v.x, curve->discPts.at(curve->discPts.size()-1).v.y); glEnd(); } /* glPointSize(5.0f); glColor3d(1.0f, 0.0f, 0.0f); glBegin(GL_POINTS); vector_2dt point = curve->closestPoint(vector_2d (absMouseX, absMouseY)); glVertex2f(point.v.x, point.v.y); glEnd(); */ //draw curve points if (style->drawCurvePoints) { glPointSize(OE_preferences::curvePointSize); glBegin(GL_POINTS); glVertex2f(curve->discPts[0].v.x, curve->discPts[0].v.y); for (i = 0; i < curve->discPts.size(); i++) { glColor3d(curve->discPts.at(i).t/((double)curve->pts.size()/3.0f), 0.0f, 0.0f); glVertex2f(curve->discPts.at(i).v.x, curve->discPts.at(i).v.y); } if (curve->getClosed()) { glVertex2f(curve->discPts[0].v.x, curve->discPts[0].v.y); } glEnd(); } return true; } /** \brief draw the curve controls on screen * * \return true if all is ok * */ bool OE_display::drawCurveControl(OE_curve* curve, bool select) { if (!curve->check() || !style->drawCurves || !style->drawCurveControls) { return false; } OE_pointcurve* tmpcurve = dynamic_cast (curve); if (tmpcurve) { if (select) { // Points glPointSize(4.0f); glPushName(0); //init the controller type index glPushName(0); //init the controller points index for (unsigned i = 0; i < tmpcurve->pts.size(); i++) { glLoadName(i); //vector_2d* p = &tmpcurve->pts[i]; glBegin(GL_POINTS); glVertex2f(tmpcurve->pts[i].x, tmpcurve->pts[i].y); glEnd(); } glPopName(); glPopName(); } else { // Tangeant lines glLineWidth(1.5); glColor4fv(OE_preferences::curveTangeantColor.rgba); glBegin(GL_LINES); for (unsigned i = 0; i < tmpcurve->pts.size()-3; i += 3) { vector_2d* p = &tmpcurve->pts[i]; glVertex2f(p[0].x, p[0].y); glVertex2f(p[1].x, p[1].y); glVertex2f(p[2].x, p[2].y); glVertex2f(p[3].x, p[3].y); } glEnd(); // Points glPointSize(OE_preferences::curvePointSize); //glColor4ubv(controlEndPointColor); glBegin(GL_POINTS); glColor4fv(OE_preferences::curvePointColor.rgba); for (unsigned i = 0; i < tmpcurve->pts.size()-3; i += 3) { vector_2d* p = &tmpcurve->pts[i]; glVertex2f(p[0].x, p[0].y); } glEnd(); // tangeant end points glPointSize(OE_preferences::curvePointSize); glColor4fv(OE_preferences::curvePointColor.rgba); glBegin(GL_POINTS); for (unsigned i = 0; i < curve->pts.size()-3; i += 3) { vector_2d* p = &curve->pts[i]; glVertex2f(p[1].x, p[1].y); glVertex2f(p[2].x, p[2].y); } glEnd(); // start point & direction /*glColor4f(1.0, 0.0, 0.0, 1.0); glPointSize(2.0f); glBegin(GL_POINTS); glVertex2f(curve->pts[0].x, curve->pts[0].y); glEnd();*/ glColor4fv(OE_preferences::curveControlsColor.rgba); drawTriangle(curve->pts[0], curve->pts[1], 13); glLineWidth(2); glBegin(GL_LINES); vector_2d p = curve->pts[1] - curve->pts[0]; p.normalize(); p = p+curve->pts[0]; glVertex2f(curve->pts[0].x, curve->pts[0].y); //glVertex2f(curve->pts[1].x, curve->pts[1].y); glVertex2f(p.x, p.y); glEnd(); } return true; } /* //if this curve is a joincurve OE_joincurve* joincurve = dynamic_cast (curve); if (joincurve) { std::list::iterator curve = joincurve->curves.begin(); if (!select) { while (curve != joincurve->curves.end()) { OE_curve* tmpcurve = (*curve); glLineWidth(3); glBegin(GL_LINE_STRIP); style->curveTangeantColor.gl(); for (unsigned i = 0; i < tmpcurve->discPts.size(); i++) { glVertex2f(tmpcurve->discPts.at(i).v.x, tmpcurve->discPts.at(i).v.y); } glEnd(); if (tmpcurve->discPts.size()>1) { style->curveControlsColor.gl(); drawTriangle(tmpcurve->pts[0], tmpcurve->pts[1], 13); } //draw the add subcurve controler if (tmpcurve->discPts.size()>1) { style->curveControlsColor.gl(); drawTriangle(tmpcurve->pts[tmpcurve->getNpts()-1]+vector_2d(10,10), tmpcurve->pts[tmpcurve->getNpts()-2]+vector_2d(10,10), 13); } curve++; } } return true; } //if this curve is a subcurve OE_subcurve* subcurve = dynamic_cast (curve); if (subcurve) { if (select) { // Points glPointSize(4.0f); glPushName(0); //init the controller type index glPushName(0); //init the controller points index glBegin(GL_POINTS); glVertex2f(subcurve->pts[0].x, subcurve->pts[0].y); glEnd(); glLoadName(1); glBegin(GL_POINTS); glVertex2f(subcurve->pts[subcurve->getNpts()-1].x, subcurve->pts[subcurve->getNpts()-1].y); glEnd(); glPopName(); glPopName(); } else { style->curvePointColor.gl(); glPointSize(5.0f); glBegin(GL_POINTS); glVertex2f(subcurve->pts[0].x, subcurve->pts[0].y); glVertex2f(subcurve->pts[subcurve->getNpts()-1].x, subcurve->pts[subcurve->getNpts()-1].y); glEnd(); // start point & direction style->curveControlsColor.gl(); drawTriangle(subcurve->pts[0], subcurve->pts[1], 13); } return true; }*/ return false; } void OE_display::drawJoincurveControl(OE_joincurve* curve, bool select, int index) { const float uiSize = zoom * 10; const float uiDistance = zoom * 17; if (select) { glLoadName(index);//set the controller type index glPushName(0); //init the controller points index for (unsigned i = 0; i < curve->curves.size(); i++) { OE_subcurve* subcurve = curve->getCurve(i); glLoadName(i*2+1); glBegin(GL_POINTS); glVertex2f(subcurve->pts[0].x, subcurve->pts[0].y); glEnd(); glLoadName(i*2); glBegin(GL_POINTS); glVertex2f(subcurve->pts[subcurve->getNpts()-1].x, subcurve->pts[subcurve->getNpts()-1].y); glEnd(); } glPopName(); glLoadName(index + 1);//set the controller type index glPushName(0); //init the controller points index // draw the insert subcurve control picking zone OE_subcurve* subcurve = curve->getCurve(0); glPointSize(2*uiSize); glLoadName(0); glBegin(GL_POINTS); glVertex2f(subcurve->pts[0].x+uiDistance, subcurve->pts[0].y-uiDistance); glEnd(); for (unsigned i = 0; i < curve->curves.size(); i++) { subcurve = curve->getCurve(i); glLoadName(i+1); glBegin(GL_POINTS); glVertex2f(subcurve->pts[subcurve->getNpts()-1].x+uiDistance, subcurve->pts[subcurve->getNpts()-1].y-uiDistance); glEnd(); } glPopName(); } else { for (unsigned i = 0; i < curve->curves.size(); i++) { OE_subcurve* subcurve = curve->getCurve(i); // draw the subcurves glLineWidth(2); glBegin(GL_LINE_STRIP); glColor4fv(OE_preferences::curveTangeantColor.rgba); for (unsigned i = 0; i < subcurve->discPts.size(); i++) { glVertex2f(subcurve->discPts.at(i).v.x, subcurve->discPts.at(i).v.y); } glEnd(); // draw the insert subcurve control glColor4fv(OE_preferences::curveControlsColor.rgba); if (i == 0) { glBegin(GL_LINES); glVertex2f(subcurve->pts[0].x-uiSize+uiDistance, subcurve->pts[0].y-uiDistance); glVertex2f(subcurve->pts[0].x+uiSize+uiDistance, subcurve->pts[0].y-uiDistance); glVertex2f(subcurve->pts[0].x+uiDistance, subcurve->pts[0].y-uiSize-uiDistance); glVertex2f(subcurve->pts[0].x+uiDistance, subcurve->pts[0].y+uiSize-uiDistance); glEnd(); } glBegin(GL_LINES); glVertex2f(subcurve->pts[subcurve->getNpts()-1].x-uiSize+uiDistance, subcurve->pts[subcurve->getNpts()-1].y-uiDistance); glVertex2f(subcurve->pts[subcurve->getNpts()-1].x+uiSize+uiDistance, subcurve->pts[subcurve->getNpts()-1].y-uiDistance); glVertex2f(subcurve->pts[subcurve->getNpts()-1].x+uiDistance, subcurve->pts[subcurve->getNpts()-1].y-uiSize-uiDistance); glVertex2f(subcurve->pts[subcurve->getNpts()-1].x+uiDistance, subcurve->pts[subcurve->getNpts()-1].y+uiSize-uiDistance); glEnd(); // draw the subcurves controls glColor4fv(OE_preferences::curveControlsColor.rgba); glPointSize(6.0f); glBegin(GL_POINTS); glVertex2f(subcurve->pts[0].x, subcurve->pts[0].y); glVertex2f(subcurve->pts[subcurve->getNpts()-1].x, subcurve->pts[subcurve->getNpts()-1].y); glEnd(); // start point & direction glColor4fv(OE_preferences::curveControlsColor.rgba); drawTriangle(subcurve->pts[0], subcurve->pts[1], 13); } } } void OE_display::drawFillstitchControl(OE_fillstitch* fillstitch, bool select) { std::vector grid = fillstitch->getGridControl(); std::vector curves = fillstitch->getCurveControl(); if (select) { for (unsigned i = 0; i < grid.size(); i++) { glLoadName(i); glBegin(GL_POINTS); glVertex2f(grid[i].x, grid[i].y); glEnd(); } } else { glColor4fv(OE_preferences::curveControlsColor.rgba); for (unsigned i = 0; i < curves.size(); i++) { drawCurve(&curves[i]); } glColor4fv(OE_preferences::curveControlsColor.rgba); for (unsigned i = 0; i < grid.size(); i++) { glBegin(GL_POINTS); glVertex2f(grid[i].x, grid[i].y); glEnd(); } /* for (unsigned i = 0; i < curve->curves.size(); i++) { OE_subcurve* subcurve = curve->getCurve(i); // draw the subcurves glLineWidth(2); glBegin(GL_LINE_STRIP); style->curveTangeantColor.gl(); for (unsigned i = 0; i < subcurve->discPts.size(); i++) { glVertex2f(subcurve->discPts.at(i).v.x, subcurve->discPts.at(i).v.y); } glEnd(); // draw the subcurves controls style->curveControlsColor.gl(); glPointSize(6.0f); glBegin(GL_POINTS); glVertex2f(subcurve->pts[0].x, subcurve->pts[0].y); glVertex2f(subcurve->pts[subcurve->getNpts()-1].x, subcurve->pts[subcurve->getNpts()-1].y); glEnd(); // start point & direction style->curveControlsColor.gl(); drawTriangle(subcurve->pts[0], subcurve->pts[1], 13); }*/ } } /** \brief draw the stitchs controls on screen * * \return true if all is ok * */ bool OE_display::drawStitchControl(OE_stitchs* stitch, bool select) { if (!stitch->check() || !style->drawStitches || !style->drawStitchControl) { return false; } OE_linestitch* linestitch = dynamic_cast (stitch); if (linestitch) { OE_joincurve* joinCurve = linestitch->getJoincurve(); vector_2d dir = joinCurve->pts[1] - joinCurve->pts[0]; dir.normalize(); dir.turnRight(); vector_2d scaleDir = dir*zoom*10; dir = scaleDir * 10+ joinCurve->pts[0]; if (select) { // Points glPointSize(4.0f); glPushName(0); //init the controller type index if (linestitch->getJoincurve()) { drawJoincurveControl(linestitch->getJoincurve(), true, 0); } glLoadName(2); //set the controller type index glPushName(0); //init the controller points index //draw stitch width controller glBegin(GL_TRIANGLES); glVertex2f(dir.x-scaleDir.y+scaleDir.x/3, dir.y+scaleDir.x+scaleDir.y/3); glVertex2f(dir.x+scaleDir.x*2, dir.y+scaleDir.y*2); glVertex2f(dir.x+scaleDir.y+scaleDir.x/3, dir.y-scaleDir.x+scaleDir.y/3); glVertex2f(dir.x+scaleDir.y-scaleDir.x/3, dir.y-scaleDir.x-scaleDir.y/3); glVertex2f(dir.x-scaleDir.x*2, dir.y-scaleDir.y*2); glVertex2f(dir.x-scaleDir.y-scaleDir.x/3, dir.y+scaleDir.x-scaleDir.y/3); glEnd(); glPopName(); glPopName(); } else { glLineWidth(2); glBegin(GL_LINE_STRIP); glColor4fv(OE_preferences::stitchLineBeforeCurrentColor.rgba); glVertex2f(joinCurve->pts[0].x, joinCurve->pts[0].y); glVertex2f(dir.x, dir.y); glEnd(); drawJoincurveControl(joinCurve, false); //draw stitch width controller glBegin(GL_TRIANGLES); glColor4fv(OE_preferences::stitchControlsColor.rgba); glVertex2f(dir.x-scaleDir.y+scaleDir.x/3, dir.y+scaleDir.x+scaleDir.y/3); glVertex2f(dir.x+scaleDir.x*2, dir.y+scaleDir.y*2); glVertex2f(dir.x+scaleDir.y+scaleDir.x/3, dir.y-scaleDir.x+scaleDir.y/3); glVertex2f(dir.x+scaleDir.y-scaleDir.x/3, dir.y-scaleDir.x-scaleDir.y/3); glVertex2f(dir.x-scaleDir.x*2, dir.y-scaleDir.y*2); glVertex2f(dir.x-scaleDir.y-scaleDir.x/3, dir.y+scaleDir.x-scaleDir.y/3); glEnd(); } return true; } OE_birailstitch* birailstitch = dynamic_cast (stitch); if (birailstitch) { if (select) { // Points glPointSize(4.0f); glPushName(0); //init the controller type index drawJoincurveControl(birailstitch->getJoincurve1(), true, 0); drawJoincurveControl(birailstitch->getJoincurve2(), true, 2); glPopName(); } else { drawJoincurveControl(birailstitch->getJoincurve1(), false); drawJoincurveControl(birailstitch->getJoincurve2(), false); } return true; } OE_fillstitch* fillstitch = dynamic_cast (stitch); if (fillstitch) { if (select) { // Points glPointSize(4.0f); glPushName(0); //init the controller type index drawJoincurveControl(fillstitch->getJoincurve(), true, 0); glLoadName(2); glPushName(0); drawFillstitchControl(fillstitch, true); glPopName(); glPopName(); } else { drawJoincurveControl(fillstitch->getJoincurve(), false); drawFillstitchControl(fillstitch, false); } return true; } OE_linkstitch* linkstitch = dynamic_cast (stitch); if (linkstitch) { const float uiSize = zoom * 7; const float uiDistance = zoom * 17; if (select) { glPushName(0); //init the controller type index as points glPushName(0); //init the controller points index glPointSize(4.0f); int index = 0; for (auto stepPt : linkstitch->stepPts) { glBegin(GL_POINTS); glVertex2f(stepPt.x, stepPt.y); glEnd(); glLoadName(++index); } glPopName(); glLoadName(1); //init the controller type index as add glPushName(0); //init the controller points index glPointSize(4.0f); const std::vector& points = linkstitch->getPoints(); vector_2d prevVert = points.at(0); vector_2d p; index = 0; std::list::iterator stepPt = linkstitch->stepPts.begin(); while (stepPt != linkstitch->stepPts.end()) { p = (*stepPt + prevVert)/2; glBegin(GL_POINTS); glVertex2f(p.x, p.y); glEnd(); prevVert = *stepPt; stepPt++; glLoadName(++index); } glLoadName(index); p = (points.at(points.size()-1) + prevVert)/2; glBegin(GL_POINTS); glVertex2f(p.x, p.y); glEnd(); glPopName(); glLoadName(2); //init the controller type index as delete glPushName(0); //init the controller points index index = 0; for (auto stepPt : linkstitch->stepPts) { glBegin(GL_LINES); glVertex2f(stepPt.x-uiSize+uiDistance, stepPt.y-uiDistance); glVertex2f(stepPt.x+uiSize+uiDistance, stepPt.y-uiDistance); glEnd(); glLoadName(++index); } glPopName(); glPopName(); } else { glLineWidth(2.5); glPointSize(5.0f); glColor4fv(OE_preferences::stitchStartPointColor.rgba); for (auto stepPt : linkstitch->stepPts) { glColor4fv(OE_preferences::stitchControlsColor.rgba); glBegin(GL_POINTS); glVertex2f(stepPt.x, stepPt.y); glEnd(); //OE_preferences::stitchStartPointColor.gl(); glBegin(GL_LINES); glVertex2f(stepPt.x-uiSize+uiDistance, stepPt.y-uiDistance); glVertex2f(stepPt.x+uiSize+uiDistance, stepPt.y-uiDistance); glEnd(); } glColor4fv(OE_preferences::stitchStartPointColor.rgba); glBegin(GL_LINES); const std::vector& points = linkstitch->getPoints(); vector_2d prevVert = points.at(0); vector_2d p; std::list::iterator stepPt = linkstitch->stepPts.begin(); glColor4fv(OE_preferences::stitchControlsColor.rgba); while (stepPt != linkstitch->stepPts.end()) { p = (*stepPt + prevVert)/2; glVertex2f(p.x-uiSize, p.y); glVertex2f(p.x+uiSize, p.y); glVertex2f(p.x, p.y+uiSize); glVertex2f(p.x, p.y-uiSize); prevVert = *stepPt; stepPt++; } p = (points.at(points.size()-1) + prevVert)/2; glVertex2f(p.x-uiSize, p.y); glVertex2f(p.x+uiSize, p.y); glVertex2f(p.x, p.y+uiSize); glVertex2f(p.x, p.y-uiSize); glEnd(); } return true; } return false; } /** \brief draw the instruction points * * \return true if all is ok * */ bool OE_display::drawCommands() { float scaleRatio = document->getPulsePerMm(); if (document->instPoints.size() == 0) { return false; } unsigned i; // Points glPointSize(OE_preferences::instPointSize); glBegin(GL_POINTS); glColor4fv(OE_preferences::instLineBeforeCurrentColor.rgba); for (i = 1; i < document->curPoint; i++) { glVertex2f(document->instPoints.at(i).x/scaleRatio, document->instPoints.at(i).y/scaleRatio); } glColor4fv(OE_preferences::instLineAfterCurrentColor.rgba); for (i = document->curPoint; i < document->instPoints.size(); i++) { glVertex2f(document->instPoints.at(i).x/scaleRatio, document->instPoints.at(i).y/scaleRatio); } glEnd(); //draw lines unsigned pt = 0; OE_color curcolor; glLineWidth(OE_preferences::instLineWidth); glBegin(GL_LINE_STRIP); for (i = 0; i < document->instCommand.size(); i++) { for (; pt < document->instCommand.at(i)->getIdPoint(); pt++) { if (pt == document->curPoint) { glColor4fv((curcolor*OE_color(1, 1, 1, OE_preferences::instLineBeforeCurrentColor.rgba[3])).rgba); } glVertex2f(document->instPoints.at(pt).x/scaleRatio, document->instPoints.at(pt).y/scaleRatio); } OE_waitcolor* color = dynamic_cast (document->instCommand.at(i)); if (color) { curcolor = color->getThreadColor(); if (pt > document->curPoint) { glColor4fv(curcolor.rgba); } else { glColor4fv((curcolor*OE_color(1, 1, 1, OE_preferences::instLineBeforeCurrentColor.rgba[3])).rgba); } } OE_start* start = dynamic_cast (document->instCommand.at(i)); if (start) { curcolor = start->getThreadColor(); glColor4fv((curcolor*OE_color(1, 1, 1, OE_preferences::instLineBeforeCurrentColor.rgba[3])).rgba); } } for (; pt < document->instPoints.size(); pt++) { if (pt == document->curPoint) { glColor4fv((curcolor*OE_color(1, 1, 1, OE_preferences::instLineBeforeCurrentColor.rgba[3])).rgba); } glVertex2f(document->instPoints.at(pt).x/scaleRatio, document->instPoints.at(pt).y/scaleRatio); } glEnd(); // start point glColor4fv(OE_preferences::instStartPointColor.rgba); glPointSize(OE_preferences::instStartPointSize); glBegin(GL_POINTS); glVertex2f(document->instPoints.at(0).x/scaleRatio, document->instPoints.at(0).y/scaleRatio); glEnd(); // current point if (document->curPoint < document->instPoints.size()) { glColor4fv(OE_preferences::instCurPointColor.rgba); glPointSize(OE_preferences::instCurPointSize); glBegin(GL_POINTS); glVertex2f(document->instPoints.at(document->curPoint).x/scaleRatio, document->instPoints.at(document->curPoint).y/scaleRatio); glEnd(); } return true; } /** \brief draw the document on screen * * \return true if all is ok * */ bool OE_display::draw() { if (!document) { return false; } float wzoom, hzoom; glViewport(0, 0, width, height); glClearColor(OE_preferences::backgroundColor.rgba[0], OE_preferences::backgroundColor.rgba[1], OE_preferences::backgroundColor.rgba[2], 1.0f); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_TEXTURE_2D); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glEnd(); wzoom = (float)width*zoom; hzoom = (float)height*zoom; glOrtho(viewPos.x-wzoom, viewPos.x+wzoom, viewPos.y+hzoom, viewPos.y-hzoom, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glDisable(GL_DEPTH_TEST); glColor4ub(255,255,255,255); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); vector_2d hoopSize = document->getHoopSize()/2; vector_2d zero = document->getZeroPoint(); //draw hoop if (style->drawHoop) { glLineWidth(3); glBegin(GL_LINE_STRIP); glColor4fv(OE_preferences::hoopColor.rgba); glVertex2f(zero.x-hoopSize.x, zero.y-hoopSize.y); glVertex2f(zero.x-hoopSize.x, zero.y+hoopSize.y); glVertex2f(zero.x+hoopSize.x, zero.y+hoopSize.y); glVertex2f(zero.x+hoopSize.x, zero.y-hoopSize.y); glVertex2f(zero.x-hoopSize.x, zero.y-hoopSize.y); glEnd(); } //draw grid if (style->drawGrid) { glLineWidth(1.5); glBegin(GL_LINES); glColor4fv((OE_preferences::gridColor * OE_color(1, 1, 1, std::max(0.0f, 0.2f-zoom*2))).rgba); int offset = (int)-hoopSize.x; while (offsetdrawZero) { float zeroSize = OE_preferences::zeroSize; glLineWidth(1.5); glBegin(GL_LINE_STRIP); glColor4fv(OE_preferences::zeroColor.rgba); glVertex2f(zero.x-zeroSize, zero.y); glVertex2f(zero.x, zero.y+zeroSize); glVertex2f(zero.x+zeroSize, zero.y); glVertex2f(zero.x, zero.y-zeroSize); glVertex2f(zero.x-zeroSize, zero.y); glEnd(); glBegin(GL_LINES); glColor4fv(OE_preferences::zeroColor.rgba); glVertex2f(zero.x-zeroSize, zero.y); glVertex2f(zero.x+zeroSize, zero.y); glVertex2f(zero.x, zero.y-zeroSize); glVertex2f(zero.x, zero.y+zeroSize); glEnd(); } refreshAll(); document->lock(); /*if (changeDpi) { refreshAll(); }*/ selectionBounds.init = false; if (style->drawCurves) { std::list::iterator curve = document->curves.begin(); while (curve != document->curves.end()) { drawCurve(*curve); curve++; } curve = document->selectedCurves.begin(); while (curve != document->selectedCurves.end()) { drawCurveControl(*curve); selectionBounds += (*curve)->getBound(); curve++; } } if (style->drawStitches) { std::list::iterator stitch = document->stitchs.begin(); int curpoint = document->curPoint; while (stitch != document->stitchs.end()) { drawStitch(*stitch, curpoint); curpoint -= (*stitch)->getNpts(); stitch++; } stitch = document->selectedStitchs.begin(); while (stitch != document->selectedStitchs.end()) { drawStitchControl(*stitch); selectionBounds += (*stitch)->getBound(); stitch++; } if(higligtedStitch) drawStitch(higligtedStitch, 0); } if (style->drawCommands) { drawCommands(); } document->unlock(); drawSelectionTools(); return true; } void OE_display::pick(std::list selectedCurves, std::list selectedStitches) { std::list::iterator curve; std::list::iterator stitch; int index; glViewport(0, 0, width, height); glClearColor(0.85f, 0.85f, 0.85f, 1.0f); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_TEXTURE_2D); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glEnd(); glOrtho(absMouse.x-7*zoom, absMouse.x+7*zoom, absMouse.y+7*zoom, absMouse.y-7*zoom, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glDisable(GL_DEPTH_TEST); glColor4ub(255,255,255,255); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glRenderMode(GL_SELECT); //Init of name stack glInitNames(); glPushName(TOOLSSELID); //id of the tools /* glPushName(ZEROID); //id of the zero tool //draw 0 vector_2d zero = document->getZeroPoint(); glPointSize(6); glBegin(GL_POINT); glVertex2f(zero.x, zero.y); glEnd(); glPopName(); */ glPushName(TRANSTOOLID); //id of the move tool drawSelectionTools(true); glPopName(); //if (changeDpi) refreshAll(); // if sitches are selectables draw their controls if (style->selectStitches) { glLoadName(STITCHSSELID); //id of the stitches index = 0; glPushName(index); //init the stitches index stitch = selectedStitches.begin(); while (stitch != selectedStitches.end()) { drawStitchControl(*stitch, true); stitch++; index++; glLoadName(index); } glPopName(); } // if curves are selectables draw their controls if (style->selectCurves) { glLoadName(CURVESSELID); //id of the curves index = 0; glPushName(index); //init the curves index curve = selectedCurves.begin(); while (curve != selectedCurves.end()) { drawCurveControl(*curve, true); curve++; index++; glLoadName(index); } glPopName(); } // if sitches are selectables draw the stitch if (style->selectStitches) { glLoadName(STITCHSSELID); //id of the stitches index = 0; glPushName(index); //init the stitches index int curpoint = document->curPoint; stitch = document->stitchs.begin(); while (stitch != document->stitchs.end()) { drawStitch(*stitch, curpoint); curpoint -= (*stitch)->getNpts(); stitch++; index++; glLoadName(index); } glPopName(); } // if curves are selectables draw them if (style->selectCurves) { glLoadName(CURVESSELID); //id of the curves index = 0; glPushName(index); //init the curves index curve = document->curves.begin(); while (curve != document->curves.end()) { drawCurve(*curve); curve++; index++; glLoadName(index); } glPopName(); } } /** \brief move and zoom to see the entire document */ void OE_display::showAll() { if (document) { BoundingBox bound = document->getBound(); viewPos.x = (bound.getMax().x + bound.getMin().x)/2; viewPos.y = (bound.getMax().y + bound.getMin().y)/2; zoom = std::max((bound.getMax().x - bound.getMin().x)/width/1.5, (bound.getMax().y - bound.getMin().y)/height/1.5); changeDpi = true; } } void OE_display::zoomSelection() { if (document&&controller) { BoundingBox bound = controller->getSelectionBoundingBox(); if (!bound.init) { vector_2d hoop = document->getHoopSize(); bound = BoundingBox(-hoop.x/2.f,-hoop.y/2.f,hoop.x/2.f,hoop.y/2.f); } viewPos.x = (bound.getMax().x + bound.getMin().x)/2; viewPos.y = (bound.getMax().y + bound.getMin().y)/2; zoom = std::max((bound.getMax().x - bound.getMin().x)/width/1.5, (bound.getMax().y - bound.getMin().y)/height/1.5); changeDpi = true; } } bool OE_display::mouse_Pos(double x, double y) { if (pan) { viewPos = viewPos + (mouse-vector_2d(x, y))*zoom*2; } mouse.x = x; mouse.y = y; absMouse = viewPos+(mouse-vector_2d(width, height)/2)*zoom*2; return true; } bool OE_display::mouse_Button(QMouseEvent* event) { bool redraw = false; if (event->button() == Qt::MiddleButton) { pan = event->type() == QEvent::MouseButtonPress; if (pan) redraw = true; } return redraw; } void OE_display::scroll(double /*xoffset*/, double yoffset) { if (!pan) { if (yoffset>0) { zoom = zoom/1.1f; } else { zoom = zoom*1.1f; } changeDpi = true; } } void OE_display::resize(int width, int height) { this->width = width; this->height = height; } void OE_display::keyPressEvent(QKeyEvent* event) { if (event->isAutoRepeat()) return; key(event); } void OE_display::keyReleaseEvent(QKeyEvent* event) { if (event->isAutoRepeat()) return; key(event); } void OE_display::key(QKeyEvent* /*event*/) { //DEBUG printf("%s \"%s\"\n", event->type()==QEvent::KeyPress?"Keypress":"Keyrelease", event->text().toStdString().c_str(), event->count()); fflush(stdout); update(); // TODO only when necessary } vector_2d OE_display::screenToDocument(vector_2d pos) { return viewPos+(pos-vector_2d(width, height)/2)*zoom*2; }