Skip to content
OE_interfaceDisplay.cpp 15.2 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>

#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_actionsMetaLineStitchs.h"
#include "actions/OE_actionsBirailStitchs.h"
#include "actions/OE_actionsSelection.h"
#include "actions/OE_actionsThreads.h"

OE_interfaceDisplay::OE_interfaceDisplay()
{
    editDisplay = new OE_editDisplay();
    commandDisplay = new OE_commandDisplay();

    curDisplay = editDisplay;
}

OE_interfaceDisplay::OE_interfaceDisplay(OE_document document)
{
    editDisplay = new OE_editDisplay();
    editDisplay->setDocument(&document);
    commandDisplay = new OE_commandDisplay();
    commandDisplay->setDocument(&document);

    curDisplay = editDisplay;
}

OE_interfaceDisplay::~OE_interfaceDisplay()
{
    delete editDisplay;
    delete commandDisplay;
}


bool OE_interfaceDisplay::setDocument(OE_document * document)
{

    this->document = document;
    if(document)
    {
        editDisplay->setDocument(document);
        commandDisplay->setDocument(document);
    }
    return true;
}


bool OE_interfaceDisplay::setController(OE_controller* controller)
{
    this->controller = controller;
    if(controller)
    {
        if (editDisplay) editDisplay->setController(controller);
        if (commandDisplay) commandDisplay->setController(controller);
    }
    return true;
}

void OE_interfaceDisplay::showAll()
{
    if (curDisplay) curDisplay->showAll();
}

void OE_interfaceDisplay::mouse_Pos(double x, double y)
{
    OE_display::mouse_Pos( x, y);
    if (curDisplay) curDisplay->mouse_Pos(x, y);
    if ((selControlCurve)&&(selControlType == 0))
        controller->editLastAction(vector_2d((mouseX - clicOldMouseX)*zoom*2,(mouseY - clicOldMouseY)*zoom*2));

    if ((selControlStitch)&&(selControlType == 0))
    {

        OE_metaLinestitch* tmpMetaLineStitch = dynamic_cast<OE_metaLinestitch*>(selControlStitch);
        vector_2dt pos = tmpMetaLineStitch->getSubCurve(selControlIndex/2)->getCurve()->closestPoint(vector_2d(absMouseX,absMouseY));

        std::cout<<"pxet1 "<<absMouseX<<" "<<absMouseY<<"  "<<pos.t<<" "<<selControlIndex<<std::endl;
        controller->editLastAction(pos.t);
        //std::cout<<"pxet1"<<std::endl;
    }

}

void OE_interfaceDisplay::mouse_Button(int button, int action, int mods)
{
    if (curDisplay) curDisplay->mouse_Button(button, action, mods);
3dsman's avatar
3dsman committed
    if((curDisplay == editDisplay)&&(button == GLFW_MOUSE_BUTTON_LEFT)&&(action==GLFW_PRESS))
    {
        clicOldMouseX = mouseX;
        clicOldMouseY = mouseY;
        selection = true;
3dsman's avatar
3dsman committed
    }
    if((curDisplay == editDisplay)&&(button == GLFW_MOUSE_BUTTON_LEFT)&&(action==GLFW_RELEASE))
    {
        if(selection)
        {
            if ((abs(mouseX-clicOldMouseX)>5)||(abs(mouseY-clicOldMouseY)>5))
                selectBox();

            selectApply(selectedCurves, selectedStitches);
            selection = false;
        }
        if(selControlCurve)selControlCurve = 0;
        if(selControlStitch)selControlStitch = 0;
}

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)
{
    if((action == GLFW_PRESS)&&(curDisplay == editDisplay))
    {
        if ((key == GLFW_KEY_Z)&&(mods == GLFW_MOD_CONTROL))
        {
            if (controller) controller->undoAction();
        }

        if ((key == GLFW_KEY_Z)&&(mods == GLFW_MOD_CONTROL+GLFW_MOD_SHIFT))
        {
            if (controller) controller->redoAction();
        }
    }
    if((action == GLFW_RELEASE)&&(key == GLFW_KEY_F5))
    {
        if(curDisplay == editDisplay)
        {
            if (controller) controller->generateInstructions();
            curDisplay = commandDisplay;
        }
        else
            curDisplay = editDisplay;
    }

    curDisplay->key( key,  scancode,  action,  mods);
3dsman's avatar
3dsman committed

bool OE_interfaceDisplay::selectBox()
{
    selectedCurves.clear();
    selectedStitches.clear();
3dsman's avatar
3dsman committed

    float clicAbsMouseX = cx+(clicOldMouseX-width/2)*zoom*2;
    float clicAbsMouseY = cy+(clicOldMouseY-height/2)*zoom*2;
    float tmpXMin, tmpYMin, tmpXMax, tmpYMax;

    std::list<OE_curve*>::iterator curve = document->curves.begin();
    while (curve != document->curves.end())
    {
         (*curve)->getBound(&tmpXMin, &tmpYMin, &tmpXMax, &tmpYMax);
         if ((tmpXMin>minf(clicAbsMouseX,absMouseX))
             &&(tmpXMax<maxf(clicAbsMouseX,absMouseX))
             &&(tmpYMin>minf(clicAbsMouseY,absMouseY))
             &&(tmpYMax<maxf(clicAbsMouseY,absMouseY)))
             selectedCurves.push_back(*curve);
         curve++;
    }

    std::list<OE_stitchs*>::iterator stitch = document->stitchs.begin();
    while (stitch != document->stitchs.end())
    {
         (*stitch)->getBound(&tmpXMin, &tmpYMin, &tmpXMax, &tmpYMax);
         if ((tmpXMin>minf(clicAbsMouseX,absMouseX))
             &&(tmpXMax<maxf(clicAbsMouseX,absMouseX))
             &&(tmpYMin>minf(clicAbsMouseY,absMouseY))
             &&(tmpYMax<maxf(clicAbsMouseY,absMouseY)))
             selectedStitches.push_back(*stitch);
         stitch++;
    }

bool OE_interfaceDisplay::checkPicking()
{
    if(selControlStitch)
    {

        OE_metaLinestitch* tmpMetaLineStitch = dynamic_cast<OE_metaLinestitch*>(selControlStitch);

        selection = false;
        if ((tmpMetaLineStitch)&&(selControlType == 0))
        {
            std::cout<<"puk "<<std::endl;
            OE_subcurve* tmpcurve = tmpMetaLineStitch->getSubCurve(selControlIndex/2);
            vector_2dt pos = tmpcurve->getCurve()->closestPoint(vector_2d(absMouseX,absMouseY));

            controller->addAction(new OE_actionSetSubcurvePos( tmpcurve, selControlIndex%2, pos.t));
            std::cout<<"puk "<<std::endl;

            //controller->addAction(new OE_actionSetMetaLineStitchSub( tmpMetaLineStitch, selControlIndex, pos.t));
            return true;
        }
        selControlStitch = 0;
    }

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

        selection = false;
        if ((tmpPointCurve)&&(selControlType == 0))
        {
            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::select()
{
    GLuint selectBuf[64];
    GLint hits;

    glSelectBuffer(64, selectBuf);

    draw(true);
    hits = glRenderMode(GL_RENDER);

    selectedCurves.clear();
    selectedStitches.clear();

    GLuint i, nb_names, name, *ptr;

    std::cout<<"hits : "<<std::endl;
    ptr = (GLuint *) selectBuf;
    for (GLuint i = 0; i < hits; i++) {  //  for each hit

        GLuint names = *ptr;
        if (names==4) //if name count correspond to a sub element (like control point)
            ptr+=3; //jump near and far info and goto first index
            if (*ptr == 1) //stitches index
            {
                ptr++;
                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();
                        /*
                    OE_metaLinestitch* tmpMetaLineStitch = dynamic_cast<OE_metaLinestitch*>(selControlStitch);

                    selection = false;
                    if ((tmpMetaLineStitch)&&(selControlType == 0))
                    {
                        return controller->addAction(new OE_actionSetMetaLineStitchSub( tmpMetaLineStitch, selControlIndex, vector_2d(absMouseX,absMouseY)));
                    }
                    selControlStitch = 0;
                    */
                    return true;
                }else
                    ptr+=4;
            }else if (*ptr == 2) //curves index
            {
                ptr++;
                if(*ptr < document->selectedCurves.size())
                {
                    std::list<OE_curve*>::iterator it = document->selectedCurves.begin();
                    std::advance(it, *ptr++);
                    selControlCurve = *it;
                    selControlType = *ptr++;
                    selControlIndex = *ptr++;

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

                    selection = false;
                    if ((tmpPointCurve)&&(selControlType == 0))
                    {
                        return controller->addAction(new OE_actionMovePointCurve( tmpPointCurve, selControlIndex + 1, vector_2d(0,0)));
                    }
                    selControlCurve = 0;
                    return true;
                }else
                    ptr+=4;
            }

        }else if (names==2) //if name count correspond to a simple element
        {
            ptr+=3; //jump near and far info and goto first index
            if (*ptr == 0) //tools index
            {
                ptr++;
                if(*ptr == 0)
                    std::cout<<"    zero ";
                ptr++;
            }else if (*ptr == 1) //stitches index
            {
                ptr++;
                std::cout<<"    stitch "<<*ptr;
                if (document->stitchs.size() > *ptr)
                {
                    std::list<OE_stitchs*>::iterator it = document->stitchs.begin();
                    std::advance(it, *ptr);
                    selectedStitches.push_back(*it);
                }
            }else if (*ptr == 2) //curves index
            {
                ptr++;
                std::cout<<"    curve "<<*ptr;
                if (document->curves.size() > *ptr)
                {
                    std::list<OE_curve*>::iterator it = document->curves.begin();
                    std::advance(it, *ptr);
                    selectedCurves.push_back(*it);
                }
                ptr++;
            }else
            {
                ptr++;
                std::cout<<"    unrecognized item "<<*ptr;ptr++;
            }

            std::cout<<std::endl;
        }
        else
        {
            std::cout<<" strange hit! probably a bug : "<< names<<std::endl; ptr+=3;
            std::cout<<"   names are ";
            for (GLuint j = 0; j < names; j++) { /*  for each name */
               std::cout<< *ptr<<" ";
               ptr++;
            }
            std::cout<<std::endl;
        }
    }
3dsman's avatar
3dsman committed

    return true;
}

bool OE_interfaceDisplay::selectApply(std::list<OE_curve*> 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));

/** \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 (select)
    {
        glRenderMode(GL_SELECT);
        //Init of name stack
        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;

    if(select)
        glOrtho(absMouseX-5*zoom, absMouseX+5*zoom, absMouseY+5*zoom, absMouseY-5*zoom, -1, 1);
    else
        glOrtho(cx-wzoom, cx+wzoom, cy+hzoom, cy-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 (document && curDisplay)
    {
        if(select && (curDisplay == editDisplay))
            editDisplay->select(document->selectedCurves, document->selectedStitchs);
        else
            curDisplay->draw();
    }

    if(!select)
    {
        // cursor cross
3dsman's avatar
3dsman committed
        glLineWidth(1.5);
        glBegin(GL_LINES);
3dsman's avatar
3dsman committed
            glColor4d(0.0f, 0.0f, 0.0f, 0.3f);
            glVertex2f(absMouseX,-10000);
            glVertex2f(absMouseX,10000);
3dsman's avatar
3dsman committed
            glVertex2f(-10000,absMouseY);
            glVertex2f(10000,absMouseY);
3dsman's avatar
3dsman committed

        //cursor select zone
        glLineWidth(2);
        glBegin(GL_LINE_STRIP);
            glColor4d(0.0f, 0.0f, 0.0f, 0.3f);
            glVertex2f(absMouseX-5*zoom,absMouseY+5*zoom);
            glVertex2f(absMouseX-5*zoom,absMouseY-5*zoom);
            glVertex2f(absMouseX+5*zoom,absMouseY-5*zoom);
            glVertex2f(absMouseX+5*zoom,absMouseY+5*zoom);
            glVertex2f(absMouseX-5*zoom,absMouseY+5*zoom);
        glEnd();

3dsman's avatar
3dsman committed
        if(selection)
        {
            float clicAbsMouseX = cx+(clicOldMouseX-width/2)*zoom*2;
            float clicAbsMouseY = cy+(clicOldMouseY-height/2)*zoom*2;
            glLineWidth(2);
            glBegin(GL_LINE_STRIP);
                glColor4d(0.0f, 0.0f, 0.0f, 0.3f);
                glVertex2f(absMouseX,clicAbsMouseY);
                glVertex2f(absMouseX,absMouseY);
                glVertex2f(clicAbsMouseX,absMouseY);
                glVertex2f(clicAbsMouseX,clicAbsMouseY);
                glVertex2f(absMouseX,clicAbsMouseY);
            glEnd();
        }