Add skeleton snapshot support (Prepare for undo/redo feature)
15
README.md
|
@ -1,3 +1,5 @@
|
|||
WIP...
|
||||
|
||||
Build
|
||||
--------
|
||||
```
|
||||
|
@ -7,3 +9,16 @@ $ make && make install
|
|||
|
||||
$ qmake -spec macx-xcode
|
||||
```
|
||||
|
||||
UI Resources Source
|
||||
--------
|
||||
Qt Dark Theme:
|
||||
- https://gist.github.com/QuantumCD/6245215
|
||||
|
||||
Icons:
|
||||
- https://material.io/icons/
|
||||
18dp white
|
||||
3d rotation -> rotate
|
||||
add circle outline -> add
|
||||
zoom in -> zoomin
|
||||
zoom out -> zoomout
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
convert thirdparty/capicon/png/white/059.png -fuzz 90% -fill 'rgb(252,102,33)' -opaque 'rgb(255,255,255)' resources/add.png
|
||||
convert thirdparty/capicon/png/white/262.png -fuzz 90% -fill 'rgb(252,102,33)' -opaque 'rgb(255,255,255)' resources/select.png
|
||||
convert thirdparty/capicon/png/white/078.png -fuzz 90% -fill 'rgb(252,102,33)' -opaque 'rgb(255,255,255)' resources/picture.png
|
||||
convert thirdparty/capicon/png/white/226.png -fuzz 90% -fill 'rgb(252,102,33)' -opaque 'rgb(255,255,255)' resources/save.png
|
||||
convert thirdparty/capicon/png/white/341.png -fuzz 90% -fill 'rgb(252,102,33)' -opaque 'rgb(255,255,255)' resources/info.png
|
||||
convert thirdparty/capicon/png/white/279.png -fuzz 90% -fill 'rgb(252,102,33)' -opaque 'rgb(255,255,255)' resources/up.png
|
||||
convert thirdparty/capicon/png/white/278.png -fuzz 90% -fill 'rgb(252,102,33)' -opaque 'rgb(255,255,255)' resources/down.png
|
||||
convert thirdparty/capicon/png/white/274.png -fuzz 90% -fill 'rgb(252,102,33)' -opaque 'rgb(255,255,255)' resources/clip.png
|
||||
convert thirdparty/capicon/png/white/254.png -fuzz 90% -fill 'rgb(252,102,33)' -opaque 'rgb(255,255,255)' resources/rangeselect.png
|
||||
convert thirdparty/capicon/png/white/057.png -fuzz 90% -fill 'rgb(252,102,33)' -opaque 'rgb(255,255,255)' resources/delete.png
|
||||
convert thirdparty/capicon/png/white/047.png -fuzz 90% -fill 'rgb(252,102,33)' -opaque 'rgb(255,255,255)' resources/new.png
|
||||
convert thirdparty/capicon/png/white/039.png -fuzz 90% -fill 'rgb(252,102,33)' -opaque 'rgb(255,255,255)' resources/palette.png
|
||||
convert thirdparty/capicon/png/white/030.png -fuzz 90% -fill 'rgb(252,102,33)' -opaque 'rgb(255,255,255)' resources/trashbin.png
|
||||
cp -f thirdparty/capicon/svg/059.svg resources/add.svg
|
||||
cp -f thirdparty/capicon/svg/262.svg resources/select.svg
|
||||
cp -f thirdparty/capicon/svg/078.svg resources/picture.svg
|
||||
cp -f thirdparty/capicon/svg/226.svg resources/save.svg
|
||||
cp -f thirdparty/capicon/svg/341.svg resources/info.svg
|
||||
cp -f thirdparty/capicon/svg/279.svg resources/up.svg
|
||||
cp -f thirdparty/capicon/svg/278.svg resources/down.svg
|
||||
cp -f thirdparty/capicon/svg/274.svg resources/clip.svg
|
||||
cp -f thirdparty/capicon/svg/254.svg resources/rangeselect.svg
|
||||
cp -f thirdparty/capicon/svg/057.svg resources/delete.svg
|
||||
cp -f thirdparty/capicon/svg/047.svg resources/new.svg
|
||||
cp -f thirdparty/capicon/svg/039.svg resources/palette.svg
|
||||
cp -f thirdparty/capicon/svg/030.svg resources/trashbin.svg
|
||||
|
|
|
@ -28,6 +28,12 @@ HEADERS += src/turnaroundloader.h
|
|||
SOURCES += src/skeletonwidget.cpp
|
||||
HEADERS += src/skeletonwidget.h
|
||||
|
||||
SOURCES += src/skeletonsnapshot.cpp
|
||||
HEADERS += src/skeletonsnapshot.h
|
||||
|
||||
SOURCES += src/skeletonxml.cpp
|
||||
HEADERS += src/skeletonxml.h
|
||||
|
||||
SOURCES += src/ds3file.cpp
|
||||
HEADERS += src/ds3file.h
|
||||
|
||||
|
|
|
@ -1,17 +1,8 @@
|
|||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file>resources/add.png</file>
|
||||
<file>resources/select.png</file>
|
||||
<file>resources/picture.png</file>
|
||||
<file>resources/save.png</file>
|
||||
<file>resources/info.png</file>
|
||||
<file>resources/up.png</file>
|
||||
<file>resources/down.png</file>
|
||||
<file>resources/clip.png</file>
|
||||
<file>resources/rangeselect.png</file>
|
||||
<file>resources/delete.png</file>
|
||||
<file>resources/new.png</file>
|
||||
<file>resources/palette.png</file>
|
||||
<file>resources/trashbin.png</file>
|
||||
<file>resources/add.svg</file>
|
||||
<file>resources/rotate.svg</file>
|
||||
<file>resources/zoomin.svg</file>
|
||||
<file>resources/zoomout.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.6 KiB |
BIN
resources/up.png
Before Width: | Height: | Size: 1.2 KiB |
|
@ -33,7 +33,8 @@ int main(int argc, char ** argv)
|
|||
|
||||
QFont font;
|
||||
font.setWeight(QFont::Light);
|
||||
font.setPointSize(9);
|
||||
font.setPixelSize(9);
|
||||
font.setBold(false);
|
||||
QApplication::setFont(font);
|
||||
|
||||
MainWindow mainWindow;
|
||||
|
|
|
@ -12,11 +12,14 @@
|
|||
#include <QBuffer>
|
||||
#include <QFormLayout>
|
||||
#include <QComboBox>
|
||||
#include <QMenu>
|
||||
#include <QMenuBar>
|
||||
#include <assert.h>
|
||||
#include "mainwindow.h"
|
||||
#include "skeletonwidget.h"
|
||||
#include "theme.h"
|
||||
#include "ds3file.h"
|
||||
#include "skeletonxml.h"
|
||||
|
||||
MainWindow::MainWindow()
|
||||
{
|
||||
|
@ -24,7 +27,7 @@ MainWindow::MainWindow()
|
|||
m_sharePageButton = new QPushButton("Share");
|
||||
|
||||
QWidget *hrWidget = new QWidget;
|
||||
hrWidget->setFixedHeight(2);
|
||||
hrWidget->setFixedHeight(1);
|
||||
hrWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
hrWidget->setStyleSheet(QString("background-color: #fc6621;"));
|
||||
hrWidget->setContentsMargins(0, 0, 0, 0);
|
||||
|
@ -42,8 +45,7 @@ MainWindow::MainWindow()
|
|||
|
||||
QHBoxLayout *topButtonsLayout = new QHBoxLayout;
|
||||
topButtonsLayout->setContentsMargins(0, 0, 0, 0);
|
||||
topButtonsLayout->setSpacing(0);
|
||||
topButtonsLayout->addStretch();
|
||||
topButtonsLayout->setSpacing(20);
|
||||
topButtonsLayout->addWidget(m_modelPageButton);
|
||||
topButtonsLayout->addWidget(m_sharePageButton);
|
||||
topButtonsLayout->addStretch();
|
||||
|
@ -96,7 +98,7 @@ MainWindow::MainWindow()
|
|||
|
||||
QHBoxLayout *modelPageLayout = new QHBoxLayout;
|
||||
modelPageLayout->addWidget(skeletonWidget);
|
||||
modelPageLayout->addLayout(modelRightLayout);
|
||||
//modelPageLayout->addLayout(modelRightLayout);
|
||||
|
||||
QWidget *modelPageWidget = new QWidget;
|
||||
modelPageWidget->setLayout(modelPageLayout);
|
||||
|
@ -106,12 +108,14 @@ MainWindow::MainWindow()
|
|||
QStackedWidget *stackedWidget = new QStackedWidget;
|
||||
stackedWidget->addWidget(modelPageWidget);
|
||||
stackedWidget->addWidget(sharePageWidget);
|
||||
stackedWidget->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
m_stackedWidget = stackedWidget;
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(topLayout);
|
||||
//mainLayout->addLayout(topLayout);
|
||||
mainLayout->addWidget(stackedWidget);
|
||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
QWidget *centralWidget = new QWidget;
|
||||
centralWidget->setLayout(mainLayout);
|
||||
|
@ -119,6 +123,74 @@ MainWindow::MainWindow()
|
|||
setCentralWidget(centralWidget);
|
||||
setWindowTitle(tr("Dust 3D"));
|
||||
|
||||
QAction *newAct = new QAction(tr("&New"), this);
|
||||
newAct->setShortcuts(QKeySequence::New);
|
||||
newAct->setStatusTip(tr("Create a new file"));
|
||||
connect(newAct, &QAction::triggered, this, &MainWindow::newFile);
|
||||
|
||||
QAction *openAct = new QAction(tr("&Open..."), this);
|
||||
openAct->setShortcuts(QKeySequence::Open);
|
||||
openAct->setStatusTip(tr("Open an existing file"));
|
||||
connect(openAct, &QAction::triggered, this, &MainWindow::open);
|
||||
|
||||
QAction *saveAct = new QAction(tr("&Save"), this);
|
||||
saveAct->setShortcuts(QKeySequence::Save);
|
||||
saveAct->setStatusTip(tr("Save the document to disk"));
|
||||
connect(saveAct, &QAction::triggered, this, &MainWindow::save);
|
||||
|
||||
QAction *exitAct = new QAction(tr("E&xit"), this);
|
||||
exitAct->setShortcuts(QKeySequence::Quit);
|
||||
exitAct->setStatusTip(tr("Exit the application"));
|
||||
connect(exitAct, &QAction::triggered, this, &QWidget::close);
|
||||
|
||||
QAction *undoAct = new QAction(tr("&Undo"), this);
|
||||
undoAct->setShortcuts(QKeySequence::Undo);
|
||||
undoAct->setStatusTip(tr("Undo the last operation"));
|
||||
connect(undoAct, &QAction::triggered, this, &MainWindow::undo);
|
||||
|
||||
QAction *redoAct = new QAction(tr("&Redo"), this);
|
||||
redoAct->setShortcuts(QKeySequence::Redo);
|
||||
redoAct->setStatusTip(tr("Redo the last operation"));
|
||||
connect(redoAct, &QAction::triggered, this, &MainWindow::redo);
|
||||
|
||||
QAction *cutAct = new QAction(tr("Cu&t"), this);
|
||||
cutAct->setShortcuts(QKeySequence::Cut);
|
||||
cutAct->setStatusTip(tr("Cut the current selection's contents to the "
|
||||
"clipboard"));
|
||||
connect(cutAct, &QAction::triggered, this, &MainWindow::cut);
|
||||
|
||||
QAction *copyAct = new QAction(tr("&Copy"), this);
|
||||
copyAct->setShortcuts(QKeySequence::Copy);
|
||||
copyAct->setStatusTip(tr("Copy the current selection's contents to the "
|
||||
"clipboard"));
|
||||
connect(copyAct, &QAction::triggered, this, &MainWindow::copy);
|
||||
|
||||
QAction *pasteAct = new QAction(tr("&Paste"), this);
|
||||
pasteAct->setShortcuts(QKeySequence::Paste);
|
||||
pasteAct->setStatusTip(tr("Paste the clipboard's contents into the current "
|
||||
"selection"));
|
||||
connect(pasteAct, &QAction::triggered, this, &MainWindow::paste);
|
||||
|
||||
QAction *changeTurnaroundAct = new QAction(tr("&Change Turnaround..."), this);
|
||||
connect(changeTurnaroundAct, &QAction::triggered, skeletonWidget, &SkeletonWidget::changeTurnaround);
|
||||
|
||||
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
|
||||
fileMenu->addAction(newAct);
|
||||
fileMenu->addAction(openAct);
|
||||
fileMenu->addAction(saveAct);
|
||||
fileMenu->addSeparator();
|
||||
fileMenu->addAction(exitAct);
|
||||
|
||||
QMenu *editMenu = menuBar()->addMenu(tr("&Edit"));
|
||||
editMenu->addAction(undoAct);
|
||||
editMenu->addAction(redoAct);
|
||||
editMenu->addSeparator();
|
||||
editMenu->addAction(cutAct);
|
||||
editMenu->addAction(copyAct);
|
||||
editMenu->addAction(pasteAct);
|
||||
editMenu->addSeparator();
|
||||
editMenu->addAction(changeTurnaroundAct);
|
||||
|
||||
bool connectResult = false;
|
||||
|
||||
connectResult = connect(changeTurnaroundButton, SIGNAL(clicked()), skeletonWidget, SLOT(changeTurnaround()));
|
||||
|
@ -142,6 +214,46 @@ MainWindow::MainWindow()
|
|||
updatePageButtons();
|
||||
}
|
||||
|
||||
void MainWindow::newFile()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::open()
|
||||
{
|
||||
loadModel();
|
||||
}
|
||||
|
||||
void MainWindow::save()
|
||||
{
|
||||
saveModel();
|
||||
}
|
||||
|
||||
void MainWindow::undo()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::redo()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::cut()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::copy()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::paste()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::exportModel()
|
||||
{
|
||||
QString exportTo = QFileDialog::getSaveFileName(this,
|
||||
|
@ -167,7 +279,9 @@ void MainWindow::loadModel()
|
|||
QByteArray data;
|
||||
ds3Reader.loadItem(item.name, &data);
|
||||
QXmlStreamReader xmlReader(data);
|
||||
m_skeletonWidget->graphicsView()->loadFromXmlStream(xmlReader);
|
||||
SkeletonSnapshot snapshot;
|
||||
loadSkeletonFromXmlStream(&snapshot, xmlReader);
|
||||
m_skeletonWidget->graphicsView()->loadFromSnapshot(&snapshot);
|
||||
} else if (item.type == "asset") {
|
||||
if (item.name == "canvas.png") {
|
||||
QByteArray data;
|
||||
|
@ -195,7 +309,9 @@ void MainWindow::saveModel()
|
|||
|
||||
QByteArray modelXml;
|
||||
QXmlStreamWriter stream(&modelXml);
|
||||
m_skeletonWidget->graphicsView()->saveToXmlStream(&stream);
|
||||
SkeletonSnapshot snapshot;
|
||||
m_skeletonWidget->graphicsView()->saveToSnapshot(&snapshot);
|
||||
saveSkeletonToXmlStream(&snapshot, &stream);
|
||||
if (modelXml.size() > 0)
|
||||
ds3Writer.add("model1.xml", "model", &modelXml);
|
||||
|
||||
|
|
|
@ -17,6 +17,14 @@ public slots:
|
|||
void saveModel();
|
||||
void loadModel();
|
||||
void exportModel();
|
||||
void newFile();
|
||||
void open();
|
||||
void save();
|
||||
void undo();
|
||||
void redo();
|
||||
void cut();
|
||||
void copy();
|
||||
void paste();
|
||||
private:
|
||||
QPushButton *m_modelPageButton;
|
||||
QPushButton *m_sharePageButton;
|
||||
|
|
|
@ -28,8 +28,13 @@ bool SkeletonEditEdgeItem::checked()
|
|||
|
||||
void SkeletonEditEdgeItem::updateAppearance()
|
||||
{
|
||||
QPen pen(m_checked ? Theme::skeletonMasterNodeBorderHighlightColor : Theme::skeletonMasterNodeBorderColor);
|
||||
pen.setWidth(Theme::skeletonMasterNodeBorderSize);
|
||||
QPen pen;
|
||||
if (m_firstNode) {
|
||||
pen.setColor(m_firstNode->sideColor());
|
||||
} else if (m_secondNode) {
|
||||
pen.setColor(m_secondNode->sideColor());
|
||||
}
|
||||
pen.setWidth(Theme::skeletonEdgeWidth);
|
||||
setPen(pen);
|
||||
}
|
||||
|
||||
|
@ -51,6 +56,7 @@ void SkeletonEditEdgeItem::updatePosition()
|
|||
QLineF line(m_firstNode->origin(), m_secondNode->origin());
|
||||
setLine(line);
|
||||
}
|
||||
updateAppearance();
|
||||
}
|
||||
|
||||
SkeletonEditNodeItem *SkeletonEditEdgeItem::firstNode()
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "skeletoneditgraphicsview.h"
|
||||
#include "skeletoneditnodeitem.h"
|
||||
#include "skeletoneditedgeitem.h"
|
||||
#include "theme.h"
|
||||
|
||||
qreal SkeletonEditGraphicsView::m_initialNodeSize = 128;
|
||||
qreal SkeletonEditGraphicsView::m_minimalNodeSize = 8;
|
||||
|
@ -22,8 +23,7 @@ SkeletonEditGraphicsView::SkeletonEditGraphicsView(QWidget *parent) :
|
|||
m_lastHoverNodeItem(NULL),
|
||||
m_lastMousePos(0, 0),
|
||||
m_isMovingNodeItem(false),
|
||||
m_backgroundLoaded(false),
|
||||
m_selectedEdgeItem(NULL)
|
||||
m_backgroundLoaded(false)
|
||||
{
|
||||
setScene(new QGraphicsScene());
|
||||
|
||||
|
@ -128,31 +128,13 @@ void SkeletonEditGraphicsView::mousePressEvent(QMouseEvent *event)
|
|||
if (event->button() == Qt::LeftButton) {
|
||||
if (!m_inAddNodeMode) {
|
||||
if (m_lastHoverNodeItem) {
|
||||
setNextStartNodeItem(m_lastHoverNodeItem->master());
|
||||
setNextStartNodeItem(m_lastHoverNodeItem);
|
||||
m_lastHoverNodeItem = NULL;
|
||||
} else {
|
||||
if (m_nextStartNodeItem) {
|
||||
setNextStartNodeItem(NULL);
|
||||
}
|
||||
}
|
||||
SkeletonEditEdgeItem *edgeItem = findEdgeItemByPos(pos);
|
||||
if (edgeItem) {
|
||||
if (m_selectedEdgeItem != edgeItem) {
|
||||
if (m_selectedEdgeItem) {
|
||||
m_selectedEdgeItem->setChecked(false);
|
||||
m_selectedEdgeItem = NULL;
|
||||
}
|
||||
edgeItem->setChecked(true);
|
||||
m_selectedEdgeItem = edgeItem;
|
||||
emit edgeCheckStateChanged();
|
||||
}
|
||||
} else {
|
||||
if (m_selectedEdgeItem) {
|
||||
m_selectedEdgeItem->setChecked(false);
|
||||
m_selectedEdgeItem = NULL;
|
||||
emit edgeCheckStateChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m_lastMousePos = pos;
|
||||
|
@ -165,11 +147,6 @@ void SkeletonEditGraphicsView::mouseDoubleClickEvent(QMouseEvent *event)
|
|||
emit changeTurnaroundTriggered();
|
||||
}
|
||||
|
||||
float SkeletonEditGraphicsView::findXForSlave(float x)
|
||||
{
|
||||
return x - m_backgroundItem->boundingRect().width() / 4;
|
||||
}
|
||||
|
||||
void SkeletonEditGraphicsView::removeSelectedItems()
|
||||
{
|
||||
if (m_nextStartNodeItem) {
|
||||
|
@ -182,9 +159,6 @@ void SkeletonEditGraphicsView::removeSelectedItems()
|
|||
|
||||
void SkeletonEditGraphicsView::removeNodeItem(SkeletonEditNodeItem *nodeItem)
|
||||
{
|
||||
if (nodeItem->pair()) {
|
||||
scene()->removeItem(nodeItem->pair());
|
||||
}
|
||||
scene()->removeItem(nodeItem);
|
||||
QList<QGraphicsItem *>::iterator it;
|
||||
QList<QGraphicsItem *> list = scene()->items();
|
||||
|
@ -198,29 +172,19 @@ void SkeletonEditGraphicsView::removeNodeItem(SkeletonEditNodeItem *nodeItem)
|
|||
}
|
||||
}
|
||||
|
||||
void SkeletonEditGraphicsView::removeGroupByNodeItem(SkeletonEditNodeItem *nodeItem)
|
||||
void SkeletonEditGraphicsView::fetchNodeItemAndAllSidePairs(SkeletonEditNodeItem *nodeItem, std::vector<SkeletonEditNodeItem *> *sidePairs)
|
||||
{
|
||||
if (nodeItem->pair()) {
|
||||
scene()->removeItem(nodeItem->pair());
|
||||
sidePairs->push_back(nodeItem);
|
||||
sidePairs->push_back(nodeItem->nextSidePair());
|
||||
sidePairs->push_back(nodeItem->nextSidePair()->nextSidePair());
|
||||
}
|
||||
scene()->removeItem(nodeItem);
|
||||
QList<QGraphicsItem *>::iterator it;
|
||||
QList<QGraphicsItem *> list = scene()->items();
|
||||
std::vector<SkeletonEditNodeItem *> delayRemoveList;
|
||||
for (it = list.begin(); it != list.end(); ++it) {
|
||||
if ((*it)->data(0).toString() == "edge") {
|
||||
SkeletonEditEdgeItem *edgeItem = static_cast<SkeletonEditEdgeItem *>(*it);
|
||||
if (edgeItem->firstNode() == nodeItem) {
|
||||
scene()->removeItem(edgeItem);
|
||||
delayRemoveList.push_back(edgeItem->secondNode());
|
||||
} else if (edgeItem->secondNode() == nodeItem) {
|
||||
scene()->removeItem(edgeItem);
|
||||
delayRemoveList.push_back(edgeItem->firstNode());
|
||||
}
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < delayRemoveList.size(); i++) {
|
||||
removeNodeItem(delayRemoveList[i]);
|
||||
|
||||
void SkeletonEditGraphicsView::removeNodeItemAndSidePairs(SkeletonEditNodeItem *nodeItem)
|
||||
{
|
||||
std::vector<SkeletonEditNodeItem *> nodes;
|
||||
fetchNodeItemAndAllSidePairs(nodeItem, &nodes);
|
||||
for (size_t i = 0; i < nodes.size(); i++) {
|
||||
removeNodeItem(nodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,6 +206,52 @@ void SkeletonEditGraphicsView::resizeEvent(QResizeEvent *event)
|
|||
emit sizeChanged();
|
||||
}
|
||||
|
||||
SkeletonEditNodeItem *SkeletonEditGraphicsView::addNodeItemAndSidePairs(QRectF area, SkeletonEditNodeItem *fromNodeItem, const QString &sideColorName)
|
||||
{
|
||||
float pairedX = 0;
|
||||
QRectF pairedRect = area;
|
||||
if (fromNodeItem) {
|
||||
pairedX = fromNodeItem->nextSidePair()->rect().x();
|
||||
} else {
|
||||
if (area.center().x() < scene()->sceneRect().width() / 2) {
|
||||
pairedX = area.center().x() + scene()->sceneRect().width() / 4;
|
||||
} else {
|
||||
pairedX = area.center().x() - scene()->sceneRect().width() / 4;
|
||||
}
|
||||
}
|
||||
pairedRect.translate(pairedX - area.x(), 0);
|
||||
SkeletonEditNodeItem *firstNode = new SkeletonEditNodeItem(area);
|
||||
scene()->addItem(firstNode);
|
||||
firstNode->setSideColorName(fromNodeItem ? fromNodeItem->sideColorName() : sideColorName);
|
||||
SkeletonEditNodeItem *secondNode = new SkeletonEditNodeItem(pairedRect);
|
||||
scene()->addItem(secondNode);
|
||||
secondNode->setSideColorName(firstNode->nextSideColorName());
|
||||
firstNode->setNextSidePair(secondNode);
|
||||
secondNode->setNextSidePair(firstNode);
|
||||
setNextStartNodeItem(firstNode);
|
||||
if (!fromNodeItem) {
|
||||
return firstNode;
|
||||
}
|
||||
addEdgeItem(fromNodeItem, firstNode);
|
||||
addEdgeItem(fromNodeItem->nextSidePair(), firstNode->nextSidePair());
|
||||
return firstNode;
|
||||
}
|
||||
|
||||
SkeletonEditNodeItem *SkeletonEditGraphicsView::addNodeItem(float originX, float originY, float radius)
|
||||
{
|
||||
QRectF area(originX - radius, originY - radius, radius * 2, radius * 2);
|
||||
SkeletonEditNodeItem *firstNode = new SkeletonEditNodeItem(area);
|
||||
scene()->addItem(firstNode);
|
||||
return firstNode;
|
||||
}
|
||||
|
||||
void SkeletonEditGraphicsView::addEdgeItem(SkeletonEditNodeItem *first, SkeletonEditNodeItem *second)
|
||||
{
|
||||
SkeletonEditEdgeItem *newEdge = new SkeletonEditEdgeItem();
|
||||
newEdge->setNodes(first, second);
|
||||
scene()->addItem(newEdge);
|
||||
}
|
||||
|
||||
void SkeletonEditGraphicsView::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
QWidget::mouseReleaseEvent(event);
|
||||
|
@ -249,38 +259,16 @@ void SkeletonEditGraphicsView::mouseReleaseEvent(QMouseEvent *event)
|
|||
return;
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
if (m_inAddNodeMode) {
|
||||
if (m_lastHoverNodeItem && m_nextStartNodeItem && m_lastHoverNodeItem != m_nextStartNodeItem) {
|
||||
if (!findEdgeItemByNodePair(m_lastHoverNodeItem->master(), m_nextStartNodeItem)) {
|
||||
SkeletonEditEdgeItem *newEdge = new SkeletonEditEdgeItem();
|
||||
newEdge->setNodes(m_nextStartNodeItem, m_lastHoverNodeItem->master());
|
||||
scene()->addItem(newEdge);
|
||||
if (m_lastHoverNodeItem && m_nextStartNodeItem &&
|
||||
m_lastHoverNodeItem != m_nextStartNodeItem &&
|
||||
m_lastHoverNodeItem->sideColor() == m_nextStartNodeItem->sideColor()) {
|
||||
if (!findEdgeItemByNodePair(m_lastHoverNodeItem, m_nextStartNodeItem)) {
|
||||
addEdgeItem(m_nextStartNodeItem, m_lastHoverNodeItem);
|
||||
addEdgeItem(m_nextStartNodeItem->nextSidePair(), m_lastHoverNodeItem->nextSidePair());
|
||||
emit nodesChanged();
|
||||
}
|
||||
} else {
|
||||
float newNodeX = m_pendingNodeItem->x();
|
||||
QRectF newNodeRect = m_pendingNodeItem->rect();
|
||||
SkeletonEditNodeItem *masterNode = new SkeletonEditNodeItem(newNodeRect);
|
||||
scene()->addItem(masterNode);
|
||||
QRectF slaveRect = newNodeRect;
|
||||
float x = newNodeX + newNodeRect.width() / 2;
|
||||
slaveRect.translate(findXForSlave(x) - x, 0);
|
||||
SkeletonEditNodeItem *slaveNode = new SkeletonEditNodeItem(slaveRect);
|
||||
scene()->addItem(slaveNode);
|
||||
masterNode->setSlave(slaveNode);
|
||||
slaveNode->setMaster(masterNode);
|
||||
if (m_nextStartNodeItem) {
|
||||
SkeletonEditEdgeItem *newEdge = new SkeletonEditEdgeItem();
|
||||
newEdge->setNodes(masterNode, m_nextStartNodeItem);
|
||||
scene()->addItem(newEdge);
|
||||
masterNode->setGroup(m_nextStartNodeItem->group());
|
||||
slaveNode->setGroup(masterNode->group());
|
||||
} else {
|
||||
QGraphicsItemGroup *group = new QGraphicsItemGroup();
|
||||
scene()->addItem(group);
|
||||
masterNode->setGroup(group);
|
||||
slaveNode->setGroup(masterNode->group());
|
||||
}
|
||||
setNextStartNodeItem(masterNode);
|
||||
addNodeItemAndSidePairs(m_pendingNodeItem->rect(), m_nextStartNodeItem);
|
||||
emit nodesChanged();
|
||||
}
|
||||
}
|
||||
|
@ -294,9 +282,9 @@ bool SkeletonEditGraphicsView::canNodeItemMoveTo(SkeletonEditNodeItem *item, QPo
|
|||
return false;
|
||||
if (moveTo.y() < 0)
|
||||
return false;
|
||||
if (moveTo.x() + item->rect().width() >= m_backgroundItem->boundingRect().width())
|
||||
if (moveTo.x() + item->rect().width() >= scene()->sceneRect().width())
|
||||
return false;
|
||||
if (moveTo.y() + item->rect().height() >= m_backgroundItem->boundingRect().height())
|
||||
if (moveTo.y() + item->rect().height() >= scene()->sceneRect().height())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -312,10 +300,10 @@ void SkeletonEditGraphicsView::mouseMoveEvent(QMouseEvent *event)
|
|||
moveTo.setX(0);
|
||||
if (moveTo.y() < 0)
|
||||
moveTo.setY(0);
|
||||
if (moveTo.x() + m_pendingNodeItem->rect().width() >= m_backgroundItem->boundingRect().width())
|
||||
moveTo.setX(m_backgroundItem->boundingRect().width() - m_pendingNodeItem->rect().width());
|
||||
if (moveTo.y() + m_pendingNodeItem->rect().height() >= m_backgroundItem->boundingRect().height())
|
||||
moveTo.setY(m_backgroundItem->boundingRect().height() - m_pendingNodeItem->rect().height());
|
||||
if (moveTo.x() + m_pendingNodeItem->rect().width() >= scene()->sceneRect().width())
|
||||
moveTo.setX(scene()->sceneRect().width() - m_pendingNodeItem->rect().width());
|
||||
if (moveTo.y() + m_pendingNodeItem->rect().height() >= scene()->sceneRect().height())
|
||||
moveTo.setY(scene()->sceneRect().height() - m_pendingNodeItem->rect().height());
|
||||
QSizeF oldSize = m_pendingNodeItem->rect().size();
|
||||
m_pendingNodeItem->setRect(moveTo.x(), moveTo.y(),
|
||||
oldSize.width(),
|
||||
|
@ -327,11 +315,11 @@ void SkeletonEditGraphicsView::mouseMoveEvent(QMouseEvent *event)
|
|||
if (!m_isMovingNodeItem) {
|
||||
SkeletonEditNodeItem *hoverNodeItem = findNodeItemByPos(pos);
|
||||
if (hoverNodeItem) {
|
||||
hoverNodeItem->setHighlighted(true);
|
||||
hoverNodeItem->setHovered(true);
|
||||
}
|
||||
if (hoverNodeItem != m_lastHoverNodeItem) {
|
||||
if (m_lastHoverNodeItem)
|
||||
m_lastHoverNodeItem->setHighlighted(false);
|
||||
m_lastHoverNodeItem->setHovered(false);
|
||||
m_lastHoverNodeItem = hoverNodeItem;
|
||||
}
|
||||
}
|
||||
|
@ -341,32 +329,28 @@ void SkeletonEditGraphicsView::mouseMoveEvent(QMouseEvent *event)
|
|||
(curMousePos != m_lastMousePos || m_isMovingNodeItem)) {
|
||||
m_isMovingNodeItem = true;
|
||||
QRectF rect = m_lastHoverNodeItem->rect();
|
||||
QRectF slaveRect;
|
||||
if (m_lastHoverNodeItem->isMaster()) {
|
||||
QRectF pairedRect;
|
||||
|
||||
rect.translate(curMousePos.x() - m_lastMousePos.x(), curMousePos.y() - m_lastMousePos.y());
|
||||
slaveRect = m_lastHoverNodeItem->slave()->rect();
|
||||
slaveRect.translate(0, curMousePos.y() - m_lastMousePos.y());
|
||||
} else {
|
||||
rect.translate(curMousePos.x() - m_lastMousePos.x(), 0);
|
||||
}
|
||||
if (canNodeItemMoveTo(m_lastHoverNodeItem, QPointF(rect.x(), rect.y()))) {
|
||||
if (m_lastHoverNodeItem->isMaster()) {
|
||||
m_lastHoverNodeItem->slave()->setRect(slaveRect);
|
||||
}
|
||||
pairedRect = m_lastHoverNodeItem->nextSidePair()->rect();
|
||||
pairedRect.translate(0, curMousePos.y() - m_lastMousePos.y());
|
||||
|
||||
m_lastHoverNodeItem->setRect(rect);
|
||||
m_lastHoverNodeItem->nextSidePair()->setRect(pairedRect);
|
||||
|
||||
QList<QGraphicsItem *>::iterator it;
|
||||
QList<QGraphicsItem *> list = scene()->items();
|
||||
for (it = list.begin(); it != list.end(); ++it) {
|
||||
if ((*it)->data(0).toString() == "edge") {
|
||||
SkeletonEditEdgeItem *edgeItem = static_cast<SkeletonEditEdgeItem *>(*it);
|
||||
if (edgeItem->connects(m_lastHoverNodeItem))
|
||||
if (edgeItem->connects(m_lastHoverNodeItem) ||
|
||||
edgeItem->connects(m_lastHoverNodeItem->nextSidePair()))
|
||||
edgeItem->updatePosition();
|
||||
}
|
||||
}
|
||||
emit nodesChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
m_lastMousePos = curMousePos;
|
||||
}
|
||||
|
||||
|
@ -382,9 +366,9 @@ void SkeletonEditGraphicsView::AddItemRadius(QGraphicsEllipseItem *item, float d
|
|||
}
|
||||
QPointF newLeftTop = QPointF(originPt.x() - newSize.width() / 2,
|
||||
originPt.y() - newSize.height() / 2);
|
||||
if (newLeftTop.x() < 0 || newLeftTop.x() + newSize.width() >= m_backgroundItem->boundingRect().width())
|
||||
if (newLeftTop.x() < 0 || newLeftTop.x() + newSize.width() >= scene()->sceneRect().width())
|
||||
return;
|
||||
if (newLeftTop.y() < 0 || newLeftTop.y() + newSize.height() >= m_backgroundItem->boundingRect().height())
|
||||
if (newLeftTop.y() < 0 || newLeftTop.y() + newSize.height() >= scene()->sceneRect().height())
|
||||
return;
|
||||
item->setRect(newLeftTop.x(),
|
||||
newLeftTop.y(),
|
||||
|
@ -404,9 +388,9 @@ bool SkeletonEditGraphicsView::canAddItemRadius(QGraphicsEllipseItem *item, floa
|
|||
}
|
||||
QPointF newLeftTop = QPointF(originPt.x() - newSize.width() / 2,
|
||||
originPt.y() - newSize.height() / 2);
|
||||
if (newLeftTop.x() < 0 || newLeftTop.x() + newSize.width() >= m_backgroundItem->boundingRect().width())
|
||||
if (newLeftTop.x() < 0 || newLeftTop.x() + newSize.width() >= scene()->sceneRect().width())
|
||||
return false;
|
||||
if (newLeftTop.y() < 0 || newLeftTop.y() + newSize.height() >= m_backgroundItem->boundingRect().height())
|
||||
if (newLeftTop.y() < 0 || newLeftTop.y() + newSize.height() >= scene()->sceneRect().height())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -421,9 +405,9 @@ void SkeletonEditGraphicsView::wheelEvent(QWheelEvent *event)
|
|||
delta = delta < 0 ? -1.0 : 1.0;
|
||||
AddItemRadius(m_pendingNodeItem, delta);
|
||||
if (!m_inAddNodeMode && m_lastHoverNodeItem) {
|
||||
if (canAddItemRadius(m_lastHoverNodeItem, delta)) {
|
||||
//if (canAddItemRadius(m_lastHoverNodeItem, delta)) {
|
||||
AddItemRadius(m_lastHoverNodeItem, delta);
|
||||
}
|
||||
//}
|
||||
emit nodesChanged();
|
||||
}
|
||||
}
|
||||
|
@ -432,11 +416,11 @@ void SkeletonEditGraphicsView::setNextStartNodeItem(SkeletonEditNodeItem *item)
|
|||
{
|
||||
if (m_nextStartNodeItem != item) {
|
||||
if (m_nextStartNodeItem)
|
||||
m_nextStartNodeItem->setIsNextStartNode(false);
|
||||
m_nextStartNodeItem->setChecked(false);
|
||||
}
|
||||
m_nextStartNodeItem = item;
|
||||
if (m_nextStartNodeItem)
|
||||
m_nextStartNodeItem->setIsNextStartNode(true);
|
||||
m_nextStartNodeItem->setChecked(true);
|
||||
applyAddNodeMode();
|
||||
}
|
||||
|
||||
|
@ -444,8 +428,8 @@ void SkeletonEditGraphicsView::updateBackgroundImage(const QImage &image)
|
|||
{
|
||||
QSizeF oldSceneSize = scene()->sceneRect().size();
|
||||
QPixmap pixmap = QPixmap::fromImage(image);
|
||||
m_backgroundItem->setPixmap(pixmap);
|
||||
scene()->setSceneRect(pixmap.rect());
|
||||
m_backgroundItem->setPixmap(pixmap);
|
||||
adjustItems(oldSceneSize, scene()->sceneRect().size());
|
||||
if (!m_backgroundLoaded) {
|
||||
m_backgroundLoaded = true;
|
||||
|
@ -488,169 +472,99 @@ void SkeletonEditGraphicsView::adjustItems(QSizeF oldSceneSize, QSizeF newSceneS
|
|||
}
|
||||
}
|
||||
|
||||
void SkeletonEditGraphicsView::loadFromXmlStream(QXmlStreamReader &reader)
|
||||
void SkeletonEditGraphicsView::loadFromSnapshot(SkeletonSnapshot *snapshot)
|
||||
{
|
||||
float radiusMul = 1.0;
|
||||
float xMul = 1.0;
|
||||
float yMul = radiusMul;
|
||||
|
||||
std::vector<std::map<QString, QString>> pendingNodes;
|
||||
std::vector<std::map<QString, QString>> pendingEdges;
|
||||
std::map<QString, SkeletonEditNodeItem *> addedNodeMapById;
|
||||
std::map<QString, QGraphicsItemGroup *> addedGroupMapById;
|
||||
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNext();
|
||||
if (reader.isStartElement()) {
|
||||
if (reader.name() == "canvas") {
|
||||
QString canvasWidth = reader.attributes().value("width").toString();
|
||||
QString canvasHeight = reader.attributes().value("height").toString();
|
||||
float canvasHeightWidth = canvasWidth.toFloat();
|
||||
QString canvasWidth = snapshot->canvas["width"];
|
||||
QString canvasHeight = snapshot->canvas["height"];
|
||||
float canvasWidthVal = canvasWidth.toFloat();
|
||||
float canvasHeightVal = canvasHeight.toFloat();
|
||||
if (!hasBackgroundImage()) {
|
||||
QPixmap emptyImage((int)canvasHeightWidth, (int)canvasHeightVal);
|
||||
QPixmap emptyImage((int)canvasWidthVal, (int)canvasHeightVal);
|
||||
emptyImage.fill(QWidget::palette().color(QWidget::backgroundRole()));
|
||||
updateBackgroundImage(emptyImage.toImage());
|
||||
}
|
||||
if (canvasHeightVal > 0)
|
||||
radiusMul = (float)scene()->sceneRect().height() / canvasHeightVal;
|
||||
if (canvasHeightWidth > 0)
|
||||
xMul = (float)scene()->sceneRect().width() / canvasHeightWidth;
|
||||
if (canvasWidthVal > 0)
|
||||
xMul = (float)scene()->sceneRect().width() / canvasWidthVal;
|
||||
yMul = radiusMul;
|
||||
} else if (reader.name() == "origin") {
|
||||
if (pendingNodes.size() > 0) {
|
||||
pendingNodes[pendingNodes.size() - 1]["x"] = QString("%1").arg(reader.attributes().value("x").toString().toFloat() * xMul);
|
||||
pendingNodes[pendingNodes.size() - 1]["y"] = QString("%1").arg(reader.attributes().value("y").toString().toFloat() * yMul);
|
||||
}
|
||||
} else if (reader.name() == "node") {
|
||||
QString nodeId = reader.attributes().value("id").toString();
|
||||
QString nodeGroupId = reader.attributes().value("group").toString();
|
||||
QString nodeType = reader.attributes().value("type").toString();
|
||||
QString nodePairId = reader.attributes().value("pair").toString();
|
||||
QString nodeRadius = reader.attributes().value("radius").toString();
|
||||
std::map<QString, QString> pendingNode;
|
||||
pendingNode["id"] = nodeId;
|
||||
pendingNode["group"] = nodeGroupId;
|
||||
pendingNode["type"] = nodeType;
|
||||
pendingNode["pair"] = nodePairId;
|
||||
pendingNode["radius"] = QString("%1").arg(nodeRadius.toFloat() * radiusMul);
|
||||
pendingNode["x"] = "0";
|
||||
pendingNode["y"] = "0";
|
||||
pendingNodes.push_back(pendingNode);
|
||||
} else if (reader.name() == "edge") {
|
||||
QString edgeId = reader.attributes().value("id").toString();
|
||||
QString edgeFromNodeId = reader.attributes().value("from").toString();
|
||||
QString edgeToNodeId = reader.attributes().value("to").toString();
|
||||
if (!edgeFromNodeId.isEmpty() && !edgeToNodeId.isEmpty()) {
|
||||
std::map<QString, QString> pendingEdge;
|
||||
pendingEdge["id"] = edgeId;
|
||||
pendingEdge["from"] = edgeFromNodeId;
|
||||
pendingEdge["to"] = edgeToNodeId;
|
||||
pendingEdges.push_back(pendingEdge);
|
||||
}
|
||||
}
|
||||
|
||||
std::map<QString, SkeletonEditNodeItem *> nodeItemMap;
|
||||
std::map<QString, std::map<QString, QString>>::iterator nodeIterator;
|
||||
for (nodeIterator = snapshot->nodes.begin(); nodeIterator != snapshot->nodes.end(); nodeIterator++) {
|
||||
std::map<QString, QString> *snapshotNode = &nodeIterator->second;
|
||||
SkeletonEditNodeItem *nodeItem = addNodeItem((*snapshotNode)["x"].toFloat() * xMul,
|
||||
(*snapshotNode)["y"].toFloat() * yMul,
|
||||
(*snapshotNode)["radius"].toFloat() * radiusMul);
|
||||
nodeItem->setSideColorName((*snapshotNode)["sideColorName"]);
|
||||
nodeItemMap[nodeIterator->first] = nodeItem;
|
||||
}
|
||||
for (nodeIterator = snapshot->nodes.begin(); nodeIterator != snapshot->nodes.end(); nodeIterator++) {
|
||||
std::map<QString, QString> *snapshotNode = &nodeIterator->second;
|
||||
SkeletonEditNodeItem *nodeItem = nodeItemMap[nodeIterator->first];
|
||||
nodeItem->setNextSidePair(nodeItemMap[(*snapshotNode)["nextSidePair"]]);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < pendingNodes.size(); i++) {
|
||||
std::map<QString, QString> *pendingNode = &pendingNodes[i];
|
||||
float radius = (*pendingNode)["radius"].toFloat();
|
||||
QRectF nodeRect((*pendingNode)["x"].toFloat() - radius, (*pendingNode)["y"].toFloat() - radius,
|
||||
radius * 2, radius * 2);
|
||||
SkeletonEditNodeItem *nodeItem = new SkeletonEditNodeItem(nodeRect);
|
||||
addedNodeMapById[(*pendingNode)["id"]] = nodeItem;
|
||||
std::map<QString, QGraphicsItemGroup *>::iterator findGroup = addedGroupMapById.find((*pendingNode)["group"]);
|
||||
if (findGroup == addedGroupMapById.end()) {
|
||||
QGraphicsItemGroup *group = new QGraphicsItemGroup;
|
||||
scene()->addItem(group);
|
||||
addedGroupMapById[(*pendingNode)["group"]] = group;
|
||||
}
|
||||
nodeItem->setGroup(addedGroupMapById[(*pendingNode)["group"]]);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < pendingNodes.size(); i++) {
|
||||
std::map<QString, QString> *pendingNode = &pendingNodes[i];
|
||||
if ((*pendingNode)["type"] == "master") {
|
||||
addedNodeMapById[(*pendingNode)["id"]]->setSlave(addedNodeMapById[(*pendingNode)["pair"]]);
|
||||
} else if ((*pendingNode)["type"] == "slave") {
|
||||
addedNodeMapById[(*pendingNode)["id"]]->setMaster(addedNodeMapById[(*pendingNode)["pair"]]);
|
||||
}
|
||||
scene()->addItem(addedNodeMapById[(*pendingNode)["id"]]);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < pendingEdges.size(); i++) {
|
||||
std::map<QString, QString> *pendingEdge = &pendingEdges[i];
|
||||
SkeletonEditEdgeItem *newEdge = new SkeletonEditEdgeItem();
|
||||
SkeletonEditNodeItem *fromNodeItem = addedNodeMapById[(*pendingEdge)["from"]];
|
||||
SkeletonEditNodeItem *toNodeItem = addedNodeMapById[(*pendingEdge)["to"]];
|
||||
newEdge->setNodes(fromNodeItem, toNodeItem);
|
||||
scene()->addItem(newEdge);
|
||||
std::map<QString, std::map<QString, QString>>::iterator edgeIterator;
|
||||
for (edgeIterator = snapshot->edges.begin(); edgeIterator != snapshot->edges.end(); edgeIterator++) {
|
||||
std::map<QString, QString> *snapshotEdge = &edgeIterator->second;
|
||||
addEdgeItem(nodeItemMap[(*snapshotEdge)["from"]], nodeItemMap[(*snapshotEdge)["to"]]);
|
||||
}
|
||||
|
||||
emit nodesChanged();
|
||||
}
|
||||
|
||||
void SkeletonEditGraphicsView::saveToXmlStream(QXmlStreamWriter *writer)
|
||||
void SkeletonEditGraphicsView::saveToSnapshot(SkeletonSnapshot *snapshot)
|
||||
{
|
||||
writer->setAutoFormatting(true);
|
||||
writer->writeStartDocument();
|
||||
|
||||
writer->writeStartElement("canvas");
|
||||
writer->writeAttribute("width", QString("%1").arg(scene()->sceneRect().width()));
|
||||
writer->writeAttribute("height", QString("%1").arg(scene()->sceneRect().height()));
|
||||
snapshot->canvas["width"] = QString("%1").arg(scene()->sceneRect().width());
|
||||
snapshot->canvas["height"] = QString("%1").arg(scene()->sceneRect().height());
|
||||
|
||||
QList<QGraphicsItem *>::iterator it;
|
||||
QList<QGraphicsItem *> list = scene()->items();
|
||||
std::map<SkeletonEditNodeItem *, int> nodeIdMap;
|
||||
std::map<QGraphicsItemGroup *, int> groupIdMap;
|
||||
|
||||
int nextNodeId = 1;
|
||||
int nextGroupId = 1;
|
||||
std::map<SkeletonEditNodeItem *, QString> nodeIdMap;
|
||||
for (it = list.begin(); it != list.end(); ++it) {
|
||||
if ((*it)->data(0).toString() == "node") {
|
||||
SkeletonEditNodeItem *nodeItem = static_cast<SkeletonEditNodeItem *>(*it);
|
||||
nodeIdMap[nodeItem] = nextNodeId;
|
||||
QString nodeId = QString("node%1").arg(nextNodeId);
|
||||
std::map<QString, QString> *snapshotNode = &snapshot->nodes[nodeId];
|
||||
(*snapshotNode)["id"] = nodeId;
|
||||
(*snapshotNode)["sideColorName"] = nodeItem->sideColorName();
|
||||
(*snapshotNode)["radius"] = QString("%1").arg(nodeItem->radius());
|
||||
QPointF origin = nodeItem->origin();
|
||||
(*snapshotNode)["x"] = QString("%1").arg(origin.x());
|
||||
(*snapshotNode)["y"] = QString("%1").arg(origin.y());
|
||||
nodeIdMap[nodeItem] = nodeId;
|
||||
nextNodeId++;
|
||||
}
|
||||
}
|
||||
writer->writeStartElement("nodes");
|
||||
|
||||
for (it = list.begin(); it != list.end(); ++it) {
|
||||
if ((*it)->data(0).toString() == "node") {
|
||||
SkeletonEditNodeItem *nodeItem = static_cast<SkeletonEditNodeItem *>(*it);
|
||||
writer->writeStartElement("node");
|
||||
std::map<QGraphicsItemGroup *, int>::iterator findGroup = groupIdMap.find(nodeItem->group());
|
||||
if (findGroup == groupIdMap.end()) {
|
||||
groupIdMap[nodeItem->group()] = nextGroupId++;
|
||||
}
|
||||
writer->writeAttribute("id", QString("node%1").arg(nodeIdMap[nodeItem]));
|
||||
writer->writeAttribute("group", QString("group%1").arg(groupIdMap[nodeItem->group()]));
|
||||
writer->writeAttribute("type", nodeItem->isMaster() ? "master" : "slave");
|
||||
writer->writeAttribute("pair", QString("node%1").arg(nodeIdMap[nodeItem->pair()]));
|
||||
writer->writeAttribute("radius", QString("%1").arg(nodeItem->radius()));
|
||||
writer->writeStartElement("origin");
|
||||
QPointF origin = nodeItem->origin();
|
||||
writer->writeAttribute("x", QString("%1").arg(origin.x()));
|
||||
writer->writeAttribute("y", QString("%1").arg(origin.y()));
|
||||
writer->writeEndElement();
|
||||
writer->writeEndElement();
|
||||
QString nodeId = nodeIdMap[nodeItem];
|
||||
std::map<QString, QString> *snapshotNode = &snapshot->nodes[nodeId];
|
||||
(*snapshotNode)["nextSidePair"] = nodeIdMap[nodeItem->nextSidePair()];
|
||||
}
|
||||
}
|
||||
writer->writeEndElement();
|
||||
writer->writeStartElement("edges");
|
||||
|
||||
int nextEdgeId = 1;
|
||||
for (it = list.begin(); it != list.end(); ++it) {
|
||||
if ((*it)->data(0).toString() == "edge") {
|
||||
SkeletonEditEdgeItem *edgeItem = static_cast<SkeletonEditEdgeItem *>(*it);
|
||||
writer->writeStartElement("edge");
|
||||
writer->writeAttribute("id", QString("edge%1").arg(nextEdgeId));
|
||||
writer->writeAttribute("from", QString("node%1").arg(nodeIdMap[edgeItem->firstNode()]));
|
||||
writer->writeAttribute("to", QString("node%1").arg(nodeIdMap[edgeItem->secondNode()]));
|
||||
writer->writeEndElement();
|
||||
QString edgeId = QString("edge%1").arg(nextEdgeId);
|
||||
std::map<QString, QString> *snapshotEdge = &snapshot->edges[edgeId];
|
||||
(*snapshotEdge)["id"] = edgeId;
|
||||
(*snapshotEdge)["from"] = nodeIdMap[edgeItem->firstNode()];
|
||||
(*snapshotEdge)["to"] = nodeIdMap[edgeItem->secondNode()];
|
||||
nextEdgeId++;
|
||||
}
|
||||
}
|
||||
writer->writeEndElement();
|
||||
|
||||
writer->writeEndElement();
|
||||
writer->writeEndDocument();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <QXmlStreamReader>
|
||||
#include "skeletoneditnodeitem.h"
|
||||
#include "skeletoneditedgeitem.h"
|
||||
#include "skeletonsnapshot.h"
|
||||
|
||||
class SkeletonEditGraphicsView : public QGraphicsView
|
||||
{
|
||||
|
@ -22,10 +23,10 @@ public slots:
|
|||
public:
|
||||
SkeletonEditGraphicsView(QWidget *parent = 0);
|
||||
void updateBackgroundImage(const QImage &image);
|
||||
void saveToXmlStream(QXmlStreamWriter *writer);
|
||||
void loadFromXmlStream(QXmlStreamReader &reader);
|
||||
bool hasBackgroundImage();
|
||||
QPixmap backgroundImage();
|
||||
void saveToSnapshot(SkeletonSnapshot *snapshot);
|
||||
void loadFromSnapshot(SkeletonSnapshot *snapshot);
|
||||
protected:
|
||||
void mouseMoveEvent(QMouseEvent *event);
|
||||
void wheelEvent(QWheelEvent *event);
|
||||
|
@ -46,7 +47,6 @@ private:
|
|||
QPointF m_lastMousePos;
|
||||
bool m_isMovingNodeItem;
|
||||
bool m_backgroundLoaded;
|
||||
SkeletonEditEdgeItem *m_selectedEdgeItem;
|
||||
private:
|
||||
void toggleAddNodeMode();
|
||||
void applyAddNodeMode();
|
||||
|
@ -55,14 +55,17 @@ private:
|
|||
SkeletonEditEdgeItem *findEdgeItemByNodePair(SkeletonEditNodeItem *first,
|
||||
SkeletonEditNodeItem *second);
|
||||
void setNextStartNodeItem(SkeletonEditNodeItem *item);
|
||||
float findXForSlave(float x);
|
||||
bool canNodeItemMoveTo(SkeletonEditNodeItem *item, QPointF moveTo);
|
||||
void AddItemRadius(QGraphicsEllipseItem *item, float delta);
|
||||
bool canAddItemRadius(QGraphicsEllipseItem *item, float delta);
|
||||
void adjustItems(QSizeF oldSceneSize, QSizeF newSceneSize);
|
||||
void removeSelectedItems();
|
||||
void removeNodeItem(SkeletonEditNodeItem *nodeItem);
|
||||
void removeGroupByNodeItem(SkeletonEditNodeItem *nodeItem);
|
||||
void removeNodeItemAndSidePairs(SkeletonEditNodeItem *nodeItem);
|
||||
void fetchNodeItemAndAllSidePairs(SkeletonEditNodeItem *nodeItem, std::vector<SkeletonEditNodeItem *> *sidePairs);
|
||||
SkeletonEditNodeItem *addNodeItemAndSidePairs(QRectF area, SkeletonEditNodeItem *fromNodeItem, const QString &sideColorName="red");
|
||||
SkeletonEditNodeItem *addNodeItem(float originX, float originY, float radius);
|
||||
void addEdgeItem(SkeletonEditNodeItem *first, SkeletonEditNodeItem *second);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,50 +4,69 @@
|
|||
|
||||
SkeletonEditNodeItem::SkeletonEditNodeItem(const QRectF &rect, QGraphicsItem *parent) :
|
||||
QGraphicsEllipseItem(rect, parent),
|
||||
m_highlighted(false),
|
||||
m_isNextStartNode(false),
|
||||
m_master(NULL),
|
||||
m_slave(NULL)
|
||||
m_hovered(false),
|
||||
m_checked(false),
|
||||
m_nextSidePair(NULL),
|
||||
m_sideColor(Theme::red),
|
||||
m_sideColorName("red")
|
||||
{
|
||||
setData(0, "node");
|
||||
updateBorder();
|
||||
updateAppearance();
|
||||
}
|
||||
|
||||
bool SkeletonEditNodeItem::isSlave()
|
||||
const QString &SkeletonEditNodeItem::sideColorName()
|
||||
{
|
||||
return NULL != m_master;
|
||||
return m_sideColorName;
|
||||
}
|
||||
|
||||
bool SkeletonEditNodeItem::isMaster()
|
||||
QString SkeletonEditNodeItem::nextSideColorName()
|
||||
{
|
||||
return NULL == m_master;
|
||||
return Theme::nextSideColorNameMap[m_sideColorName];
|
||||
}
|
||||
|
||||
SkeletonEditNodeItem *SkeletonEditNodeItem::master()
|
||||
void SkeletonEditNodeItem::setSideColorName(const QString &name)
|
||||
{
|
||||
return m_master ? m_master : this;
|
||||
m_sideColorName = name;
|
||||
m_sideColor = Theme::sideColorNameToColorMap[m_sideColorName];
|
||||
updateAppearance();
|
||||
}
|
||||
|
||||
void SkeletonEditNodeItem::setMaster(SkeletonEditNodeItem *nodeItem)
|
||||
bool SkeletonEditNodeItem::hovered()
|
||||
{
|
||||
m_master = nodeItem;
|
||||
updateBorder();
|
||||
return m_hovered;
|
||||
}
|
||||
|
||||
void SkeletonEditNodeItem::setSlave(SkeletonEditNodeItem *nodeItem)
|
||||
void SkeletonEditNodeItem::setHovered(bool hovered)
|
||||
{
|
||||
m_slave = nodeItem;
|
||||
updateBorder();
|
||||
m_hovered = hovered;
|
||||
updateAppearance();
|
||||
}
|
||||
|
||||
SkeletonEditNodeItem *SkeletonEditNodeItem::pair()
|
||||
bool SkeletonEditNodeItem::checked()
|
||||
{
|
||||
return m_master ? m_master : m_slave;
|
||||
return m_checked;
|
||||
}
|
||||
|
||||
SkeletonEditNodeItem *SkeletonEditNodeItem::slave()
|
||||
void SkeletonEditNodeItem::setChecked(bool checked)
|
||||
{
|
||||
return m_slave;
|
||||
m_checked = checked;
|
||||
updateAppearance();
|
||||
}
|
||||
|
||||
SkeletonEditNodeItem *SkeletonEditNodeItem::nextSidePair()
|
||||
{
|
||||
return m_nextSidePair;
|
||||
}
|
||||
|
||||
void SkeletonEditNodeItem::setNextSidePair(SkeletonEditNodeItem *nodeItem)
|
||||
{
|
||||
m_nextSidePair = nodeItem;
|
||||
updateAppearance();
|
||||
}
|
||||
|
||||
const QColor &SkeletonEditNodeItem::sideColor()
|
||||
{
|
||||
return m_sideColor;
|
||||
}
|
||||
|
||||
QPointF SkeletonEditNodeItem::origin()
|
||||
|
@ -76,31 +95,22 @@ void SkeletonEditNodeItem::setOrigin(QPointF point)
|
|||
setRect(newRect);
|
||||
}
|
||||
|
||||
void SkeletonEditNodeItem::setHighlighted(bool highlighted)
|
||||
void SkeletonEditNodeItem::updateAppearance()
|
||||
{
|
||||
m_highlighted = highlighted;
|
||||
if (m_highlighted) {
|
||||
setBrush(QBrush(isMaster() ? Theme::skeletonMasterNodeFillColor : Theme::skeletonSlaveNodeFillColor));
|
||||
} else {
|
||||
setBrush(QBrush(Qt::transparent));
|
||||
}
|
||||
if (m_slave)
|
||||
{
|
||||
m_slave->setHighlighted(highlighted);
|
||||
}
|
||||
}
|
||||
|
||||
void SkeletonEditNodeItem::setIsNextStartNode(bool isNextStartNode)
|
||||
{
|
||||
m_isNextStartNode = isNextStartNode;
|
||||
updateBorder();
|
||||
}
|
||||
|
||||
void SkeletonEditNodeItem::updateBorder()
|
||||
{
|
||||
QPen pen(m_isNextStartNode ?
|
||||
(isMaster() ? Theme::skeletonMasterNodeBorderHighlightColor : Theme::skeletonSlaveNodeBorderHighlightColor) :
|
||||
(isMaster() ? Theme::skeletonMasterNodeBorderColor : Theme::skeletonSlaveNodeBorderColor));
|
||||
pen.setWidth(isMaster() ? Theme::skeletonMasterNodeBorderSize : Theme::skeletonSlaveNodeBorderSize);
|
||||
QColor penColor = m_sideColor;
|
||||
penColor.setAlphaF(m_checked ? Theme::checkedAlpha : Theme::normalAlpha);
|
||||
QPen pen(penColor);
|
||||
pen.setWidth(Theme::skeletonNodeBorderSize);
|
||||
setPen(pen);
|
||||
|
||||
QColor brushColor = m_sideColor;
|
||||
brushColor.setAlphaF((m_hovered || m_checked) ? Theme::fillAlpha : 0);
|
||||
QBrush brush(brushColor);
|
||||
setBrush(brush);
|
||||
}
|
||||
|
||||
QColor SkeletonEditNodeItem::nextSideColor()
|
||||
{
|
||||
return Theme::sideColorNameToColorMap[Theme::nextSideColorNameMap[m_sideColorName]];
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#ifndef SKELETON_EDIT_NODE_ITEM_H
|
||||
#define SKELETON_EDIT_NODE_ITEM_H
|
||||
#include <QGraphicsEllipseItem>
|
||||
#include <map>
|
||||
#include <QString>
|
||||
#include <QColor>
|
||||
|
||||
class SkeletonEditEdgeItem;
|
||||
|
||||
|
@ -9,25 +12,28 @@ class SkeletonEditNodeItem : public QGraphicsEllipseItem
|
|||
public:
|
||||
SkeletonEditNodeItem(const QRectF &rect, QGraphicsItem *parent = 0);
|
||||
QPointF origin();
|
||||
float radius();
|
||||
void setHighlighted(bool highlited);
|
||||
void setIsNextStartNode(bool isNextStartNode);
|
||||
bool isSlave();
|
||||
bool isMaster();
|
||||
void setMaster(SkeletonEditNodeItem *nodeItem);
|
||||
void setSlave(SkeletonEditNodeItem *nodeItem);
|
||||
SkeletonEditNodeItem *master();
|
||||
SkeletonEditNodeItem *slave();
|
||||
SkeletonEditNodeItem *pair();
|
||||
void setRadius(float radius);
|
||||
void setOrigin(QPointF point);
|
||||
float radius();
|
||||
void setRadius(float radius);
|
||||
bool hovered();
|
||||
void setHovered(bool hovered);
|
||||
bool checked();
|
||||
void setChecked(bool checked);
|
||||
SkeletonEditNodeItem *nextSidePair();
|
||||
void setNextSidePair(SkeletonEditNodeItem *nodeItem);
|
||||
const QColor &sideColor();
|
||||
QColor nextSideColor();
|
||||
const QString &sideColorName();
|
||||
QString nextSideColorName();
|
||||
void setSideColorName(const QString &name);
|
||||
private:
|
||||
bool m_highlighted;
|
||||
bool m_isNextStartNode;
|
||||
SkeletonEditNodeItem *m_master;
|
||||
SkeletonEditNodeItem *m_slave;
|
||||
bool m_hovered;
|
||||
bool m_checked;
|
||||
SkeletonEditNodeItem *m_nextSidePair;
|
||||
QColor m_sideColor;
|
||||
QString m_sideColorName;
|
||||
private:
|
||||
void updateBorder();
|
||||
void updateAppearance();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
#include "skeletonsnapshot.h"
|
||||
#include <assert.h>
|
||||
|
||||
SkeletonSnapshot::SkeletonSnapshot() :
|
||||
m_boundingBoxResolved(false),
|
||||
m_rootNodeResolved(false)
|
||||
{
|
||||
}
|
||||
|
||||
void joinNodeAndNeighborsToGroup(std::map<QString, std::vector<QString>> &nodeLinkMap,
|
||||
std::map<QString, int> &nodeGroupMap,
|
||||
const QString &nodeId,
|
||||
int groupId,
|
||||
std::vector<QString> &group)
|
||||
{
|
||||
group.push_back(nodeId);
|
||||
nodeGroupMap[nodeId] = groupId;
|
||||
std::vector<QString> *neighbors = &nodeLinkMap[nodeId];
|
||||
for (size_t i = 0; i < neighbors->size(); i++) {
|
||||
QString neighborNodeId = (*neighbors)[i];
|
||||
if (nodeGroupMap.find(neighborNodeId) != nodeGroupMap.end())
|
||||
continue;
|
||||
nodeGroupMap[neighborNodeId] = groupId;
|
||||
joinNodeAndNeighborsToGroup(nodeLinkMap,
|
||||
nodeGroupMap,
|
||||
neighborNodeId,
|
||||
groupId,
|
||||
group);
|
||||
}
|
||||
}
|
||||
|
||||
void SkeletonSnapshot::splitByConnectivity(std::vector<SkeletonSnapshot> *groups)
|
||||
{
|
||||
std::map<QString, std::vector<QString>> nodeLinkMap;
|
||||
std::map<QString, std::map<QString, QString>>::iterator edgeIterator;
|
||||
for (edgeIterator = edges.begin(); edgeIterator != edges.end(); edgeIterator++) {
|
||||
nodeLinkMap[edgeIterator->second["from"]].push_back(edgeIterator->second["to"]);
|
||||
nodeLinkMap[edgeIterator->second["to"]].push_back(edgeIterator->second["from"]);
|
||||
}
|
||||
std::map<QString, std::map<QString, QString>>::iterator nodeIterator;
|
||||
for (nodeIterator = nodes.begin(); nodeIterator != nodes.end(); nodeIterator++) {
|
||||
nodeLinkMap[nodeIterator->first].push_back(nodeIterator->second["nextSidePair"]);
|
||||
}
|
||||
std::map<QString, int> nodeGroupMap;
|
||||
std::vector<std::vector<QString>> nameGroups;
|
||||
for (nodeIterator = nodes.begin(); nodeIterator != nodes.end(); nodeIterator++) {
|
||||
if (nodeGroupMap.find(nodeIterator->first) != nodeGroupMap.end())
|
||||
continue;
|
||||
std::vector<QString> nameGroup;
|
||||
joinNodeAndNeighborsToGroup(nodeLinkMap,
|
||||
nodeGroupMap,
|
||||
nodeIterator->first,
|
||||
nameGroups.size(),
|
||||
nameGroup);
|
||||
for (size_t i = 0; i < nameGroup.size(); i++) {
|
||||
nodeGroupMap[nameGroup[i]] = nameGroups.size();
|
||||
}
|
||||
nameGroups.push_back(nameGroup);
|
||||
}
|
||||
groups->resize(nameGroups.size());
|
||||
for (edgeIterator = edges.begin(); edgeIterator != edges.end(); edgeIterator++) {
|
||||
int groupIndex = nodeGroupMap[edgeIterator->second["from"]];
|
||||
(*groups)[groupIndex].edges[edgeIterator->first] = edgeIterator->second;
|
||||
}
|
||||
for (nodeIterator = nodes.begin(); nodeIterator != nodes.end(); nodeIterator++) {
|
||||
int groupIndex = nodeGroupMap[nodeIterator->first];
|
||||
(*groups)[groupIndex].nodes[nodeIterator->first] = nodeIterator->second;
|
||||
}
|
||||
for (size_t i = 0; i < groups->size(); i++) {
|
||||
(*groups)[i].canvas = canvas;
|
||||
}
|
||||
}
|
||||
|
||||
const QRectF &SkeletonSnapshot::boundingBoxFront()
|
||||
{
|
||||
if (!m_boundingBoxResolved)
|
||||
resolveBoundingBox();
|
||||
return m_boundingBoxFront;
|
||||
}
|
||||
|
||||
const QRectF &SkeletonSnapshot::boundingBoxSide()
|
||||
{
|
||||
if (!m_boundingBoxResolved)
|
||||
resolveBoundingBox();
|
||||
return m_boundingBoxSide;
|
||||
}
|
||||
|
||||
void SkeletonSnapshot::resolveBoundingBox()
|
||||
{
|
||||
if (m_boundingBoxResolved)
|
||||
return;
|
||||
m_boundingBoxResolved = true;
|
||||
|
||||
float left = -1;
|
||||
float right = -1;
|
||||
float top = -1;
|
||||
float bottom = -1;
|
||||
float zLeft = -1;
|
||||
float zRight = -1;
|
||||
std::map<QString, std::map<QString, QString>>::iterator nodeIterator;
|
||||
for (nodeIterator = nodes.begin(); nodeIterator != nodes.end(); nodeIterator++) {
|
||||
printf("loop node:%s color: %s\n", nodeIterator->first.toUtf8().constData(), nodeIterator->second["sideColorName"].toUtf8().constData());
|
||||
}
|
||||
for (nodeIterator = nodes.begin(); nodeIterator != nodes.end(); nodeIterator++) {
|
||||
if ("red" != nodeIterator->second["sideColorName"])
|
||||
continue;
|
||||
float originX = nodeIterator->second["x"].toFloat();
|
||||
float originY = nodeIterator->second["y"].toFloat();
|
||||
float originZ = 0;
|
||||
QString nextSidePairId = nodeIterator->second["nextSidePair"];
|
||||
printf("nextSidePair: %s\n", nextSidePairId.toUtf8().constData());
|
||||
std::map<QString, std::map<QString, QString>>::iterator findNextSidePair = nodes.find(nextSidePairId);
|
||||
if (findNextSidePair != nodes.end()) {
|
||||
originZ = findNextSidePair->second["x"].toFloat();
|
||||
}
|
||||
if (left < 0 || originX < left) {
|
||||
left = originX;
|
||||
}
|
||||
if (top < 0 || originY < top) {
|
||||
top = originY;
|
||||
}
|
||||
if (originX > right) {
|
||||
right = originX;
|
||||
}
|
||||
if (originY > bottom) {
|
||||
bottom = originY;
|
||||
}
|
||||
if (zLeft < 0 || originZ < zLeft) {
|
||||
zLeft = originZ;
|
||||
}
|
||||
if (originZ > zRight) {
|
||||
zRight = originZ;
|
||||
}
|
||||
}
|
||||
|
||||
m_boundingBoxFront = QRectF(left, top, right - left, bottom - top);
|
||||
m_boundingBoxSide = QRectF(zLeft, top, zRight - zLeft, bottom - top);
|
||||
}
|
||||
|
||||
QString SkeletonSnapshot::rootNode()
|
||||
{
|
||||
if (!m_rootNodeResolved)
|
||||
resolveRootNode();
|
||||
return m_rootNode;
|
||||
}
|
||||
|
||||
void SkeletonSnapshot::setRootNode(const QString &nodeName)
|
||||
{
|
||||
assert(!nodeName.isEmpty());
|
||||
m_rootNode = nodeName;
|
||||
m_rootNodeResolved = true;
|
||||
}
|
||||
|
||||
QString SkeletonSnapshot::findMaxNeighborNumberNode()
|
||||
{
|
||||
std::map<QString, std::map<QString, QString>>::iterator edgeIterator;
|
||||
std::map<QString, int> nodeNeighborCountMap;
|
||||
for (edgeIterator = edges.begin(); edgeIterator != edges.end(); edgeIterator++) {
|
||||
if ("red" != nodes[edgeIterator->second["from"]]["sideColorName"])
|
||||
continue;
|
||||
nodeNeighborCountMap[edgeIterator->second["from"]]++;
|
||||
nodeNeighborCountMap[edgeIterator->second["to"]]++;
|
||||
}
|
||||
if (nodeNeighborCountMap.size() == 0)
|
||||
return "";
|
||||
auto x = std::max_element(nodeNeighborCountMap.begin(), nodeNeighborCountMap.end(),
|
||||
[](const std::pair<QString, int>& p1, const std::pair<QString, int>& p2) {
|
||||
return p1.second < p2.second;
|
||||
});
|
||||
return x->first;
|
||||
}
|
||||
|
||||
void SkeletonSnapshot::resolveRootNode()
|
||||
{
|
||||
if (m_rootNodeResolved)
|
||||
return;
|
||||
m_rootNodeResolved = true;
|
||||
|
||||
std::map<QString, std::map<QString, QString>>::iterator edgeIterator;
|
||||
std::map<QString, int> nodeNeighborCountMap;
|
||||
for (edgeIterator = edges.begin(); edgeIterator != edges.end(); edgeIterator++) {
|
||||
if ("red" != nodes[edgeIterator->second["from"]]["sideColorName"])
|
||||
continue;
|
||||
nodeNeighborCountMap[edgeIterator->second["from"]]++;
|
||||
nodeNeighborCountMap[edgeIterator->second["to"]]++;
|
||||
}
|
||||
std::map<QString, std::map<QString, QString>>::iterator nodeIterator;
|
||||
|
||||
// First try to select the node with more than 2 neighbors and have the largest radius.
|
||||
float maxRadius = 0;
|
||||
m_rootNode = "";
|
||||
for (nodeIterator = nodes.begin(); nodeIterator != nodes.end(); nodeIterator++) {
|
||||
if ("red" != nodeIterator->second["sideColorName"])
|
||||
continue;
|
||||
if (nodeNeighborCountMap[nodeIterator->first] < 3)
|
||||
continue;
|
||||
float radius = nodeIterator->second["radius"].toFloat();
|
||||
if (radius > maxRadius) {
|
||||
maxRadius = radius;
|
||||
m_rootNode = nodeIterator->first;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_rootNode.isEmpty())
|
||||
m_rootNode = findMaxNeighborNumberNode();
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef SKELETON_SNAPSHOT_H
|
||||
#define SKELETON_SNAPSHOT_H
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <QString>
|
||||
#include <QRectF>
|
||||
#include <QSizeF>
|
||||
|
||||
class SkeletonSnapshot
|
||||
{
|
||||
public:
|
||||
std::map<QString, QString> canvas;
|
||||
std::map<QString, std::map<QString, QString>> nodes;
|
||||
std::map<QString, std::map<QString, QString>> edges;
|
||||
public:
|
||||
SkeletonSnapshot();
|
||||
void splitByConnectivity(std::vector<SkeletonSnapshot> *groups);
|
||||
QString rootNode();
|
||||
void setRootNode(const QString &nodeName);
|
||||
const QRectF &boundingBoxFront();
|
||||
const QRectF &boundingBoxSide();
|
||||
private:
|
||||
QString m_rootNode;
|
||||
QRectF m_boundingBoxFront;
|
||||
QRectF m_boundingBoxSide;
|
||||
bool m_boundingBoxResolved;
|
||||
bool m_rootNodeResolved;
|
||||
private:
|
||||
void resolveBoundingBox();
|
||||
void resolveRootNode();
|
||||
QString findMaxNeighborNumberNode();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -2,6 +2,7 @@
|
|||
#include "meshlite.h"
|
||||
#include "skeletoneditnodeitem.h"
|
||||
#include "skeletoneditedgeitem.h"
|
||||
#include "skeletonsnapshot.h"
|
||||
#include <vector>
|
||||
|
||||
#define USE_CARVE 1
|
||||
|
@ -202,67 +203,10 @@ struct NodeItemInfo
|
|||
int neighborCount;
|
||||
};
|
||||
|
||||
SkeletonToMesh::SkeletonToMesh(SkeletonEditGraphicsView *graphicsView) :
|
||||
m_mesh(NULL)
|
||||
SkeletonToMesh::SkeletonToMesh(SkeletonSnapshot *snapshot) :
|
||||
m_mesh(NULL),
|
||||
m_snapshot(*snapshot)
|
||||
{
|
||||
QList<QGraphicsItem *>::iterator it;
|
||||
QList<QGraphicsItem *> list = graphicsView->scene()->items();
|
||||
std::map<SkeletonEditNodeItem *, NodeItemInfo> nodeItemsMap;
|
||||
std::map<QGraphicsItemGroup *, int> groupIdsMap;
|
||||
int maxNeighborCount = 0;
|
||||
for (it = list.begin(); it != list.end(); ++it) {
|
||||
if ((*it)->data(0).toString() == "edge") {
|
||||
SkeletonEditEdgeItem *edgeItem = static_cast<SkeletonEditEdgeItem *>(*it);
|
||||
SkeletonEditNodeItem *nodeItems[] = {edgeItem->firstNode(), edgeItem->secondNode()};
|
||||
int nodeIndices[] = {0, 0};
|
||||
SkeletonGroup *skeletonGroup = NULL;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
SkeletonEditNodeItem *nodeItem = nodeItems[i];
|
||||
std::map<QGraphicsItemGroup *, int>::iterator findGroupId = groupIdsMap.find(nodeItem->group());
|
||||
if (findGroupId == groupIdsMap.end()) {
|
||||
SkeletonGroup group;
|
||||
group.maxNeighborCount = 0;
|
||||
group.rootNode = 0;
|
||||
group.bmeshId = -1;
|
||||
group.meshId = -1;
|
||||
groupIdsMap[nodeItem->group()] = m_groups.size();
|
||||
m_groups.push_back(group);
|
||||
}
|
||||
skeletonGroup = &m_groups[groupIdsMap[nodeItem->group()]];
|
||||
std::map<SkeletonEditNodeItem *, NodeItemInfo>::iterator findNode = nodeItemsMap.find(nodeItem);
|
||||
if (findNode == nodeItemsMap.end()) {
|
||||
SkeletonNode node;
|
||||
NodeItemInfo info;
|
||||
QPointF origin = nodeItem->origin();
|
||||
|
||||
node.originX = origin.x();
|
||||
node.originY = origin.y();
|
||||
node.originZ = nodeItem->slave()->origin().x();
|
||||
node.bmeshNodeId = -1;
|
||||
node.radius = nodeItem->radius();
|
||||
node.thickness = nodeItem->slave()->radius();
|
||||
|
||||
info.index = skeletonGroup->nodes.size();
|
||||
info.neighborCount = 1;
|
||||
|
||||
nodeIndices[i] = info.index;
|
||||
nodeItemsMap[nodeItem] = info;
|
||||
skeletonGroup->nodes.push_back(node);
|
||||
} else {
|
||||
nodeIndices[i] = findNode->second.index;
|
||||
findNode->second.neighborCount++;
|
||||
if (findNode->second.neighborCount > skeletonGroup->maxNeighborCount) {
|
||||
skeletonGroup->rootNode = findNode->second.index;
|
||||
maxNeighborCount = findNode->second.neighborCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
SkeletonEdge edge;
|
||||
edge.firstNode = nodeIndices[0];
|
||||
edge.secondNode = nodeIndices[1];
|
||||
skeletonGroup->edges.push_back(edge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SkeletonToMesh::~SkeletonToMesh()
|
||||
|
@ -291,103 +235,64 @@ Mesh *SkeletonToMesh::takeResultMesh()
|
|||
|
||||
void SkeletonToMesh::process()
|
||||
{
|
||||
if (m_groups.size() <= 0) {
|
||||
emit finished();
|
||||
return;
|
||||
}
|
||||
float left = -1;
|
||||
float right = -1;
|
||||
float top = -1;
|
||||
float bottom = -1;
|
||||
float zLeft = -1;
|
||||
float zRight = -1;
|
||||
for (size_t i = 0; i < m_groups.size(); i++) {
|
||||
SkeletonGroup *group = &m_groups[i];
|
||||
for (size_t j = 0; j < group->nodes.size(); j++) {
|
||||
SkeletonNode *node = &group->nodes[j];
|
||||
if (left < 0 || node->originX < left) {
|
||||
left = node->originX;
|
||||
}
|
||||
if (top < 0 || node->originY < top) {
|
||||
top = node->originY;
|
||||
}
|
||||
if (node->originX > right) {
|
||||
right = node->originX;
|
||||
}
|
||||
if (node->originY > bottom) {
|
||||
bottom = node->originY;
|
||||
}
|
||||
if (zLeft < 0 || node->originZ < zLeft) {
|
||||
zLeft = node->originZ;
|
||||
}
|
||||
if (node->originZ > zRight) {
|
||||
zRight = node->originZ;
|
||||
}
|
||||
}
|
||||
}
|
||||
float height = bottom - top;
|
||||
if (height <= 0) {
|
||||
emit finished();
|
||||
return;
|
||||
}
|
||||
float zWidth = right - left;
|
||||
void *context = meshlite_create_context();
|
||||
std::vector<SkeletonSnapshot> groups;
|
||||
m_snapshot.splitByConnectivity(&groups);
|
||||
|
||||
for (size_t i = 0; i < m_groups.size(); i++) {
|
||||
SkeletonGroup *group = &m_groups[i];
|
||||
group->bmeshId = meshlite_bmesh_create(context);
|
||||
for (size_t j = 0; j < group->nodes.size(); j++) {
|
||||
SkeletonNode *node = &group->nodes[j];
|
||||
float x = (node->originX - left - height / 2) / height;
|
||||
float y = (node->originY - top - height / 2) / height;
|
||||
float z = (node->originZ - zLeft - zWidth / 2) / height;
|
||||
float r = node->radius / height;
|
||||
float t = node->thickness / height;
|
||||
node->bmeshNodeId = meshlite_bmesh_add_node(context, group->bmeshId, x, y, z, r, t);
|
||||
}
|
||||
for (size_t j = 0; j < group->edges.size(); j++) {
|
||||
SkeletonNode *firstNode = &group->nodes[group->edges[j].firstNode];
|
||||
SkeletonNode *secondNode = &group->nodes[group->edges[j].secondNode];
|
||||
meshlite_bmesh_add_edge(context, group->bmeshId, firstNode->bmeshNodeId, secondNode->bmeshNodeId);
|
||||
}
|
||||
group->meshId = meshlite_bmesh_generate_mesh(context, group->bmeshId, group->nodes[group->rootNode].bmeshNodeId);
|
||||
std::vector<int> meshIds;
|
||||
void *meshliteContext = meshlite_create_context();
|
||||
for (size_t i = 0; i < groups.size(); i++) {
|
||||
SkeletonSnapshot *skeleton = &groups[i];
|
||||
QRectF front = skeleton->boundingBoxFront();
|
||||
QRectF side = skeleton->boundingBoxSide();
|
||||
|
||||
std::map<QString, int> bmeshNodeMap;
|
||||
|
||||
std::map<QString, std::map<QString, QString>>::iterator nodeIterator;
|
||||
int bmeshId = meshlite_bmesh_create(meshliteContext);
|
||||
for (nodeIterator = skeleton->nodes.begin(); nodeIterator != skeleton->nodes.end(); nodeIterator++) {
|
||||
if ("red" != nodeIterator->second["sideColorName"])
|
||||
continue;
|
||||
std::map<QString, std::map<QString, QString>>::iterator nextSidePair = skeleton->nodes.find(nodeIterator->second["nextSidePair"]);
|
||||
if (nextSidePair == skeleton->nodes.end())
|
||||
continue;
|
||||
float x = (nodeIterator->second["x"].toFloat() - front.left() - front.height() / 2) / front.height();
|
||||
float y = (nodeIterator->second["y"].toFloat() - front.top() - front.height() / 2) / front.height();
|
||||
float z = (nextSidePair->second["x"].toFloat() - side.left() - side.width() / 2) / side.height();
|
||||
float r = nodeIterator->second["radius"].toFloat() / front.height();
|
||||
float t = nextSidePair->second["radius"].toFloat() / side.height();
|
||||
int bmeshNodeId = meshlite_bmesh_add_node(meshliteContext, bmeshId, x, y, z, r, t);
|
||||
printf("meshlite_bmesh_add_node x:%f y:%f z:%f r:%f t:%f nodeName:%s bmeshNodeId:%d\n", x, y, z, r, t, nodeIterator->first.toUtf8().constData(), bmeshNodeId);
|
||||
bmeshNodeMap[nodeIterator->first] = bmeshNodeId;
|
||||
}
|
||||
|
||||
int mergedMeshId = m_groups[0].meshId;
|
||||
for (size_t i = 1; i < m_groups.size(); i++) {
|
||||
mergedMeshId = meshlite_merge(context, mergedMeshId, m_groups[i].meshId);
|
||||
std::map<QString, std::map<QString, QString>>::iterator edgeIterator;
|
||||
for (edgeIterator = skeleton->edges.begin(); edgeIterator != skeleton->edges.end(); edgeIterator++) {
|
||||
std::map<QString, int>::iterator from = bmeshNodeMap.find(edgeIterator->second["from"]);
|
||||
if (from == bmeshNodeMap.end())
|
||||
continue;
|
||||
std::map<QString, int>::iterator to = bmeshNodeMap.find(edgeIterator->second["to"]);
|
||||
if (to == bmeshNodeMap.end())
|
||||
continue;
|
||||
printf("meshlite_bmesh_add_edge %d -> %d\n", from->second, to->second);
|
||||
meshlite_bmesh_add_edge(meshliteContext, bmeshId, from->second, to->second);
|
||||
}
|
||||
|
||||
/*
|
||||
ExternalMesh *unionPolyhedron = makeExternalMeshFromMeshlite(context, m_groups[0].meshId);
|
||||
for (size_t i = 1; i < m_groups.size(); i++) {
|
||||
ExternalMesh *polyhedron = makeExternalMeshFromMeshlite(context, m_groups[i].meshId);
|
||||
ExternalMesh *newUnionPolyhedron = unionExternalMeshs(unionPolyhedron, polyhedron);
|
||||
delete polyhedron;
|
||||
delete unionPolyhedron;
|
||||
unionPolyhedron = newUnionPolyhedron;
|
||||
if (NULL == unionPolyhedron) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
for (size_t i = 1; i < m_groups.size(); i++) {
|
||||
meshlite_bmesh_destroy(context, m_groups[i].bmeshId);
|
||||
if (bmeshNodeMap.size() > 0 && !skeleton->rootNode().isEmpty()) {
|
||||
int meshId = meshlite_bmesh_generate_mesh(meshliteContext, bmeshId, bmeshNodeMap[skeleton->rootNode()]);
|
||||
meshIds.push_back(meshId);
|
||||
}
|
||||
|
||||
/*
|
||||
if (unionPolyhedron) {
|
||||
int meshIdGeneratedFromExternal = makeMeshliteMeshFromExternal(context, unionPolyhedron);
|
||||
delete unionPolyhedron;
|
||||
|
||||
meshlite_export(context, meshIdGeneratedFromExternal, "/Users/jeremy/testlib.obj");
|
||||
m_mesh = new Mesh(context, meshIdGeneratedFromExternal);
|
||||
meshlite_bmesh_destroy(meshliteContext, bmeshId);
|
||||
}
|
||||
*/
|
||||
|
||||
m_mesh = new Mesh(context, mergedMeshId);
|
||||
if (meshIds.size() > 0) {
|
||||
int mergedMeshId = meshIds[0];
|
||||
for (size_t i = 1; i < meshIds.size(); i++) {
|
||||
mergedMeshId = meshlite_merge(meshliteContext, mergedMeshId, meshIds[i]);
|
||||
}
|
||||
m_mesh = new Mesh(meshliteContext, mergedMeshId);
|
||||
}
|
||||
|
||||
meshlite_destroy_context(context);
|
||||
meshlite_destroy_context(meshliteContext);
|
||||
emit finished();
|
||||
}
|
||||
|
|
|
@ -6,38 +6,13 @@
|
|||
#include <map>
|
||||
#include "skeletoneditgraphicsview.h"
|
||||
#include "mesh.h"
|
||||
|
||||
struct SkeletonNode
|
||||
{
|
||||
float originX;
|
||||
float originY;
|
||||
float originZ;
|
||||
float radius;
|
||||
float thickness;
|
||||
int bmeshNodeId;
|
||||
};
|
||||
|
||||
struct SkeletonEdge
|
||||
{
|
||||
int firstNode;
|
||||
int secondNode;
|
||||
};
|
||||
|
||||
struct SkeletonGroup
|
||||
{
|
||||
std::vector<SkeletonNode> nodes;
|
||||
std::vector<SkeletonEdge> edges;
|
||||
int rootNode;
|
||||
int maxNeighborCount;
|
||||
int bmeshId;
|
||||
int meshId;
|
||||
};
|
||||
#include "skeletonsnapshot.h"
|
||||
|
||||
class SkeletonToMesh : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SkeletonToMesh(SkeletonEditGraphicsView *graphicsView);
|
||||
SkeletonToMesh(SkeletonSnapshot *snapshot);
|
||||
~SkeletonToMesh();
|
||||
Mesh *takeResultMesh();
|
||||
signals:
|
||||
|
@ -46,7 +21,7 @@ public slots:
|
|||
void process();
|
||||
private:
|
||||
Mesh *m_mesh;
|
||||
std::vector<SkeletonGroup> m_groups;
|
||||
SkeletonSnapshot m_snapshot;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -22,13 +22,15 @@ SkeletonWidget::SkeletonWidget(QWidget *parent) :
|
|||
{
|
||||
QHBoxLayout *topLayout = new QHBoxLayout;
|
||||
topLayout->addStretch();
|
||||
topLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
m_graphicsView = new SkeletonEditGraphicsView(this);
|
||||
m_graphicsView->setRenderHint(QPainter::Antialiasing, false);
|
||||
m_graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
m_graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
|
||||
m_graphicsView->setBackgroundBrush(QBrush(QWidget::palette().color(QWidget::backgroundRole()), Qt::SolidPattern));
|
||||
m_graphicsView->setContentsMargins(0, 0, 0, 0);
|
||||
m_graphicsView->setFrameStyle(QFrame::NoFrame);
|
||||
|
||||
m_modelWidget = new ModelWidget(this);
|
||||
m_modelWidget->setMinimumSize(128, 128);
|
||||
|
@ -37,41 +39,48 @@ SkeletonWidget::SkeletonWidget(QWidget *parent) :
|
|||
m_modelWidget->setWindowTitle("3D Model");
|
||||
|
||||
QVBoxLayout *rightLayout = new QVBoxLayout;
|
||||
rightLayout->addSpacing(10);
|
||||
rightLayout->addSpacing(0);
|
||||
rightLayout->addStretch();
|
||||
rightLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
QToolBar *toolbar = new QToolBar;
|
||||
toolbar->setIconSize(QSize(16, 16));
|
||||
toolbar->setIconSize(QSize(18, 18));
|
||||
toolbar->setOrientation(Qt::Vertical);
|
||||
|
||||
QAction *addAction = new QAction(tr("Add"), this);
|
||||
addAction->setIcon(QIcon(":/resources/add.png"));
|
||||
addAction->setIcon(QPixmap(":/resources/add.svg"));
|
||||
toolbar->addAction(addAction);
|
||||
|
||||
QAction *selectAction = new QAction(tr("Select"), this);
|
||||
selectAction->setIcon(QIcon(":/resources/select.png"));
|
||||
selectAction->setIcon(QPixmap(":/resources/rotate.svg"));
|
||||
toolbar->addAction(selectAction);
|
||||
|
||||
QAction *rangeSelectAction = new QAction(tr("Range Select"), this);
|
||||
rangeSelectAction->setIcon(QIcon(":/resources/rangeselect.png"));
|
||||
rangeSelectAction->setIcon(QPixmap(":/resources/zoomin.svg"));
|
||||
toolbar->addAction(rangeSelectAction);
|
||||
|
||||
toolbar->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
QVBoxLayout *leftLayout = new QVBoxLayout;
|
||||
leftLayout->addWidget(toolbar);
|
||||
leftLayout->addStretch();
|
||||
leftLayout->addSpacing(10);
|
||||
leftLayout->addSpacing(0);
|
||||
leftLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
QHBoxLayout *middleLayout = new QHBoxLayout;
|
||||
middleLayout->addLayout(leftLayout);
|
||||
//middleLayout->addLayout(leftLayout);
|
||||
middleLayout->addWidget(m_graphicsView);
|
||||
middleLayout->addLayout(rightLayout);
|
||||
//middleLayout->addLayout(rightLayout);
|
||||
middleLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(topLayout);
|
||||
//mainLayout->addLayout(topLayout);
|
||||
//mainLayout->addSpacing(10);
|
||||
mainLayout->addLayout(middleLayout);
|
||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
setLayout(mainLayout);
|
||||
setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
setWindowTitle(tr("Dust 3D"));
|
||||
|
||||
|
@ -139,7 +148,9 @@ void SkeletonWidget::skeletonChanged()
|
|||
m_skeletonDirty = false;
|
||||
|
||||
QThread *thread = new QThread;
|
||||
m_skeletonToMesh = new SkeletonToMesh(m_graphicsView);
|
||||
SkeletonSnapshot snapshot;
|
||||
m_graphicsView->saveToSnapshot(&snapshot);
|
||||
m_skeletonToMesh = new SkeletonToMesh(&snapshot);
|
||||
m_skeletonToMesh->moveToThread(thread);
|
||||
connect(thread, SIGNAL(started()), m_skeletonToMesh, SLOT(process()));
|
||||
connect(m_skeletonToMesh, SIGNAL(finished()), this, SLOT(meshReady()));
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
#include "skeletonxml.h"
|
||||
|
||||
void saveSkeletonToXmlStream(SkeletonSnapshot *snapshot, QXmlStreamWriter *writer)
|
||||
{
|
||||
writer->setAutoFormatting(true);
|
||||
writer->writeStartDocument();
|
||||
|
||||
writer->writeStartElement("canvas");
|
||||
std::map<QString, QString>::iterator canvasIterator;
|
||||
for (canvasIterator = snapshot->canvas.begin(); canvasIterator != snapshot->canvas.end(); canvasIterator++) {
|
||||
writer->writeAttribute(canvasIterator->first, canvasIterator->second);
|
||||
}
|
||||
|
||||
writer->writeStartElement("nodes");
|
||||
std::map<QString, std::map<QString, QString>>::iterator nodeIterator;
|
||||
for (nodeIterator = snapshot->nodes.begin(); nodeIterator != snapshot->nodes.end(); nodeIterator++) {
|
||||
std::map<QString, QString>::iterator nodeAttributeIterator;
|
||||
writer->writeStartElement("node");
|
||||
for (nodeAttributeIterator = nodeIterator->second.begin(); nodeAttributeIterator != nodeIterator->second.end(); nodeAttributeIterator++) {
|
||||
writer->writeAttribute(nodeAttributeIterator->first, nodeAttributeIterator->second);
|
||||
}
|
||||
writer->writeEndElement();
|
||||
}
|
||||
writer->writeEndElement();
|
||||
|
||||
writer->writeStartElement("edges");
|
||||
std::map<QString, std::map<QString, QString>>::iterator edgeIterator;
|
||||
for (edgeIterator = snapshot->edges.begin(); edgeIterator != snapshot->edges.end(); edgeIterator++) {
|
||||
std::map<QString, QString>::iterator edgeAttributeIterator;
|
||||
writer->writeStartElement("edge");
|
||||
for (edgeAttributeIterator = edgeIterator->second.begin(); edgeAttributeIterator != edgeIterator->second.end(); edgeAttributeIterator++) {
|
||||
writer->writeAttribute(edgeAttributeIterator->first, edgeAttributeIterator->second);
|
||||
}
|
||||
writer->writeEndElement();
|
||||
}
|
||||
writer->writeEndElement();
|
||||
writer->writeEndElement();
|
||||
|
||||
writer->writeEndDocument();
|
||||
}
|
||||
|
||||
void loadSkeletonFromXmlStream(SkeletonSnapshot *snapshot, QXmlStreamReader &reader)
|
||||
{
|
||||
while (!reader.atEnd()) {
|
||||
reader.readNext();
|
||||
if (reader.isStartElement()) {
|
||||
if (reader.name() == "canvas") {
|
||||
foreach(const QXmlStreamAttribute &attr, reader.attributes()) {
|
||||
snapshot->canvas[attr.name().toString()] = attr.value().toString();
|
||||
}
|
||||
} else if (reader.name() == "node") {
|
||||
QString nodeId = reader.attributes().value("id").toString();
|
||||
std::map<QString, QString> *nodeMap = &snapshot->nodes[nodeId];
|
||||
foreach(const QXmlStreamAttribute &attr, reader.attributes()) {
|
||||
(*nodeMap)[attr.name().toString()] = attr.value().toString();
|
||||
}
|
||||
} else if (reader.name() == "edge") {
|
||||
QString nodeId = reader.attributes().value("id").toString();
|
||||
std::map<QString, QString> *edgeMap = &snapshot->edges[nodeId];
|
||||
foreach(const QXmlStreamAttribute &attr, reader.attributes()) {
|
||||
(*edgeMap)[attr.name().toString()] = attr.value().toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef SKELETON_XML_H
|
||||
#define SKELETON_XML_H
|
||||
#include <QXmlStreamWriter>
|
||||
#include "skeletonsnapshot.h"
|
||||
|
||||
void saveSkeletonToXmlStream(SkeletonSnapshot *snapshot, QXmlStreamWriter *writer);
|
||||
void loadSkeletonFromXmlStream(SkeletonSnapshot *snapshot, QXmlStreamReader &reader);
|
||||
|
||||
#endif
|
|
@ -1,17 +1,45 @@
|
|||
#include "theme.h"
|
||||
|
||||
// Red
|
||||
// 0xfc, 0x66, 0x21
|
||||
// 252, 102, 33
|
||||
// 0.99, 0.4, 0.13
|
||||
|
||||
QColor Theme::skeletonMasterNodeBorderColor = QColor(0xfc, 0x66, 0x21, 128);
|
||||
QColor Theme::skeletonMasterNodeBorderHighlightColor = QColor(0xfc, 0x66, 0x21);
|
||||
QColor Theme::skeletonMasterNodeFillColor = QColor(0xfc, 0x66, 0x21, 50);
|
||||
int Theme::skeletonMasterNodeBorderSize = 7;
|
||||
QColor Theme::skeletonSlaveNodeBorderColor = QColor(0xcc, 0xcc, 0xcc, 64);
|
||||
QColor Theme::skeletonSlaveNodeBorderHighlightColor = QColor(0xcc, 0xcc, 0xcc);
|
||||
QColor Theme::skeletonSlaveNodeFillColor = QColor(0xcc, 0xcc, 0xcc, 25);
|
||||
int Theme::skeletonSlaveNodeBorderSize = 7;
|
||||
// Green
|
||||
// 0xaa, 0xeb, 0xc4
|
||||
|
||||
// Blue
|
||||
// 0x2a, 0x5a, 0xac
|
||||
|
||||
// White
|
||||
// 0xf7, 0xd9, 0xc8
|
||||
|
||||
QColor Theme::red = QColor(0xfc, 0x66, 0x21);
|
||||
QColor Theme::green = QColor(0xaa, 0xeb, 0xc4);
|
||||
QColor Theme::blue = QColor(0x2a, 0x5a, 0xac);
|
||||
float Theme::normalAlpha = 128.0 / 255;
|
||||
float Theme::checkedAlpha = 1.0;
|
||||
float Theme::fillAlpha = 50.0 / 255;
|
||||
int Theme::skeletonNodeBorderSize = 1;
|
||||
int Theme::skeletonEdgeWidth = 1;
|
||||
|
||||
std::map<QString, QString> createSideColorNameMap() {
|
||||
std::map<QString, QString> map;
|
||||
map["red"] = "green";
|
||||
map["green"] = "red";
|
||||
return map;
|
||||
}
|
||||
|
||||
std::map<QString, QColor> createSideColorNameToColorMap() {
|
||||
std::map<QString, QColor> map;
|
||||
map["red"] = Theme::red;
|
||||
map["green"] = Theme::green;
|
||||
return map;
|
||||
}
|
||||
|
||||
std::map<QString, QString> Theme::nextSideColorNameMap = createSideColorNameMap();
|
||||
std::map<QString, QColor> Theme::sideColorNameToColorMap = createSideColorNameToColorMap();
|
||||
|
||||
QString Theme::tabButtonSelectedStylesheet = "QPushButton { color: #efefef; background-color: #fc6621; border: 0px; padding-top: 2px; padding-bottom: 2px; padding-left: 25px; padding-right: 25px;}";
|
||||
QString Theme::tabButtonStylesheet = "QPushButton { color: #efefef; background-color: #353535; border: 0px; padding-top: 2px; padding-bottom: 2px; padding-left: 25px; padding-right: 25px;}";
|
||||
|
||||
|
|
19
src/theme.h
|
@ -2,20 +2,23 @@
|
|||
#define THEME_H
|
||||
#include <QColor>
|
||||
#include <QString>
|
||||
#include <map>
|
||||
|
||||
class Theme
|
||||
{
|
||||
public:
|
||||
static QColor skeletonMasterNodeBorderColor;
|
||||
static QColor skeletonMasterNodeBorderHighlightColor;
|
||||
static QColor skeletonMasterNodeFillColor;
|
||||
static int skeletonMasterNodeBorderSize;
|
||||
static QColor skeletonSlaveNodeBorderColor;
|
||||
static QColor skeletonSlaveNodeBorderHighlightColor;
|
||||
static QColor skeletonSlaveNodeFillColor;
|
||||
static int skeletonSlaveNodeBorderSize;
|
||||
static QColor red;
|
||||
static QColor green;
|
||||
static QColor blue;
|
||||
static float normalAlpha;
|
||||
static float checkedAlpha;
|
||||
static float fillAlpha;
|
||||
static int skeletonNodeBorderSize;
|
||||
static int skeletonEdgeWidth;
|
||||
static QString tabButtonSelectedStylesheet;
|
||||
static QString tabButtonStylesheet;
|
||||
static std::map<QString, QString> nextSideColorNameMap;
|
||||
static std::map<QString, QColor> sideColorNameToColorMap;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,150 +0,0 @@
|
|||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: sans-serif;
|
||||
font-size: 1em;
|
||||
line-height: 1.5;
|
||||
color: #555;
|
||||
background: #fff;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.5em;
|
||||
font-weight: normal;
|
||||
}
|
||||
small {
|
||||
font-size: .66666667em;
|
||||
}
|
||||
a {
|
||||
color: #e74c3c;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover, a:focus {
|
||||
box-shadow: 0 1px #e74c3c;
|
||||
}
|
||||
.bshadow0, input {
|
||||
box-shadow: inset 0 -2px #e7e7e7;
|
||||
}
|
||||
input:hover {
|
||||
box-shadow: inset 0 -2px #ccc;
|
||||
}
|
||||
input, fieldset {
|
||||
font-size: 1em;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
input {
|
||||
color: inherit;
|
||||
line-height: 1.5;
|
||||
height: 1.5em;
|
||||
padding: .25em 0;
|
||||
}
|
||||
input:focus {
|
||||
outline: none;
|
||||
box-shadow: inset 0 -2px #449fdb;
|
||||
}
|
||||
.glyph {
|
||||
font-size: 16px;
|
||||
width: 15em;
|
||||
padding-bottom: 1em;
|
||||
margin-right: 4em;
|
||||
margin-bottom: 1em;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
}
|
||||
.liga {
|
||||
width: 80%;
|
||||
width: calc(100% - 2.5em);
|
||||
}
|
||||
.talign-right {
|
||||
text-align: right;
|
||||
}
|
||||
.talign-center {
|
||||
text-align: center;
|
||||
}
|
||||
.bgc1 {
|
||||
background: #f1f1f1;
|
||||
}
|
||||
.fgc1 {
|
||||
color: #999;
|
||||
}
|
||||
.fgc0 {
|
||||
color: #000;
|
||||
}
|
||||
p {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
.mvm {
|
||||
margin-top: .75em;
|
||||
margin-bottom: .75em;
|
||||
}
|
||||
.mtn {
|
||||
margin-top: 0;
|
||||
}
|
||||
.mtl, .mal {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
.mbl, .mal {
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
.mal, .mhl {
|
||||
margin-left: 1.5em;
|
||||
margin-right: 1.5em;
|
||||
}
|
||||
.mhmm {
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
.mls {
|
||||
margin-left: .25em;
|
||||
}
|
||||
.ptl {
|
||||
padding-top: 1.5em;
|
||||
}
|
||||
.pbs, .pvs {
|
||||
padding-bottom: .25em;
|
||||
}
|
||||
.pvs, .pts {
|
||||
padding-top: .25em;
|
||||
}
|
||||
.unit {
|
||||
float: left;
|
||||
}
|
||||
.unitRight {
|
||||
float: right;
|
||||
}
|
||||
.size1of2 {
|
||||
width: 50%;
|
||||
}
|
||||
.size1of1 {
|
||||
width: 100%;
|
||||
}
|
||||
.clearfix:before, .clearfix:after {
|
||||
content: " ";
|
||||
display: table;
|
||||
}
|
||||
.clearfix:after {
|
||||
clear: both;
|
||||
}
|
||||
.hidden-true {
|
||||
display: none;
|
||||
}
|
||||
.textbox0 {
|
||||
width: 3em;
|
||||
background: #f1f1f1;
|
||||
padding: .25em .5em;
|
||||
line-height: 1.5;
|
||||
height: 1.5em;
|
||||
}
|
||||
#testDrive {
|
||||
display: block;
|
||||
padding-top: 24px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.fs0 {
|
||||
font-size: 16px;
|
||||
}
|
||||
.fs1 {
|
||||
font-size: 32px;
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
if (!('boxShadow' in document.body.style)) {
|
||||
document.body.setAttribute('class', 'noBoxShadow');
|
||||
}
|
||||
|
||||
document.body.addEventListener("click", function(e) {
|
||||
var target = e.target;
|
||||
if (target.tagName === "INPUT" &&
|
||||
target.getAttribute('class').indexOf('liga') === -1) {
|
||||
target.select();
|
||||
}
|
||||
});
|
||||
|
||||
(function() {
|
||||
var fontSize = document.getElementById('fontSize'),
|
||||
testDrive = document.getElementById('testDrive'),
|
||||
testText = document.getElementById('testText');
|
||||
function updateTest() {
|
||||
testDrive.innerHTML = testText.value || String.fromCharCode(160);
|
||||
if (window.icomoonLiga) {
|
||||
window.icomoonLiga(testDrive);
|
||||
}
|
||||
}
|
||||
function updateSize() {
|
||||
testDrive.style.fontSize = fontSize.value + 'px';
|
||||
}
|
||||
fontSize.addEventListener('change', updateSize, false);
|
||||
testText.addEventListener('input', updateTest, false);
|
||||
testText.addEventListener('change', updateTest, false);
|
||||
updateSize();
|
||||
}());
|
Before Width: | Height: | Size: 372 KiB |
|
@ -1,406 +0,0 @@
|
|||
/* To avoid CSS expressions while still supporting IE 7 and IE 6, use this script */
|
||||
/* The script tag referencing this file must be placed before the ending body tag. */
|
||||
|
||||
/* Use conditional comments in order to target IE 7 and older:
|
||||
<!--[if lt IE 8]><!-->
|
||||
<script src="ie7/ie7.js"></script>
|
||||
<!--<![endif]-->
|
||||
*/
|
||||
|
||||
(function() {
|
||||
function addIcon(el, entity) {
|
||||
var html = el.innerHTML;
|
||||
el.innerHTML = '<span style="font-family: \'captainicon\'">' + entity + '</span>' + html;
|
||||
}
|
||||
var icons = {
|
||||
'icon-001': '',
|
||||
'icon-002': '',
|
||||
'icon-003': '',
|
||||
'icon-004': '',
|
||||
'icon-005': '',
|
||||
'icon-006': '',
|
||||
'icon-007': '',
|
||||
'icon-008': '',
|
||||
'icon-009': '',
|
||||
'icon-010': '',
|
||||
'icon-011': '',
|
||||
'icon-012': '',
|
||||
'icon-013': '',
|
||||
'icon-014': '',
|
||||
'icon-015': '',
|
||||
'icon-016': '',
|
||||
'icon-017': '',
|
||||
'icon-018': '',
|
||||
'icon-019': '',
|
||||
'icon-020': '',
|
||||
'icon-021': '',
|
||||
'icon-022': '',
|
||||
'icon-023': '',
|
||||
'icon-024': '',
|
||||
'icon-025': '',
|
||||
'icon-026': '',
|
||||
'icon-027': '',
|
||||
'icon-028': '',
|
||||
'icon-029': '',
|
||||
'icon-030': '',
|
||||
'icon-031': '',
|
||||
'icon-032': '',
|
||||
'icon-033': '',
|
||||
'icon-034': '',
|
||||
'icon-035': '',
|
||||
'icon-036': '',
|
||||
'icon-037': '',
|
||||
'icon-038': '',
|
||||
'icon-039': '',
|
||||
'icon-040': '',
|
||||
'icon-041': '',
|
||||
'icon-042': '',
|
||||
'icon-043': '',
|
||||
'icon-044': '',
|
||||
'icon-045': '',
|
||||
'icon-046': '',
|
||||
'icon-047': '',
|
||||
'icon-048': '',
|
||||
'icon-049': '',
|
||||
'icon-050': '',
|
||||
'icon-051': '',
|
||||
'icon-052': '',
|
||||
'icon-053': '',
|
||||
'icon-054': '',
|
||||
'icon-055': '',
|
||||
'icon-056': '',
|
||||
'icon-057': '',
|
||||
'icon-058': '',
|
||||
'icon-059': '',
|
||||
'icon-060': '',
|
||||
'icon-061': '',
|
||||
'icon-062': '',
|
||||
'icon-063': '',
|
||||
'icon-064': '',
|
||||
'icon-065': '',
|
||||
'icon-066': '',
|
||||
'icon-067': '',
|
||||
'icon-068': '',
|
||||
'icon-069': '',
|
||||
'icon-070': '',
|
||||
'icon-071': '',
|
||||
'icon-072': '',
|
||||
'icon-073': '',
|
||||
'icon-074': '',
|
||||
'icon-075': '',
|
||||
'icon-076': '',
|
||||
'icon-077': '',
|
||||
'icon-078': '',
|
||||
'icon-079': '',
|
||||
'icon-080': '',
|
||||
'icon-081': '',
|
||||
'icon-082': '',
|
||||
'icon-083': '',
|
||||
'icon-084': '',
|
||||
'icon-085': '',
|
||||
'icon-086': '',
|
||||
'icon-087': '',
|
||||
'icon-088': '',
|
||||
'icon-089': '',
|
||||
'icon-090': '',
|
||||
'icon-091': '',
|
||||
'icon-092': '',
|
||||
'icon-093': '',
|
||||
'icon-094': '',
|
||||
'icon-095': '',
|
||||
'icon-096': '',
|
||||
'icon-097': '',
|
||||
'icon-98': '',
|
||||
'icon-099': '',
|
||||
'icon-100': '',
|
||||
'icon-101': '',
|
||||
'icon-102': '',
|
||||
'icon-103': '',
|
||||
'icon-104': '',
|
||||
'icon-105': '',
|
||||
'icon-106': '',
|
||||
'icon-107': '',
|
||||
'icon-108': '',
|
||||
'icon-109': '',
|
||||
'icon-110': '',
|
||||
'icon-111': '',
|
||||
'icon-112': '',
|
||||
'icon-113': '',
|
||||
'icon-114': '',
|
||||
'icon-115': '',
|
||||
'icon-116': '',
|
||||
'icon-117': '',
|
||||
'icon-118': '',
|
||||
'icon-119': '',
|
||||
'icon-120': '',
|
||||
'icon-121': '',
|
||||
'icon-122': '',
|
||||
'icon-123': '',
|
||||
'icon-124': '',
|
||||
'icon-125': '',
|
||||
'icon-126': '',
|
||||
'icon-127': '',
|
||||
'icon-128': '',
|
||||
'icon-129': '',
|
||||
'icon-130': '',
|
||||
'icon-131': '',
|
||||
'icon-132': '',
|
||||
'icon-133': '',
|
||||
'icon-134': '',
|
||||
'icon-135': '',
|
||||
'icon-136': '',
|
||||
'icon-137': '',
|
||||
'icon-138': '',
|
||||
'icon-139': '',
|
||||
'icon-140': '',
|
||||
'icon-141': '',
|
||||
'icon-142': '',
|
||||
'icon-143': '',
|
||||
'icon-144': '',
|
||||
'icon-145': '',
|
||||
'icon-146': '',
|
||||
'icon-147': '',
|
||||
'icon-148': '',
|
||||
'icon-149': '',
|
||||
'icon-150': '',
|
||||
'icon-151': '',
|
||||
'icon-152': '',
|
||||
'icon-153': '',
|
||||
'icon-154': '',
|
||||
'icon-155': '',
|
||||
'icon-156': '',
|
||||
'icon-157': '',
|
||||
'icon-158': '',
|
||||
'icon-159': '',
|
||||
'icon-160': '',
|
||||
'icon-161': '',
|
||||
'icon-162': '',
|
||||
'icon-163': '',
|
||||
'icon-164': '',
|
||||
'icon-165': '',
|
||||
'icon-166': '',
|
||||
'icon-167': '',
|
||||
'icon-168': '',
|
||||
'icon-169': '',
|
||||
'icon-170': '',
|
||||
'icon-171': '',
|
||||
'icon-172': '',
|
||||
'icon-173': '',
|
||||
'icon-174': '',
|
||||
'icon-175': '',
|
||||
'icon-176': '',
|
||||
'icon-177': '',
|
||||
'icon-178': '',
|
||||
'icon-179': '',
|
||||
'icon-180': '',
|
||||
'icon-181': '',
|
||||
'icon-182': '',
|
||||
'icon-183': '',
|
||||
'icon-184': '',
|
||||
'icon-185': '',
|
||||
'icon-186': '',
|
||||
'icon-187': '',
|
||||
'icon-188': '',
|
||||
'icon-189': '',
|
||||
'icon-190': '',
|
||||
'icon-191': '',
|
||||
'icon-192': '',
|
||||
'icon-193': '',
|
||||
'icon-194': '',
|
||||
'icon-195': '',
|
||||
'icon-196': '',
|
||||
'icon-197': '',
|
||||
'icon-198': '',
|
||||
'icon-199': '',
|
||||
'icon-200': '',
|
||||
'icon-201': '',
|
||||
'icon-202': '',
|
||||
'icon-203': '',
|
||||
'icon-204': '',
|
||||
'icon-205': '',
|
||||
'icon-206': '',
|
||||
'icon-207': '',
|
||||
'icon-208': '',
|
||||
'icon-209': '',
|
||||
'icon-210': '',
|
||||
'icon-211': '',
|
||||
'icon-212': '',
|
||||
'icon-213': '',
|
||||
'icon-214': '',
|
||||
'icon-215': '',
|
||||
'icon-216': '',
|
||||
'icon-217': '',
|
||||
'icon-218': '',
|
||||
'icon-219': '',
|
||||
'icon-220': '',
|
||||
'icon-221': '',
|
||||
'icon-222': '',
|
||||
'icon-223': '',
|
||||
'icon-224': '',
|
||||
'icon-225': '',
|
||||
'icon-226': '',
|
||||
'icon-227': '',
|
||||
'icon-228': '',
|
||||
'icon-229': '',
|
||||
'icon-230': '',
|
||||
'icon-231': '',
|
||||
'icon-232': '',
|
||||
'icon-233': '',
|
||||
'icon-234': '',
|
||||
'icon-235': '',
|
||||
'icon-236': '',
|
||||
'icon-237': '',
|
||||
'icon-238': '',
|
||||
'icon-239': '',
|
||||
'icon-240': '',
|
||||
'icon-241': '',
|
||||
'icon-242': '',
|
||||
'icon-243': '',
|
||||
'icon-244': '',
|
||||
'icon-245': '',
|
||||
'icon-246': '',
|
||||
'icon-247': '',
|
||||
'icon-248': '',
|
||||
'icon-249': '',
|
||||
'icon-250': '',
|
||||
'icon-251': '',
|
||||
'icon-252': '',
|
||||
'icon-253': '',
|
||||
'icon-254': '',
|
||||
'icon-255': '',
|
||||
'icon-256': '',
|
||||
'icon-257': '',
|
||||
'icon-258': '',
|
||||
'icon-259': '',
|
||||
'icon-260': '',
|
||||
'icon-261': '',
|
||||
'icon-262': '',
|
||||
'icon-263': '',
|
||||
'icon-264': '',
|
||||
'icon-265': '',
|
||||
'icon-266': '',
|
||||
'icon-267': '',
|
||||
'icon-268': '',
|
||||
'icon-269': '',
|
||||
'icon-270': '',
|
||||
'icon-271': '',
|
||||
'icon-272': '',
|
||||
'icon-273': '',
|
||||
'icon-274': '',
|
||||
'icon-275': '',
|
||||
'icon-276': '',
|
||||
'icon-277': '',
|
||||
'icon-278': '',
|
||||
'icon-279': '',
|
||||
'icon-280': '',
|
||||
'icon-281': '',
|
||||
'icon-282': '',
|
||||
'icon-283': '',
|
||||
'icon-284': '',
|
||||
'icon-285': '',
|
||||
'icon-286': '',
|
||||
'icon-287': '',
|
||||
'icon-288': '',
|
||||
'icon-289': '',
|
||||
'icon-290': '',
|
||||
'icon-291': '',
|
||||
'icon-292': '',
|
||||
'icon-293': '',
|
||||
'icon-294': '',
|
||||
'icon-295': '',
|
||||
'icon-296': '',
|
||||
'icon-297': '',
|
||||
'icon-298': '',
|
||||
'icon-299': '',
|
||||
'icon-300': '',
|
||||
'icon-301': '',
|
||||
'icon-302': '',
|
||||
'icon-303': '',
|
||||
'icon-304': '',
|
||||
'icon-305': '',
|
||||
'icon-306': '',
|
||||
'icon-307': '',
|
||||
'icon-308': '',
|
||||
'icon-309': '',
|
||||
'icon-310': '',
|
||||
'icon-311': '',
|
||||
'icon-312': '',
|
||||
'icon-313': '',
|
||||
'icon-314': '',
|
||||
'icon-315': '',
|
||||
'icon-316': '',
|
||||
'icon-317': '',
|
||||
'icon-318': '',
|
||||
'icon-319': '',
|
||||
'icon-320': '',
|
||||
'icon-321': '',
|
||||
'icon-322': '',
|
||||
'icon-323': '',
|
||||
'icon-324': '',
|
||||
'icon-325': '',
|
||||
'icon-326': '',
|
||||
'icon-327': '',
|
||||
'icon-328': '',
|
||||
'icon-329': '',
|
||||
'icon-330': '',
|
||||
'icon-331': '',
|
||||
'icon-332': '',
|
||||
'icon-333': '',
|
||||
'icon-334': '',
|
||||
'icon-335': '',
|
||||
'icon-336': '',
|
||||
'icon-337': '',
|
||||
'icon-338': '',
|
||||
'icon-339': '',
|
||||
'icon-340': '',
|
||||
'icon-341': '',
|
||||
'icon-342': '',
|
||||
'icon-343': '',
|
||||
'icon-344': '',
|
||||
'icon-345': '',
|
||||
'icon-346': '',
|
||||
'icon-347': '',
|
||||
'icon-348': '',
|
||||
'icon-349': '',
|
||||
'icon-350': '',
|
||||
'icon-351': '',
|
||||
'icon-352': '',
|
||||
'icon-353': '',
|
||||
'icon-354': '',
|
||||
'icon-355': '',
|
||||
'icon-356': '',
|
||||
'icon-357': '',
|
||||
'icon-358': '',
|
||||
'icon-359': '',
|
||||
'icon-360': '',
|
||||
'icon-361': '',
|
||||
'icon-362': '',
|
||||
'icon-363': '',
|
||||
'icon-364': '',
|
||||
'icon-365': '',
|
||||
'icon-366': '',
|
||||
'icon-367': '',
|
||||
'icon-368': '',
|
||||
'icon-369': '',
|
||||
'icon-370': '',
|
||||
'icon-371': '',
|
||||
'icon-372': '',
|
||||
'icon-373': '',
|
||||
'icon-374': '',
|
||||
'icon-375': '',
|
||||
'0': 0
|
||||
},
|
||||
els = document.getElementsByTagName('*'),
|
||||
i, c, el;
|
||||
for (i = 0; ; i += 1) {
|
||||
el = els[i];
|
||||
if(!el) {
|
||||
break;
|
||||
}
|
||||
c = el.className;
|
||||
c = c.match(/icon-[^\s'"]+/);
|
||||
if (c && icons[c[0]]) {
|
||||
addIcon(el, icons[c[0]]);
|
||||
}
|
||||
}
|
||||
}());
|
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.5 KiB |