Merge branch 'statesaving' of github.com:libremapping/libremapping into statesaving

This commit is contained in:
Alexandre Quessy
2014-01-05 18:26:08 -05:00
168 changed files with 37486 additions and 443 deletions

View File

@@ -24,13 +24,17 @@
#include "Facade.h"
#include <sstream>
MainWindow* MainWindow::instance = 0;
MainWindow::MainWindow()
{
mappingManager = new MappingManager;
_facade = new Facade(mappingManager, this);
currentPaintId = -1;
currentMappingId = -1;
currentPaintId = 0;
currentMappingId = 0;
_hasCurrentPaint = false;
_hasCurrentMapping = false;
createLayout();
@@ -49,8 +53,14 @@ MainWindow::MainWindow()
MainWindow& MainWindow::getInstance()
{
static MainWindow instance;
return instance;
Q_ASSERT(instance);
return *instance;
}
void MainWindow::setInstance(MainWindow* inst)
{
instance = inst;
}
MainWindow::~MainWindow()
@@ -63,42 +73,57 @@ void MainWindow::handleSourceItemSelectionChanged()
{
std::cout << "selection changed" << std::endl;
QListWidgetItem* item = sourceList->currentItem();
int idx = item->data(Qt::UserRole).toInt();
uint idx = item->data(Qt::UserRole).toUInt();
std::cout << "idx=" << idx << std::endl;
setCurrentPaint(idx);
// Reconstruct shape item list.
shapeList->clear();
setCurrentMapping(-1); // de-select current mapping to avoid being stuck with the last selection
// Retrieve all mappings associated to paint.
std::map<int, Mapping::ptr> mappings = getMappingManager().getPaintMappings(idx);
for (std::map<int, Mapping::ptr>::iterator it = mappings.begin(); it != mappings.end(); ++it)
{
addMappingItem(it->first);
}
removeCurrentMapping();
// Update canvases.
sourceCanvas->update();
destinationCanvas->update();
updateAll();
//sourceCanvas->switchImage(idx);
//sourceCanvas->repaint();
//destinationCanvas->repaint();
}
void MainWindow::handleShapeItemSelectionChanged()
void MainWindow::handleLayerItemSelectionChanged()
{
std::cout << "shape selection changed" << std::endl;
QListWidgetItem* item = shapeList->currentItem();
int idx = item->data(Qt::UserRole).toInt();
std::cout << "idx=" << idx << std::endl;
setCurrentMapping(idx);
sourceCanvas->update();
destinationCanvas->update();
QListWidgetItem* item = layerList->currentItem();
uint idx = item->data(Qt::UserRole).toUInt();
Mapping::ptr mapping = mappingManager->getLayerById(idx)->getMapping();
setCurrentPaint(mapping->getPaint()->getId());
setCurrentMapping(mapping->getId());
updateAll();
//sourceCanvas->switchImage(idx);
//sourceCanvas->repaint();
//destinationCanvas->repaint();
}
void MainWindow::handleLayerItemChanged(QListWidgetItem* item)
{
uint layerId = item->data(Qt::UserRole).toUInt();
Layer::ptr layer = mappingManager->getLayerById(layerId);
layer->setVisible(item->checkState() == Qt::Checked);
updateAll();
}
void MainWindow::handleLayerIndexesMoved()
{
qDebug() << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1Moved!!!" << endl;
std::vector<uint> newOrder;
for (int row=layerList->count()-1; row>=0; row--)
{
uint layerId = layerList->item(row)->data(Qt::UserRole).toUInt();
newOrder.push_back(layerId);
}
mappingManager->reorderLayers(newOrder);
updateAll();
}
//void MainWindow::handleSourceSelectionChanged(const QItemSelection& selection)
//{
// std::cout << "selection changed" << std::endl;
@@ -174,7 +199,7 @@ void MainWindow::import()
}
}
void MainWindow::addQuad()
void MainWindow::addMesh()
{
// FIXME: crashes if there is no current paint id. (if no paint exists)
@@ -188,13 +213,15 @@ void MainWindow::addQuad()
Q_CHECK_PTR(texture);
// Create input and output quads.
Shape::ptr outputQuad = Shape::ptr(Util::createQuadForTexture(texture.get(), sourceCanvas->width(), sourceCanvas->height()));
Shape::ptr inputQuad = Shape::ptr(Util::createQuadForTexture(texture.get(), sourceCanvas->width(), sourceCanvas->height()));
qDebug() << "adding mesh" << endl;
Shape::ptr outputQuad = Shape::ptr(Util::createMeshForTexture(texture.get(), sourceCanvas->width(), sourceCanvas->height()));
Shape::ptr inputQuad = Shape::ptr(Util::createMeshForTexture(texture.get(), sourceCanvas->width(), sourceCanvas->height()));
// Create texture mapping.
int mappingId = mappingManager->addMapping(Mapping::ptr(new TextureMapping(paint, outputQuad, inputQuad)));
Mapping::ptr mapping(new TextureMapping(paint, outputQuad, inputQuad));
uint layerId = mappingManager->addLayer(mapping);
addMappingItem(mappingId);
addLayerItem(layerId);
}
void MainWindow::addTriangle()
@@ -215,9 +242,10 @@ void MainWindow::addTriangle()
Shape::ptr inputTriangle = Shape::ptr(Util::createTriangleForTexture(texture.get(), sourceCanvas->width(), sourceCanvas->height()));
// Create texture mapping.
int mappingId = mappingManager->addMapping(Mapping::ptr(new TextureMapping(paint, inputTriangle, outputTriangle)));
Mapping::ptr mapping(new TextureMapping(paint, inputTriangle, outputTriangle));
uint layerId = mappingManager->addLayer(mapping);
addMappingItem(mappingId);
addLayerItem(layerId);
}
void MainWindow::about()
@@ -228,6 +256,8 @@ void MainWindow::about()
"</h2>"
"<p>Copyright &copy; 2013 Sofian Audry"
"<p>Copyright &copy; 2013 Alexandre Quessy"
"<p>Copyright &copy; 2013 Vasilis Liaskovitis"
"<p>Copyright &copy; 2013 Sylvain Cormier"
"<p>Libremapping is a free software for video mapping. "
"<p>Projection mapping, also known as video mapping and spatial augmented reality, "
"is a projection technology used to turn objects, often irregularly shaped, into "
@@ -260,16 +290,25 @@ void MainWindow::createLayout()
{
sourceList = new QListWidget;
sourceList->setSelectionMode(QAbstractItemView::SingleSelection);
sourceList->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
sourceList->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
sourceList->setMinimumWidth(SOURCE_LIST_MINIMUM_WIDTH);
shapeList = new QListWidget;
shapeList->setSelectionMode(QAbstractItemView::SingleSelection);
shapeList->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
layerList = new QListWidget;
layerList->setSelectionMode(QAbstractItemView::SingleSelection);
layerList->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
//layerList->setDragDropMode(QAbstractItemView::DragDrop);
layerList->setDefaultDropAction(Qt::MoveAction);
layerList->setDragDropMode(QAbstractItemView::InternalMove);
layerList->setMinimumWidth(LAYER_LIST_MINIMUM_WIDTH);
propertyPanel = new QStackedWidget;
propertyPanel->setDisabled(true);
propertyPanel->setMinimumWidth(PROPERTY_PANEL_MINIMUM_WIDTH);
sourceCanvas = new SourceGLCanvas;
destinationCanvas = new DestinationGLCanvas(0, sourceCanvas);
connect(sourceCanvas, SIGNAL(quadChanged()),
connect(sourceCanvas, SIGNAL(shapeChanged(Shape*)),
destinationCanvas, SLOT(updateCanvas()));
// connect(destinationCanvas, SIGNAL(imageChanged()),
@@ -284,19 +323,29 @@ void MainWindow::createLayout()
sourceCanvas->setMinimumSize(CANVAS_MINIMUM_WIDTH, CANVAS_MINIMUM_HEIGHT);
destinationCanvas->setMinimumSize(CANVAS_MINIMUM_WIDTH, CANVAS_MINIMUM_HEIGHT);
mainSplitter = new QSplitter(Qt::Horizontal);
mainSplitter = new QSplitter(Qt::Vertical);
resourceSplitter = new QSplitter(Qt::Horizontal);
resourceSplitter->addWidget(sourceList);
resourceSplitter->addWidget(layerList);
resourceSplitter->addWidget(propertyPanel);
canvasSplitter = new QSplitter(Qt::Horizontal);
canvasSplitter->addWidget(sourceCanvas);
canvasSplitter->addWidget(destinationCanvas);
sourceSplitter = new QSplitter(Qt::Vertical);
sourceSplitter->addWidget(sourceList);
sourceSplitter->addWidget(shapeList);
mainSplitter->addWidget(sourceSplitter);
mainSplitter->addWidget(canvasSplitter);
mainSplitter->setStretchFactor(1, 1); // Upon resizing window, give the extra stretch expansion to canvasSplitter.
mainSplitter->addWidget(resourceSplitter);
// Initialize size to 2:1 proportions.
QSize sz = mainSplitter->size();
QList<int> sizes;
sizes.append(sz.height() * 2 / 3);
sizes.append(sz.height() - sizes.at(0));
mainSplitter->setSizes(sizes);
// Upon resizing window, give some extra stretch expansion to canvasSplitter.
//mainSplitter->setStretchFactor(0, 1);
setWindowTitle(tr("Libremapping"));
resize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
@@ -319,9 +368,17 @@ void MainWindow::createLayout()
connect(sourceList, SIGNAL(itemSelectionChanged()),
this, SLOT(handleSourceItemSelectionChanged()));
connect(shapeList, SIGNAL(itemSelectionChanged()),
this, SLOT(handleShapeItemSelectionChanged()));
// sourceList->setModel(sourcesModel);
connect(layerList, SIGNAL(itemSelectionChanged()),
this, SLOT(handleLayerItemSelectionChanged()));
connect(layerList, SIGNAL(itemChanged(QListWidgetItem*)),
this, SLOT(handleLayerItemChanged(QListWidgetItem*)));
connect(layerList->model(), SIGNAL(layoutChanged()),
this, SLOT(handleLayerIndexesMoved()));
// sourceList->setModel(sourcesModel);
//
// connect(sourceList->selectionModel(),
// SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
@@ -355,12 +412,12 @@ void MainWindow::createActions()
importAction = new QAction(tr("&Import media source..."), this);
importAction->setIcon(QIcon(":/images/document-import-2.png"));
importAction->setShortcut(QKeySequence::Italic); // ctrl-I
importAction->setShortcut(QKeySequence::Open);
importAction->setStatusTip(tr("Import a media source file"));
connect(importAction, SIGNAL(triggered()), this, SLOT(import()));
exitAction = new QAction(tr("E&xit"), this);
exitAction->setShortcut(QKeySequence::Quit);
exitAction->setShortcut(tr("Ctrl+Q"));
exitAction->setStatusTip(tr("Exit the application"));
connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));
@@ -394,7 +451,7 @@ void MainWindow::createActions()
addQuadAction = new QAction(tr("&Add quad"), this);
addQuadAction->setIcon(QIcon(":/images/draw-rectangle-2.png"));
addQuadAction->setStatusTip(tr("Add quad"));
connect(addQuadAction, SIGNAL(triggered()), this, SLOT(addQuad()));
connect(addQuadAction, SIGNAL(triggered()), this, SLOT(addMesh()));
addTriangleAction = new QAction(tr("&Add triangle"), this);
addTriangleAction->setIcon(QIcon(":/images/draw-triangle.png"));
@@ -497,7 +554,7 @@ void MainWindow::readSettings()
restoreGeometry(settings.value("geometry").toByteArray());
mainSplitter->restoreState(settings.value("mainSplitter").toByteArray());
sourceSplitter->restoreState(settings.value("sourceSplitter").toByteArray());
resourceSplitter->restoreState(settings.value("resourceSplitter").toByteArray());
canvasSplitter->restoreState(settings.value("canvasSplitter").toByteArray());
config_osc_receive_port = settings.value("osc_receive_port", 12345).toInt();
}
@@ -508,7 +565,7 @@ void MainWindow::writeSettings()
settings.setValue("geometry", saveGeometry());
settings.setValue("mainSplitter", mainSplitter->saveState());
settings.setValue("sourceSplitter", sourceSplitter->saveState());
settings.setValue("resourceSplitter", resourceSplitter->saveState());
settings.setValue("canvasSplitter", canvasSplitter->saveState());
settings.setValue("osc_receive_port", config_osc_receive_port);
}
@@ -619,7 +676,7 @@ bool MainWindow::importMediaFile(const QString &fileName)
QApplication::setOverrideCursor(Qt::WaitCursor);
// Add image to model.
int imageId = mappingManager->addImage(fileName, sourceCanvas->width(), sourceCanvas->height());
uint imageId = mappingManager->addImage(fileName, sourceCanvas->width(), sourceCanvas->height());
// Add image to sourceList widget.
QListWidgetItem* item = new QListWidgetItem(strippedName(fileName));
@@ -637,24 +694,39 @@ bool MainWindow::importMediaFile(const QString &fileName)
return true;
}
void MainWindow::addMappingItem(int mappingId)
void MainWindow::addLayerItem(uint layerId)
{
Mapping::ptr mapping = mappingManager->getMapping(mappingId);
Q_CHECK_PTR(mapping);
Layer::ptr layer = mappingManager->getLayerById(layerId);
Q_CHECK_PTR(layer);
Mapping::ptr mapping = layer->getMapping();
uint mappingId = mapping->getId();
QString label;
QIcon icon;
// Add mapper.
// XXX hardcoded for textures
std::tr1::shared_ptr<TextureMapping> textureMapping = std::tr1::static_pointer_cast<TextureMapping>(mapping);
Q_CHECK_PTR(textureMapping);
Mapper::ptr mapper;
// XXX Branching on nVertices() is crap
// Triangle
if (mapping->getShape()->nVertices() == 3)
{
label = QString("Triangle %1").arg(mappingId);
icon = QIcon(":/images/draw-triangle.png");
mapper = Mapper::ptr(new TriangleTextureMapper(textureMapping));
}
// Mesh
else if (mapping->getShape()->nVertices() == 4)
{
label = QString("Quad %1").arg(mappingId);
icon = QIcon(":/images/draw-rectangle-2.png");
mapper = Mapper::ptr(new MeshTextureMapper(textureMapping));
}
else
{
@@ -662,19 +734,43 @@ void MainWindow::addMappingItem(int mappingId)
icon = QIcon(":/images/draw-polygon-2.png");
}
// Add image to sourceList widget.
// Add to list of mappers.
mappers[mappingId] = mapper;
QWidget* mapperEditor = mapper->getPropertiesEditor();
propertyPanel->addWidget(mapperEditor);
propertyPanel->setCurrentWidget(mapperEditor);
propertyPanel->setEnabled(true);
// When mapper value is changed, update canvases.
connect(mapper.get(), SIGNAL(valueChanged()),
this, SLOT(updateAll()));
connect(sourceCanvas, SIGNAL(shapeChanged(Shape*)),
mapper.get(), SLOT(updateShape(Shape*)));
connect(destinationCanvas, SIGNAL(shapeChanged(Shape*)),
mapper.get(), SLOT(updateShape(Shape*)));
// Add item to layerList widget.
QListWidgetItem* item = new QListWidgetItem(label);
item->setData(Qt::UserRole, mappingId); // TODO: could possibly be replaced by a Paint pointer
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
item->setCheckState(Qt::Checked);
item->setData(Qt::UserRole, layerId); // TODO: could possibly be replaced by a Paint pointer
item->setIcon(icon);
item->setSizeHint(QSize(item->sizeHint().width(), MainWindow::SHAPE_LIST_ITEM_HEIGHT));
shapeList->addItem(item);
shapeList->setCurrentItem(item);
layerList->insertItem(0, item);
layerList->setCurrentItem(item);
}
void MainWindow::clearWindow()
{
// TODO: implement Facade::clearProject()
this->_facade->clearProject();
// TODO: implement clearWindow()
}
void MainWindow::updateAll()
{
sourceCanvas->update();
destinationCanvas->update();
}
QString MainWindow::strippedName(const QString &fullFileName)
@@ -706,4 +802,57 @@ void MainWindow::pollOscInterface()
#endif
}
void MainWindow::applyOscCommand(QVariantList & command)
{
bool VERBOSE = true;
if (VERBOSE)
{
std::cout << "Receive OSC: ";
for (int i = 0; i < command.size(); ++i)
{
if (command.at(i).type() == QVariant::Int)
{
std::cout << command.at(i).toInt() << " ";
}
else if (command.at(i).type() == QVariant::Double)
{
std::cout << command.at(i).toDouble() << " ";
}
else if (command.at(i).type() == QVariant::String)
{
std::cout << command.at(i).toString().toStdString() << " ";
}
else
{
std::cout << "??? ";
}
}
std::cout << std::endl;
std::cout.flush();
}
if (command.size() < 2)
return;
if (command.at(0).type() != QVariant::String)
return;
if (command.at(1).type() != QVariant::String)
return;
std::string path = command.at(0).toString().toStdString();
std::string typetags = command.at(1).toString().toStdString();
// Handle all OSC messages here
if (path == "/image/uri" && typetags == "s")
{
std::string image_uri = command.at(2).toString().toStdString();
std::cout << "TODO load /image/uri " << image_uri << std::endl;
}
else if (path == "/add/quad")
addMesh();
else if (path == "/add/triangle")
addTriangle();
else if (path == "/project/save")
save();
else if (path == "/project/open")
open();
}