509 lines
17 KiB
C++
509 lines
17 KiB
C++
/*
|
|
* Copyright (C) 2012 Open Source Robotics Foundation
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
* Brick-wall, Window and Door designed by Juan Pablo Bravo from the
|
|
* thenounproject.com
|
|
* Stairs designed by Brian Oppenlander from the thenounproject.com
|
|
*/
|
|
#include <boost/bind.hpp>
|
|
|
|
#include "gazebo/gui/building/BuildingEditorPalettePrivate.hh"
|
|
#include "gazebo/gui/building/BuildingEditorPalette.hh"
|
|
#include "gazebo/gui/building/BuildingEditorEvents.hh"
|
|
#include "gazebo/gui/building/ImportImageDialog.hh"
|
|
|
|
using namespace gazebo;
|
|
using namespace gui;
|
|
|
|
/////////////////////////////////////////////////
|
|
BuildingEditorPalette::BuildingEditorPalette(QWidget *_parent)
|
|
: QWidget(_parent), dataPtr(new BuildingEditorPalettePrivate)
|
|
{
|
|
this->setObjectName("buildingEditorPalette");
|
|
|
|
this->dataPtr->buildingDefaultName = "Untitled";
|
|
this->dataPtr->currentMode = std::string();
|
|
|
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
|
|
|
// Model name layout
|
|
QHBoxLayout *modelNameLayout = new QHBoxLayout;
|
|
QLabel *modelLabel = new QLabel(tr("Model Name: "));
|
|
this->dataPtr->modelNameEdit = new QLineEdit();
|
|
this->dataPtr->modelNameEdit->setText(
|
|
tr(this->dataPtr->buildingDefaultName.c_str()));
|
|
modelNameLayout->addWidget(modelLabel);
|
|
modelNameLayout->addWidget(this->dataPtr->modelNameEdit);
|
|
connect(this->dataPtr->modelNameEdit, SIGNAL(textChanged(QString)), this,
|
|
SLOT(OnNameChanged(QString)));
|
|
|
|
// Brushes (button group)
|
|
this->dataPtr->brushes = new QButtonGroup();
|
|
connect(this->dataPtr->brushes, SIGNAL(buttonClicked(int)),
|
|
this, SLOT(OnBrush(int)));
|
|
|
|
QSize toolButtonSize(100, 100);
|
|
QSize iconSize(65, 65);
|
|
|
|
// Walls label
|
|
QLabel *wallsLabel = new QLabel(tr(
|
|
"<font size=4 color='white'>Create Walls</font>"));
|
|
|
|
// Wall button
|
|
QToolButton *wallButton = new QToolButton(this);
|
|
wallButton->setFixedSize(toolButtonSize);
|
|
wallButton->setCheckable(true);
|
|
wallButton->setChecked(false);
|
|
wallButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
|
|
wallButton->setIcon(QPixmap(":/images/wall.svg"));
|
|
wallButton->setText("Wall");
|
|
wallButton->setIconSize(QSize(iconSize));
|
|
wallButton->setToolTip("Hold Shift to override snapping");
|
|
this->dataPtr->brushIdToModeMap["wall"] =
|
|
this->dataPtr->brushes->buttons().size();
|
|
this->dataPtr->brushes->addButton(wallButton,
|
|
this->dataPtr->brushes->buttons().size());
|
|
|
|
// Features label
|
|
QLabel *featuresLabel = new QLabel(tr(
|
|
"<font size=4 color='white'>Add Features</font>"));
|
|
|
|
// Window button
|
|
QToolButton *windowButton = new QToolButton(this);
|
|
windowButton->setFixedSize(toolButtonSize);
|
|
windowButton->setCheckable(true);
|
|
windowButton->setChecked(false);
|
|
windowButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
|
|
windowButton->setIcon(QPixmap(":/images/window.svg"));
|
|
windowButton->setText("Window");
|
|
windowButton->setIconSize(QSize(iconSize));
|
|
this->dataPtr->brushIdToModeMap["window"] =
|
|
this->dataPtr->brushes->buttons().size();
|
|
this->dataPtr->brushes->addButton(windowButton,
|
|
this->dataPtr->brushes->buttons().size());
|
|
|
|
// Door button
|
|
QToolButton *doorButton = new QToolButton(this);
|
|
doorButton->setFixedSize(toolButtonSize);
|
|
doorButton->setCheckable(true);
|
|
doorButton->setChecked(false);
|
|
doorButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
|
|
doorButton->setIcon(QPixmap(":/images/door.svg"));
|
|
doorButton->setText("Door");
|
|
doorButton->setIconSize(QSize(iconSize));
|
|
this->dataPtr->brushIdToModeMap["door"] =
|
|
this->dataPtr->brushes->buttons().size();
|
|
this->dataPtr->brushes->addButton(doorButton,
|
|
this->dataPtr->brushes->buttons().size());
|
|
|
|
// Stairs button
|
|
QToolButton *stairsButton = new QToolButton(this);
|
|
stairsButton->setFixedSize(toolButtonSize);
|
|
stairsButton->setCheckable(true);
|
|
stairsButton->setChecked(false);
|
|
stairsButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
|
|
stairsButton->setIcon(QPixmap(":/images/stairs.svg"));
|
|
stairsButton->setText("Stairs");
|
|
stairsButton->setIconSize(QSize(iconSize));
|
|
this->dataPtr->brushIdToModeMap["stairs"] =
|
|
this->dataPtr->brushes->buttons().size();
|
|
this->dataPtr->brushes->addButton(stairsButton,
|
|
this->dataPtr->brushes->buttons().size());
|
|
|
|
// Features layout
|
|
QGridLayout *featuresLayout = new QGridLayout;
|
|
featuresLayout->addWidget(windowButton, 0, 0);
|
|
featuresLayout->addWidget(doorButton, 0, 1);
|
|
featuresLayout->addWidget(stairsButton, 1, 0);
|
|
|
|
// Colors
|
|
QLabel *colorsLabel = new QLabel(tr(
|
|
"<font size=4 color='white'>Add Color</font>"));
|
|
|
|
QGridLayout *colorsLayout = new QGridLayout;
|
|
this->dataPtr->colorList.push_back(QColor(255, 255, 255, 255));
|
|
this->dataPtr->colorList.push_back(QColor(194, 169, 160, 255));
|
|
this->dataPtr->colorList.push_back(QColor(235, 206, 157, 255));
|
|
this->dataPtr->colorList.push_back(QColor(254, 121, 5, 255));
|
|
this->dataPtr->colorList.push_back(QColor(255, 195, 78, 255));
|
|
this->dataPtr->colorList.push_back(QColor(111, 203, 172, 255));
|
|
for (unsigned int i = 0; i < this->dataPtr->colorList.size(); ++i)
|
|
{
|
|
QToolButton *colorButton = new QToolButton(this);
|
|
colorButton->setFixedSize(40, 40);
|
|
colorButton->setCheckable(true);
|
|
colorButton->setChecked(false);
|
|
colorButton->setToolButtonStyle(Qt::ToolButtonIconOnly);
|
|
QPixmap colorIcon(30, 30);
|
|
colorIcon.fill(this->dataPtr->colorList.at(i));
|
|
colorButton->setIcon(colorIcon);
|
|
std::ostringstream colorStr;
|
|
colorStr << "color_" << i;
|
|
this->dataPtr->lastDefaultColor = colorStr.str();
|
|
this->dataPtr->brushIdToModeMap[this->dataPtr->lastDefaultColor] =
|
|
this->dataPtr->brushes->buttons().size();
|
|
this->dataPtr->brushes->addButton(colorButton,
|
|
this->dataPtr->brushes->buttons().size());
|
|
colorsLayout->addWidget(colorButton, 0, i);
|
|
}
|
|
|
|
this->dataPtr->customColorButton = new QPushButton("More");
|
|
this->dataPtr->customColorButton->setCheckable(true);
|
|
this->dataPtr->customColorButton->setChecked(false);
|
|
colorsLayout->addWidget(this->dataPtr->customColorButton, 1, 4, 1, 2);
|
|
this->dataPtr->brushIdToModeMap["color_custom"] =
|
|
this->dataPtr->brushes->buttons().size();
|
|
this->dataPtr->brushes->addButton(this->dataPtr->customColorButton,
|
|
this->dataPtr->brushes->buttons().size());
|
|
|
|
this->dataPtr->customColorDialog = new QColorDialog(Qt::green, this);
|
|
this->dataPtr->customColorDialog->setWindowModality(Qt::NonModal);
|
|
connect(this->dataPtr->customColorDialog,
|
|
SIGNAL(currentColorChanged(const QColor)),
|
|
this, SLOT(OnCustomColor(const QColor)));
|
|
connect(this->dataPtr->customColorDialog, SIGNAL(rejected()), this,
|
|
SLOT(CancelDrawModes()));
|
|
|
|
// Textures
|
|
QLabel *texturesLabel = new QLabel(tr(
|
|
"<font size=4 color='white'>Add Texture</font>"));
|
|
|
|
QGridLayout *texturesLayout = new QGridLayout;
|
|
std::vector<QString> textureButtonTextList;
|
|
|
|
this->dataPtr->textureList.push_back(":wood.jpg");
|
|
textureButtonTextList.push_back("Wood");
|
|
this->dataPtr->textureList.push_back(":tiles.jpg");
|
|
textureButtonTextList.push_back("Tiles");
|
|
this->dataPtr->textureList.push_back(":bricks.png");
|
|
textureButtonTextList.push_back("Bricks");
|
|
|
|
for (unsigned int i = 0; i < this->dataPtr->textureList.size(); ++i)
|
|
{
|
|
QToolButton *textureButton = new QToolButton(this);
|
|
textureButton->setFixedSize(70, 70);
|
|
textureButton->setCheckable(true);
|
|
textureButton->setChecked(false);
|
|
textureButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
|
|
textureButton->setIcon(QPixmap(this->dataPtr->textureList[i]).scaled(
|
|
QSize(90, 90), Qt::IgnoreAspectRatio));
|
|
textureButton->setText(textureButtonTextList[i]);
|
|
textureButton->setIconSize(QSize(40, 40));
|
|
std::ostringstream textureStr;
|
|
textureStr << "texture_" << i;
|
|
this->dataPtr->lastDefaultTexture = textureStr.str();
|
|
this->dataPtr->brushIdToModeMap[this->dataPtr->lastDefaultTexture] =
|
|
this->dataPtr->brushes->buttons().size();
|
|
this->dataPtr->brushes->addButton(textureButton,
|
|
this->dataPtr->brushes->buttons().size());
|
|
texturesLayout->addWidget(textureButton, 0, i);
|
|
}
|
|
|
|
// Import button
|
|
QPushButton *importImageButton = new QPushButton(tr("Import"),
|
|
this);
|
|
importImageButton->setCheckable(true);
|
|
importImageButton->setChecked(false);
|
|
importImageButton->setToolTip(tr(
|
|
"Import an existing floor plan to use as a guide"));
|
|
this->dataPtr->brushIdToModeMap["image"] =
|
|
this->dataPtr->brushes->buttons().size();
|
|
this->dataPtr->brushes->addButton(importImageButton,
|
|
this->dataPtr->brushes->buttons().size());
|
|
|
|
QHBoxLayout *buttonsLayout = new QHBoxLayout;
|
|
buttonsLayout->addWidget(importImageButton);
|
|
buttonsLayout->setAlignment(Qt::AlignHCenter);
|
|
buttonsLayout->setContentsMargins(30, 11, 30, 11);
|
|
|
|
// Main layout
|
|
mainLayout->addLayout(modelNameLayout);
|
|
mainLayout->addItem(new QSpacerItem(10, 20, QSizePolicy::Expanding,
|
|
QSizePolicy::Minimum));
|
|
mainLayout->addWidget(wallsLabel);
|
|
mainLayout->addWidget(wallButton);
|
|
mainLayout->addWidget(featuresLabel);
|
|
mainLayout->addLayout(featuresLayout);
|
|
mainLayout->addWidget(colorsLabel);
|
|
mainLayout->addLayout(colorsLayout);
|
|
mainLayout->addWidget(texturesLabel);
|
|
mainLayout->addLayout(texturesLayout);
|
|
mainLayout->addItem(new QSpacerItem(10, 20, QSizePolicy::Expanding,
|
|
QSizePolicy::Minimum));
|
|
mainLayout->addLayout(buttonsLayout);
|
|
mainLayout->setAlignment(Qt::AlignTop | Qt::AlignHCenter);
|
|
|
|
// Scroll area
|
|
auto scrollWidget = new QWidget();
|
|
scrollWidget->setObjectName("buildingEditorPaletteScroll");
|
|
scrollWidget->setLayout(mainLayout);
|
|
scrollWidget->setMinimumWidth(200);
|
|
|
|
auto scrollArea = new QScrollArea;
|
|
scrollArea->setWidget(scrollWidget);
|
|
scrollArea->setWidgetResizable(true);
|
|
|
|
auto scrollLayout = new QVBoxLayout();
|
|
scrollLayout->addWidget(scrollArea);
|
|
|
|
this->setLayout(scrollLayout);
|
|
|
|
// Connections
|
|
this->dataPtr->connections.push_back(
|
|
gui::editor::Events::ConnectSaveBuildingModel(
|
|
boost::bind(&BuildingEditorPalette::OnSaveModel, this, _1)));
|
|
|
|
this->dataPtr->connections.push_back(
|
|
gui::editor::Events::ConnectNewBuildingModel(
|
|
boost::bind(&BuildingEditorPalette::OnNewModel, this)));
|
|
|
|
this->dataPtr->connections.push_back(
|
|
gui::editor::Events::ConnectCreateBuildingEditorItem(
|
|
boost::bind(&BuildingEditorPalette::OnCreateEditorItem, this, _1)));
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
BuildingEditorPalette::~BuildingEditorPalette()
|
|
{
|
|
delete this->dataPtr;
|
|
this->dataPtr = NULL;
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
std::string BuildingEditorPalette::GetModelName() const
|
|
{
|
|
return this->dataPtr->modelNameEdit->text().toStdString();
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void BuildingEditorPalette::OnBrush(int _buttonId)
|
|
{
|
|
if (_buttonId == this->dataPtr->brushIdToModeMap["wall"])
|
|
{
|
|
this->OnDrawWall();
|
|
}
|
|
else if (_buttonId == this->dataPtr->brushIdToModeMap["window"])
|
|
{
|
|
this->OnAddWindow();
|
|
}
|
|
else if (_buttonId == this->dataPtr->brushIdToModeMap["door"])
|
|
{
|
|
this->OnAddDoor();
|
|
}
|
|
else if (_buttonId == this->dataPtr->brushIdToModeMap["stairs"])
|
|
{
|
|
this->OnAddStair();
|
|
}
|
|
else if (_buttonId >= this->dataPtr->brushIdToModeMap["color_0"] &&
|
|
_buttonId <= this->dataPtr->brushIdToModeMap[
|
|
this->dataPtr->lastDefaultColor])
|
|
{
|
|
this->OnDefaultColor(_buttonId -
|
|
this->dataPtr->brushIdToModeMap["color_0"]);
|
|
}
|
|
else if (_buttonId == this->dataPtr->brushIdToModeMap["color_custom"])
|
|
{
|
|
this->OnCustomColorDialog();
|
|
}
|
|
else if (_buttonId >= this->dataPtr->brushIdToModeMap["texture_0"] &&
|
|
_buttonId <= this->dataPtr->brushIdToModeMap[
|
|
this->dataPtr->lastDefaultTexture])
|
|
{
|
|
this->OnTexture(_buttonId - this->dataPtr->brushIdToModeMap["texture_0"]);
|
|
}
|
|
else if (_buttonId == this->dataPtr->brushIdToModeMap["image"])
|
|
{
|
|
this->OnImportImage();
|
|
}
|
|
else
|
|
{
|
|
gzerr << "Requested brush doesn't exist." << std::endl;
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void BuildingEditorPalette::OnDrawWall()
|
|
{
|
|
if (this->dataPtr->currentMode != "wall")
|
|
gui::editor::Events::createBuildingEditorItem("wall");
|
|
else
|
|
this->CancelDrawModes();
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void BuildingEditorPalette::OnAddWindow()
|
|
{
|
|
if (this->dataPtr->currentMode != "window")
|
|
gui::editor::Events::createBuildingEditorItem("window");
|
|
else
|
|
this->CancelDrawModes();
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void BuildingEditorPalette::OnAddDoor()
|
|
{
|
|
if (this->dataPtr->currentMode != "door")
|
|
gui::editor::Events::createBuildingEditorItem("door");
|
|
else
|
|
this->CancelDrawModes();
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void BuildingEditorPalette::OnImportImage()
|
|
{
|
|
if (this->dataPtr->currentMode != "image")
|
|
gui::editor::Events::createBuildingEditorItem("image");
|
|
else
|
|
this->CancelDrawModes();
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void BuildingEditorPalette::OnAddStair()
|
|
{
|
|
if (this->dataPtr->currentMode != "stairs")
|
|
gui::editor::Events::createBuildingEditorItem("stairs");
|
|
else
|
|
this->CancelDrawModes();
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void BuildingEditorPalette::OnNewModel()
|
|
{
|
|
this->dataPtr->modelNameEdit->setText(
|
|
tr(this->dataPtr->buildingDefaultName.c_str()));
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void BuildingEditorPalette::OnSaveModel(const std::string &_saveName)
|
|
{
|
|
this->dataPtr->modelNameEdit->setText(tr(_saveName.c_str()));
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void BuildingEditorPalette::OnNameChanged(const QString &_name)
|
|
{
|
|
gui::editor::Events::buildingNameChanged(_name.toStdString());
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void BuildingEditorPalette::OnCreateEditorItem(const std::string &_mode)
|
|
{
|
|
gui::editor::Events::colorSelected(QColor::Invalid);
|
|
gui::editor::Events::textureSelected(QString(""));
|
|
|
|
if (_mode.empty() || this->dataPtr->currentMode == _mode)
|
|
{
|
|
this->dataPtr->brushes->setExclusive(false);
|
|
if (this->dataPtr->brushes->checkedButton())
|
|
this->dataPtr->brushes->checkedButton()->setChecked(false);
|
|
this->dataPtr->brushes->setExclusive(true);
|
|
|
|
this->dataPtr->currentMode.clear();
|
|
}
|
|
else
|
|
{
|
|
this->dataPtr->currentMode = _mode;
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void BuildingEditorPalette::OnDefaultColor(int _colorId)
|
|
{
|
|
std::ostringstream colorStr;
|
|
colorStr << "color_" << _colorId;
|
|
QColor color = this->dataPtr->colorList[_colorId];
|
|
if (this->dataPtr->currentMode != colorStr.str())
|
|
{
|
|
this->dataPtr->currentMode = colorStr.str();
|
|
this->OnColor(color);
|
|
}
|
|
else
|
|
{
|
|
this->CancelDrawModes();
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void BuildingEditorPalette::OnCustomColorDialog()
|
|
{
|
|
this->CancelDrawModes();
|
|
this->dataPtr->customColorButton->setChecked(true);
|
|
this->dataPtr->customColorDialog->show();
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void BuildingEditorPalette::OnCustomColor(const QColor _color)
|
|
{
|
|
this->dataPtr->customColorButton->setChecked(true);
|
|
if (_color.isValid())
|
|
{
|
|
this->dataPtr->currentMode = "color_custom";
|
|
this->OnColor(_color);
|
|
}
|
|
else
|
|
{
|
|
this->CancelDrawModes();
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void BuildingEditorPalette::OnColor(QColor _color)
|
|
{
|
|
gui::editor::Events::colorSelected(_color);
|
|
QPixmap colorCursor(30, 30);
|
|
colorCursor.fill(_color);
|
|
QApplication::setOverrideCursor(QCursor(colorCursor));
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void BuildingEditorPalette::OnTexture(int _textureId)
|
|
{
|
|
std::ostringstream textureStr;
|
|
textureStr << "texture_" << _textureId;
|
|
QString texture = this->dataPtr->textureList[_textureId];
|
|
if (this->dataPtr->currentMode != textureStr.str())
|
|
{
|
|
gui::editor::Events::textureSelected(texture);
|
|
this->dataPtr->currentMode = textureStr.str();
|
|
|
|
QPixmap textureCursor(this->dataPtr->textureList[_textureId]);
|
|
textureCursor = textureCursor.scaled(QSize(30, 30), Qt::IgnoreAspectRatio,
|
|
Qt::SmoothTransformation);
|
|
QApplication::setOverrideCursor(textureCursor);
|
|
}
|
|
else
|
|
{
|
|
this->CancelDrawModes();
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void BuildingEditorPalette::mousePressEvent(QMouseEvent * /*_event*/)
|
|
{
|
|
this->CancelDrawModes();
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
void BuildingEditorPalette::CancelDrawModes()
|
|
{
|
|
gui::editor::Events::createBuildingEditorItem(std::string());
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
QColorDialog *BuildingEditorPalette::CustomColorDialog() const
|
|
{
|
|
return this->dataPtr->customColorDialog;
|
|
}
|