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 (editSubcurve) //if we are working on a defined subcurve get the closest point on it
{
editClosestPoint = controller->getClosestPoint(editSubcurve->getCurve(), absMouse);
}
if (editionState == NewSubcurve) //if we must find the closest subcurve (get the closest point on it too)
closestCurve = controller->getClosestCurve(absMouse, editClosestPoint);
if (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);
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 && selControlType == 0)||
(tmpFillStitch && selControlType == 0)||
(tmpBirailStitch && (selControlType == 0 || selControlType == 1)))
{
if (editionState == NewSubcurve)
{
editionState = TraceSubcurve;
if (oldClosestPoint.t>editClosestPoint.t) controller->editActionAddSubcurvePosSwitchDir();
}
if (editionState == TraceSubcurve)
{
controller->editActionAddSubcurvePosEnd(editClosestPoint.t);
}
else
{
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 == TraceSubcurve)
{
editionState = NewSubcurve;
editSubcurve = 0;
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)
{
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
290
291
292
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 != selectedStitches.end())
{
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_F5)
{
if (curScreen == edit)
{
curScreen = command;
setDisplayStyle(commandStyle);
else
{
curScreen = edit;
setDisplayStyle(editStyle);
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
}
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"))
{
if (controller)
{
controller->newFillStitch(50,50,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;
}
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
}
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_actionScaleSelectedLineStitchLen(1.1));
controller->addAction(new OE_actionScaleSelectedBirailStitchLen(1.1));
}
controller->addAction(new OE_actionScaleSelectedLineStitchWidth(1.1));
controller->addAction(new OE_actionScaleSelectedLineStitchLen(1/1.1));
controller->addAction(new OE_actionScaleSelectedBirailStitchLen(1/1.1));
}
controller->addAction(new OE_actionScaleSelectedLineStitchWidth(1/1.1));
controller->addAction(new OE_actionSetSelectedLineStitchPattern(controller->getPattern(0)));
controller->addAction(new OE_actionSetSelectedLineStitchPattern(controller->getPattern(1)));
controller->addAction(new OE_actionSetSelectedLineStitchPattern(controller->getPattern(2)));
controller->addAction(new OE_actionSetSelectedLineStitchPattern(controller->getPattern(3)));
controller->addAction(new OE_actionSetSelectedLineStitchPattern(controller->getPattern(4)));
controller->addAction(new OE_actionSetSelectedLineStitchPattern(controller->getPattern(5)));
controller->addAction(new OE_actionSetSelectedLineStitchPattern(controller->getPattern(6)));
{
controller->addAction(new OE_actionSetSelectedLineStitchPattern(controller->getPattern(7)));
{
controller->addAction(new OE_actionSetSelectedLineStitchPattern(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_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();
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();
// 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
{
glColor4d(0.0f, 0.0f, 0.0f, 0.3f);
}
glVertex2f(absMouse.x,-10000);
glVertex2f(absMouse.x,10000);
glVertex2f(-10000,absMouse.y);
glVertex2f(10000,absMouse.y);
glEnd();
//cursor select zone
glLineWidth(2);
glBegin(GL_LINE_LOOP);
glColor4d(0.0f, 0.0f, 0.0f, 0.3f);
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);
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;
}