Skip to content
OE_interfaceDisplay.cpp 27 KiB
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>
raoul's avatar
raoul committed
#include <qevent.h>
#include <GL/gl.h>
#include <cstdlib>
#include <math.h>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <QFileDialog>
#include "actions/OE_actionsCurves.h"
#include "actions/OE_actionsStitchs.h"
#include "actions/OE_actionsLineStitchs.h"
#include "actions/OE_actionsBirailStitchs.h"
3dsman's avatar
3dsman committed
#include "actions/OE_actionsFillStitchs.h"
#include "actions/OE_actionsSelection.h"
#include "actions/OE_actionsThreads.h"

raoul's avatar
raoul committed
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;
raoul's avatar
raoul committed
	setDocument(nullptr);
	modState = Qt::KeyboardModifier::NoModifier;
}

OE_interfaceDisplay::~OE_interfaceDisplay()
{
raoul's avatar
raoul committed
bool OE_interfaceDisplay::setDocument(OE_document* document)
raoul's avatar
raoul committed
	return true;
}


bool OE_interfaceDisplay::setController(OE_controller* controller)
{
raoul's avatar
raoul committed
	return true;
raoul's avatar
raoul committed
bool OE_interfaceDisplay::mouse_Pos(double x, double y)
raoul's avatar
raoul committed
	bool redraw = false;
	redraw |= OE_display::mouse_Pos(x, y);
	vector_2dt oldClosestPoint = editClosestPoint;
raoul's avatar
raoul committed
	vector_2d absMove = vector_2d((mouse.x - clicOldMouse.x)*zoom*2, (mouse.y - clicOldMouse.y)*zoom*2);
raoul's avatar
raoul committed
	if (editionState == MoveSelection) //if the move action is enabled
raoul's avatar
raoul committed
		controller->editActionMoveSelection(vector_2d((mouse.x - clicOldMouse.x)*zoom*2,
		                                              (mouse.y - clicOldMouse.y)*zoom*2));
raoul's avatar
raoul committed
		return true;
raoul's avatar
raoul committed
	if (editionState == ScaleSelection) //if the scale action is enabled
	{
		vector_2d bbCenter = controller->getSelectionBoundingBox().getCenter();
		float scale = (absMouse-bbCenter).len()/(screenToDocument(clicOldMouse)-bbCenter).len();
raoul's avatar
raoul committed
		controller->editActionScaleSelection(vector_2d(scale,scale));
raoul's avatar
raoul committed
		return true;
	if (editionState == NewSubcurve) //if we must find the closest subcurve (get the closest point on it too)
	{
		closestCurve = controller->getClosestCurve(absMouse, editClosestPoint);
raoul's avatar
raoul committed
		redraw = true;
	}
	else if (editSubcurve) //if we are working on a defined subcurve get the closest point on it
raoul's avatar
raoul committed
	{
		editClosestPoint = controller->getClosestPoint(editSubcurve->getCurve(), absMouse);
raoul's avatar
raoul committed
		redraw = true;
raoul's avatar
raoul committed
	}
	if (editionState == MovePointcurve && selControlCurve && selControlType==0) //if we're moving a curve control point
raoul's avatar
raoul committed
		controller->editActionMovePointCurve(vector_2d((mouse.x - clicOldMouse.x)*zoom*2,
		                                               (mouse.y - clicOldMouse.y)*zoom*2));
raoul's avatar
raoul committed
		return true;
	if (editionState == MovePointstitch) //if we're moving a linkstitch control point
	{
		controller->editActionMovePointLinkStitch(absMove);
		controller->editActionMoveGridPointFillStitch(absMove);
raoul's avatar
raoul committed
		return true;

	//if we're editing the scaleWidth of a linestitch
	if (editionState == OffsetWidthLinestitch)
raoul's avatar
raoul committed
	{
		controller->editActionSetLinestitchWidth((mouse.x - clicOldMouse.x)/100.0f, true);
raoul's avatar
raoul committed
		return 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();
raoul's avatar
raoul committed
		redraw = true;
	}

	if (editionState == TraceSubcurve)
	{
		controller->editActionAddSubcurvePosEnd(editClosestPoint.t);
raoul's avatar
raoul committed
		redraw = true;
	}
	else if (editionState == MoveSubcurve)
	{
		controller->editActionSetSubcurvePos(editClosestPoint.t);
raoul's avatar
raoul committed
		redraw = true;
raoul's avatar
raoul committed
	}
raoul's avatar
raoul committed
	return redraw;
raoul's avatar
raoul committed
bool OE_interfaceDisplay::mouse_Button(QMouseEvent* event)
raoul's avatar
raoul committed
	bool redraw = false;
	redraw |= OE_display::mouse_Button(event);
	if (curScreen == edit && event->button() == Qt::LeftButton && event->type() == QEvent::MouseButtonPress)
raoul's avatar
raoul committed
		redraw = true;
raoul's avatar
raoul committed
		if (editionState == NewSubcurve)
		{
			if (!closestCurve)
raoul's avatar
raoul committed
			else
			{
				controller->addAction(new OE_actionJoincurveAddSubCurve(document, curJoincurve, subcurve_id, closestCurve,
raoul's avatar
raoul committed
				                                                        editClosestPoint.t, editClosestPoint.t,
				                                                        false));
				//subcurve_id = -1;
raoul's avatar
raoul committed
				selControlStitch = controller->getStitch(-1);
				selControlType = 0;
				//editSubcurve = curJoincurve->getCurve(-1);
				editSubcurve = curJoincurve->getCurve(subcurve_id);
raoul's avatar
raoul committed
			}
		}
		else
		{
			clicOldMouse = mouse;
raoul's avatar
raoul committed
			if (editionState == None)
			{
raoul's avatar
raoul committed
			}
			if (editionState == None)
			{
raoul's avatar
raoul committed
			}
		}
raoul's avatar
raoul committed
		return redraw;
raoul's avatar
raoul committed
	}
raoul's avatar
raoul committed
	if (curScreen == edit && event->button() == Qt::LeftButton && event->type() == QEvent::MouseButtonRelease)
raoul's avatar
raoul committed
		redraw = true;
		selControlCurve = nullptr;
		selControlStitch = nullptr;
		if (editionState == AddSubcurve)
		{
			//curJoincurve = controller->getLineStitch(-1)->getJoincurve();
			//closestCurve = controller->getClosestCurve(absMouse, editClosestPoint);
			editionState = NewSubcurve;
			joincurve_id = 0;
raoul's avatar
raoul committed
			return true;
raoul's avatar
raoul committed
		if (editionState == Selection)
		{
			if ((mouse-clicOldMouse).len()>5)
raoul's avatar
raoul committed
			{
raoul's avatar
raoul committed
			}
			selectApply(selectedCurves, selectedStitches);
			editionState = None;
		}
		if ((editionState == NewSubcurve)||(editionState == TraceSubcurve))
raoul's avatar
raoul committed
		{
			if (joincurve_id == 0)
			{
				editionState = None;
				editSubcurve = nullptr;
			}
			else
			{
				editionState = NewSubcurve;
				curJoincurve = controller->getBirailStitch(-1)->getJoincurve2();
				closestCurve = controller->getClosestCurve(absMouse, editClosestPoint);
				joincurve_id -= 1;
			}
raoul's avatar
raoul committed
			return true;
raoul's avatar
raoul committed
		return redraw;
	return redraw;
}

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);
raoul's avatar
raoul committed
void OE_interfaceDisplay::key(QKeyEvent* event)
	static QString writeFilters = QString::fromStdString(OE_document::getWriteDialogFilters());
	static QString readFilters = QString::fromStdString(OE_document::getReadDialogFilters());
	if (event->type() == QEvent::KeyPress)
		modState = event->modifiers();
	else
		modState = Qt::KeyboardModifier::NoModifier;
raoul's avatar
raoul committed
	if (event->type() == QEvent::KeyPress && curScreen == edit)
raoul's avatar
raoul committed
	{
		if (event->key() == Qt::Key_R && event->modifiers() == Qt::NoModifier)
raoul's avatar
raoul committed
		{
			if (editionState == TraceSubcurve)
raoul's avatar
raoul committed
			{
				controller->editActionAddSubcurvePosSwitchDir();
raoul's avatar
raoul committed
			}
			else if (editionState == MoveSubcurve)
raoul's avatar
raoul committed
			{
				controller->editActionSetSubcurvePosSwitchDir();
raoul's avatar
raoul committed
			}
		}
raoul's avatar
raoul committed
		{
			if (event->key() == Qt::Key_Z && event->modifiers() == Qt::ControlModifier)
raoul's avatar
raoul committed
			{
				if (controller)
				{
raoul's avatar
raoul committed
				}
			}
			else if (event->key() == Qt::Key_S && event->modifiers() == Qt::ControlModifier)
raoul's avatar
raoul committed
			{
					QString fileName = QFileDialog::getSaveFileName(this, "Save design", "", writeFilters);
					if (!fileName.isEmpty())
					{
						document->saveToFile(fileName.toStdString());
					}
raoul's avatar
raoul committed
				}
			else if (event->key() == Qt::Key_O && event->modifiers() == Qt::ControlModifier)
				QString type;
				QString fileName = QFileDialog::getOpenFileName(this, "Open design", "", readFilters, &type);
				if (!fileName.isEmpty())
					loadFile(fileName.toStdString());
					update();
raoul's avatar
raoul committed
			}
			else if (event->key() == Qt::Key_Z && event->modifiers() == (Qt::ControlModifier|Qt::ShiftModifier))
				if (controller)
				{
					controller->redoAction();
raoul's avatar
raoul committed
			}
			else if (event->modifiers() == Qt::NoModifier)
				if (event->key() == Qt::Key_C)
						controller->toggleCloseSelectedCurve();
raoul's avatar
raoul committed
				else if (event->key() == Qt::Key_Delete)
				{
					//TODO create an action to delete all selected stitches
					std::list<OE_stitchs*>::iterator it=selectedStitches.begin();
					controller->addAction(new OE_actionDelStitch(document, *it));
raoul's avatar
raoul committed
				else if (event->key() == Qt::Key_Right)
				{
					std::list<OE_stitchs*>::iterator it=selectedStitches.begin();
					if (it != selectedStitches.end())
					{
raoul's avatar
raoul committed
						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);
raoul's avatar
raoul committed
				else if (event->key() == Qt::Key_Left)
					std::list<OE_stitchs*>::iterator it=selectedStitches.begin();
					if (it != selectedStitches.end())
raoul's avatar
raoul committed
						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);
raoul's avatar
raoul committed
	if (event->type() == QEvent::KeyRelease)
		if (event->key() == Qt::Key_R)
				{
					if (editionState == TraceSubcurve)
					{
						controller->editActionAddSubcurvePosSwitchDir();
					}
					else if (editionState == MoveSubcurve)
					{
						controller->editActionSetSubcurvePosSwitchDir();
					}
				}
		if(editionState==None)
raoul's avatar
raoul committed
		{
raoul's avatar
raoul committed
			if (curScreen == command && event->key() == Qt::Key_Space)
				run=true;
raoul's avatar
raoul committed
			}
raoul's avatar
raoul committed
			if (event->key() == Qt::Key_F12)
				if (curScreen == edit)
				{
					curScreen = command;
					setDisplayStyle(commandStyle);
				}
				else
				{
					curScreen = edit;
					setDisplayStyle(editStyle);
			else if (event->key() == Qt::Key_L)
raoul's avatar
raoul committed
			{
				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);
raoul's avatar
raoul committed

					editionState = NewSubcurve;
					joincurve_id = 0;
					subcurve_id = -1;
raoul's avatar
raoul committed
			}
			else if (event->key() == Qt::Key_B)
raoul's avatar
raoul committed
			{
				if (controller)
				{
					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);
raoul's avatar
raoul committed

					editionState = NewSubcurve;
					joincurve_id = 1;
					subcurve_id = -1;
raoul's avatar
raoul committed
			}
			else if (event->key() == Qt::Key_F)
3dsman's avatar
3dsman committed
			{
				if (controller)
				{
					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);
3dsman's avatar
3dsman committed

					editionState = NewSubcurve;
					joincurve_id = 0;
					subcurve_id = -1;
3dsman's avatar
3dsman committed
			}
raoul's avatar
raoul committed
			/*else if (event->key() == Qt::Key_Enter)
			{
				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 && event->modifiers() & Qt::KeypadModifier)
raoul's avatar
raoul committed
			{
				if (event->modifiers() & Qt::ControlModifier)
raoul's avatar
raoul committed
				{
					controller->addAction(new OE_actionScaleSelectedStitchLen(document, 1.1f));
raoul's avatar
raoul committed
				}
				else
				{
					controller->addAction(new OE_actionScaleSelectedStitchWidth(document, 1.1f));
raoul's avatar
raoul committed
				}
			}
			else if (event->key() == Qt::Key_Minus && event->modifiers() & Qt::KeypadModifier)
raoul's avatar
raoul committed
			{
				if (event->modifiers() & Qt::ControlModifier)
					controller->addAction(new OE_actionScaleSelectedStitchLen(document, 1.f/1.1f));
					controller->addAction(new OE_actionScaleSelectedStitchWidth(document, 1.f/1.1f));
raoul's avatar
raoul committed
			}
			else if (event->key() == Qt::Key_1 && event->modifiers() & Qt::KeypadModifier)
raoul's avatar
raoul committed
			{
				controller->addAction(new OE_actionSetSelectedStitchPattern(document, controller->getPattern(0)));
raoul's avatar
raoul committed
			}
			else if (event->key() == Qt::Key_2 && event->modifiers() & Qt::KeypadModifier)
				controller->addAction(new OE_actionSetSelectedStitchPattern(document, controller->getPattern(1)));
			else if (event->key() == Qt::Key_3 && event->modifiers() & Qt::KeypadModifier)
raoul's avatar
raoul committed
			{
				controller->addAction(new OE_actionSetSelectedStitchPattern(document, controller->getPattern(2)));
raoul's avatar
raoul committed
			}
			else if (event->key() == Qt::Key_4 && event->modifiers() & Qt::KeypadModifier)
				controller->addAction(new OE_actionSetSelectedStitchPattern(document, controller->getPattern(3)));
			else if (event->key() == Qt::Key_5 && event->modifiers() & Qt::KeypadModifier)
raoul's avatar
raoul committed
			{
				controller->addAction(new OE_actionSetSelectedStitchPattern(document, controller->getPattern(4)));
			else if (event->key() == Qt::Key_6 && event->modifiers() & Qt::KeypadModifier)
				controller->addAction(new OE_actionSetSelectedStitchPattern(document, controller->getPattern(5)));
			else if (event->key() == Qt::Key_7 && event->modifiers() & Qt::KeypadModifier)
				controller->addAction(new OE_actionSetSelectedStitchPattern(document, controller->getPattern(6)));
			else if (event->key() == Qt::Key_8 && event->modifiers() & Qt::KeypadModifier)
				controller->addAction(new OE_actionSetSelectedStitchPattern(document, controller->getPattern(7)));
			else if (event->key() == Qt::Key_9 && event->modifiers() & Qt::KeypadModifier)
				controller->addAction(new OE_actionSetSelectedStitchPattern(document, controller->getPattern(8)));
raoul's avatar
raoul committed
			}
raoul's avatar
raoul committed
			if (event->key() == Qt::Key_Home)
			{
				zoomSelection();
raoul's avatar
raoul committed
	}
3dsman's avatar
3dsman committed

void OE_interfaceDisplay::selectBox()
3dsman's avatar
3dsman committed
{
raoul's avatar
raoul committed
	selectedCurves.clear();
	selectedStitches.clear();
	vector_2d clicAbsMouse = viewPos+(clicOldMouse-vector_2d(width,height)/2)*zoom*2;
3dsman's avatar
3dsman committed

raoul's avatar
raoul committed
	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)))
raoul's avatar
raoul committed
		{
			selectedCurves.push_back(*curve);
		}
		curve++;
	}
3dsman's avatar
3dsman committed

raoul's avatar
raoul committed
	std::list<OE_stitchs*>::iterator stitch = document->stitchs.begin();
	while (stitch != document->stitchs.end())
	{
raoul's avatar
raoul committed
		BoundingBox box = (*stitch)->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)))
raoul's avatar
raoul committed
		{
			selectedStitches.push_back(*stitch);
		}
		stitch++;
	}
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(document, 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;
}

3dsman's avatar
3dsman committed
bool OE_interfaceDisplay::pickingTool(int toolType, int toolIndex)
3dsman's avatar
3dsman committed
    if (toolType == ZEROID) //zero
    {
    }
    if (toolType == TRANSTOOLID) //one of the transform selection tools
    {
        if (toolIndex == MOVETOOLID) //move selection tools
        {
            return pickingMoveTool();
        }
        if (toolIndex == SCALETOOLID) //scale selection tools
        {
            return pickingScaleTool();
        }
    }
    return false;
}
3dsman's avatar
3dsman committed
bool OE_interfaceDisplay::pickingMoveTool()
{
    editionState = MoveSelection;
    controller->addAction(new OE_actionMoveSelection(document, vector_2d(0,0)));
    return true;
}
3dsman's avatar
3dsman committed
bool OE_interfaceDisplay::pickingScaleTool()
{
    editionState = ScaleSelection;
    controller->addAction(new OE_actionScaleSelection(document, vector_2d(1,1), controller->getSelectionBoundingBox().getCenter()));
    return true;
}
3dsman's avatar
3dsman committed
bool OE_interfaceDisplay::pickingStitch(int stitchIndex)
{
    if (stitchIndex >= document->stitchs.size())
    {
        return false;
    }

    std::list<OE_stitchs*>::iterator it = document->stitchs.begin();
    std::advance(it, stitchIndex);
    selectedStitches.push_back(*it);
    return true;
}
3dsman's avatar
3dsman committed
bool OE_interfaceDisplay::pickingStitchControl(int stitchIndex, int ctrlType, int ctrlIndex)
{
    if (stitchIndex >= document->selectedStitchs.size())
    {
        return false;
    }

    std::list<OE_stitchs*>::iterator it = document->selectedStitchs.begin();
    std::advance(it, stitchIndex);
    selControlStitch = *it;
    selControlType = ctrlType;
    selControlIndex = ctrlIndex;
	int ControlTypeIndex = 0;
3dsman's avatar
3dsman committed
    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(document, tmpLineStitch, tmpLineStitch->getWidth()));
            return true;
        }
    }

    OE_birailstitch* tmpBirailStitch = dynamic_cast<OE_birailstitch*>(selControlStitch);

    if (tmpBirailStitch)
    {
        // check generic joinCurve controls for each birail's joincurve
        if (checkJoinCurveControl(tmpBirailStitch->getJoincurve1(), ControlTypeIndex)) return true;
        if (checkJoinCurveControl(tmpBirailStitch->getJoincurve2(), ControlTypeIndex)) return true;
        return false;
    }

    OE_fillstitch* tmpFillStitch = dynamic_cast<OE_fillstitch*>(selControlStitch);

    if (tmpFillStitch)
    {
        // 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(document, tmpFillStitch, selControlIndex, vector_2d(0,0)));
            return true;
        }
        return false;
    }

    OE_linkstitch* tmpLinkStitch = dynamic_cast<OE_linkstitch*>(selControlStitch);

    if (tmpLinkStitch)
    {
        //check picking of control point, add or delete
        if (selControlType == 0)
        {
            editionState = MovePointstitch;
            controller->addAction(new OE_actionMovePointLinkStitch(document, tmpLinkStitch, selControlIndex, vector_2d()));
            return true;
        }
        else if (selControlType == 1)
        {
            editionState = MovePointstitch;
            controller->addAction(new OE_actionAddPointLinkStitch(document, tmpLinkStitch, selControlIndex, absMouse));
            return true;
        }
        else if (selControlType == 2)
        {
            editionState = DelPointstitch;
            controller->addAction(new OE_actionDelPointLinkStitch(document, tmpLinkStitch, selControlIndex));
            return true;
        }
        return false;
    }

    selControlStitch = nullptr;
    return false;
}
3dsman's avatar
3dsman committed
bool OE_interfaceDisplay::pickingCurve(int curveIndex)
{
    if (curveIndex >= document->curves.size())
    {
        return false;
    }

    std::list<OE_pointcurve*>::iterator it = document->curves.begin();
    std::advance(it, curveIndex);
    selectedCurves.push_back(*it);
    return true;
}
3dsman's avatar
3dsman committed
bool OE_interfaceDisplay::pickingCurveControl(int curveIndex, int ctrlType, int ctrlIndex)
{
    if (curveIndex >= document->selectedCurves.size())
    {
        return false;
    }

    std::list<OE_pointcurve*>::iterator it = document->selectedCurves.begin();
    std::advance(it, curveIndex);
    selControlCurve = *it;
    selControlType = ctrlType;
    selControlIndex = ctrlIndex;

    OE_pointcurve* tmpPointCurve = dynamic_cast<OE_pointcurve*>(selControlCurve);

    if (tmpPointCurve && selControlType == 0)
    {
        editionState = MovePointcurve;
        controller->addAction(new OE_actionMovePointCurve(document, tmpPointCurve,
                                                          selControlIndex+1,
                                                          vector_2d(0,0)));
        return true;
    }

    selControlCurve = nullptr;
    return false;
/** \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

	GLint hits = glRenderMode(GL_RENDER);
	selectedCurves.clear();
3dsman's avatar
3dsman committed
    selectedStitches.clear();
	GLuint *ptr;
	ptr = static_cast<GLuint*>(selectBuf);
	for (GLint i=0; i<hits; i++)  //  for each hit
		ptr+=3; //skip nearZ and farZ info (we don't use it) and goto first index
3dsman's avatar
3dsman committed
        //in *ptr we got "item type", "item id" then, if we picked a control "control type" and at last "control id"
        switch(*ptr) {
            case TOOLSSELID :
                    return pickingTool(*(ptr+1), *(ptr+2));
                break;

            case STITCHSSELID :
                    if (names==2) //we picked an item
                        return pickingStitch(*(ptr+1));
                    else if (names==4) //we've got a control
                        return pickingStitchControl(*(ptr+1), *(ptr+2), *(ptr+3));
                break;

            case CURVESSELID:
                    if (names==2)
                        return pickingCurve(*(ptr+1));
                    else if (names==4)
                        return pickingCurveControl(*(ptr+1), *(ptr+2), *(ptr+3));
                break;
        }
bool OE_interfaceDisplay::selectApply(std::list<OE_pointcurve*> selectedCurves, std::list<OE_stitchs*> selectedStitches)
raoul's avatar
raoul committed
	if (selectedCurves.size())
	{
raoul's avatar
raoul committed
		if (modState.testFlag(Qt::ControlModifier))
raoul's avatar
raoul committed
		{
			controller->unselectCurves(selectedCurves);
		}
		else
		{
raoul's avatar
raoul committed
			controller->selectCurves(selectedCurves, !modState.testFlag(Qt::ShiftModifier));
raoul's avatar
raoul committed
		}
	}

	if (selectedStitches.size())
	{
raoul's avatar
raoul committed
		if (modState.testFlag(Qt::ControlModifier))
raoul's avatar
raoul committed
		{
			controller->unselectStitches(selectedStitches);
		}
		else
		{
raoul's avatar
raoul committed
			controller->selectStitches(selectedStitches, !modState.testFlag(Qt::ShiftModifier));
raoul's avatar
raoul committed
		}
	}
raoul's avatar
raoul 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()
{
raoul's avatar
raoul committed
	if (run)
	{
		//TODO remove controller->sendInstPoint();
raoul's avatar
raoul committed
	}

	//draw the closest point
	if (editionState==NewSubcurve)
raoul's avatar
raoul committed
	{
		// Points
		glPointSize(5.0f);

		glBegin(GL_POINTS);
		if (joincurve_id == 0)
raoul's avatar
raoul committed
		{
			glColor4f(0.8f, 0.0f, 0.0f, 1.0f);
raoul's avatar
raoul committed
		}
		else
		{
			glColor4f(0.0f, 0.8f, 0.0f, 1.0f);
raoul's avatar
raoul committed
		}
		glVertex2f(editClosestPoint.v.x,editClosestPoint.v.y);
		glEnd();
raoul's avatar
raoul committed
	}
	// draw the cursor cross
	glLineWidth(1.5);
	glBegin(GL_LINES);
		if (editionState)
raoul's avatar
raoul committed
		{
			if (joincurve_id == 0)
			{
				glColor4f(0.8f, 0.0f, 0.0f, 0.5f);
raoul's avatar
raoul committed
			}
			else
			{
				glColor4f(0.0f, 0.8f, 0.0f, 0.5f);
raoul's avatar
raoul committed
			}
		}
			glColor4fv(style->cursorColor.rgba);
		}
		glVertex2f(absMouse.x,-10000);
		glVertex2f(absMouse.x,10000);
raoul's avatar
raoul committed

		glVertex2f(-10000,absMouse.y);
		glVertex2f(10000,absMouse.y);
	glEnd();
raoul's avatar
raoul committed

	// 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();
raoul's avatar
raoul committed

	if (editionState == Selection)
	{
		vector_2d clicAbsMouse = viewPos+(clicOldMouse-vector_2d(width,height)/2)*zoom*2;
raoul's avatar
raoul committed
		glLineWidth(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);
raoul's avatar
raoul committed
		glEnd();
	}