/* mapwidget.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 "entitywidget.h" #include "manipulator.h" #include "mapwidget.h" #include #include #include #include #include #include namespace editor { MapWidget::MapWidget(QWidget *parent) : QWidget(parent) { //setMinimumSize(256,256); mapwidget_manipulator = new Manipulator(this); // zoom factor mapwidget_zoomfactor = 0; // reset dragging dragstart_x = 0; dragstart_y = 0; is_dragging = false; mapwidget_selected = 0; setFocusPolicy(Qt::ClickFocus); } float MapWidget::zoom() const { return ::pow(2.0f, (float) mapwidget_zoomfactor); } void MapWidget::wheelEvent(QWheelEvent *event) { if (event->orientation() == Qt::Vertical) { mapwidget_zoomfactor += event->delta() / 120; if (mapwidget_zoomfactor < - 64) { mapwidget_zoomfactor = -64; } else if (mapwidget_zoomfactor > 64) { mapwidget_zoomfactor = 64; } resizeChildren(); update(); event->accept(); } } void MapWidget::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::RightButton) { dragstart_x = event->pos().x(); dragstart_y = event->pos().y(); event->accept(); is_dragging = true; } else { is_dragging = false; } } void MapWidget::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::RightButton) { is_dragging = false; } } void MapWidget::mouseMoveEvent(QMouseEvent *event) { if (is_dragging) { float delta_x = event->pos().x() - dragstart_x; float delta_y = event->pos().y() - dragstart_y; // move map center, mapwidget_center is in world coordinates mapwidget_center[0] += delta_y / zoom(); mapwidget_center[1] += delta_x / zoom(); dragstart_x = event->pos().x(); dragstart_y = event->pos().y(); event->accept(); resizeChildren(); update(); } } void MapWidget::resizeChildren() { if ((width() < 16) || (height() < 16)) return; for (int i = 0; i < mapwidget_enties.size(); ++i) { EntityWidget * entity = mapwidget_enties.at(i); int radius = (int) (entity->properties()->radius() * zoom()); if (radius < 6) { radius = 6; } int x = width() / 2 - (int)((entity->properties()->location()[1] - mapwidget_center[1]) * zoom()) - radius; int y = height() / 2 - (int)((entity->properties()->location()[0] - mapwidget_center[0]) * zoom()) - radius; entity->setGeometry(x, y, radius * 2 , radius * 2); if (entity->selected()) { mapwidget_manipulator->setSize(entity); mapwidget_manipulator->setProperties(entity->properties()); mapwidget_manipulator->update(); } } } void MapWidget::deselect() { for (int i = 0; i < mapwidget_enties.size(); ++i) { EntityWidget *entitywidget = mapwidget_enties.at(i); entitywidget->set_selected(false); } mapwidget_selected = 0; emit propertiesChanged(0); mapwidget_manipulator->setMode(Manipulator::None); mapwidget_manipulator->update(); } void MapWidget::dragEntity(EntityWidget *entity, int x, int y) { int radius = (int) (entity->properties()->radius() * zoom()); if (radius < 6) radius = 6; entity->properties()->set_location( entity->properties()->location()[0] - (int) ((float) (y - radius) / zoom()), entity->properties()->location()[1] - (int) ((float) (x - radius) / zoom()), entity->properties()->location()[2] ); emit propertiesChanged(entity->properties()); resizeChildren(); mapwidget_manipulator->setMode(Manipulator::Move); } void MapWidget::select(EntityWidget *entity) { mapwidget_selected = 0; mapwidget_manipulator->setMode(Manipulator::None); for (int i = 0; i < mapwidget_enties.size(); ++i) { EntityWidget *entitywidget = mapwidget_enties.at(i); if (entity == entitywidget) { 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); mapwidget_selected = entity; } else { entitywidget->set_selected(false); } } update(); } void MapWidget::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Escape) { deselect(); event->accept(); } else { event->ignore(); } } void MapWidget::resizeEvent(QResizeEvent *event) { resizeChildren(); } void MapWidget::paintEvent(QPaintEvent *event) { if ((width() < 16) || (height() < 16)) return; const QColor gridlinecolor(0, 0, 128); const QColor axislinecolor(128, 0, 0); QPen pen(gridlinecolor, 1, Qt::SolidLine); QPainter painter(this); painter.setPen(pen); // mapwidget_zoom is used to scale from game units to screen coorinates // 1 grid square is 128 game units // gridsize is the size of one grid square in screen coordinates int gridsize = (int) (128.0f * zoom()); if (gridsize <= 0) return; int x = (int)(mapwidget_center.y() * zoom()) + width() / 2; pen.setColor(axislinecolor); painter.setPen(pen); painter.drawLine(x, 0, x, height()); x -= gridsize; pen.setColor(gridlinecolor); painter.setPen(pen); while (x > 0) { painter.drawLine(x, 0, x, height()); x -= gridsize; } x = (int) (mapwidget_center.y() * zoom()) + width() / 2 + gridsize; while (x <= width()) { painter.drawLine(x, 0, x, height()); x += gridsize; } int y = (int) (mapwidget_center.x() * zoom()) + height() / 2; pen.setColor(axislinecolor); painter.setPen(pen); painter.drawLine(0, y, width(), y); y -= gridsize; pen.setColor(gridlinecolor); painter.setPen(pen); while (y > 0) { painter.drawLine(0, y, width(), y); y -= gridsize; } y = (int) (mapwidget_center.x() * zoom()) + height() / 2 + gridsize; while (y <= height()) { painter.drawLine(0, y, width(), y); y += gridsize; } } void MapWidget::save(QTextStream &textstream) { for (int i = 0; i < mapwidget_enties.size(); ++i) { EntityWidget *entitywidget = mapwidget_enties.at(i); entitywidget->properties()->save(textstream); } } EntityWidget *MapWidget::addEntity() { EntityWidget *entitywidget = new EntityWidget(this); mapwidget_enties.append(entitywidget); // connect the EntityWidget::clicked() signal to the MapWidget::selected() slot connect(entitywidget, SIGNAL(clicked(EntityWidget *)), this, SLOT(select(EntityWidget *))); connect(entitywidget, SIGNAL(dragMove(EntityWidget *, int, int)), this, SLOT(dragEntity(EntityWidget *, int, int))); entitywidget->show(); resizeChildren(); update(); return entitywidget; } void MapWidget::duplicateSelected() { std::vector new_widgets; for (int i = 0; i < mapwidget_enties.size(); ++i) { EntityWidget *entitywidget = mapwidget_enties.at(i); if (entitywidget->selected()) { // duplicate the child widget EntityWidget *new_entitywidget = addEntity(); new_widgets.push_back(new_entitywidget); new_entitywidget->assign(*entitywidget); // offset the new widget's position const int offset = 32; Vector3f location = new_entitywidget->properties()->location(); new_entitywidget->properties()->set_location(location.x() + offset, location.y() - offset, location.z()); // deselect the old widgets entitywidget->set_selected(false); } else { } } // select the new widgets for(int i = 0; i < new_widgets.size(); ++i) new_widgets.at(i)->set_selected(true); resizeChildren(); update(); } void MapWidget::deleteSelected() { Entities::iterator i = mapwidget_enties.begin(); while (i != mapwidget_enties.end()) { EntityWidget *entitywidget = (*i); if (entitywidget->selected()) { // delete the child widget delete entitywidget; // set the pointer in the list to NULL (*i) = 0; // remove the actual list entry i = mapwidget_enties.erase(i); } else { ++i; } } deselect(); } }