-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Minimap in a resizing dialog #1516
Conversation
This is something I have wanted to do for years, but somehow never prioritized it over other stuff. I shortly tried it out and it's really cool! I'll try to get around to a detailed code review in the evening, or at least in the coming days.
I'm not sure about this. It depends on whether it's more important for the user to see the remaining piece of the map, or what part he is cutting away. If the remaining piece is what he wants to focus on, it should be generally easier to select that area and use the "Crop to Selection" action. So in general I'm inclined to think it's better to make sure the whole map is visible, even if it will be smaller as a result. |
|
Nice catch! Can you open a separate pull request for the this bug, to the
I don't notice strange behavior currently in Tiled, so I assume this was about this pull request? |
Oh, yes, it becomes strange to me only when a minimap is inserted.
Ok, is it still needed here? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A preview behavior was strange if a new size was smaller than an old one. Now in that case it doesn't scale and a user can select a new rect by moving a frame.
I think the behavior is still unexpected and would prefer you reverted the changes made to the mouse handling and scale calculations. The original behavior was intentional, and you can see this also in the same kind of widget in GIMP when going to Image -> Canvas Size.
I've added some inline comments regarding the implementation.
@@ -0,0 +1,126 @@ | |||
#include "minimaprenderer.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't forget to copy the license header from minimap.cpp
.
src/tiled/minimaprenderer.h
Outdated
|
||
Q_DECLARE_FLAGS(MiniMapRenderFlags, MiniMapRenderFlag) | ||
|
||
static MiniMapRenderer* instance(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I doesn't makes sense to have the MiniMapRenderer
as a singleton, since it doesn't store any state that would be useful to keep around. Instead, please just allocate it on the stack where you need it, passing the MapDocument*
to its constructor instead of having a setMapDocument
method:
MiniMapRenderer renderer(mMapDocument);
renderer.renderToImage(image, flags);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is that ResizeHelper
has no mMapDocument
. That's why I've implemented the renderer as a singleton.
Or is it better to somehow pass it to ResizeHelper
? I think it is more complicated than the singleton approach.
src/tiled/minimaprenderer.h
Outdated
class MiniMapRenderer | ||
{ | ||
public: | ||
enum MiniMapRenderFlag { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please call it just RenderFlags
.
src/tiled/minimaprenderer.h
Outdated
Q_DECLARE_FLAGS(MiniMapRenderFlags, MiniMapRenderFlag) | ||
|
||
static MiniMapRenderer* instance(); | ||
void renderMinimapToImage(QImage& image, const MiniMapRenderFlags minimapRenderFlags) const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can call this renderToImage
since it's clear that it renders a mini-map.
You can remove the const
on the flags
parameter (please also shorten its name). It has no meaning since the parameter is passed by value.
src/tiled/minimaprenderer.h
Outdated
/* | ||
* minimaprenderer.h | ||
* Copyright 2017, Yuriy Natarov <natarur@gmail.com> | ||
* Based on a minimap by Christoph Schnackenberg and Thorbjørn Lindeijer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please just copy the copyright lines from minimap.h
instead of writing a custom message.
src/tiled/resizehelper.cpp
Outdated
mMiniMapRenderer->renderMinimapToImage(minimap, MiniMapRenderer::DrawObjects | ||
| MiniMapRenderer::DrawImages | ||
| MiniMapRenderer::DrawTiles | ||
| MiniMapRenderer::IgnoreInvisibleLayer); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rendering the mini-map on each paint event is too slow for large maps. Instead, please keep the image around and only repaint it when the scale changes.
Ideally, we'd do the rendering in a thread. I think we can easily do that here, because the resize helper dialog is modal so there can't be any changes to the underlying data in the meantime. Up to you whether you want to look into that or leave it for later.
Done, but I personally think that my approach was better because currently, in case of a map shrinking, a lot of the space is unused and the minimap become smaller, so as a profit from its usage here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is that ResizeHelper has no mMapDocument. That's why I've implemented the renderer as a singleton.
Or is it better to somehow pass it to ResizeHelper? I think it is more complicated than the singleton approach.
Hmm, right, I hadn't thought of that. I'm not entirely happy with the singleton solution though. I'll need to find some time to consider other solutions.
Done, but I personally think that my approach was better because currently, in case of a map shrinking, a lot of the space is unused and the minimap become smaller, so as a profit from its usage here.
While you're right that the image is smaller that it'd need to be, I think it is confusing when you for example scale a 100x100 map to 50x200 map, that in one direction the mouse drags the existing map and in the other direction it drags the preview of the new area.
src/tiled/resizehelper.cpp
Outdated
@@ -179,7 +177,13 @@ void ResizeHelper::recalculateScale() | |||
// Pick the smallest scale | |||
const double scaleW = _size.width() / (double) width; | |||
const double scaleH = _size.height() / (double) height; | |||
mScale = (scaleW < scaleH) ? scaleW : scaleH; | |||
mScale = qMin(scaleW, scaleH); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That the scale is recalculated doesn't mean it'll change, so please still compare with the previous scale and don't recreate the image when it isn't necessary.
How about zooming as a compromise solution? It allows a user to switch between a general and a detailed picture. Waiting for your ideas regarding the singleton. |
I like the zooming! It's rather hidden, but indeed this way it can help people who want to see more detail. About the singleton, I struggled a bit to resolve it myself, and then rather than explaining how I would like it to be solved, I decided to just push that in a follow-up change myself. See commit 62a89e1. It may make the code a little more convoluted, especially since I needed to forward the renderer callback from the ResizeDialog, but it keeps things more cleanly separated. Thanks for the nice improvement! I do hope that before release either me or somebody else will get around to making it render the image in a thread so that the UI stays more responsive when resizing larger maps. |
Not sure why I didn't think if this before, but I noticed today that the implementation as such only works for orthogonal maps using square tiles. I've opened issue #1554 about extending the functionality to other map configurations. |
I think it is useful to allow a user to see what exactly is going to be removed while resizing and visually estimate the proportions.