1
0
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:
nordsoft 2023-10-13 05:21:09 +02:00
parent 006def7690
commit d85c5189ba
12 changed files with 207 additions and 28 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -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);
}

View File

@ -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;

View File

@ -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>

View File

@ -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)

View File

@ -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);

View File

@ -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)

View File

@ -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)
{

View File

@ -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();
};