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 <algorithm>
#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(OE_document* document)
{
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();
}
void OE_interfaceDisplay::mouse_Pos(double x, double 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));
return;
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));
return;
if (editionState == NewSubcurve) //if we must find the closest subcurve (get the closest point on it too)
{
closestCurve = controller->getClosestCurve(absMouse, editClosestPoint);
}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));
return;
}
3dsman
committed
if (editionState == MovePointstitch) //if we're moving a linkstitch control point
{
controller->editActionMovePointLinkStitch(absMove);
controller->editActionMoveGridPointFillStitch(absMove);
3dsman
committed
return;
}
if (selControlStitch) //if we're working on a stitch
{
OE_linestitch* tmpLineStitch = dynamic_cast<OE_linestitch*>(selControlStitch);
OE_birailstitch* tmpBirailStitch = dynamic_cast<OE_birailstitch*>(selControlStitch);
OE_fillstitch* tmpFillStitch = dynamic_cast<OE_fillstitch*>(selControlStitch);
if (tmpLineStitch && editionState == OffsetWidthLinestitch) //if this is a linestitch and we're picking the scaleWidth controler
controller->editActionSetLinestitchWidth((mouse.x - clicOldMouse.x)/100.0f, true);
return;
//if we're define control curves for linestitch or birailstitch
if (((tmpLineStitch || tmpFillStitch ||tmpBirailStitch) && selControlType == 0)||
(tmpBirailStitch && selControlType == 1))
{
if (editionState == NewSubcurve)
{
editionState = TraceSubcurve;
if (oldClosestPoint.t>editClosestPoint.t) controller->editActionAddSubcurvePosSwitchDir();
}
if (editionState == TraceSubcurve)
{
controller->editActionAddSubcurvePosEnd(editClosestPoint.t);
}
else if (editionState == MoveSubcurve)
{
controller->editActionSetSubcurvePos(editClosestPoint.t);
}
}
}
}
void OE_interfaceDisplay::mouse_Button(int button, int action, int mods)
{
OE_display::mouse_Button(button, action, mods);
if (curScreen == edit && button == GLFW_MOUSE_BUTTON_LEFT && action==GLFW_PRESS)
if (editionState == NewSubcurve)
{
if (!closestCurve)
{
editionState = None;
return;
}
else
{
controller->addAction(new OE_actionJoincurveAddSubCurve(curJoincurve, -1, closestCurve,
editClosestPoint.t, editClosestPoint.t,
false));
selControlStitch = controller->getStitch(-1);
selControlType = 0;
editSubcurve = curJoincurve->getCurve(-1);
return;
editionState = Selection;
return;
if (curScreen == edit && button == GLFW_MOUSE_BUTTON_LEFT && action==GLFW_RELEASE)
//if (selControlCurve)selControlCurve = 0;
//if (selControlStitch)selControlStitch = 0;
selControlCurve = 0;
selControlStitch = 0;
{
if ((mouse-clicOldMouse).len()>5)
selectBox();
selectApply(selectedCurves, selectedStitches);
editionState = None;
}
if ((editionState == NewSubcurve)||(editionState == TraceSubcurve))
return;
}
if (editionState == MoveSubcurve ||
editionState == MovePointcurve ||
editionState == MovePointstitch ||
editionState == DelPointstitch ||
editionState == MoveSelection ||
editionState == ScaleSelection)
{
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);
}
void OE_interfaceDisplay::key(int key, int scancode, int action, int mods)
{
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
modState = mods;
if (action == GLFW_PRESS && curScreen == edit)
{
if (!strcmp(key_name, "z") && mods == GLFW_MOD_CONTROL)
{
if (controller)
{
controller->undoAction();
}
}
else if (!strcmp(key_name, "s") && mods == GLFW_MOD_CONTROL)
{
if (document)
{
document->saveToFile("../roger.oe");
}
}
else if (!strcmp(key_name, "o") && mods == GLFW_MOD_CONTROL)
{
if (document)
{
document->loadFromFile("../roger.oe");
}
}
else if (!strcmp(key_name, "z") && mods == (GLFW_MOD_CONTROL|GLFW_MOD_SHIFT))
{
if (controller)
{
controller->redoAction();
}
}
else if (mods == 0)
{
{
if (controller)
{
controller->toggleCloseSelectedCurve();
}
}
else if (!strcmp(key_name, "r"))
{
if (editionState == TraceSubcurve)
{
controller->editActionAddSubcurvePosSwitchDir();
{
controller->editActionSetSubcurvePosSwitchDir();
}
//TODO create an action to delete all selected stitches
std::list<OE_stitchs*>::iterator it=selectedStitches.begin();
controller->addAction(new OE_actionDelStitch(*it));
std::list<OE_stitchs*>::iterator it=selectedStitches.begin();
if (it != selectedStitches.end())
{
it = 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);
}
}
else if (key == GLFW_KEY_LEFT)
{
std::list<OE_stitchs*>::iterator it=selectedStitches.begin();
if (it != selectedStitches.end())
{
it = 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);
}
}
}
if (curScreen == command && key == GLFW_KEY_SPACE)
{
run=true;
}
if (key == GLFW_KEY_F12)
{
curScreen = command;
setDisplayStyle(commandStyle);
else
{
curScreen = edit;
setDisplayStyle(editStyle);
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
}
else if (!strcmp(key_name, "l"))
{
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;
}
}
else if (!strcmp(key_name, "b"))
{
if (controller)
{
controller->newBirailStitch(false, false, 0,0,0.7);
document->selectedStitchs.push_back(controller->getBirailStitch(-1));
curJoincurve = controller->getBirailStitch(-1)->getJoincurve1();
closestCurve = controller->getClosestCurve(absMouse, editClosestPoint);
editionState = NewSubcurve;
joincurve_id = 1;
}
}
else if (!strcmp(key_name, "f"))
controller->newFillStitch(1.5,0.3,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;
}
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
}
else if (key == GLFW_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 (!strcmp(key_name, "r"))
{
if (editionState == TraceSubcurve)
{
controller->editActionAddSubcurvePosSwitchDir();
}
else if (editionState == MoveSubcurve)
{
controller->editActionSetSubcurvePosSwitchDir();
}
}
else if (key == GLFW_KEY_KP_ADD)
{
if (mods == GLFW_MOD_CONTROL)
controller->addAction(new OE_actionScaleSelectedStitchLen(1.1));
controller->addAction(new OE_actionScaleSelectedStitchWidth(1.1));
controller->addAction(new OE_actionScaleSelectedStitchLen(1/1.1));
controller->addAction(new OE_actionScaleSelectedStitchWidth(1/1.1));
controller->addAction(new OE_actionSetSelectedStitchPattern(controller->getPattern(0)));
controller->addAction(new OE_actionSetSelectedStitchPattern(controller->getPattern(1)));
controller->addAction(new OE_actionSetSelectedStitchPattern(controller->getPattern(2)));
controller->addAction(new OE_actionSetSelectedStitchPattern(controller->getPattern(3)));
controller->addAction(new OE_actionSetSelectedStitchPattern(controller->getPattern(4)));
controller->addAction(new OE_actionSetSelectedStitchPattern(controller->getPattern(5)));
controller->addAction(new OE_actionSetSelectedStitchPattern(controller->getPattern(6)));
controller->addAction(new OE_actionSetSelectedStitchPattern(controller->getPattern(7)));
controller->addAction(new OE_actionSetSelectedStitchPattern(controller->getPattern(8)));
3dsman
committed
3dsman
committed
{
zoomSelection();
3dsman
committed
}
//OE_display::key( key, scancode, action, mods);
}
selectedCurves.clear();
selectedStitches.clear();
vector_2d clicAbsMouse = viewPos+(clicOldMouse-vector_2d(width,height)/2)*zoom*2;
float tmpXMin, tmpYMin, tmpXMax, tmpYMax;
std::list<OE_pointcurve*>::iterator curve = document->curves.begin();
while (curve != document->curves.end())
{
BoundingBox box = (*curve)->getBound();
if ((box.getMin().x>minf(clicAbsMouse.x,absMouse.x))
&&(box.getMax().x<maxf(clicAbsMouse.x,absMouse.x))
&&(box.getMin().y>minf(clicAbsMouse.y,absMouse.y))
&&(box.getMax().y<maxf(clicAbsMouse.y,absMouse.y)))
{
selectedCurves.push_back(*curve);
}
curve++;
}
std::list<OE_stitchs*>::iterator stitch = document->stitchs.begin();
while (stitch != document->stitchs.end())
{
BoundingBox box = (*stitch)->getBound();
if ((box.getMin().x>minf(clicAbsMouse.x,absMouse.x))
&&(box.getMax().x<maxf(clicAbsMouse.x,absMouse.x))
&&(box.getMin().y>minf(clicAbsMouse.y,absMouse.y))
&&(box.getMax().y<maxf(clicAbsMouse.y,absMouse.y)))
{
selectedStitches.push_back(*stitch);
}
stitch++;
}
bool OE_interfaceDisplay::checkPicking()
{
{
editionState = MoveSelection;
return controller->addAction(new OE_actionMoveSelection(vector_2d(0,0)));
}
{
editionState = ScaleSelection;
return controller->addAction(new OE_actionScaleSelection(vector_2d(1,1), controller->getSelectionBoundingBox().getCenter()));
}
OE_linestitch* tmpLineStitch = dynamic_cast<OE_linestitch*>(selControlStitch);
if (tmpLineStitch)
{
{
// get the corresponding subcurve
editSubcurve = tmpLineStitch->getJoincurve()->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;
}
editionState = OffsetWidthLinestitch;
controller->addAction(new OE_actionSetLineStitchWidth(tmpLineStitch, tmpLineStitch->getWidth()));
return true;
}
}
OE_birailstitch* tmpBirailStitch = dynamic_cast<OE_birailstitch*>(selControlStitch);
if (tmpBirailStitch && (selControlType == 0 || selControlType == 1))
{
// get the corresponding subcurve
if (selControlType == 0)
{
editSubcurve = tmpBirailStitch->getJoincurve1()->getCurve(selControlIndex/2);
}
else if (selControlType == 1)
{
editSubcurve = tmpBirailStitch->getJoincurve2()->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;
}
3dsman
committed
OE_fillstitch* tmpFillStitch = dynamic_cast<OE_fillstitch*>(selControlStitch);
if (tmpFillStitch && (selControlType == 0 || selControlType == 1))
{
// get the corresponding subcurve
if (selControlType == 0)
{
editSubcurve = tmpFillStitch->getJoincurve()->getCurve(selControlIndex/2);
}
else if (selControlType == 1)
{
editionState = MovePointstitch;
//edit gridpoint
controller->addAction(new OE_actionMovePointFillStitch(tmpFillStitch, selControlIndex, absMouse));
return true;
}
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;
}
3dsman
committed
OE_linkstitch* tmpLinkStitch = dynamic_cast<OE_linkstitch*>(selControlStitch);
if (tmpLinkStitch && (selControlType == 0 || selControlType == 1 || selControlType == 2))
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;
}
selControlStitch = 0;
}
OE_pointcurve* tmpPointCurve = dynamic_cast<OE_pointcurve*>(selControlCurve);
editionState = MovePointcurve;
return controller->addAction(new OE_actionMovePointCurve(tmpPointCurve,
selControlIndex+1,
vector_2d(0,0)));
}
selControlCurve = 0;
/** \brief set selection
*
* \return true if all is ok
*
*/
bool OE_interfaceDisplay::drawPicking()
GLuint selectBuf[64];
GLint hits;
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
hits = glRenderMode(GL_RENDER);
selectedCurves.clear();
selectedStitches.clear();
toolAction = 0;
//std::cout<<"hits : "<<"\r\n";
ptr = (GLuint *) selectBuf;
{
bool recognized = false;
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)
if (selectedCurves.size())
{
if (modState&GLFW_MOD_CONTROL)
{
controller->unselectCurves(selectedCurves);
}
else
{
controller->selectCurves(selectedCurves, !(modState&GLFW_MOD_SHIFT));
}
}
if (selectedStitches.size())
{
if (modState&GLFW_MOD_CONTROL)
{
controller->unselectStitches(selectedStitches);
}
else
{
controller->selectStitches(selectedStitches, !(modState&GLFW_MOD_SHIFT));
}
}
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)
glColor4d(0.8f, 0.0f, 0.0f, 1.0f);
glColor4d(0.0f, 0.8f, 0.0f, 1.0f);
glVertex2f(editClosestPoint.v.x,editClosestPoint.v.y);
glEnd();
// draw the cursor cross
glLineWidth(1.5);
glBegin(GL_LINES);
if (editionState)
glColor4d(0.8f, 0.0f, 0.0f, 0.5f);
glColor4d(0.0f, 0.8f, 0.0f, 0.5f);
else
{
style->cursorColor.gl();
}
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);
style->cursorColor.gl();
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);
style->cursorColor.gl();
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;
}