mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Add object lock and zoom functinoality
This commit is contained in:
parent
006def7690
commit
d85c5189ba
BIN
mapeditor/icons/zoom_base.png
Normal file
BIN
mapeditor/icons/zoom_base.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
mapeditor/icons/zoom_minus.png
Normal file
BIN
mapeditor/icons/zoom_minus.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
mapeditor/icons/zoom_plus.png
Normal file
BIN
mapeditor/icons/zoom_plus.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
mapeditor/icons/zoom_zero.png
Normal file
BIN
mapeditor/icons/zoom_zero.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
@ -222,6 +222,8 @@ MainWindow::MainWindow(QWidget* parent) :
|
||||
scenePreview = new QGraphicsScene(this);
|
||||
ui->objectPreview->setScene(scenePreview);
|
||||
|
||||
initialScale = ui->mapView->viewport()->geometry();
|
||||
|
||||
//loading objects
|
||||
loadObjectsTree();
|
||||
|
||||
@ -296,6 +298,7 @@ void MainWindow::initializeMap(bool isNew)
|
||||
ui->mapView->setScene(controller.scene(mapLevel));
|
||||
ui->minimapView->setScene(controller.miniScene(mapLevel));
|
||||
ui->minimapView->dimensions();
|
||||
initialScale = ui->mapView->mapToScene(ui->mapView->viewport()->geometry()).boundingRect();
|
||||
|
||||
//enable settings
|
||||
ui->actionMapSettings->setEnabled(true);
|
||||
@ -1281,3 +1284,65 @@ void MainWindow::on_actionh3m_converter_triggered()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_actionLock_triggered()
|
||||
{
|
||||
if(controller.map())
|
||||
{
|
||||
if(controller.scene(mapLevel)->selectionObjectsView.getSelection().empty())
|
||||
{
|
||||
for(auto obj : controller.map()->objects)
|
||||
{
|
||||
controller.scene(mapLevel)->selectionObjectsView.setLockObject(obj, true);
|
||||
controller.scene(mapLevel)->objectsView.setLockObject(obj, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(auto * obj : controller.scene(mapLevel)->selectionObjectsView.getSelection())
|
||||
{
|
||||
controller.scene(mapLevel)->selectionObjectsView.setLockObject(obj, true);
|
||||
controller.scene(mapLevel)->objectsView.setLockObject(obj, true);
|
||||
}
|
||||
controller.scene(mapLevel)->selectionObjectsView.clear();
|
||||
}
|
||||
controller.scene(mapLevel)->objectsView.update();
|
||||
controller.scene(mapLevel)->selectionObjectsView.update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_actionUnlock_triggered()
|
||||
{
|
||||
if(controller.map())
|
||||
{
|
||||
controller.scene(mapLevel)->selectionObjectsView.unlockAll();
|
||||
controller.scene(mapLevel)->objectsView.unlockAll();
|
||||
}
|
||||
controller.scene(mapLevel)->objectsView.update();
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_actionZoom_in_triggered()
|
||||
{
|
||||
auto rect = ui->mapView->mapToScene(ui->mapView->viewport()->geometry()).boundingRect();
|
||||
rect -= QMargins{32 + 1, 32 + 1, 32 + 2, 32 + 2}; //compensate bounding box
|
||||
ui->mapView->fitInView(rect, Qt::KeepAspectRatioByExpanding);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_actionZoom_out_triggered()
|
||||
{
|
||||
auto rect = ui->mapView->mapToScene(ui->mapView->viewport()->geometry()).boundingRect();
|
||||
rect += QMargins{32 - 1, 32 - 1, 32 - 2, 32 - 2}; //compensate bounding box
|
||||
ui->mapView->fitInView(rect, Qt::KeepAspectRatioByExpanding);
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_actionZoom_reset_triggered()
|
||||
{
|
||||
auto center = ui->mapView->mapToScene(ui->mapView->viewport()->geometry().center());
|
||||
ui->mapView->fitInView(initialScale, Qt::KeepAspectRatioByExpanding);
|
||||
ui->mapView->centerOn(center);
|
||||
}
|
||||
|
||||
|
@ -124,6 +124,16 @@ private slots:
|
||||
|
||||
void on_actionh3m_converter_triggered();
|
||||
|
||||
void on_actionLock_triggered();
|
||||
|
||||
void on_actionUnlock_triggered();
|
||||
|
||||
void on_actionZoom_in_triggered();
|
||||
|
||||
void on_actionZoom_out_triggered();
|
||||
|
||||
void on_actionZoom_reset_triggered();
|
||||
|
||||
public slots:
|
||||
|
||||
void treeViewSelected(const QModelIndex &selected, const QModelIndex &deselected);
|
||||
@ -166,6 +176,7 @@ private:
|
||||
QStandardItemModel objectsModel;
|
||||
|
||||
int mapLevel = 0;
|
||||
QRectF initialScale;
|
||||
|
||||
std::set<int> catalog;
|
||||
|
||||
|
@ -86,6 +86,8 @@
|
||||
<addaction name="actionCopy"/>
|
||||
<addaction name="actionPaste"/>
|
||||
<addaction name="actionErase"/>
|
||||
<addaction name="actionLock"/>
|
||||
<addaction name="actionUnlock"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuView">
|
||||
<property name="title">
|
||||
@ -94,6 +96,10 @@
|
||||
<addaction name="actionLevel"/>
|
||||
<addaction name="actionGrid"/>
|
||||
<addaction name="actionPass"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionZoom_in"/>
|
||||
<addaction name="actionZoom_out"/>
|
||||
<addaction name="actionZoom_reset"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuPlayer">
|
||||
<property name="title">
|
||||
@ -143,6 +149,13 @@
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionFill"/>
|
||||
<addaction name="actionTranslations"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionLock"/>
|
||||
<addaction name="actionUnlock"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionZoom_in"/>
|
||||
<addaction name="actionZoom_out"/>
|
||||
<addaction name="actionZoom_reset"/>
|
||||
</widget>
|
||||
<widget class="QDockWidget" name="dockWidget_2">
|
||||
<property name="sizePolicy">
|
||||
@ -804,8 +817,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>128</width>
|
||||
<height>192</height>
|
||||
<width>256</width>
|
||||
<height>90</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -847,8 +860,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>128</width>
|
||||
<height>192</height>
|
||||
<width>256</width>
|
||||
<height>90</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -883,8 +896,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>128</width>
|
||||
<height>192</height>
|
||||
<width>256</width>
|
||||
<height>90</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -1332,6 +1345,57 @@
|
||||
<string>h3m converter</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionLock">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>icons:lock-closed.png</normaloff>icons:lock-closed.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Lock</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Lock objects on map to avoid unnecessary changes</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionUnlock">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>icons:lock-open.png</normaloff>icons:lock-open.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Unlock</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Unlock all objects on the map</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionZoom_in">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>icons:zoom_plus.png</normaloff>icons:zoom_plus.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Zoom in</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionZoom_out">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>icons:zoom_minus.png</normaloff>icons:zoom_minus.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Zoom out</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionZoom_reset">
|
||||
<property name="icon">
|
||||
<iconset>
|
||||
<normaloff>icons:zoom_zero.png</normaloff>icons:zoom_zero.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Zoom reset</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
@ -322,8 +322,11 @@ std::vector<TileObject> & MapHandler::getObjects(int x, int y, int z)
|
||||
return ttiles[index(x, y, z)];
|
||||
}
|
||||
|
||||
void MapHandler::drawObjects(QPainter & painter, int x, int y, int z)
|
||||
void MapHandler::drawObjects(QPainter & painter, int x, int y, int z, const std::set<const CGObjectInstance *> & locked)
|
||||
{
|
||||
painter.setRenderHint(QPainter::Antialiasing, false);
|
||||
painter.setRenderHint(QPainter::SmoothPixmapTransform, false);
|
||||
|
||||
for(auto & object : getObjects(x, y, z))
|
||||
{
|
||||
const CGObjectInstance * obj = object.obj;
|
||||
@ -343,8 +346,15 @@ void MapHandler::drawObjects(QPainter & painter, int x, int y, int z)
|
||||
{
|
||||
auto pos = obj->getPosition();
|
||||
|
||||
painter.drawImage(QPoint(x * tileSize, y * tileSize), *objData.objBitmap, object.rect);
|
||||
|
||||
painter.drawImage(QPoint(x * tileSize, y * tileSize), *objData.objBitmap, object.rect, Qt::AutoColor | Qt::NoOpaqueDetection);
|
||||
|
||||
if(locked.count(obj))
|
||||
{
|
||||
painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
||||
painter.fillRect(x * tileSize, y * tileSize, object.rect.width(), object.rect.height(), Qt::Dense4Pattern);
|
||||
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
||||
}
|
||||
|
||||
if(objData.flagBitmap)
|
||||
{
|
||||
if(x == pos.x && y == pos.y)
|
||||
|
@ -88,6 +88,8 @@ private:
|
||||
void initObjectRects();
|
||||
void initTerrainGraphics();
|
||||
QRgb getTileColor(int x, int y, int z);
|
||||
|
||||
QPolygon lockBitMask;
|
||||
|
||||
public:
|
||||
MapHandler();
|
||||
@ -110,7 +112,7 @@ public:
|
||||
std::vector<int3> getTilesUnderObject(CGObjectInstance *) const;
|
||||
|
||||
/// draws all objects on current tile (higher-level logic, unlike other draw*** methods)
|
||||
void drawObjects(QPainter & painter, int x, int y, int z);
|
||||
void drawObjects(QPainter & painter, int x, int y, int z, const std::set<const CGObjectInstance *> & locked);
|
||||
void drawObject(QPainter & painter, const TileObject & object);
|
||||
void drawObjectAt(QPainter & painter, const CGObjectInstance * object, int x, int y);
|
||||
std::vector<TileObject> & getObjects(int x, int y, int z);
|
||||
|
@ -44,15 +44,9 @@ void MinimapView::mouseMoveEvent(QMouseEvent *mouseEvent)
|
||||
if(!sc)
|
||||
return;
|
||||
|
||||
int w = sc->viewport.viewportWidth();
|
||||
int h = sc->viewport.viewportHeight();
|
||||
auto pos = mapToScene(mouseEvent->pos());
|
||||
pos.setX(pos.x() - w / 2);
|
||||
pos.setY(pos.y() - h / 2);
|
||||
|
||||
QPointF point = pos * 32;
|
||||
|
||||
emit cameraPositionChanged(point);
|
||||
pos *= 32;
|
||||
emit cameraPositionChanged(pos);
|
||||
}
|
||||
|
||||
void MinimapView::mousePressEvent(QMouseEvent* event)
|
||||
@ -68,8 +62,7 @@ MapView::MapView(QWidget * parent):
|
||||
|
||||
void MapView::cameraChanged(const QPointF & pos)
|
||||
{
|
||||
horizontalScrollBar()->setValue(pos.x());
|
||||
verticalScrollBar()->setValue(pos.y());
|
||||
centerOn(pos);
|
||||
}
|
||||
|
||||
void MapView::setController(MapController * ctrl)
|
||||
|
@ -377,8 +377,7 @@ void ObjectsLayer::draw(bool onlyDirty)
|
||||
return;
|
||||
|
||||
QPainter painter(pixmap.get());
|
||||
std::set<const CGObjectInstance *> drawen;
|
||||
|
||||
|
||||
if(onlyDirty)
|
||||
{
|
||||
//objects could be modified
|
||||
@ -392,7 +391,7 @@ void ObjectsLayer::draw(bool onlyDirty)
|
||||
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
||||
|
||||
for(auto & p : dirty)
|
||||
handler->drawObjects(painter, p.x, p.y, p.z);
|
||||
handler->drawObjects(painter, p.x, p.y, p.z, lockedObjects);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -401,7 +400,7 @@ void ObjectsLayer::draw(bool onlyDirty)
|
||||
{
|
||||
for(int i = 0; i < map->width; ++i)
|
||||
{
|
||||
handler->drawObjects(painter, i, j, scene->level);
|
||||
handler->drawObjects(painter, i, j, scene->level, lockedObjects);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -430,6 +429,19 @@ void ObjectsLayer::setDirty(const CGObjectInstance * object)
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectsLayer::setLockObject(const CGObjectInstance * object, bool lock)
|
||||
{
|
||||
if(lock)
|
||||
lockedObjects.insert(object);
|
||||
else
|
||||
lockedObjects.erase(object);
|
||||
}
|
||||
|
||||
void ObjectsLayer::unlockAll()
|
||||
{
|
||||
lockedObjects.clear();
|
||||
}
|
||||
|
||||
SelectionObjectsLayer::SelectionObjectsLayer(MapSceneBase * s): AbstractLayer(s), newObject(nullptr)
|
||||
{
|
||||
}
|
||||
@ -501,7 +513,7 @@ CGObjectInstance * SelectionObjectsLayer::selectObjectAt(int x, int y, const CGO
|
||||
//visitable is most important
|
||||
for(auto & object : objects)
|
||||
{
|
||||
if(!object.obj || object.obj == ignore)
|
||||
if(!object.obj || object.obj == ignore || lockedObjects.count(object.obj))
|
||||
continue;
|
||||
|
||||
if(object.obj->visitableAt(x, y))
|
||||
@ -513,7 +525,7 @@ CGObjectInstance * SelectionObjectsLayer::selectObjectAt(int x, int y, const CGO
|
||||
//if not visitable tile - try to get blocked
|
||||
for(auto & object : objects)
|
||||
{
|
||||
if(!object.obj || object.obj == ignore)
|
||||
if(!object.obj || object.obj == ignore || lockedObjects.count(object.obj))
|
||||
continue;
|
||||
|
||||
if(object.obj->blockingAt(x, y))
|
||||
@ -525,7 +537,7 @@ CGObjectInstance * SelectionObjectsLayer::selectObjectAt(int x, int y, const CGO
|
||||
//finally, we can take any object
|
||||
for(auto & object : objects)
|
||||
{
|
||||
if(!object.obj || object.obj == ignore)
|
||||
if(!object.obj || object.obj == ignore || lockedObjects.count(object.obj))
|
||||
continue;
|
||||
|
||||
if(object.obj->coveringAt(x, y))
|
||||
@ -555,7 +567,8 @@ void SelectionObjectsLayer::selectObjects(int x1, int y1, int x2, int y2)
|
||||
if(map->isInTheMap(int3(i, j, scene->level)))
|
||||
{
|
||||
for(auto & o : handler->getObjects(i, j, scene->level))
|
||||
selectObject(o.obj, false); //do not inform about each object added
|
||||
if(!lockedObjects.count(o.obj))
|
||||
selectObject(o.obj, false); //do not inform about each object added
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -599,6 +612,19 @@ void SelectionObjectsLayer::onSelection()
|
||||
emit selectionMade(!selectedObjects.empty());
|
||||
}
|
||||
|
||||
void SelectionObjectsLayer::setLockObject(const CGObjectInstance * object, bool lock)
|
||||
{
|
||||
if(lock)
|
||||
lockedObjects.insert(object);
|
||||
else
|
||||
lockedObjects.erase(object);
|
||||
}
|
||||
|
||||
void SelectionObjectsLayer::unlockAll()
|
||||
{
|
||||
lockedObjects.clear();
|
||||
}
|
||||
|
||||
MinimapLayer::MinimapLayer(MapSceneBase * s): AbstractLayer(s)
|
||||
{
|
||||
|
||||
|
@ -120,9 +120,13 @@ public:
|
||||
|
||||
void setDirty(int x, int y);
|
||||
void setDirty(const CGObjectInstance * object);
|
||||
|
||||
void setLockObject(const CGObjectInstance * object, bool lock);
|
||||
void unlockAll();
|
||||
|
||||
private:
|
||||
std::set<const CGObjectInstance *> objDirty;
|
||||
std::set<const CGObjectInstance *> lockedObjects;
|
||||
std::set<int3> dirty;
|
||||
};
|
||||
|
||||
@ -180,6 +184,9 @@ public:
|
||||
bool isSelected(const CGObjectInstance *) const;
|
||||
std::set<CGObjectInstance*> getSelection() const;
|
||||
void clear();
|
||||
|
||||
void setLockObject(const CGObjectInstance * object, bool lock);
|
||||
void unlockAll();
|
||||
|
||||
QPoint shift;
|
||||
CGObjectInstance * newObject;
|
||||
@ -191,6 +198,7 @@ signals:
|
||||
|
||||
private:
|
||||
std::set<CGObjectInstance *> selectedObjects;
|
||||
std::set<const CGObjectInstance *> lockedObjects;
|
||||
|
||||
void onSelection();
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user