mirror of
https://github.com/huderlem/porymap.git
synced 2026-09-30 03:46:35 -05:00
Merge branch 'dev' into heal-locations
This commit is contained in:
21
CHANGELOG.md
21
CHANGELOG.md
@@ -8,20 +8,21 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
|
||||
|
||||
## [Unreleased]
|
||||
### Added
|
||||
- Add the ability to edit layouts with no corresponding map.
|
||||
- Add ``Duplicate Map`` / ``Duplicate Layout`` options, accessible by right-clicking a map or layout in the map list.
|
||||
- Redesigned the Connections tab, adding a number of new features including the option to open or display diving maps and a list UI for easier edit access.
|
||||
- Redesigned the map list, adding new features including opening/editing layouts with no associated map, duplicating maps or layouts (accessible via right-click), editing the names of map groups, rearranging maps and map groups, and hiding empty folders.
|
||||
- Add a drop-down for changing the layout of the currently opened map.
|
||||
- Redesigned the Connections tab, adding new features including the option to open or display diving maps and a list UI for easier edit access.
|
||||
- Add a `Close Project` option
|
||||
- Add charts to the `Wild Pokémon` tab that show species and level distributions.
|
||||
- Add a search button to the `Wild Pokémon` tab that shows the encounter data for a species across all maps.
|
||||
- Add charts to the `Wild Pokémon` tab that show species and level distributions for the current map.
|
||||
- Add options for customizing the map grid under `View -> Grid Settings`.
|
||||
- Add an option to display a dividing line between tilesets in the Tileset Editor.
|
||||
- An alert will be displayed when attempting to open a seemingly invalid project.
|
||||
- Add support for defining project values with `enum` where `#define` was expected.
|
||||
- Add button to enable editing map groups including renaming groups and rearranging the maps within them.
|
||||
- Add buttons to hide and show empty folders in each map tree view.
|
||||
- Add a setting to specify the tile values to use for the unused metatile layer.
|
||||
|
||||
### Changed
|
||||
- `Change Dimensions` now has an interactive resizing rectangle.
|
||||
- Redesigned the new map dialog, including better error checking and a collapsible section for header data.
|
||||
- Map groups and ``MAPSEC`` names specified when creating a new map will be added automatically if they don't already exist.
|
||||
- Edits to map connections now have Undo/Redo and can be viewed in exported timelapses.
|
||||
@@ -32,10 +33,12 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
|
||||
- It's now possible to cancel quitting if there are unsaved changes in sub-windows.
|
||||
- The triple-layer metatiles setting can now be set automatically using a project constant.
|
||||
- `Export Map Stitch Image` now shows a preview of the full image, not just the current map.
|
||||
- Maps and layouts were internally separated.
|
||||
- `Custom Attributes` tables now display numbers using spin boxes. The `type` column was removed, because `value`'s type is now obvious.
|
||||
- Unrecognized map names in Event or Connections data will no longer be overwritten.
|
||||
- Reduced diff noise when saving maps.
|
||||
- Map names and ``MAP_NAME`` constants are no longer required to match.
|
||||
- Porymap will no longer overwrite ``include/constants/map_groups.h`` or ``include/constants/layouts.h``.
|
||||
- Primary/secondary metatile images are now kept on separate rows, rather than blending together if the primary size is not divisible by 8.
|
||||
|
||||
### Fixed
|
||||
- Fix `Add Region Map...` not updating the region map settings file.
|
||||
@@ -49,7 +52,8 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
|
||||
- Fix the `Edit History` window not raising to the front when reactivated.
|
||||
- New maps are now always inserted in map dropdowns at the correct position, rather than at the bottom of the list until the project is reloaded.
|
||||
- Fix invalid species names clearing from wild pokémon data when revisited.
|
||||
- Fix editing wild pokémon data not marking the map as edited.
|
||||
- Fix editing wild pokémon data not marking the map as unsaved.
|
||||
- Fix editing an event's `Custom Attributes` not marking the map as unsaved.
|
||||
- Fix changes to map connections not marking connected maps as unsaved.
|
||||
- Fix numerous issues related to connecting a map to itself.
|
||||
- Fix incorrect map connections getting selected when opening a map by double-clicking a map connection.
|
||||
@@ -72,8 +76,11 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
|
||||
- Fix exported tile images containing garbage pixels after the end of the tiles.
|
||||
- Fix fully transparent pixels rendering with the incorrect color.
|
||||
- Fix the values for some config fields shuffling their order every save.
|
||||
- Fix `key`s in `Custom Attributes` disappearing if given an empty name or the name of an existing field.
|
||||
- Fix some problems with tileset detection when importing maps from AdvanceMap.
|
||||
- Fix certain input fields allowing invalid identifiers, like names starting with numbers.
|
||||
- Fix crash in the Shortcuts Editor when applying changes after closing certain windows.
|
||||
- Fix `Display Metatile Usage Counts` sometimes changing the counts after repeated use.
|
||||
|
||||
## [5.4.1] - 2024-03-21
|
||||
### Fixed
|
||||
|
||||
@@ -153,9 +153,9 @@ Callbacks
|
||||
|
||||
.. js:function:: onMapOpened(mapName)
|
||||
|
||||
Called when a map is opened.
|
||||
Called when a map or layout is opened.
|
||||
|
||||
:param mapName: the name of the opened map
|
||||
:param mapName: the name of the opened map or layout
|
||||
:type mapName: string
|
||||
|
||||
.. js:function:: onBlockChanged(x, y, prevBlock, newBlock)
|
||||
@@ -1995,7 +1995,28 @@ All utility functions are callable via the global ``utility`` object.
|
||||
|
||||
Gets the list of map names.
|
||||
|
||||
:returns: the list of map names
|
||||
:returns: the list of map names (e.g. `PetalburgCity`)
|
||||
:rtype: array
|
||||
|
||||
.. js:function:: utility.getMapConstants()
|
||||
|
||||
Gets the list of map IDs (e.g. `MAP_PETALBURG_CITY`)
|
||||
|
||||
:returns: the list of map IDs
|
||||
:rtype: array
|
||||
|
||||
.. js:function:: utility.getLayoutNames()
|
||||
|
||||
Gets the list of layout names.
|
||||
|
||||
:returns: the list of layout names (e.g. `PetalburgCity_Layout`)
|
||||
:rtype: array
|
||||
|
||||
.. js:function:: utility.getLayoutConstants()
|
||||
|
||||
Gets the list of layout IDs (e.g. `LAYOUT_PETALBURG_CITY`)
|
||||
|
||||
:returns: the list of layout IDs
|
||||
:rtype: array
|
||||
|
||||
.. js:function:: utility.getTilesetNames()
|
||||
|
||||
@@ -1484,7 +1484,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="mapView_ObjectInfo">
|
||||
<widget class="QWidget" name="mapView_EventInfo">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>1</number>
|
||||
@@ -1499,7 +1499,7 @@
|
||||
<number>1</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QFrame" name="frame_Objects">
|
||||
<widget class="QFrame" name="frame_Events">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@@ -1582,7 +1582,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="toolButton_deleteObject">
|
||||
<widget class="QToolButton" name="toolButton_deleteEvent">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<widget class="QLabel" name="label_MapSelection">
|
||||
<property name="text">
|
||||
<string>Map</string>
|
||||
</property>
|
||||
|
||||
276
forms/resizelayoutpopup.ui
Normal file
276
forms/resizelayoutpopup.ui
Normal file
@@ -0,0 +1,276 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ResizeLayoutPopup</class>
|
||||
<widget class="QDialog" name="ResizeLayoutPopup">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>598</width>
|
||||
<height>378</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Resize Layout</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>8</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset</set>
|
||||
</property>
|
||||
<property name="centerButtons">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QGraphicsView" name="graphicsView"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Width</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="NoScrollSpinBox" name="spinBox_width">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Height</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="NoScrollSpinBox" name="spinBox_height">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QFrame" name="frame_border">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Border Width</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="NoScrollSpinBox" name="spinBox_borderWidth">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Border Height</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="NoScrollSpinBox" name="spinBox_borderHeight">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>NoScrollSpinBox</class>
|
||||
<extends>QSpinBox</extends>
|
||||
<header>noscrollspinbox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>ResizeLayoutPopup</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ResizeLayoutPopup</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <QUndoCommand>
|
||||
#include <QList>
|
||||
#include <QPointer>
|
||||
#include <QMargins>
|
||||
|
||||
class Map;
|
||||
class Layout;
|
||||
@@ -203,7 +204,7 @@ private:
|
||||
/// Implements a command to commit a map or border resize action.
|
||||
class ResizeLayout : public QUndoCommand {
|
||||
public:
|
||||
ResizeLayout(Layout *layout, QSize oldLayoutDimensions, QSize newLayoutDimensions,
|
||||
ResizeLayout(Layout *layout, QSize oldLayoutDimensions, QMargins newLayoutMargins,
|
||||
const Blockdata &oldMetatiles, const Blockdata &newMetatiles,
|
||||
QSize oldBorderDimensions, QSize newBorderDimensions,
|
||||
const Blockdata &oldBorder, const Blockdata &newBorder,
|
||||
@@ -220,8 +221,7 @@ private:
|
||||
|
||||
int oldLayoutWidth;
|
||||
int oldLayoutHeight;
|
||||
int newLayoutWidth;
|
||||
int newLayoutHeight;
|
||||
QMargins newLayoutMargins;
|
||||
|
||||
int oldBorderWidth;
|
||||
int oldBorderHeight;
|
||||
|
||||
@@ -103,6 +103,7 @@ public:
|
||||
void setBlock(int x, int y, Block block, bool enableScriptCallback = false);
|
||||
void setBlockdata(Blockdata blockdata, bool enableScriptCallback = false);
|
||||
|
||||
void adjustDimensions(QMargins margins, bool setNewBlockdata = true);
|
||||
void setDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false);
|
||||
void setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false);
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
Metatile* metatileAt(unsigned int i) const { return m_metatiles.at(i); }
|
||||
|
||||
void clearMetatiles();
|
||||
void resizeMetatiles(unsigned int newNumMetatiles);
|
||||
void resizeMetatiles(int newNumMetatiles);
|
||||
int numMetatiles() const { return m_metatiles.length(); }
|
||||
|
||||
private:
|
||||
|
||||
@@ -108,14 +108,15 @@ public:
|
||||
void toggleBorderVisibility(bool visible, bool enableScriptCallback = true);
|
||||
void updateCustomMapAttributes();
|
||||
|
||||
DraggablePixmapItem *addMapEvent(Event *event);
|
||||
DraggablePixmapItem *addEventPixmapItem(Event *event);
|
||||
void removeEventPixmapItem(Event *event);
|
||||
bool eventLimitReached(Map *, Event::Type);
|
||||
void selectMapEvent(DraggablePixmapItem *object, bool toggle = false);
|
||||
void selectMapEvent(DraggablePixmapItem *item, bool toggle = false);
|
||||
DraggablePixmapItem *addNewEvent(Event::Type type);
|
||||
void updateSelectedEvents();
|
||||
void duplicateSelectedEvents();
|
||||
void redrawObject(DraggablePixmapItem *item);
|
||||
QList<DraggablePixmapItem *> getObjects();
|
||||
void redrawEventPixmapItem(DraggablePixmapItem *item);
|
||||
QList<DraggablePixmapItem *> getEventPixmapItems();
|
||||
|
||||
void updateCursorRectPos(int x, int y);
|
||||
void setCursorRectVisible(bool visible);
|
||||
@@ -155,7 +156,7 @@ public:
|
||||
|
||||
enum class EditAction { None, Paint, Select, Fill, Shift, Pick, Move };
|
||||
EditAction mapEditAction = EditAction::Paint;
|
||||
EditAction objectEditAction = EditAction::Select;
|
||||
EditAction eventEditAction = EditAction::Select;
|
||||
|
||||
enum class EditMode { None, Disabled, Metatiles, Collision, Header, Events, Connections, Encounters };
|
||||
EditMode editMode = EditMode::None;
|
||||
@@ -169,7 +170,7 @@ public:
|
||||
void setEditingMetatiles();
|
||||
void setEditingCollision();
|
||||
void setEditingHeader();
|
||||
void setEditingObjects();
|
||||
void setEditingEvents();
|
||||
void setEditingConnections();
|
||||
void setEditingEncounters();
|
||||
|
||||
@@ -179,7 +180,9 @@ public:
|
||||
qreal collisionOpacity = 0.5;
|
||||
static QList<QList<const QImage*>> collisionIcons;
|
||||
|
||||
void objectsView_onMousePress(QMouseEvent *event);
|
||||
int eventShiftActionId = 0;
|
||||
|
||||
void eventsView_onMousePress(QMouseEvent *event);
|
||||
|
||||
int getBorderDrawDistance(int dimension);
|
||||
|
||||
@@ -253,7 +256,7 @@ private slots:
|
||||
void onWheelZoom(int);
|
||||
|
||||
signals:
|
||||
void objectsChanged();
|
||||
void eventsChanged();
|
||||
void openConnectedMap(MapConnection*);
|
||||
void wildMonTableOpened(EncounterTableModel*);
|
||||
void wildMonTableClosed();
|
||||
|
||||
@@ -96,6 +96,7 @@ namespace fex
|
||||
case Type::kValuePair:
|
||||
return pair_.first + " = " + pair_.second->ToString() + "\n";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static ArrayValue Empty()
|
||||
|
||||
@@ -221,8 +221,8 @@ private slots:
|
||||
void addNewEvent(Event::Type type);
|
||||
void tryAddEventTab(QWidget * tab);
|
||||
void displayEventTabs();
|
||||
void updateSelectedObjects();
|
||||
void updateObjects();
|
||||
void updateSelectedEvents();
|
||||
void updateEvents();
|
||||
|
||||
void on_toolButton_Paint_clicked();
|
||||
void on_toolButton_Select_clicked();
|
||||
@@ -325,6 +325,7 @@ private:
|
||||
|
||||
QAction *undoAction = nullptr;
|
||||
QAction *redoAction = nullptr;
|
||||
QPointer<QUndoView> undoView = nullptr;
|
||||
|
||||
QAction *copyAction = nullptr;
|
||||
QAction *pasteAction = nullptr;
|
||||
@@ -353,6 +354,7 @@ private:
|
||||
bool setProjectUI();
|
||||
void clearProjectUI();
|
||||
|
||||
void openEditHistory();
|
||||
void openNewMapDialog();
|
||||
void openDuplicateMapDialog(const QString &mapName);
|
||||
NewLayoutDialog* createNewLayoutDialog(const Layout *layoutToCopy = nullptr);
|
||||
@@ -380,7 +382,7 @@ private:
|
||||
|
||||
void updateMapList();
|
||||
void openMapListItem(const QModelIndex &index);
|
||||
void saveMapListTab(int index);
|
||||
void onMapListTabChanged(int index);
|
||||
|
||||
void displayMapProperties();
|
||||
void checkToolButtons();
|
||||
|
||||
@@ -42,6 +42,9 @@ public:
|
||||
Q_INVOKABLE QList<float> getMetatileLayerOpacity();
|
||||
Q_INVOKABLE void setMetatileLayerOpacity(QList<float> order);
|
||||
Q_INVOKABLE QList<QString> getMapNames();
|
||||
Q_INVOKABLE QList<QString> getMapConstants();
|
||||
Q_INVOKABLE QList<QString> getLayoutNames();
|
||||
Q_INVOKABLE QList<QString> getLayoutConstants();
|
||||
Q_INVOKABLE QList<QString> getTilesetNames();
|
||||
Q_INVOKABLE QList<QString> getPrimaryTilesetNames();
|
||||
Q_INVOKABLE QList<QString> getSecondaryTilesetNames();
|
||||
|
||||
@@ -30,7 +30,7 @@ public:
|
||||
|
||||
WildMonInfo encounterData() const { return m_monInfo; }
|
||||
EncounterField encounterField() const { return m_encounterField; }
|
||||
QList<double> percentages() const { return m_slotPercentages; }
|
||||
QVector<double> percentages() const { return m_slotPercentages; }
|
||||
|
||||
private:
|
||||
int m_numRows = 0;
|
||||
@@ -38,7 +38,7 @@ private:
|
||||
WildMonInfo m_monInfo;
|
||||
EncounterField m_encounterField;
|
||||
QMap<int,QString> m_groupNames;
|
||||
QList<double> m_slotPercentages;
|
||||
QVector<double> m_slotPercentages;
|
||||
|
||||
signals:
|
||||
void edited();
|
||||
|
||||
@@ -3,15 +3,28 @@
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
class FilterChildrenProxyModel : public QSortFilterProxyModel
|
||||
class NumericSortProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FilterChildrenProxyModel(QObject *parent = nullptr);
|
||||
void setHideEmpty(bool hidden) { this->hideEmpty = hidden; }
|
||||
explicit NumericSortProxyModel(QObject *parent = nullptr) : QSortFilterProxyModel(parent) {};
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow(int source_row, const QModelIndex & source_parent) const;
|
||||
virtual bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override;
|
||||
};
|
||||
|
||||
class FilterChildrenProxyModel : public NumericSortProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FilterChildrenProxyModel(QObject *parent = nullptr) : NumericSortProxyModel(parent) {};
|
||||
void setHideEmpty(bool hidden) { this->hideEmpty = hidden; }
|
||||
|
||||
protected:
|
||||
virtual bool filterAcceptsRow(int source_row, const QModelIndex & source_parent) const override;
|
||||
|
||||
private:
|
||||
bool hideEmpty = false;
|
||||
};
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
|
||||
#include <QWidget>
|
||||
#include <QPointer>
|
||||
#include "mapheader.h"
|
||||
|
||||
class Project;
|
||||
#include "mapheader.h"
|
||||
#include "project.h"
|
||||
|
||||
namespace Ui {
|
||||
class MapHeaderForm;
|
||||
|
||||
@@ -79,7 +79,6 @@ protected:
|
||||
|
||||
QString activeItemName;
|
||||
QString folderTypeName;
|
||||
bool sortingEnabled = false;
|
||||
bool editable = false;
|
||||
|
||||
QIcon mapGrayIcon;
|
||||
|
||||
@@ -37,6 +37,8 @@ public:
|
||||
void setFilterLocked(bool locked) { m_filterLocked = locked; }
|
||||
bool isFilterLocked() const { return m_filterLocked; }
|
||||
|
||||
void setSearchFocus();
|
||||
|
||||
signals:
|
||||
void filterCleared(MapTree*);
|
||||
void addFolderClicked();
|
||||
|
||||
@@ -79,6 +79,7 @@ private:
|
||||
bool positionIsValid(const QPoint &pos) const;
|
||||
bool selectionIsValid();
|
||||
void hoverChanged();
|
||||
int numPrimaryMetatilesRounded() const;
|
||||
|
||||
signals:
|
||||
void hoveredMetatileSelectionChanged(uint16_t);
|
||||
|
||||
@@ -5,12 +5,13 @@
|
||||
#include <QPainter>
|
||||
#include <QRgb>
|
||||
|
||||
class MovableRect : public QGraphicsItem
|
||||
|
||||
|
||||
class MovableRect : public QGraphicsRectItem
|
||||
{
|
||||
public:
|
||||
MovableRect(bool *enabled, int width, int height, QRgb color);
|
||||
QRectF boundingRect() const override
|
||||
{
|
||||
QRectF boundingRect() const override {
|
||||
qreal penWidth = 4;
|
||||
return QRectF(-penWidth,
|
||||
-penWidth,
|
||||
@@ -18,21 +19,65 @@ public:
|
||||
20 * 8 + penWidth * 2);
|
||||
}
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override
|
||||
{
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override {
|
||||
if (!(*enabled)) return;
|
||||
painter->setPen(this->color);
|
||||
painter->drawRect(x() - 2, y() - 2, this->width + 3, this->height + 3);
|
||||
painter->drawRect(this->rect().x() - 2, this->rect().y() - 2, this->rect().width() + 3, this->rect().height() + 3);
|
||||
painter->setPen(QColor(0, 0, 0));
|
||||
painter->drawRect(x() - 3, y() - 3, this->width + 5, this->height + 5);
|
||||
painter->drawRect(x() - 1, y() - 1, this->width + 1, this->height + 1);
|
||||
painter->drawRect(this->rect().x() - 3, this->rect().y() - 3, this->rect().width() + 5, this->rect().height() + 5);
|
||||
painter->drawRect(this->rect().x() - 1, this->rect().y() - 1, this->rect().width() + 1, this->rect().height() + 1);
|
||||
}
|
||||
void updateLocation(int x, int y);
|
||||
bool *enabled;
|
||||
private:
|
||||
int width;
|
||||
int height;
|
||||
|
||||
protected:
|
||||
QRgb color;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// A MovableRect with the addition of being resizable.
|
||||
class ResizableRect : public QObject, public MovableRect
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ResizableRect(QObject *parent, bool *enabled, int width, int height, QRgb color);
|
||||
|
||||
QRectF boundingRect() const override {
|
||||
return QRectF(this->rect() + QMargins(lineWidth, lineWidth, lineWidth, lineWidth));
|
||||
}
|
||||
|
||||
QPainterPath shape() const override {
|
||||
QPainterPath path;
|
||||
path.addRect(this->rect() + QMargins(lineWidth, lineWidth, lineWidth, lineWidth));
|
||||
path.addRect(this->rect() - QMargins(lineWidth, lineWidth, lineWidth, lineWidth));
|
||||
return path;
|
||||
}
|
||||
|
||||
void updatePosFromRect(QRect newPos);
|
||||
void setLimit(QRect limit) { this->limit = limit; }
|
||||
|
||||
protected:
|
||||
void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override;
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *) override;
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
enum class Edge { None, Left, Right, Top, Bottom, TopLeft, BottomLeft, TopRight, BottomRight };
|
||||
ResizableRect::Edge detectEdge(int x, int y);
|
||||
|
||||
// Variables for keeping state of original rect while resizing
|
||||
ResizableRect::Edge clickedEdge = ResizableRect::Edge::None;
|
||||
QPointF clickedPos = QPointF();
|
||||
QRect clickedRect;
|
||||
|
||||
QRect limit = QRect();
|
||||
|
||||
int lineWidth = 8;
|
||||
|
||||
signals:
|
||||
void rectUpdated(QRect rect);
|
||||
};
|
||||
|
||||
#endif // MOVABLERECT_H
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <QAbstractButton>
|
||||
#include <QPointer>
|
||||
|
||||
class Project;
|
||||
#include "project.h"
|
||||
|
||||
namespace Ui {
|
||||
class NewLocationDialog;
|
||||
|
||||
@@ -12,6 +12,8 @@ public:
|
||||
void wheelEvent(QWheelEvent *event) override;
|
||||
void focusOutEvent(QFocusEvent *event) override;
|
||||
|
||||
void setLineEditEnabled(bool enabled);
|
||||
|
||||
unsigned getActionId();
|
||||
|
||||
private:
|
||||
|
||||
109
include/ui/resizelayoutpopup.h
Normal file
109
include/ui/resizelayoutpopup.h
Normal file
@@ -0,0 +1,109 @@
|
||||
#ifndef RESIZELAYOUTPOPUP_H
|
||||
#define RESIZELAYOUTPOPUP_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QPointer>
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsLineItem>
|
||||
#include <QGraphicsRectItem>
|
||||
#include <QDialogButtonBox>
|
||||
|
||||
class ResizableRect;
|
||||
class Editor;
|
||||
namespace Ui {
|
||||
class ResizeLayoutPopup;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Custom scene that paints its background a gray checkered pattern.
|
||||
/// Additionally there is a definable "valid" area which will paint the checkerboard green inside.
|
||||
class CheckeredBgScene : public QGraphicsScene {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CheckeredBgScene(QObject *parent = nullptr);
|
||||
void setValidRect(int x, int y, int width, int height) {
|
||||
this->validRect = QRect(x * this->gridSize, y * this->gridSize, width * this->gridSize, height * this->gridSize);
|
||||
}
|
||||
void setValidRect(QRect rect) {
|
||||
this->validRect = rect;
|
||||
}
|
||||
QRect getValidRect() { return this->validRect; }
|
||||
|
||||
protected:
|
||||
void drawBackground(QPainter *painter, const QRectF &rect) override;
|
||||
|
||||
private:
|
||||
int gridSize = 16; // virtual pixels
|
||||
QRect validRect = QRect();
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// PixmapItem subclass which allows for creating a boundary which determine whether
|
||||
/// the pixmap paints normally or with a black tint.
|
||||
/// This item is movable and snaps on a 16x16 grid.
|
||||
class BoundedPixmapItem : public QGraphicsPixmapItem {
|
||||
public:
|
||||
BoundedPixmapItem(const QPixmap &pixmap, QGraphicsItem *parent = nullptr);
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override;
|
||||
|
||||
void setBoundary(ResizableRect *rect) { this->boundary = rect; }
|
||||
|
||||
protected:
|
||||
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
|
||||
|
||||
private:
|
||||
ResizableRect *boundary = nullptr;
|
||||
QPointF clickedPos = QPointF();
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// The main (modal) dialog window for resizing layout and border dimensions.
|
||||
/// The dialog itself is minimal, and is connected to the parent widget's geometry.
|
||||
class ResizeLayoutPopup : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ResizeLayoutPopup(QWidget *parent, Editor *editor);
|
||||
~ResizeLayoutPopup();
|
||||
|
||||
void setupLayoutView();
|
||||
|
||||
void resetPosition();
|
||||
|
||||
QMargins getResult();
|
||||
QSize getBorderResult();
|
||||
|
||||
protected:
|
||||
void moveEvent(QMoveEvent *) override {
|
||||
// Prevent the dialog from being moved
|
||||
this->resetPosition();
|
||||
}
|
||||
|
||||
void resizeEvent(QResizeEvent *) override {
|
||||
// Prevent the dialog from being resized
|
||||
this->resetPosition();
|
||||
}
|
||||
|
||||
private slots:
|
||||
void on_spinBox_width_valueChanged(int value);
|
||||
void on_spinBox_height_valueChanged(int value);
|
||||
void on_buttonBox_clicked(QAbstractButton *button);
|
||||
|
||||
private:
|
||||
QWidget *parent = nullptr;
|
||||
Editor *editor = nullptr;
|
||||
|
||||
Ui::ResizeLayoutPopup *ui;
|
||||
|
||||
ResizableRect *outline = nullptr;
|
||||
BoundedPixmapItem *layoutPixmap = nullptr;
|
||||
|
||||
QPointer<CheckeredBgScene> scene = nullptr;
|
||||
};
|
||||
|
||||
#endif // RESIZELAYOUTPOPUP_H
|
||||
@@ -35,9 +35,9 @@ signals:
|
||||
private:
|
||||
Ui::ShortcutsEditor *ui;
|
||||
QWidget *main_container;
|
||||
QMultiMap<QString, const QObject *> labels_objects;
|
||||
QMultiMap<QString, QPointer<const QObject>> labels_objects;
|
||||
QHash<QString, QFormLayout *> contexts_layouts;
|
||||
QHash<MultiKeyEdit *, const QObject *> multiKeyEdits_objects;
|
||||
QHash<MultiKeyEdit *, QPointer<const QObject>> multiKeyEdits_objects;
|
||||
|
||||
void parseObjectList(const QObjectList &objectList);
|
||||
QString getLabel(const QObject *object) const;
|
||||
|
||||
@@ -51,6 +51,7 @@ private:
|
||||
void drawCounts();
|
||||
QImage buildAllMetatilesImage();
|
||||
QImage buildImage(int metatileIdStart, int numMetatiles);
|
||||
int numPrimaryMetatilesRounded() const;
|
||||
|
||||
signals:
|
||||
void hoveredMetatileChanged(uint16_t);
|
||||
|
||||
@@ -2,9 +2,24 @@
|
||||
#define WILDMONSEARCH_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QTableWidgetItem>
|
||||
#include <QCollator>
|
||||
|
||||
class Project;
|
||||
|
||||
class NumericSortTableItem : public QTableWidgetItem
|
||||
{
|
||||
public:
|
||||
explicit NumericSortTableItem(const QString &text) : QTableWidgetItem(text) {};
|
||||
|
||||
protected:
|
||||
virtual bool operator<(const QTableWidgetItem &other) const override {
|
||||
QCollator collator;
|
||||
collator.setNumericMode(true);
|
||||
return collator.compare(text(), other.text()) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
namespace Ui {
|
||||
class WildMonSearch;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ DEFINES += PORYMAP_VERSION=\\\"$$VERSION\\\"
|
||||
|
||||
SOURCES += src/core/advancemapparser.cpp \
|
||||
src/core/block.cpp \
|
||||
src/ui/resizelayoutpopup.cpp \
|
||||
src/core/bitpacker.cpp \
|
||||
src/core/blockdata.cpp \
|
||||
src/core/events.cpp \
|
||||
@@ -255,7 +256,8 @@ HEADERS += include/core/advancemapparser.h \
|
||||
include/ui/uintspinbox.h \
|
||||
include/ui/updatepromoter.h \
|
||||
include/ui/wildmonchart.h \
|
||||
include/ui/wildmonsearch.h
|
||||
include/ui/wildmonsearch.h \
|
||||
include/ui/resizelayoutpopup.h
|
||||
|
||||
FORMS += forms/mainwindow.ui \
|
||||
forms/colorinputwidget.ui \
|
||||
@@ -288,7 +290,8 @@ FORMS += forms/mainwindow.ui \
|
||||
forms/customattributesdialog.ui \
|
||||
forms/updatepromoter.ui \
|
||||
forms/wildmonchart.ui \
|
||||
forms/wildmonsearch.ui
|
||||
forms/wildmonsearch.ui \
|
||||
forms/resizelayoutpopup.ui
|
||||
|
||||
RESOURCES += \
|
||||
resources/images.qrc \
|
||||
|
||||
@@ -177,7 +177,7 @@ bool ShiftMetatiles::mergeWith(const QUndoCommand *command) {
|
||||
************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
ResizeLayout::ResizeLayout(Layout *layout, QSize oldLayoutDimensions, QSize newLayoutDimensions,
|
||||
ResizeLayout::ResizeLayout(Layout *layout, QSize oldLayoutDimensions, QMargins newLayoutMargins,
|
||||
const Blockdata &oldMetatiles, const Blockdata &newMetatiles,
|
||||
QSize oldBorderDimensions, QSize newBorderDimensions,
|
||||
const Blockdata &oldBorder, const Blockdata &newBorder,
|
||||
@@ -189,8 +189,7 @@ ResizeLayout::ResizeLayout(Layout *layout, QSize oldLayoutDimensions, QSize newL
|
||||
this->oldLayoutWidth = oldLayoutDimensions.width();
|
||||
this->oldLayoutHeight = oldLayoutDimensions.height();
|
||||
|
||||
this->newLayoutWidth = newLayoutDimensions.width();
|
||||
this->newLayoutHeight = newLayoutDimensions.height();
|
||||
this->newLayoutMargins = newLayoutMargins;
|
||||
|
||||
this->oldMetatiles = oldMetatiles;
|
||||
this->newMetatiles = newMetatiles;
|
||||
@@ -210,12 +209,14 @@ void ResizeLayout::redo() {
|
||||
|
||||
if (!layout) return;
|
||||
|
||||
layout->blockdata = newMetatiles;
|
||||
layout->setDimensions(newLayoutWidth, newLayoutHeight, false, true);
|
||||
|
||||
layout->border = newBorder;
|
||||
layout->setBorderDimensions(newBorderWidth, newBorderHeight, false, true);
|
||||
|
||||
layout->width = oldLayoutWidth;
|
||||
layout->height = oldLayoutHeight;
|
||||
layout->adjustDimensions(this->newLayoutMargins);
|
||||
layout->blockdata = newMetatiles;
|
||||
|
||||
layout->lastCommitBlocks.layoutDimensions = QSize(layout->getWidth(), layout->getHeight());
|
||||
layout->lastCommitBlocks.borderDimensions = QSize(layout->getBorderWidth(), layout->getBorderHeight());
|
||||
|
||||
@@ -225,12 +226,14 @@ void ResizeLayout::redo() {
|
||||
void ResizeLayout::undo() {
|
||||
if (!layout) return;
|
||||
|
||||
layout->blockdata = oldMetatiles;
|
||||
layout->setDimensions(oldLayoutWidth, oldLayoutHeight, false, true);
|
||||
|
||||
layout->border = oldBorder;
|
||||
layout->setBorderDimensions(oldBorderWidth, oldBorderHeight, false, true);
|
||||
|
||||
layout->width = oldLayoutWidth + newLayoutMargins.left() + newLayoutMargins.right();
|
||||
layout->height = oldLayoutHeight + newLayoutMargins.top() + newLayoutMargins.bottom();
|
||||
layout->adjustDimensions(-this->newLayoutMargins);
|
||||
layout->blockdata = oldMetatiles;
|
||||
|
||||
layout->lastCommitBlocks.layoutDimensions = QSize(layout->getWidth(), layout->getHeight());
|
||||
layout->lastCommitBlocks.borderDimensions = QSize(layout->getBorderWidth(), layout->getBorderHeight());
|
||||
|
||||
@@ -324,9 +327,7 @@ void EventCreate::redo() {
|
||||
QUndoCommand::redo();
|
||||
|
||||
map->addEvent(event);
|
||||
|
||||
editor->project->setEventPixmap(event);
|
||||
editor->addMapEvent(event);
|
||||
editor->addEventPixmapItem(event);
|
||||
|
||||
// select this event
|
||||
editor->selected_events->clear();
|
||||
@@ -335,12 +336,7 @@ void EventCreate::redo() {
|
||||
|
||||
void EventCreate::undo() {
|
||||
map->removeEvent(event);
|
||||
|
||||
if (editor->scene->items().contains(event->getPixmapItem())) {
|
||||
editor->scene->removeItem(event->getPixmapItem());
|
||||
}
|
||||
editor->selected_events->removeOne(event->getPixmapItem());
|
||||
|
||||
editor->removeEventPixmapItem(event);
|
||||
editor->shouldReselectEvents();
|
||||
|
||||
QUndoCommand::undo();
|
||||
@@ -375,11 +371,7 @@ void EventDelete::redo() {
|
||||
|
||||
for (Event *event : selectedEvents) {
|
||||
map->removeEvent(event);
|
||||
|
||||
if (editor->scene->items().contains(event->getPixmapItem())) {
|
||||
editor->scene->removeItem(event->getPixmapItem());
|
||||
}
|
||||
editor->selected_events->removeOne(event->getPixmapItem());
|
||||
editor->removeEventPixmapItem(event);
|
||||
}
|
||||
|
||||
editor->selected_events->clear();
|
||||
@@ -391,8 +383,7 @@ void EventDelete::redo() {
|
||||
void EventDelete::undo() {
|
||||
for (Event *event : selectedEvents) {
|
||||
map->addEvent(event);
|
||||
editor->project->setEventPixmap(event);
|
||||
editor->addMapEvent(event);
|
||||
editor->addEventPixmapItem(event);
|
||||
}
|
||||
|
||||
// select these events
|
||||
@@ -433,8 +424,7 @@ void EventDuplicate::redo() {
|
||||
|
||||
for (Event *event : selectedEvents) {
|
||||
map->addEvent(event);
|
||||
editor->project->setEventPixmap(event);
|
||||
editor->addMapEvent(event);
|
||||
editor->addEventPixmapItem(event);
|
||||
}
|
||||
|
||||
// select these events
|
||||
@@ -448,11 +438,7 @@ void EventDuplicate::redo() {
|
||||
void EventDuplicate::undo() {
|
||||
for (Event *event : selectedEvents) {
|
||||
map->removeEvent(event);
|
||||
|
||||
if (editor->scene->items().contains(event->getPixmapItem())) {
|
||||
editor->scene->removeItem(event->getPixmapItem());
|
||||
}
|
||||
editor->selected_events->removeOne(event->getPixmapItem());
|
||||
editor->removeEventPixmapItem(event);
|
||||
}
|
||||
|
||||
editor->shouldReselectEvents();
|
||||
|
||||
@@ -176,6 +176,34 @@ void Layout::setDimensions(int newWidth, int newHeight, bool setNewBlockdata, bo
|
||||
emit layoutDimensionsChanged(QSize(getWidth(), getHeight()));
|
||||
}
|
||||
|
||||
void Layout::adjustDimensions(QMargins margins, bool setNewBlockdata) {
|
||||
int oldWidth = this->width;
|
||||
int oldHeight = this->height;
|
||||
int newWidth = this->width + margins.left() + margins.right();
|
||||
int newHeight = this->height + margins.top() + margins.bottom();
|
||||
|
||||
if (setNewBlockdata) {
|
||||
// Fill new blockdata
|
||||
Blockdata newBlockdata;
|
||||
for (int y = 0; y < newHeight; y++)
|
||||
for (int x = 0; x < newWidth; x++) {
|
||||
if ((x < margins.left()) || (x >= newWidth - margins.right()) || (y < margins.top()) || (y >= newHeight - margins.bottom())) {
|
||||
newBlockdata.append(0);
|
||||
} else {
|
||||
int index = (y - margins.top()) * oldWidth + (x - margins.left());
|
||||
newBlockdata.append(this->blockdata.value(index));
|
||||
}
|
||||
}
|
||||
this->blockdata = newBlockdata;
|
||||
}
|
||||
|
||||
this->width = newWidth;
|
||||
this->height = newHeight;
|
||||
|
||||
emit layoutChanged(this);
|
||||
emit layoutDimensionsChanged(QSize(getWidth(), getHeight()));
|
||||
}
|
||||
|
||||
void Layout::setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata, bool enableScriptCallback) {
|
||||
if (setNewBlockdata) {
|
||||
setNewBorderDimensionsBlockdata(newWidth, newHeight);
|
||||
|
||||
@@ -83,7 +83,8 @@ void Tileset::addMetatile(Metatile* metatile) {
|
||||
m_metatiles.append(metatile);
|
||||
}
|
||||
|
||||
void Tileset::resizeMetatiles(unsigned int newNumMetatiles) {
|
||||
void Tileset::resizeMetatiles(int newNumMetatiles) {
|
||||
if (newNumMetatiles < 0) newNumMetatiles = 0;
|
||||
while (m_metatiles.length() > newNumMetatiles) {
|
||||
delete m_metatiles.takeLast();
|
||||
}
|
||||
|
||||
130
src/editor.cpp
130
src/editor.cpp
@@ -135,36 +135,26 @@ void Editor::setEditorView() {
|
||||
return;
|
||||
}
|
||||
|
||||
map_item->setEditsEnabled(this->editMode != EditMode::Connections);
|
||||
map_item->draw();
|
||||
collision_item->draw();
|
||||
|
||||
current_view->setVisible(true);
|
||||
|
||||
updateBorderVisibility();
|
||||
this->cursorMapTileRect->setSingleTileMode();
|
||||
this->cursorMapTileRect->setActive(true);
|
||||
|
||||
switch (this->editMode) {
|
||||
case EditMode::Metatiles:
|
||||
case EditMode::Collision:
|
||||
map_item->setEditsEnabled(true);
|
||||
this->editGroup.setActiveStack(&this->layout->editHistory);
|
||||
break;
|
||||
case EditMode::Connections:
|
||||
this->cursorMapTileRect->setActive(false);
|
||||
map_item->setEditsEnabled(false);
|
||||
case EditMode::Events:
|
||||
if (this->map) {
|
||||
this->editGroup.setActiveStack(this->map->editHistory());
|
||||
}
|
||||
break;
|
||||
case EditMode::Header:
|
||||
case EditMode::Encounters:
|
||||
default:
|
||||
this->editGroup.setActiveStack(nullptr);
|
||||
break;
|
||||
QUndoStack *editStack = this->map ? this->map->editHistory() : nullptr;
|
||||
bool usesCursor = false;
|
||||
if (this->editMode == EditMode::Metatiles || this->editMode == EditMode::Collision) {
|
||||
if (this->layout) editStack = &this->layout->editHistory;
|
||||
usesCursor = true;
|
||||
}
|
||||
|
||||
this->cursorMapTileRect->setSingleTileMode();
|
||||
this->cursorMapTileRect->setActive(usesCursor);
|
||||
this->editGroup.setActiveStack(editStack);
|
||||
|
||||
|
||||
if (this->events_group) {
|
||||
this->events_group->setVisible(this->editMode == EditMode::Events);
|
||||
}
|
||||
@@ -189,7 +179,7 @@ void Editor::setEditingHeader() {
|
||||
setEditorView();
|
||||
}
|
||||
|
||||
void Editor::setEditingObjects() {
|
||||
void Editor::setEditingEvents() {
|
||||
this->editMode = EditMode::Events;
|
||||
|
||||
setEditorView();
|
||||
@@ -1306,7 +1296,7 @@ void Editor::setStraightPathCursorMode(QGraphicsSceneMouseEvent *event) {
|
||||
}
|
||||
|
||||
void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *item) {
|
||||
// TODO: add event tab object painting tool buttons stuff here
|
||||
// TODO: add event tab event painting tool buttons stuff here
|
||||
if (!item->getEditsEnabled()) {
|
||||
return;
|
||||
}
|
||||
@@ -1361,10 +1351,10 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *i
|
||||
item->shift(event);
|
||||
}
|
||||
} else if (this->editMode == EditMode::Events) {
|
||||
if (objectEditAction == EditAction::Paint && event->type() == QEvent::GraphicsSceneMousePress) {
|
||||
if (eventEditAction == EditAction::Paint && event->type() == QEvent::GraphicsSceneMousePress) {
|
||||
// Right-clicking while in paint mode will change mode to select.
|
||||
if (event->buttons() & Qt::RightButton) {
|
||||
this->objectEditAction = EditAction::Select;
|
||||
this->eventEditAction = EditAction::Select;
|
||||
this->settings->mapCursor = QCursor();
|
||||
this->cursorMapTileRect->setSingleTileMode();
|
||||
this->ui->toolButton_Paint->setChecked(false);
|
||||
@@ -1380,18 +1370,17 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *i
|
||||
DraggablePixmapItem *newEvent = addNewEvent(eventType);
|
||||
if (newEvent) {
|
||||
newEvent->move(pos.x(), pos.y());
|
||||
emit objectsChanged();
|
||||
emit eventsChanged();
|
||||
selectMapEvent(newEvent);
|
||||
}
|
||||
}
|
||||
} else if (objectEditAction == EditAction::Select) {
|
||||
} else if (eventEditAction == EditAction::Select) {
|
||||
// do nothing here, at least for now
|
||||
} else if (objectEditAction == EditAction::Shift) {
|
||||
} else if (eventEditAction == EditAction::Shift) {
|
||||
static QPoint selection_origin;
|
||||
static unsigned actionId = 0;
|
||||
|
||||
if (event->type() == QEvent::GraphicsSceneMouseRelease) {
|
||||
actionId++;
|
||||
this->eventShiftActionId++;
|
||||
} else {
|
||||
if (event->type() == QEvent::GraphicsSceneMousePress) {
|
||||
selection_origin = QPoint(pos.x(), pos.y());
|
||||
@@ -1402,12 +1391,12 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *i
|
||||
|
||||
QList<Event *> selectedEvents;
|
||||
|
||||
for (DraggablePixmapItem *pixmapItem : getObjects()) {
|
||||
for (DraggablePixmapItem *pixmapItem : getEventPixmapItems()) {
|
||||
selectedEvents.append(pixmapItem->event);
|
||||
}
|
||||
selection_origin = QPoint(pos.x(), pos.y());
|
||||
|
||||
map->commit(new EventShift(selectedEvents, xDelta, yDelta, actionId));
|
||||
map->commit(new EventShift(selectedEvents, xDelta, yDelta, this->eventShiftActionId));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1702,15 +1691,13 @@ void Editor::displayMovementPermissionSelector() {
|
||||
|
||||
void Editor::clearMapEvents() {
|
||||
if (events_group) {
|
||||
if (events_group->scene()) {
|
||||
events_group->scene()->removeItem(events_group);
|
||||
}
|
||||
for (QGraphicsItem *child : events_group->childItems()) {
|
||||
events_group->removeFromGroup(child);
|
||||
delete child;
|
||||
}
|
||||
|
||||
if (events_group->scene()) {
|
||||
events_group->scene()->removeItem(events_group);
|
||||
}
|
||||
|
||||
delete events_group;
|
||||
events_group = nullptr;
|
||||
}
|
||||
@@ -1724,18 +1711,29 @@ void Editor::displayMapEvents() {
|
||||
scene->addItem(events_group);
|
||||
|
||||
for (const auto &event : map->getEvents()) {
|
||||
project->setEventPixmap(event);
|
||||
addMapEvent(event);
|
||||
addEventPixmapItem(event);
|
||||
}
|
||||
//objects_group->setFiltersChildEvents(false);
|
||||
|
||||
events_group->setHandlesChildEvents(false);
|
||||
}
|
||||
|
||||
DraggablePixmapItem *Editor::addMapEvent(Event *event) {
|
||||
DraggablePixmapItem *object = new DraggablePixmapItem(event, this);
|
||||
this->redrawObject(object);
|
||||
events_group->addToGroup(object);
|
||||
return object;
|
||||
DraggablePixmapItem *Editor::addEventPixmapItem(Event *event) {
|
||||
this->project->setEventPixmap(event);
|
||||
auto item = new DraggablePixmapItem(event, this);
|
||||
redrawEventPixmapItem(item);
|
||||
this->events_group->addToGroup(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
void Editor::removeEventPixmapItem(Event *event) {
|
||||
auto item = event->getPixmapItem();
|
||||
if (!item) return;
|
||||
|
||||
this->events_group->removeFromGroup(item);
|
||||
this->selected_events->removeOne(item);
|
||||
|
||||
event->setPixmapItem(nullptr);
|
||||
delete item;
|
||||
}
|
||||
|
||||
void Editor::clearMapConnections() {
|
||||
@@ -1987,7 +1985,7 @@ Tileset* Editor::getCurrentMapPrimaryTileset()
|
||||
return project->getTileset(tilesetLabel);
|
||||
}
|
||||
|
||||
QList<DraggablePixmapItem *> Editor::getObjects() {
|
||||
QList<DraggablePixmapItem *> Editor::getEventPixmapItems() {
|
||||
QList<DraggablePixmapItem *> list;
|
||||
for (QGraphicsItem *child : events_group->childItems()) {
|
||||
list.append(static_cast<DraggablePixmapItem *>(child));
|
||||
@@ -1995,7 +1993,7 @@ QList<DraggablePixmapItem *> Editor::getObjects() {
|
||||
return list;
|
||||
}
|
||||
|
||||
void Editor::redrawObject(DraggablePixmapItem *item) {
|
||||
void Editor::redrawEventPixmapItem(DraggablePixmapItem *item) {
|
||||
if (item && item->event && !item->event->getPixmap().isNull()) {
|
||||
qreal opacity = item->event->getUsingSprite() ? 1.0 : 0.7;
|
||||
item->setOpacity(opacity);
|
||||
@@ -2050,27 +2048,27 @@ void Editor::shouldReselectEvents() {
|
||||
}
|
||||
|
||||
void Editor::updateSelectedEvents() {
|
||||
for (DraggablePixmapItem *item : getObjects()) {
|
||||
redrawObject(item);
|
||||
for (DraggablePixmapItem *item : getEventPixmapItems()) {
|
||||
redrawEventPixmapItem(item);
|
||||
}
|
||||
|
||||
emit objectsChanged();
|
||||
emit eventsChanged();
|
||||
}
|
||||
|
||||
void Editor::selectMapEvent(DraggablePixmapItem *object, bool toggle) {
|
||||
if (!selected_events || !object)
|
||||
void Editor::selectMapEvent(DraggablePixmapItem *item, bool toggle) {
|
||||
if (!selected_events || !item)
|
||||
return;
|
||||
|
||||
if (!toggle) {
|
||||
// Selecting just this event
|
||||
selected_events->clear();
|
||||
selected_events->append(object);
|
||||
} else if (!selected_events->contains(object)) {
|
||||
selected_events->append(item);
|
||||
} else if (!selected_events->contains(item)) {
|
||||
// Adding event to group selection
|
||||
selected_events->append(object);
|
||||
selected_events->append(item);
|
||||
} else if (selected_events->length() > 1) {
|
||||
// Removing event from group selection
|
||||
selected_events->removeOne(object);
|
||||
selected_events->removeOne(item);
|
||||
} else {
|
||||
// Attempting to toggle the only currently-selected event.
|
||||
// Unselecting an event this way would be unexpected, so we ignore it.
|
||||
@@ -2083,17 +2081,9 @@ void Editor::selectedEventIndexChanged(int index, Event::Group eventGroup) {
|
||||
int event_offs = Event::getIndexOffset(eventGroup);
|
||||
index = index - event_offs;
|
||||
Event *event = this->map->getEvent(eventGroup, index);
|
||||
DraggablePixmapItem *selectedEvent = nullptr;
|
||||
for (QGraphicsItem *child : this->events_group->childItems()) {
|
||||
DraggablePixmapItem *item = static_cast<DraggablePixmapItem *>(child);
|
||||
if (item->event == event) {
|
||||
selectedEvent = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedEvent) {
|
||||
this->selectMapEvent(selectedEvent);
|
||||
if (event && event->getPixmapItem()) {
|
||||
this->selectMapEvent(event->getPixmapItem());
|
||||
} else {
|
||||
updateSelectedEvents();
|
||||
}
|
||||
@@ -2295,13 +2285,13 @@ bool Editor::startDetachedProcess(const QString &command, const QString &working
|
||||
// Since the DraggablePixmapItem's event fires first, we can set a temp
|
||||
// variable "selectingEvent" so that we can detect whether or not the user
|
||||
// is clicking on the background instead of an event.
|
||||
void Editor::objectsView_onMousePress(QMouseEvent *event) {
|
||||
// make sure we are in object editing mode
|
||||
void Editor::eventsView_onMousePress(QMouseEvent *event) {
|
||||
// make sure we are in event editing mode
|
||||
if (map_item && this->editMode != EditMode::Events) {
|
||||
return;
|
||||
}
|
||||
if (this->objectEditAction == EditAction::Paint && event->buttons() & Qt::RightButton) {
|
||||
this->objectEditAction = EditAction::Select;
|
||||
if (this->eventEditAction == EditAction::Paint && event->buttons() & Qt::RightButton) {
|
||||
this->eventEditAction = EditAction::Select;
|
||||
this->settings->mapCursor = QCursor();
|
||||
this->cursorMapTileRect->setSingleTileMode();
|
||||
this->ui->toolButton_Paint->setChecked(false);
|
||||
|
||||
@@ -116,6 +116,10 @@ static void dump(const QString &value, QString &out, int *indent, bool isKey = f
|
||||
static void dump(const Json::array &values, QString &out, int *indent) {
|
||||
bool first = true;
|
||||
if (!out.endsWith(": ")) out += QString(*indent * 2, ' ');
|
||||
if (values.empty()) {
|
||||
out += "[]";
|
||||
return;
|
||||
}
|
||||
out += "[\n";
|
||||
*indent += 1;
|
||||
for (const auto &value : values) {
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "newmapconnectiondialog.h"
|
||||
#include "config.h"
|
||||
#include "filedialog.h"
|
||||
#include "resizelayoutpopup.h"
|
||||
#include "newmapdialog.h"
|
||||
#include "newtilesetdialog.h"
|
||||
#include "newmapgroupdialog.h"
|
||||
@@ -92,6 +93,7 @@ MainWindow::~MainWindow()
|
||||
saveGlobalConfigs();
|
||||
|
||||
delete label_MapRulerStatus;
|
||||
delete undoView;
|
||||
delete editor;
|
||||
delete ui;
|
||||
}
|
||||
@@ -332,14 +334,14 @@ void MainWindow::checkForUpdates(bool) {}
|
||||
|
||||
void MainWindow::initEditor() {
|
||||
this->editor = new Editor(ui);
|
||||
connect(this->editor, &Editor::objectsChanged, this, &MainWindow::updateObjects);
|
||||
connect(this->editor, &Editor::eventsChanged, this, &MainWindow::updateEvents);
|
||||
connect(this->editor, &Editor::openConnectedMap, this, &MainWindow::onOpenConnectedMap);
|
||||
connect(this->editor, &Editor::warpEventDoubleClicked, this, &MainWindow::openWarpMap);
|
||||
connect(this->editor, &Editor::currentMetatilesSelectionChanged, this, &MainWindow::currentMetatilesSelectionChanged);
|
||||
connect(this->editor, &Editor::wildMonTableEdited, [this] { this->markMapEdited(); });
|
||||
connect(this->editor, &Editor::mapRulerStatusChanged, this, &MainWindow::onMapRulerStatusChanged);
|
||||
connect(this->editor, &Editor::tilesetUpdated, this, &Scripting::cb_TilesetUpdated);
|
||||
connect(ui->toolButton_deleteObject, &QAbstractButton::clicked, this->editor, &Editor::deleteSelectedEvents);
|
||||
connect(ui->toolButton_deleteEvent, &QAbstractButton::clicked, this->editor, &Editor::deleteSelectedEvents);
|
||||
|
||||
this->loadUserSettings();
|
||||
|
||||
@@ -354,15 +356,15 @@ void MainWindow::initEditor() {
|
||||
ui->menuEdit->addAction(undoAction);
|
||||
ui->menuEdit->addAction(redoAction);
|
||||
|
||||
QUndoView *undoView = new QUndoView(&editor->editGroup);
|
||||
undoView->setWindowTitle(tr("Edit History"));
|
||||
undoView->setAttribute(Qt::WA_QuitOnClose, false);
|
||||
this->undoView = new QUndoView(&editor->editGroup);
|
||||
this->undoView->setWindowTitle(tr("Edit History"));
|
||||
this->undoView->setAttribute(Qt::WA_QuitOnClose, false);
|
||||
|
||||
// Show the EditHistory dialog with Ctrl+E
|
||||
QAction *showHistory = new QAction("Show Edit History...", this);
|
||||
showHistory->setObjectName("action_ShowEditHistory");
|
||||
showHistory->setShortcut(QKeySequence("Ctrl+E"));
|
||||
connect(showHistory, &QAction::triggered, [this, undoView](){ openSubWindow(undoView); });
|
||||
connect(showHistory, &QAction::triggered, this, &MainWindow::openEditHistory);
|
||||
|
||||
ui->menuEdit->addAction(showHistory);
|
||||
|
||||
@@ -387,6 +389,10 @@ void MainWindow::initEditor() {
|
||||
});
|
||||
}
|
||||
|
||||
void MainWindow::openEditHistory() {
|
||||
openSubWindow(this->undoView);
|
||||
}
|
||||
|
||||
void MainWindow::initMiscHeapObjects() {
|
||||
ui->tabWidget_EventType->clear();
|
||||
}
|
||||
@@ -450,7 +456,7 @@ void MainWindow::initMapList() {
|
||||
connect(ui->mapListToolBar_Locations, &MapListToolBar::addFolderClicked, this, &MainWindow::openNewLocationDialog);
|
||||
connect(ui->mapListToolBar_Layouts, &MapListToolBar::addFolderClicked, this, &MainWindow::openNewLayoutDialog);
|
||||
|
||||
connect(ui->mapListContainer, &QTabWidget::currentChanged, this, &MainWindow::saveMapListTab);
|
||||
connect(ui->mapListContainer, &QTabWidget::currentChanged, this, &MainWindow::onMapListTabChanged);
|
||||
}
|
||||
|
||||
void MainWindow::updateWindowTitle() {
|
||||
@@ -830,12 +836,7 @@ void MainWindow::on_action_Open_Project_triggered()
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Reload_Project_triggered() {
|
||||
// TODO: when undo history is complete show only if has unsaved changes
|
||||
WarningMessage msgBox(QStringLiteral("Reloading this project will discard any unsaved changes."), this);
|
||||
msgBox.addButton(QMessageBox::Cancel);
|
||||
msgBox.setDefaultButton(QMessageBox::Cancel);
|
||||
if (msgBox.exec() == QMessageBox::Ok)
|
||||
openProject(editor->project->root);
|
||||
openProject(editor->project->root);
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Close_Project_triggered() {
|
||||
@@ -953,6 +954,7 @@ bool MainWindow::setLayout(QString layoutId) {
|
||||
|
||||
connect(editor->layout, &Layout::needsRedrawing, this, &MainWindow::redrawMapScene, Qt::UniqueConnection);
|
||||
|
||||
Scripting::cb_MapOpened(layout->name);
|
||||
updateTilesetEditor();
|
||||
|
||||
userConfig.recentMapOrLayout = layoutId;
|
||||
@@ -961,8 +963,8 @@ bool MainWindow::setLayout(QString layoutId) {
|
||||
}
|
||||
|
||||
void MainWindow::redrawMapScene() {
|
||||
editor->displayMap();
|
||||
editor->displayLayout();
|
||||
editor->displayMap();
|
||||
refreshMapScene();
|
||||
}
|
||||
|
||||
@@ -1008,13 +1010,12 @@ void MainWindow::openWarpMap(QString map_name, int event_id, Event::Group event_
|
||||
int index = event_id - Event::getIndexOffset(event_group);
|
||||
Event* event = editor->map->getEvent(event_group, index);
|
||||
if (event) {
|
||||
for (DraggablePixmapItem *item : editor->getObjects()) {
|
||||
if (item->event == event) {
|
||||
editor->selected_events->clear();
|
||||
editor->selected_events->append(item);
|
||||
editor->updateSelectedEvents();
|
||||
return;
|
||||
}
|
||||
auto item = event->getPixmapItem();
|
||||
if (item) {
|
||||
editor->selected_events->clear();
|
||||
editor->selected_events->append(item);
|
||||
editor->updateSelectedEvents();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Can still warp to this map, but can't select the specified event
|
||||
@@ -1106,11 +1107,15 @@ bool MainWindow::setProjectUI() {
|
||||
this->locationListProxyModel = new FilterChildrenProxyModel();
|
||||
locationListProxyModel->setSourceModel(this->mapLocationModel);
|
||||
ui->locationList->setModel(locationListProxyModel);
|
||||
ui->locationList->setSortingEnabled(true);
|
||||
ui->locationList->sortByColumn(0, Qt::SortOrder::AscendingOrder);
|
||||
|
||||
this->layoutTreeModel = new LayoutTreeModel(editor->project);
|
||||
this->layoutListProxyModel = new FilterChildrenProxyModel();
|
||||
this->layoutListProxyModel->setSourceModel(this->layoutTreeModel);
|
||||
ui->layoutList->setModel(layoutListProxyModel);
|
||||
ui->layoutList->setSortingEnabled(true);
|
||||
ui->layoutList->sortByColumn(0, Qt::SortOrder::AscendingOrder);
|
||||
|
||||
ui->mapCustomAttributesFrame->table()->setRestrictedKeys(project->topLevelMapFields);
|
||||
|
||||
@@ -1465,8 +1470,15 @@ void MainWindow::currentMetatilesSelectionChanged() {
|
||||
scrollMetatileSelectorToSelection();
|
||||
}
|
||||
|
||||
void MainWindow::saveMapListTab(int index) {
|
||||
void MainWindow::onMapListTabChanged(int index) {
|
||||
// Save current tab for future sessions.
|
||||
porymapConfig.mapListTab = index;
|
||||
|
||||
// After changing a map list tab the old tab's search widget can keep focus, which isn't helpful
|
||||
// (and might be a little confusing to the user, because they don't know that each search bar is secretly a separate object).
|
||||
// When we change tabs we'll automatically focus in on the search bar. This should also make finding maps a little quicker.
|
||||
auto toolbar = getCurrentMapListToolBar();
|
||||
if (toolbar) toolbar->setSearchFocus();
|
||||
}
|
||||
|
||||
void MainWindow::openMapListItem(const QModelIndex &index) {
|
||||
@@ -1737,7 +1749,7 @@ void MainWindow::paste() {
|
||||
|
||||
if (!newEvents.empty()) {
|
||||
editor->map->commit(new EventPaste(this->editor, editor->map, newEvents));
|
||||
updateObjects();
|
||||
updateEvents();
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -1793,8 +1805,8 @@ void MainWindow::on_mainTabBar_tabBarClicked(int index)
|
||||
clickToolButtonFromEditAction(editor->mapEditAction);
|
||||
} else if (index == MainTab::Events) {
|
||||
ui->stackedWidget_MapEvents->setCurrentIndex(1);
|
||||
editor->setEditingObjects();
|
||||
clickToolButtonFromEditAction(editor->objectEditAction);
|
||||
editor->setEditingEvents();
|
||||
clickToolButtonFromEditAction(editor->eventEditAction);
|
||||
} else if (index == MainTab::Connections) {
|
||||
editor->setEditingConnections();
|
||||
ui->graphicsView_Connections->setFocus(); // Avoid opening tab with focus on something editable
|
||||
@@ -1935,13 +1947,13 @@ void MainWindow::resetMapViewScale() {
|
||||
|
||||
void MainWindow::addNewEvent(Event::Type type) {
|
||||
if (editor && editor->project) {
|
||||
DraggablePixmapItem *object = editor->addNewEvent(type);
|
||||
if (object) {
|
||||
DraggablePixmapItem *item = editor->addNewEvent(type);
|
||||
if (item) {
|
||||
auto halfSize = ui->graphicsView_Map->size() / 2;
|
||||
auto centerPos = ui->graphicsView_Map->mapToScene(halfSize.width(), halfSize.height());
|
||||
object->moveTo(Metatile::coordFromPixmapCoord(centerPos));
|
||||
updateObjects();
|
||||
editor->selectMapEvent(object);
|
||||
item->moveTo(Metatile::coordFromPixmapCoord(centerPos));
|
||||
updateEvents();
|
||||
editor->selectMapEvent(item);
|
||||
} else {
|
||||
WarningMessage msgBox(QStringLiteral("Failed to add new event."), this);
|
||||
if (Event::typeToGroup(type) == Event::Group::Object) {
|
||||
@@ -1973,17 +1985,17 @@ void MainWindow::displayEventTabs() {
|
||||
tryAddEventTab(ui->tab_HealLocations);
|
||||
}
|
||||
|
||||
void MainWindow::updateObjects() {
|
||||
QList<DraggablePixmapItem *> all_objects = editor->getObjects();
|
||||
void MainWindow::updateEvents() {
|
||||
QList<DraggablePixmapItem *> items = editor->getEventPixmapItems();
|
||||
for (auto i = this->lastSelectedEvent.cbegin(), end = this->lastSelectedEvent.cend(); i != end; i++) {
|
||||
if (i.value() && !all_objects.contains(i.value()))
|
||||
if (i.value() && !items.contains(i.value()))
|
||||
this->lastSelectedEvent.insert(i.key(), nullptr);
|
||||
}
|
||||
displayEventTabs();
|
||||
updateSelectedObjects();
|
||||
updateSelectedEvents();
|
||||
}
|
||||
|
||||
void MainWindow::updateSelectedObjects() {
|
||||
void MainWindow::updateSelectedEvents() {
|
||||
QList<DraggablePixmapItem *> events;
|
||||
|
||||
if (editor->selected_events && editor->selected_events->length()) {
|
||||
@@ -1998,7 +2010,7 @@ void MainWindow::updateSelectedObjects() {
|
||||
DraggablePixmapItem *selectedEvent = all_events.first()->getPixmapItem();
|
||||
if (selectedEvent) {
|
||||
editor->selected_events->append(selectedEvent);
|
||||
editor->redrawObject(selectedEvent);
|
||||
editor->redrawEventPixmapItem(selectedEvent);
|
||||
events.append(selectedEvent);
|
||||
}
|
||||
}
|
||||
@@ -2143,7 +2155,7 @@ Event::Group MainWindow::getEventGroupFromTabWidget(QWidget *tab) {
|
||||
void MainWindow::eventTabChanged(int index) {
|
||||
if (editor->map) {
|
||||
Event::Group group = getEventGroupFromTabWidget(ui->tabWidget_EventType->widget(index));
|
||||
DraggablePixmapItem *selectedEvent = this->lastSelectedEvent.value(group, nullptr);
|
||||
DraggablePixmapItem *selectedItem = this->lastSelectedEvent.value(group, nullptr);
|
||||
|
||||
switch (group) {
|
||||
case Event::Group::Object:
|
||||
@@ -2166,18 +2178,11 @@ void MainWindow::eventTabChanged(int index) {
|
||||
}
|
||||
|
||||
if (!isProgrammaticEventTabChange) {
|
||||
if (!selectedEvent && editor->map->getNumEvents(group)) {
|
||||
if (!selectedItem) {
|
||||
Event *event = editor->map->getEvent(group, 0);
|
||||
for (QGraphicsItem *child : editor->events_group->childItems()) {
|
||||
DraggablePixmapItem *item = static_cast<DraggablePixmapItem *>(child);
|
||||
if (item->event == event) {
|
||||
selectedEvent = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (event) selectedItem = event->getPixmapItem();
|
||||
}
|
||||
|
||||
if (selectedEvent) editor->selectMapEvent(selectedEvent);
|
||||
if (selectedItem) editor->selectMapEvent(selectedItem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2246,7 +2251,7 @@ void MainWindow::on_toolButton_Paint_clicked()
|
||||
if (ui->mainTabBar->currentIndex() == MainTab::Map)
|
||||
editor->mapEditAction = Editor::EditAction::Paint;
|
||||
else
|
||||
editor->objectEditAction = Editor::EditAction::Paint;
|
||||
editor->eventEditAction = Editor::EditAction::Paint;
|
||||
|
||||
editor->settings->mapCursor = QCursor(QPixmap(":/icons/pencil_cursor.ico"), 10, 10);
|
||||
|
||||
@@ -2267,7 +2272,7 @@ void MainWindow::on_toolButton_Select_clicked()
|
||||
if (ui->mainTabBar->currentIndex() == MainTab::Map)
|
||||
editor->mapEditAction = Editor::EditAction::Select;
|
||||
else
|
||||
editor->objectEditAction = Editor::EditAction::Select;
|
||||
editor->eventEditAction = Editor::EditAction::Select;
|
||||
|
||||
editor->settings->mapCursor = QCursor();
|
||||
editor->cursorMapTileRect->setSingleTileMode();
|
||||
@@ -2286,7 +2291,7 @@ void MainWindow::on_toolButton_Fill_clicked()
|
||||
if (ui->mainTabBar->currentIndex() == MainTab::Map)
|
||||
editor->mapEditAction = Editor::EditAction::Fill;
|
||||
else
|
||||
editor->objectEditAction = Editor::EditAction::Fill;
|
||||
editor->eventEditAction = Editor::EditAction::Fill;
|
||||
|
||||
editor->settings->mapCursor = QCursor(QPixmap(":/icons/fill_color_cursor.ico"), 10, 10);
|
||||
editor->cursorMapTileRect->setSingleTileMode();
|
||||
@@ -2305,7 +2310,7 @@ void MainWindow::on_toolButton_Dropper_clicked()
|
||||
if (ui->mainTabBar->currentIndex() == MainTab::Map)
|
||||
editor->mapEditAction = Editor::EditAction::Pick;
|
||||
else
|
||||
editor->objectEditAction = Editor::EditAction::Pick;
|
||||
editor->eventEditAction = Editor::EditAction::Pick;
|
||||
|
||||
editor->settings->mapCursor = QCursor(QPixmap(":/icons/pipette_cursor.ico"), 10, 10);
|
||||
editor->cursorMapTileRect->setSingleTileMode();
|
||||
@@ -2324,7 +2329,7 @@ void MainWindow::on_toolButton_Move_clicked()
|
||||
if (ui->mainTabBar->currentIndex() == MainTab::Map)
|
||||
editor->mapEditAction = Editor::EditAction::Move;
|
||||
else
|
||||
editor->objectEditAction = Editor::EditAction::Move;
|
||||
editor->eventEditAction = Editor::EditAction::Move;
|
||||
|
||||
editor->settings->mapCursor = QCursor(QPixmap(":/icons/move.ico"), 7, 7);
|
||||
editor->cursorMapTileRect->setSingleTileMode();
|
||||
@@ -2343,7 +2348,7 @@ void MainWindow::on_toolButton_Shift_clicked()
|
||||
if (ui->mainTabBar->currentIndex() == MainTab::Map)
|
||||
editor->mapEditAction = Editor::EditAction::Shift;
|
||||
else
|
||||
editor->objectEditAction = Editor::EditAction::Shift;
|
||||
editor->eventEditAction = Editor::EditAction::Shift;
|
||||
|
||||
editor->settings->mapCursor = QCursor(QPixmap(":/icons/shift_cursor.ico"), 10, 10);
|
||||
editor->cursorMapTileRect->setSingleTileMode();
|
||||
@@ -2362,7 +2367,7 @@ void MainWindow::checkToolButtons() {
|
||||
if (ui->mainTabBar->currentIndex() == MainTab::Map) {
|
||||
editAction = editor->mapEditAction;
|
||||
} else {
|
||||
editAction = editor->objectEditAction;
|
||||
editAction = editor->eventEditAction;
|
||||
if (editAction == Editor::EditAction::Select && editor->map_ruler)
|
||||
editor->map_ruler->setEnabled(true);
|
||||
else if (editor->map_ruler)
|
||||
@@ -2589,87 +2594,39 @@ void MainWindow::on_comboBox_SecondaryTileset_currentTextChanged(const QString &
|
||||
void MainWindow::on_pushButton_ChangeDimensions_clicked() {
|
||||
if (!editor || !editor->layout) return;
|
||||
|
||||
QDialog dialog(this, Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
|
||||
dialog.setWindowTitle("Change Map Dimensions");
|
||||
dialog.setWindowModality(Qt::NonModal);
|
||||
ResizeLayoutPopup popup(this->ui->graphicsView_Map, this->editor);
|
||||
popup.show();
|
||||
popup.setupLayoutView();
|
||||
if (popup.exec() == QDialog::Accepted) {
|
||||
Layout *layout = this->editor->layout;
|
||||
Map *map = this->editor->map;
|
||||
|
||||
QFormLayout form(&dialog);
|
||||
|
||||
QSpinBox *widthSpinBox = new QSpinBox();
|
||||
QSpinBox *heightSpinBox = new QSpinBox();
|
||||
QSpinBox *bwidthSpinBox = new QSpinBox();
|
||||
QSpinBox *bheightSpinBox = new QSpinBox();
|
||||
widthSpinBox->setMinimum(1);
|
||||
heightSpinBox->setMinimum(1);
|
||||
bwidthSpinBox->setMinimum(1);
|
||||
bheightSpinBox->setMinimum(1);
|
||||
widthSpinBox->setMaximum(editor->project->getMaxMapWidth());
|
||||
heightSpinBox->setMaximum(editor->project->getMaxMapHeight());
|
||||
bwidthSpinBox->setMaximum(MAX_BORDER_WIDTH);
|
||||
bheightSpinBox->setMaximum(MAX_BORDER_HEIGHT);
|
||||
widthSpinBox->setValue(editor->layout->getWidth());
|
||||
heightSpinBox->setValue(editor->layout->getHeight());
|
||||
bwidthSpinBox->setValue(editor->layout->getBorderWidth());
|
||||
bheightSpinBox->setValue(editor->layout->getBorderHeight());
|
||||
if (projectConfig.useCustomBorderSize) {
|
||||
form.addRow(new QLabel("Map Width"), widthSpinBox);
|
||||
form.addRow(new QLabel("Map Height"), heightSpinBox);
|
||||
form.addRow(new QLabel("Border Width"), bwidthSpinBox);
|
||||
form.addRow(new QLabel("Border Height"), bheightSpinBox);
|
||||
} else {
|
||||
form.addRow(new QLabel("Width"), widthSpinBox);
|
||||
form.addRow(new QLabel("Height"), heightSpinBox);
|
||||
}
|
||||
|
||||
QLabel *errorLabel = new QLabel();
|
||||
errorLabel->setStyleSheet("QLabel { color: red }");
|
||||
errorLabel->setVisible(false);
|
||||
|
||||
QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog);
|
||||
form.addRow(&buttonBox);
|
||||
connect(&buttonBox, &QDialogButtonBox::accepted, [&dialog, &widthSpinBox, &heightSpinBox, &errorLabel, this](){
|
||||
// Ensure width and height are an acceptable size.
|
||||
// The maximum number of metatiles in a map is the following:
|
||||
// max = (width + 15) * (height + 14)
|
||||
// This limit can be found in fieldmap.c in pokeruby/pokeemerald/pokefirered.
|
||||
int numMetatiles = editor->project->getMapDataSize(widthSpinBox->value(), heightSpinBox->value());
|
||||
int maxMetatiles = editor->project->getMaxMapDataSize();
|
||||
if (numMetatiles <= maxMetatiles) {
|
||||
dialog.accept();
|
||||
} else {
|
||||
QString errorText = QString("Error: The specified width and height are too large.\n"
|
||||
"The maximum layout width and height is the following: (width + 15) * (height + 14) <= %1\n"
|
||||
"The specified layout width and height was: (%2 + 15) * (%3 + 14) = %4")
|
||||
.arg(maxMetatiles)
|
||||
.arg(widthSpinBox->value())
|
||||
.arg(heightSpinBox->value())
|
||||
.arg(numMetatiles);
|
||||
errorLabel->setText(errorText);
|
||||
errorLabel->setVisible(true);
|
||||
}
|
||||
});
|
||||
connect(&buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
|
||||
|
||||
form.addRow(errorLabel);
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
Layout *layout = editor->layout;
|
||||
Blockdata oldMetatiles = layout->blockdata;
|
||||
Blockdata oldBorder = layout->border;
|
||||
QSize oldMapDimensions(layout->getWidth(), layout->getHeight());
|
||||
QMargins result = popup.getResult();
|
||||
QSize borderResult = popup.getBorderResult();
|
||||
QSize oldLayoutDimensions(layout->getWidth(), layout->getHeight());
|
||||
QSize oldBorderDimensions(layout->getBorderWidth(), layout->getBorderHeight());
|
||||
QSize newMapDimensions(widthSpinBox->value(), heightSpinBox->value());
|
||||
QSize newBorderDimensions(bwidthSpinBox->value(), bheightSpinBox->value());
|
||||
if (oldMapDimensions != newMapDimensions || oldBorderDimensions != newBorderDimensions) {
|
||||
layout->setDimensions(newMapDimensions.width(), newMapDimensions.height(), true, true);
|
||||
layout->setBorderDimensions(newBorderDimensions.width(), newBorderDimensions.height(), true, true);
|
||||
editor->layout->editHistory.push(new ResizeLayout(layout,
|
||||
oldMapDimensions, newMapDimensions,
|
||||
if (!result.isNull() || (borderResult != oldBorderDimensions)) {
|
||||
Blockdata oldMetatiles = layout->blockdata;
|
||||
Blockdata oldBorder = layout->border;
|
||||
|
||||
layout->adjustDimensions(result);
|
||||
layout->setBorderDimensions(borderResult.width(), borderResult.height(), true, true);
|
||||
layout->editHistory.push(new ResizeLayout(layout,
|
||||
oldLayoutDimensions, result,
|
||||
oldMetatiles, layout->blockdata,
|
||||
oldBorderDimensions, newBorderDimensions,
|
||||
oldBorderDimensions, borderResult,
|
||||
oldBorder, layout->border
|
||||
));
|
||||
}
|
||||
// If we're in map-editing mode, adjust the events' position by the same amount.
|
||||
if (map) {
|
||||
auto events = map->getEvents();
|
||||
int deltaX = result.left();
|
||||
int deltaY = result.top();
|
||||
if ((deltaX || deltaY) && !events.isEmpty()) {
|
||||
map->commit(new EventShift(events, deltaX, deltaY, this->editor->eventShiftActionId++));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2848,8 +2805,15 @@ void MainWindow::reloadScriptEngine() {
|
||||
Scripting::populateGlobalObject(this);
|
||||
// Lying to the scripts here, simulating a project reload
|
||||
Scripting::cb_ProjectOpened(projectConfig.projectDir);
|
||||
if (editor && editor->map)
|
||||
Scripting::cb_MapOpened(editor->map->name()); // TODO: API should have equivalent for layout
|
||||
if (this->editor) {
|
||||
QString curName;
|
||||
if (this->editor->map)
|
||||
curName = this->editor->map->name();
|
||||
else if (editor->layout)
|
||||
curName = this->editor->layout->name;
|
||||
|
||||
Scripting::cb_MapOpened(curName);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_horizontalSlider_MetatileZoom_valueChanged(int value) {
|
||||
|
||||
@@ -398,6 +398,7 @@ Map *Project::createNewMap(const Project::NewMapSettings &settings, const Map* t
|
||||
this->mapNameToMapSectionName.insert(map->name(), map->header()->location());
|
||||
|
||||
map->setIsPersistedToFile(false);
|
||||
this->mapCache.insert(map->name(), map);
|
||||
|
||||
emit mapCreated(map, settings.group);
|
||||
|
||||
@@ -966,7 +967,7 @@ bool Project::loadLayoutTilesets(Layout *layout) {
|
||||
layout->tileset_primary = getTileset(layout->tileset_primary_label);
|
||||
if (!layout->tileset_primary) {
|
||||
QString defaultTileset = this->getDefaultPrimaryTilesetLabel();
|
||||
logWarn(QString("Map layout %1 has invalid primary tileset '%2'. Using default '%3'").arg(layout->id).arg(layout->tileset_primary_label).arg(defaultTileset));
|
||||
logWarn(QString("%1 has invalid primary tileset '%2'. Using default '%3'").arg(layout->name).arg(layout->tileset_primary_label).arg(defaultTileset));
|
||||
layout->tileset_primary_label = defaultTileset;
|
||||
layout->tileset_primary = getTileset(layout->tileset_primary_label);
|
||||
if (!layout->tileset_primary) {
|
||||
@@ -978,7 +979,7 @@ bool Project::loadLayoutTilesets(Layout *layout) {
|
||||
layout->tileset_secondary = getTileset(layout->tileset_secondary_label);
|
||||
if (!layout->tileset_secondary) {
|
||||
QString defaultTileset = this->getDefaultSecondaryTilesetLabel();
|
||||
logWarn(QString("Map layout %1 has invalid secondary tileset '%2'. Using default '%3'").arg(layout->id).arg(layout->tileset_secondary_label).arg(defaultTileset));
|
||||
logWarn(QString("%1 has invalid secondary tileset '%2'. Using default '%3'").arg(layout->name).arg(layout->tileset_secondary_label).arg(defaultTileset));
|
||||
layout->tileset_secondary_label = defaultTileset;
|
||||
layout->tileset_secondary = getTileset(layout->tileset_secondary_label);
|
||||
if (!layout->tileset_secondary) {
|
||||
@@ -1047,7 +1048,8 @@ bool Project::loadBlockdata(Layout *layout) {
|
||||
layout->lastCommitBlocks.layoutDimensions = QSize(layout->getWidth(), layout->getHeight());
|
||||
|
||||
if (layout->blockdata.count() != layout->getWidth() * layout->getHeight()) {
|
||||
logWarn(QString("Layout blockdata length %1 does not match dimensions %2x%3 (should be %4). Resizing blockdata.")
|
||||
logWarn(QString("%1 blockdata length %2 does not match dimensions %3x%4 (should be %5). Resizing blockdata.")
|
||||
.arg(layout->name)
|
||||
.arg(layout->blockdata.count())
|
||||
.arg(layout->getWidth())
|
||||
.arg(layout->getHeight())
|
||||
@@ -1084,7 +1086,8 @@ bool Project::loadLayoutBorder(Layout *layout) {
|
||||
|
||||
int borderLength = layout->getBorderWidth() * layout->getBorderHeight();
|
||||
if (layout->border.count() != borderLength) {
|
||||
logWarn(QString("Layout border blockdata length %1 must be %2. Resizing border blockdata.")
|
||||
logWarn(QString("%1 border blockdata length %2 must be %3. Resizing border blockdata.")
|
||||
.arg(layout->name)
|
||||
.arg(layout->border.count())
|
||||
.arg(borderLength));
|
||||
layout->border.resize(borderLength);
|
||||
@@ -1207,7 +1210,7 @@ void Project::saveMap(Map *map) {
|
||||
}
|
||||
mapObj["connections"] = connectionsArr;
|
||||
} else {
|
||||
mapObj["connections"] = QJsonValue::Null;
|
||||
mapObj["connections"] = OrderedJson();
|
||||
}
|
||||
|
||||
if (map->sharedEventsMap().isEmpty()) {
|
||||
|
||||
@@ -794,7 +794,7 @@ void MainWindow::setMetatileTile(int metatileId, int tileIndex, QJSValue tileObj
|
||||
}
|
||||
|
||||
QJSValue MainWindow::getTilePixels(int tileId) {
|
||||
if (tileId < 0 || !this->editor || !this->editor->project || !this->editor->map || !this->editor->layout)
|
||||
if (tileId < 0 || !this->editor || !this->editor->layout)
|
||||
return QJSValue();
|
||||
QImage tileImage = getTileImage(tileId, this->editor->layout->tileset_primary, this->editor->layout->tileset_secondary);
|
||||
if (tileImage.isNull() || tileImage.sizeInBytes() < 64)
|
||||
|
||||
@@ -249,6 +249,27 @@ QList<QString> ScriptUtility::getMapNames() {
|
||||
return window->editor->project->mapNames;
|
||||
}
|
||||
|
||||
QList<QString> ScriptUtility::getMapConstants() {
|
||||
if (!window || !window->editor || !window->editor->project)
|
||||
return QList<QString>();
|
||||
return window->editor->project->mapConstantsToMapNames.keys();
|
||||
}
|
||||
|
||||
QList<QString> ScriptUtility::getLayoutNames() {
|
||||
QList<QString> names;
|
||||
if (!window || !window->editor || !window->editor->project)
|
||||
return names;
|
||||
for (const auto &layout : window->editor->project->mapLayouts)
|
||||
names.append(layout->name);
|
||||
return names;
|
||||
}
|
||||
|
||||
QList<QString> ScriptUtility::getLayoutConstants() {
|
||||
if (!window || !window->editor || !window->editor->project)
|
||||
return QList<QString>();
|
||||
return window->editor->project->layoutIds;
|
||||
}
|
||||
|
||||
QList<QString> ScriptUtility::getTilesetNames() {
|
||||
if (!window || !window->editor || !window->editor->project)
|
||||
return QList<QString>();
|
||||
|
||||
@@ -29,7 +29,7 @@ void DraggablePixmapItem::emitPositionChanged() {
|
||||
void DraggablePixmapItem::updatePixmap() {
|
||||
editor->project->setEventPixmap(event, true);
|
||||
this->updatePosition();
|
||||
editor->redrawObject(this);
|
||||
editor->redrawEventPixmapItem(this);
|
||||
emit spriteChanged(event->getPixmap());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
#include "filterchildrenproxymodel.h"
|
||||
|
||||
FilterChildrenProxyModel::FilterChildrenProxyModel(QObject *parent) :
|
||||
QSortFilterProxyModel(parent)
|
||||
{
|
||||
|
||||
}
|
||||
#include <QCollator>
|
||||
|
||||
bool FilterChildrenProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
||||
{
|
||||
@@ -42,3 +38,16 @@ bool FilterChildrenProxyModel::filterAcceptsRow(int source_row, const QModelInde
|
||||
// parent call for initial behaviour
|
||||
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
|
||||
}
|
||||
|
||||
bool NumericSortProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const {
|
||||
QVariant l = (source_left.model() ? source_left.model()->data(source_left, sortRole()) : QVariant());
|
||||
QVariant r = (source_right.model() ? source_right.model()->data(source_right, sortRole()) : QVariant());
|
||||
|
||||
if (l.canConvert<QString>() && r.canConvert<QString>()) {
|
||||
// We need to override lexical comparison of strings to do a numeric sort.
|
||||
QCollator collator;
|
||||
collator.setNumericMode(true);
|
||||
return collator.compare(l.toString(), r.toString()) < 0;
|
||||
}
|
||||
return QSortFilterProxyModel::lessThan(source_left, source_right);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
void GraphicsView::mousePressEvent(QMouseEvent *event) {
|
||||
QGraphicsView::mousePressEvent(event);
|
||||
if (editor) {
|
||||
editor->objectsView_onMousePress(event);
|
||||
editor->eventsView_onMousePress(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,12 @@ MapImageExporter::MapImageExporter(QWidget *parent, Editor *editor, ImageExporte
|
||||
ui->comboBox_MapSelection->addItems(editor->project->mapNames);
|
||||
ui->comboBox_MapSelection->setCurrentText(m_map->name());
|
||||
ui->comboBox_MapSelection->setEnabled(false);// TODO: allow selecting map from drop-down
|
||||
} else {
|
||||
// Some settings only apply to maps. When exporting an image in layout-only mode we hide them.
|
||||
ui->comboBox_MapSelection->setVisible(false);
|
||||
ui->label_MapSelection->setVisible(false);
|
||||
ui->groupBox_Events->setVisible(false);
|
||||
ui->groupBox_Connections->setVisible(false);
|
||||
}
|
||||
|
||||
connect(ui->pushButton_Save, &QPushButton::pressed, this, &MapImageExporter::saveImage);
|
||||
|
||||
@@ -135,9 +135,6 @@ QStandardItem *MapListModel::insertMapItem(const QString &mapName, const QString
|
||||
if (folder) {
|
||||
folder->appendRow(map);
|
||||
}
|
||||
|
||||
if (this->sortingEnabled)
|
||||
this->sort(0, Qt::AscendingOrder);
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -147,8 +144,6 @@ QStandardItem *MapListModel::insertMapFolderItem(const QString &folderName) {
|
||||
|
||||
QStandardItem *item = createMapFolderItem(folderName);
|
||||
this->root->appendRow(item);
|
||||
if (this->sortingEnabled)
|
||||
this->sort(0, Qt::AscendingOrder);
|
||||
return item;
|
||||
}
|
||||
|
||||
@@ -432,9 +427,6 @@ MapLocationModel::MapLocationModel(Project *project, QObject *parent) : MapListM
|
||||
for (const auto &mapName : this->project->mapNames) {
|
||||
insertMapItem(mapName, this->project->mapNameToMapSectionName.value(mapName));
|
||||
}
|
||||
|
||||
this->sortingEnabled = true;
|
||||
sort(0, Qt::AscendingOrder);
|
||||
}
|
||||
|
||||
void MapLocationModel::removeItem(QStandardItem *item) {
|
||||
@@ -459,9 +451,6 @@ LayoutTreeModel::LayoutTreeModel(Project *project, QObject *parent) : MapListMod
|
||||
for (const auto &mapName : this->project->mapNames) {
|
||||
insertMapItem(mapName, this->project->mapNameToLayoutId.value(mapName));
|
||||
}
|
||||
|
||||
this->sortingEnabled = true;
|
||||
sort(0, Qt::AscendingOrder);
|
||||
}
|
||||
|
||||
void LayoutTreeModel::removeItem(QStandardItem *) {
|
||||
|
||||
@@ -139,3 +139,7 @@ void MapListToolBar::applyFilter(const QString &filterText) {
|
||||
void MapListToolBar::clearFilter() {
|
||||
applyFilter("");
|
||||
}
|
||||
|
||||
void MapListToolBar::setSearchFocus() {
|
||||
ui->lineEdit_filterBox->setFocus();
|
||||
}
|
||||
|
||||
@@ -9,12 +9,17 @@ QPoint MetatileSelector::getSelectionDimensions() {
|
||||
return SelectablePixmapItem::getSelectionDimensions();
|
||||
}
|
||||
|
||||
int MetatileSelector::numPrimaryMetatilesRounded() const {
|
||||
// We round up the number of primary metatiles to keep the tilesets on separate rows.
|
||||
return ceil((double)this->primaryTileset->numMetatiles() / this->numMetatilesWide) * this->numMetatilesWide;
|
||||
}
|
||||
|
||||
void MetatileSelector::draw() {
|
||||
if (!this->primaryTileset || !this->secondaryTileset) {
|
||||
this->setPixmap(QPixmap());
|
||||
}
|
||||
|
||||
int primaryLength = this->primaryTileset->numMetatiles();
|
||||
int primaryLength = this->numPrimaryMetatilesRounded();
|
||||
int length_ = primaryLength + this->secondaryTileset->numMetatiles();
|
||||
int height_ = length_ / this->numMetatilesWide;
|
||||
if (length_ % this->numMetatilesWide != 0) {
|
||||
@@ -149,7 +154,7 @@ void MetatileSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
|
||||
|
||||
void MetatileSelector::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
if (!positionIsValid(pos) || this->cellPos == pos)
|
||||
if (this->cellPos == pos)
|
||||
return;
|
||||
|
||||
this->cellPos = pos;
|
||||
@@ -199,10 +204,11 @@ void MetatileSelector::updateExternalSelectedMetatiles() {
|
||||
|
||||
uint16_t MetatileSelector::getMetatileId(int x, int y) const {
|
||||
int index = y * this->numMetatilesWide + x;
|
||||
if (index < this->primaryTileset->numMetatiles()) {
|
||||
int numPrimary = this->numPrimaryMetatilesRounded();
|
||||
if (index < numPrimary) {
|
||||
return static_cast<uint16_t>(index);
|
||||
} else {
|
||||
return static_cast<uint16_t>(Project::getNumMetatilesPrimary() + index - this->primaryTileset->numMetatiles());
|
||||
return static_cast<uint16_t>(Project::getNumMetatilesPrimary() + index - numPrimary);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,7 +221,7 @@ QPoint MetatileSelector::getMetatileIdCoords(uint16_t metatileId) {
|
||||
|
||||
int index = metatileId < Project::getNumMetatilesPrimary()
|
||||
? metatileId
|
||||
: metatileId - Project::getNumMetatilesPrimary() + this->primaryTileset->numMetatiles();
|
||||
: metatileId - Project::getNumMetatilesPrimary() + this->numPrimaryMetatilesRounded();
|
||||
return QPoint(index % this->numMetatilesWide, index / this->numMetatilesWide);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,175 @@
|
||||
#include <QCursor>
|
||||
#include <QGraphicsSceneHoverEvent>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "movablerect.h"
|
||||
|
||||
MovableRect::MovableRect(bool *enabled, int width, int height, QRgb color)
|
||||
: QGraphicsRectItem(0, 0, width, height)
|
||||
{
|
||||
this->enabled = enabled;
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
this->color = color;
|
||||
this->setVisible(*enabled);
|
||||
}
|
||||
|
||||
void MovableRect::updateLocation(int x, int y)
|
||||
{
|
||||
this->setX((x * 16) - this->width / 2 + 8);
|
||||
this->setY((y * 16) - this->height / 2 + 8);
|
||||
/// Center rect on grid position (x, y)
|
||||
void MovableRect::updateLocation(int x, int y) {
|
||||
this->setRect((x * 16) - this->rect().width() / 2 + 8, (y * 16) - this->rect().height() / 2 + 8, this->rect().width(), this->rect().height());
|
||||
this->setVisible(*this->enabled);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
int roundUp(int numToRound, int multiple) {
|
||||
return (numToRound + multiple - 1) & -multiple;
|
||||
}
|
||||
|
||||
ResizableRect::ResizableRect(QObject *parent, bool *enabled, int width, int height, QRgb color)
|
||||
: QObject(parent),
|
||||
MovableRect(enabled, width * 16, height * 16, color)
|
||||
{
|
||||
setZValue(0xFFFFFFFF); // ensure on top of view
|
||||
setAcceptHoverEvents(true);
|
||||
setFlags(this->flags() | QGraphicsItem::ItemIsMovable);
|
||||
}
|
||||
|
||||
ResizableRect::Edge ResizableRect::detectEdge(int x, int y) {
|
||||
QRectF edge = this->boundingRect();
|
||||
if (x <= edge.left() + this->lineWidth) {
|
||||
if (y >= edge.top() + 2 * this->lineWidth) {
|
||||
if (y <= edge.bottom() - 2 * this->lineWidth) {
|
||||
return ResizableRect::Edge::Left;
|
||||
}
|
||||
else {
|
||||
return ResizableRect::Edge::BottomLeft;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return ResizableRect::Edge::TopLeft;
|
||||
}
|
||||
}
|
||||
else if (x >= edge.right() - this->lineWidth) {
|
||||
if (y >= edge.top() + 2 * this->lineWidth) {
|
||||
if (y <= edge.bottom() - 2 * this->lineWidth) {
|
||||
return ResizableRect::Edge::Right;
|
||||
}
|
||||
else {
|
||||
return ResizableRect::Edge::BottomRight;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return ResizableRect::Edge::TopRight;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (y <= edge.top() + this->lineWidth) {
|
||||
return ResizableRect::Edge::Top;
|
||||
}
|
||||
else if (y >= edge.bottom() - this->lineWidth) {
|
||||
return ResizableRect::Edge::Bottom;
|
||||
}
|
||||
}
|
||||
return ResizableRect::Edge::None;
|
||||
}
|
||||
|
||||
void ResizableRect::updatePosFromRect(QRect newRect) {
|
||||
prepareGeometryChange();
|
||||
this->setRect(newRect);
|
||||
emit this->rectUpdated(newRect);
|
||||
}
|
||||
|
||||
void ResizableRect::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
|
||||
switch (this->detectEdge(event->pos().x(), event->pos().y())) {
|
||||
case ResizableRect::Edge::None:
|
||||
default:
|
||||
break;
|
||||
case ResizableRect::Edge::Left:
|
||||
case ResizableRect::Edge::Right:
|
||||
this->setCursor(Qt::SizeHorCursor);
|
||||
break;
|
||||
case ResizableRect::Edge::Top:
|
||||
case ResizableRect::Edge::Bottom:
|
||||
this->setCursor(Qt::SizeVerCursor);
|
||||
break;
|
||||
case ResizableRect::Edge::TopRight:
|
||||
case ResizableRect::Edge::BottomLeft:
|
||||
this->setCursor(Qt::SizeBDiagCursor);
|
||||
break;
|
||||
case ResizableRect::Edge::TopLeft:
|
||||
case ResizableRect::Edge::BottomRight:
|
||||
this->setCursor(Qt::SizeFDiagCursor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ResizableRect::hoverLeaveEvent(QGraphicsSceneHoverEvent *) {
|
||||
this->unsetCursor();
|
||||
}
|
||||
|
||||
void ResizableRect::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||
int x = event->pos().x();
|
||||
int y = event->pos().y();
|
||||
this->clickedPos = event->scenePos();
|
||||
this->clickedRect = this->rect().toAlignedRect();
|
||||
this->clickedEdge = this->detectEdge(x, y);
|
||||
}
|
||||
|
||||
void ResizableRect::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
|
||||
int dx = roundUp(event->scenePos().x() - this->clickedPos.x(), 16);
|
||||
int dy = roundUp(event->scenePos().y() - this->clickedPos.y(), 16);
|
||||
|
||||
QRect resizedRect = this->clickedRect;
|
||||
|
||||
switch (this->clickedEdge) {
|
||||
case ResizableRect::Edge::None:
|
||||
default:
|
||||
return;
|
||||
case ResizableRect::Edge::Left:
|
||||
resizedRect.adjust(dx, 0, 0, 0);
|
||||
break;
|
||||
case ResizableRect::Edge::Right:
|
||||
resizedRect.adjust(0, 0, dx, 0);
|
||||
break;
|
||||
case ResizableRect::Edge::Top:
|
||||
resizedRect.adjust(0, dy, 0, 0);
|
||||
break;
|
||||
case ResizableRect::Edge::Bottom:
|
||||
resizedRect.adjust(0, 0, 0, dy);
|
||||
break;
|
||||
case ResizableRect::Edge::TopRight:
|
||||
resizedRect.adjust(0, dy, dx, 0);
|
||||
break;
|
||||
case ResizableRect::Edge::BottomLeft:
|
||||
resizedRect.adjust(dx, 0, 0, dy);
|
||||
break;
|
||||
case ResizableRect::Edge::TopLeft:
|
||||
resizedRect.adjust(dx, dy, 0, 0);
|
||||
break;
|
||||
case ResizableRect::Edge::BottomRight:
|
||||
resizedRect.adjust(0, 0, dx, dy);
|
||||
break;
|
||||
}
|
||||
|
||||
// Lower limits: smallest possible size is 16x16 square
|
||||
if (resizedRect.width() < 16) {
|
||||
if (dx < 0) { // right sided adjustment made
|
||||
resizedRect.setWidth(16);
|
||||
} else { // left sided adjustment slightly more complicated
|
||||
int dxMax = this->clickedRect.right() - this->clickedRect.left() - 16;
|
||||
resizedRect.adjust(dxMax - dx, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
if (resizedRect.height() < 16) {
|
||||
if (dy < 0) { // bottom
|
||||
resizedRect.setHeight(16);
|
||||
} else { // top
|
||||
int dyMax = this->clickedRect.bottom() - this->clickedRect.top() - 16;
|
||||
resizedRect.adjust(0, dyMax - dy, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Upper limits: clip resized to limit rect
|
||||
this->updatePosFromRect(resizedRect & this->limit);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ void NewEventToolButton::init()
|
||||
this->newSecretBaseAction->setIcon(QIcon(":/icons/add.ico"));
|
||||
connect(this->newSecretBaseAction, &QAction::triggered, this, &NewEventToolButton::newSecretBase);
|
||||
|
||||
QMenu *alignMenu = new QMenu();
|
||||
QMenu *alignMenu = new QMenu(this);
|
||||
alignMenu->addAction(this->newObjectAction);
|
||||
alignMenu->addAction(this->newCloneObjectAction);
|
||||
alignMenu->addAction(this->newWarpAction);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "noscrollspinbox.h"
|
||||
#include <QWheelEvent>
|
||||
#include <QLineEdit>
|
||||
|
||||
unsigned actionId = 0xffff;
|
||||
|
||||
@@ -25,6 +26,10 @@ void NoScrollSpinBox::focusOutEvent(QFocusEvent *event) {
|
||||
QSpinBox::focusOutEvent(event);
|
||||
}
|
||||
|
||||
void NoScrollSpinBox::setLineEditEnabled(bool enabled) {
|
||||
this->lineEdit()->setReadOnly(!enabled);
|
||||
}
|
||||
|
||||
unsigned NoScrollSpinBox::getActionId() {
|
||||
return actionId;
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ void ProjectSettingsEditor::initUi() {
|
||||
// Validate that the border metatiles text is a comma-separated list of metatile values
|
||||
static const QString regex_Hex = "(0[xX])?[A-Fa-f0-9]+";
|
||||
static const QRegularExpression expression_HexList(QString("^(%1,)*%1$").arg(regex_Hex)); // Comma-separated list of hex values
|
||||
QRegularExpressionValidator *validator_HexList = new QRegularExpressionValidator(expression_HexList);
|
||||
QRegularExpressionValidator *validator_HexList = new QRegularExpressionValidator(expression_HexList, this);
|
||||
ui->lineEdit_BorderMetatiles->setValidator(validator_HexList);
|
||||
this->setBorderMetatilesUi(projectConfig.useCustomBorderSize);
|
||||
|
||||
|
||||
210
src/ui/resizelayoutpopup.cpp
Normal file
210
src/ui/resizelayoutpopup.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
#include "resizelayoutpopup.h"
|
||||
#include "editor.h"
|
||||
#include "movablerect.h"
|
||||
#include "config.h"
|
||||
|
||||
#include "ui_resizelayoutpopup.h"
|
||||
|
||||
// TODO: put this in a util file or something
|
||||
extern int roundUp(int, int);
|
||||
|
||||
CheckeredBgScene::CheckeredBgScene(QObject *parent) : QGraphicsScene(parent) { }
|
||||
|
||||
void CheckeredBgScene::drawBackground(QPainter *painter, const QRectF &rect) {
|
||||
QRect r = rect.toRect();
|
||||
int xMin = r.left() - r.left() % this->gridSize - this->gridSize;
|
||||
int yMin = r.top() - r.top() % this->gridSize - this->gridSize;
|
||||
int xMax = r.right() - r.right() % this->gridSize + this->gridSize;
|
||||
int yMax = r.bottom() - r.bottom() % this->gridSize + this->gridSize;
|
||||
|
||||
// draw grid 16x16 from top to bottom of scene
|
||||
QColor paintColor(0x00ff00);
|
||||
for (int x = xMin, xTile = 0; x <= xMax; x += this->gridSize, xTile++) {
|
||||
for (int y = yMin, yTile = 0; y <= yMax; y += this->gridSize, yTile++) {
|
||||
if (!((xTile ^ yTile) & 1)) { // tile numbers have same parity (evenness)
|
||||
if (this->validRect.contains(x, y))
|
||||
paintColor = QColor(132, 217, 165); // green light color
|
||||
else
|
||||
paintColor = 0xbcbcbc; // normal light color
|
||||
}
|
||||
else {
|
||||
if (this->validRect.contains(x, y))
|
||||
paintColor = QColor(76, 178, 121); // green dark color
|
||||
else
|
||||
paintColor = 0x969696; // normal dark color
|
||||
}
|
||||
painter->fillRect(QRect(x, y, this->gridSize, this->gridSize), paintColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
BoundedPixmapItem::BoundedPixmapItem(const QPixmap &pixmap, QGraphicsItem *parent) : QGraphicsPixmapItem(pixmap, parent) {
|
||||
setFlags(this->flags() | QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemSendsGeometryChanges | QGraphicsItem::ItemIsSelectable);
|
||||
}
|
||||
|
||||
void BoundedPixmapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) {
|
||||
// Draw the pixmap darkened in the background
|
||||
painter->fillRect(this->boundingRect().toAlignedRect(), QColor(0x444444));
|
||||
painter->setCompositionMode(QPainter::CompositionMode_Multiply);
|
||||
painter->drawPixmap(this->boundingRect().toAlignedRect(), this->pixmap());
|
||||
|
||||
// draw the normal pixmap on top, cropping to validRect as needed
|
||||
painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
|
||||
QRect intersection = this->mapRectFromScene(this->boundary->rect()).toAlignedRect() & this->boundingRect().toAlignedRect();
|
||||
QPixmap cropped = this->pixmap().copy(intersection);
|
||||
painter->drawPixmap(intersection, cropped);
|
||||
}
|
||||
|
||||
QVariant BoundedPixmapItem::itemChange(GraphicsItemChange change, const QVariant &value) {
|
||||
if (change == ItemPositionChange && scene()) {
|
||||
QPointF newPos = value.toPointF();
|
||||
return QPointF(roundUp(newPos.x(), 16), roundUp(newPos.y(), 16));
|
||||
}
|
||||
else
|
||||
return QGraphicsItem::itemChange(change, value);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
************************************************************************
|
||||
******************************************************************************/
|
||||
|
||||
ResizeLayoutPopup::ResizeLayoutPopup(QWidget *parent, Editor *editor) :
|
||||
QDialog(parent),
|
||||
parent(parent),
|
||||
editor(editor),
|
||||
ui(new Ui::ResizeLayoutPopup)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
this->resetPosition();
|
||||
this->setWindowFlags(this->windowFlags() | Qt::FramelessWindowHint);
|
||||
this->setWindowModality(Qt::ApplicationModal);
|
||||
|
||||
this->scene = new CheckeredBgScene(this);
|
||||
this->ui->graphicsView->setScene(this->scene);
|
||||
this->ui->graphicsView->setRenderHints(QPainter::Antialiasing);
|
||||
this->ui->graphicsView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
|
||||
}
|
||||
|
||||
ResizeLayoutPopup::~ResizeLayoutPopup() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
/// Reset position of the dialog to cover the MainWindow's layout metatile scene
|
||||
void ResizeLayoutPopup::resetPosition() {
|
||||
this->setGeometry(QRect(parent->mapToGlobal(QPoint(0, 0)), parent->size()));
|
||||
}
|
||||
|
||||
void ResizeLayoutPopup::on_buttonBox_clicked(QAbstractButton *button) {
|
||||
if(button == this->ui->buttonBox->button(QDialogButtonBox::Reset) ) {
|
||||
this->scene->clear();
|
||||
setupLayoutView();
|
||||
}
|
||||
}
|
||||
|
||||
/// Custom scene contains
|
||||
/// (1) pixmap representing the current layout / not resizable / drag-movable
|
||||
/// (1) layout outline / resizable / not movable
|
||||
void ResizeLayoutPopup::setupLayoutView() {
|
||||
if (!this->editor || !this->editor->layout) return;
|
||||
|
||||
// Border stuff
|
||||
bool bordersEnabled = projectConfig.useCustomBorderSize;
|
||||
if (bordersEnabled) {
|
||||
this->ui->spinBox_borderWidth->setMinimum(1);
|
||||
this->ui->spinBox_borderHeight->setMinimum(1);
|
||||
this->ui->spinBox_borderWidth->setMaximum(MAX_BORDER_WIDTH);
|
||||
this->ui->spinBox_borderHeight->setMaximum(MAX_BORDER_HEIGHT);
|
||||
} else {
|
||||
this->ui->frame_border->setVisible(false);
|
||||
}
|
||||
this->ui->spinBox_borderWidth->setValue(this->editor->layout->getBorderWidth());
|
||||
this->ui->spinBox_borderHeight->setValue(this->editor->layout->getBorderHeight());
|
||||
|
||||
// Layout stuff
|
||||
QPixmap pixmap = this->editor->layout->pixmap;
|
||||
this->layoutPixmap = new BoundedPixmapItem(pixmap);
|
||||
this->scene->addItem(layoutPixmap);
|
||||
int maxWidth = this->editor->project->getMaxMapWidth();
|
||||
int maxHeight = this->editor->project->getMaxMapHeight();
|
||||
QGraphicsRectItem *cover = new QGraphicsRectItem(-maxWidth * 8, -maxHeight * 8, maxWidth * 16, maxHeight * 16);
|
||||
this->scene->addItem(cover);
|
||||
|
||||
this->ui->spinBox_width->setMinimum(1);
|
||||
this->ui->spinBox_width->setMaximum(maxWidth);
|
||||
this->ui->spinBox_height->setMinimum(1);
|
||||
this->ui->spinBox_height->setMaximum(maxHeight);
|
||||
|
||||
static bool layoutSizeRectVisible = true;
|
||||
|
||||
this->outline = new ResizableRect(this, &layoutSizeRectVisible, this->editor->layout->getWidth(), this->editor->layout->getHeight(), qRgb(255, 0, 255));
|
||||
this->outline->setLimit(cover->rect().toAlignedRect());
|
||||
connect(outline, &ResizableRect::rectUpdated, [=](QRect rect){
|
||||
// Note: this extra limit check needs access to the project values, so it is done here and not ResizableRect::mouseMoveEvent
|
||||
// Upper limits: maximum metatiles in a map formula:
|
||||
// max = (width + 15) * (height + 14)
|
||||
// This limit can be found in fieldmap.c in pokeruby/pokeemerald/pokefirered.
|
||||
int numMetatiles = editor->project->getMapDataSize(rect.width() / 16, rect.height() / 16);
|
||||
int maxMetatiles = editor->project->getMaxMapDataSize();
|
||||
if (numMetatiles > maxMetatiles) {
|
||||
QString errorText = QString("The maximum layout width and height is the following: (width + 15) * (height + 14) <= %1\n"
|
||||
"The specified layout width and height was: (%2 + 15) * (%3 + 14) = %4")
|
||||
.arg(maxMetatiles)
|
||||
.arg(rect.width() / 16)
|
||||
.arg(rect.height() / 16)
|
||||
.arg(numMetatiles);
|
||||
QMessageBox warning;
|
||||
warning.setIcon(QMessageBox::Warning);
|
||||
warning.setText("The specified width and height are too large.");
|
||||
warning.setInformativeText(errorText);
|
||||
warning.setStandardButtons(QMessageBox::Ok);
|
||||
warning.setDefaultButton(QMessageBox::Ok);
|
||||
warning.exec();
|
||||
// adjust rect to last accepted size
|
||||
rect = this->scene->getValidRect();
|
||||
}
|
||||
this->scene->setValidRect(rect);
|
||||
this->outline->setRect(rect);
|
||||
this->ui->spinBox_width->setValue(rect.width() / 16);
|
||||
this->ui->spinBox_height->setValue(rect.height() / 16);
|
||||
});
|
||||
scene->addItem(outline);
|
||||
|
||||
layoutPixmap->setBoundary(outline);
|
||||
this->outline->rectUpdated(outline->rect().toAlignedRect());
|
||||
|
||||
// TODO: is this an ideal size for all maps, or should this adjust based on starting dimensions?
|
||||
this->ui->graphicsView->setTransform(QTransform::fromScale(0.5, 0.5));
|
||||
this->ui->graphicsView->centerOn(layoutPixmap);
|
||||
}
|
||||
|
||||
void ResizeLayoutPopup::on_spinBox_width_valueChanged(int value) {
|
||||
if (!this->outline) return;
|
||||
QRectF rect = this->outline->rect();
|
||||
this->outline->updatePosFromRect(QRect(rect.x(), rect.y(), value * 16, rect.height()));
|
||||
}
|
||||
|
||||
void ResizeLayoutPopup::on_spinBox_height_valueChanged(int value) {
|
||||
if (!this->outline) return;
|
||||
QRectF rect = this->outline->rect();
|
||||
this->outline->updatePosFromRect(QRect(rect.x(), rect.y(), rect.width(), value * 16));
|
||||
}
|
||||
|
||||
/// Result is the number of metatiles to add (or subtract) to each side of the map after dimension changes
|
||||
QMargins ResizeLayoutPopup::getResult() {
|
||||
QMargins result = QMargins();
|
||||
|
||||
result.setLeft(this->layoutPixmap->x() - this->outline->rect().left());
|
||||
result.setTop(this->layoutPixmap->y() - this->outline->rect().top());
|
||||
result.setRight(this->outline->rect().right() - (this->layoutPixmap->x() + this->layoutPixmap->pixmap().width()));
|
||||
result.setBottom(this->outline->rect().bottom() - (this->layoutPixmap->y() + this->layoutPixmap->pixmap().height()));
|
||||
|
||||
return result / 16;
|
||||
}
|
||||
|
||||
QSize ResizeLayoutPopup::getBorderResult() {
|
||||
return QSize(this->ui->spinBox_borderWidth->value(), this->ui->spinBox_borderHeight->value());
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "ui_shortcutseditor.h"
|
||||
#include "config.h"
|
||||
#include "multikeyedit.h"
|
||||
#include "message.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <QGroupBox>
|
||||
@@ -46,6 +47,15 @@ void ShortcutsEditor::setShortcutableObjects(const QObjectList &shortcutableObje
|
||||
void ShortcutsEditor::saveShortcuts() {
|
||||
QMultiMap<const QObject *, QKeySequence> objects_keySequences;
|
||||
for (auto it = multiKeyEdits_objects.cbegin(); it != multiKeyEdits_objects.cend(); ++it) {
|
||||
if (!it.value()) {
|
||||
// Some shortcuts cannot be saved. Pointers in the object map can become null if they are
|
||||
// deleted externally while the shortcuts editor is open. Ideally we should try to restore
|
||||
// the original object so the shortcut can be saved. Alternatively this could generally be
|
||||
// prevented by making the shortcuts editor modal. For now, saving these shortcuts is skipped,
|
||||
// and we warn the user that this happened.
|
||||
ErrorMessage::show(QStringLiteral("Some shortcuts failed to save. Please close the Shortcuts Editor and retry."), this);
|
||||
return;
|
||||
}
|
||||
if (it.key()->keySequences().isEmpty())
|
||||
objects_keySequences.insert(it.value(), QKeySequence());
|
||||
for (auto keySequence : it.key()->keySequences())
|
||||
@@ -60,6 +70,7 @@ void ShortcutsEditor::saveShortcuts() {
|
||||
// Restores default shortcuts but doesn't save until Apply or OK is clicked.
|
||||
void ShortcutsEditor::resetShortcuts() {
|
||||
for (auto it = multiKeyEdits_objects.begin(); it != multiKeyEdits_objects.end(); ++it) {
|
||||
if (!it.value()) continue;
|
||||
it.key()->blockSignals(true);
|
||||
const auto defaults = shortcutsConfig.defaultShortcuts(it.value());
|
||||
it.key()->setKeySequences(defaults);
|
||||
@@ -90,6 +101,7 @@ bool ShortcutsEditor::stringPropertyIsNotEmpty(const QObject *object, const char
|
||||
|
||||
void ShortcutsEditor::populateMainContainer() {
|
||||
for (auto object : labels_objects) {
|
||||
if (!object) continue;
|
||||
const auto shortcutContext = getShortcutContext(object);
|
||||
if (!contexts_layouts.contains(shortcutContext))
|
||||
addNewContextGroup(shortcutContext);
|
||||
|
||||
@@ -29,13 +29,7 @@ TilesetEditor::TilesetEditor(Project *project, Layout *layout, QWidget *parent)
|
||||
this->tileYFlip = ui->checkBox_yFlip->isChecked();
|
||||
this->paletteId = ui->spinBox_paletteSelector->value();
|
||||
|
||||
// TODO: The dividing line at the moment is only accurate if the number of primary metatiles is divisible by 8.
|
||||
// If it's not, the secondary metatiles will wrap above the line. This has other problems (like skewing
|
||||
// metatile groups the user may have designed) so this should be fixed by filling the primary metatiles
|
||||
// image with invalid magenta metatiles until it's divisible by 8. Then the line can be re-enabled as-is.
|
||||
ui->actionShow_Tileset_Divider->setChecked(/*porymapConfig.showTilesetEditorDivider*/false);
|
||||
ui->actionShow_Tileset_Divider->setVisible(false);
|
||||
|
||||
ui->actionShow_Tileset_Divider->setChecked(porymapConfig.showTilesetEditorDivider);
|
||||
ui->spinBox_paletteSelector->setMinimum(0);
|
||||
ui->spinBox_paletteSelector->setMaximum(Project::getNumPalettesTotal() - 1);
|
||||
ui->lineEdit_metatileLabel->setValidator(new IdentifierValidator(this));
|
||||
@@ -759,7 +753,7 @@ void TilesetEditor::on_actionChange_Metatiles_Count_triggered()
|
||||
{
|
||||
QDialog dialog(this, Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
|
||||
dialog.setWindowTitle("Change Number of Metatiles");
|
||||
dialog.setWindowModality(Qt::NonModal);
|
||||
dialog.setWindowModality(Qt::WindowModal);
|
||||
|
||||
QFormLayout form(&dialog);
|
||||
|
||||
@@ -1051,20 +1045,19 @@ void TilesetEditor::countMetatileUsage() {
|
||||
// do not double count
|
||||
metatileSelector->usedMetatiles.fill(0);
|
||||
|
||||
for (auto layout : this->project->mapLayouts.values()) {
|
||||
bool usesPrimary = false;
|
||||
bool usesSecondary = false;
|
||||
for (auto layout : this->project->mapLayouts) {
|
||||
// It's possible for a layout's tileset labels to change if they are invalid,
|
||||
// so we need to load all the tilesets even if they aren't the tileset we're looking for.
|
||||
// Otherwise the metatile usage counts may change because the layouts with invalid tilesets
|
||||
// were updated to use a tileset we were looking for.
|
||||
this->project->loadLayoutTilesets(layout);
|
||||
|
||||
if (layout->tileset_primary_label == this->primaryTileset->name) {
|
||||
usesPrimary = true;
|
||||
}
|
||||
|
||||
if (layout->tileset_secondary_label == this->secondaryTileset->name) {
|
||||
usesSecondary = true;
|
||||
}
|
||||
bool usesPrimary = (layout->tileset_primary_label == this->primaryTileset->name);
|
||||
bool usesSecondary = (layout->tileset_secondary_label == this->secondaryTileset->name);
|
||||
|
||||
if (usesPrimary || usesSecondary) {
|
||||
this->project->loadLayout(layout);
|
||||
if (!this->project->loadLayout(layout))
|
||||
continue;
|
||||
|
||||
// for each block in the layout, mark in the vector that it is used
|
||||
for (int i = 0; i < layout->blockdata.length(); i++) {
|
||||
@@ -1097,9 +1090,9 @@ void TilesetEditor::countTileUsage() {
|
||||
QSet<Tileset*> secondaryTilesets;
|
||||
|
||||
for (auto layout : this->project->mapLayouts.values()) {
|
||||
this->project->loadLayoutTilesets(layout);
|
||||
if (layout->tileset_primary_label == this->primaryTileset->name
|
||||
|| layout->tileset_secondary_label == this->secondaryTileset->name) {
|
||||
this->project->loadLayoutTilesets(layout);
|
||||
// need to check metatiles
|
||||
if (layout->tileset_primary && layout->tileset_secondary) {
|
||||
primaryTilesets.insert(layout->tileset_primary);
|
||||
|
||||
@@ -22,11 +22,16 @@ int TilesetEditorMetatileSelector::numRows(int numMetatiles) {
|
||||
}
|
||||
|
||||
int TilesetEditorMetatileSelector::numRows() {
|
||||
return this->numRows(this->primaryTileset->numMetatiles() + this->secondaryTileset->numMetatiles());
|
||||
return this->numRows(this->numPrimaryMetatilesRounded() + this->secondaryTileset->numMetatiles());
|
||||
}
|
||||
|
||||
int TilesetEditorMetatileSelector::numPrimaryMetatilesRounded() const {
|
||||
// We round up the number of primary metatiles to keep the tilesets on separate rows.
|
||||
return ceil((double)this->primaryTileset->numMetatiles() / this->numMetatilesWide) * this->numMetatilesWide;
|
||||
}
|
||||
|
||||
QImage TilesetEditorMetatileSelector::buildAllMetatilesImage() {
|
||||
return this->buildImage(0, this->primaryTileset->numMetatiles() + this->secondaryTileset->numMetatiles());
|
||||
return this->buildImage(0, this->numPrimaryMetatilesRounded() + this->secondaryTileset->numMetatiles());
|
||||
}
|
||||
|
||||
QImage TilesetEditorMetatileSelector::buildPrimaryMetatilesImage() {
|
||||
@@ -39,11 +44,11 @@ QImage TilesetEditorMetatileSelector::buildSecondaryMetatilesImage() {
|
||||
|
||||
QImage TilesetEditorMetatileSelector::buildImage(int metatileIdStart, int numMetatiles) {
|
||||
int numMetatilesHigh = this->numRows(numMetatiles);
|
||||
int numPrimary = this->primaryTileset->numMetatiles();
|
||||
int numPrimary = this->numPrimaryMetatilesRounded();
|
||||
int maxPrimary = Project::getNumMetatilesPrimary();
|
||||
bool includesPrimary = metatileIdStart < maxPrimary;
|
||||
|
||||
QImage image(this->numMetatilesWide * 32, numMetatilesHigh * 32, QImage::Format_RGBA8888);
|
||||
QImage image(this->numMetatilesWide * this->cellWidth, numMetatilesHigh * this->cellHeight, QImage::Format_RGBA8888);
|
||||
image.fill(Qt::magenta);
|
||||
QPainter painter(&image);
|
||||
for (int i = 0; i < numMetatiles; i++) {
|
||||
@@ -57,10 +62,10 @@ QImage TilesetEditorMetatileSelector::buildImage(int metatileIdStart, int numMet
|
||||
this->layout->metatileLayerOrder,
|
||||
this->layout->metatileLayerOpacity,
|
||||
true)
|
||||
.scaled(32, 32);
|
||||
.scaled(this->cellWidth, this->cellHeight);
|
||||
int map_y = i / this->numMetatilesWide;
|
||||
int map_x = i % this->numMetatilesWide;
|
||||
QPoint metatile_origin = QPoint(map_x * 32, map_y * 32);
|
||||
QPoint metatile_origin = QPoint(map_x * this->cellWidth, map_y * this->cellHeight);
|
||||
painter.drawImage(metatile_origin, metatile_image);
|
||||
}
|
||||
painter.end();
|
||||
@@ -107,10 +112,11 @@ uint16_t TilesetEditorMetatileSelector::getSelectedMetatileId() {
|
||||
|
||||
uint16_t TilesetEditorMetatileSelector::getMetatileId(int x, int y) {
|
||||
int index = y * this->numMetatilesWide + x;
|
||||
if (index < this->primaryTileset->numMetatiles()) {
|
||||
int numPrimary = numPrimaryMetatilesRounded();
|
||||
if (index < numPrimary) {
|
||||
return static_cast<uint16_t>(index);
|
||||
} else {
|
||||
return static_cast<uint16_t>(Project::getNumMetatilesPrimary() + index - this->primaryTileset->numMetatiles());
|
||||
return static_cast<uint16_t>(Project::getNumMetatilesPrimary() + index - numPrimary);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +162,7 @@ QPoint TilesetEditorMetatileSelector::getMetatileIdCoords(uint16_t metatileId) {
|
||||
}
|
||||
int index = metatileId < Project::getNumMetatilesPrimary()
|
||||
? metatileId
|
||||
: metatileId - Project::getNumMetatilesPrimary() + this->primaryTileset->numMetatiles();
|
||||
: metatileId - Project::getNumMetatilesPrimary() + this->numPrimaryMetatilesRounded();
|
||||
return QPoint(index % this->numMetatilesWide, index / this->numMetatilesWide);
|
||||
}
|
||||
|
||||
@@ -176,12 +182,12 @@ void TilesetEditorMetatileSelector::drawGrid() {
|
||||
const int numColumns = this->numMetatilesWide;
|
||||
const int numRows = this->numRows();
|
||||
for (int column = 1; column < numColumns; column++) {
|
||||
int x = column * 32;
|
||||
painter.drawLine(x, 0, x, numRows * 32);
|
||||
int x = column * this->cellWidth;
|
||||
painter.drawLine(x, 0, x, numRows * this->cellHeight);
|
||||
}
|
||||
for (int row = 1; row < numRows; row++) {
|
||||
int y = row * 32;
|
||||
painter.drawLine(0, y, numColumns * 32, y);
|
||||
int y = row * this->cellHeight;
|
||||
painter.drawLine(0, y, numColumns * this->cellWidth, y);
|
||||
}
|
||||
painter.end();
|
||||
this->setPixmap(pixmap);
|
||||
@@ -191,12 +197,12 @@ void TilesetEditorMetatileSelector::drawDivider() {
|
||||
if (!this->showDivider)
|
||||
return;
|
||||
|
||||
const int y = this->numRows(this->primaryTileset->numMetatiles()) * 32;
|
||||
const int y = this->numRows(this->numPrimaryMetatilesRounded()) * this->cellHeight;
|
||||
|
||||
QPixmap pixmap = this->pixmap();
|
||||
QPainter painter(&pixmap);
|
||||
painter.setPen(Qt::white);
|
||||
painter.drawLine(0, y, this->numMetatilesWide * 32, y);
|
||||
painter.drawLine(0, y, this->numMetatilesWide * this->cellWidth, y);
|
||||
painter.end();
|
||||
this->setPixmap(pixmap);
|
||||
}
|
||||
@@ -212,7 +218,7 @@ void TilesetEditorMetatileSelector::drawFilters() {
|
||||
|
||||
void TilesetEditorMetatileSelector::drawUnused() {
|
||||
// setup the circle with a line through it image to layer above unused metatiles
|
||||
QPixmap redX(32, 32);
|
||||
QPixmap redX(this->cellWidth, this->cellHeight);
|
||||
redX.fill(Qt::transparent);
|
||||
|
||||
QPen whitePen(Qt::white);
|
||||
@@ -223,21 +229,21 @@ void TilesetEditorMetatileSelector::drawUnused() {
|
||||
QPainter oPainter(&redX);
|
||||
|
||||
oPainter.setPen(whitePen);
|
||||
oPainter.drawEllipse(QRect(1, 1, 30, 30));
|
||||
oPainter.drawEllipse(QRect(1, 1, this->cellWidth - 2, this->cellHeight - 2));
|
||||
oPainter.setPen(pinkPen);
|
||||
oPainter.drawEllipse(QRect(2, 2, 28, 28));
|
||||
oPainter.drawEllipse(QRect(3, 3, 26, 26));
|
||||
oPainter.drawEllipse(QRect(2, 2, this->cellWidth - 4, this->cellHeight - 4));
|
||||
oPainter.drawEllipse(QRect(3, 3, this->cellWidth - 6, this->cellHeight - 6));
|
||||
|
||||
oPainter.setPen(whitePen);
|
||||
oPainter.drawEllipse(QRect(4, 4, 24, 24));
|
||||
oPainter.drawEllipse(QRect(4, 4, this->cellHeight - 8, this->cellHeight - 8));
|
||||
|
||||
whitePen.setWidth(5);
|
||||
oPainter.setPen(whitePen);
|
||||
oPainter.drawLine(0, 0, 31, 31);
|
||||
oPainter.drawLine(0, 0, this->cellWidth - 1, this->cellHeight - 1);
|
||||
|
||||
pinkPen.setWidth(3);
|
||||
oPainter.setPen(pinkPen);
|
||||
oPainter.drawLine(2, 2, 29, 29);
|
||||
oPainter.drawLine(2, 2, this->cellWidth - 3, this->cellHeight - 3);
|
||||
|
||||
oPainter.end();
|
||||
|
||||
@@ -247,19 +253,13 @@ void TilesetEditorMetatileSelector::drawUnused() {
|
||||
QPainter unusedPainter(&metatilesPixmap);
|
||||
unusedPainter.setOpacity(0.5);
|
||||
|
||||
int primaryLength = this->primaryTileset->numMetatiles();
|
||||
int length_ = primaryLength + this->secondaryTileset->numMetatiles();
|
||||
|
||||
for (int i = 0; i < length_; i++) {
|
||||
int tile = i;
|
||||
if (i >= primaryLength) {
|
||||
tile += Project::getNumMetatilesPrimary() - primaryLength;
|
||||
}
|
||||
if (!usedMetatiles[tile]) {
|
||||
unusedPainter.drawPixmap((i % 8) * 32, (i / 8) * 32, redX);
|
||||
}
|
||||
for (int metatileId = 0; metatileId < this->usedMetatiles.size(); metatileId++) {
|
||||
if (this->usedMetatiles.at(metatileId) || !Tileset::metatileIsValid(metatileId, this->primaryTileset, this->secondaryTileset))
|
||||
continue;
|
||||
// Adjust position from center to top-left corner
|
||||
QPoint pos = getMetatileIdCoordsOnWidget(metatileId) - QPoint(this->cellWidth / 2, this->cellHeight / 2);
|
||||
unusedPainter.drawPixmap(pos.x(), pos.y(), redX);
|
||||
}
|
||||
|
||||
unusedPainter.end();
|
||||
|
||||
this->setPixmap(metatilesPixmap);
|
||||
@@ -268,38 +268,28 @@ void TilesetEditorMetatileSelector::drawUnused() {
|
||||
void TilesetEditorMetatileSelector::drawCounts() {
|
||||
QPen blackPen(Qt::black);
|
||||
blackPen.setWidth(1);
|
||||
|
||||
QPixmap metatilesPixmap = this->pixmap();
|
||||
|
||||
QPainter countPainter(&metatilesPixmap);
|
||||
countPainter.setPen(blackPen);
|
||||
|
||||
for (int tile = 0; tile < this->usedMetatiles.size(); tile++) {
|
||||
int count = usedMetatiles[tile];
|
||||
QString countText = QString::number(count);
|
||||
if (count > 1000) countText = ">1k";
|
||||
countPainter.drawText((tile % 8) * 32, (tile / 8) * 32 + 32, countText);
|
||||
}
|
||||
|
||||
// write in white and black for contrast
|
||||
QPen whitePen(Qt::white);
|
||||
whitePen.setWidth(1);
|
||||
countPainter.setPen(whitePen);
|
||||
|
||||
int primaryLength = this->primaryTileset->numMetatiles();
|
||||
int length_ = primaryLength + this->secondaryTileset->numMetatiles();
|
||||
QPixmap metatilesPixmap = this->pixmap();
|
||||
QPainter countPainter(&metatilesPixmap);
|
||||
|
||||
for (int i = 0; i < length_; i++) {
|
||||
int tile = i;
|
||||
if (i >= primaryLength) {
|
||||
tile += Project::getNumMetatilesPrimary() - primaryLength;
|
||||
}
|
||||
int count = usedMetatiles[tile];
|
||||
QString countText = QString::number(count);
|
||||
if (count > 1000) countText = ">1k";
|
||||
countPainter.drawText((i % 8) * 32 + 1, (i / 8) * 32 + 32 - 1, countText);
|
||||
for (int metatileId = 0; metatileId < this->usedMetatiles.size(); metatileId++) {
|
||||
if (!Tileset::metatileIsValid(metatileId, this->primaryTileset, this->secondaryTileset))
|
||||
continue;
|
||||
|
||||
int count = this->usedMetatiles.at(metatileId);
|
||||
QString countText = (count > 1000) ? QStringLiteral(">1k") : QString::number(count);
|
||||
|
||||
// Adjust position from center to bottom-left corner
|
||||
QPoint pos = getMetatileIdCoordsOnWidget(metatileId) + QPoint(-(this->cellWidth / 2), this->cellHeight / 2);
|
||||
|
||||
// write in black and white for contrast
|
||||
countPainter.setPen(blackPen);
|
||||
countPainter.drawText(pos.x(), pos.y(), countText);
|
||||
countPainter.setPen(whitePen);
|
||||
countPainter.drawText(pos.x() + 1, pos.y() - 1, countText);
|
||||
}
|
||||
|
||||
countPainter.end();
|
||||
|
||||
this->setPixmap(metatilesPixmap);
|
||||
|
||||
@@ -109,7 +109,7 @@ void WildMonChart::readTable() {
|
||||
}
|
||||
|
||||
// Read data from the table, combining data for duplicate entries
|
||||
const QList<double> tableFrequencies = this->table->percentages();
|
||||
const QVector<double> tableFrequencies = this->table->percentages();
|
||||
const QVector<WildPokemon> tablePokemon = this->table->encounterData().wildPokemon;
|
||||
const int numRows = qMin(tableFrequencies.length(), tablePokemon.length());
|
||||
const QString speciesPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_species_prefix);
|
||||
|
||||
@@ -58,13 +58,13 @@ void WildMonSearch::addTableEntry(const RowData &rowData) {
|
||||
int row = ui->table_Results->rowCount();
|
||||
ui->table_Results->insertRow(row);
|
||||
|
||||
auto groupItem = new QTableWidgetItem(rowData.groupName);
|
||||
auto groupItem = new NumericSortTableItem(rowData.groupName);
|
||||
groupItem->setData(ResultsDataRole::MapName, rowData.mapName);
|
||||
|
||||
ui->table_Results->setItem(row, ResultsColumn::Group, groupItem);
|
||||
ui->table_Results->setItem(row, ResultsColumn::Field, new QTableWidgetItem(rowData.fieldName));
|
||||
ui->table_Results->setItem(row, ResultsColumn::Level, new QTableWidgetItem(rowData.levelRange));
|
||||
ui->table_Results->setItem(row, ResultsColumn::Chance, new QTableWidgetItem(rowData.chance));
|
||||
ui->table_Results->setItem(row, ResultsColumn::Field, new NumericSortTableItem(rowData.fieldName));
|
||||
ui->table_Results->setItem(row, ResultsColumn::Level, new NumericSortTableItem(rowData.levelRange));
|
||||
ui->table_Results->setItem(row, ResultsColumn::Chance, new NumericSortTableItem(rowData.chance));
|
||||
}
|
||||
|
||||
QList<WildMonSearch::RowData> WildMonSearch::search(const QString &species) const {
|
||||
@@ -137,7 +137,6 @@ void WildMonSearch::updateResults(const QString &species) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This does a lexical sort... We might need custom item delegates to get proper numerical sorting in this table.
|
||||
ui->table_Results->setSortingEnabled(true);
|
||||
|
||||
this->resultsCache.insert(species, results);
|
||||
|
||||
Reference in New Issue
Block a user