Newer
Older
/*
* Copyright (c) 2015 Tricoire Sebastien 3dsman@free.fr
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
*/
#include "OE_interfaceDisplay.h"
#include "OE_utils.h"
#include "OE_controller.h"
#include <iostream>
#include <GL/gl.h>
#include <cstdlib>
#include <math.h>
#include <cstdio>
#include <cstring>
#include "actions/OE_actionsCurves.h"
#include "actions/OE_actionsStitchs.h"
#include "actions/OE_actionsLineStitchs.h"
#include "actions/OE_actionsBirailStitchs.h"
3dsman
committed
#include "actions/OE_actionsLinkStitchs.h"
#include "actions/OE_actionsSelection.h"
#include "actions/OE_actionsThreads.h"
static const GLuint TOOLSSELID = 0;
static const GLuint STITCHSSELID = 1;
static const GLuint CURVESSELID = 2;
static const GLuint ZEROID = 0;
static const GLuint TRANSTOOLID = 1;
static const GLuint MOVETOOLID = 0;
static const GLuint SCALETOOLID = 1;
OE_interfaceDisplay::OE_interfaceDisplay(QWidget *parent, Qt::WindowFlags f) : OE_display(parent, f)
{
editStyle = new OE_display::OE_displayStyle();
commandStyle = new OE_display::OE_displayStyle();
commandStyle->drawGrid = false;
commandStyle->drawCurves = false;
commandStyle->drawStitches = false;
commandStyle->drawCommands = true;
setDisplayStyle(editStyle);
}
OE_interfaceDisplay::~OE_interfaceDisplay()
{
//delete curDisplay;
}
bool OE_interfaceDisplay::setDocument(OE_document* document)
{
this->document = document;
}
bool OE_interfaceDisplay::setController(OE_controller* controller)
{
this->controller = controller;
}
void OE_interfaceDisplay::showAll()
{
OE_display::showAll();
}
{
bool redraw = false;
redraw |= OE_display::mouse_Pos(x, y);
vector_2dt oldClosestPoint = editClosestPoint;
vector_2d absMove = vector_2d((mouse.x - clicOldMouse.x)*zoom*2, (mouse.y - clicOldMouse.y)*zoom*2);
if (editionState == MoveSelection) //if the move action is enabled
controller->editActionMoveSelection(vector_2d((mouse.x - clicOldMouse.x)*zoom*2,
(mouse.y - clicOldMouse.y)*zoom*2));
if (editionState == ScaleSelection) //if the scale action is enabled
{
vector_2d bbCenter = controller->getSelectionBoundingBox().getCenter();
float scale = (absMouse-bbCenter).len()/(screenToDocument(clicOldMouse)-bbCenter).len();
controller->editActionScaleSelection(vector_2d(scale,scale));
if (editionState == NewSubcurve) //if we must find the closest subcurve (get the closest point on it too)
{
closestCurve = controller->getClosestCurve(absMouse, editClosestPoint);
redraw = true;
}
else if (editSubcurve) //if we are working on a defined subcurve get the closest point on it
{
editClosestPoint = controller->getClosestPoint(editSubcurve->getCurve(), absMouse);
if (editionState == MovePointcurve && selControlCurve && selControlType==0) //if we're moving a curve control point
controller->editActionMovePointCurve(vector_2d((mouse.x - clicOldMouse.x)*zoom*2,
(mouse.y - clicOldMouse.y)*zoom*2));
3dsman
committed
if (editionState == MovePointstitch) //if we're moving a linkstitch control point
{
controller->editActionMovePointLinkStitch(absMove);
controller->editActionMoveGridPointFillStitch(absMove);
3dsman
committed
}
//if we're editing the scaleWidth of a linestitch
if (editionState == OffsetWidthLinestitch)
controller->editActionSetLinestitchWidth((mouse.x - clicOldMouse.x)/100.0f, true);
//if we're define a new subcurve and the reference curve is already picked
if ((editionState == NewSubcurve)&&(selControlStitch))
{
editionState = TraceSubcurve;
if (oldClosestPoint.t>editClosestPoint.t) controller->editActionAddSubcurvePosSwitchDir();
}
if (editionState == TraceSubcurve)
{
controller->editActionAddSubcurvePosEnd(editClosestPoint.t);
}
else if (editionState == MoveSubcurve)
{
controller->editActionSetSubcurvePos(editClosestPoint.t);
}
{
bool redraw = false;
redraw |= OE_display::mouse_Button(event);
if (curScreen == edit && event->button() == Qt::LeftButton && event->type() == QEvent::MouseButtonPress)
if (editionState == NewSubcurve)
{
if (!closestCurve)
{
editionState = None;
}
controller->addAction(new OE_actionJoincurveAddSubCurve(curJoincurve, subcurve_id, closestCurve,
selControlStitch = controller->getStitch(-1);
selControlType = 0;
//editSubcurve = curJoincurve->getCurve(-1);
editSubcurve = curJoincurve->getCurve(subcurve_id);
editionState = Selection;
if (curScreen == edit && event->button() == Qt::LeftButton && event->type() == QEvent::MouseButtonRelease)
selControlCurve = nullptr;
selControlStitch = nullptr;
if (editionState == AddSubcurve)
{
//curJoincurve = controller->getLineStitch(-1)->getJoincurve();
//closestCurve = controller->getClosestCurve(absMouse, editClosestPoint);
editionState = NewSubcurve;
joincurve_id = 0;
{
if ((mouse-clicOldMouse).len()>5)
selectBox();
selectApply(selectedCurves, selectedStitches);
editionState = None;
}
if ((editionState == NewSubcurve)||(editionState == TraceSubcurve))
if (joincurve_id == 0)
{
editionState = None;
}
else
{
editionState = NewSubcurve;
curJoincurve = controller->getBirailStitch(-1)->getJoincurve2();
closestCurve = controller->getClosestCurve(absMouse, editClosestPoint);
joincurve_id -= 1;
}
editionState = None;
}
}
void OE_interfaceDisplay::scroll(double xoffset, double yoffset)
{
OE_display::scroll(xoffset, yoffset);
}
void OE_interfaceDisplay::resize(int width, int height)
{
OE_display::resize(width, height);
}
{
if (event->type() == QEvent::KeyPress && curScreen == edit)
if (event->key() == Qt::Key_R && modState == Qt::NoModifier)
if (editionState == TraceSubcurve)
controller->editActionAddSubcurvePosSwitchDir();
update();
else if (editionState == MoveSubcurve)
controller->editActionSetSubcurvePosSwitchDir();
update();
if(editionState==None)
if (event->key() == Qt::Key_Z && modState == Qt::ControlModifier)
controller->undoAction();
update();
else if (event->key() == Qt::Key_S && modState == Qt::ControlModifier)
if (document)
QString fileName = QFileDialog::getSaveFileName(this, "Save design", "", "OE designer (*.oe)");
if (!fileName.isEmpty())
{
document->saveToFile(fileName.toStdString());
}
else if (event->key() == Qt::Key_O && modState == Qt::ControlModifier)
QString type;
QString fileName = QFileDialog::getOpenFileName(this, "Open design", "", "All supported (*.oe *.svg *.pes);;OE designer (*.oe);;SVG drawing (*.svg);;PES (*.pes)", &type);
if (!fileName.isEmpty())
loadFile(fileName.toStdString());
update();
else if (event->key() == Qt::Key_Z && modState == (Qt::ControlModifier|Qt::ShiftModifier))
if (controller)
{
controller->redoAction();
update();
if (controller)
controller->toggleCloseSelectedCurve();
update();
{
//TODO create an action to delete all selected stitches
std::list<OE_stitchs*>::iterator it=selectedStitches.begin();
controller->addAction(new OE_actionDelStitch(*it));
update();
{
std::list<OE_stitchs*>::iterator it=selectedStitches.begin();
if (it != selectedStitches.end())
{
it = std::find (document->stitchs.begin(), document->stitchs.end(), *it);
it++;
if (it != document->stitchs.end())
{
selectedStitches.clear();
selectedStitches.push_back(*it);
controller->clearSelection();
controller->selectStitches(selectedStitches,true);
update();
}
}
}
std::list<OE_stitchs*>::iterator it=selectedStitches.begin();
if (it != selectedStitches.end())
it = std::find (document->stitchs.begin(), document->stitchs.end(), *it);
if (it != document->stitchs.begin())
{
it--;
selectedStitches.clear();
selectedStitches.push_back(*it);
controller->clearSelection();
controller->selectStitches(selectedStitches,true);
update();
}
}
}
{
if (editionState == TraceSubcurve)
{
controller->editActionAddSubcurvePosSwitchDir();
update();
}
else if (editionState == MoveSubcurve)
{
controller->editActionSetSubcurvePosSwitchDir();
update();
update();
if (curScreen == edit)
{
curScreen = command;
setDisplayStyle(commandStyle);
update();
}
else
{
curScreen = edit;
setDisplayStyle(editStyle);
update();
if (controller)
{
controller->newLineStitch(2.5, 2.5, controller->getPattern(0));
document->selectedStitchs.push_back(controller->getLineStitch(-1));
curJoincurve = controller->getLineStitch(-1)->getJoincurve();
closestCurve = controller->getClosestCurve(absMouse, editClosestPoint);
editionState = NewSubcurve;
joincurve_id = 0;
subcurve_id = -1;
update();
controller->newBirailStitch(false, false, 0, 0, 0.7f);
document->selectedStitchs.push_back(controller->getBirailStitch(-1));
curJoincurve = controller->getBirailStitch(-1)->getJoincurve1();
closestCurve = controller->getClosestCurve(absMouse, editClosestPoint);
editionState = NewSubcurve;
joincurve_id = 1;
subcurve_id = -1;
update();
controller->newFillStitch(1.5f, 0.3f, controller->getPattern(0));
document->selectedStitchs.push_back(controller->getFillStitch(-1));
curJoincurve = controller->getFillStitch(-1)->getJoincurve();
closestCurve = controller->getClosestCurve(absMouse, editClosestPoint);
editionState = NewSubcurve;
joincurve_id = 0;
update();
{
if (editionState == NewSubcurve)
{
if (joincurve_id == 0)
{
editionState = None;
curJoincurve = 0;
}
else
{
curJoincurve = controller->getBirailStitch(-1)->getJoincurve2();
closestCurve = controller->getClosestCurve(absMouse, editClosestPoint);
joincurve_id -= 1;
}
}
}*/
else if (event->key() == Qt::Key_Plus && modState & Qt::KeypadModifier)
controller->addAction(new OE_actionScaleSelectedStitchLen(1.1f));
update();
controller->addAction(new OE_actionScaleSelectedStitchWidth(1.1f));
update();
else if (event->key() == Qt::Key_Minus && modState & Qt::KeypadModifier)
controller->addAction(new OE_actionScaleSelectedStitchLen(1.f/1.1f));
update();
controller->addAction(new OE_actionScaleSelectedStitchWidth(1.f/1.1f));
update();
else if (event->key() == Qt::Key_1 && modState & Qt::KeypadModifier)
controller->addAction(new OE_actionSetSelectedStitchPattern(controller->getPattern(0)));
update();
else if (event->key() == Qt::Key_2 && modState & Qt::KeypadModifier)
controller->addAction(new OE_actionSetSelectedStitchPattern(controller->getPattern(1)));
update();
else if (event->key() == Qt::Key_3 && modState & Qt::KeypadModifier)
controller->addAction(new OE_actionSetSelectedStitchPattern(controller->getPattern(2)));
update();
else if (event->key() == Qt::Key_4 && modState & Qt::KeypadModifier)
controller->addAction(new OE_actionSetSelectedStitchPattern(controller->getPattern(3)));
update();
else if (event->key() == Qt::Key_5 && modState & Qt::KeypadModifier)
controller->addAction(new OE_actionSetSelectedStitchPattern(controller->getPattern(4)));
update();
else if (event->key() == Qt::Key_6 && modState & Qt::KeypadModifier)
{
controller->addAction(new OE_actionSetSelectedStitchPattern(controller->getPattern(5)));
update();
else if (event->key() == Qt::Key_7 && modState & Qt::KeypadModifier)
{
controller->addAction(new OE_actionSetSelectedStitchPattern(controller->getPattern(6)));
update();
else if (event->key() == Qt::Key_8 && modState & Qt::KeypadModifier)
{
controller->addAction(new OE_actionSetSelectedStitchPattern(controller->getPattern(7)));
update();
else if (event->key() == Qt::Key_9 && modState & Qt::KeypadModifier)
{
controller->addAction(new OE_actionSetSelectedStitchPattern(controller->getPattern(8)));
update();
3dsman
committed
update();
3dsman
committed
}
}
selectedCurves.clear();
selectedStitches.clear();
vector_2d clicAbsMouse = viewPos+(clicOldMouse-vector_2d(width,height)/2)*zoom*2;
std::list<OE_pointcurve*>::iterator curve = document->curves.begin();
while (curve != document->curves.end())
{
BoundingBox box = (*curve)->getBound();
if ((box.getMin().x > std::min(clicAbsMouse.x, absMouse.x))
&&(box.getMax().x < std::max(clicAbsMouse.x, absMouse.x))
&&(box.getMin().y > std::min(clicAbsMouse.y, absMouse.y))
&&(box.getMax().y < std::max(clicAbsMouse.y, absMouse.y)))
{
selectedCurves.push_back(*curve);
}
curve++;
}
std::list<OE_stitchs*>::iterator stitch = document->stitchs.begin();
while (stitch != document->stitchs.end())
{
if ((box.getMin().x > std::min(clicAbsMouse.x, absMouse.x))
&&(box.getMax().x < std::max(clicAbsMouse.x, absMouse.x))
&&(box.getMin().y > std::min(clicAbsMouse.y, absMouse.y))
&&(box.getMax().y < std::max(clicAbsMouse.y, absMouse.y)))
{
selectedStitches.push_back(*stitch);
}
stitch++;
}
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
bool OE_interfaceDisplay::checkJoinCurveControl(OE_joincurve* joinCurve, int &index)
{
if (selControlType == index)
{
// get the corresponding subcurve
editSubcurve = joinCurve->getCurve(selControlIndex/2);
if (editSubcurve)
{
editionState = MoveSubcurve;
// get the closest point t value
vector_2dt pos = editSubcurve->getCurve()->closestPoint(absMouse);
// and add an action to move the point
controller->addAction(new OE_actionSetSubcurvePos(editSubcurve, selControlIndex%2, pos.t));
return true;
}
return false;
}
index++;
if (selControlType == index)
{
editionState = AddSubcurve;
subcurve_id = selControlIndex;
curJoincurve = joinCurve;
return true;
}
index++;
return false;
}
bool OE_interfaceDisplay::checkPicking()
{
{
editionState = MoveSelection;
controller->addAction(new OE_actionMoveSelection(vector_2d(0,0)));
return true;
{
editionState = ScaleSelection;
controller->addAction(new OE_actionScaleSelection(vector_2d(1,1), controller->getSelectionBoundingBox().getCenter()));
return true;
// if we picked a stitch control
OE_linestitch* tmpLineStitch = dynamic_cast<OE_linestitch*>(selControlStitch);
if (tmpLineStitch)
{
// check generic joinCurve controls
if (checkJoinCurveControl(tmpLineStitch->getJoincurve(), ControlTypeIndex)) return true;
//check picking for linestitch width controller
if (selControlType == ControlTypeIndex && selControlIndex == 0)
editionState = OffsetWidthLinestitch;
controller->addAction(new OE_actionSetLineStitchWidth(tmpLineStitch, tmpLineStitch->getWidth()));
return true;
}
}
OE_birailstitch* tmpBirailStitch = dynamic_cast<OE_birailstitch*>(selControlStitch);
// check generic joinCurve controls for each birail's joincurve
if (checkJoinCurveControl(tmpBirailStitch->getJoincurve1(), ControlTypeIndex)) return true;
if (checkJoinCurveControl(tmpBirailStitch->getJoincurve2(), ControlTypeIndex)) return true;
3dsman
committed
OE_fillstitch* tmpFillStitch = dynamic_cast<OE_fillstitch*>(selControlStitch);
// check generic joinCurve controls
if (checkJoinCurveControl(tmpFillStitch->getJoincurve(), ControlTypeIndex)) return true;
// check picking for grid's controller points
else if (selControlType == ControlTypeIndex)
editionState = MovePointstitch;
//edit gridpoint
controller->addAction(new OE_actionMovePointFillStitch(tmpFillStitch, selControlIndex, vector_2d(0,0)));
return true;
}
return false;
}
3dsman
committed
OE_linkstitch* tmpLinkStitch = dynamic_cast<OE_linkstitch*>(selControlStitch);
3dsman
committed
{
//check picking of control point, add or delete
3dsman
committed
if (selControlType == 0)
{
editionState = MovePointstitch;
controller->addAction(new OE_actionMovePointLinkStitch(tmpLinkStitch, selControlIndex, vector_2d()));
3dsman
committed
{
editionState = MovePointstitch;
controller->addAction(new OE_actionAddPointLinkStitch(tmpLinkStitch, selControlIndex, absMouse));
{
editionState = DelPointstitch;
controller->addAction(new OE_actionDelPointLinkStitch(tmpLinkStitch, selControlIndex));
3dsman
committed
}
return false;
}
3dsman
committed
}
OE_pointcurve* tmpPointCurve = dynamic_cast<OE_pointcurve*>(selControlCurve);
editionState = MovePointcurve;
controller->addAction(new OE_actionMovePointCurve(tmpPointCurve,
selControlIndex+1,
vector_2d(0,0)));
return true;
/** \brief set selection
*
* \return true if all is ok
*
*/
bool OE_interfaceDisplay::drawPicking()
GLuint selectBuf[64];
glSelectBuffer(64, selectBuf);
OE_display::pick(document->selectedCurves, document->selectedStitchs);
//get the hits of the picking
//hits are represented by an array of GLuint*
// first value give us the number of items on the name stack at the time of the hit
// next 2 values are deep value of the picked object (we don't use it)
// then the items we need arrived
// we format it like that:
// - type of the picked object (tool, stitch or curve)
// - index of the picked object (list index for stitch or curve, index of the tool for the tools)
// - if we picked a sub element of a curve, stich or tool here come his type (handle, startpoint,...)
// - then his index
//
// so a hit can be defined by
// 2 values in case a curve of a stitch was picked directly
// 3 values in case of picking a transform tool like move
// or 4 values if we picked a sub element of a curve or stitch
selectedCurves.clear();
selectedStitches.clear();
toolAction = 0;
//std::cout<<"hits : "<<"\r\n";
ptr = static_cast<GLuint*>(selectBuf);
for (GLint i=0; i<hits; i++) // for each hit
{
GLuint names = *ptr;
ptr+=3; //skip nearZ and farZ info (we don't use it) and goto first index
if (*ptr == TOOLSSELID) //tools picking
{
ptr++;
{
}
if (*ptr == TRANSTOOLID) //one of the transform selection tools
ptr++;
{
toolAction = 1;
checkPicking();
return true;
}
{
toolAction = 2;
checkPicking();
return true;
}
return false;
//ptr++;
{
ptr++;
if (names==2) //if name count correspond to an object (we picked a stitch, not one of his sub element)
if (*ptr >= document->stitchs.size())
{
return false;
}
std::list<OE_stitchs*>::iterator it = document->stitchs.begin();
std::advance(it, *ptr);
selectedStitches.push_back(*it);
return true;
}
else if (names==4) //if name count correspond to a stitch sub element (like control point)
if (*ptr >= document->selectedStitchs.size())
{
return false;
}
std::list<OE_stitchs*>::iterator it = document->selectedStitchs.begin();
std::advance(it, *ptr++);
selControlStitch = *it;
selControlType = *ptr++;
selControlIndex = *ptr++;
checkPicking();
return true;
{
ptr++;
if (names==2) //if name count correspond to an object (we picked a curve, not one of his sub element)
{
if (*ptr >= document->curves.size())
{
return false;
}
std::list<OE_pointcurve*>::iterator it = document->curves.begin();
std::advance(it, *ptr);
selectedCurves.push_back(*it);
return true;
}
else if (names==4) //if name count correspond to a sub element of curve (like control point)
if (*ptr >= document->selectedCurves.size())
{
return false;
}
//in *ptr we got "curve id" then "control type" and at last "control id"
std::list<OE_pointcurve*>::iterator it = document->selectedCurves.begin();
std::advance(it, *ptr++);
selControlCurve = *it;
selControlType = *ptr++;
selControlIndex = *ptr++;
checkPicking();
return true;
}
3dsman
committed
bool OE_interfaceDisplay::selectApply(std::list<OE_pointcurve*> selectedCurves, std::list<OE_stitchs*> selectedStitches)
{
controller->unselectCurves(selectedCurves);
}
else
{
controller->selectCurves(selectedCurves, !modState.testFlag(Qt::ShiftModifier));
{
controller->unselectStitches(selectedStitches);
}
else
{
controller->selectStitches(selectedStitches, !modState.testFlag(Qt::ShiftModifier));
3dsman
committed
if (!selectedStitches.size() && !selectedCurves.size())
{
controller->clearSelection();
}
return true;
/** \brief draw the document on screen
*
* \return true if all is ok
*
*/
bool OE_interfaceDisplay::draw()
{
if (!document)
{
return false;
}
OE_display::draw();
//draw the closest point
if (editionState==NewSubcurve)
// Points
glPointSize(5.0f);
glBegin(GL_POINTS);
if (joincurve_id == 0)
glVertex2f(editClosestPoint.v.x,editClosestPoint.v.y);
glEnd();
// draw the cursor cross
glLineWidth(1.5);
glBegin(GL_LINES);
if (editionState)
glColor4f(0.8f, 0.0f, 0.0f, 0.5f);
glColor4f(0.0f, 0.8f, 0.0f, 0.5f);
glColor4fv(style->cursorColor.rgba);
}
glVertex2f(absMouse.x,-10000);
glVertex2f(absMouse.x,10000);
glVertex2f(-10000,absMouse.y);
glVertex2f(10000,absMouse.y);
glEnd();
// draw the cursor picking zone
glLineWidth(2);
glBegin(GL_LINE_LOOP);
glColor4fv(style->cursorColor.rgba);
glVertex2f(absMouse.x-5*zoom,absMouse.y+5*zoom);
glVertex2f(absMouse.x-5*zoom,absMouse.y-5*zoom);
glVertex2f(absMouse.x+5*zoom,absMouse.y-5*zoom);
glVertex2f(absMouse.x+5*zoom,absMouse.y+5*zoom);
glEnd();
if (editionState == Selection)
{
vector_2d clicAbsMouse = viewPos+(clicOldMouse-vector_2d(width,height)/2)*zoom*2;
glBegin(GL_LINE_STRIP);
glColor4fv(style->cursorColor.rgba);
glVertex2f(absMouse.x,clicAbsMouse.y);
glVertex2f(absMouse.x,absMouse.y);
glVertex2f(clicAbsMouse.x,absMouse.y);
glVertex2f(clicAbsMouse.x,clicAbsMouse.y);
glVertex2f(absMouse.x,clicAbsMouse.y);
return true;
}