Skip to content

Improve: remember 2D mapper zoom amounts between sessions#6615

Merged
SlySven merged 7 commits intoMudlet:developmentfrom
SlySven:Improve_rememberMapperZoomAmountBetweenSessions_simplified
Mar 16, 2023
Merged

Improve: remember 2D mapper zoom amounts between sessions#6615
SlySven merged 7 commits intoMudlet:developmentfrom
SlySven:Improve_rememberMapperZoomAmountBetweenSessions_simplified

Conversation

@SlySven
Copy link
Copy Markdown
Member

@SlySven SlySven commented Mar 8, 2023

This is intended to close #2388.

This enables the 2D (only) map zoom amounts for each map area to be save independently and restored when switching between areas in the mapper. It also saves the data between session.

It extends the existing setMapZoom(...) API to take an optional second argument to specify the map area ID to set the zoom (which is a floating point number) for any existing area, not just the current one.

It also adds a getMapZoom(...) function that, without any arguments, returns the currently used 2D map zoom value for the area currently being shown in the 2D mapper. If an area ID is provided it instead returns the value that was last used for that area - or the default value that is used initially on starting the profile or for an area that has not been viewed before.

Importantly when switching between the areas in the 2D mapper the values are retained and applied so that one area can be zoomed in and another zoomed out and switching from the first to the second and back to the first means that the zoom level used in the first is reused when it is returned to. Deleting an area will forget the stored zoom level so if it is reused it starts from scratch.

Code to save the zoom level for each area has also been implemented within the C++ core. It saves it in the Area User Data for current map formats (but removes it on loading so the user never sees it there) under a system.fallback_map2DZoom key but will save it directly in the binary data (which is more efficient) in the next format version whenever it is enabled.

A new Mudlet event, which has been called mapAreaViewedChangeEvent has been added with two additional arguments being the area ID changed to followed by the one that it was changed from. I originally thought I would need it to handle saving the zoom level for each area via the Lua system but I found that that was not practicable. I'll leave it in for now but it could be removed if peer-review finds it not to be of use.

Also, in refactoring T2DMap::paintEvent(...) I:
Removed/combined some locals:

  • (TArea*) playerArea and (TArea*) pPlayerArea ==> pArea
  • (TRoom*) playerRoom ==> pPlayerRoom

Remove unneeded (refactored out):

  • (qreal) ox
  • (qreal) oy

Signed-off by: Stephen Lyons slysven@virginmedia.com

This is intended to close Mudlet#2388.

This enables the 2D (only) map zoom amounts for each map area to be save
independently and restored when switching between areas in the mapper. It
also saves the data between session.

It extends the existing `setMapZoom(...)` API to take an optional second
argument to specify the map area ID to set the zoom (which is a floating
point number) for any existing area, not just the current one.

It also adds a `getMapZoom(...)` function that, without any arguments,
returns the currently used 2D map zoom value for the area currently being
shown in the 2D mapper. If an area ID is provided it instead returns the
value that was last used for that area - or the default value that is used
initially on starting the profile or for an area that has not been viewed
before.

Importantly when switching between the areas in the 2D mapper the values
are retained and applied so that one area can be zoomed in and another
zoomed out and switching from the first to the second and back to the first
means that the zoom level used in the first is reused when it is returned
to. Deleting an area will forget the stored zoom level so if it is reused
it starts from scratch.

Code to save the zoom level for each area has also been implemented within
the C++ core. It saves it in the Area User Data for current map formats
(but removes it on loading so the user never sees it there) under a
`system.fallback_map2DZoom` key but will save it directly in the binary
data (which is more efficient) in the next format version whenever it is
enabled.

A new Mudlet event, which has been called `mapAreaViewedChangeEvent` has
been added with two additional arguments being the area ID changed to
followed by the one that it was changed from. I originally thought I
would need it to handle saving the zoom level for each area via the Lua
system but I found that that was not practicable. I'll leave it in for
now but it could be removed if peer-review finds it not to be of use.

Also, in refactoring `T2DMap::paintEvent(...)` I:
Removed/combined some locals:
* `(TArea*) playerArea` and `(TArea*) pPlayerArea` ==> `pArea`
* `(TRoom*) playerRoom` ==> `pPlayerRoom`

Remove unneeded (refactored out):
* `(qreal) ox`
* `(qreal) oy`

Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
@SlySven SlySven added enhancement bounty-50 see https://wiki.mudlet.org/w/Bounty_Process labels Mar 8, 2023
@SlySven SlySven added this to the 4.18.0 milestone Mar 8, 2023
@SlySven SlySven requested a review from a team as a code owner March 8, 2023 05:39
@SlySven SlySven requested review from a team March 8, 2023 05:39
@add-deployment-links
Copy link
Copy Markdown

add-deployment-links bot commented Mar 8, 2023

Hey there! Thanks for helping Mudlet improve. 🌟

Test versions

You can directly test the changes here:

No need to install anything - just unzip and run.
Let us know if it works well, and if it doesn't, please give details.

@vadi2 vadi2 changed the title Improve: remember mapper zoom amounts between sessions Improve: remember 2D mapper zoom amounts between sessions Mar 8, 2023
Copy link
Copy Markdown
Contributor

@Kebap Kebap left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does what it says on the tin.
Ideas for further improvement:

  • Also remember the previous position on map, because right now, switching back and to a map will indeed show the same zoom level, but a different position, if you moved in the intermediate area meanwhile.
  • Prevent mapper zoom / pan combinations which actually show no rooms at all in the resulting view part
  • Smartly calculate a "good" default zoom level for each first visit in an area, so it shows the whole map, unless it gets "too big", whatever that means exactly

Kebap
Kebap previously requested changes Mar 9, 2023
Copy link
Copy Markdown
Contributor

@Kebap Kebap left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seems to be something wrong, as setMapZoom(integer) does not change zoom view at all, and:

image

@Kebap
Copy link
Copy Markdown
Contributor

Kebap commented Mar 9, 2023

If I request lua setMapZoom(1, nil) this should set the current area map zoom to 1, right?
Instead, I receive an error informing me about a missing optional argument:
<setMapZoom: bad argument #2 type (area id as number is optional, got nil!)>

@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Mar 9, 2023

There seems to be something wrong, as setMapZoom(integer) does not change zoom view at all, and:

image

No, the minimum zoom value is 3.0 - anything less than that will produce no effect.

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Mar 9, 2023

In that case it should be a Lua error since it'll never be possible to have a zoom level less than 3. What does zoom value 3.0 actually look like though?

@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Mar 9, 2023

If I request lua setMapZoom(1, nil) this should set the current area map zoom to 1, right? Instead, I receive an error informing me about a missing optional argument: <setMapZoom: bad argument #2 type (area id as number is optional, got nil!)>

The second argument is optional, but by explicitly providing a nil you have provided a value - but it is not the correct type (it is a nil not a number) as the error message is reporting.

Remember someone did a lot of refactoring to create and use all those getVerifiedXxxx(...) functions in the TLuaInterpreter class and they included an argument in them to report that the argument that it is extracting a value for from what was passed to the Lua function that the user is invoking is "optional" rather than "required". However those same functions do not have any code in them to check that the "optional" argument was actually provided by the user! 🙄

@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Mar 9, 2023

In that case it should be a Lua error since it'll never be possible to have a zoom level less than 3. What does zoom value 3.0 actually look like though?

That isn't an (argument type) error, it would only be a (run-time, value) warning - and since the previous code did not do anything to report such an issue and behaved in the same way (as far as setting the zoom for the currently viewed area) I didn't feel compelled to add it.

3.0 looks something like this on my particular setup:
image
That is on a 1920x1080 monitor.

@vadi2
Copy link
Copy Markdown
Member

vadi2 commented Mar 9, 2023

For backwards compatibility that would make sense. It shouldn't return true though should it?

@Kebap
Copy link
Copy Markdown
Contributor

Kebap commented Mar 9, 2023

Remember someone did a lot of refactoring 🙄

What you describe seems like a worthwhile addition (in a new PR).
Indeed I have now compared other existing functions and they show a similar flaw when you provide an optional argument with a nil value.
Then it is OK here for now as well.

@Kebap Kebap added the needs documentation This pull request changes things the players would use/see and thus needs an update in the manual label Mar 9, 2023
@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Mar 9, 2023

For backwards compatibility that would make sense. It shouldn't return true though should it?

Well, given that it has been extended - and there are a number of ways that it can fail and return a nil + error message I think it is not unreasonable to return a true on success. Given that, I now think that it would not be unreasonable to report if the zoom level supplied was too small - that would have given @Kebap a better clue as to what was going on when he tried it and got nothing back when it didn't work. Fortunately that will be a trivial change to do - especially as I parametrised(?) the minimum to a publicly available static symbol (int) T2DMap::csmMinXYZoom! 😀

…l zoom

Also revise the error message for it and the corresponding getter
`getZoom(...)`, when the versions with an area id provided has an id that
doesn't exist, to the same text as some other cases in the Lua API.

Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
}

if (zoom < T2DMap::csmMinXYZoom) {
return warnArgumentValue(L, __func__, qsl("%1 is less than the minimum value allowed for zoom which is %2").arg(QString::number(zoom), QString::number(T2DMap::csmMinXYZoom)));
Copy link
Copy Markdown
Contributor

@Kebap Kebap Mar 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Align language to other warnings in this file.

Suggested change
return warnArgumentValue(L, __func__, qsl("%1 is less than the minimum value allowed for zoom which is %2").arg(QString::number(zoom), QString::number(T2DMap::csmMinXYZoom)));
return warnArgumentValue(L, __func__, qsl("zoom %1 is invalid, it must be greater than %2").arg(QString::number(zoom), QString::number(T2DMap::csmMinXYZoom)));

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically it should be "greater than or equal to" or "not less than" - the second is shorter in English, not sure if that negative form is the clearest to use though.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough.

Suggested change
return warnArgumentValue(L, __func__, qsl("%1 is less than the minimum value allowed for zoom which is %2").arg(QString::number(zoom), QString::number(T2DMap::csmMinXYZoom)));
return warnArgumentValue(L, __func__, qsl("zoom %1 is invalid, it must be at least %2").arg(QString::number(zoom), QString::number(T2DMap::csmMinXYZoom)));

You're welcome.

if (!result) {
// Whilst it will also return false should there not be a map or mapper
// we should have already ruled those cases out:
return warnArgumentValue(L, __func__, qsl("number %1 is not a valid area id").arg(QString::number(areaID.value())));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as discussed in #2605

Suggested change
return warnArgumentValue(L, __func__, qsl("number %1 is not a valid area id").arg(QString::number(areaID.value())));
return warnArgumentValue(L, __func__, qsl("number %1 is not a valid areaID").arg(QString::number(areaID.value())));

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are multiple instances of both texts in the file IIRC and I didn't do a count of each to find which one was precisely the most common... as it is that issue has not, um, been actioned/resolved yet! However I will take on board that you have pointed it out in regard to these texts in the PR.


if (areaID.has_value()) {
if (!host.mpMap->mpRoomDB->getArea(areaID.value())) {
return warnArgumentValue(L, __func__, qsl("number %1 is not a valid area id").arg(QString::number(areaID.value())));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return warnArgumentValue(L, __func__, qsl("number %1 is not a valid area id").arg(QString::number(areaID.value())));
return warnArgumentValue(L, __func__, qsl("number %1 is not a valid areaID").arg(QString::number(areaID.value())));

@Kebap
Copy link
Copy Markdown
Contributor

Kebap commented Mar 10, 2023

The default zoom value seems not very enticing, and short of implementing any smart calculation, I implore you to reconsider this:

I foresee setting zoom per-area being a massive amount of pain since it'll reset between areas on the first time and so on.

If you enter a new area for the first time that does not have a zoom setting yet, start with the previous area's one.

@Kebap
Copy link
Copy Markdown
Contributor

Kebap commented Mar 10, 2023

There seems to be something wrong, as setMapZoom(integer) does not change zoom view at all

While I now see a minimum value announced (is there also a maximum?) the zoom value still doesn't change:

image

Also the area displayed in mapper does not change its zoom levels during this at all.

@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Mar 10, 2023

The default zoom value seems not very enticing, and short of implementing any smart calculation, I implore you to reconsider this:

I foresee setting zoom per-area being a massive amount of pain since it'll reset between areas on the first time and so on.

If you enter a new area for the first time that does not have a zoom setting yet, start with the previous area's one.

Those values are the ones that are already in place, the mapper was starting off the session at 20.0 and 3.0 was the existing limit - therefore they are the least surprising values to use going forward. This PR currently means that if you go to a newly created area (or to one for the first time since you use Mudlet with this PR in place) you will get the default 20.0 zoom - because each area is now handled separately.

Whilst I suppose it might be possible to copy over the zoom from the last area previous viewed I think that that will required extra code and make this PR larger. Would it be reasonable to defer that to a separate PR?

@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Mar 10, 2023

There seems to be something wrong, as setMapZoom(integer) does not change zoom view at all

While I now see a minimum value announced (is there also a maximum?) the zoom value still doesn't change:

{image omitted}

Also the area displayed in mapper does not change its zoom levels during this at all.

There is no maximum limit (well other than an inherent int overflow!)...

Let me check that - I thought it did repaint the map in the new zoom, but maybe I left out an update(); for the case when the area being viewed is the one that the zoom is set for; as it is now possible to set the zoom on a complete different area that is NOT being viewed and that shouldn't prompt a redraw...

@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Mar 10, 2023

Not redrawing map after using single argument setMapZoom(...): Confirmed 🐞 .

Strange thing is that the Lua updateMap() is called (in all cases where the setting is successful yet it is proving ineffectual) furthermore that should only be called in the single argument case or when the area being viewed IS the area given in the two argument case...

I need to dig deeper.

@Kebap
Copy link
Copy Markdown
Contributor

Kebap commented Mar 10, 2023

Please convert to draft until new tests are possible

Also revise some error/warning texts.

Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Mar 10, 2023

Please convert to draft until new tests are possible

Not really necessary - I think it is fixed-up now. Both the messages and the single argument setting case.

@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Mar 11, 2023

📚 Documentation pending in Area 51:

@SlySven SlySven removed the needs documentation This pull request changes things the players would use/see and thus needs an update in the manual label Mar 11, 2023
@vadi2 vadi2 self-requested a review March 12, 2023 07:37
SlySven added a commit that referenced this pull request Mar 15, 2023
#### Brief overview of PR changes/additions
In particular try and use ID in a uniform manner when referring to an
integer number that uniquely identifies an instance of something like a
room or an area in the map.

#### Motivation for adding to Mudlet
It became clear that there are a significant number of duplicate strings
involving ID and it was possible to reduce the number of duplicate
`qsl(`...`)` - which are our wrapper of `QStringLiteral` - by replacing
each with a QString constant initialised at compile time. This is a good
thing as it is bad to have multiple copies of the same string as one of
these as each one is stored separately in the (Read-Only) data part of
the executable.

#### Other info (issues closed, discussion etc)
This should close #2605.

This was prompted by @Kebap 's comments here:
#6615 (comment)

Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
SlySven added 2 commits March 15, 2023 23:29
Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
@SlySven
Copy link
Copy Markdown
Member Author

SlySven commented Mar 16, 2023

📚 Documentation reordered/improved.

@SlySven SlySven dismissed Kebap’s stale review March 16, 2023 14:51

Work has been done and approval given by project leader.

@SlySven SlySven merged commit c6e3aa7 into Mudlet:development Mar 16, 2023
@SlySven SlySven deleted the Improve_rememberMapperZoomAmountBetweenSessions_simplified branch March 16, 2023 15:00
vadi2 added a commit that referenced this pull request Mar 18, 2023
vadi2 added a commit that referenced this pull request Mar 18, 2023
vadi2 added a commit that referenced this pull request Mar 18, 2023
vadi2 added a commit that referenced this pull request Mar 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bounty-50 see https://wiki.mudlet.org/w/Bounty_Process

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: Mudlet Remember mapper zoom amount between sessions.

3 participants