/* 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 #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; is_box_selecting = false; mapwidget_selected = 0; setFocusPolicy(Qt::ClickFocus); } float MapWidget::zoom() const { return ::pow(2.0f, (float) mapwidget_zoomfactor); } void MapWidget::wheelEvent(QWheelEvent *event) { QPoint p = event->angleDelta() / 120; if (!p.isNull()) { mapwidget_zoomfactor += p.y(); 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::LeftButton) { dragstart_x = event->pos().x(); dragstart_y = event->pos().y(); dragstop_x = dragstart_x; dragstop_y = dragstart_y; is_dragging = false; is_box_selecting = true; event->accept(); } else if (event->button() == Qt::RightButton) { dragstart_x = event->pos().x(); dragstart_y = event->pos().y(); is_dragging = true; is_box_selecting = false; event->accept(); } else { is_dragging = false; is_box_selecting = false; } } void MapWidget::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { doBoxSelect(); is_box_selecting = false; update(); } else 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(); } else if (is_box_selecting) { dragstop_x = event->pos().x(); dragstop_y = event->pos().y(); event->accept(); 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()== EntityWidget::SelectActive) { mapwidget_manipulator->setSize(entity); mapwidget_manipulator->setProperties(entity->properties()); mapwidget_manipulator->update(); } } } void MapWidget::doBoxSelect() { // deselect all for (int i = 0; i < mapwidget_enties.size(); ++i) { EntityWidget *entitywidget = mapwidget_enties.at(i); entitywidget->set_selected(EntityWidget::SelectNone); } const int x = dragstop_x < dragstart_x ? dragstop_x : dragstart_x; const int y = dragstop_y < dragstart_y ? dragstop_y : dragstart_y; const int w = abs(dragstop_x - dragstart_x); const int h = abs(dragstop_y - dragstart_y); QRect box(x, y, w, h); mapwidget_selected = 0; for (int i = 0; i < mapwidget_enties.size(); ++i) { EntityWidget *entitywidget = mapwidget_enties.at(i); if (box.contains(entitywidget->geometry())) { entitywidget->set_selected(EntityWidget::SelectHighlight); mapwidget_selected = entitywidget; } } if (mapwidget_selected) { mapwidget_selected->set_selected(EntityWidget::SelectActive); emit propertiesChanged(mapwidget_selected->properties()); mapwidget_manipulator->setMode(Manipulator::Select); mapwidget_manipulator->setProperties(mapwidget_selected->properties()); mapwidget_manipulator->setSize(mapwidget_selected); } else { mapwidget_selected = 0; emit propertiesChanged(0); mapwidget_manipulator->setMode(Manipulator::None); } mapwidget_manipulator->update(); } void MapWidget::deselect() { for (int i = 0; i < mapwidget_enties.size(); ++i) { EntityWidget *entitywidget = mapwidget_enties.at(i); entitywidget->set_selected(EntityWidget::SelectNone); } 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; for (int i = 0; i < mapwidget_enties.size(); ++i) { EntityWidget *entitywidget = mapwidget_enties.at(i); if ((entitywidget->selected() == EntityWidget::SelectHighlight) || (entitywidget->selected() == EntityWidget::SelectActive)) { entitywidget->properties()->set_location( entitywidget->properties()->location()[0] - (int) ((float) (y - radius) / zoom()), entitywidget->properties()->location()[1] - (int) ((float) (x - radius) / zoom()), entitywidget->properties()->location()[2] ); } } emit propertiesChanged(entity->properties()); resizeChildren(); mapwidget_manipulator->setMode(Manipulator::Move); } void MapWidget::select(EntityWidget *entity) { if (mapwidget_selected == entity) { return; } 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(EntityWidget::SelectActive); //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(EntityWidget::SelectNone); } } 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; } if (is_box_selecting) { x = dragstop_x < dragstart_x ? dragstop_x : dragstart_x; y = dragstop_y < dragstart_y ? dragstop_y : dragstart_y; int w = abs(dragstop_x - dragstart_x); int h = abs(dragstop_y - dragstart_y); pen.setColor(QColor(255, 0, 0)); painter.setPen(pen); painter.drawRect(x, y, w ,h); } } 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() { // obtain count only once, this will exclude the new widgets copying itself in an endless loop const int count = mapwidget_enties.size(); for (int i = 0; i < count; ++i) { EntityWidget *entitywidget = mapwidget_enties.at(i); if ((entitywidget->selected() == EntityWidget::SelectHighlight) || (entitywidget->selected() == EntityWidget::SelectActive)) { // duplicate the child widget EntityWidget *new_entitywidget = addEntity(); 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()); // copy selection state to the new widget new_entitywidget->set_selected(entitywidget->selected()); // deselect the old widgets entitywidget->set_selected(EntityWidget::SelectNone); if (entitywidget == mapwidget_selected) { mapwidget_selected = new_entitywidget; } } } emit propertiesChanged(mapwidget_selected->properties()); resizeChildren(); update(); } void MapWidget::deleteSelected() { Entities::iterator i = mapwidget_enties.begin(); while (i != mapwidget_enties.end()) { EntityWidget *entitywidget = (*i); if ((entitywidget->selected() == EntityWidget::SelectHighlight) || (entitywidget->selected() == EntityWidget::SelectActive)) { // 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(); } }