From e10c0a7602c612993e6b99348bab507b7def0881 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sat, 25 Feb 2012 16:56:25 +0000 Subject: Add entity manipulator widget, added support for editing entity angles. --- src/Makefile.am | 2 ++ src/editorwindow.cc | 15 ++++++++++- src/entityproperties.cc | 4 +++ src/entityproperties.h | 51 +++++++++++++++++++++++++++++++++++ src/entitywidget.cc | 31 ++++++++++++++++++--- src/entitywidget.h | 16 ++++++++++- src/manipulator.cc | 59 ++++++++++++++++++++++++++++++++++++++++ src/manipulator.h | 68 ++++++++++++++++++++++++++++++++++++++++++++++ src/mapwidget.cc | 21 ++++++++++++--- src/mapwidget.h | 5 +++- src/sidebar.cc | 72 +++++++++++++++++++++++++++++++++++++++++++++++++ src/sidebar.h | 9 +++++++ 12 files changed, 344 insertions(+), 9 deletions(-) create mode 100644 src/manipulator.cc create mode 100644 src/manipulator.h diff --git a/src/Makefile.am b/src/Makefile.am index 3614a61..35d1496 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,6 +8,7 @@ editor_SOURCES = \ entityproperties.cc \ entitywidget.cc \ inistream.cc \ + manipulator.cc \ mainwindow.cc \ mapwidget.cc \ properties.cc \ @@ -20,6 +21,7 @@ editor_SOURCES = \ nodist_editor_SOURCES = \ moc_editorwindow.cc \ moc_entitywidget.cc \ + moc_manipulator.cc \ moc_mainwindow.cc \ moc_mapwidget.cc \ moc_sidebar.cc diff --git a/src/editorwindow.cc b/src/editorwindow.cc index ae7d024..bd00189 100644 --- a/src/editorwindow.cc +++ b/src/editorwindow.cc @@ -137,7 +137,7 @@ bool EditorWindow::loadFile(const QString &filename) if (ini.got_key_vector3f("location" , x, y, z)) { entity->properties()->set_comment("location", ini.comment()); entity->properties()->set_location(x, y, z); - //qDebug() << "got location " << x << " " << y << " " << z; + //qDebug() << "got location " << x << " " << y << " " << z; } else if (ini.got_key_string("label", str)) { entity->properties()->set_comment("label", ini.comment()); @@ -150,6 +150,19 @@ bool EditorWindow::loadFile(const QString &filename) } else if (ini.got_key_float("radius", f)) { entity->properties()->set_comment("radius", ini.comment()); entity->properties()->set_radius(f); + + } else if (ini.got_key_vector3f("angles" , x, y, z)) { + entity->properties()->set_comment(ini.key(), ini.comment()); + entity->properties()->set_angles(x, y, z); + + } else if (ini.got_key_float("yaw", x)) { + entity->properties()->set_yaw(x); + + } else if (ini.got_key_float("pitch", y)) { + entity->properties()->set_pitch(y); + + } else if (ini.got_key_float("roll", z)) { + entity->properties()->set_roll(z); } else if (ini.got_key_string("info", str)) { QString comment = entity->properties()->comment("info"); diff --git a/src/entityproperties.cc b/src/entityproperties.cc index 429b759..bdc2394 100644 --- a/src/entityproperties.cc +++ b/src/entityproperties.cc @@ -73,6 +73,10 @@ void EntityProperties::save(QTextStream &textstream) save_comment(textstream, "location"); textstream << "location=" << location().x() << " " << location().y() << " " << location().z() << '\n'; + // angles + save_comment(textstream, "angles"); + textstream << "angles=" << angles().x() << " " << angles().y() << " " << angles().z() << '\n'; + // radius save_comment(textstream, "radius"); if (radius()) { diff --git a/src/entityproperties.h b/src/entityproperties.h index b80a82e..9a276cb 100644 --- a/src/entityproperties.h +++ b/src/entityproperties.h @@ -43,6 +43,20 @@ public: return properties_radius; } + /** + * @brief returns the angles of this object + * */ + inline const Vector3f &angles() const { + return properties_angles; + } + + /** + * @brief returns the yaw angle of this object + * */ + inline const float yaw() const { + return properties_angles[0]; + } + /** * @brief returns the subsections string of this object * */ @@ -83,11 +97,48 @@ public: properties_radius = radius; } + /** + * @brief set the object angles + * */ + inline void set_angles(const Vector3f &angles) { + properties_angles.assign(angles); + } + + /** + * @brief set the object yaw angle + * */ + inline void set_yaw(const float yaw) { + properties_angles[0] = yaw; + } + + /** + * @brief set the object pitch angle + * */ + inline void set_pitch(const float pitch) { + properties_angles[1] = pitch; + } + + /** + * @brief set the object roll angle + * */ + inline void set_roll (const float roll ) { + properties_angles[2] = roll ; + } + + /** + * @brief set the object angles + * */ + inline void set_angles(const float yaw, const float pitch, const float roll) { + properties_angles.assign(yaw, pitch, roll); + } + private: float properties_radius; QString properties_subsections; QString properties_type; + + Vector3f properties_angles; }; } // namespace editor diff --git a/src/entitywidget.cc b/src/entitywidget.cc index c903ea8..b589063 100644 --- a/src/entitywidget.cc +++ b/src/entitywidget.cc @@ -11,6 +11,8 @@ #include #include +#include + namespace editor { @@ -34,10 +36,30 @@ void EntityWidget::paintEvent(QPaintEvent *event) if (is_selected) { pen.setColor(Qt::red); painter.setPen(pen); + + painter.setClipping(false); + } else { + painter.setClipping(true); } painter.setPen(pen); painter.drawEllipse(0, 0, width() - 1 , height() - 1); + + float r = width() / 2; + if (r < 12) + r = 12; + + /* + float dx = r * sin(entitywidget_entityproperties.yaw()); + float dy = r * cos(entitywidget_entityproperties.yaw()); + + if (!is_selected) { + pen.setColor(Qt::yellow); + } + painter.setPen(pen); + + painter.drawLine(width() /2, height() /2, width() /2 - dx, height() /2 - dy); + */ } void EntityWidget::mousePressEvent(QMouseEvent *event) @@ -45,8 +67,10 @@ void EntityWidget::mousePressEvent(QMouseEvent *event) if (event->button() == Qt::LeftButton) { //qDebug() << "clicked entity " << name(); event->accept(); - if (is_selected) + if (is_selected) { is_dragging = true; + emit dragStart(); + } emit clicked(this); } else { event->ignore(); @@ -57,6 +81,8 @@ void EntityWidget::mousePressEvent(QMouseEvent *event) void EntityWidget::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { + if (is_dragging) + emit dragStop(); is_dragging = false; } } @@ -64,8 +90,7 @@ void EntityWidget::mouseReleaseEvent(QMouseEvent *event) void EntityWidget::mouseMoveEvent(QMouseEvent *event) { if (is_dragging) { - // TODO add delay - emit dragged(this, event->pos().x(), event->pos().y()); + emit dragMove(this, event->pos().x(), event->pos().y()); } } diff --git a/src/entitywidget.h b/src/entitywidget.h index 1bdfb93..2eb1a42 100644 --- a/src/entitywidget.h +++ b/src/entitywidget.h @@ -34,16 +34,30 @@ public: return &entitywidget_entityproperties; } + inline const bool selected() const { + return is_selected; + } + signals: /** * @brief this signal is emitted if the entity is clicked with the left mouse button * */ void clicked(EntityWidget *entity); + /** + * @brief this signal is emitted when the entity is first dragged + * */ + void dragStart(); + + /** + * @brief this signal is emitted when the entity stops being dragged + * */ + void dragStop(); + /** * @brief this signal is emitted if the entity is dragged * */ - void dragged(EntityWidget *entity, int x, int y); + void dragMove(EntityWidget *entity, int x, int y); public slots: diff --git a/src/manipulator.cc b/src/manipulator.cc new file mode 100644 index 0000000..33585a9 --- /dev/null +++ b/src/manipulator.cc @@ -0,0 +1,59 @@ +/* + manipulator.cc + This file is part of the Project::OSiRiON world editor + and is distributed under the terms and conditions of + the GNU General Public License version 2 +*/ + +#include "manipulator.h" + +#include +#include +#include +#include + +namespace editor +{ + +Manipulator::Manipulator(QWidget *parent) : QWidget(parent) +{ + manipulator_mode = None; + manipulator_yaw = 0; +} + +void Manipulator::setSize(const QWidget *widget) +{ + const int s = 16; + setGeometry( + widget->x() - s, + widget->y() -s, + widget->width() + 2 * s, + widget->height() + 2 * s + ); +} + +void Manipulator::paintEvent(QPaintEvent *event) +{ + if (mode() == None) + return; + + QColor green; + green.setRgb(0, 156, 0); + QPen pen(green, 1, Qt::SolidLine); + QPainter painter(this); + + painter.setPen(pen); + painter.drawEllipse(0, 0, width() - 1 , height() - 1); + + const int r = width() / 2; + const float dx = r * sin(manipulator_yaw * M_PI / 180.0f); + const float dy = r * cos(manipulator_yaw * M_PI / 180.0f); + painter.drawLine(width() /2, height() /2, width() /2 - dx, height() /2 - dy); +} + +void Manipulator::setProperties(const EntityProperties *properties) +{ + manipulator_yaw = properties->yaw(); +} + +} // namespace editor diff --git a/src/manipulator.h b/src/manipulator.h new file mode 100644 index 0000000..9ac28be --- /dev/null +++ b/src/manipulator.h @@ -0,0 +1,68 @@ +/* + manipulator.h + This file is part of the Project::OSiRiON world editor + and is distributed under the terms and conditions of + the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_EDITOR_MANIPULATOR__ +#define __INCLUDED_EDITOR_MANIPULATOR__ + +#include "entityproperties.h" + +#include + +namespace editor +{ + + +/** + * @brief a Widget displaying the manipulator state of an entity + * */ +class Manipulator : public QWidget +{ + Q_OBJECT + +public: + enum Mode {None = 0, Select = 1, Move = 2, Rotate = 3 }; + + Manipulator(QWidget *parent = 0); + + /* ---- inspectors ---- */ + + /** + * @brief returns the current manipulator Mode + * */ + inline const Mode mode() const { + return manipulator_mode; + } + + /* ---- mutatorss ---- */ + + /** + * @brief set the manipulator mode + * */ + inline void setMode(Mode mode) { + manipulator_mode = mode; + } + + void setSize(const QWidget *widget); + +public slots: + void setProperties(const EntityProperties *properties); + +protected: + /** + * @brief handle draw events + * */ + virtual void paintEvent(QPaintEvent *event); + +private: + + Mode manipulator_mode; + float manipulator_yaw; +}; + +} + +#endif // __INCLUDED_EDITOR_MANIPULATOR__ diff --git a/src/mapwidget.cc b/src/mapwidget.cc index d2c5676..fe84ada 100644 --- a/src/mapwidget.cc +++ b/src/mapwidget.cc @@ -6,6 +6,7 @@ */ #include "entitywidget.h" +#include "manipulator.h" #include "mapwidget.h" #include @@ -20,6 +21,7 @@ namespace editor MapWidget::MapWidget(QWidget *parent) : QWidget(parent) { //setMinimumSize(256,256); + mapwidget_manipulator = new Manipulator(this); // zoom sucks but it works mapwidget_zoom = 16; @@ -93,6 +95,7 @@ void MapWidget::mouseMoveEvent(QMouseEvent *event) event->accept(); resizeChildren(); + update(); } } @@ -115,6 +118,11 @@ void MapWidget::resizeChildren() entity->setGeometry(center_x + x, center_y + y, radius * 2 , radius * 2); //qDebug() << "Moving entity to " << x << " " << y; + if (entity->selected()) { + mapwidget_manipulator->setSize(entity); + mapwidget_manipulator->setProperties(entity->properties()); + mapwidget_manipulator->update(); + } } } @@ -125,7 +133,9 @@ void MapWidget::deselect() EntityWidget *entitywidget = mapwidget_enties.at(i); entitywidget->set_selected(false); } - emit propertiesChanged(0); + + emit propertiesChanged(0); + mapwidget_manipulator->setMode(Manipulator::None); } void MapWidget::dragEntity(EntityWidget *entity, int x, int y) @@ -142,11 +152,13 @@ void MapWidget::dragEntity(EntityWidget *entity, int x, int y) ); emit propertiesChanged(entity->properties()); - resizeChildren(); + resizeChildren(); + mapwidget_manipulator->setMode(Manipulator::Move); } void MapWidget::select(EntityWidget *entity) { + mapwidget_manipulator->setMode(Manipulator::None); for (int i = 0; i < mapwidget_enties.size(); ++i) { EntityWidget *entitywidget = mapwidget_enties.at(i); @@ -156,6 +168,9 @@ void MapWidget::select(EntityWidget *entity) entity->set_selected(true); //qDebug() << "selected entity " << entity->name(); emit propertiesChanged(entity->properties()); + mapwidget_manipulator->setMode(Manipulator::Select); + mapwidget_manipulator->setProperties(entity->properties()); + mapwidget_manipulator->setSize(entity); } else { @@ -246,7 +261,7 @@ EntityWidget *MapWidget::addEntity() // connect the EntityWidget::clicked() signal to the MapWidget::selected() slot connect(entitywidget, SIGNAL(clicked(EntityWidget *)), this, SLOT(select(EntityWidget *))); - connect(entitywidget, SIGNAL(dragged(EntityWidget *, int, int)), this, SLOT(dragEntity(EntityWidget *, int, int))); + connect(entitywidget, SIGNAL(dragMove(EntityWidget *, int, int)), this, SLOT(dragEntity(EntityWidget *, int, int))); entitywidget->show(); diff --git a/src/mapwidget.h b/src/mapwidget.h index c68d127..a7dbb66 100644 --- a/src/mapwidget.h +++ b/src/mapwidget.h @@ -17,7 +17,8 @@ namespace editor { class EntityWidget; - +class Manipulator; + /** * @brief MapWidget shows the zone map with the blue grid line * */ @@ -112,6 +113,8 @@ private: bool is_dragging; QList mapwidget_enties; + + Manipulator *mapwidget_manipulator; }; } diff --git a/src/sidebar.cc b/src/sidebar.cc index 77d87ae..bcd944e 100644 --- a/src/sidebar.cc +++ b/src/sidebar.cc @@ -56,6 +56,20 @@ SideBar::SideBar(QWidget *parent) : QWidget(parent) connect(edit_entitylocation_y, SIGNAL(textChanged(const QString &)), this, SLOT(updateEntityLocationY(const QString &))); connect(edit_entitylocation_z, SIGNAL(textChanged(const QString &)), this, SLOT(updateEntityLocationZ(const QString &))); + // entity angles + QHBoxLayout *box_entityangles = new QHBoxLayout(); + QLabel *label_entityangles = new QLabel(tr("angles")); + edit_entityangles_yaw = new QLineEdit(tr("yaw")); + edit_entityangles_pitch = new QLineEdit(tr("pitch")); + edit_entityangles_roll = new QLineEdit(tr("roll")); + box_entityangles->addWidget(label_entityangles); + box_entityangles->addWidget(edit_entityangles_yaw); + box_entityangles->addWidget(edit_entityangles_pitch); + box_entityangles->addWidget(edit_entityangles_roll); + connect(edit_entityangles_yaw, SIGNAL(textChanged(const QString &)), this, SLOT(updateEntityAnglesYaw(const QString &))); + connect(edit_entityangles_pitch, SIGNAL(textChanged(const QString &)), this, SLOT(updateEntityAnglesPitch(const QString &))); + connect(edit_entityangles_roll, SIGNAL(textChanged(const QString &)), this, SLOT(updateEntityAnglesRoll(const QString &))); + // entity radius QHBoxLayout *box_entityradius = new QHBoxLayout(); QLabel *label_entityradius = new QLabel(tr("radius")); @@ -93,6 +107,7 @@ SideBar::SideBar(QWidget *parent) : QWidget(parent) box_global->addLayout(box_entitylabel); box_global->addLayout(box_entityname); box_global->addLayout(box_entitylocation); + box_global->addLayout(box_entityangles); box_global->addLayout(box_entityradius); box_global->addWidget(label_entityproperties); @@ -159,6 +174,42 @@ void SideBar::updateEntityLocationZ(const QString &value) } } +void SideBar::updateEntityAnglesYaw(const QString &value) +{ + if (last_selected) { + bool ok; + float yaw = value.toFloat(&ok); + if (ok) { + last_selected->set_angles(yaw, last_selected->angles()[1], last_selected->angles()[2]); + emit entityChanged(); + } + } +} + +void SideBar::updateEntityAnglesPitch(const QString &value) +{ + if (last_selected) { + bool ok; + float pitch = value.toFloat(&ok); + if (ok) { + last_selected->set_angles(last_selected->angles()[0], pitch, last_selected->angles()[2]); + emit entityChanged(); + } + } +} + +void SideBar::updateEntityAnglesRoll(const QString &value) +{ + if (last_selected) { + bool ok; + float roll = value.toFloat(&ok); + if (ok) { + last_selected->set_angles(last_selected->angles()[0], last_selected->angles()[1], roll); + emit entityChanged(); + } + } +} + void SideBar::updateEntityRadius(const QString &value) { if (last_selected) { @@ -216,6 +267,15 @@ void SideBar::setProperties(EntityProperties *properties) edit_entitylocation_z->setEnabled(false); edit_entitylocation_z->clear(); + edit_entityangles_yaw->setEnabled(false); + edit_entityangles_yaw->clear(); + + edit_entityangles_pitch->setEnabled(false); + edit_entityangles_pitch->clear(); + + edit_entityangles_roll->setEnabled(false); + edit_entityangles_roll->clear(); + edit_entityradius->setEnabled(false); edit_entityradius->clear(); @@ -254,6 +314,18 @@ void SideBar::setProperties(EntityProperties *properties) value.setNum(properties->location()[2]); edit_entitylocation_z->setText(value); + edit_entityangles_yaw->setEnabled(true); + value.setNum(properties->angles()[0]); + edit_entityangles_yaw->setText(value); + + edit_entityangles_pitch->setEnabled(true); + value.setNum(properties->angles()[1]); + edit_entityangles_pitch->setText(value); + + edit_entityangles_roll->setEnabled(true); + value.setNum(properties->angles()[2]); + edit_entityangles_roll->setText(value); + edit_entityradius->setEnabled(true); value.setNum(properties->radius()); edit_entityradius->setText(value); diff --git a/src/sidebar.h b/src/sidebar.h index e731327..0ed8d2a 100644 --- a/src/sidebar.h +++ b/src/sidebar.h @@ -57,6 +57,12 @@ private slots: void updateEntityLocationZ(const QString &value); + void updateEntityAnglesYaw(const QString &value); + + void updateEntityAnglesPitch(const QString &value); + + void updateEntityAnglesRoll(const QString &value); + void updateEntityRadius(const QString &value); void updateEntityValues(); @@ -77,6 +83,9 @@ private: QLineEdit *edit_entitylocation_x; QLineEdit *edit_entitylocation_y; QLineEdit *edit_entitylocation_z; + QLineEdit *edit_entityangles_yaw; + QLineEdit *edit_entityangles_pitch; + QLineEdit *edit_entityangles_roll; QLineEdit *edit_entityradius; QTextEdit *text_entityvalues; QTextEdit *text_subsections; -- cgit v1.2.3