(release 30)enhancement: move TArea::rooms to QSet (updated)#308
Conversation
In situations when we check whether a room in an area both for internal
purposes and when rooms on a mapper is selected, using QSet instead of a
QList is faster in performance for large numbers of entries in set.
As it reworks the mapper code it also fixes issue where the multi-room
selection widget overwrites map info display - the latter is re-sized and
re-positioned (and regains a semi-transparent background which helped to
show this working during debugging!) The former is now: dynamically
resized to only take up enough vertical space to show the selected rooms;
also displays the associate room names if there are any, expanding the
widget as required; sorts the display either by room name or number and in
either direction.
The mouse wheel handler is modified so that using the scroll wheel ONLY
scrolls the list within the widget - previously (by default) once the end
in either direction was hit the related events would be passed up the
widget chain where it would otherwise invoke the 2D mapper's zoom in/out
code.
In modifying the zoom in/out code I have replaced the (obsoleted in Qt5.x)
QWheelEvent::delta() method to use the QWheelEvent::angleDelta() method,
using only the Y-component the latter provides. If the Control modifier is
active the zoom value is modified by an extra x10 factor which is useful
when working with large maps as otherwise the zooming rate is "slow" at
high values - ideally the control should be logarithmic or exponential or
some other "non-linear" algorithm to work more uniformly over the range of
practical use cases.
The code to paint the map info text has been revised also to use the
mMapInfoRect which was being defined but NOT used.
The info text now reports whether the room name is for the player room
{set via the Lua command centerview(roomId)} or is one that is selected
by mouse dragging - and if more than one room is selected by that indicates
the count of rooms in the selection. In the case of multiple rooms being
selected the room that single room context menu operations will act upon
is highlighted by the same style of yellow target used to show the custom
exit line destination but is drawn in a different point in the code so that
it is drawn over the rooms.
Because of the change to the way that multiple rooms are selected routines
that use that information had to be revised - in doing so it was possible
to improve the usability/operation of:
T2DMap::slot_movePosition()
T2DMap::slot_setCharacter()
T2DMap::slot_spread()
T2DMap::slot_shrink()
T2DMap::slot_lockRoom():
T2DMap::slot_unlockRoom():
This method, also resurrected here to the 2D mapper context menu, as it is
also affected by the changes:
T2DMap::slot_setPlayerLocation()
There was a slot_setPlayerLocation code that set a global lua variable
mRoomSet and moved the player to that room Id (introduced in
commit-c25faf4e 2012-05-04 07:44:36 by Heiko) but the corresponding 2D
Mapper context menu item that called it was commented out and thus removed
from the menu in commit-93f65962 2012-12-29 01:16:28 also by Heiko without
any explaination. Since that has not been used since then I have replaced
it with a new Event: sysManualLocationSetEvent with a single numeric value
which is the new (valid) room Id number - user scripts can capture this
event if they want to know that the user has manually re-positioned the
current player room in the 2D mapper.
In passing:
* Fixed Text font changing between docked and un-docked forms of the
built-in map widget (when not incorporated into a console) - as it was
not previously explicitly set it assumed the Application one whilst
docked but the Qt System one when a free floating widget - and the two
do not have to be the same. This fixes:
https://bugs.launchpad.net/mudlet/+bug/1432841 .
* Starts to fix https://bugs.launchpad.net/mudlet/+bug/1376511 by changing
from use of obsolete QWheelEvent::delta() to QWheelEvent::angleDelta() in
T2DMap::wheelEvent(...); will need duplicating in
TTextEdit::wheelEvent(...) and GLWidget::wheelEvent(...) .
* Adds the profile name to the Mapper dockable widget so that it's
parentage can be determined when multiple profiles are active.
Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
Found during testing with humongous map files that the "Loading" & "Saving" messages did not show up - turns out a qApp->processingEvents() call is needed... Whilst fixing that in relevant places on that the Profile Preferences dialog also applied QStringLiteral(...)/ tr(...) wrappers as needed. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
…asis It is possible to copy a saved map from one profile to another - even if that other profile is in use. However this will lose the details of where the (other) player is located in THAT profile. This commit aims to correct that by sneaking a look at where the other player is and storing that in the file that is both copied for this profile before it is copied and to the file that is copied over. This data was stored in (int) TMap::mRoomId which has now become a: (QHash<QString, int>) TMap::mRoomIdHash with the profile name as the key and the Value being the equivalent of mRoomId in the new code. This has required an increment in the Map file format version from 17 to 18. The default - that will be used unless the developer or tester changes it in the Profile Preferences dialog remains at 16. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
As well as fixing the Area ownership of rooms (which has been an issue that crops up from past buggy TArea code) this also clears out custom exit line junk - including details for lines where the key was an empty string, those arose during previous buggy code that allow exit lines to be drawn without specifying which exit they were for. The checks also removes any stub exits that are present on rooms that have an actual exit in the same (normal exit) direction. The current code prevents the creation of such things but it did not in the past (I have encountered it - especially when the real exit is a "circular" one that goes to the SAME room as it leaves from!) BTW Such a exit type, although initially seeming to be pointless is a feature of some MUDs and the normal exit drawing code for the 2D map does not currently show them (future thing to cover?) though a custom exit line can be drawn that shows the "circular-ness" of the exit! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
Refactor the code that identifies where player is in other profiles, saves
it in current profile's map, copies it to other profiles and tells them
to load it in.
The code to copy to another map as was only permitted one other profile to
be done at a time - this makes it difficult to ensure that all the profiles
get the same data for all the other affected maps. The profile selection
part of "Profile Preferences" "Mapper" has been changed to be something
that allows all the destination targets (other profiles) to be selected,
excluding the current profile (as that ALWAYS gets the new map - it is
intrinsic to the copying process). Only when one (or more) other profiles
are selected does the "Copy" button become enabled and then all active
profiles are checked to see if they are included, their player room is
noted as before and all the details are written to the current profile's
new map. After copying (with some checks for success) the map to ALL
profiles a signal is sent to all active profiles (with a list of profiles
to respond) that causes the listed ones to reload a new map from their
home map directory. (Extensive, formatted!) tooltips have been added to
the two controls concerned in the profile preferences.
Slots and signals are used (via the singleton class mudlet) to try and
accommodate future situations when Mudlet becomes properly multi-threaded
and each profile runs in a different thread - getting the current room
from each profile may become more tricky THEN.
Also a bug where the currently selected (in the same dialog) map save file
format was not being used when the current profile's map has been changed
has been fixed in this commit.
===========================================================================
To support the inclusion of other profile player location data in the map
file MAP FILE FORMAT 18 (or greater) MUST BE CHOOSEN BEFORE THE MAP IS
COPIED.
===========================================================================
If this is not done then the map will not contain the data and then the
other profiles' player will be reset to the location of the player in the
currently active profile - as would happen for the old code (prior to
commit entitled "Enhance: store current player location in map file on a
per profile basis"). One bonus of this code is that only one copy of the
map to be copied over is made in the current profile's directory and all
the copies will have the same date-time stamp name between the profiles,
instead of a sequence of differently timed files as the file is copied one
profile at a time that code prior to this series of commits will produce!
Some items in the profile_preferences.ui have been renamed to clarify their
type or purpose or change thereof:
QGroupBox:
* groupBox_3 ==> groupBox_mapFiles
QLabel:
* label_9 ==> label_saveMap
* label_10 ==> label_loadMap
* label_12 ==> label_copyMap
* map_file_action ==> label_mapFileActionResult
QPushButtons:
* copy_map_profile ==> pushButton_copyMap
* load_map_button ==> pushButton_loadMap
* save_map_button ==> pushButton_saveMap
Changes:
* (QComboBox) mapper_profiles_combobox
==> (QPushButton) pushButton_chooseProfiles
Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
Recent code changes uses longer messages in the "label_mapFileActionResult" in the "Mapper" tab of the "Profile Preferences" dialog, it was however only occupying one of the three columns in the QGridLayout in the part of the dialogue where it was place - so that when a long message is displayed it caused all the surrounding widgets in the other columns in the same layout to be pushed out of the way. This tweak makes it occupy ALL three columns so this no longer occurs! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
|
😕 Humm, that there Travis C.I. "1 failing check" is the Linux, gcc, cmake build objecting to the use of |
|
Well, it is the modern equivalent, it's just too modern to be available by default in the version of gcc that the Travis build is using (4.6). It would probably be fine if you had it compile with -std=c++0x or -std=gnu++0x, but you'd want to make sure it didn't cause any problems with linking against shared libraries compiled against the old ABI and so on. |
|
Actually the GCC gets updated to 4.7.3 in the before_install stage IIRC - but what is really weird is that the same construct ( Ah, I have raised a launchpad bug 1571439 on this as someone needs to look at this IMHO. |
One build version on Travis C.I. (Linux/Cmake/GCC) did not seem to like the use of nullptr - so I have reverted to the ubiquitous numeric 0 instead. This is because it is a C++11 feature and there is no requirement to use C++11 specified in the CMake project file. In passing also noted that a used file ./src/irc/ircglobal.h is used but not listed in the qmake ./src/src.pro project file - so it does not show up in the Qt Creator IDE - and it contains the version number of the LibIrcClient-Qt library that we incorporate and use. So, I've added it to the project file as well. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
|
I did see that gcc 4.7 was specified in the mudlet repository, but the Travis build logs seemed to indicate that 4.6 was actually being used. Not sure what would cause that disparity, or whether I just read something wrong. But yes, the basic issue is that nullptr is a c++11 feature, and it's probably a bit early to expect it to be universally supported. There's probably a #define that would let you use an #ifdef to use nullptr if available and NULL otherwise. |
|
Are you sure about that GCC 4.6 - I deliberately included something that reports the compiler version being used just before starting the actual build - and as I say, although 4.6 is the preloaded default we do upgrade it to 4.7 in the |
Although we have the provision of a default area (with Id -1) we have not previously actually made sure it exists after loading (or clearing) prior to loading in a map - which causes all sorts of error messages when a map WITHOUT that area is loaded. This will possible need checking with a planned revision to code to allow user loading of XML map files in the near future. Also: * moved all instance in TMap class of mpHost->postMessage( QString ) to own postMessage( QString ) implimentation * removed unused QDataStream reference argument in: * (void) TRoomDB::restoreSingleArea( QDataStream &, int, TArea * ) * (void) TRoomDB::restoreSingleRoom( QDataStream &, int, TRoom * ) * removed unused Globals in XMLimport.cpp: * int maxAreas * QMap<int,int> areaMap Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
|
Oops - we didn't check for (or create if necessary) the "Default Area" with Id of -1 after the map data was cleared or a new map loaded. Now fixed that. |
|
Humm, seems to have a bug which is causing doors to be removed from normal direction exits even though there is an exit or a stub (will be checking to see if it is related to the code that prevents a stub being on the same exit direction as a real exit, when in that case the stub is automatically removed...) #301 will have the same bug. |
Also refactored TLuaInterpreter::setDoor(...) & getDoor(...) to current error handling standards - including checks for validity. The name of the normal exit directions always were specific but are now explicitly checked for - this goes in step with the recently added auditing code that removes doors on exits that do not exist (even as a normal direction "stub" exit). The setDoor(...) function returns true if a change was made to the room's doors and false if the command was ineffective. It now also returns a secondary error message if a nil is returned to explain what the problem was...! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
src/TRoom.cpp
Outdated
| if( ! exitStubs.contains( dirCode ) ) { | ||
| // Add the stub | ||
| exitStubs.append( dirCode ); | ||
| exitStubsPool.remove( dirCode ); // Remove the stub in this direction from check pool as we have handled it |
There was a problem hiding this comment.
Blast it! I think, perhaps this line need to be outside this if(...).
Update: Well yes, it does, as we will be adding a stub.
If there is already a stub in that direction then that is a "double fault" or corner-case of {invalid exit Id} + {non-(-1) exit AND a stub in same direction} but in the scheme of things that is probably not worth reporting.
Needed to move a line:
exitStubsPool.remove( dirCode );
outside of an:
if( ! exitStubs.contains( dirCode ) ) {...}
test in (void)TRoom::auditExit(...) so that an extra warning message will
may be avoided in a potential corner-case - though I'm not sure I can
express when it might occur!
Also:
* Extend info/warnings about more elements of an invalid exit Id; in
reviewing what is preserved in the room user data in the event of
encountering an invalid exit id (<1 but not the "no exit" -1 case) we can
preserve information about whether the exit was locked and had an exit
weight easily (but not a custom exit line that would be much harder) in
the room user data - with information to the user about all three.
* prevent use of TRoom::setExitLock( int, bool ) from causing duplicates
in the (QList<int>) TRoom::exitLocks member - otherwise it caused
that correctable issue to occur which adds to the volume of audit
messages.
* Fix a recently introduce bug in the Lua setDoor(...) command that would
fail to set a door on a specialExit as the code to validate the command
forgot the lock indication prefix of '0' or '1' in the exit command.
Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
I had got the logic wrong in identifying whether an exit was a normal or a special exit - so the validation did not work correctly as to whether a door could be allowed to be set/reset in a room. Also: added a call to refresh the 2D mapper display if a change WAS successfully made to the doors for a room... Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
The recently introduced code that "improved" the saving/sharing of a map to other profiles had a superfluous signal/slot usage: signal: (void) dlgProfilePrerence::signal_otherProfilesToReloadMaps( QList<QString> ) connected to slot: (void) mudlet::slot_requestProfilesToReloadMaps( QList<QString> ); When it is possible to call the replacement NON-slot: (void) mudlet::requestProfilesToReloadMaps( QList<QString> ) directly from the dlgProfilePreferences::copyMap() method without too much risk of problems as Mudlet is current constructed. I spotted this whilst investigating another, subsequently redirected coding task (in following commit). Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
As per this message in the Forum: http://forums.mudlet.org/viewtopic.php?f=13&t=4857&start=20#p24479 now that a recent commit correctly ensures that a TArea for the default area Id of -1 IS instantiated - they have noticed that it shows up in the area control widget (a non-editable QComboBox) whereas it had not in the past. However the original poster has a need to HIDE that area from casual inspection by the user of their package. As the "fix" of that recent commit does affect the application behaviour this commit provides both script-able and GUI means to select whether to show the Default area in that widget. The setting DOES not persist between settings (it would not be easy to save in a profile specific way without introducing a new setting to the game save format - which is NOT currently versioned {unlike the Map file format} and it is not really a map setting). Also, it cannot be applied until a map display (mapper) is created - so the option is hidden on the "Profile Preferences" => "Special Options" tab and the lua command "setDefaultAreaVisible(bool)" will return false until there is one; after that the checkbox control is shown on the dialog and will return true from the lua command. On profile loading/mapper creation the Default Area WILL be shown in the widget - corresponding to a true value to the lua command. Using the lua command will immediately refresh the list of Areas in that widget if the setting is changed. Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
As discussed in http://forums.mudlet.org/viewtopic.php?f=13&t=4818#p24498 this commit improves the way the centre of the view is selected when the area selection widget is used to (temporarily) show a view of a different area: * A) if the selected area has the same z-coordinate as the current view in the (2D) mapper then the mean coordinate of all the rooms on THAT level is calculated and then the room nearest to that is chosen to be at the centre of the view in the selected area. * B) if the selected area does not have any rooms on the same level then the level with the MOST rooms (and the lowest z coordinate if there are ties) is chosen and the room closest to the mean again selected. * C) if there are NOT rooms in the area then the view is centred on the origin. * D) if (after using the control more than once OR even if NOT) the original area is selected then the view snaps back to the current player room (this can be used to recenter on that if the scroll buttons have been used to offset the view!) The center of view position is made from code within the 2D mapper - but there is no need to do the same for the 3D one - instead the area ID and position is passed up to the TMap class instance which forwards the details to the 3D mapper. The bottom line is that (unless it is an empty area) a reasonable choice of room is ALWAYS displayed in the centre of the map when the area is changed manually (and the 2 and 3D maps will be centred on the same room). Code associated with loading maps has been refactored in an attempt to ensure that the area selection widget is set to the correct value before the first use by the user - there was four places where the map file was being loaded (although the one in the Host class constructor seems unnecessary - and problematic to handle as the Host class is instantiated before the mapper widget is created!) I *think* I have got it straight now but some testing in the map down load from server case may need a check to see that I have not broken anything. Also: * have tweaked the map information display to change the text format to emphasise when it reflects details of a selection (the text turns a bit orange and is written BOLD) or if the player room (which is what is referred to if NO rooms are selected) is in this area (the data is written in BOLD) or is not in the current area shown (the data is written in ITALICS and not bold). Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
This detail was missing and was confusing when centerview(roomId) was used. Also, handle the case when the displayed map IS the default area (through using centerview(...) when the room is in that area AND the area widget has been set to hide that area name OR it has just been told not to! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
As the amount of messages produced by the new/improve map auditing/clean-up code can be large for old map files this commit causes them to be sent to a profile specific file that is already opened by the Host class but has not been used for some time. An option (a check-box) on the "map" tab of the "profile preferences" dialog controls whether the equivalent information is also shown on the profile's main console as in the past. If the option (a global one) which is saved between sessions/runs is NOT enabled then an advisory is sent to the console advising the user to review the file contents if a "significant" issue was detected. If it is enabled a similar message advising that the information has also been saved. In either case, as the file is appended to, and not rewritten each time, the message includes details of the first line of the report so that it can be located in the file. One difference between the on-screen and the file versions of the information is that the former puts up the issues as they are detected whereas the latter groups the information by subject, first the general overall issues, then the area ones, in order of the areas' id numbers and then the room ones, in room order. Following earlier discussions in these Pull Request I have attempted to edit all uses of the word "Id" in user visible places to be "id" instead. This threw up some other messages with issues in several files that I have tweaked here as well! Signed-off-by: Stephen Lyons <slysven@virginmedia.com>
I've finally ported the code across from #301 to the release_30 branch. I think I got everything cloned (apart from the differences) correctly. I squashed a couple of bug-fix commits into the prior commits that caused the bugs that they fixed (so this branch has a few less commits in it). Whilst testing I became aware of a minor cosmetic bug in the form for the map save/load/copy actions which the last commit fixes that was also appended to the 301 branch.
I'd suggest given this one a good going-over/testing to see if there is anything that I haven't caught - with the audit code you may get quite a few (fixed) items when loading in an existing map - hopefully the presented information will be enough to work out what was found and then done to fix it. 😀