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"
#include "actions/OE_actionsSelection.h"
#include "actions/OE_actionsThreads.h"
#define TOOLSSELID 0
#define STITCHSSELID 1
#define CURVESSELID 2
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;
curDisplay = new OE_display();
curDisplay->setDisplayStyle(editStyle);
}
OE_interfaceDisplay::~OE_interfaceDisplay()
{
delete curDisplay;
}
bool OE_interfaceDisplay::setDocument(OE_document * document)
{
this->document = document;
if(document)
curDisplay->setDocument(document);
return true;
}
bool OE_interfaceDisplay::setController(OE_controller* controller)
{
this->controller = controller;
if((controller)&&(curDisplay))
curDisplay->setController(controller);
return true;
}
void OE_interfaceDisplay::showAll()
{
if (curDisplay) curDisplay->showAll();
}
void OE_interfaceDisplay::mouse_Pos(double x, double y)
{
3dsman
committed
vector_2dt oldClosestPoint = editClosestPoint;
if (curDisplay) curDisplay->mouse_Pos(x, y);
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;
}
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);
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))||((tmpBirailStitch)&&((selControlType == 0)||(selControlType == 1))))
{
if (editionState == NewSubcurve)
{
editionState = TraceSubcurve;
if(oldClosestPoint.t>editClosestPoint.t) controller->editActionAddSubcurvePosSwitchDir();
}
3dsman
committed
if (editionState == TraceSubcurve)
{
controller->editActionAddSubcurvePosEnd(editClosestPoint.t);
3dsman
committed
}
else
controller->editActionSetSubcurvePos(editClosestPoint.t);
}
void OE_interfaceDisplay::mouse_Button(int button, int action, int mods)
{
modState = mods;
if (curDisplay) curDisplay->mouse_Button(button, action, mods);
if((curScreen == edit)&&(button == GLFW_MOUSE_BUTTON_LEFT)&&(action==GLFW_PRESS))
if(editionState == NewSubcurve)
{
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;
if(editionState == None)
picking();
if(editionState == None)
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(editionState == Selection)
{
if ((mouse-clicOldMouse).len()>5)
selectBox();
selectApply(selectedCurves, selectedStitches);
editionState = None;
}
3dsman
committed
if (editionState == TraceSubcurve)
3dsman
committed
editionState = NewSubcurve;
return;
}
if((editionState == MoveSubcurve)||(editionState == MovePointcurve)||(editionState == MoveSelection)||(editionState = ScaleSelection))
editionState = None;
}
void OE_interfaceDisplay::scroll(double xoffset, double yoffset)
{
if (curDisplay) curDisplay->scroll(xoffset, yoffset);
}
void OE_interfaceDisplay::resize(int width, int height)
{
if (curDisplay) curDisplay->resize(width, height);
}
void OE_interfaceDisplay::key(int key, int scancode, int action, int mods)
{
const char* key_name = glfwGetKeyName(key, 0);
if (!key_name) key_name = " ";
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();
if (editionState == TraceSubcurve)
{
controller->editActionAddSubcurvePosSwitchDir();
}else if (editionState == MoveSubcurve)
{
controller->editActionSetSubcurvePosSwitchDir();
}
}else if (key == GLFW_KEY_DELETE)
{
//TODO create an action to delete all selected stitches
std::list<OE_stitchs*>::iterator it=selectedStitches.begin();
controller->addAction(new OE_actionDelStitch(*it));
}else if (key == GLFW_KEY_RIGHT)
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;
curDisplay->setDisplayStyle(commandStyle);
else
{
curScreen = edit;
curDisplay->setDisplayStyle(editStyle);
}
3dsman
committed
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);
3dsman
committed
editionState = NewSubcurve;
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);
3dsman
committed
editionState = NewSubcurve;
}else if(key == GLFW_KEY_ENTER)
3dsman
committed
if(editionState == NewSubcurve)
3dsman
committed
editionState = None;
curJoincurve = 0;
}else
{
curJoincurve = controller->getBirailStitch(-1)->getJoincurve2();
closestCurve = controller->getClosestCurve(absMouse, editClosestPoint);
joincurve_id -= 1;
}
{
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));
}
else
controller->addAction(new OE_actionScaleSelectedLineStitchWidth(1.1));
}else if (key == GLFW_KEY_KP_SUBTRACT)
{
if(mods == GLFW_MOD_CONTROL)
controller->addAction(new OE_actionScaleSelectedLineStitchLen(1/1.1));
controller->addAction(new OE_actionScaleSelectedBirailStitchLen(1/1.1));
}
else
controller->addAction(new OE_actionScaleSelectedLineStitchWidth(1/1.1));
}else if (key == GLFW_KEY_KP_1)
{
controller->addAction(new OE_actionSetSelectedLineStitchPattern(controller->getPattern(0)));
}else if (key == GLFW_KEY_KP_2)
{
controller->addAction(new OE_actionSetSelectedLineStitchPattern(controller->getPattern(1)));
}else if (key == GLFW_KEY_KP_3)
{
controller->addAction(new OE_actionSetSelectedLineStitchPattern(controller->getPattern(2)));
}else if (key == GLFW_KEY_KP_4)
{
controller->addAction(new OE_actionSetSelectedLineStitchPattern(controller->getPattern(3)));
}else if (key == GLFW_KEY_KP_5)
{
controller->addAction(new OE_actionSetSelectedLineStitchPattern(controller->getPattern(4)));
}else if (key == GLFW_KEY_KP_6)
{
controller->addAction(new OE_actionSetSelectedLineStitchPattern(controller->getPattern(5)));
controller->addAction(new OE_actionSetSelectedLineStitchPattern(controller->getPattern(6)));
}else if (key == GLFW_KEY_KP_8)
{
controller->addAction(new OE_actionSetSelectedLineStitchPattern(controller->getPattern(7)));
}else if (key == GLFW_KEY_KP_9)
{
controller->addAction(new OE_actionSetSelectedLineStitchPattern(controller->getPattern(8)));
3dsman
committed
if(key == GLFW_KEY_HOME)
{
curDisplay->zoomSelection();
3dsman
committed
}
}
//curDisplay->key( key, scancode, action, mods);
}
selectedCurves.clear();
selectedStitches.clear();
vector_2d clicAbsMouse = viewPos+(clicOldMouse-vector_2d(width,height)/2)*zoom*2;
3dsman
committed
std::list<OE_pointcurve*>::iterator curve = document->curves.begin();
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()
{
if(toolAction)
if(toolAction == 1)
{
editionState = MoveSelection;
return controller->addAction(new OE_actionMoveSelection(vector_2d(0,0)));
}
if(toolAction == 2)
{
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)
{
if(selControlType == 0)
{
// 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;
}
if ((selControlType == 1)&&(selControlIndex==0))
{
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;
selControlStitch = 0;
}
if(selControlCurve)
OE_pointcurve* tmpPointCurve = dynamic_cast<OE_pointcurve*>(selControlCurve);
if ((tmpPointCurve)&&(selControlType == 0))
{
editionState = MovePointcurve;
return controller->addAction(new OE_actionMovePointCurve( tmpPointCurve, selControlIndex + 1, vector_2d(0,0)));
/** \brief set selection
*
* \return true if all is ok
*
*/
bool OE_interfaceDisplay::picking()
{
GLuint selectBuf[64];
GLint hits;
glSelectBuffer(64, selectBuf);
draw(true);
hits = glRenderMode(GL_RENDER);
selectedCurves.clear();
selectedStitches.clear();
toolAction = 0;
for (GLuint i = 0; i < hits; i++) // for each hit
{
ptr+=3; //jump near and far info and goto first index
if (*ptr == TOOLSSELID) //tools index
{
std::cout<<" tool"<< std::endl;
ptr++;
if(*ptr == 0)
std::cout<<" select tools"<< std::endl;
ptr++;
if(*ptr == 0)
{
std::cout<<" move tool"<< std::endl;
toolAction = 1;
checkPicking();
return true;
}
if(*ptr == 1)
{
std::cout<<" scale tool"<< std::endl;
toolAction = 2;
checkPicking();
return true;
}
return false;
//ptr++;
}else if (*ptr == STITCHSSELID) //stitches index
std::cout<<" stitch"<< std::endl;
ptr++;
if (names==2) //if name count correspond to a stitch
std::cout<<" select"<< std::endl;
if (document->stitchs.size() > *ptr)
{
std::list<OE_stitchs*>::iterator it = document->stitchs.begin();
std::advance(it, *ptr);
selectedStitches.push_back(*it);
return true;
}
return false;
//ptr++;
} else if (names==4) //if name count correspond to a sub element of stitch (like control point)
{
std::cout<<" sub element"<< std::endl;
if(*ptr < document->selectedStitchs.size())
{
std::list<OE_stitchs*>::iterator it = document->selectedStitchs.begin();
std::advance(it, *ptr++);
selControlStitch = *it;
selControlType = *ptr++;
selControlIndex = *ptr++;
checkPicking();
return true;
}
return false;
//ptr+=4;
}else if (*ptr == CURVESSELID) //curves index
{
std::cout<<" curve"<< std::endl;
ptr++;
if (names==2) //if name count correspond to a curve
std::cout<<" select"<< std::endl;
if (document->curves.size() > *ptr)
{
std::list<OE_pointcurve*>::iterator it = document->curves.begin();
std::advance(it, *ptr);
selectedCurves.push_back(*it);
return true;
}
return false;
//ptr++;
} else if (names==4) //if name count correspond to a sub element of curve (like control point)
{
std::cout<<" sub element"<< std::endl;
if(*ptr < document->selectedCurves.size())
{
std::cout<<" curve id "<<*ptr << std::endl;
3dsman
committed
std::list<OE_pointcurve*>::iterator it = document->selectedCurves.begin();
std::advance(it, *ptr++);
selControlCurve = *it;
std::cout<<" control type "<<*ptr <<std::endl;
std::cout<<" control id "<<*ptr << std::endl;
return false;
//ptr+=4;
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();
}
/** \brief draw the document on screen
*
* \return true if all is ok
*
*/
bool OE_interfaceDisplay::draw()
{
draw(false);
}
/** \brief draw the document on screen
*
* \return true if all is ok
*
*/
bool OE_interfaceDisplay::draw(bool select)
{
if (run) controller->sendInstPoint();
if (select)
{
glRenderMode(GL_SELECT);
glInitNames();
glPushName(0);
}
float wzoom, hzoom;
glViewport(0, 0, width, height);
glClearColor(220.0f/255.0f, 220.0f/255.0f, 220.0f/255.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_TEXTURE_2D);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
wzoom = (float)width*zoom;
hzoom = (float)height*zoom;
glOrtho(absMouse.x-7*zoom, absMouse.x+7*zoom, absMouse.y+7*zoom, absMouse.y-7*zoom, -1, 1);
glOrtho(viewPos.x-wzoom, viewPos.x+wzoom, viewPos.y+hzoom, viewPos.y-hzoom, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_DEPTH_TEST);
glColor4ub(255,255,255,255);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
if(select && (curScreen == edit))
curDisplay->select(document->selectedCurves, document->selectedStitchs);
else
curDisplay->draw();
}
if(!select)
{
if (editionState==NewSubcurve)
{
// Points
glPointSize(5.0f);
glBegin(GL_POINTS);
if (joincurve_id == 0)
glColor4d(0.8f, 0.0f, 0.0f, 1.0f);
else
glColor4d(0.0f, 0.8f, 0.0f, 1.0f);
glVertex2f(editClosestPoint.v.x,editClosestPoint.v.y);
if (editionState)
{
if (joincurve_id == 0)
glColor4d(0.8f, 0.0f, 0.0f, 0.5f);
else
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);
//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);
if(editionState == Selection)
vector_2d clicAbsMouse = viewPos+(clicOldMouse-vector_2d(width,height)/2)*zoom*2;
glLineWidth(2);
glBegin(GL_LINE_STRIP);
glColor4d(0.0f, 0.0f, 0.0f, 0.3f);
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);