mirror of
https://github.com/huderlem/porymap.git
synced 2026-08-25 18:16:57 -05:00
Merge branch 'dev' of https://github.com/huderlem/porymap into version-check
This commit is contained in:
17
CHANGELOG.md
17
CHANGELOG.md
@@ -21,20 +21,23 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
|
||||
- Add an input field to the Tileset Editor for editing the full metatile attributes value directly, including unused bits.
|
||||
- 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 support for referring to object events and warps with named IDs, rather than referring to them with their index number.
|
||||
- Add a setting to specify the tile values to use for the unused metatile layer.
|
||||
- Add a setting to specify the maximum number of events in a group. A warning will be shown if too many events are added.
|
||||
- Add a setting to customize the size and position of the player view distance.
|
||||
- Add `onLayoutOpened` to the scripting API.
|
||||
- Add a splash loading screen for project openings.
|
||||
|
||||
### 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.
|
||||
- New maps/layouts are no longer saved automatically, and can be fully discarded by closing without saving.
|
||||
- Map groups and ``MAPSEC`` names specified when creating a new map will be added automatically if they don't already exist.
|
||||
- Custom fields in JSON files that Porymap writes are no longer discarded.
|
||||
- Edits to map connections now have Undo/Redo and can be viewed in exported timelapses.
|
||||
- Changes to the "Mirror to Connecting Maps" setting will now be saved between sessions.
|
||||
- A notice will be displayed when attempting to open the "Dynamic" map, rather than nothing happening.
|
||||
- The base game version is now auto-detected if the project name contains only one of "emerald", "firered/leafgreen", or "ruby/sapphire".
|
||||
- The max encounter rate is now read from the project, rather than assuming the default value from RSE.
|
||||
- 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` and `Export Map Timelapse Image` now show a preview of the full image/gif, not just the current map.
|
||||
@@ -49,6 +52,10 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
|
||||
- `Script` dropdowns now autocomplete only with scripts from the current map, rather than every script in the project. The old behavior is available via a new setting.
|
||||
- The options for `Encounter Type` and `Terrain Type` in the Tileset Editor are not hardcoded anymore, they're now read from the project.
|
||||
- The `symbol_wild_encounters` setting was replaced; this value is now read from the project.
|
||||
- The max encounter rate is now read from the project, rather than assuming the default value from RSE.
|
||||
- `MAP_OFFSET_W` and `MAP_OFFSET_H` (used to limit the maximum map size) are now read from the project.
|
||||
- The rendered area of the map border is now limited to the maximum player view distance (prior to this it included two extra rows on the top and bottom).
|
||||
- An error message will now be shown when Porymap is unable to save changes (e.g. if Porymap doesn't have write permissions for your project).
|
||||
- A project may now be opened even if it has no maps or map groups. A minimum of one map layout is required.
|
||||
- The file extensions that are expected for `.png` and `.pal` data files and the extensions outputted when creating a new tileset can now be customized.
|
||||
- Miscellaneous performance improvements, especially for opening projects.
|
||||
@@ -57,12 +64,18 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
|
||||
- Fix `Add Region Map...` not updating the region map settings file.
|
||||
- Fix some crashes on invalid region map tilesets.
|
||||
- Improve error reporting for invalid region map editor settings.
|
||||
- Fix the region map editor's palette resetting between region maps.
|
||||
- Fix the region map editor's h-flip and v-flip settings being swapped.
|
||||
- Fix config files being written before the project is opened successfully.
|
||||
- Fix the map and other project info still displaying if a new project fails to open.
|
||||
- Fix unsaved changes being ignored when quitting (such as with Cmd+Q on macOS).
|
||||
- Fix selections with multiple Events not always clearing when making a new selection.
|
||||
- Fix selections with multiple events not always clearing when making a new selection.
|
||||
- Fix the new event button not updating correctly when selecting object events.
|
||||
- Fix duplicated `Hidden Item` events not copying the `Requires Itemfinder` field.
|
||||
- Fix event sprites disappearing in certain areas outside the map boundaries.
|
||||
- Fix deselecting an event still allowing you to drag the event around.
|
||||
- Fix events rendering on top of the ruler at very high y values.
|
||||
- Fix new map names not appearing in event dropdowns that have already been populated.
|
||||
- Fix `About porymap` opening a new window each time it's activated.
|
||||
- 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.
|
||||
|
||||
@@ -97,6 +97,8 @@ In addition to these files, there are some specific symbol and macro names that
|
||||
``define_pals_total``, ``NUM_PALS_TOTAL``,
|
||||
``define_tiles_per_metatile``, ``NUM_TILES_PER_METATILE``, to determine if triple-layer metatiles are in use. Values other than 8 or 12 are ignored
|
||||
``define_map_size``, ``MAX_MAP_DATA_SIZE``, to limit map dimensions
|
||||
``define_map_offset_width``, ``MAP_OFFSET_W``, to limit map dimensions
|
||||
``define_map_offset_height``, ``MAP_OFFSET_H``, to limit map dimensions
|
||||
``define_mask_metatile``, ``MAPGRID_METATILE_ID_MASK``, optionally read to get settings on ``Maps`` tab
|
||||
``define_mask_collision``, ``MAPGRID_COLLISION_MASK``, optionally read to get settings on ``Maps`` tab
|
||||
``define_mask_elevation``, ``MAPGRID_ELEVATION_MASK``, optionally read to get settings on ``Maps`` tab
|
||||
|
||||
@@ -204,7 +204,7 @@ Callbacks
|
||||
|
||||
Called when the mouse exits the map.
|
||||
|
||||
.. js:function:: onMapResized(oldWidth, oldHeight, newWidth, newHeight)
|
||||
.. js:function:: onMapResized(oldWidth, oldHeight, delta)
|
||||
|
||||
Called when the dimensions of the map are changed.
|
||||
|
||||
@@ -212,10 +212,8 @@ Callbacks
|
||||
:type oldWidth: number
|
||||
:param oldHeight: the height of the map before the change
|
||||
:type oldHeight: number
|
||||
:param newWidth: the width of the map after the change
|
||||
:type newWidth: number
|
||||
:param newHeight: the height of the map after the change
|
||||
:type newHeight: number
|
||||
:param delta: the amount the map size changed in each direction. The object's shape is ``{left, right, top, bottom}``
|
||||
:type prevBlock: delta
|
||||
|
||||
.. js:function:: onBorderResized(oldWidth, oldHeight, newWidth, newHeight)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>178</width>
|
||||
<width>188</width>
|
||||
<height>157</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -20,7 +20,7 @@
|
||||
<string notr="true">.ConnectionsListItem { border-width: 1px; }</string>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
<enum>QFrame::Shape::StyledPanel</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
@@ -65,7 +65,7 @@
|
||||
<item row="3" column="2">
|
||||
<widget class="QToolButton" name="button_Delete">
|
||||
<property name="toolTip">
|
||||
<string>Remove this connection.</string>
|
||||
<string><html><head/><body><p>Remove this connection.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
@@ -79,28 +79,28 @@
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="NoScrollComboBox" name="comboBox_Direction">
|
||||
<property name="toolTip">
|
||||
<string>Where the connected map should be positioned relative to the current map.</string>
|
||||
<string><html><head/><body><p>Where the connected map should be positioned relative to the current map.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="NoScrollComboBox" name="comboBox_Map">
|
||||
<property name="toolTip">
|
||||
<string>The name of the map to connect to the current map.</string>
|
||||
<string><html><head/><body><p>The name of the map to connect to the current map.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="2">
|
||||
<widget class="NoScrollSpinBox" name="spinBox_Offset">
|
||||
<property name="toolTip">
|
||||
<string>The number of spaces to move the connected map perpendicular to its connected direction.</string>
|
||||
<string><html><head/><body><p>The number of spaces to move the connected map perpendicular to its connected direction.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QToolButton" name="button_OpenMap">
|
||||
<property name="toolTip">
|
||||
<string>Open the connected map.</string>
|
||||
<string><html><head/><body><p>Open the connected map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_Name">
|
||||
<property name="toolTip">
|
||||
<string>The key name for the new JSON field</string>
|
||||
<string><html><head/><body><p>The key name for the new JSON field</p></body></html></string>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
@@ -50,7 +50,7 @@
|
||||
<item row="2" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_Type">
|
||||
<property name="toolTip">
|
||||
<string>The data type for the new JSON field</string>
|
||||
<string><html><head/><body><p>The data type for the new JSON field</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -70,7 +70,7 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The value for the new JSON field</string>
|
||||
<string><html><head/><body><p>The value for the new JSON field</p></body></html></string>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_String">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
<item>
|
||||
<widget class="QPushButton" name="button_CreateNewScript">
|
||||
<property name="toolTip">
|
||||
<string>Create a new Porymap script file with a default template</string>
|
||||
<string><html><head/><body><p>Create a new Porymap script file with a default template</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Create New Script...</string>
|
||||
@@ -74,7 +74,7 @@
|
||||
<item>
|
||||
<widget class="QPushButton" name="button_LoadScript">
|
||||
<property name="toolTip">
|
||||
<string>Add an existing script file to the list below</string>
|
||||
<string><html><head/><body><p>Add an existing script file to the list below</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Load Script...</string>
|
||||
@@ -88,7 +88,7 @@
|
||||
<item>
|
||||
<widget class="QPushButton" name="button_RefreshScripts">
|
||||
<property name="toolTip">
|
||||
<string>Refresh all loaded scripts to account for any recent edits</string>
|
||||
<string><html><head/><body><p>Refresh all loaded scripts to account for any recent edits</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Refresh Scripts</string>
|
||||
|
||||
164
forms/loadingscreen.ui
Normal file
164
forms/loadingscreen.ui
Normal file
@@ -0,0 +1,164 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LoadingScreen</class>
|
||||
<widget class="QWidget" name="LoadingScreen">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::ApplicationModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>366</width>
|
||||
<height>255</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>BusyCursor</cursorShape>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::NoContextMenu</enum>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelPorymap">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>20</pointsize>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>porymap</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelVersion">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Version X.x.x</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<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>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelPixmap">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>IMAGE</string>
|
||||
</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>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelLoading">
|
||||
<property name="text">
|
||||
<string>Loading.....</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="labelText">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -260,9 +260,6 @@
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab_Map">
|
||||
<property name="toolTip">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_9">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
@@ -351,12 +348,6 @@
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="transformationAnchor">
|
||||
<enum>QGraphicsView::ViewportAnchor::AnchorUnderMouse</enum>
|
||||
</property>
|
||||
<property name="resizeAnchor">
|
||||
<enum>QGraphicsView::ViewportAnchor::AnchorUnderMouse</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -2386,7 +2377,7 @@
|
||||
<item row="0" column="7">
|
||||
<widget class="QCheckBox" name="checkBox_MirrorConnections">
|
||||
<property name="toolTip">
|
||||
<string>If enabled, connections will automatically be updated on the connected map.</string>
|
||||
<string><html><head/><body><p>If enabled, the connected Emerge and/or Dive maps will be displayed with an opacity set using the slider.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Mirror to Connecting Maps</string>
|
||||
@@ -2435,8 +2426,11 @@
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QToolButton" name="button_OpenDiveMap">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Open the selected Dive Map</string>
|
||||
<string><html><head/><body><p>Open the selected Dive Map</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
@@ -2450,7 +2444,7 @@
|
||||
<item row="0" column="4" rowspan="2">
|
||||
<widget class="QGroupBox" name="groupBox_DiveMapOpacity">
|
||||
<property name="toolTip">
|
||||
<string>If enabled, the connected Emerge and/or Dive maps will be displayed with an opacity set using the slider.</string>
|
||||
<string><html><head/><body><p>If enabled, the connected Emerge and/or Dive maps will be displayed with an opacity set using the slider.</p></body></html></string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Show Emerge/Dive Maps</string>
|
||||
@@ -2569,8 +2563,11 @@
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QToolButton" name="button_OpenEmergeMap">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Open the selected Emerge Map</string>
|
||||
<string><html><head/><body><p>Open the selected Emerge Map</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
@@ -2589,7 +2586,7 @@
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QGraphicsView" name="graphicsView_Connections">
|
||||
<widget class="ConnectionsView" name="graphicsView_Connections">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -2863,6 +2860,7 @@
|
||||
<addaction name="menuOpen_Recent_Project"/>
|
||||
<addaction name="action_Reload_Project"/>
|
||||
<addaction name="action_Close_Project"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_Save"/>
|
||||
<addaction name="action_Save_Project"/>
|
||||
<addaction name="separator"/>
|
||||
@@ -2887,8 +2885,10 @@
|
||||
<addaction name="actionCursor_Tile_Outline"/>
|
||||
<addaction name="actionPlayer_View_Rectangle"/>
|
||||
<addaction name="actionBetter_Cursors"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionDive_Emerge_Map"/>
|
||||
<addaction name="actionShow_Events_In_Map_View"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionShow_Grid"/>
|
||||
<addaction name="actionGrid_Settings"/>
|
||||
</widget>
|
||||
@@ -3076,45 +3076,6 @@
|
||||
<string>Ctrl+T</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSort_by_Location">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/images.qrc">
|
||||
<normaloff>:/icons/sort_alphabet.ico</normaloff>:/icons/sort_alphabet.ico</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sort by &Location</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSort_by_Group">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/images.qrc">
|
||||
<normaloff>:/icons/sort_number.ico</normaloff>:/icons/sort_number.ico</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sort by &Group</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Sort by Group</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSort_by_Layout">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/images.qrc">
|
||||
<normaloff>:/icons/sort_map.ico</normaloff>:/icons/sort_map.ico</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sort by &Layout</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAbout_Porymap">
|
||||
<property name="text">
|
||||
<string>About Porymap...</string>
|
||||
@@ -3310,9 +3271,14 @@
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>MapView</class>
|
||||
<extends>QWidget</extends>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>mapview.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ConnectionsView</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>graphicsview.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>MapTree</class>
|
||||
<extends>QTreeView</extends>
|
||||
@@ -3321,7 +3287,7 @@
|
||||
<customwidget>
|
||||
<class>NoScrollGraphicsView</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>mapview.h</header>
|
||||
<header>graphicsview.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>MapListToolBar</class>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>407</width>
|
||||
<height>349</height>
|
||||
<height>380</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -224,7 +224,11 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_LocationName"/>
|
||||
<widget class="QLineEdit" name="lineEdit_LocationName">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The name that will be displayed in-game for this Location. This name will be shared with any other map that has the same Location.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
<item>
|
||||
<widget class="QToolButton" name="button_AddFolder">
|
||||
<property name="toolTip">
|
||||
<string>Add a new folder to the list.</string>
|
||||
<string><html><head/><body><p>Add a new folder to the list.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
@@ -73,7 +73,7 @@
|
||||
<item>
|
||||
<widget class="QToolButton" name="button_ExpandAll">
|
||||
<property name="toolTip">
|
||||
<string>Expand all folders in the list.</string>
|
||||
<string><html><head/><body><p>Expand all folders in the list.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
@@ -93,7 +93,7 @@
|
||||
<item>
|
||||
<widget class="QToolButton" name="button_CollapseAll">
|
||||
<property name="toolTip">
|
||||
<string>Collapse all folders in the list.</string>
|
||||
<string><html><head/><body><p>Collapse all folders in the list.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
@@ -113,7 +113,7 @@
|
||||
<item>
|
||||
<widget class="QToolButton" name="button_ToggleEdit">
|
||||
<property name="toolTip">
|
||||
<string>If enabled, folders may be renamed and items in the list may be rearranged.</string>
|
||||
<string><html><head/><body><p>If enabled, folders may be renamed and items in the list may be rearranged.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
||||
89
forms/newdefinedialog.ui
Normal file
89
forms/newdefinedialog.ui
Normal file
@@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>NewDefineDialog</class>
|
||||
<widget class="QDialog" name="NewDefineDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>252</width>
|
||||
<height>124</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QFrame" name="form">
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<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_Name">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_Name">
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_NameError">
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: rgb(255, 0, 0)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_Value"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_Value">
|
||||
<property name="text">
|
||||
<string>Value</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
|
||||
</property>
|
||||
<property name="centerButtons">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -17,10 +17,10 @@
|
||||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
<enum>QFrame::Shadow::Plain</enum>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<property name="leftMargin">
|
||||
@@ -45,7 +45,7 @@
|
||||
<item row="0" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_Map">
|
||||
<property name="toolTip">
|
||||
<string>The name of the map to connect to the current map.</string>
|
||||
<string><html><head/><body><p>The name of the map to connect to the current map.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -59,7 +59,7 @@
|
||||
<item row="1" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_Direction">
|
||||
<property name="toolTip">
|
||||
<string>Where the connected map should be positioned relative to the current map.</string>
|
||||
<string><html><head/><body><p>Where the connected map should be positioned relative to the current map.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -82,10 +82,10 @@
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_MonitorProjectFiles">
|
||||
<property name="toolTip">
|
||||
<string>If checked, a prompt to reload your project will appear if relevant project files are edited</string>
|
||||
<string><html><head/><body><p>If checked, a prompt to reload your project will appear if relevant project files are edited</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Monitor project files</string>
|
||||
@@ -50,7 +50,7 @@
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_OpenRecentProject">
|
||||
<property name="toolTip">
|
||||
<string>If checked, Porymap will automatically open your most recently opened project on startup</string>
|
||||
<string><html><head/><body><p>If checked, Porymap will automatically open your most recently opened project on startup</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Open recent project on launch</string>
|
||||
@@ -60,7 +60,7 @@
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_CheckForUpdates">
|
||||
<property name="toolTip">
|
||||
<string>If checked, Porymap will automatically alert you on startup if a new release is available</string>
|
||||
<string><html><head/><body><p>If checked, Porymap will automatically alert you on startup if a new release is available</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Automatically check for updates</string>
|
||||
@@ -112,7 +112,7 @@
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_DisableEventWarning">
|
||||
<property name="toolTip">
|
||||
<string>If checked, no warning will be shown when deleting an event that has an associated #define that may also be deleted.</string>
|
||||
<string><html><head/><body><p>If checked, no warning will be shown when deleting an event that has an associated #define that may also be deleted.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Disable warning when deleting events with IDs</string>
|
||||
@@ -138,7 +138,7 @@
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_OnSprite">
|
||||
<property name="toolTip">
|
||||
<string>If enabled, an event can be selected by clicking directly on the opaque pixels of its sprite. This may be preferable when events are overlapping.</string>
|
||||
<string><html><head/><body><p>If enabled, an event can be selected by clicking directly on the opaque pixels of its sprite. This may be preferable when events are overlapping.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Select by clicking on sprite</string>
|
||||
@@ -148,7 +148,7 @@
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_WithinRect">
|
||||
<property name="toolTip">
|
||||
<string>If enabled, an event can be selected by clicking anywhere within its sprite dimensions. This may be preferable for events with small or mostly transparent sprites.</string>
|
||||
<string><html><head/><body><p>If enabled, an event can be selected by clicking anywhere within its sprite dimensions. This may be preferable for events with small or mostly transparent sprites.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Select by clicking within bounding rectangle</string>
|
||||
@@ -231,7 +231,7 @@
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_TextEditorOpenFolder">
|
||||
<property name="toolTip">
|
||||
<string>The shell command for your preferred text editor (possibly an absolute path if the program doesn't exist in your PATH).</string>
|
||||
<string><html><head/><body><p>The shell command for your preferred text editor (possibly an absolute path if the program doesn't exist in your PATH).</p></body></html></string>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>e.g. code %D</string>
|
||||
@@ -264,7 +264,7 @@
|
||||
<item row="5" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_TextEditorGotoLine">
|
||||
<property name="toolTip">
|
||||
<string>The shell command for your preferred text editor to open a file to a specific line number (possibly an absolute path if the program doesn't exist in your PATH).</string>
|
||||
<string><html><head/><body><p>The shell command for your preferred text editor to open a file to a specific line number (possibly an absolute path if the program doesn't exist in your PATH).</p></body></html></string>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>e.g. code --goto %F:%L</string>
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>631</width>
|
||||
<height>600</height>
|
||||
<width>642</width>
|
||||
<height>609</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -38,8 +38,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>559</width>
|
||||
<height>568</height>
|
||||
<width>570</width>
|
||||
<height>692</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
@@ -52,7 +52,7 @@
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_UsePoryscript">
|
||||
<property name="toolTip">
|
||||
<string>Whether map script files should prefer using .pory</string>
|
||||
<string><html><head/><body><p>Whether map script files should prefer using .pory</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Use Poryscript</string>
|
||||
@@ -61,11 +61,24 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_ShowWildEncounterTables">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If enabled, Porymap will display wild encounter data on the Wild Pokémon tab.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Wild Encounter Tables</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_PreserveMatchingOnlyData">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If enabled, Porymap will not discard data like &quot;connections_include_order&quot; or &quot;name_clone&quot;, which serve no purpose other than recreating the original game.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Preserve data only needed to match the original game</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -89,7 +102,7 @@
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="button_ImportDefaultPrefabs">
|
||||
<property name="toolTip">
|
||||
<string>Restore the data in the prefabs file to the version defaults. Will create a new file if one doesn't exist.</string>
|
||||
<string><html><head/><body><p>Restore the data in the prefabs file to the version defaults. Will create a new file if one doesn't exist.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Import Defaults</string>
|
||||
@@ -99,7 +112,7 @@
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_PrefabsPath">
|
||||
<property name="toolTip">
|
||||
<string>The file that will be used to populate the Prefabs tab</string>
|
||||
<string><html><head/><body><p>The file that will be used to populate the Prefabs tab</p></body></html></string>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>prefabs.json</string>
|
||||
@@ -138,7 +151,7 @@
|
||||
<item row="0" column="1" colspan="6">
|
||||
<widget class="QLineEdit" name="lineEdit_CollisionGraphics">
|
||||
<property name="toolTip">
|
||||
<string>The image sheet that will be used to represent elevation and collision on the Collision tab</string>
|
||||
<string><html><head/><body><p>The image sheet that will be used to represent elevation and collision on the Collision tab</p></body></html></string>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
@@ -166,7 +179,7 @@
|
||||
<item row="1" column="5">
|
||||
<widget class="NoScrollSpinBox" name="spinBox_MaxCollision">
|
||||
<property name="toolTip">
|
||||
<string>The maximum collision value represented with an icon on the image sheet</string>
|
||||
<string><html><head/><body><p>The maximum collision value represented with an icon on the image sheet</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -187,7 +200,7 @@
|
||||
<item row="1" column="2">
|
||||
<widget class="NoScrollSpinBox" name="spinBox_MaxElevation">
|
||||
<property name="toolTip">
|
||||
<string>The maximum elevation value represented with an icon on the image sheet</string>
|
||||
<string><html><head/><body><p>The maximum elevation value represented with an icon on the image sheet</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -260,7 +273,7 @@
|
||||
<item row="1" column="2" colspan="3">
|
||||
<widget class="QLineEdit" name="lineEdit_PokemonIcon">
|
||||
<property name="toolTip">
|
||||
<string>The icon that will be displayed on the Wild Pokémon tab for the above species</string>
|
||||
<string><html><head/><body><p>The icon that will be displayed on the Wild Pokémon tab for the above species</p></body></html></string>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
@@ -270,6 +283,91 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_PlayerViewDistance">
|
||||
<property name="title">
|
||||
<string>Player View Distance</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_PlayerViewDistanceCol1">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_PlayerViewDistance_North">
|
||||
<property name="text">
|
||||
<string>North</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_PlayerViewDistance_South">
|
||||
<property name="text">
|
||||
<string>South</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="NoScrollSpinBox" name="spinBox_PlayerViewDistance_North">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The distance (in pixels) that a player is able to see North of their character's position in-game. By default this is the distance from the center 16x16 to the edge of the 160 pixel tall GBA screen.</p></body></html></string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="NoScrollSpinBox" name="spinBox_PlayerViewDistance_South">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The distance (in pixels) that a player is able to see South of their character's position in-game. By default this is the distance from the center 16x16 to the edge of the 160 pixel tall GBA screen.</p></body></html></string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_PlayerViewDistanceCol2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_PlayerViewDistance_West">
|
||||
<property name="text">
|
||||
<string>West</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_PlayerViewDistance_East">
|
||||
<property name="text">
|
||||
<string>East</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="NoScrollSpinBox" name="spinBox_PlayerViewDistance_West">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The distance (in pixels) that a player is able to see West of their character's position in-game. By default this is the distance from the center 16x16 to the edge of the 240 pixel wide GBA screen.</p></body></html></string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="NoScrollSpinBox" name="spinBox_PlayerViewDistance_East">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The distance (in pixels) that a player is able to see East of their character's position in-game. By default this is the distance from the center 16x16 to the edge of the 240 pixel wide GBA screen.</p></body></html></string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_Warning">
|
||||
<property name="styleSheet">
|
||||
@@ -368,8 +466,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>559</width>
|
||||
<height>560</height>
|
||||
<width>570</width>
|
||||
<height>622</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_16">
|
||||
@@ -379,37 +477,6 @@
|
||||
<string>Map Data Defaults</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="1" column="1" colspan="3">
|
||||
<widget class="QWidget" name="widget_CustomSizeBorderMetatiles" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<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>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="NoScrollSpinBox" name="spinBox_FillMetatile">
|
||||
<property name="toolTip">
|
||||
<string>The default metatile value that will be used to fill new maps</string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>0x</string>
|
||||
</property>
|
||||
<property name="displayIntegerBase">
|
||||
<number>16</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_Elevation">
|
||||
<property name="text">
|
||||
@@ -417,6 +484,50 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_MapWidth">
|
||||
<property name="text">
|
||||
<string>Width</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="NoScrollSpinBox" name="spinBox_Elevation">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The default elevation that will be used to fill new maps</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkBox_CreateTextFile">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Whether a separate text.inc or text.pory file will be created for new maps, alongside the scripts file</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Create separate text file</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="NoScrollSpinBox" name="spinBox_MapWidth">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The default layout width for new maps</p></body></html></string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="NoScrollSpinBox" name="spinBox_MapHeight">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The default layout height for new maps</p></body></html></string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_FillMetatile">
|
||||
<property name="text">
|
||||
@@ -424,13 +535,10 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkBox_CreateTextFile">
|
||||
<property name="toolTip">
|
||||
<string>Whether a separate text.inc or text.pory file will be created for new maps, alongside the scripts file</string>
|
||||
</property>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_Collision">
|
||||
<property name="text">
|
||||
<string>Create separate text file</string>
|
||||
<string>Collision</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -441,6 +549,20 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_FillMetatile">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The default metatile value that will be used to fill new maps</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="NoScrollSpinBox" name="spinBox_Collision">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The default collision that will be used to fill new maps</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="3">
|
||||
<widget class="QStackedWidget" name="stackedWidget_BorderMetatiles">
|
||||
<widget class="QWidget" name="page_CustomBorderSize">
|
||||
@@ -460,7 +582,7 @@
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit_BorderMetatiles">
|
||||
<property name="toolTip">
|
||||
<string>A comma-separated list of metatile values that will be used to fill new map borders</string>
|
||||
<string><html><head/><body><p>A comma-separated list of metatile values that will be used to fill new map borders</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -481,54 +603,30 @@
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="NoScrollSpinBox" name="spinBox_BorderMetatile1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_BorderMetatile1">
|
||||
<property name="toolTip">
|
||||
<string>The default metatile value that will be used for the top-left border metatile on new maps.</string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>0x</string>
|
||||
</property>
|
||||
<property name="displayIntegerBase">
|
||||
<number>16</number>
|
||||
<string><html><head/><body><p>The default metatile value that will be used for the top-left border metatile on new maps.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="NoScrollSpinBox" name="spinBox_BorderMetatile2">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_BorderMetatile2">
|
||||
<property name="toolTip">
|
||||
<string>The default metatile value that will be used for the top-right border metatile on new maps.</string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>0x</string>
|
||||
</property>
|
||||
<property name="displayIntegerBase">
|
||||
<number>16</number>
|
||||
<string><html><head/><body><p>The default metatile value that will be used for the top-right border metatile on new maps.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="NoScrollSpinBox" name="spinBox_BorderMetatile3">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_BorderMetatile3">
|
||||
<property name="toolTip">
|
||||
<string>The default metatile value that will be used for the bottom-left border metatile on new maps.</string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>0x</string>
|
||||
</property>
|
||||
<property name="displayIntegerBase">
|
||||
<number>16</number>
|
||||
<string><html><head/><body><p>The default metatile value that will be used for the bottom-left border metatile on new maps.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="NoScrollSpinBox" name="spinBox_BorderMetatile4">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_BorderMetatile4">
|
||||
<property name="toolTip">
|
||||
<string>The default metatile value that will be used for the bottom-right border metatile on new maps.</string>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string>0x</string>
|
||||
</property>
|
||||
<property name="displayIntegerBase">
|
||||
<number>16</number>
|
||||
<string><html><head/><body><p>The default metatile value that will be used for the bottom-right border metatile on new maps.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -536,24 +634,28 @@
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="NoScrollSpinBox" name="spinBox_Elevation">
|
||||
<property name="toolTip">
|
||||
<string>The default elevation that will be used to fill new maps</string>
|
||||
</property>
|
||||
<item row="1" column="1" colspan="3">
|
||||
<widget class="QWidget" name="widget_CustomSizeBorderMetatiles" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<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>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_Collision">
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_MapHeight">
|
||||
<property name="text">
|
||||
<string>Collision</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="NoScrollSpinBox" name="spinBox_Collision">
|
||||
<property name="toolTip">
|
||||
<string>The default collision that will be used to fill new maps</string>
|
||||
<string>Height</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -604,7 +706,7 @@
|
||||
<item row="0" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_MetatileIdMask">
|
||||
<property name="toolTip">
|
||||
<string>The mask used to read/write metatile IDs in map data.</string>
|
||||
<string><html><head/><body><p>The mask used to read/write metatile IDs in map data.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -618,7 +720,7 @@
|
||||
<item row="1" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_CollisionMask">
|
||||
<property name="toolTip">
|
||||
<string>The mask used to read/write collision values in map data.</string>
|
||||
<string><html><head/><body><p>The mask used to read/write collision values in map data.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -632,7 +734,7 @@
|
||||
<item row="2" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_ElevationMask">
|
||||
<property name="toolTip">
|
||||
<string>The mask used to read/write elevation values in map data.</string>
|
||||
<string><html><head/><body><p>The mask used to read/write elevation values in map data.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -661,7 +763,7 @@
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_EnableAllowFlags">
|
||||
<property name="toolTip">
|
||||
<string>Whether "Allow Running", "Allow Biking" and "Allow Dig & Escape Rope" are default options for Map Headers</string>
|
||||
<string><html><head/><body><p>Whether &quot;Allow Running&quot;, &quot;Allow Biking&quot; and &quot;Allow Dig &amp; Escape Rope&quot; are default options for Map Headers</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable 'Allow Running/Biking/Escaping'</string>
|
||||
@@ -671,7 +773,7 @@
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="checkBox_EnableFloorNumber">
|
||||
<property name="toolTip">
|
||||
<string>Whether "Floor Number" is a default option for Map Headers</string>
|
||||
<string><html><head/><body><p>Whether &quot;Floor Number&quot; is a default option for Map Headers</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable 'Floor Number'</string>
|
||||
@@ -681,7 +783,7 @@
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="checkBox_EnableCustomBorderSize">
|
||||
<property name="toolTip">
|
||||
<string>Whether the dimensions of the border can be changed. If not set, all borders are 2x2</string>
|
||||
<string><html><head/><body><p>Whether the dimensions of the border can be changed. If not set, all borders are 2x2</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable Custom Border Size</string>
|
||||
@@ -741,7 +843,7 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>559</width>
|
||||
<width>570</width>
|
||||
<height>798</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -760,7 +862,11 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_DefaultPrimaryTileset"/>
|
||||
<widget class="NoScrollComboBox" name="comboBox_DefaultPrimaryTileset">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The default primary tileset to use for new maps/layouts.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_SecondaryTileset">
|
||||
@@ -770,7 +876,11 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_DefaultSecondaryTileset"/>
|
||||
<widget class="NoScrollComboBox" name="comboBox_DefaultSecondaryTileset">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The default secondary tileset to use for new maps/layouts.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@@ -784,7 +894,7 @@
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_RenderBlack">
|
||||
<property name="toolTip">
|
||||
<string>Fully transparent pixels will be rendered as black pixels (the Pokémon games do this by default)</string>
|
||||
<string><html><head/><body><p>Fully transparent pixels will be rendered as black pixels (the Pokémon games do this by default)</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Render as black</string>
|
||||
@@ -794,7 +904,7 @@
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_RenderFirstPalColor">
|
||||
<property name="toolTip">
|
||||
<string>Fully transparent pixels will be rendered using the first palette color (this the default behavior for the GBA)</string>
|
||||
<string><html><head/><body><p>Fully transparent pixels will be rendered using the first palette color (this the default behavior for the GBA)</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Render using first palette color</string>
|
||||
@@ -820,7 +930,7 @@
|
||||
<item row="0" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_UnusedTileNormal">
|
||||
<property name="toolTip">
|
||||
<string>This raw tile value will be used to fill the unused bottom layer of Normal metatiles</string>
|
||||
<string><html><head/><body><p>This raw tile value will be used to fill the unused bottom layer of Normal metatiles</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -834,7 +944,7 @@
|
||||
<item row="1" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_UnusedTileCovered">
|
||||
<property name="toolTip">
|
||||
<string>This raw tile value will be used to fill the unused top layer of Covered metatiles</string>
|
||||
<string><html><head/><body><p>This raw tile value will be used to fill the unused top layer of Covered metatiles</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -848,7 +958,7 @@
|
||||
<item row="2" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_UnusedTileSplit">
|
||||
<property name="toolTip">
|
||||
<string>This raw tile value will be used to fill the unused middle layer of Split metatiles</string>
|
||||
<string><html><head/><body><p>This raw tile value will be used to fill the unused middle layer of Split metatiles</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -892,22 +1002,19 @@
|
||||
<item row="4" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_LayerTypeMask">
|
||||
<property name="toolTip">
|
||||
<string>The mask used to read/write Layer Type from the metatile's attributes data. If 0, this attribute is disabled.</string>
|
||||
<string><html><head/><body><p>The mask used to read/write Layer Type from the metatile's attributes data. If 0, this attribute is disabled.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_BehaviorMask">
|
||||
<property name="toolTip">
|
||||
<string>The mask used to read/write Metatile Behavior from the metatile's attributes data. If 0, this attribute is disabled.</string>
|
||||
<string><html><head/><body><p>The mask used to read/write Metatile Behavior from the metatile's attributes data. If 0, this attribute is disabled.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_AttributesSize">
|
||||
<property name="toolTip">
|
||||
<string>The number of bytes used per metatile for metatile attributes</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Attributes size (in bytes)</string>
|
||||
</property>
|
||||
@@ -938,6 +1045,9 @@
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="checkBox_EnableTripleLayerMetatiles">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If checked, metatiles will be interpreted as having 3 layers of 4 tiles each (12 tiles total) as opposed to the default 2 layers of 4 tiles each (8 total).</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable Triple Layer Metatiles</string>
|
||||
</property>
|
||||
@@ -946,7 +1056,7 @@
|
||||
<item row="7" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_TerrainTypeMask">
|
||||
<property name="toolTip">
|
||||
<string>The mask used to read/write Terrain Type from the metatile's attributes data. If 0, this attribute is disabled.</string>
|
||||
<string><html><head/><body><p>The mask used to read/write Terrain Type from the metatile's attributes data. If 0, this attribute is disabled.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -973,7 +1083,7 @@
|
||||
<item row="5" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_EncounterTypeMask">
|
||||
<property name="toolTip">
|
||||
<string>The mask used to read/write Encounter Type from the metatile's attributes data. If 0, this attribute is disabled.</string>
|
||||
<string><html><head/><body><p>The mask used to read/write Encounter Type from the metatile's attributes data. If 0, this attribute is disabled.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -986,6 +1096,9 @@
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_AttributesSize">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The number of bytes each metatile has for metatile attributes. This is the metadata about each metatile like behvior, layer type, etc.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@@ -1026,7 +1139,7 @@
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_OutputCallback">
|
||||
<property name="toolTip">
|
||||
<string>Whether the C data outputted for new tilesets will include the "callback" field</string>
|
||||
<string><html><head/><body><p>Whether the C data outputted for new tilesets will include the &quot;callback&quot; field</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Output 'callback' field</string>
|
||||
@@ -1036,7 +1149,7 @@
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_OutputIsCompressed">
|
||||
<property name="toolTip">
|
||||
<string>Whether the C data outputted for new tilesets will include the "isCompressed" field</string>
|
||||
<string><html><head/><body><p>Whether the C data outputted for new tilesets will include the &quot;isCompressed&quot; field</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Output 'isCompressed' field</string>
|
||||
@@ -1083,8 +1196,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>559</width>
|
||||
<height>788</height>
|
||||
<width>570</width>
|
||||
<height>840</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
@@ -1111,7 +1224,7 @@
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_WarpsIcon">
|
||||
<property name="toolTip">
|
||||
<string>The icon that will be used to represent Warp events</string>
|
||||
<string><html><head/><body><p>The icon that will be used to represent Warp events</p></body></html></string>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
@@ -1121,7 +1234,7 @@
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_HealLocationsIcon">
|
||||
<property name="toolTip">
|
||||
<string>The icon that will be used to represent Heal Location events</string>
|
||||
<string><html><head/><body><p>The icon that will be used to represent Heal Location events</p></body></html></string>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
@@ -1145,7 +1258,7 @@
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_ObjectsIcon">
|
||||
<property name="toolTip">
|
||||
<string>The icon that will be used to represent Object events that don't have their own sprite</string>
|
||||
<string><html><head/><body><p>The icon that will be used to represent Object events that don't have their own sprite</p></body></html></string>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
@@ -1162,7 +1275,7 @@
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_TriggersIcon">
|
||||
<property name="toolTip">
|
||||
<string>The icon that will be used to represent Trigger events</string>
|
||||
<string><html><head/><body><p>The icon that will be used to represent Trigger events</p></body></html></string>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
@@ -1172,7 +1285,7 @@
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_BGsIcon">
|
||||
<property name="toolTip">
|
||||
<string>The icon that will be used to represent BG events</string>
|
||||
<string><html><head/><body><p>The icon that will be used to represent BG events</p></body></html></string>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
@@ -1246,7 +1359,7 @@
|
||||
<item row="1" column="2">
|
||||
<widget class="QToolButton" name="button_RemoveWarpBehavior">
|
||||
<property name="toolTip">
|
||||
<string>Remove the current text from the list</string>
|
||||
<string><html><head/><body><p>Remove the current text from the list</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
@@ -1270,7 +1383,7 @@
|
||||
<item row="0" column="0" colspan="3">
|
||||
<widget class="QCheckBox" name="checkBox_DisableWarning">
|
||||
<property name="toolTip">
|
||||
<string>If checked, Warp Events will not display a warning about incompatible metatile behaviors</string>
|
||||
<string><html><head/><body><p>If checked, Warp Events will not display a warning about incompatible metatile behaviors</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Disable Warning</string>
|
||||
@@ -1281,9 +1394,9 @@
|
||||
<widget class="NoScrollComboBox" name="comboBox_WarpBehaviors"/>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="3">
|
||||
<widget class="QTextEdit" name="textEdit_WarpBehaviors">
|
||||
<widget class="NoScrollTextEdit" name="textEdit_WarpBehaviors">
|
||||
<property name="toolTip">
|
||||
<string>Metatile Behaviors on this list won't trigger warnings for Warp Events</string>
|
||||
<string><html><head/><body><p>Metatile Behaviors on this list won't trigger warnings for Warp Events</p></body></html></string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
@@ -1299,7 +1412,7 @@
|
||||
<item row="1" column="1">
|
||||
<widget class="QToolButton" name="button_AddWarpBehavior">
|
||||
<property name="toolTip">
|
||||
<string>Add the current text to the list</string>
|
||||
<string><html><head/><body><p>Add the current text to the list</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
@@ -1465,23 +1578,25 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>559</width>
|
||||
<height>490</height>
|
||||
<width>570</width>
|
||||
<height>499</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
<item>
|
||||
<widget class="QToolButton" name="button_HelpFiles">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
<layout class="QGridLayout" name="gridLayout_10" rowstretch="1,2,8">
|
||||
<item row="0" column="1">
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/images.qrc">
|
||||
<normaloff>:/icons/help.ico</normaloff>:/icons/help.ico</iconset>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<item row="2" column="0" colspan="3">
|
||||
<widget class="QWidget" name="widget_ProjectPaths" native="true">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<property name="spacing">
|
||||
@@ -1512,8 +1627,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>533</width>
|
||||
<height>428</height>
|
||||
<width>544</width>
|
||||
<height>338</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="layout_ProjectPaths">
|
||||
@@ -1533,6 +1648,34 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="button_AddGlobalConstantsFile">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Add additional C files containing #defines or enums. These will be used to resolve unknown symbols during project launch.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add Global Constants File...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/images.qrc">
|
||||
<normaloff>:/icons/add.ico</normaloff>:/icons/add.ico</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QToolButton" name="button_HelpFiles">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/images.qrc">
|
||||
<normaloff>:/icons/help.ico</normaloff>:/icons/help.ico</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="3">
|
||||
<layout class="QGridLayout" name="gridLayout_GlobalConstantsFiles"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
@@ -1554,12 +1697,12 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>559</width>
|
||||
<height>490</height>
|
||||
<width>570</width>
|
||||
<height>499</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_19">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_11">
|
||||
<item row="0" column="0">
|
||||
<widget class="QToolButton" name="button_HelpIdentifiers">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
@@ -1570,7 +1713,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<item row="2" column="0" colspan="3">
|
||||
<widget class="QWidget" name="widget_Identifiers" native="true">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_20">
|
||||
<property name="spacing">
|
||||
@@ -1601,8 +1744,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>533</width>
|
||||
<height>428</height>
|
||||
<width>544</width>
|
||||
<height>421</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="layout_Identifiers">
|
||||
@@ -1622,6 +1765,36 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QPushButton" name="button_AddGlobalConstant">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Add an additional #define name and expression. This may be used to evaluate other #defines during project launch.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add Global Constant...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/images.qrc">
|
||||
<normaloff>:/icons/add.ico</normaloff>:/icons/add.ico</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="horizontalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="3">
|
||||
<layout class="QGridLayout" name="gridLayout_GlobalConstants"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
@@ -1651,6 +1824,11 @@
|
||||
<extends>QSpinBox</extends>
|
||||
<header>noscrollspinbox.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>NoScrollTextEdit</class>
|
||||
<extends>QTextEdit</extends>
|
||||
<header>noscrolltextedit.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>UIntSpinBox</class>
|
||||
<extends>QAbstractSpinBox</extends>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_4">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
<enum>QFormLayout::FieldGrowthPolicy::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
@@ -33,7 +33,7 @@
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="config_alias">
|
||||
<property name="toolTip">
|
||||
<string>A nickname for this region map that will differentiate it from others (should be unique).</string>
|
||||
<string><html><head/><body><p>A nickname for this region map that will differentiate it from others (should be unique).</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -131,7 +131,7 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>The height of the tilemap</string>
|
||||
<string><html><head/><body><p>The height of the tilemap</p></body></html></string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>255</number>
|
||||
@@ -148,10 +148,10 @@
|
||||
<item row="6" column="1">
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
@@ -218,10 +218,10 @@
|
||||
<string><html><head/><body><p>Path to the tilemap binary relative to the project root.</p></body></html></string>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
@@ -269,10 +269,10 @@
|
||||
<item row="10" column="1">
|
||||
<widget class="QFrame" name="frame_3">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
<enum>QFrame::Shadow::Plain</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="leftMargin">
|
||||
@@ -392,10 +392,10 @@
|
||||
<item row="2" column="1">
|
||||
<widget class="QFrame" name="frame_5">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<property name="leftMargin">
|
||||
@@ -487,7 +487,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -517,7 +517,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -590,7 +590,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -617,7 +617,7 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -646,7 +646,7 @@
|
||||
<item row="9" column="0">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -659,10 +659,10 @@
|
||||
<item row="9" column="1">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -145,7 +145,7 @@
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
<enum>QComboBox::AdjustToMinimumContentsLengthWithIcon</enum>
|
||||
</property>
|
||||
<property name="minimumContentsLength">
|
||||
<number>8</number>
|
||||
|
||||
@@ -14,19 +14,20 @@
|
||||
#include <QGraphicsPixmapItem>
|
||||
|
||||
#include "events.h"
|
||||
#include "gridsettings.h"
|
||||
|
||||
static const QVersionNumber porymapVersion = QVersionNumber::fromString(PORYMAP_VERSION);
|
||||
extern const QVersionNumber porymapVersion;
|
||||
|
||||
// In both versions the default new map border is a generic tree
|
||||
#define DEFAULT_BORDER_RSE (QList<uint16_t>{0x1D4, 0x1D5, 0x1DC, 0x1DD})
|
||||
#define DEFAULT_BORDER_FRLG (QList<uint16_t>{0x14, 0x15, 0x1C, 0x1D})
|
||||
// Distance in pixels from the edge of a GBA screen (240x160) to the center 16x16 pixels.
|
||||
#define GBA_H_DIST_TO_CENTER ((240-16)/2)
|
||||
#define GBA_V_DIST_TO_CENTER ((160-16)/2)
|
||||
|
||||
#define CONFIG_BACKWARDS_COMPATABILITY
|
||||
|
||||
class KeyValueConfigBase
|
||||
{
|
||||
public:
|
||||
void save();
|
||||
bool save();
|
||||
void load();
|
||||
virtual ~KeyValueConfigBase();
|
||||
virtual void reset() = 0;
|
||||
@@ -36,9 +37,11 @@ protected:
|
||||
virtual QMap<QString, QString> getKeyValueMap() = 0;
|
||||
virtual void init() = 0;
|
||||
virtual void setUnreadKeys() = 0;
|
||||
bool getConfigBool(QString key, QString value);
|
||||
int getConfigInteger(QString key, QString value, int min = INT_MIN, int max = INT_MAX, int defaultValue = 0);
|
||||
uint32_t getConfigUint32(QString key, QString value, uint32_t min = 0, uint32_t max = UINT_MAX, uint32_t defaultValue = 0);
|
||||
|
||||
static bool getConfigBool(const QString &key, const QString &value);
|
||||
static int getConfigInteger(const QString &key, const QString &value, int min = INT_MIN, int max = INT_MAX, int defaultValue = 0);
|
||||
static uint32_t getConfigUint32(const QString &key, const QString &value, uint32_t min = 0, uint32_t max = UINT_MAX, uint32_t defaultValue = 0);
|
||||
static QColor getConfigColor(const QString &key, const QString &value, const QColor &defaultValue = Qt::black);
|
||||
};
|
||||
|
||||
class PorymapConfig: public KeyValueConfigBase
|
||||
@@ -92,6 +95,7 @@ public:
|
||||
this->rateLimitTimes.clear();
|
||||
this->eventSelectionShapeMode = QGraphicsPixmapItem::MaskShape;
|
||||
this->shownInGameReloadMessage = false;
|
||||
this->gridSettings = GridSettings();
|
||||
}
|
||||
void addRecentProject(QString project);
|
||||
void setRecentProjects(QStringList projects);
|
||||
@@ -156,6 +160,7 @@ public:
|
||||
QByteArray newMapDialogGeometry;
|
||||
QByteArray newLayoutDialogGeometry;
|
||||
bool shownInGameReloadMessage;
|
||||
GridSettings gridSettings;
|
||||
|
||||
protected:
|
||||
virtual QString getConfigFilepath() override;
|
||||
@@ -214,6 +219,8 @@ enum ProjectIdentifier {
|
||||
define_pals_total,
|
||||
define_tiles_per_metatile,
|
||||
define_map_size,
|
||||
define_map_offset_width,
|
||||
define_map_offset_height,
|
||||
define_mask_metatile,
|
||||
define_mask_collision,
|
||||
define_mask_elevation,
|
||||
@@ -317,18 +324,20 @@ public:
|
||||
this->defaultMetatileId = 1;
|
||||
this->defaultElevation = 3;
|
||||
this->defaultCollision = 0;
|
||||
this->defaultMapSize = QSize(20,20);
|
||||
this->defaultPrimaryTileset = "gTileset_General";
|
||||
this->prefabFilepath = QString();
|
||||
this->prefabImportPrompted = false;
|
||||
this->tilesetsHaveCallback = true;
|
||||
this->tilesetsHaveIsCompressed = true;
|
||||
this->setTransparentPixelsBlack = true;
|
||||
this->preserveMatchingOnlyData = false;
|
||||
this->filePaths.clear();
|
||||
this->eventIconPaths.clear();
|
||||
this->pokemonIconPaths.clear();
|
||||
this->collisionSheetPath = QString();
|
||||
this->collisionSheetWidth = 2;
|
||||
this->collisionSheetHeight = 16;
|
||||
this->collisionSheetSize = QSize(2, 16);
|
||||
this->playerViewDistance = QMargins(GBA_H_DIST_TO_CENTER, GBA_V_DIST_TO_CENTER, GBA_H_DIST_TO_CENTER, GBA_V_DIST_TO_CENTER);
|
||||
this->blockMetatileIdMask = 0x03FF;
|
||||
this->blockCollisionMask = 0x0C00;
|
||||
this->blockElevationMask = 0xF000;
|
||||
@@ -337,6 +346,8 @@ public:
|
||||
this->unusedTileSplit = 0x0000;
|
||||
this->maxEventsPerGroup = 255;
|
||||
this->forcedMajorVersion = 0;
|
||||
this->globalConstantsFilepaths.clear();
|
||||
this->globalConstants.clear();
|
||||
this->identifiers.clear();
|
||||
this->readKeys.clear();
|
||||
}
|
||||
@@ -382,6 +393,7 @@ public:
|
||||
uint16_t defaultMetatileId;
|
||||
uint16_t defaultElevation;
|
||||
uint16_t defaultCollision;
|
||||
QSize defaultMapSize;
|
||||
QList<uint16_t> newMapBorderMetatileIds;
|
||||
QString defaultPrimaryTileset;
|
||||
QString defaultSecondaryTileset;
|
||||
@@ -390,6 +402,7 @@ public:
|
||||
bool tilesetsHaveCallback;
|
||||
bool tilesetsHaveIsCompressed;
|
||||
bool setTransparentPixelsBlack;
|
||||
bool preserveMatchingOnlyData;
|
||||
int metatileAttributesSize;
|
||||
uint32_t metatileBehaviorMask;
|
||||
uint32_t metatileTerrainTypeMask;
|
||||
@@ -403,11 +416,13 @@ public:
|
||||
uint16_t unusedTileSplit;
|
||||
bool mapAllowFlagsEnabled;
|
||||
QString collisionSheetPath;
|
||||
int collisionSheetWidth;
|
||||
int collisionSheetHeight;
|
||||
QSize collisionSheetSize;
|
||||
QMargins playerViewDistance;
|
||||
QList<uint32_t> warpBehaviors;
|
||||
int maxEventsPerGroup;
|
||||
int forcedMajorVersion;
|
||||
QStringList globalConstantsFilepaths;
|
||||
QMap<QString,QString> globalConstants;
|
||||
|
||||
protected:
|
||||
virtual QString getConfigFilepath() override;
|
||||
|
||||
@@ -14,7 +14,7 @@ class Map;
|
||||
class Layout;
|
||||
class Blockdata;
|
||||
class Event;
|
||||
class DraggablePixmapItem;
|
||||
class EventPixmapItem;
|
||||
class Editor;
|
||||
|
||||
enum CommandId {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <QPointer>
|
||||
|
||||
#include "orderedjson.h"
|
||||
#include "parseutil.h"
|
||||
|
||||
|
||||
class Project;
|
||||
@@ -18,7 +19,7 @@ class EventFrame;
|
||||
class ObjectFrame;
|
||||
class CloneObjectFrame;
|
||||
class WarpFrame;
|
||||
class DraggablePixmapItem;
|
||||
class EventPixmapItem;
|
||||
|
||||
class Event;
|
||||
class ObjectEvent;
|
||||
@@ -78,9 +79,13 @@ public:
|
||||
None,
|
||||
};
|
||||
|
||||
// all event groups except warps have IDs that start at 1
|
||||
// Normally we refer to events using their index in the list of that group's events.
|
||||
// Object events often get referred to with a special "local ID", which is really just the index + 1.
|
||||
// We use this local ID number in the index spinner for object events instead of the actual index.
|
||||
// This distinction is only really important for object and warp events, because these are normally
|
||||
// the only two groups of events that need to be explicitly referred to.
|
||||
static int getIndexOffset(Event::Group group) {
|
||||
return (group == Event::Group::Warp) ? 0 : 1;
|
||||
return (group == Event::Group::Object) ? 1 : 0;
|
||||
}
|
||||
|
||||
static Event::Group typeToGroup(Event::Type type) {
|
||||
@@ -139,23 +144,22 @@ public:
|
||||
Event::Type getEventType() const { return this->eventType; }
|
||||
|
||||
virtual OrderedJson::object buildEventJson(Project *project) = 0;
|
||||
virtual bool loadFromJson(const QJsonObject &json, Project *project) = 0;
|
||||
virtual bool loadFromJson(QJsonObject json, Project *project) = 0;
|
||||
|
||||
virtual void setDefaultValues(Project *project);
|
||||
|
||||
virtual QSet<QString> getExpectedFields() = 0;
|
||||
void readCustomAttributes(const QJsonObject &json);
|
||||
void addCustomAttributesTo(OrderedJson::object *obj) const;
|
||||
const QMap<QString, QJsonValue> getCustomAttributes() const { return this->customAttributes; }
|
||||
void setCustomAttributes(const QMap<QString, QJsonValue> newCustomAttributes) { this->customAttributes = newCustomAttributes; }
|
||||
|
||||
virtual void loadPixmap(Project *project);
|
||||
QJsonObject getCustomAttributes() const { return this->customAttributes; }
|
||||
void setCustomAttributes(const QJsonObject &newCustomAttributes) { this->customAttributes = newCustomAttributes; }
|
||||
|
||||
virtual QPixmap loadPixmap(Project *project);
|
||||
|
||||
void setPixmap(QPixmap newPixmap) { this->pixmap = newPixmap; }
|
||||
QPixmap getPixmap() const { return this->pixmap; }
|
||||
|
||||
void setPixmapItem(DraggablePixmapItem *item);
|
||||
DraggablePixmapItem *getPixmapItem() const { return this->pixmapItem; }
|
||||
void setPixmapItem(EventPixmapItem *item);
|
||||
EventPixmapItem *getPixmapItem() const { return this->pixmapItem; }
|
||||
|
||||
void setUsesDefaultPixmap(bool newUsesDefaultPixmap) { this->usesDefaultPixmap = newUsesDefaultPixmap; }
|
||||
bool getUsesDefaultPixmap() const { return this->usesDefaultPixmap; }
|
||||
@@ -191,12 +195,16 @@ protected:
|
||||
// When deleting events like this we want to warn the user that the #define may also be deleted.
|
||||
QString idName;
|
||||
|
||||
QMap<QString, QJsonValue> customAttributes;
|
||||
QJsonObject customAttributes;
|
||||
|
||||
QPixmap pixmap;
|
||||
DraggablePixmapItem *pixmapItem = nullptr;
|
||||
EventPixmapItem *pixmapItem = nullptr;
|
||||
|
||||
QPointer<EventFrame> eventFrame;
|
||||
|
||||
static QString readString(QJsonObject *object, const QString &key) { return ParseUtil::jsonToQString(object->take(key)); }
|
||||
static int readInt(QJsonObject *object, const QString &key) { return ParseUtil::jsonToInt(object->take(key)); }
|
||||
static bool readBool(QJsonObject *object, const QString &key) { return ParseUtil::jsonToBool(object->take(key)); }
|
||||
};
|
||||
|
||||
|
||||
@@ -219,13 +227,13 @@ public:
|
||||
virtual EventFrame *createEventFrame() override;
|
||||
|
||||
virtual OrderedJson::object buildEventJson(Project *project) override;
|
||||
virtual bool loadFromJson(const QJsonObject &json, Project *project) override;
|
||||
virtual bool loadFromJson(QJsonObject json, Project *project) override;
|
||||
|
||||
virtual void setDefaultValues(Project *project) override;
|
||||
|
||||
virtual QSet<QString> getExpectedFields() override;
|
||||
|
||||
virtual void loadPixmap(Project *project) override;
|
||||
virtual QPixmap loadPixmap(Project *project) override;
|
||||
|
||||
void setGfx(QString newGfx) { this->gfx = newGfx; }
|
||||
QString getGfx() const { return this->gfx; }
|
||||
@@ -286,23 +294,23 @@ public:
|
||||
virtual EventFrame *createEventFrame() override;
|
||||
|
||||
virtual OrderedJson::object buildEventJson(Project *project) override;
|
||||
virtual bool loadFromJson(const QJsonObject &json, Project *project) override;
|
||||
virtual bool loadFromJson(QJsonObject json, Project *project) override;
|
||||
|
||||
virtual void setDefaultValues(Project *project) override;
|
||||
|
||||
virtual QSet<QString> getExpectedFields() override;
|
||||
|
||||
virtual void loadPixmap(Project *project) override;
|
||||
virtual QPixmap loadPixmap(Project *project) override;
|
||||
|
||||
void setTargetMap(QString newTargetMap) { this->targetMap = newTargetMap; }
|
||||
QString getTargetMap() const { return this->targetMap; }
|
||||
|
||||
void setTargetID(int newTargetID) { this->targetID = newTargetID; }
|
||||
int getTargetID() const { return this->targetID; }
|
||||
void setTargetID(QString newTargetID) { this->targetID = newTargetID; }
|
||||
QString getTargetID() const { return this->targetID; }
|
||||
|
||||
private:
|
||||
QString targetMap;
|
||||
int targetID = 0;
|
||||
QString targetID;
|
||||
};
|
||||
|
||||
|
||||
@@ -324,7 +332,7 @@ public:
|
||||
virtual EventFrame *createEventFrame() override;
|
||||
|
||||
virtual OrderedJson::object buildEventJson(Project *project) override;
|
||||
virtual bool loadFromJson(const QJsonObject &json, Project *project) override;
|
||||
virtual bool loadFromJson(QJsonObject json, Project *project) override;
|
||||
|
||||
virtual void setDefaultValues(Project *project) override;
|
||||
|
||||
@@ -361,7 +369,7 @@ public:
|
||||
virtual EventFrame *createEventFrame() override = 0;
|
||||
|
||||
virtual OrderedJson::object buildEventJson(Project *project) override = 0;
|
||||
virtual bool loadFromJson(const QJsonObject &json, Project *project) override = 0;
|
||||
virtual bool loadFromJson(QJsonObject json, Project *project) override = 0;
|
||||
|
||||
virtual void setDefaultValues(Project *project) override = 0;
|
||||
|
||||
@@ -389,7 +397,7 @@ public:
|
||||
virtual EventFrame *createEventFrame() override;
|
||||
|
||||
virtual OrderedJson::object buildEventJson(Project *project) override;
|
||||
virtual bool loadFromJson(const QJsonObject &json, Project *project) override;
|
||||
virtual bool loadFromJson(QJsonObject json, Project *project) override;
|
||||
|
||||
virtual void setDefaultValues(Project *project) override;
|
||||
|
||||
@@ -429,7 +437,7 @@ public:
|
||||
virtual EventFrame *createEventFrame() override;
|
||||
|
||||
virtual OrderedJson::object buildEventJson(Project *project) override;
|
||||
virtual bool loadFromJson(const QJsonObject &json, Project *project) override;
|
||||
virtual bool loadFromJson(QJsonObject json, Project *project) override;
|
||||
|
||||
virtual void setDefaultValues(Project *project) override;
|
||||
|
||||
@@ -460,7 +468,7 @@ public:
|
||||
virtual EventFrame *createEventFrame() override = 0;
|
||||
|
||||
virtual OrderedJson::object buildEventJson(Project *project) override = 0;
|
||||
virtual bool loadFromJson(const QJsonObject &json, Project *project) override = 0;
|
||||
virtual bool loadFromJson(QJsonObject json, Project *project) override = 0;
|
||||
|
||||
virtual void setDefaultValues(Project *project) override = 0;
|
||||
|
||||
@@ -487,7 +495,7 @@ public:
|
||||
virtual EventFrame *createEventFrame() override;
|
||||
|
||||
virtual OrderedJson::object buildEventJson(Project *project) override;
|
||||
virtual bool loadFromJson(const QJsonObject &json, Project *project) override;
|
||||
virtual bool loadFromJson(QJsonObject json, Project *project) override;
|
||||
|
||||
virtual void setDefaultValues(Project *project) override;
|
||||
|
||||
@@ -522,7 +530,7 @@ public:
|
||||
virtual EventFrame *createEventFrame() override;
|
||||
|
||||
virtual OrderedJson::object buildEventJson(Project *project) override;
|
||||
virtual bool loadFromJson(const QJsonObject &json, Project *project) override;
|
||||
virtual bool loadFromJson(QJsonObject json, Project *project) override;
|
||||
|
||||
virtual void setDefaultValues(Project *project) override;
|
||||
|
||||
@@ -567,7 +575,7 @@ public:
|
||||
virtual EventFrame *createEventFrame() override;
|
||||
|
||||
virtual OrderedJson::object buildEventJson(Project *project) override;
|
||||
virtual bool loadFromJson(const QJsonObject &json, Project *project) override;
|
||||
virtual bool loadFromJson(QJsonObject json, Project *project) override;
|
||||
|
||||
virtual void setDefaultValues(Project *project) override;
|
||||
|
||||
@@ -599,12 +607,15 @@ public:
|
||||
virtual EventFrame *createEventFrame() override;
|
||||
|
||||
virtual OrderedJson::object buildEventJson(Project *project) override;
|
||||
virtual bool loadFromJson(const QJsonObject &, Project *) override;
|
||||
virtual bool loadFromJson(QJsonObject json, Project *project) override;
|
||||
|
||||
virtual void setDefaultValues(Project *project) override;
|
||||
|
||||
virtual QSet<QString> getExpectedFields() override;
|
||||
|
||||
void setHostMapName(QString newHostMapName) { this->hostMapName = newHostMapName; }
|
||||
QString getHostMapName() const;
|
||||
|
||||
void setRespawnMapName(QString newRespawnMapName) { this->respawnMapName = newRespawnMapName; }
|
||||
QString getRespawnMapName() const { return this->respawnMapName; }
|
||||
|
||||
@@ -614,6 +625,7 @@ public:
|
||||
private:
|
||||
QString respawnMapName;
|
||||
QString respawnNPC;
|
||||
QString hostMapName; // Only needed if the host map fails to load.
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -22,10 +22,6 @@
|
||||
#define MAX_BORDER_WIDTH 255
|
||||
#define MAX_BORDER_HEIGHT 255
|
||||
|
||||
// Number of metatiles to draw out from edge of map. Could allow modification of this in the future.
|
||||
// porymap will reflect changes to it, but the value is hard-coded in the projects at the moment
|
||||
#define BORDER_DISTANCE 7
|
||||
|
||||
class LayoutPixmapItem;
|
||||
class CollisionPixmapItem;
|
||||
class BorderMetatilesPixmapItem;
|
||||
@@ -76,6 +72,8 @@ public:
|
||||
void resetEvents();
|
||||
QList<Event *> getEvents(Event::Group group = Event::Group::None) const;
|
||||
Event* getEvent(Event::Group group, int index) const;
|
||||
Event* getEvent(Event::Group group, const QString &idName) const;
|
||||
QStringList getEventIdNames(Event::Group group) const;
|
||||
int getNumEvents(Event::Group group = Event::Group::None) const;
|
||||
QStringList getScriptLabels(Event::Group group = Event::Group::None);
|
||||
QString getScriptsFilePath() const;
|
||||
@@ -87,6 +85,7 @@ public:
|
||||
|
||||
void deleteConnections();
|
||||
QList<MapConnection*> getConnections() const { return m_connections; }
|
||||
MapConnection* getConnection(const QString &direction) const;
|
||||
void removeConnection(MapConnection *);
|
||||
void addConnection(MapConnection *);
|
||||
void loadConnection(MapConnection *);
|
||||
@@ -100,8 +99,8 @@ public:
|
||||
bool hasUnsavedChanges() const;
|
||||
void pruneEditHistory();
|
||||
|
||||
void setCustomAttributes(const QMap<QString, QJsonValue> &attributes) { m_customAttributes = attributes; }
|
||||
QMap<QString, QJsonValue> customAttributes() const { return m_customAttributes; }
|
||||
void setCustomAttributes(const QJsonObject &attributes) { m_customAttributes = attributes; }
|
||||
QJsonObject customAttributes() const { return m_customAttributes; }
|
||||
|
||||
private:
|
||||
QString m_name;
|
||||
@@ -110,7 +109,7 @@ private:
|
||||
QString m_sharedScriptsMap = "";
|
||||
|
||||
QStringList m_scriptsFileLabels;
|
||||
QMap<QString, QJsonValue> m_customAttributes;
|
||||
QJsonObject m_customAttributes;
|
||||
|
||||
MapHeader *m_header = nullptr;
|
||||
Layout *m_layout = nullptr;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <QString>
|
||||
#include <QObject>
|
||||
#include <QMap>
|
||||
#include <QJsonObject>
|
||||
|
||||
class Project;
|
||||
class Map;
|
||||
@@ -34,6 +35,9 @@ public:
|
||||
int offset() const { return m_offset; }
|
||||
void setOffset(int offset, bool mirror = true);
|
||||
|
||||
QJsonObject customData() const { return m_customData; }
|
||||
void setCustomData(const QJsonObject &customData) { m_customData = customData; }
|
||||
|
||||
MapConnection* findMirror();
|
||||
MapConnection* createMirror();
|
||||
|
||||
@@ -55,6 +59,7 @@ private:
|
||||
QString m_targetMapName;
|
||||
QString m_direction;
|
||||
int m_offset;
|
||||
QJsonObject m_customData;
|
||||
|
||||
void markMapEdited();
|
||||
Map* getMap(const QString& mapName) const;
|
||||
|
||||
@@ -42,6 +42,8 @@ public:
|
||||
Tileset *tileset_primary = nullptr;
|
||||
Tileset *tileset_secondary = nullptr;
|
||||
|
||||
QJsonObject customData;
|
||||
|
||||
Blockdata blockdata;
|
||||
|
||||
QImage image;
|
||||
@@ -94,8 +96,8 @@ public:
|
||||
int getHeight() const { return height; }
|
||||
int getBorderWidth() const { return border_width; }
|
||||
int getBorderHeight() const { return border_height; }
|
||||
int getBorderDrawWidth() const;
|
||||
int getBorderDrawHeight() const;
|
||||
QMargins getBorderMargins() const;
|
||||
QRect getVisibleRect() const;
|
||||
|
||||
bool isWithinBounds(int x, int y) const;
|
||||
bool isWithinBounds(const QRect &rect) const;
|
||||
@@ -105,8 +107,8 @@ 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 adjustDimensions(const QMargins &margins, bool setNewBlockdata = true);
|
||||
void setDimensions(int newWidth, int newHeight, bool setNewBlockdata = true);
|
||||
void setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false);
|
||||
|
||||
void cacheBlockdata();
|
||||
@@ -114,9 +116,12 @@ public:
|
||||
void clearBorderCache();
|
||||
void cacheBorder();
|
||||
|
||||
void setClean();
|
||||
bool hasUnsavedChanges() const;
|
||||
|
||||
bool save(const QString &root);
|
||||
bool saveBorder(const QString &root);
|
||||
bool saveBlockdata(const QString &root);
|
||||
|
||||
bool layoutBlockChanged(int i, const Blockdata &cache);
|
||||
|
||||
uint16_t getBorderMetatileId(int x, int y);
|
||||
@@ -141,6 +146,7 @@ public:
|
||||
private:
|
||||
void setNewDimensionsBlockdata(int newWidth, int newHeight);
|
||||
void setNewBorderDimensionsBlockdata(int newWidth, int newHeight);
|
||||
bool writeBlockdata(const QString &path, const Blockdata &blockdata) const;
|
||||
|
||||
static int getBorderDrawDistance(int dimension, qreal minimum);
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
namespace PaletteUtil {
|
||||
QList<QRgb> parse(QString filepath, bool *error);
|
||||
void writeJASC(QString filepath, QVector<QRgb> colors, int offset, int nColors);
|
||||
bool writeJASC(const QString &filepath, const QVector<QRgb> &colors, int offset, int nColors);
|
||||
}
|
||||
|
||||
#endif // PALETTEUTIL_H
|
||||
|
||||
@@ -43,7 +43,7 @@ class ParseUtil
|
||||
{
|
||||
public:
|
||||
ParseUtil();
|
||||
void set_root(const QString &dir);
|
||||
void setRoot(const QString &dir) { this->root = dir; }
|
||||
static QString readTextFile(const QString &path, QString *error = nullptr);
|
||||
bool cacheFile(const QString &path, QString *error = nullptr);
|
||||
void clearFileCache() { this->fileCache.clear(); }
|
||||
@@ -55,10 +55,14 @@ public:
|
||||
QString readCIncbin(const QString &text, const QString &label);
|
||||
QMap<QString, QString> readCIncbinMulti(const QString &filepath);
|
||||
QStringList readCIncbinArray(const QString &filename, const QString &label);
|
||||
QMap<QString, int> readCDefinesByRegex(const QString &filename, const QSet<QString> ®exList, QString *error = nullptr);
|
||||
QMap<QString, int> readCDefinesByName(const QString &filename, const QSet<QString> &names, QString *error = nullptr);
|
||||
QHash<QString, int> readCDefinesByRegex(const QString &filename, const QSet<QString> ®exList, QString *error = nullptr);
|
||||
QHash<QString, int> readCDefinesByName(const QString &filename, const QSet<QString> &names, QString *error = nullptr);
|
||||
QStringList readCDefineNames(const QString &filename, const QSet<QString> ®exList, QString *error = nullptr);
|
||||
tsl::ordered_map<QString, QHash<QString, QString>> readCStructs(const QString &, const QString & = "", const QHash<int, QString>& = {});
|
||||
void loadGlobalCDefinesFromFile(const QString &filename, QString *error = nullptr);
|
||||
void loadGlobalCDefines(const QMap<QString,QString> &defines);
|
||||
void loadGlobalCDefines(const QHash<QString,QString> &defines);
|
||||
void resetCDefines();
|
||||
OrderedMap<QString, QHash<QString, QString>> readCStructs(const QString &, const QString & = "", const QHash<int, QString>& = {});
|
||||
QList<QStringList> getLabelMacros(const QList<QStringList>&, const QString&);
|
||||
QStringList getLabelValues(const QList<QStringList>&, const QString&);
|
||||
bool tryParseJsonFile(QJsonDocument *out, const QString &filepath, QString *error = nullptr);
|
||||
@@ -90,8 +94,20 @@ private:
|
||||
QString curDefine;
|
||||
QHash<QString, QString> fileCache;
|
||||
QHash<QString, QStringList> errorMap;
|
||||
int evaluateDefine(const QString&, const QString &, QMap<QString, int>*, QMap<QString, QString>*);
|
||||
QList<Token> tokenizeExpression(QString, QMap<QString, int>*, QMap<QString, QString>*);
|
||||
|
||||
// The maps of define names to values/expressions that are available while parsing C defines.
|
||||
// As the parser reads and evaluates more defines it will update these maps accordingly.
|
||||
QHash<QString, int> knownDefineValues;
|
||||
QHash<QString, QString> knownDefineExpressions;
|
||||
|
||||
// Maps of special define names to values/expressions that take precedence over defines encountered while parsing.
|
||||
// Some (like 'TRUE'/'FALSE') are always present in these maps, others may be specified by the user with 'loadGlobalCDefines' / 'loadGlobalCDefinesFromFile'.
|
||||
QHash<QString, int> globalDefineValues;
|
||||
QHash<QString, QString> globalDefineExpressions;
|
||||
|
||||
int evaluateDefine(const QString &identifier, bool *ok = nullptr);
|
||||
int evaluateExpression(const QString &expression);
|
||||
QList<Token> tokenizeExpression(QString expression);
|
||||
QList<Token> generatePostfix(const QList<Token> &tokens);
|
||||
int evaluatePostfix(const QList<Token> &postfix);
|
||||
void recordError(const QString &message);
|
||||
@@ -100,11 +116,11 @@ private:
|
||||
QString createErrorMessage(const QString &message, const QString &expression);
|
||||
|
||||
struct ParsedDefines {
|
||||
QMap<QString,QString> expressions; // Map of all define names encountered to their expressions
|
||||
QHash<QString,QString> expressions; // Map of all define names encountered to their expressions
|
||||
QStringList filteredNames; // List of define names that matched the search text, in the order that they were encountered
|
||||
};
|
||||
ParsedDefines readCDefines(const QString &filename, const QSet<QString> &filterList, bool useRegex, QString *error);
|
||||
QMap<QString, int> evaluateCDefines(const QString &filename, const QSet<QString> &filterList, bool useRegex, QString *error);
|
||||
QHash<QString, int> evaluateCDefines(const QString &filename, const QSet<QString> &filterList, bool useRegex, QString *error);
|
||||
bool defineNameMatchesFilter(const QString &name, const QSet<QString> &filterList) const;
|
||||
bool defineNameMatchesFilter(const QString &name, const QSet<QRegularExpression> &filterList) const;
|
||||
QString loadTextFile(const QString &path, QString *error = nullptr);
|
||||
|
||||
@@ -56,8 +56,8 @@ public:
|
||||
bool loadLayout(poryjson::Json);
|
||||
bool loadEntries();
|
||||
|
||||
void setEntries(QMap<QString, MapSectionEntry> *entries) { this->region_map_entries = entries; }
|
||||
void setEntries(const QMap<QString, MapSectionEntry> &entries) { *(this->region_map_entries) = entries; }
|
||||
void setEntries(QHash<QString, MapSectionEntry> *entries) { this->region_map_entries = entries; }
|
||||
void setEntries(const QHash<QString, MapSectionEntry> &entries) { *(this->region_map_entries) = entries; }
|
||||
void clearEntries() { this->region_map_entries->clear(); }
|
||||
MapSectionEntry getEntry(QString section);
|
||||
void setEntry(QString section, MapSectionEntry entry);
|
||||
@@ -151,7 +151,7 @@ signals:
|
||||
void mapNeedsDisplaying();
|
||||
|
||||
private:
|
||||
QMap<QString, MapSectionEntry> *region_map_entries = nullptr;
|
||||
QHash<QString, MapSectionEntry> *region_map_entries = nullptr;
|
||||
|
||||
QString alias = "";
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ private:
|
||||
/// ClearEntries
|
||||
class ClearEntries : public QUndoCommand {
|
||||
public:
|
||||
ClearEntries(RegionMap *map, QMap<QString, MapSectionEntry>, QUndoCommand *parent = nullptr);
|
||||
ClearEntries(RegionMap *map, QHash<QString, MapSectionEntry>, QUndoCommand *parent = nullptr);
|
||||
|
||||
void undo() override;
|
||||
void redo() override;
|
||||
@@ -163,7 +163,7 @@ public:
|
||||
|
||||
private:
|
||||
RegionMap *map;
|
||||
QMap<QString, MapSectionEntry> entries;
|
||||
QHash<QString, MapSectionEntry> entries;
|
||||
};
|
||||
|
||||
#endif // REGIONMAPEDITCOMMANDS_H
|
||||
|
||||
@@ -55,17 +55,17 @@ public:
|
||||
static QString getExpectedDir(QString tilesetName, bool isSecondary);
|
||||
QString getExpectedDir();
|
||||
|
||||
void load();
|
||||
void loadMetatiles();
|
||||
void loadMetatileAttributes();
|
||||
void loadTilesImage(QImage *importedImage = nullptr);
|
||||
void loadPalettes();
|
||||
bool load();
|
||||
bool loadMetatiles();
|
||||
bool loadMetatileAttributes();
|
||||
bool loadTilesImage(QImage *importedImage = nullptr);
|
||||
bool loadPalettes();
|
||||
|
||||
void save();
|
||||
void saveMetatileAttributes();
|
||||
void saveMetatiles();
|
||||
void saveTilesImage();
|
||||
void savePalettes();
|
||||
bool save();
|
||||
bool saveMetatileAttributes();
|
||||
bool saveMetatiles();
|
||||
bool saveTilesImage();
|
||||
bool savePalettes();
|
||||
|
||||
bool appendToHeaders(QString root, QString friendlyName, bool usingAsm);
|
||||
bool appendToGraphics(QString root, QString friendlyName, bool usingAsm);
|
||||
|
||||
@@ -9,6 +9,8 @@ namespace Util {
|
||||
int roundUp(int numToRound, int multiple);
|
||||
QString toDefineCase(QString input);
|
||||
QString toHexString(uint32_t value, int minLength = 0);
|
||||
QString toHtmlParagraph(const QString &text);
|
||||
Qt::Orientations getOrientation(bool xflip, bool yflip);
|
||||
}
|
||||
|
||||
#endif // UTILITY_H
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#define GUARD_WILDMONINFO_H
|
||||
|
||||
#include <QtWidgets>
|
||||
#include "orderedmap.h"
|
||||
#include "orderedjson.h"
|
||||
|
||||
class WildPokemon {
|
||||
public:
|
||||
@@ -13,22 +13,26 @@ public:
|
||||
int minLevel;
|
||||
int maxLevel;
|
||||
QString species;
|
||||
OrderedJson::object customData;
|
||||
};
|
||||
|
||||
struct WildMonInfo {
|
||||
bool active = false;
|
||||
int encounterRate = 0;
|
||||
QVector<WildPokemon> wildPokemon;
|
||||
OrderedJson::object customData;
|
||||
};
|
||||
|
||||
struct WildPokemonHeader {
|
||||
tsl::ordered_map<QString, WildMonInfo> wildMons;
|
||||
OrderedMap<QString, WildMonInfo> wildMons;
|
||||
OrderedJson::object customData;
|
||||
};
|
||||
|
||||
struct EncounterField {
|
||||
QString name; // Ex: "fishing_mons"
|
||||
QVector<int> encounterRates;
|
||||
tsl::ordered_map<QString, QVector<int>> groups; // Ex: "good_rod", {2, 3, 4}
|
||||
OrderedMap<QString, QVector<int>> groups; // Ex: "good_rod", {2, 3, 4}
|
||||
OrderedJson::object customData;
|
||||
};
|
||||
|
||||
typedef QVector<EncounterField> EncounterFields;
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include "mapruler.h"
|
||||
#include "encountertablemodel.h"
|
||||
|
||||
class DraggablePixmapItem;
|
||||
class EventPixmapItem;
|
||||
class MetatilesPixmapItem;
|
||||
|
||||
class Editor : public QObject
|
||||
@@ -57,8 +57,8 @@ public:
|
||||
GridSettings gridSettings;
|
||||
|
||||
void setProject(Project * project);
|
||||
void saveAll();
|
||||
void saveCurrent();
|
||||
bool saveAll();
|
||||
bool saveCurrent();
|
||||
void saveEncounterTabData();
|
||||
|
||||
void closeProject();
|
||||
@@ -92,14 +92,16 @@ public:
|
||||
void setConnectionsVisibility(bool visible);
|
||||
void updateDivingMapsVisibility();
|
||||
void renderDivingConnections();
|
||||
void addConnection(MapConnection* connection);
|
||||
void addNewConnection(const QString &mapName, const QString &direction);
|
||||
void replaceConnection(const QString &mapName, const QString &direction);
|
||||
void removeConnection(MapConnection* connection);
|
||||
void removeSelectedConnection();
|
||||
void addNewWildMonGroup(QWidget *window);
|
||||
void deleteWildMonGroup();
|
||||
void configureEncounterJSON(QWidget *);
|
||||
EncounterTableModel* getCurrentWildMonTable();
|
||||
void updateDiveMap(QString mapName);
|
||||
void updateEmergeMap(QString mapName);
|
||||
bool setDivingMapName(const QString &mapName, const QString &direction);
|
||||
QString getDivingMapName(const QString &direction) const;
|
||||
void setSelectedConnection(MapConnection *connection);
|
||||
|
||||
void updatePrimaryTileset(QString tilesetLabel, bool forceLoad = false);
|
||||
@@ -107,7 +109,7 @@ public:
|
||||
void toggleBorderVisibility(bool visible, bool enableScriptCallback = true);
|
||||
void updateCustomMapAttributes();
|
||||
|
||||
DraggablePixmapItem *addEventPixmapItem(Event *event);
|
||||
EventPixmapItem *addEventPixmapItem(Event *event);
|
||||
void removeEventPixmapItem(Event *event);
|
||||
bool canAddEvents(const QList<Event*> &events);
|
||||
void selectMapEvent(Event *event, bool toggle = false);
|
||||
@@ -116,12 +118,16 @@ public:
|
||||
void duplicateSelectedEvents();
|
||||
void redrawAllEvents();
|
||||
void redrawEvents(const QList<Event*> &events);
|
||||
void redrawEventPixmapItem(DraggablePixmapItem *item);
|
||||
void redrawEventPixmapItem(EventPixmapItem *item);
|
||||
void updateEventPixmapItemZValue(EventPixmapItem *item);
|
||||
qreal getEventOpacity(const Event *event) const;
|
||||
|
||||
void setPlayerViewRect(const QRectF &rect);
|
||||
void updateCursorRectPos(int x, int y);
|
||||
void setCursorRectVisible(bool visible);
|
||||
|
||||
void onEventDragged(Event *event, const QPoint &oldPosition, const QPoint &newPosition);
|
||||
void onEventReleased(Event *event, const QPoint &position);
|
||||
void updateWarpEventWarning(Event *event);
|
||||
void updateWarpEventWarnings();
|
||||
|
||||
@@ -172,10 +178,7 @@ public:
|
||||
static QList<QList<const QImage*>> collisionIcons;
|
||||
|
||||
int eventShiftActionId = 0;
|
||||
|
||||
void eventsView_onMousePress(QMouseEvent *event);
|
||||
|
||||
bool selectingEvent = false;
|
||||
int eventMoveActionId = 0;
|
||||
|
||||
void deleteSelectedEvents();
|
||||
void shouldReselectEvents();
|
||||
@@ -183,6 +186,22 @@ public:
|
||||
static void openInTextEditor(const QString &path, int lineNum = 0);
|
||||
void setCollisionGraphics();
|
||||
|
||||
enum ZValue {
|
||||
MapBorder = -4,
|
||||
MapConnectionInactive = -3,
|
||||
MapConnectionActive = -2,
|
||||
MapConnectionMask = -1,
|
||||
|
||||
// Event pixmaps set their z value to be their y position on the map.
|
||||
// Their y value is int16_t, so we have enough space to allocate the
|
||||
// full range + 1 for the selected event (which should always be on top).
|
||||
EventMinimum = 1,
|
||||
EventMaximum = EventMinimum + 0x10000,
|
||||
|
||||
Ruler,
|
||||
ResizeLayoutPopup
|
||||
};
|
||||
|
||||
public slots:
|
||||
void openMapScripts() const;
|
||||
void openScript(const QString &scriptLabel) const;
|
||||
@@ -199,7 +218,7 @@ private:
|
||||
|
||||
EditMode editMode = EditMode::None;
|
||||
|
||||
void save(bool currentOnly);
|
||||
bool save(bool currentOnly);
|
||||
void clearMap();
|
||||
void clearMetatileSelector();
|
||||
void clearMovementPermissionSelector();
|
||||
@@ -218,8 +237,9 @@ private:
|
||||
void removeConnectionPixmap(MapConnection *connection);
|
||||
void displayConnection(MapConnection *connection);
|
||||
void displayDivingConnection(MapConnection *connection);
|
||||
void setDivingMapName(QString mapName, QString direction);
|
||||
void removeDivingMapPixmap(MapConnection *connection);
|
||||
void onDivingMapEditingFinished(NoScrollComboBox* combo, const QString &direction);
|
||||
void updateDivingMapButton(QToolButton* button, const QString &mapName);
|
||||
void updateEncounterFields(EncounterFields newFields);
|
||||
QString getMovementPermissionText(uint16_t collision, uint16_t elevation);
|
||||
QString getMetatileDisplayMessage(uint16_t metatileId);
|
||||
@@ -249,11 +269,11 @@ private slots:
|
||||
|
||||
signals:
|
||||
void eventsChanged();
|
||||
void openEventMap(Event*);
|
||||
void openConnectedMap(MapConnection*);
|
||||
void wildMonTableOpened(EncounterTableModel*);
|
||||
void wildMonTableClosed();
|
||||
void wildMonTableEdited();
|
||||
void warpEventDoubleClicked(QString, int, Event::Group);
|
||||
void currentMetatilesSelectionChanged();
|
||||
void mapRulerStatusChanged(const QString &);
|
||||
void tilesetUpdated(QString);
|
||||
|
||||
@@ -99,7 +99,7 @@ public:
|
||||
|
||||
// Array and object typedefs
|
||||
typedef QVector<Json> array;
|
||||
typedef tsl::ordered_map<QString, Json> object;
|
||||
typedef OrderedMap<QString, Json> object;
|
||||
|
||||
// Constructors for the various types of JSON value.
|
||||
Json() noexcept; // NUL
|
||||
@@ -132,7 +132,22 @@ public:
|
||||
int>::type = 0>
|
||||
Json(const V & v) : Json(array(v.begin(), v.end())) {}
|
||||
|
||||
static const Json fromQJsonValue(QJsonValue value);
|
||||
static Json fromQJsonValue(const QJsonValue &value);
|
||||
|
||||
static void append(Json::array *array, const QJsonArray &addendum) {
|
||||
for (const auto &i : addendum) array->push_back(fromQJsonValue(i));
|
||||
}
|
||||
static void append(Json::array *array, const Json::array &addendum) {
|
||||
for (const auto &i : addendum) array->push_back(i);
|
||||
}
|
||||
static void append(Json::object *object, const QJsonObject &addendum) {
|
||||
for (auto it = addendum.constBegin(); it != addendum.constEnd(); it++)
|
||||
(*object)[it.key()] = fromQJsonValue(it.value());
|
||||
}
|
||||
static void append(Json::object *object, const Json::object &addendum) {
|
||||
for (auto it = addendum.cbegin(); it != addendum.cend(); it++)
|
||||
(*object)[it.key()] = it.value();
|
||||
}
|
||||
|
||||
// This prevents Json(some_pointer) from accidentally producing a bool. Use
|
||||
// Json(bool(some_pointer)) if that behavior is desired.
|
||||
|
||||
@@ -1977,6 +1977,14 @@ public:
|
||||
size_type erase(const K& key, std::size_t precalculated_hash) {
|
||||
return m_ht.erase(key, precalculated_hash);
|
||||
}
|
||||
|
||||
// Naive solution for take, should probably be replaced with one that does a single lookup and no unnecessary insertion.
|
||||
// We want to mirror the behavior of QMap::take, which returns a default-constructed value if the key is not present.
|
||||
T take(const key_type& key) {
|
||||
typename ValueSelect::value_type value = m_ht[key];
|
||||
m_ht.erase(key);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2404,4 +2412,7 @@ private:
|
||||
|
||||
} // end namespace tsl
|
||||
|
||||
template<class Key, class T>
|
||||
using OrderedMap = tsl::ordered_map<Key, T>;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -52,6 +52,8 @@ public:
|
||||
MainWindow(const MainWindow &) = delete;
|
||||
MainWindow & operator = (const MainWindow &) = delete;
|
||||
|
||||
void initialize();
|
||||
|
||||
// Scripting API
|
||||
Q_INVOKABLE QJSValue getBlock(int x, int y);
|
||||
void tryRedrawMapArea(bool forceRedraw);
|
||||
@@ -175,9 +177,9 @@ private slots:
|
||||
void on_action_Reload_Project_triggered();
|
||||
void on_action_Close_Project_triggered();
|
||||
void on_action_Save_Project_triggered();
|
||||
void save(bool currentOnly = false);
|
||||
bool save(bool currentOnly = false);
|
||||
|
||||
void openWarpMap(QString map_name, int event_id, Event::Group event_group);
|
||||
void openEventMap(Event *event);
|
||||
|
||||
void duplicate();
|
||||
void setClipboardData(poryjson::Json::object);
|
||||
@@ -197,8 +199,7 @@ private slots:
|
||||
void onMapLoaded(Map *map);
|
||||
void onMapRulerStatusChanged(const QString &);
|
||||
void applyUserShortcuts();
|
||||
void markMapEdited();
|
||||
void markSpecificMapEdited(Map*);
|
||||
void markMapEdited(Map*);
|
||||
void markLayoutEdited();
|
||||
|
||||
void on_actionNew_Tileset_triggered();
|
||||
@@ -243,13 +244,9 @@ private slots:
|
||||
void on_pushButton_AddConnection_clicked();
|
||||
void on_button_OpenDiveMap_clicked();
|
||||
void on_button_OpenEmergeMap_clicked();
|
||||
void on_comboBox_DiveMap_currentTextChanged(const QString &mapName);
|
||||
void on_comboBox_EmergeMap_currentTextChanged(const QString &mapName);
|
||||
void on_comboBox_PrimaryTileset_currentTextChanged(const QString &arg1);
|
||||
void on_comboBox_SecondaryTileset_currentTextChanged(const QString &arg1);
|
||||
void on_pushButton_ChangeDimensions_clicked();
|
||||
void on_checkBox_smartPaths_stateChanged(int selected);
|
||||
void on_checkBox_ToggleBorder_stateChanged(int selected);
|
||||
|
||||
void resetMapViewScale();
|
||||
|
||||
@@ -260,7 +257,6 @@ private slots:
|
||||
|
||||
void eventTabChanged(int index);
|
||||
|
||||
void on_checkBox_MirrorConnections_stateChanged(int selected);
|
||||
void on_actionDive_Emerge_Map_triggered();
|
||||
void on_actionShow_Events_In_Map_View_triggered();
|
||||
void on_groupBox_DiveMapOpacity_toggled(bool on);
|
||||
@@ -437,6 +433,10 @@ private:
|
||||
|
||||
void checkForUpdates(bool requestedByUser);
|
||||
void setDivingMapsVisible(bool visible);
|
||||
|
||||
void setSmartPathsEnabled(bool enabled);
|
||||
void setBorderVisibility(bool visible);
|
||||
void setMirrorConnectionsEnabled(bool enabled);
|
||||
};
|
||||
|
||||
// These are namespaced in a struct to avoid colliding with e.g. class Map.
|
||||
|
||||
@@ -62,7 +62,6 @@ public:
|
||||
QStringList mapSectionIdNames;
|
||||
QMap<uint32_t, QString> encounterTypeToName;
|
||||
QMap<uint32_t, QString> terrainTypeToName;
|
||||
QMap<QString, MapSectionEntry> regionMapEntries;
|
||||
QMap<QString, QMap<QString, uint16_t>> metatileLabelsMap;
|
||||
QMap<QString, uint16_t> unusedMetatileLabels;
|
||||
QMap<QString, uint32_t> metatileBehaviorMap;
|
||||
@@ -72,13 +71,12 @@ public:
|
||||
QSet<QString> modifiedFiles;
|
||||
bool usingAsmTilesets;
|
||||
QSet<QString> disabledSettingsNames;
|
||||
QSet<QString> topLevelMapFields;
|
||||
int pokemonMinLevel;
|
||||
int pokemonMaxLevel;
|
||||
int maxEncounterRate;
|
||||
bool wildEncountersLoaded;
|
||||
|
||||
void set_root(QString);
|
||||
void setRoot(const QString&);
|
||||
|
||||
void clearMaps();
|
||||
void clearTilesetCache();
|
||||
@@ -111,10 +109,6 @@ public:
|
||||
bool loadBlockdata(Layout *);
|
||||
bool loadLayoutBorder(Layout *);
|
||||
|
||||
void saveTextFile(QString path, QString text);
|
||||
void appendTextFile(QString path, QString text);
|
||||
void deleteFile(QString path);
|
||||
|
||||
bool readMapGroups();
|
||||
void addNewMapGroup(const QString &groupName);
|
||||
QString mapNameToMapGroup(const QString &mapName) const;
|
||||
@@ -145,12 +139,11 @@ public:
|
||||
QString getNewHealLocationName(const Map* map) const;
|
||||
|
||||
bool readWildMonData();
|
||||
tsl::ordered_map<QString, tsl::ordered_map<QString, WildPokemonHeader>> wildMonData;
|
||||
OrderedMap<QString, OrderedMap<QString, WildPokemonHeader>> wildMonData;
|
||||
|
||||
QString wildMonTableName;
|
||||
QVector<EncounterField> wildMonFields;
|
||||
QVector<QString> encounterGroupLabels;
|
||||
QVector<poryjson::Json::object> extraEncounterGroups;
|
||||
|
||||
bool readSpeciesIconPaths();
|
||||
QString getDefaultSpeciesIconPath(const QString &species);
|
||||
@@ -158,40 +151,34 @@ public:
|
||||
|
||||
bool addNewMapsec(const QString &idName, const QString &displayName = QString());
|
||||
void removeMapsec(const QString &idName);
|
||||
QString getMapsecDisplayName(const QString &idName) const { return this->mapSectionDisplayNames.value(idName); }
|
||||
QString getMapsecDisplayName(const QString &idName) const { return this->locationData.value(idName).displayName; }
|
||||
void setMapsecDisplayName(const QString &idName, const QString &displayName);
|
||||
|
||||
bool hasUnsavedChanges();
|
||||
bool hasUnsavedDataChanges = false;
|
||||
|
||||
void initTopLevelMapFields();
|
||||
bool readMapJson(const QString &mapName, QJsonDocument * out);
|
||||
bool loadMapEvent(Map *map, const QJsonObject &json, Event::Type defaultType = Event::Type::None);
|
||||
bool loadMapEvent(Map *map, QJsonObject json, Event::Type defaultType = Event::Type::None);
|
||||
bool loadMapData(Map*);
|
||||
bool readMapLayouts();
|
||||
Layout *loadLayout(QString layoutId);
|
||||
bool loadLayout(Layout *);
|
||||
bool loadMapLayout(Map*);
|
||||
bool loadLayoutTilesets(Layout *);
|
||||
void loadTilesetAssets(Tileset*);
|
||||
bool loadTilesetAssets(Tileset*);
|
||||
void loadTilesetMetatileLabels(Tileset*);
|
||||
void readTilesetPaths(Tileset* tileset);
|
||||
|
||||
void saveAll();
|
||||
void saveGlobalData();
|
||||
void saveLayout(Layout *);
|
||||
void saveLayoutBlockdata(Layout *);
|
||||
void saveLayoutBorder(Layout *);
|
||||
void writeBlockdata(QString, const Blockdata &);
|
||||
void saveMap(Map *map, bool skipLayout = false);
|
||||
void saveConfig();
|
||||
void saveMapLayouts();
|
||||
void saveMapGroups();
|
||||
void saveRegionMapSections();
|
||||
void saveWildMonData();
|
||||
void saveHealLocations();
|
||||
void saveTilesets(Tileset*, Tileset*);
|
||||
void saveTilesetMetatileLabels(Tileset*, Tileset*);
|
||||
bool saveAll();
|
||||
bool saveGlobalData();
|
||||
bool saveConfig();
|
||||
bool saveLayout(Layout *layout);
|
||||
bool saveMap(Map *map, bool skipLayout = false);
|
||||
bool saveTextFile(const QString &path, const QString &text);
|
||||
bool saveRegionMapSections();
|
||||
bool saveTilesets(Tileset*, Tileset*);
|
||||
bool saveTilesetMetatileLabels(Tileset*, Tileset*);
|
||||
|
||||
void appendTilesetLabel(const QString &label, const QString &isSecondaryStr);
|
||||
bool readTilesetLabels();
|
||||
bool readTilesetMetatileLabels();
|
||||
@@ -217,6 +204,7 @@ public:
|
||||
bool readEventGraphics();
|
||||
bool readFieldmapProperties();
|
||||
bool readFieldmapMasks();
|
||||
bool readGlobalConstants();
|
||||
QMap<QString, QMap<QString, QString>> readObjEventGfxInfo();
|
||||
|
||||
QPixmap getEventPixmap(const QString &gfxName, const QString &movementName);
|
||||
@@ -240,35 +228,52 @@ public:
|
||||
|
||||
static QString getExistingFilepath(QString filepath);
|
||||
void applyParsedLimits();
|
||||
|
||||
void setRegionMapEntries(const QHash<QString, MapSectionEntry> &entries);
|
||||
QHash<QString, MapSectionEntry> getRegionMapEntries() const;
|
||||
|
||||
QSet<QString> getTopLevelMapFields() const;
|
||||
|
||||
int getMapDataSize(int width, int height) const;
|
||||
int getMaxMapDataSize() const { return this->maxMapDataSize; }
|
||||
int getMaxMapWidth() const;
|
||||
int getMaxMapHeight() const;
|
||||
bool mapDimensionsValid(int width, int height) const;
|
||||
bool calculateDefaultMapSize();
|
||||
QSize getDefaultMapSize() const { return this->defaultMapSize; }
|
||||
QSize getMapSizeAddition() const { return this->mapSizeAddition; }
|
||||
|
||||
int getMaxEvents(Event::Group group) const;
|
||||
|
||||
static QString getEmptyMapDefineName();
|
||||
static QString getDynamicMapDefineName();
|
||||
static QString getDynamicMapName();
|
||||
static QString getEmptySpeciesName();
|
||||
static int getNumTilesPrimary();
|
||||
static int getNumTilesTotal();
|
||||
static int getNumMetatilesPrimary();
|
||||
static int getNumMetatilesTotal();
|
||||
static int getNumPalettesPrimary();
|
||||
static int getNumPalettesTotal();
|
||||
static int getMaxMapDataSize();
|
||||
static int getDefaultMapDimension();
|
||||
static int getMaxMapWidth();
|
||||
static int getMaxMapHeight();
|
||||
static int getMapDataSize(int width, int height);
|
||||
static bool mapDimensionsValid(int width, int height);
|
||||
bool calculateDefaultMapSize();
|
||||
int getMaxEvents(Event::Group group);
|
||||
static QMargins getMetatileViewDistance();
|
||||
static int getNumTilesPrimary() { return num_tiles_primary; }
|
||||
static int getNumTilesTotal() { return num_tiles_total; }
|
||||
static int getNumMetatilesPrimary() { return num_metatiles_primary; }
|
||||
static int getNumMetatilesTotal() { return Block::getMaxMetatileId() + 1; }
|
||||
static int getNumPalettesPrimary(){ return num_pals_primary; }
|
||||
static int getNumPalettesTotal() { return num_pals_total; }
|
||||
static QString getEmptyMapsecName();
|
||||
static QString getMapGroupPrefix();
|
||||
|
||||
private:
|
||||
QHash<QString, QString> mapSectionDisplayNames;
|
||||
QMap<QString, qint64> modifiedFileTimestamps;
|
||||
QMap<QString, QString> facingDirections;
|
||||
QHash<QString, QString> speciesToIconPath;
|
||||
QHash<QString, Map*> maps;
|
||||
|
||||
// Fields for preserving top-level JSON data that Porymap isn't expecting.
|
||||
QJsonObject customLayoutsData;
|
||||
QJsonObject customMapSectionsData;
|
||||
QJsonObject customMapGroupsData;
|
||||
QJsonObject customHealLocationsData;
|
||||
OrderedJson::object customWildMonData;
|
||||
OrderedJson::object customWildMonGroupData;
|
||||
OrderedJson::array extraEncounterGroups;
|
||||
|
||||
// Maps/layouts represented in these sets have been fully loaded from the project.
|
||||
// If a valid map name / layout id is not in these sets, a Map / Layout object exists
|
||||
// for it in Project::maps / Project::mapLayouts, but it has been minimally populated
|
||||
@@ -292,7 +297,14 @@ private:
|
||||
};
|
||||
QMap<QString, EventGraphics*> eventGraphicsMap;
|
||||
|
||||
void updateLayout(Layout *);
|
||||
// The extra data that can be associated with each MAPSEC name.
|
||||
struct LocationData
|
||||
{
|
||||
MapSectionEntry map;
|
||||
QString displayName;
|
||||
QJsonObject custom;
|
||||
};
|
||||
QHash<QString, LocationData> locationData;
|
||||
|
||||
void setNewLayoutBlockdata(Layout *layout);
|
||||
void setNewLayoutBorder(Layout *layout);
|
||||
@@ -301,17 +313,27 @@ private:
|
||||
void recordFileChange(const QString &filepath);
|
||||
void resetFileCache();
|
||||
|
||||
bool saveMapLayouts();
|
||||
bool saveMapGroups();
|
||||
bool saveWildMonData();
|
||||
bool saveHealLocations();
|
||||
bool appendTextFile(const QString &path, const QString &text);
|
||||
|
||||
QString findSpeciesIconPath(const QStringList &names) const;
|
||||
|
||||
int maxEventsPerGroup;
|
||||
int maxObjectEvents;
|
||||
int maxMapDataSize;
|
||||
QSize defaultMapSize;
|
||||
QSize mapSizeAddition;
|
||||
|
||||
// TODO: These really shouldn't be static, they're specific to a single project.
|
||||
// We're making an assumption here that we only have one project open at a single time
|
||||
// (which is true, but then if that's the case we should have some global Project instance instead)
|
||||
static int num_tiles_primary;
|
||||
static int num_tiles_total;
|
||||
static int num_metatiles_primary;
|
||||
static int num_pals_primary;
|
||||
static int num_pals_total;
|
||||
static int max_map_data_size;
|
||||
static int default_map_dimension;
|
||||
|
||||
signals:
|
||||
void fileChanged(const QString &filepath);
|
||||
|
||||
@@ -39,6 +39,7 @@ public:
|
||||
static void populateGlobalObject(MainWindow *mainWindow);
|
||||
static QJSEngine *getEngine();
|
||||
static void invokeAction(int actionIndex);
|
||||
|
||||
static void cb_ProjectOpened(QString projectPath);
|
||||
static void cb_ProjectClosed(QString projectPath);
|
||||
static void cb_MetatileChanged(int x, int y, Block prevBlock, Block newBlock);
|
||||
@@ -47,18 +48,20 @@ public:
|
||||
static void cb_BlockHoverCleared();
|
||||
static void cb_MapOpened(QString mapName);
|
||||
static void cb_LayoutOpened(QString layoutName);
|
||||
static void cb_MapResized(int oldWidth, int oldHeight, int newWidth, int newHeight);
|
||||
static void cb_MapResized(int oldWidth, int oldHeight, const QMargins &delta);
|
||||
static void cb_BorderResized(int oldWidth, int oldHeight, int newWidth, int newHeight);
|
||||
static void cb_MapShifted(int xDelta, int yDelta);
|
||||
static void cb_TilesetUpdated(QString tilesetName);
|
||||
static void cb_MainTabChanged(int oldTab, int newTab);
|
||||
static void cb_MapViewTabChanged(int oldTab, int newTab);
|
||||
static void cb_BorderVisibilityToggled(bool visible);
|
||||
|
||||
static bool tryErrorJS(QJSValue js);
|
||||
static QJSValue fromBlock(Block block);
|
||||
static QJSValue fromTile(Tile tile);
|
||||
static Tile toTile(QJSValue obj);
|
||||
static QJSValue dimensions(int width, int height);
|
||||
static QJSValue margins(const QMargins &margins);
|
||||
static QJSValue position(int x, int y);
|
||||
static const QImage * getImage(const QString &filepath, bool useCache);
|
||||
static QJSValue dialogInput(QJSValue input, bool selectedOk);
|
||||
|
||||
@@ -13,6 +13,8 @@ class AboutPorymap : public QDialog
|
||||
public:
|
||||
explicit AboutPorymap(QWidget *parent = nullptr);
|
||||
~AboutPorymap();
|
||||
|
||||
static QString getVersionString();
|
||||
private:
|
||||
Ui::AboutPorymap *ui;
|
||||
};
|
||||
|
||||
@@ -43,8 +43,6 @@ protected:
|
||||
virtual void mousePressEvent(QGraphicsSceneMouseEvent*) override;
|
||||
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent*) override;
|
||||
virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*) override;
|
||||
virtual void keyPressEvent(QKeyEvent*) override;
|
||||
virtual void focusInEvent(QFocusEvent*) override;
|
||||
|
||||
signals:
|
||||
void connectionItemDoubleClicked(MapConnection*);
|
||||
|
||||
@@ -36,19 +36,17 @@ private:
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent*) override;
|
||||
virtual void focusInEvent(QFocusEvent*) override;
|
||||
virtual void keyPressEvent(QKeyEvent*) override;
|
||||
virtual bool eventFilter(QObject*, QEvent *event) override;
|
||||
|
||||
signals:
|
||||
void selected();
|
||||
void openMapClicked(MapConnection*);
|
||||
|
||||
private slots:
|
||||
void on_comboBox_Direction_currentTextChanged(QString direction);
|
||||
void on_comboBox_Map_currentTextChanged(QString mapName);
|
||||
void on_spinBox_Offset_valueChanged(int offset);
|
||||
void on_button_Delete_clicked();
|
||||
void on_button_OpenMap_clicked();
|
||||
private:
|
||||
void commitDirection();
|
||||
void commitMap(const QString &mapName);
|
||||
void commitMove(int offset);
|
||||
void commitRemove();
|
||||
};
|
||||
|
||||
#endif // CONNECTIONSLISTITEM_H
|
||||
|
||||
@@ -13,8 +13,8 @@ public:
|
||||
explicit CustomAttributesTable(QWidget *parent = nullptr);
|
||||
~CustomAttributesTable() {};
|
||||
|
||||
QMap<QString, QJsonValue> getAttributes() const;
|
||||
void setAttributes(const QMap<QString, QJsonValue> &attributes);
|
||||
QJsonObject getAttributes() const;
|
||||
void setAttributes(const QJsonObject &attributes);
|
||||
|
||||
void addNewAttribute(const QString &key, const QJsonValue &value);
|
||||
bool deleteSelectedAttributes();
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
#ifndef DRAGGABLEPIXMAPITEM_H
|
||||
#define DRAGGABLEPIXMAPITEM_H
|
||||
|
||||
#include <QString>
|
||||
#include <QGraphicsItemGroup>
|
||||
#include <QGraphicsPixmapItem>
|
||||
#include <QGraphicsItemAnimation>
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
#include "events.h"
|
||||
|
||||
class Editor;
|
||||
|
||||
class DraggablePixmapItem : public QObject, public QGraphicsPixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
DraggablePixmapItem(QPixmap pixmap): QGraphicsPixmapItem(pixmap) {}
|
||||
|
||||
DraggablePixmapItem(Event *event, Editor *editor) : QGraphicsPixmapItem(event->getPixmap()) {
|
||||
this->event = event;
|
||||
event->setPixmapItem(this);
|
||||
this->editor = editor;
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
Event *event = nullptr;
|
||||
|
||||
void updatePosition();
|
||||
void move(int dx, int dy);
|
||||
void moveTo(const QPoint &pos);
|
||||
void emitPositionChanged();
|
||||
void updatePixmap();
|
||||
|
||||
private:
|
||||
Editor *editor = nullptr;
|
||||
QPoint lastPos;
|
||||
bool active = false;
|
||||
bool releaseSelectionQueued = false;
|
||||
|
||||
signals:
|
||||
void positionChanged(Event *event);
|
||||
void xChanged(int);
|
||||
void yChanged(int);
|
||||
void elevationChanged(int);
|
||||
void spriteChanged(QPixmap pixmap);
|
||||
void onPropertyChanged(QString key, QString value);
|
||||
|
||||
public slots:
|
||||
void set_x(int x) {
|
||||
event->setX(x);
|
||||
updatePosition();
|
||||
}
|
||||
void set_y(int y) {
|
||||
event->setY(y);
|
||||
updatePosition();
|
||||
}
|
||||
void set_elevation(int z) {
|
||||
event->setElevation(z);
|
||||
updatePosition();
|
||||
}
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*);
|
||||
};
|
||||
|
||||
#endif // DRAGGABLEPIXMAPITEM_H
|
||||
@@ -57,7 +57,9 @@ protected:
|
||||
bool initialized = false;
|
||||
bool connected = false;
|
||||
|
||||
void populateDropdown(NoScrollComboBox * combo, const QStringList &items);
|
||||
void populateScriptDropdown(NoScrollComboBox * combo, Project * project);
|
||||
void populateIdNameDropdown(NoScrollComboBox * combo, Project * project, const QString &mapName, Event::Group group);
|
||||
|
||||
private:
|
||||
Event *event;
|
||||
@@ -78,6 +80,7 @@ public:
|
||||
virtual void populate(Project *project) override;
|
||||
|
||||
public:
|
||||
QLineEdit *line_edit_local_id;
|
||||
NoScrollComboBox *combo_sprite;
|
||||
NoScrollComboBox *combo_movement;
|
||||
NoScrollSpinBox *spinner_radius_x;
|
||||
@@ -108,12 +111,15 @@ public:
|
||||
virtual void populate(Project *project) override;
|
||||
|
||||
public:
|
||||
QLineEdit *line_edit_local_id;
|
||||
NoScrollComboBox *combo_sprite;
|
||||
NoScrollSpinBox *spinner_target_id;
|
||||
NoScrollComboBox *combo_target_id;
|
||||
NoScrollComboBox *combo_target_map;
|
||||
|
||||
private:
|
||||
CloneObjectEvent *clone;
|
||||
|
||||
void tryInvalidateIdDropdown(Map *map);
|
||||
};
|
||||
|
||||
|
||||
@@ -131,12 +137,15 @@ public:
|
||||
virtual void populate(Project *project) override;
|
||||
|
||||
public:
|
||||
QLineEdit *line_edit_id;
|
||||
NoScrollComboBox *combo_dest_map;
|
||||
NoScrollComboBox *combo_dest_warp;
|
||||
QPushButton *warning;
|
||||
|
||||
private:
|
||||
WarpEvent *warp;
|
||||
|
||||
void tryInvalidateIdDropdown(Map *map);
|
||||
};
|
||||
|
||||
|
||||
@@ -275,6 +284,8 @@ public:
|
||||
|
||||
private:
|
||||
HealLocationEvent *healLocation;
|
||||
|
||||
void tryInvalidateIdDropdown(Map *map);
|
||||
};
|
||||
|
||||
#endif // EVENTRAMES_H
|
||||
|
||||
58
include/ui/eventpixmapitem.h
Normal file
58
include/ui/eventpixmapitem.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#ifndef EVENTPIXMAPITEM_H
|
||||
#define EVENTPIXMAPITEM_H
|
||||
|
||||
#include <QString>
|
||||
#include <QGraphicsItemGroup>
|
||||
#include <QGraphicsPixmapItem>
|
||||
#include <QGraphicsItemAnimation>
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
#include "events.h"
|
||||
|
||||
class Project;
|
||||
|
||||
class EventPixmapItem : public QObject, public QGraphicsPixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit EventPixmapItem(Event *event);
|
||||
|
||||
void render(Project *project);
|
||||
|
||||
bool isSelected() const { return m_selected; }
|
||||
void setSelected(bool selected) { m_selected = selected; }
|
||||
|
||||
Event * getEvent() const { return m_event; }
|
||||
|
||||
void move(int dx, int dy);
|
||||
void moveTo(int x, int y);
|
||||
void moveTo(const QPoint &pos);
|
||||
|
||||
private:
|
||||
QPixmap m_basePixmap;
|
||||
Event *const m_event = nullptr;
|
||||
QPoint m_lastPos;
|
||||
bool m_active = false;
|
||||
bool m_selected = false;
|
||||
bool m_releaseSelectionQueued = false;
|
||||
|
||||
void updatePixelPosition();
|
||||
|
||||
signals:
|
||||
void xChanged(int x);
|
||||
void yChanged(int y);
|
||||
void posChanged(int x, int y);
|
||||
void rendered(const QPixmap &pixmap);
|
||||
void selected(Event *event, bool toggle);
|
||||
void dragged(Event *event, const QPoint &oldPosition, const QPoint &newPosition);
|
||||
void released(Event *event, const QPoint &position);
|
||||
void doubleClicked(Event *event);
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QGraphicsSceneMouseEvent*) override;
|
||||
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent*) override;
|
||||
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent*) override;
|
||||
virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*) override { emit doubleClicked(m_event); }
|
||||
};
|
||||
|
||||
#endif // EVENTPIXMAPITEM_H
|
||||
@@ -32,25 +32,17 @@ signals:
|
||||
void clicked(QMouseEvent *event);
|
||||
};
|
||||
|
||||
class Editor;
|
||||
|
||||
// TODO: This should just be MapView. It makes map-based assumptions, and no other class inherits GraphicsView.
|
||||
class GraphicsView : public QGraphicsView
|
||||
class ConnectionsView : public QGraphicsView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
GraphicsView() : QGraphicsView() {}
|
||||
GraphicsView(QWidget *parent) : QGraphicsView(parent) {}
|
||||
ConnectionsView(QWidget *parent = nullptr) : QGraphicsView(parent) {}
|
||||
|
||||
signals:
|
||||
void pressedDelete();
|
||||
|
||||
public:
|
||||
// GraphicsView_Object object;
|
||||
Editor *editor;
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
virtual void moveEvent(QMoveEvent *event) override;
|
||||
virtual void keyPressEvent(QKeyEvent *event) override;
|
||||
};
|
||||
|
||||
//Q_DECLARE_METATYPE(GraphicsView)
|
||||
|
||||
#endif // GRAPHICSVIEW_H
|
||||
|
||||
41
include/ui/loadingscreen.h
Normal file
41
include/ui/loadingscreen.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#include "qgifimage.h"
|
||||
|
||||
#include <QSplashScreen>
|
||||
#include <QTimer>
|
||||
#include <QWidget>
|
||||
|
||||
|
||||
|
||||
namespace Ui {
|
||||
class LoadingScreen;
|
||||
}
|
||||
|
||||
class PorymapLoadingScreen : public QWidget {
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PorymapLoadingScreen(QWidget *parent = nullptr);
|
||||
~PorymapLoadingScreen();
|
||||
|
||||
void setPixmap(QPixmap pixmap);
|
||||
void showMessage(QString text);
|
||||
|
||||
void start();
|
||||
void stop ();
|
||||
|
||||
private:
|
||||
void setupUi();
|
||||
|
||||
public slots:
|
||||
void updateFrame();
|
||||
|
||||
private:
|
||||
Ui::LoadingScreen *ui;
|
||||
|
||||
QGifImage splashImage;
|
||||
int frame = 0;
|
||||
QTimer timer;
|
||||
};
|
||||
|
||||
extern PorymapLoadingScreen *porysplash;
|
||||
@@ -64,6 +64,8 @@ private:
|
||||
QPointer<Project> m_project = nullptr;
|
||||
bool m_allowProjectChanges = true;
|
||||
|
||||
void setText(QComboBox *combo, const QString &text) const;
|
||||
void setText(QLineEdit *lineEdit, const QString &text) const;
|
||||
void setLocations(const QStringList &locations);
|
||||
void updateLocationName();
|
||||
|
||||
@@ -73,11 +75,11 @@ private:
|
||||
void onWeatherChanged(const QString &weather);
|
||||
void onTypeChanged(const QString &type);
|
||||
void onBattleSceneChanged(const QString &battleScene);
|
||||
void onRequiresFlashChanged(int selected);
|
||||
void onShowLocationNameChanged(int selected);
|
||||
void onAllowRunningChanged(int selected);
|
||||
void onAllowBikingChanged(int selected);
|
||||
void onAllowEscapingChanged(int selected);
|
||||
void onRequiresFlashChanged(bool enabled);
|
||||
void onShowLocationNameChanged(bool enabled);
|
||||
void onAllowRunningChanged(bool enabled);
|
||||
void onAllowBikingChanged(bool enabled);
|
||||
void onAllowEscapingChanged(bool enabled);
|
||||
void onFloorNumberChanged(int offset);
|
||||
};
|
||||
|
||||
|
||||
@@ -91,30 +91,27 @@ protected:
|
||||
virtual void showEvent(QShowEvent *) override;
|
||||
virtual void resizeEvent(QResizeEvent *) override;
|
||||
|
||||
private slots:
|
||||
void on_checkBox_Objects_stateChanged(int state);
|
||||
void on_checkBox_Warps_stateChanged(int state);
|
||||
void on_checkBox_BGs_stateChanged(int state);
|
||||
void on_checkBox_Triggers_stateChanged(int state);
|
||||
void on_checkBox_HealLocations_stateChanged(int state);
|
||||
void on_checkBox_AllEvents_stateChanged(int state);
|
||||
|
||||
void on_checkBox_ConnectionUp_stateChanged(int state);
|
||||
void on_checkBox_ConnectionDown_stateChanged(int state);
|
||||
void on_checkBox_ConnectionLeft_stateChanged(int state);
|
||||
void on_checkBox_ConnectionRight_stateChanged(int state);
|
||||
void on_checkBox_AllConnections_stateChanged(int state);
|
||||
|
||||
void on_checkBox_Collision_stateChanged(int state);
|
||||
void on_checkBox_Grid_stateChanged(int state);
|
||||
void on_checkBox_Border_stateChanged(int state);
|
||||
private:
|
||||
void setShowGrid(bool checked);
|
||||
void setShowBorder(bool checked);
|
||||
void setShowObjects(bool checked);
|
||||
void setShowWarps(bool checked);
|
||||
void setShowBgs(bool checked);
|
||||
void setShowTriggers(bool checked);
|
||||
void setShowHealLocations(bool checked);
|
||||
void setShowAllEvents(bool checked);
|
||||
void setShowConnectionUp(bool checked);
|
||||
void setShowConnectionDown(bool checked);
|
||||
void setShowConnectionLeft(bool checked);
|
||||
void setShowConnectionRight(bool checked);
|
||||
void setShowAllConnections(bool checked);
|
||||
void setShowCollision(bool checked);
|
||||
void setDisablePreviewScaling(bool checked);
|
||||
void setDisablePreviewUpdates(bool checked);
|
||||
|
||||
void on_pushButton_Reset_pressed();
|
||||
void on_spinBox_TimelapseDelay_editingFinished();
|
||||
void on_spinBox_FrameSkip_editingFinished();
|
||||
|
||||
void on_checkBox_DisablePreviewScaling_stateChanged(int state);
|
||||
void on_checkBox_DisablePreviewUpdates_stateChanged(int state);
|
||||
};
|
||||
|
||||
#endif // MAPIMAGEEXPORTER_H
|
||||
|
||||
@@ -5,13 +5,17 @@
|
||||
#include "graphicsview.h"
|
||||
#include "overlay.h"
|
||||
|
||||
class MapView : public GraphicsView
|
||||
class Editor;
|
||||
|
||||
class MapView : public QGraphicsView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MapView() : GraphicsView() {}
|
||||
MapView(QWidget *parent) : GraphicsView(parent) {}
|
||||
MapView() : QGraphicsView() {}
|
||||
MapView(QWidget *parent) : QGraphicsView(parent) {}
|
||||
|
||||
Editor *editor;
|
||||
|
||||
Overlay * getOverlay(int layer);
|
||||
void clearOverlayMap();
|
||||
@@ -73,6 +77,7 @@ public:
|
||||
protected:
|
||||
virtual void drawForeground(QPainter *painter, const QRectF &rect) override;
|
||||
virtual void keyPressEvent(QKeyEvent*) override;
|
||||
virtual void moveEvent(QMoveEvent *event) override;
|
||||
private:
|
||||
QMap<int, Overlay*> overlayMap;
|
||||
|
||||
|
||||
@@ -24,21 +24,21 @@ public:
|
||||
class ErrorMessage : public Message {
|
||||
public:
|
||||
ErrorMessage(const QString &message, QWidget *parent);
|
||||
static int show(const QString &message, QWidget *parent);
|
||||
static void show(const QString &message, QWidget *parent);
|
||||
};
|
||||
|
||||
// Basic warning message with an 'Ok' button.
|
||||
class WarningMessage : public Message {
|
||||
public:
|
||||
WarningMessage(const QString &message, QWidget *parent);
|
||||
static int show(const QString &message, QWidget *parent);
|
||||
static void show(const QString &message, QWidget *parent);
|
||||
};
|
||||
|
||||
// Basic informational message with a 'Close' button.
|
||||
class InfoMessage : public Message {
|
||||
public:
|
||||
InfoMessage(const QString &message, QWidget *parent);
|
||||
static int show(const QString &message, QWidget *parent);
|
||||
static void show(const QString &message, QWidget *parent);
|
||||
};
|
||||
|
||||
// Basic question message with a 'Yes' and 'No' button.
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
class RecentErrorMessage : public ErrorMessage {
|
||||
public:
|
||||
RecentErrorMessage(const QString &message, QWidget *parent);
|
||||
static int show(const QString &message, QWidget *parent);
|
||||
static void show(const QString &message, QWidget *parent);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -10,28 +10,35 @@
|
||||
class MovableRect : public QGraphicsRectItem
|
||||
{
|
||||
public:
|
||||
MovableRect(bool *enabled, int width, int height, QRgb color);
|
||||
MovableRect(bool *enabled, const QRectF &rect, const QRgb &color);
|
||||
QRectF boundingRect() const override {
|
||||
qreal penWidth = 4;
|
||||
return QRectF(-penWidth,
|
||||
-penWidth,
|
||||
30 * 8 + penWidth * 2,
|
||||
20 * 8 + penWidth * 2);
|
||||
this->rect().width() + penWidth * 2,
|
||||
this->rect().height() + penWidth * 2);
|
||||
}
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override {
|
||||
if (!(*enabled)) return;
|
||||
if (!isVisible()) return;
|
||||
painter->setPen(this->color);
|
||||
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(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);
|
||||
painter->drawRect(this->rect() + QMargins(1,1,1,1)); // Fill
|
||||
painter->setPen(Qt::black);
|
||||
painter->drawRect(this->rect() + QMargins(2,2,2,2)); // Outer border
|
||||
painter->drawRect(this->rect()); // Inner border
|
||||
}
|
||||
void updateLocation(int x, int y);
|
||||
bool *enabled;
|
||||
|
||||
void setActive(bool active);
|
||||
bool getActive() const { return this->active; }
|
||||
|
||||
protected:
|
||||
bool *enabled = nullptr;
|
||||
bool active = true;
|
||||
QRectF baseRect;
|
||||
QRgb color;
|
||||
|
||||
void updateVisibility();
|
||||
};
|
||||
|
||||
|
||||
|
||||
32
include/ui/newdefinedialog.h
Normal file
32
include/ui/newdefinedialog.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef NEWDEFINEDIALOG_H
|
||||
#define NEWDEFINEDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QAbstractButton>
|
||||
|
||||
namespace Ui {
|
||||
class NewDefineDialog;
|
||||
}
|
||||
|
||||
class NewDefineDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NewDefineDialog(QWidget *parent = nullptr);
|
||||
~NewDefineDialog();
|
||||
|
||||
virtual void accept() override;
|
||||
|
||||
signals:
|
||||
void createdDefine(const QString &name, const QString &expression);
|
||||
|
||||
private:
|
||||
Ui::NewDefineDialog *ui;
|
||||
|
||||
bool validateName(bool allowEmpty = false);
|
||||
void onNameChanged(const QString &name);
|
||||
void dialogButtonClicked(QAbstractButton *button);
|
||||
};
|
||||
|
||||
#endif // NEWDEFINEDIALOG_H
|
||||
@@ -20,13 +20,16 @@ public:
|
||||
virtual void accept() override;
|
||||
|
||||
signals:
|
||||
void accepted(MapConnection *result);
|
||||
void newConnectionedAdded(const QString &mapName, const QString &direction);
|
||||
void connectionReplaced(const QString &mapName, const QString &direction);
|
||||
|
||||
private:
|
||||
Ui::NewMapConnectionDialog *ui;
|
||||
Map *m_map;
|
||||
|
||||
bool mapNameIsValid();
|
||||
void setWarningVisible(bool visible);
|
||||
bool askReplaceConnection(MapConnection *connection, const QString &newMapName);
|
||||
};
|
||||
|
||||
#endif // NEWMAPCONNECTIONDIALOG_H
|
||||
|
||||
@@ -18,6 +18,9 @@ public:
|
||||
void setLineEdit(QLineEdit *edit);
|
||||
void setFocusedScrollingEnabled(bool enabled);
|
||||
|
||||
signals:
|
||||
void editingFinished();
|
||||
|
||||
private:
|
||||
void setItem(int index, const QString &text);
|
||||
|
||||
|
||||
25
include/ui/noscrolltextedit.h
Normal file
25
include/ui/noscrolltextedit.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef NOSCROLLTEXTEDIT_H
|
||||
#define NOSCROLLTEXTEDIT_H
|
||||
|
||||
#include <QTextEdit>
|
||||
#include <QWheelEvent>
|
||||
|
||||
class NoScrollTextEdit : public QTextEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit NoScrollTextEdit(const QString &text, QWidget *parent = nullptr) : QTextEdit(text, parent) {
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
};
|
||||
explicit NoScrollTextEdit(QWidget *parent = nullptr) : NoScrollTextEdit(QString(), parent) {};
|
||||
|
||||
virtual void wheelEvent(QWheelEvent *event) override {
|
||||
if (hasFocus()) {
|
||||
QTextEdit::wheelEvent(event);
|
||||
} else {
|
||||
event->ignore();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#endif // NOSCROLLTEXTEDIT_H
|
||||
@@ -67,6 +67,12 @@ private:
|
||||
void setWarpBehaviorsList(QStringList list);
|
||||
void openFilesHelp();
|
||||
void openIdentifiersHelp();
|
||||
void addNewGlobalConstantsFilepath();
|
||||
void addGlobalConstantsFilepath(const QString &filepath);
|
||||
QStringList getGlobalConstantsFilepaths();
|
||||
void addNewGlobalConstant();
|
||||
void addGlobalConstant(const QString &name, const QString &expression);
|
||||
QMap<QString,QString> getGlobalConstants();
|
||||
|
||||
private slots:
|
||||
void dialogButtonClicked(QAbstractButton *button);
|
||||
|
||||
@@ -54,7 +54,7 @@ private:
|
||||
Project *project;
|
||||
|
||||
RegionMap *region_map = nullptr;
|
||||
tsl::ordered_map<QString, RegionMap *> region_maps;
|
||||
OrderedMap<QString, RegionMap *> region_maps;
|
||||
|
||||
QString configFilepath;
|
||||
|
||||
@@ -95,7 +95,7 @@ private:
|
||||
void saveConfig();
|
||||
bool loadRegionMapEntries();
|
||||
bool saveRegionMapEntries();
|
||||
QMap<QString, MapSectionEntry> region_map_entries;
|
||||
QHash<QString, MapSectionEntry> region_map_entries;
|
||||
|
||||
bool buildConfigDialog();
|
||||
poryjson::Json configRegionMapDialog();
|
||||
@@ -121,6 +121,9 @@ private:
|
||||
void restoreWindowState();
|
||||
void closeEvent(QCloseEvent* event);
|
||||
|
||||
void setTileHFlip(bool enabled);
|
||||
void setTileVFlip(bool enabled);
|
||||
|
||||
private slots:
|
||||
void on_action_RegionMap_Save_triggered();
|
||||
void on_actionSave_All_triggered();
|
||||
@@ -145,8 +148,6 @@ private slots:
|
||||
void on_spinBox_RM_LayoutWidth_valueChanged(int);
|
||||
void on_spinBox_RM_LayoutHeight_valueChanged(int);
|
||||
void on_spinBox_tilePalette_valueChanged(int);
|
||||
void on_checkBox_tileHFlip_stateChanged(int);
|
||||
void on_checkBox_tileVFlip_stateChanged(int);
|
||||
void on_verticalSlider_Zoom_Map_Image_valueChanged(int);
|
||||
void on_verticalSlider_Zoom_Image_Tiles_valueChanged(int);
|
||||
void onHoveredRegionMapTileChanged(int x, int y);
|
||||
|
||||
@@ -49,9 +49,6 @@ public:
|
||||
void setAutoRepeat(bool on);
|
||||
bool autoRepeat() const;
|
||||
|
||||
int id() const;
|
||||
QList<int> ids() const;
|
||||
|
||||
inline QWidget *parentWidget() const
|
||||
{ return static_cast<QWidget *>(QObject::parent()); }
|
||||
|
||||
|
||||
@@ -149,10 +149,10 @@ public:
|
||||
void select(unsigned tileId);
|
||||
unsigned selectedTile = 0;
|
||||
|
||||
void selectVFlip(bool hFlip) { this->tile_hFlip = hFlip; }
|
||||
void selectHFlip(bool hFlip) { this->tile_hFlip = hFlip; }
|
||||
bool tile_hFlip = false;
|
||||
|
||||
void selectHFlip(bool vFlip) { this->tile_vFlip = vFlip; }
|
||||
void selectVFlip(bool vFlip) { this->tile_vFlip = vFlip; }
|
||||
bool tile_vFlip = false;
|
||||
|
||||
void selectPalette(int palette) {
|
||||
|
||||
@@ -71,12 +71,6 @@ private slots:
|
||||
|
||||
void on_spinBox_paletteSelector_valueChanged(int arg1);
|
||||
|
||||
void on_checkBox_xFlip_stateChanged(int arg1);
|
||||
|
||||
void on_checkBox_yFlip_stateChanged(int arg1);
|
||||
|
||||
void on_actionSave_Tileset_triggered();
|
||||
|
||||
void on_actionImport_Primary_Tiles_triggered();
|
||||
|
||||
void on_actionImport_Secondary_Tiles_triggered();
|
||||
@@ -149,6 +143,8 @@ private:
|
||||
void commitTerrainType();
|
||||
void commitLayerType();
|
||||
void setRawAttributesVisible(bool visible);
|
||||
void setXFlip(bool enabled);
|
||||
void setYFlip(bool enabled);
|
||||
|
||||
Ui::TilesetEditor *ui;
|
||||
History<MetatileHistoryItem*> metatileHistory;
|
||||
@@ -175,6 +171,8 @@ private:
|
||||
bool lockSelection = false;
|
||||
QSet<uint16_t> metatileReloadQueue;
|
||||
|
||||
bool save();
|
||||
|
||||
signals:
|
||||
void tilesetsSaved(QString, QString);
|
||||
};
|
||||
|
||||
11
porymap.pro
11
porymap.pro
@@ -73,7 +73,7 @@ SOURCES += src/core/advancemapparser.cpp \
|
||||
src/ui/customscriptseditor.cpp \
|
||||
src/ui/customscriptslistitem.cpp \
|
||||
src/ui/divingmappixmapitem.cpp \
|
||||
src/ui/draggablepixmapitem.cpp \
|
||||
src/ui/eventpixmapitem.cpp \
|
||||
src/ui/bordermetatilespixmapitem.cpp \
|
||||
src/ui/collisionpixmapitem.cpp \
|
||||
src/ui/connectionpixmapitem.cpp \
|
||||
@@ -104,6 +104,7 @@ SOURCES += src/core/advancemapparser.cpp \
|
||||
src/ui/metatileselector.cpp \
|
||||
src/ui/movablerect.cpp \
|
||||
src/ui/movementpermissionsselector.cpp \
|
||||
src/ui/newdefinedialog.cpp \
|
||||
src/ui/neweventtoolbutton.cpp \
|
||||
src/ui/newlayoutdialog.cpp \
|
||||
src/ui/newlayoutform.cpp \
|
||||
@@ -133,6 +134,7 @@ SOURCES += src/core/advancemapparser.cpp \
|
||||
src/ui/preferenceeditor.cpp \
|
||||
src/ui/regionmappropertiesdialog.cpp \
|
||||
src/ui/colorpicker.cpp \
|
||||
src/ui/loadingscreen.cpp \
|
||||
src/config.cpp \
|
||||
src/editor.cpp \
|
||||
src/main.cpp \
|
||||
@@ -184,7 +186,7 @@ HEADERS += include/core/advancemapparser.h \
|
||||
include/ui/customscriptseditor.h \
|
||||
include/ui/customscriptslistitem.h \
|
||||
include/ui/divingmappixmapitem.h \
|
||||
include/ui/draggablepixmapitem.h \
|
||||
include/ui/eventpixmapitem.h \
|
||||
include/ui/bordermetatilespixmapitem.h \
|
||||
include/ui/collisionpixmapitem.h \
|
||||
include/ui/connectionpixmapitem.h \
|
||||
@@ -216,6 +218,7 @@ HEADERS += include/core/advancemapparser.h \
|
||||
include/ui/metatileselector.h \
|
||||
include/ui/movablerect.h \
|
||||
include/ui/movementpermissionsselector.h \
|
||||
include/ui/newdefinedialog.h \
|
||||
include/ui/neweventtoolbutton.h \
|
||||
include/ui/newlayoutdialog.h \
|
||||
include/ui/newlayoutform.h \
|
||||
@@ -223,6 +226,7 @@ HEADERS += include/core/advancemapparser.h \
|
||||
include/ui/newmapgroupdialog.h \
|
||||
include/ui/noscrollcombobox.h \
|
||||
include/ui/noscrollspinbox.h \
|
||||
include/ui/noscrolltextedit.h \
|
||||
include/ui/montabwidget.h \
|
||||
include/ui/encountertablemodel.h \
|
||||
include/ui/encountertabledelegates.h \
|
||||
@@ -247,6 +251,7 @@ HEADERS += include/core/advancemapparser.h \
|
||||
include/ui/preferenceeditor.h \
|
||||
include/ui/regionmappropertiesdialog.h \
|
||||
include/ui/colorpicker.h \
|
||||
include/ui/loadingscreen.h \
|
||||
include/config.h \
|
||||
include/editor.h \
|
||||
include/mainwindow.h \
|
||||
@@ -266,8 +271,10 @@ FORMS += forms/mainwindow.ui \
|
||||
forms/connectionslistitem.ui \
|
||||
forms/customattributesframe.ui \
|
||||
forms/gridsettingsdialog.ui \
|
||||
forms/loadingscreen.ui \
|
||||
forms/mapheaderform.ui \
|
||||
forms/maplisttoolbar.ui \
|
||||
forms/newdefinedialog.ui \
|
||||
forms/newlayoutdialog.ui \
|
||||
forms/newlayoutform.ui \
|
||||
forms/newlocationdialog.ui \
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
<file>images/collisions_unknown.png</file>
|
||||
<file>images/Entities_16x16.png</file>
|
||||
<file>images/pokemon_icon_placeholder.png</file>
|
||||
<file>images/porysplash.gif</file>
|
||||
<file>icons/clipboard.ico</file>
|
||||
<file>icons/map_go.ico</file>
|
||||
</qresource>
|
||||
|
||||
BIN
resources/images/porysplash.gif
Normal file
BIN
resources/images/porysplash.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
@@ -39,7 +39,7 @@ export function onBlockHoverCleared() {
|
||||
}
|
||||
|
||||
// Called when the dimensions of the map are changed.
|
||||
export function onMapResized(oldWidth, oldHeight, newWidth, newHeight) {
|
||||
export function onMapResized(oldWidth, oldHeight, delta) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
114
src/config.cpp
114
src/config.cpp
@@ -18,6 +18,12 @@
|
||||
#include <QAction>
|
||||
#include <QAbstractButton>
|
||||
|
||||
const QVersionNumber porymapVersion = QVersionNumber::fromString(PORYMAP_VERSION);
|
||||
|
||||
// In both versions the default new map border is a generic tree
|
||||
const QList<uint16_t> defaultBorder_RSE = {0x1D4, 0x1D5, 0x1DC, 0x1DD};
|
||||
const QList<uint16_t> defaultBorder_FRLG = {0x14, 0x15, 0x1C, 0x1D};
|
||||
|
||||
const QList<uint32_t> defaultWarpBehaviors_RSE = {
|
||||
0x0E, // MB_MOSSDEEP_GYM_WARP
|
||||
0x0F, // MB_MT_PYRE_HOLE
|
||||
@@ -89,6 +95,8 @@ const QMap<ProjectIdentifier, QPair<QString, QString>> ProjectConfig::defaultIde
|
||||
{ProjectIdentifier::define_pals_total, {"define_pals_total", "NUM_PALS_TOTAL"}},
|
||||
{ProjectIdentifier::define_tiles_per_metatile, {"define_tiles_per_metatile", "NUM_TILES_PER_METATILE"}},
|
||||
{ProjectIdentifier::define_map_size, {"define_map_size", "MAX_MAP_DATA_SIZE"}},
|
||||
{ProjectIdentifier::define_map_offset_width, {"define_map_offset_width", "MAP_OFFSET_W"}},
|
||||
{ProjectIdentifier::define_map_offset_height, {"define_map_offset_height", "MAP_OFFSET_H"}},
|
||||
{ProjectIdentifier::define_mask_metatile, {"define_mask_metatile", "MAPGRID_METATILE_ID_MASK"}},
|
||||
{ProjectIdentifier::define_mask_collision, {"define_mask_collision", "MAPGRID_COLLISION_MASK"}},
|
||||
{ProjectIdentifier::define_mask_elevation, {"define_mask_elevation", "MAPGRID_ELEVATION_MASK"}},
|
||||
@@ -226,14 +234,14 @@ void KeyValueConfigBase::load() {
|
||||
continue;
|
||||
}
|
||||
|
||||
this->parseConfigKeyValue(match.captured("key").trimmed().toLower(), match.captured("value").trimmed());
|
||||
this->parseConfigKeyValue(match.captured("key").trimmed(), match.captured("value").trimmed());
|
||||
}
|
||||
this->setUnreadKeys();
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
void KeyValueConfigBase::save() {
|
||||
bool KeyValueConfigBase::save() {
|
||||
QString text = "";
|
||||
QMap<QString, QString> map = this->getKeyValueMap();
|
||||
for (QMap<QString, QString>::iterator it = map.begin(); it != map.end(); it++) {
|
||||
@@ -241,15 +249,17 @@ void KeyValueConfigBase::save() {
|
||||
}
|
||||
|
||||
QFile file(this->getConfigFilepath());
|
||||
if (file.open(QIODevice::WriteOnly)) {
|
||||
file.write(text.toUtf8());
|
||||
file.close();
|
||||
} else {
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
logError(QString("Could not open config file '%1' for writing: ").arg(this->getConfigFilepath()) + file.errorString());
|
||||
return false;
|
||||
}
|
||||
|
||||
file.write(text.toUtf8());
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KeyValueConfigBase::getConfigBool(QString key, QString value) {
|
||||
bool KeyValueConfigBase::getConfigBool(const QString &key, const QString &value) {
|
||||
bool ok;
|
||||
int result = value.toInt(&ok, 0);
|
||||
if (!ok || (result != 0 && result != 1)) {
|
||||
@@ -258,26 +268,35 @@ bool KeyValueConfigBase::getConfigBool(QString key, QString value) {
|
||||
return (result != 0);
|
||||
}
|
||||
|
||||
int KeyValueConfigBase::getConfigInteger(QString key, QString value, int min, int max, int defaultValue) {
|
||||
int KeyValueConfigBase::getConfigInteger(const QString &key, const QString &value, int min, int max, int defaultValue) {
|
||||
bool ok;
|
||||
int result = value.toInt(&ok, 0);
|
||||
if (!ok) {
|
||||
logWarn(QString("Invalid config value for %1: '%2'. Must be an integer.").arg(key).arg(value));
|
||||
return defaultValue;
|
||||
logWarn(QString("Invalid config value for %1: '%2'. Must be an integer. Using default value '%3'.").arg(key).arg(value).arg(defaultValue));
|
||||
result = defaultValue;
|
||||
}
|
||||
return qMin(max, qMax(min, result));
|
||||
}
|
||||
|
||||
uint32_t KeyValueConfigBase::getConfigUint32(QString key, QString value, uint32_t min, uint32_t max, uint32_t defaultValue) {
|
||||
uint32_t KeyValueConfigBase::getConfigUint32(const QString &key, const QString &value, uint32_t min, uint32_t max, uint32_t defaultValue) {
|
||||
bool ok;
|
||||
uint32_t result = value.toUInt(&ok, 0);
|
||||
if (!ok) {
|
||||
logWarn(QString("Invalid config value for %1: '%2'. Must be an integer.").arg(key).arg(value));
|
||||
return defaultValue;
|
||||
logWarn(QString("Invalid config value for %1: '%2'. Must be an integer. Using default value '%3'.").arg(key).arg(value).arg(defaultValue));
|
||||
result = defaultValue;
|
||||
}
|
||||
return qMin(max, qMax(min, result));
|
||||
}
|
||||
|
||||
QColor KeyValueConfigBase::getConfigColor(const QString &key, const QString &value, const QColor &defaultValue) {
|
||||
QColor color = QColor("#" + value);
|
||||
if (!color.isValid()) {
|
||||
logWarn(QString("Invalid config value for %1: '%2'. Must be a color in the format 'RRGGBB'. Using default value '%3'.").arg(key).arg(value).arg(defaultValue.name()));
|
||||
color = defaultValue;
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
PorymapConfig porymapConfig;
|
||||
|
||||
QString PorymapConfig::getConfigFilepath() {
|
||||
@@ -445,6 +464,18 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) {
|
||||
}
|
||||
} else if (key == "shown_in_game_reload_message") {
|
||||
this->shownInGameReloadMessage = getConfigBool(key, value);
|
||||
} else if (key == "grid_width") {
|
||||
this->gridSettings.width = getConfigUint32(key, value);
|
||||
} else if (key == "grid_height") {
|
||||
this->gridSettings.height = getConfigUint32(key, value);
|
||||
} else if (key == "grid_x") {
|
||||
this->gridSettings.offsetX = getConfigInteger(key, value, 0, 999);
|
||||
} else if (key == "grid_y") {
|
||||
this->gridSettings.offsetY = getConfigInteger(key, value, 0, 999);
|
||||
} else if (key == "grid_style") {
|
||||
this->gridSettings.style = GridSettings::getStyleFromName(value);
|
||||
} else if (key == "grid_color") {
|
||||
this->gridSettings.color = getConfigColor(key, value);
|
||||
} else {
|
||||
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
|
||||
}
|
||||
@@ -522,6 +553,12 @@ QMap<QString, QString> PorymapConfig::getKeyValueMap() {
|
||||
}
|
||||
map.insert("event_selection_shape_mode", (this->eventSelectionShapeMode == QGraphicsPixmapItem::MaskShape) ? "mask" : "bounding_rect");
|
||||
map.insert("shown_in_game_reload_message", this->shownInGameReloadMessage ? "1" : "0");
|
||||
map.insert("grid_width", QString::number(this->gridSettings.width));
|
||||
map.insert("grid_height", QString::number(this->gridSettings.height));
|
||||
map.insert("grid_x", QString::number(this->gridSettings.offsetX));
|
||||
map.insert("grid_y", QString::number(this->gridSettings.offsetY));
|
||||
map.insert("grid_style", GridSettings::getStyleName(this->gridSettings.style));
|
||||
map.insert("grid_color", this->gridSettings.color.name().remove("#")); // Our text config treats '#' as the start of a comment.
|
||||
|
||||
return map;
|
||||
}
|
||||
@@ -737,6 +774,10 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
|
||||
this->defaultElevation = getConfigUint32(key, value, 0, Block::maxValue);
|
||||
} else if (key == "default_collision") {
|
||||
this->defaultCollision = getConfigUint32(key, value, 0, Block::maxValue);
|
||||
} else if (key == "default_map_width") {
|
||||
this->defaultMapSize.setWidth(getConfigInteger(key, value, 1));
|
||||
} else if (key == "default_map_height") {
|
||||
this->defaultMapSize.setHeight(getConfigInteger(key, value, 1));
|
||||
} else if (key == "new_map_border_metatiles") {
|
||||
this->newMapBorderMetatileIds.clear();
|
||||
QList<QString> metatileIds = value.split(",");
|
||||
@@ -799,6 +840,10 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
|
||||
} else {
|
||||
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
|
||||
}
|
||||
} else if (key.startsWith("global_constant/")) {
|
||||
this->globalConstants.insert(key.mid(QStringLiteral("global_constant/").length()), value);
|
||||
} else if (key == "global_constants_filepaths") {
|
||||
this->globalConstantsFilepaths = value.split(",", Qt::SkipEmptyParts);
|
||||
} else if (key == "prefabs_filepath") {
|
||||
this->prefabFilepath = value;
|
||||
} else if (key == "prefabs_import_prompted") {
|
||||
@@ -809,6 +854,8 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
|
||||
this->tilesetsHaveIsCompressed = getConfigBool(key, value);
|
||||
} else if (key == "set_transparent_pixels_black") {
|
||||
this->setTransparentPixelsBlack = getConfigBool(key, value);
|
||||
} else if (key == "preserve_matching_only_data") {
|
||||
this->preserveMatchingOnlyData = getConfigBool(key, value);
|
||||
} else if (key == "event_icon_path_object") {
|
||||
this->eventIconPaths[Event::Group::Object] = value;
|
||||
} else if (key == "event_icon_path_warp") {
|
||||
@@ -820,13 +867,21 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
|
||||
} else if (key == "event_icon_path_heal") {
|
||||
this->eventIconPaths[Event::Group::Heal] = value;
|
||||
} else if (key.startsWith("pokemon_icon_path/")) {
|
||||
this->pokemonIconPaths.insert(key.mid(QStringLiteral("pokemon_icon_path/").length()).toUpper(), value);
|
||||
this->pokemonIconPaths.insert(key.mid(QStringLiteral("pokemon_icon_path/").length()), value);
|
||||
} else if (key == "collision_sheet_path") {
|
||||
this->collisionSheetPath = value;
|
||||
} else if (key == "collision_sheet_width") {
|
||||
this->collisionSheetWidth = getConfigUint32(key, value, 1, Block::maxValue);
|
||||
this->collisionSheetSize.setWidth(getConfigInteger(key, value, 1, Block::maxValue));
|
||||
} else if (key == "collision_sheet_height") {
|
||||
this->collisionSheetHeight = getConfigUint32(key, value, 1, Block::maxValue);
|
||||
this->collisionSheetSize.setHeight(getConfigInteger(key, value, 1, Block::maxValue));
|
||||
} else if (key == "player_view_north") {
|
||||
this->playerViewDistance.setTop(getConfigInteger(key, value, 0, INT_MAX, GBA_V_DIST_TO_CENTER));
|
||||
} else if (key == "player_view_south") {
|
||||
this->playerViewDistance.setBottom(getConfigInteger(key, value, 0, INT_MAX, GBA_V_DIST_TO_CENTER));
|
||||
} else if (key == "player_view_west") {
|
||||
this->playerViewDistance.setLeft(getConfigInteger(key, value, 0, INT_MAX, GBA_H_DIST_TO_CENTER));
|
||||
} else if (key == "player_view_east") {
|
||||
this->playerViewDistance.setRight(getConfigInteger(key, value, 0, INT_MAX, GBA_H_DIST_TO_CENTER));
|
||||
} else if (key == "warp_behaviors") {
|
||||
this->warpBehaviors.clear();
|
||||
value.remove(" ");
|
||||
@@ -862,7 +917,7 @@ void ProjectConfig::setUnreadKeys() {
|
||||
if (!readKeys.contains("enable_event_clone_object")) this->eventCloneObjectEnabled = isPokefirered;
|
||||
if (!readKeys.contains("enable_floor_number")) this->floorNumberEnabled = isPokefirered;
|
||||
if (!readKeys.contains("create_map_text_file")) this->createMapTextFileEnabled = (this->baseGameVersion != BaseGameVersion::pokeemerald);
|
||||
if (!readKeys.contains("new_map_border_metatiles")) this->newMapBorderMetatileIds = isPokefirered ? DEFAULT_BORDER_FRLG : DEFAULT_BORDER_RSE;
|
||||
if (!readKeys.contains("new_map_border_metatiles")) this->newMapBorderMetatileIds = isPokefirered ? defaultBorder_FRLG : defaultBorder_RSE;
|
||||
if (!readKeys.contains("default_secondary_tileset")) this->defaultSecondaryTileset = isPokefirered ? "gTileset_PalletTown" : "gTileset_Petalburg";
|
||||
if (!readKeys.contains("metatile_attributes_size")) this->metatileAttributesSize = Metatile::getDefaultAttributesSize(this->baseGameVersion);
|
||||
if (!readKeys.contains("metatile_behavior_mask")) this->metatileBehaviorMask = Metatile::getDefaultAttributesMask(this->baseGameVersion, Metatile::Attr::Behavior);
|
||||
@@ -890,6 +945,8 @@ QMap<QString, QString> ProjectConfig::getKeyValueMap() {
|
||||
map.insert("default_metatile", Metatile::getMetatileIdString(this->defaultMetatileId));
|
||||
map.insert("default_elevation", QString::number(this->defaultElevation));
|
||||
map.insert("default_collision", QString::number(this->defaultCollision));
|
||||
map.insert("default_map_width", QString::number(this->defaultMapSize.width()));
|
||||
map.insert("default_map_height", QString::number(this->defaultMapSize.height()));
|
||||
map.insert("new_map_border_metatiles", Metatile::getMetatileIdStrings(this->newMapBorderMetatileIds));
|
||||
map.insert("default_primary_tileset", this->defaultPrimaryTileset);
|
||||
map.insert("default_secondary_tileset", this->defaultSecondaryTileset);
|
||||
@@ -901,6 +958,7 @@ QMap<QString, QString> ProjectConfig::getKeyValueMap() {
|
||||
map.insert("tilesets_have_callback", QString::number(this->tilesetsHaveCallback));
|
||||
map.insert("tilesets_have_is_compressed", QString::number(this->tilesetsHaveIsCompressed));
|
||||
map.insert("set_transparent_pixels_black", QString::number(this->setTransparentPixelsBlack));
|
||||
map.insert("preserve_matching_only_data", QString::number(this->preserveMatchingOnlyData));
|
||||
map.insert("metatile_attributes_size", QString::number(this->metatileAttributesSize));
|
||||
map.insert("metatile_behavior_mask", Util::toHexString(this->metatileBehaviorMask));
|
||||
map.insert("metatile_terrain_type_mask", Util::toHexString(this->metatileTerrainTypeMask));
|
||||
@@ -918,16 +976,24 @@ QMap<QString, QString> ProjectConfig::getKeyValueMap() {
|
||||
map.insert("event_icon_path_coord", this->eventIconPaths[Event::Group::Coord]);
|
||||
map.insert("event_icon_path_bg", this->eventIconPaths[Event::Group::Bg]);
|
||||
map.insert("event_icon_path_heal", this->eventIconPaths[Event::Group::Heal]);
|
||||
for (auto i = this->pokemonIconPaths.cbegin(), end = this->pokemonIconPaths.cend(); i != end; i++){
|
||||
const QString path = i.value();
|
||||
if (!path.isEmpty()) map.insert("pokemon_icon_path/" + i.key(), path);
|
||||
for (auto it = this->pokemonIconPaths.constBegin(); it != this->pokemonIconPaths.constEnd(); it++) {
|
||||
const QString path = it.value();
|
||||
if (!path.isEmpty()) map.insert("pokemon_icon_path/" + it.key(), path);
|
||||
}
|
||||
for (auto i = this->identifiers.cbegin(), end = this->identifiers.cend(); i != end; i++) {
|
||||
map.insert("ident/"+defaultIdentifiers.value(i.key()).first, i.value());
|
||||
for (auto it = this->globalConstants.constBegin(); it != this->globalConstants.constEnd(); it++) {
|
||||
map.insert("global_constant/" + it.key(), it.value());
|
||||
}
|
||||
map.insert("global_constants_filepaths", this->globalConstantsFilepaths.join(","));
|
||||
for (auto it = this->identifiers.constBegin(); it != this->identifiers.constEnd(); it++) {
|
||||
map.insert("ident/"+defaultIdentifiers.value(it.key()).first, it.value());
|
||||
}
|
||||
map.insert("collision_sheet_path", this->collisionSheetPath);
|
||||
map.insert("collision_sheet_width", QString::number(this->collisionSheetWidth));
|
||||
map.insert("collision_sheet_height", QString::number(this->collisionSheetHeight));
|
||||
map.insert("collision_sheet_width", QString::number(this->collisionSheetSize.width()));
|
||||
map.insert("collision_sheet_height", QString::number(this->collisionSheetSize.height()));
|
||||
map.insert("player_view_north", QString::number(this->playerViewDistance.top()));
|
||||
map.insert("player_view_south", QString::number(this->playerViewDistance.bottom()));
|
||||
map.insert("player_view_west", QString::number(this->playerViewDistance.left()));
|
||||
map.insert("player_view_east", QString::number(this->playerViewDistance.right()));
|
||||
QStringList warpBehaviorStrs;
|
||||
for (const auto &value : this->warpBehaviors)
|
||||
warpBehaviorStrs.append("0x" + QString("%1").arg(value, 2, 16, QChar('0')).toUpper());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "editcommands.h"
|
||||
#include "draggablepixmapitem.h"
|
||||
#include "eventpixmapitem.h"
|
||||
#include "bordermetatilespixmapitem.h"
|
||||
#include "editor.h"
|
||||
|
||||
|
||||
@@ -20,8 +20,7 @@ Event* Event::create(Event::Type type) {
|
||||
}
|
||||
|
||||
Event::~Event() {
|
||||
if (this->eventFrame)
|
||||
this->eventFrame->deleteLater();
|
||||
delete this->eventFrame;
|
||||
}
|
||||
|
||||
EventFrame *Event::getEventFrame() {
|
||||
@@ -34,7 +33,7 @@ void Event::destroyEventFrame() {
|
||||
this->eventFrame = nullptr;
|
||||
}
|
||||
|
||||
void Event::setPixmapItem(DraggablePixmapItem *item) {
|
||||
void Event::setPixmapItem(EventPixmapItem *item) {
|
||||
this->pixmapItem = item;
|
||||
if (this->eventFrame) {
|
||||
this->eventFrame->invalidateConnections();
|
||||
@@ -51,24 +50,6 @@ void Event::setDefaultValues(Project *) {
|
||||
this->setElevation(projectConfig.defaultElevation);
|
||||
}
|
||||
|
||||
void Event::readCustomAttributes(const QJsonObject &json) {
|
||||
this->customAttributes.clear();
|
||||
const QSet<QString> expectedFields = this->getExpectedFields();
|
||||
for (auto i = json.constBegin(); i != json.constEnd(); i++) {
|
||||
if (!expectedFields.contains(i.key())) {
|
||||
this->customAttributes[i.key()] = i.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Event::addCustomAttributesTo(OrderedJson::object *obj) const {
|
||||
for (auto i = this->customAttributes.constBegin(); i != this->customAttributes.constEnd(); i++) {
|
||||
if (!obj->contains(i.key())) {
|
||||
(*obj)[i.key()] = OrderedJson::fromQJsonValue(i.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Event::modify() {
|
||||
this->map->modify();
|
||||
}
|
||||
@@ -123,7 +104,7 @@ QString Event::typeToString(Event::Type type) {
|
||||
{Event::Type::CloneObject, "Clone Object"},
|
||||
{Event::Type::Warp, "Warp"},
|
||||
{Event::Type::Trigger, "Trigger"},
|
||||
{Event::Type::WeatherTrigger, "Weather"},
|
||||
{Event::Type::WeatherTrigger, "Weather Trigger"},
|
||||
{Event::Type::Sign, "Sign"},
|
||||
{Event::Type::HiddenItem, "Hidden Item"},
|
||||
{Event::Type::SecretBase, "Secret Base"},
|
||||
@@ -132,9 +113,10 @@ QString Event::typeToString(Event::Type type) {
|
||||
return typeToStringMap.value(type);
|
||||
}
|
||||
|
||||
void Event::loadPixmap(Project *project) {
|
||||
QPixmap Event::loadPixmap(Project *project) {
|
||||
this->pixmap = project->getEventPixmap(this->getEventGroup());
|
||||
this->usesDefaultPixmap = true;
|
||||
return this->pixmap;
|
||||
}
|
||||
|
||||
|
||||
@@ -170,12 +152,13 @@ EventFrame *ObjectEvent::createEventFrame() {
|
||||
OrderedJson::object ObjectEvent::buildEventJson(Project *) {
|
||||
OrderedJson::object objectJson;
|
||||
|
||||
if (projectConfig.eventCloneObjectEnabled) {
|
||||
objectJson["type"] = Event::typeToJsonKey(Event::Type::Object);
|
||||
}
|
||||
QString idName = this->getIdName();
|
||||
if (!idName.isEmpty())
|
||||
objectJson["local_id"] = idName;
|
||||
|
||||
if (projectConfig.eventCloneObjectEnabled) {
|
||||
objectJson["type"] = Event::typeToJsonKey(Event::Type::Object);
|
||||
}
|
||||
objectJson["graphics_id"] = this->getGfx();
|
||||
objectJson["x"] = this->getX();
|
||||
objectJson["y"] = this->getY();
|
||||
@@ -187,27 +170,26 @@ OrderedJson::object ObjectEvent::buildEventJson(Project *) {
|
||||
objectJson["trainer_sight_or_berry_tree_id"] = this->getSightRadiusBerryTreeID();
|
||||
objectJson["script"] = this->getScript();
|
||||
objectJson["flag"] = this->getFlag();
|
||||
this->addCustomAttributesTo(&objectJson);
|
||||
|
||||
OrderedJson::append(&objectJson, this->getCustomAttributes());
|
||||
return objectJson;
|
||||
}
|
||||
|
||||
bool ObjectEvent::loadFromJson(const QJsonObject &json, Project *) {
|
||||
this->setX(ParseUtil::jsonToInt(json["x"]));
|
||||
this->setY(ParseUtil::jsonToInt(json["y"]));
|
||||
this->setElevation(ParseUtil::jsonToInt(json["elevation"]));
|
||||
this->setIdName(ParseUtil::jsonToQString(json["local_id"]));
|
||||
this->setGfx(ParseUtil::jsonToQString(json["graphics_id"]));
|
||||
this->setMovement(ParseUtil::jsonToQString(json["movement_type"]));
|
||||
this->setRadiusX(ParseUtil::jsonToInt(json["movement_range_x"]));
|
||||
this->setRadiusY(ParseUtil::jsonToInt(json["movement_range_y"]));
|
||||
this->setTrainerType(ParseUtil::jsonToQString(json["trainer_type"]));
|
||||
this->setSightRadiusBerryTreeID(ParseUtil::jsonToQString(json["trainer_sight_or_berry_tree_id"]));
|
||||
this->setScript(ParseUtil::jsonToQString(json["script"]));
|
||||
this->setFlag(ParseUtil::jsonToQString(json["flag"]));
|
||||
bool ObjectEvent::loadFromJson(QJsonObject json, Project *) {
|
||||
this->setX(readInt(&json, "x"));
|
||||
this->setY(readInt(&json, "y"));
|
||||
this->setElevation(readInt(&json, "elevation"));
|
||||
this->setIdName(readString(&json, "local_id"));
|
||||
this->setGfx(readString(&json, "graphics_id"));
|
||||
this->setMovement(readString(&json, "movement_type"));
|
||||
this->setRadiusX(readInt(&json, "movement_range_x"));
|
||||
this->setRadiusY(readInt(&json, "movement_range_y"));
|
||||
this->setTrainerType(readString(&json, "trainer_type"));
|
||||
this->setSightRadiusBerryTreeID(readString(&json, "trainer_sight_or_berry_tree_id"));
|
||||
this->setScript(readString(&json, "script"));
|
||||
this->setFlag(readString(&json, "flag"));
|
||||
|
||||
this->readCustomAttributes(json);
|
||||
|
||||
this->setCustomAttributes(json);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -222,36 +204,34 @@ void ObjectEvent::setDefaultValues(Project *project) {
|
||||
this->setSightRadiusBerryTreeID("0");
|
||||
}
|
||||
|
||||
const QSet<QString> expectedObjectFields = {
|
||||
"local_id",
|
||||
"graphics_id",
|
||||
"elevation",
|
||||
"movement_type",
|
||||
"movement_range_x",
|
||||
"movement_range_y",
|
||||
"trainer_type",
|
||||
"trainer_sight_or_berry_tree_id",
|
||||
"script",
|
||||
"flag",
|
||||
};
|
||||
|
||||
QSet<QString> ObjectEvent::getExpectedFields() {
|
||||
QSet<QString> expectedFields = QSet<QString>();
|
||||
expectedFields = expectedObjectFields;
|
||||
QSet<QString> expectedFields = {
|
||||
"x",
|
||||
"y",
|
||||
"local_id",
|
||||
"graphics_id",
|
||||
"elevation",
|
||||
"movement_type",
|
||||
"movement_range_x",
|
||||
"movement_range_y",
|
||||
"trainer_type",
|
||||
"trainer_sight_or_berry_tree_id",
|
||||
"script",
|
||||
"flag",
|
||||
};
|
||||
if (projectConfig.eventCloneObjectEnabled) {
|
||||
expectedFields.insert("type");
|
||||
}
|
||||
expectedFields << "x" << "y";
|
||||
return expectedFields;
|
||||
}
|
||||
|
||||
void ObjectEvent::loadPixmap(Project *project) {
|
||||
QPixmap ObjectEvent::loadPixmap(Project *project) {
|
||||
this->pixmap = project->getEventPixmap(this->gfx, this->movement);
|
||||
if (!this->pixmap.isNull()) {
|
||||
this->usesDefaultPixmap = false;
|
||||
} else {
|
||||
Event::loadPixmap(project);
|
||||
return this->pixmap;
|
||||
}
|
||||
return Event::loadPixmap(project);
|
||||
}
|
||||
|
||||
|
||||
@@ -282,65 +262,62 @@ EventFrame *CloneObjectEvent::createEventFrame() {
|
||||
OrderedJson::object CloneObjectEvent::buildEventJson(Project *project) {
|
||||
OrderedJson::object cloneJson;
|
||||
|
||||
cloneJson["type"] = Event::typeToJsonKey(Event::Type::CloneObject);
|
||||
QString idName = this->getIdName();
|
||||
if (!idName.isEmpty())
|
||||
cloneJson["local_id"] = idName;
|
||||
|
||||
cloneJson["type"] = Event::typeToJsonKey(Event::Type::CloneObject);
|
||||
cloneJson["graphics_id"] = this->getGfx();
|
||||
cloneJson["x"] = this->getX();
|
||||
cloneJson["y"] = this->getY();
|
||||
cloneJson["target_local_id"] = this->getTargetID();
|
||||
const QString mapName = this->getTargetMap();
|
||||
cloneJson["target_map"] = project->getMapConstant(mapName, mapName);
|
||||
this->addCustomAttributesTo(&cloneJson);
|
||||
|
||||
OrderedJson::append(&cloneJson, this->getCustomAttributes());
|
||||
return cloneJson;
|
||||
}
|
||||
|
||||
bool CloneObjectEvent::loadFromJson(const QJsonObject &json, Project *project) {
|
||||
this->setX(ParseUtil::jsonToInt(json["x"]));
|
||||
this->setY(ParseUtil::jsonToInt(json["y"]));
|
||||
this->setIdName(ParseUtil::jsonToQString(json["local_id"]));
|
||||
this->setGfx(ParseUtil::jsonToQString(json["graphics_id"]));
|
||||
this->setTargetID(ParseUtil::jsonToInt(json["target_local_id"]));
|
||||
bool CloneObjectEvent::loadFromJson(QJsonObject json, Project *project) {
|
||||
this->setX(readInt(&json, "x"));
|
||||
this->setY(readInt(&json, "y"));
|
||||
this->setIdName(readString(&json, "local_id"));
|
||||
this->setGfx(readString(&json, "graphics_id"));
|
||||
this->setTargetID(readString(&json, "target_local_id"));
|
||||
|
||||
// Log a warning if "target_map" isn't a known map ID, but don't overwrite user data.
|
||||
const QString mapConstant = ParseUtil::jsonToQString(json["target_map"]);
|
||||
const QString mapConstant = readString(&json, "target_map");
|
||||
if (!project->mapConstantsToMapNames.contains(mapConstant))
|
||||
logWarn(QString("Unknown Target Map constant '%1'.").arg(mapConstant));
|
||||
this->setTargetMap(project->mapConstantsToMapNames.value(mapConstant, mapConstant));
|
||||
|
||||
this->readCustomAttributes(json);
|
||||
|
||||
this->setCustomAttributes(json);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CloneObjectEvent::setDefaultValues(Project *project) {
|
||||
this->setGfx(project->gfxDefines.key(0, "0"));
|
||||
this->setTargetID(1);
|
||||
this->setTargetID(QString::number(Event::getIndexOffset(Event::Group::Object)));
|
||||
if (this->getMap()) this->setTargetMap(this->getMap()->name());
|
||||
}
|
||||
|
||||
const QSet<QString> expectedCloneObjectFields = {
|
||||
"type",
|
||||
"local_id",
|
||||
"graphics_id",
|
||||
"target_local_id",
|
||||
"target_map",
|
||||
};
|
||||
|
||||
QSet<QString> CloneObjectEvent::getExpectedFields() {
|
||||
QSet<QString> expectedFields = QSet<QString>();
|
||||
expectedFields = expectedCloneObjectFields;
|
||||
expectedFields << "x" << "y";
|
||||
static const QSet<QString> expectedFields = {
|
||||
"x",
|
||||
"y",
|
||||
"type",
|
||||
"local_id",
|
||||
"graphics_id",
|
||||
"target_local_id",
|
||||
"target_map",
|
||||
};
|
||||
return expectedFields;
|
||||
}
|
||||
|
||||
void CloneObjectEvent::loadPixmap(Project *project) {
|
||||
QPixmap CloneObjectEvent::loadPixmap(Project *project) {
|
||||
// Try to get the targeted object to clone
|
||||
int eventIndex = this->targetID - 1;
|
||||
Map *clonedMap = project->loadMap(this->targetMap);
|
||||
Event *clonedEvent = clonedMap ? clonedMap->getEvent(Event::Group::Object, eventIndex) : nullptr;
|
||||
Event *clonedEvent = clonedMap ? clonedMap->getEvent(Event::Group::Object, this->targetID) : nullptr;
|
||||
|
||||
if (clonedEvent && clonedEvent->getEventType() == Event::Type::Object) {
|
||||
// Get graphics data from cloned object
|
||||
@@ -352,7 +329,7 @@ void CloneObjectEvent::loadPixmap(Project *project) {
|
||||
this->gfx = project->gfxDefines.key(0, "0");
|
||||
this->movement = project->movementTypes.value(0, "0");
|
||||
}
|
||||
ObjectEvent::loadPixmap(project);
|
||||
return ObjectEvent::loadPixmap(project);
|
||||
}
|
||||
|
||||
|
||||
@@ -389,25 +366,23 @@ OrderedJson::object WarpEvent::buildEventJson(Project *project) {
|
||||
warpJson["dest_map"] = project->getMapConstant(mapName, mapName);
|
||||
warpJson["dest_warp_id"] = this->getDestinationWarpID();
|
||||
|
||||
this->addCustomAttributesTo(&warpJson);
|
||||
|
||||
OrderedJson::append(&warpJson, this->getCustomAttributes());
|
||||
return warpJson;
|
||||
}
|
||||
|
||||
bool WarpEvent::loadFromJson(const QJsonObject &json, Project *project) {
|
||||
this->setX(ParseUtil::jsonToInt(json["x"]));
|
||||
this->setY(ParseUtil::jsonToInt(json["y"]));
|
||||
this->setElevation(ParseUtil::jsonToInt(json["elevation"]));
|
||||
this->setDestinationWarpID(ParseUtil::jsonToQString(json["dest_warp_id"]));
|
||||
bool WarpEvent::loadFromJson(QJsonObject json, Project *project) {
|
||||
this->setX(readInt(&json, "x"));
|
||||
this->setY(readInt(&json, "y"));
|
||||
this->setElevation(readInt(&json, "elevation"));
|
||||
this->setDestinationWarpID(readString(&json, "dest_warp_id"));
|
||||
|
||||
// Log a warning if "dest_map" isn't a known map ID, but don't overwrite user data.
|
||||
const QString mapConstant = ParseUtil::jsonToQString(json["dest_map"]);
|
||||
const QString mapConstant = readString(&json, "dest_map");
|
||||
if (!project->mapConstantsToMapNames.contains(mapConstant))
|
||||
logWarn(QString("Unknown Destination Map constant '%1'.").arg(mapConstant));
|
||||
this->setDestinationMap(project->mapConstantsToMapNames.value(mapConstant, mapConstant));
|
||||
|
||||
this->readCustomAttributes(json);
|
||||
|
||||
this->setCustomAttributes(json);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -417,16 +392,14 @@ void WarpEvent::setDefaultValues(Project *) {
|
||||
this->setElevation(0);
|
||||
}
|
||||
|
||||
const QSet<QString> expectedWarpFields = {
|
||||
"elevation",
|
||||
"dest_map",
|
||||
"dest_warp_id",
|
||||
};
|
||||
|
||||
QSet<QString> WarpEvent::getExpectedFields() {
|
||||
QSet<QString> expectedFields = QSet<QString>();
|
||||
expectedFields = expectedWarpFields;
|
||||
expectedFields << "x" << "y";
|
||||
static const QSet<QString> expectedFields = {
|
||||
"x",
|
||||
"y",
|
||||
"elevation",
|
||||
"dest_map",
|
||||
"dest_warp_id",
|
||||
};
|
||||
return expectedFields;
|
||||
}
|
||||
|
||||
@@ -476,21 +449,19 @@ OrderedJson::object TriggerEvent::buildEventJson(Project *) {
|
||||
triggerJson["var_value"] = this->getScriptVarValue();
|
||||
triggerJson["script"] = this->getScriptLabel();
|
||||
|
||||
this->addCustomAttributesTo(&triggerJson);
|
||||
|
||||
OrderedJson::append(&triggerJson, this->getCustomAttributes());
|
||||
return triggerJson;
|
||||
}
|
||||
|
||||
bool TriggerEvent::loadFromJson(const QJsonObject &json, Project *) {
|
||||
this->setX(ParseUtil::jsonToInt(json["x"]));
|
||||
this->setY(ParseUtil::jsonToInt(json["y"]));
|
||||
this->setElevation(ParseUtil::jsonToInt(json["elevation"]));
|
||||
this->setScriptVar(ParseUtil::jsonToQString(json["var"]));
|
||||
this->setScriptVarValue(ParseUtil::jsonToQString(json["var_value"]));
|
||||
this->setScriptLabel(ParseUtil::jsonToQString(json["script"]));
|
||||
|
||||
this->readCustomAttributes(json);
|
||||
bool TriggerEvent::loadFromJson(QJsonObject json, Project *) {
|
||||
this->setX(readInt(&json, "x"));
|
||||
this->setY(readInt(&json, "y"));
|
||||
this->setElevation(readInt(&json, "elevation"));
|
||||
this->setScriptVar(readString(&json, "var"));
|
||||
this->setScriptVarValue(readString(&json, "var_value"));
|
||||
this->setScriptLabel(readString(&json, "script"));
|
||||
|
||||
this->setCustomAttributes(json);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -501,18 +472,16 @@ void TriggerEvent::setDefaultValues(Project *project) {
|
||||
this->setElevation(0);
|
||||
}
|
||||
|
||||
const QSet<QString> expectedTriggerFields = {
|
||||
"type",
|
||||
"elevation",
|
||||
"var",
|
||||
"var_value",
|
||||
"script",
|
||||
};
|
||||
|
||||
QSet<QString> TriggerEvent::getExpectedFields() {
|
||||
QSet<QString> expectedFields = QSet<QString>();
|
||||
expectedFields = expectedTriggerFields;
|
||||
expectedFields << "x" << "y";
|
||||
static const QSet<QString> expectedFields = {
|
||||
"x",
|
||||
"y",
|
||||
"type",
|
||||
"elevation",
|
||||
"var",
|
||||
"var_value",
|
||||
"script",
|
||||
};
|
||||
return expectedFields;
|
||||
}
|
||||
|
||||
@@ -548,19 +517,17 @@ OrderedJson::object WeatherTriggerEvent::buildEventJson(Project *) {
|
||||
weatherJson["elevation"] = this->getElevation();
|
||||
weatherJson["weather"] = this->getWeather();
|
||||
|
||||
this->addCustomAttributesTo(&weatherJson);
|
||||
|
||||
OrderedJson::append(&weatherJson, this->getCustomAttributes());
|
||||
return weatherJson;
|
||||
}
|
||||
|
||||
bool WeatherTriggerEvent::loadFromJson(const QJsonObject &json, Project *) {
|
||||
this->setX(ParseUtil::jsonToInt(json["x"]));
|
||||
this->setY(ParseUtil::jsonToInt(json["y"]));
|
||||
this->setElevation(ParseUtil::jsonToInt(json["elevation"]));
|
||||
this->setWeather(ParseUtil::jsonToQString(json["weather"]));
|
||||
|
||||
this->readCustomAttributes(json);
|
||||
bool WeatherTriggerEvent::loadFromJson(QJsonObject json, Project *) {
|
||||
this->setX(readInt(&json, "x"));
|
||||
this->setY(readInt(&json, "y"));
|
||||
this->setElevation(readInt(&json, "elevation"));
|
||||
this->setWeather(readString(&json, "weather"));
|
||||
|
||||
this->setCustomAttributes(json);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -569,16 +536,14 @@ void WeatherTriggerEvent::setDefaultValues(Project *project) {
|
||||
this->setElevation(0);
|
||||
}
|
||||
|
||||
const QSet<QString> expectedWeatherTriggerFields = {
|
||||
"type",
|
||||
"elevation",
|
||||
"weather",
|
||||
};
|
||||
|
||||
QSet<QString> WeatherTriggerEvent::getExpectedFields() {
|
||||
QSet<QString> expectedFields = QSet<QString>();
|
||||
expectedFields = expectedWeatherTriggerFields;
|
||||
expectedFields << "x" << "y";
|
||||
static const QSet<QString> expectedFields = {
|
||||
"x",
|
||||
"y",
|
||||
"type",
|
||||
"elevation",
|
||||
"weather",
|
||||
};
|
||||
return expectedFields;
|
||||
}
|
||||
|
||||
@@ -616,20 +581,18 @@ OrderedJson::object SignEvent::buildEventJson(Project *) {
|
||||
signJson["player_facing_dir"] = this->getFacingDirection();
|
||||
signJson["script"] = this->getScriptLabel();
|
||||
|
||||
this->addCustomAttributesTo(&signJson);
|
||||
|
||||
OrderedJson::append(&signJson, this->getCustomAttributes());
|
||||
return signJson;
|
||||
}
|
||||
|
||||
bool SignEvent::loadFromJson(const QJsonObject &json, Project *) {
|
||||
this->setX(ParseUtil::jsonToInt(json["x"]));
|
||||
this->setY(ParseUtil::jsonToInt(json["y"]));
|
||||
this->setElevation(ParseUtil::jsonToInt(json["elevation"]));
|
||||
this->setFacingDirection(ParseUtil::jsonToQString(json["player_facing_dir"]));
|
||||
this->setScriptLabel(ParseUtil::jsonToQString(json["script"]));
|
||||
|
||||
this->readCustomAttributes(json);
|
||||
bool SignEvent::loadFromJson(QJsonObject json, Project *) {
|
||||
this->setX(readInt(&json, "x"));
|
||||
this->setY(readInt(&json, "y"));
|
||||
this->setElevation(readInt(&json, "elevation"));
|
||||
this->setFacingDirection(readString(&json, "player_facing_dir"));
|
||||
this->setScriptLabel(readString(&json, "script"));
|
||||
|
||||
this->setCustomAttributes(json);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -639,17 +602,15 @@ void SignEvent::setDefaultValues(Project *project) {
|
||||
this->setElevation(0);
|
||||
}
|
||||
|
||||
const QSet<QString> expectedSignFields = {
|
||||
"type",
|
||||
"elevation",
|
||||
"player_facing_dir",
|
||||
"script",
|
||||
};
|
||||
|
||||
QSet<QString> SignEvent::getExpectedFields() {
|
||||
QSet<QString> expectedFields = QSet<QString>();
|
||||
expectedFields = expectedSignFields;
|
||||
expectedFields << "x" << "y";
|
||||
static const QSet<QString> expectedFields = {
|
||||
"x",
|
||||
"y",
|
||||
"type",
|
||||
"elevation",
|
||||
"player_facing_dir",
|
||||
"script",
|
||||
};
|
||||
return expectedFields;
|
||||
}
|
||||
|
||||
@@ -695,26 +656,24 @@ OrderedJson::object HiddenItemEvent::buildEventJson(Project *) {
|
||||
hiddenItemJson["underfoot"] = this->getUnderfoot();
|
||||
}
|
||||
|
||||
this->addCustomAttributesTo(&hiddenItemJson);
|
||||
|
||||
OrderedJson::append(&hiddenItemJson, this->getCustomAttributes());
|
||||
return hiddenItemJson;
|
||||
}
|
||||
|
||||
bool HiddenItemEvent::loadFromJson(const QJsonObject &json, Project *) {
|
||||
this->setX(ParseUtil::jsonToInt(json["x"]));
|
||||
this->setY(ParseUtil::jsonToInt(json["y"]));
|
||||
this->setElevation(ParseUtil::jsonToInt(json["elevation"]));
|
||||
this->setItem(ParseUtil::jsonToQString(json["item"]));
|
||||
this->setFlag(ParseUtil::jsonToQString(json["flag"]));
|
||||
bool HiddenItemEvent::loadFromJson(QJsonObject json, Project *) {
|
||||
this->setX(readInt(&json, "x"));
|
||||
this->setY(readInt(&json, "y"));
|
||||
this->setElevation(readInt(&json, "elevation"));
|
||||
this->setItem(readString(&json, "item"));
|
||||
this->setFlag(readString(&json, "flag"));
|
||||
if (projectConfig.hiddenItemQuantityEnabled) {
|
||||
this->setQuantity(ParseUtil::jsonToInt(json["quantity"]));
|
||||
this->setQuantity(readInt(&json, "quantity"));
|
||||
}
|
||||
if (projectConfig.hiddenItemRequiresItemfinderEnabled) {
|
||||
this->setUnderfoot(ParseUtil::jsonToBool(json["underfoot"]));
|
||||
this->setUnderfoot(readBool(&json, "underfoot"));
|
||||
}
|
||||
|
||||
this->readCustomAttributes(json);
|
||||
|
||||
this->setCustomAttributes(json);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -729,23 +688,21 @@ void HiddenItemEvent::setDefaultValues(Project *project) {
|
||||
}
|
||||
}
|
||||
|
||||
const QSet<QString> expectedHiddenItemFields = {
|
||||
"type",
|
||||
"elevation",
|
||||
"item",
|
||||
"flag",
|
||||
};
|
||||
|
||||
QSet<QString> HiddenItemEvent::getExpectedFields() {
|
||||
QSet<QString> expectedFields = QSet<QString>();
|
||||
expectedFields = expectedHiddenItemFields;
|
||||
QSet<QString> expectedFields = {
|
||||
"x",
|
||||
"y",
|
||||
"type",
|
||||
"elevation",
|
||||
"item",
|
||||
"flag",
|
||||
};
|
||||
if (projectConfig.hiddenItemQuantityEnabled) {
|
||||
expectedFields << "quantity";
|
||||
}
|
||||
if (projectConfig.hiddenItemRequiresItemfinderEnabled) {
|
||||
expectedFields << "underfoot";
|
||||
}
|
||||
expectedFields << "x" << "y";
|
||||
return expectedFields;
|
||||
}
|
||||
|
||||
@@ -781,19 +738,17 @@ OrderedJson::object SecretBaseEvent::buildEventJson(Project *) {
|
||||
secretBaseJson["elevation"] = this->getElevation();
|
||||
secretBaseJson["secret_base_id"] = this->getBaseID();
|
||||
|
||||
this->addCustomAttributesTo(&secretBaseJson);
|
||||
|
||||
OrderedJson::append(&secretBaseJson, this->getCustomAttributes());
|
||||
return secretBaseJson;
|
||||
}
|
||||
|
||||
bool SecretBaseEvent::loadFromJson(const QJsonObject &json, Project *) {
|
||||
this->setX(ParseUtil::jsonToInt(json["x"]));
|
||||
this->setY(ParseUtil::jsonToInt(json["y"]));
|
||||
this->setElevation(ParseUtil::jsonToInt(json["elevation"]));
|
||||
this->setBaseID(ParseUtil::jsonToQString(json["secret_base_id"]));
|
||||
|
||||
this->readCustomAttributes(json);
|
||||
bool SecretBaseEvent::loadFromJson(QJsonObject json, Project *) {
|
||||
this->setX(readInt(&json, "x"));
|
||||
this->setY(readInt(&json, "y"));
|
||||
this->setElevation(readInt(&json, "elevation"));
|
||||
this->setBaseID(readString(&json, "secret_base_id"));
|
||||
|
||||
this->setCustomAttributes(json);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -802,16 +757,14 @@ void SecretBaseEvent::setDefaultValues(Project *project) {
|
||||
this->setElevation(0);
|
||||
}
|
||||
|
||||
const QSet<QString> expectedSecretBaseFields = {
|
||||
"type",
|
||||
"elevation",
|
||||
"secret_base_id",
|
||||
};
|
||||
|
||||
QSet<QString> SecretBaseEvent::getExpectedFields() {
|
||||
QSet<QString> expectedFields = QSet<QString>();
|
||||
expectedFields = expectedSecretBaseFields;
|
||||
expectedFields << "x" << "y";
|
||||
static const QSet<QString> expectedFields = {
|
||||
"x",
|
||||
"y",
|
||||
"type",
|
||||
"elevation",
|
||||
"secret_base_id",
|
||||
};
|
||||
return expectedFields;
|
||||
}
|
||||
|
||||
@@ -823,6 +776,7 @@ Event *HealLocationEvent::duplicate() const {
|
||||
copy->setX(this->getX());
|
||||
copy->setY(this->getY());
|
||||
copy->setIdName(this->getIdName());
|
||||
copy->setHostMapName(this->getHostMapName());
|
||||
copy->setRespawnMapName(this->getRespawnMapName());
|
||||
copy->setRespawnNPC(this->getRespawnNPC());
|
||||
|
||||
@@ -839,12 +793,15 @@ EventFrame *HealLocationEvent::createEventFrame() {
|
||||
return this->eventFrame;
|
||||
}
|
||||
|
||||
QString HealLocationEvent::getHostMapName() const {
|
||||
return this->getMap() ? this->getMap()->constantName() : this->hostMapName;
|
||||
}
|
||||
|
||||
OrderedJson::object HealLocationEvent::buildEventJson(Project *project) {
|
||||
OrderedJson::object healLocationJson;
|
||||
|
||||
healLocationJson["id"] = this->getIdName();
|
||||
// This field doesn't need to be stored in the Event itself, so it's output only.
|
||||
healLocationJson["map"] = this->getMap() ? this->getMap()->constantName() : QString();
|
||||
healLocationJson["map"] = this->getHostMapName();
|
||||
healLocationJson["x"] = this->getX();
|
||||
healLocationJson["y"] = this->getY();
|
||||
if (projectConfig.healLocationRespawnDataEnabled) {
|
||||
@@ -853,26 +810,26 @@ OrderedJson::object HealLocationEvent::buildEventJson(Project *project) {
|
||||
healLocationJson["respawn_npc"] = this->getRespawnNPC();
|
||||
}
|
||||
|
||||
this->addCustomAttributesTo(&healLocationJson);
|
||||
|
||||
OrderedJson::append(&healLocationJson, this->getCustomAttributes());
|
||||
return healLocationJson;
|
||||
}
|
||||
|
||||
bool HealLocationEvent::loadFromJson(const QJsonObject &json, Project *project) {
|
||||
this->setX(ParseUtil::jsonToInt(json["x"]));
|
||||
this->setY(ParseUtil::jsonToInt(json["y"]));
|
||||
this->setIdName(ParseUtil::jsonToQString(json["id"]));
|
||||
bool HealLocationEvent::loadFromJson(QJsonObject json, Project *project) {
|
||||
this->setX(readInt(&json, "x"));
|
||||
this->setY(readInt(&json, "y"));
|
||||
this->setIdName(readString(&json, "id"));
|
||||
this->setHostMapName(readString(&json, "map"));
|
||||
|
||||
if (projectConfig.healLocationRespawnDataEnabled) {
|
||||
// Log a warning if "respawn_map" isn't a known map ID, but don't overwrite user data.
|
||||
const QString mapConstant = ParseUtil::jsonToQString(json["respawn_map"]);
|
||||
const QString mapConstant = readString(&json, "respawn_map");
|
||||
if (!project->mapConstantsToMapNames.contains(mapConstant))
|
||||
logWarn(QString("Unknown Respawn Map constant '%1'.").arg(mapConstant));
|
||||
this->setRespawnMapName(project->mapConstantsToMapNames.value(mapConstant, mapConstant));
|
||||
this->setRespawnNPC(ParseUtil::jsonToQString(json["respawn_npc"]));
|
||||
this->setRespawnNPC(readString(&json, "respawn_npc"));
|
||||
}
|
||||
|
||||
this->readCustomAttributes(json);
|
||||
this->setCustomAttributes(json);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -885,16 +842,19 @@ void HealLocationEvent::setDefaultValues(Project *project) {
|
||||
}
|
||||
|
||||
const QSet<QString> expectedHealLocationFields = {
|
||||
"id",
|
||||
"map"
|
||||
|
||||
};
|
||||
|
||||
QSet<QString> HealLocationEvent::getExpectedFields() {
|
||||
QSet<QString> expectedFields = expectedHealLocationFields;
|
||||
QSet<QString> expectedFields = {
|
||||
"x",
|
||||
"y",
|
||||
"id",
|
||||
"map",
|
||||
};
|
||||
if (projectConfig.healLocationRespawnDataEnabled) {
|
||||
expectedFields.insert("respawn_map");
|
||||
expectedFields.insert("respawn_npc");
|
||||
}
|
||||
expectedFields << "x" << "y";
|
||||
return expectedFields;
|
||||
}
|
||||
|
||||
@@ -83,16 +83,17 @@ QRect Map::getConnectionRect(const QString &direction, Layout * fromLayout) cons
|
||||
int x = 0, y = 0;
|
||||
int w = getWidth(), h = getHeight();
|
||||
|
||||
QMargins viewDistance = Project::getMetatileViewDistance();
|
||||
if (direction == "up") {
|
||||
h = qMin(h, BORDER_DISTANCE);
|
||||
h = qMin(h, viewDistance.top());
|
||||
y = getHeight() - h;
|
||||
} else if (direction == "down") {
|
||||
h = qMin(h, BORDER_DISTANCE);
|
||||
h = qMin(h, viewDistance.bottom());
|
||||
} else if (direction == "left") {
|
||||
w = qMin(w, BORDER_DISTANCE);
|
||||
w = qMin(w, viewDistance.left());
|
||||
x = getWidth() - w;
|
||||
} else if (direction == "right") {
|
||||
w = qMin(w, BORDER_DISTANCE);
|
||||
w = qMin(w, viewDistance.right());
|
||||
} else if (MapConnection::isDiving(direction)) {
|
||||
if (fromLayout) {
|
||||
w = qMin(w, fromLayout->getWidth());
|
||||
@@ -194,6 +195,49 @@ Event* Map::getEvent(Event::Group group, int index) const {
|
||||
return m_events[group].value(index, nullptr);
|
||||
}
|
||||
|
||||
Event* Map::getEvent(Event::Group group, const QString &idName) const {
|
||||
if (idName.isEmpty())
|
||||
return nullptr;
|
||||
|
||||
bool idIsNumber;
|
||||
int id = idName.toInt(&idIsNumber, 0);
|
||||
if (idIsNumber)
|
||||
return getEvent(group, id - Event::getIndexOffset(group));
|
||||
|
||||
auto events = getEvents(group);
|
||||
for (const auto &event : events) {
|
||||
if (event->getIdName() == idName) {
|
||||
return event;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Returns a list of ID names for the given event group (or all events, if no group is given).
|
||||
// For events with no explicit ID name, their index string is given instead.
|
||||
QStringList Map::getEventIdNames(Event::Group group) const {
|
||||
QList<Event::Group> groups;
|
||||
if (group == Event::Group::None) {
|
||||
groups = Event::groups();
|
||||
} else {
|
||||
groups.append(group);
|
||||
}
|
||||
|
||||
QStringList idNames;
|
||||
for (const auto &group : groups) {
|
||||
const auto events = m_events[group];
|
||||
int indexOffset = Event::getIndexOffset(group);
|
||||
for (int i = 0; i < events.length(); i++) {
|
||||
QString idName = events.at(i)->getIdName();
|
||||
if (idName.isEmpty()) {
|
||||
idName = QString::number(i + indexOffset);
|
||||
}
|
||||
idNames.append(idName);
|
||||
}
|
||||
}
|
||||
return idNames;
|
||||
}
|
||||
|
||||
int Map::getNumEvents(Event::Group group) const {
|
||||
if (group == Event::Group::None) {
|
||||
// Total number of events
|
||||
@@ -288,6 +332,15 @@ void Map::removeConnection(MapConnection *connection) {
|
||||
emit connectionRemoved(connection);
|
||||
}
|
||||
|
||||
// Return the first map connection that has the given direction.
|
||||
MapConnection* Map::getConnection(const QString &direction) const {
|
||||
for (const auto &connection : m_connections) {
|
||||
if (connection->direction() == direction)
|
||||
return connection;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Map::commit(QUndoCommand *cmd) {
|
||||
m_editHistory->push(cmd);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ void Layout::copyFrom(const Layout *other) {
|
||||
this->tileset_secondary = other->tileset_secondary;
|
||||
this->blockdata = other->blockdata;
|
||||
this->border = other->border;
|
||||
this->customData = other->customData;
|
||||
}
|
||||
|
||||
QString Layout::layoutConstantFromName(const QString &name) {
|
||||
@@ -62,17 +63,11 @@ bool Layout::isWithinBorderBounds(int x, int y) const {
|
||||
return (x >= 0 && x < this->getBorderWidth() && y >= 0 && y < this->getBorderHeight());
|
||||
}
|
||||
|
||||
int Layout::getBorderDrawWidth() const {
|
||||
return getBorderDrawDistance(border_width, BORDER_DISTANCE);
|
||||
}
|
||||
|
||||
int Layout::getBorderDrawHeight() const {
|
||||
return getBorderDrawDistance(border_height, BORDER_DISTANCE);
|
||||
}
|
||||
|
||||
// We need to draw sufficient border blocks to fill the area that gets loaded around the player in-game (BORDER_DISTANCE).
|
||||
// Note that this is not the same as the player's view distance.
|
||||
// The result will be some multiple of the input dimension, because we only draw the border in increments of its full width/height.
|
||||
// Calculate the distance away from the layout's edge that we need to start drawing border blocks.
|
||||
// We need to fulfill two requirements here:
|
||||
// - We should draw enough to fill the player's in-game view
|
||||
// - The value should be some multiple of the border's dimension
|
||||
// (otherwise the border won't be positioned the same as it would in-game).
|
||||
int Layout::getBorderDrawDistance(int dimension, qreal minimum) {
|
||||
if (dimension >= minimum)
|
||||
return dimension;
|
||||
@@ -80,6 +75,23 @@ int Layout::getBorderDrawDistance(int dimension, qreal minimum) {
|
||||
// Get first multiple of dimension >= the minimum
|
||||
return dimension * qCeil(minimum / qMax(dimension, 1));
|
||||
}
|
||||
QMargins Layout::getBorderMargins() const {
|
||||
QMargins minimum = Project::getMetatileViewDistance();
|
||||
QMargins distance;
|
||||
distance.setTop(getBorderDrawDistance(this->border_height, minimum.top()));
|
||||
distance.setBottom(getBorderDrawDistance(this->border_height, minimum.bottom()));
|
||||
distance.setLeft(getBorderDrawDistance(this->border_width, minimum.left()));
|
||||
distance.setRight(getBorderDrawDistance(this->border_width, minimum.right()));
|
||||
return distance;
|
||||
}
|
||||
|
||||
// Get a rectangle that represents (in pixels) the layout's map area and the visible area of its border.
|
||||
// At maximum, this is equal to the map size plus the border margins.
|
||||
// If the border is large (and so beyond player the view) it may be smaller than that.
|
||||
QRect Layout::getVisibleRect() const {
|
||||
QRect area = QRect(0, 0, this->width * 16, this->height * 16);
|
||||
return area += (Project::getMetatileViewDistance() * 16);
|
||||
}
|
||||
|
||||
bool Layout::getBlock(int x, int y, Block *out) {
|
||||
if (isWithinBounds(x, y)) {
|
||||
@@ -177,46 +189,38 @@ void Layout::setBorderBlockData(Blockdata newBlockdata, bool enableScriptCallbac
|
||||
}
|
||||
}
|
||||
|
||||
void Layout::setDimensions(int newWidth, int newHeight, bool setNewBlockdata, bool enableScriptCallback) {
|
||||
void Layout::setDimensions(int newWidth, int newHeight, bool setNewBlockdata) {
|
||||
if (setNewBlockdata) {
|
||||
setNewDimensionsBlockdata(newWidth, newHeight);
|
||||
}
|
||||
|
||||
int oldWidth = this->width;
|
||||
int oldHeight = this->height;
|
||||
this->width = newWidth;
|
||||
this->height = newHeight;
|
||||
|
||||
if (enableScriptCallback && (oldWidth != newWidth || oldHeight != newHeight)) {
|
||||
Scripting::cb_MapResized(oldWidth, oldHeight, newWidth, newHeight);
|
||||
}
|
||||
|
||||
emit dimensionsChanged(QSize(getWidth(), getHeight()));
|
||||
emit dimensionsChanged(QSize(this->width, this->height));
|
||||
}
|
||||
|
||||
void Layout::adjustDimensions(QMargins margins, bool setNewBlockdata) {
|
||||
int newWidth = this->width + margins.left() + margins.right();
|
||||
int newHeight = this->height + margins.top() + margins.bottom();
|
||||
void Layout::adjustDimensions(const QMargins &margins, bool setNewBlockdata) {
|
||||
int oldWidth = this->width;
|
||||
int oldHeight = this->height;
|
||||
this->width = oldWidth + margins.left() + margins.right();
|
||||
this->height = oldHeight + 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())) {
|
||||
for (int y = 0; y < this->height; y++)
|
||||
for (int x = 0; x < this->width; x++) {
|
||||
if ((x < margins.left()) || (x >= this->width - margins.right()) || (y < margins.top()) || (y >= this->height - margins.bottom())) {
|
||||
newBlockdata.append(0);
|
||||
} else {
|
||||
int index = (y - margins.top()) * this->width + (x - margins.left());
|
||||
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 dimensionsChanged(QSize(getWidth(), getHeight()));
|
||||
Scripting::cb_MapResized(oldWidth, oldHeight, margins);
|
||||
emit dimensionsChanged(QSize(this->width, this->height));
|
||||
}
|
||||
|
||||
void Layout::setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata, bool enableScriptCallback) {
|
||||
@@ -466,11 +470,50 @@ QPixmap Layout::getLayoutItemPixmap() {
|
||||
return this->layoutItem ? this->layoutItem->pixmap() : QPixmap();
|
||||
}
|
||||
|
||||
void Layout::setClean() {
|
||||
this->editHistory.setClean();
|
||||
this->hasUnsavedDataChanges = false;
|
||||
}
|
||||
|
||||
bool Layout::hasUnsavedChanges() const {
|
||||
return !this->editHistory.isClean() || this->hasUnsavedDataChanges || !this->newFolderPath.isEmpty();
|
||||
}
|
||||
|
||||
bool Layout::save(const QString &root) {
|
||||
if (!this->newFolderPath.isEmpty()) {
|
||||
// Layout directory doesn't exist yet, create it now.
|
||||
const QString fullPath = QString("%1/%2").arg(root).arg(this->newFolderPath);
|
||||
if (!QDir::root().mkpath(fullPath)) {
|
||||
logError(QString("Failed to create directory for new layout: '%1'").arg(fullPath));
|
||||
return false;
|
||||
}
|
||||
this->newFolderPath = QString();
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
if (!saveBorder(root)) success = false;
|
||||
if (!saveBlockdata(root)) success = false;
|
||||
if (!success)
|
||||
return false;
|
||||
|
||||
this->editHistory.setClean();
|
||||
this->hasUnsavedDataChanges = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Layout::saveBorder(const QString &root) {
|
||||
QString path = QString("%1/%2").arg(root).arg(this->border_path);
|
||||
return writeBlockdata(path, this->border);
|
||||
}
|
||||
|
||||
bool Layout::saveBlockdata(const QString &root) {
|
||||
QString path = QString("%1/%2").arg(root).arg(this->blockdata_path);
|
||||
return writeBlockdata(path, this->blockdata);
|
||||
}
|
||||
|
||||
bool Layout::writeBlockdata(const QString &path, const Blockdata &blockdata) const {
|
||||
QFile file(path);
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
logError(QString("Could not open '%1' for writing: %2").arg(path).arg(file.errorString()));
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray data = blockdata.serialize();
|
||||
file.write(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -38,14 +38,14 @@ QList<QRgb> PaletteUtil::parse(QString filepath, bool *error) {
|
||||
return QList<QRgb>();
|
||||
}
|
||||
|
||||
void PaletteUtil::writeJASC(QString filepath, QVector<QRgb> palette, int offset, int nColors) {
|
||||
bool PaletteUtil::writeJASC(const QString &filepath, const QVector<QRgb> &palette, int offset, int nColors) {
|
||||
if (!nColors) {
|
||||
logWarn(QString("Cannot save a palette with no colors."));
|
||||
return;
|
||||
logError(QString("Cannot save a palette with no colors."));
|
||||
return false;
|
||||
}
|
||||
if (offset > palette.size() || offset + nColors > palette.size()) {
|
||||
logWarn("Palette offset out of range for color table.");
|
||||
return;
|
||||
logError("Palette offset out of range for color table.");
|
||||
return false;
|
||||
}
|
||||
|
||||
QString text = "JASC-PAL\r\n0100\r\n";
|
||||
@@ -59,11 +59,13 @@ void PaletteUtil::writeJASC(QString filepath, QVector<QRgb> palette, int offset,
|
||||
}
|
||||
|
||||
QFile file(filepath);
|
||||
if (file.open(QIODevice::WriteOnly)) {
|
||||
file.write(text.toUtf8());
|
||||
} else {
|
||||
logWarn(QString("Could not write to file '%1': ").arg(filepath) + file.errorString());
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
logError(QString("Could not write to file '%1': ").arg(filepath) + file.errorString());
|
||||
return false;
|
||||
}
|
||||
|
||||
file.write(text.toUtf8());
|
||||
return true;
|
||||
}
|
||||
|
||||
QList<QRgb> parsePal(QString filepath, bool *error) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "log.h"
|
||||
#include "parseutil.h"
|
||||
#include "loadingscreen.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
#include <QJsonDocument>
|
||||
@@ -15,26 +16,8 @@ const QRegularExpression ParseUtil::re_poryScriptLabel("\\b(script)(\\((global|l
|
||||
const QRegularExpression ParseUtil::re_globalPoryScriptLabel("\\b(script)(\\((global)\\))?\\s*\\b(?<label>[\\w_][\\w\\d_]*)");
|
||||
const QRegularExpression ParseUtil::re_poryRawSection("\\b(raw)\\s*`(?<raw_script>[^`]*)");
|
||||
|
||||
static const QMap<QString, int> globalDefineValues = {
|
||||
{"FALSE", 0},
|
||||
{"TRUE", 1},
|
||||
{"SCHAR_MIN", SCHAR_MIN},
|
||||
{"SCHAR_MAX", SCHAR_MAX},
|
||||
{"CHAR_MIN", CHAR_MIN},
|
||||
{"CHAR_MAX", CHAR_MAX},
|
||||
{"UCHAR_MAX", UCHAR_MAX},
|
||||
{"SHRT_MIN", SHRT_MIN},
|
||||
{"SHRT_MAX", SHRT_MAX},
|
||||
{"USHRT_MAX", USHRT_MAX},
|
||||
{"INT_MIN", INT_MIN},
|
||||
{"INT_MAX", INT_MAX},
|
||||
{"UINT_MAX", UINT_MAX},
|
||||
};
|
||||
|
||||
ParseUtil::ParseUtil() { }
|
||||
|
||||
void ParseUtil::set_root(const QString &dir) {
|
||||
this->root = dir;
|
||||
ParseUtil::ParseUtil() {
|
||||
resetCDefines();
|
||||
}
|
||||
|
||||
QString ParseUtil::pathWithRoot(const QString &path) {
|
||||
@@ -74,6 +57,8 @@ QString ParseUtil::createErrorMessage(const QString &message, const QString &exp
|
||||
}
|
||||
|
||||
QString ParseUtil::readTextFile(const QString &path, QString *error) {
|
||||
// splash screen message
|
||||
porysplash->showMessage(path);
|
||||
QFile file(path);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
if (error) *error = file.errorString();
|
||||
@@ -143,28 +128,48 @@ QList<QStringList> ParseUtil::parseAsm(const QString &filename) {
|
||||
return parsed;
|
||||
}
|
||||
|
||||
// 'identifier' is the name of the #define to evaluate, e.g. 'FOO' in '#define FOO (BAR+1)'
|
||||
// 'expression' is the text of the #define to evaluate, e.g. '(BAR+1)' in '#define FOO (BAR+1)'
|
||||
// 'knownValues' is a pointer to a map of identifier->values for defines that have already been evaluated.
|
||||
// 'unevaluatedExpressions' is a pointer to a map of identifier->expressions for defines that have not been evaluated. If this map contains any
|
||||
// identifiers found in 'expression' then this function will be called recursively to evaluate that define first.
|
||||
// This function will maintain the passed maps appropriately as new #defines are evaluated.
|
||||
int ParseUtil::evaluateDefine(const QString &identifier, const QString &expression, QMap<QString, int> *knownValues, QMap<QString, QString> *unevaluatedExpressions) {
|
||||
if (unevaluatedExpressions->contains(identifier))
|
||||
unevaluatedExpressions->remove(identifier);
|
||||
// Try to evaluate the given #define/enum 'identifier' name using the information the parser has.
|
||||
// If it recognizes the name as an identifier it's aware of (either from having parsed it or having been told about
|
||||
// it using 'loadGlobalCDefines') it will evaluate it if necessary then return the resulting value and set 'ok' to true.
|
||||
// Evaluated identifiers are cached, and will only be re-evaluated if the parser encounters a new expression for that identifier.
|
||||
// If it doesn't recognize it, 'ok' will be set to false and it will return 0.
|
||||
int ParseUtil::evaluateDefine(const QString &identifier, bool *ok) {
|
||||
if (ok) *ok = true;
|
||||
|
||||
if (knownValues->contains(identifier))
|
||||
return knownValues->value(identifier);
|
||||
// Global defines take precedence
|
||||
if (this->globalDefineExpressions.contains(identifier)) {
|
||||
int value = evaluateExpression(this->globalDefineExpressions.take(identifier));
|
||||
this->globalDefineValues.insert(identifier, value);
|
||||
return value;
|
||||
}
|
||||
auto it = this->globalDefineValues.constFind(identifier);
|
||||
if (it != this->globalDefineValues.constEnd()) {
|
||||
return it.value();
|
||||
}
|
||||
|
||||
QList<Token> tokens = tokenizeExpression(expression, knownValues, unevaluatedExpressions);
|
||||
QList<Token> postfixExpression = generatePostfix(tokens);
|
||||
int value = evaluatePostfix(postfixExpression);
|
||||
// Check known expressions before checking known values.
|
||||
// If an identifier is redefined then we'll receive a new expression for it, and we want to make sure we re-evaluate it.
|
||||
if (this->knownDefineExpressions.contains(identifier)) {
|
||||
int value = evaluateExpression(this->knownDefineExpressions.take(identifier));
|
||||
this->knownDefineValues.insert(identifier, value);
|
||||
return value;
|
||||
}
|
||||
it = this->knownDefineValues.constFind(identifier);
|
||||
if (it != this->knownDefineValues.constEnd()) {
|
||||
return it.value();
|
||||
}
|
||||
|
||||
knownValues->insert(identifier, value);
|
||||
return value;
|
||||
if (ok) *ok = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
QList<Token> ParseUtil::tokenizeExpression(QString expression, QMap<QString, int> *knownValues, QMap<QString, QString> *unevaluatedExpressions) {
|
||||
int ParseUtil::evaluateExpression(const QString &expression) {
|
||||
QList<Token> tokens = tokenizeExpression(expression);
|
||||
QList<Token> postfixExpression = generatePostfix(tokens);
|
||||
return evaluatePostfix(postfixExpression);
|
||||
}
|
||||
|
||||
QList<Token> ParseUtil::tokenizeExpression(QString expression) {
|
||||
QList<Token> tokens;
|
||||
|
||||
static const QStringList tokenTypes = {"hex", "decimal", "identifier", "operator", "leftparen", "rightparen"};
|
||||
@@ -181,14 +186,14 @@ QList<Token> ParseUtil::tokenizeExpression(QString expression, QMap<QString, int
|
||||
QString token = match.captured(tokenType);
|
||||
if (!token.isEmpty()) {
|
||||
if (tokenType == "identifier") {
|
||||
if (unevaluatedExpressions->contains(token)) {
|
||||
// This expression depends on a define we know of but haven't evaluated. Evaluate it now
|
||||
evaluateDefine(token, unevaluatedExpressions->value(token), knownValues, unevaluatedExpressions);
|
||||
}
|
||||
if (knownValues->contains(token)) {
|
||||
bool ok;
|
||||
int tokenValue = evaluateDefine(token, &ok);
|
||||
if (ok) {
|
||||
// Any errors encountered when this identifier was evaluated should be recorded for this expression as well.
|
||||
recordErrors(this->errorMap.value(token));
|
||||
QString actualToken = QString("%1").arg(knownValues->value(token));
|
||||
|
||||
// Replace token with evaluated expression
|
||||
QString actualToken = QString::number(tokenValue);
|
||||
expression = expression.replace(0, token.length(), actualToken);
|
||||
token = actualToken;
|
||||
tokenType = "decimal";
|
||||
@@ -481,23 +486,27 @@ ParseUtil::ParsedDefines ParseUtil::readCDefines(const QString &filename, const
|
||||
result.filteredNames.append(name);
|
||||
}
|
||||
}
|
||||
// QHash::insert(const QHash<K, V> &other) was introduced in 5.15.
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||
this->knownDefineExpressions.insert(result.expressions);
|
||||
#else
|
||||
for (auto it = result.expressions.constBegin(); it != result.expressions.constEnd(); it++) {
|
||||
this->knownDefineExpressions.insert(it.key(), it.value());
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
// Read all the define names and their expressions in the specified file, then evaluate the ones matching the search text (and any they depend on).
|
||||
QMap<QString, int> ParseUtil::evaluateCDefines(const QString &filename, const QSet<QString> &filterList, bool useRegex, QString *error) {
|
||||
QHash<QString, int> ParseUtil::evaluateCDefines(const QString &filename, const QSet<QString> &filterList, bool useRegex, QString *error) {
|
||||
ParsedDefines defines = readCDefines(filename, filterList, useRegex, error);
|
||||
|
||||
// Evaluate defines
|
||||
QMap<QString, int> filteredValues;
|
||||
QMap<QString, int> allValues = globalDefineValues;
|
||||
QHash<QString, int> filteredValues;
|
||||
this->errorMap.clear();
|
||||
while (!defines.filteredNames.isEmpty()) {
|
||||
const QString name = defines.filteredNames.takeFirst();
|
||||
const QString expression = defines.expressions.take(name);
|
||||
if (expression == " ") continue;
|
||||
this->curDefine = name;
|
||||
filteredValues.insert(name, evaluateDefine(name, expression, &allValues, &defines.expressions));
|
||||
this->curDefine = defines.filteredNames.takeFirst();
|
||||
filteredValues.insert(this->curDefine, evaluateDefine(this->curDefine));
|
||||
logRecordedErrors(); // Only log errors for defines that Porymap is looking for
|
||||
}
|
||||
|
||||
@@ -505,12 +514,12 @@ QMap<QString, int> ParseUtil::evaluateCDefines(const QString &filename, const QS
|
||||
}
|
||||
|
||||
// Find and evaluate a specific set of defines with known names.
|
||||
QMap<QString, int> ParseUtil::readCDefinesByName(const QString &filename, const QSet<QString> &names, QString *error) {
|
||||
QHash<QString, int> ParseUtil::readCDefinesByName(const QString &filename, const QSet<QString> &names, QString *error) {
|
||||
return evaluateCDefines(filename, names, false, error);
|
||||
}
|
||||
|
||||
// Find and evaluate an unknown list of defines with a known name pattern.
|
||||
QMap<QString, int> ParseUtil::readCDefinesByRegex(const QString &filename, const QSet<QString> ®exList, QString *error) {
|
||||
QHash<QString, int> ParseUtil::readCDefinesByRegex(const QString &filename, const QSet<QString> ®exList, QString *error) {
|
||||
return evaluateCDefines(filename, regexList, true, error);
|
||||
}
|
||||
|
||||
@@ -521,6 +530,50 @@ QStringList ParseUtil::readCDefineNames(const QString &filename, const QSet<QStr
|
||||
return readCDefines(filename, regexList, true, error).filteredNames;
|
||||
}
|
||||
|
||||
// Find any defines in the specified file and save their expressions.
|
||||
// If any of these defines are encountered later by other define parsing functions then they'll be recognized and evaluated.
|
||||
void ParseUtil::loadGlobalCDefinesFromFile(const QString &filename, QString *error) {
|
||||
loadGlobalCDefines(readCDefines(filename, {}, false, error).expressions);
|
||||
}
|
||||
|
||||
void ParseUtil::loadGlobalCDefines(const QHash<QString,QString> &defines) {
|
||||
// QHash::insert(const QHash<K, V> &other) was introduced in 5.15.
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
|
||||
this->globalDefineExpressions.insert(defines);
|
||||
#else
|
||||
for (auto it = defines.constBegin(); it != defines.constEnd(); it++) {
|
||||
this->globalDefineExpressions.insert(it.key(), it.value());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ParseUtil::loadGlobalCDefines(const QMap<QString,QString> &defines) {
|
||||
for (auto it = defines.constBegin(); it != defines.constEnd(); it++)
|
||||
this->globalDefineExpressions.insert(it.key(), it.value());
|
||||
}
|
||||
|
||||
void ParseUtil::resetCDefines() {
|
||||
static const QHash<QString, int> defaultDefineValues = {
|
||||
{"FALSE", 0},
|
||||
{"TRUE", 1},
|
||||
{"SCHAR_MIN", SCHAR_MIN},
|
||||
{"SCHAR_MAX", SCHAR_MAX},
|
||||
{"CHAR_MIN", CHAR_MIN},
|
||||
{"CHAR_MAX", CHAR_MAX},
|
||||
{"UCHAR_MAX", UCHAR_MAX},
|
||||
{"SHRT_MIN", SHRT_MIN},
|
||||
{"SHRT_MAX", SHRT_MAX},
|
||||
{"USHRT_MAX", USHRT_MAX},
|
||||
{"INT_MIN", INT_MIN},
|
||||
{"INT_MAX", INT_MAX},
|
||||
{"UINT_MAX", UINT_MAX},
|
||||
};
|
||||
this->globalDefineValues = defaultDefineValues;
|
||||
this->globalDefineExpressions.clear();
|
||||
this->knownDefineValues.clear();
|
||||
this->knownDefineExpressions.clear();
|
||||
}
|
||||
|
||||
QStringList ParseUtil::readCArray(const QString &filename, const QString &label) {
|
||||
QStringList list;
|
||||
|
||||
@@ -610,12 +663,12 @@ bool ParseUtil::gameStringToBool(const QString &gameString, bool * ok) {
|
||||
return gameStringToInt(gameString, ok) != 0;
|
||||
}
|
||||
|
||||
tsl::ordered_map<QString, QHash<QString, QString>> ParseUtil::readCStructs(const QString &filename, const QString &label, const QHash<int, QString> &memberMap) {
|
||||
OrderedMap<QString, QHash<QString, QString>> ParseUtil::readCStructs(const QString &filename, const QString &label, const QHash<int, QString> &memberMap) {
|
||||
QString filePath = pathWithRoot(filename);
|
||||
auto cParser = fex::Parser();
|
||||
auto tokens = fex::Lexer().LexFile(filePath);
|
||||
auto topLevelObjects = cParser.ParseTopLevelObjects(tokens);
|
||||
tsl::ordered_map<QString, QHash<QString, QString>> structs;
|
||||
OrderedMap<QString, QHash<QString, QString>> structs;
|
||||
for (auto it = topLevelObjects.begin(); it != topLevelObjects.end(); it++) {
|
||||
QString structLabel = QString::fromStdString(it->first);
|
||||
if (structLabel.isEmpty()) continue;
|
||||
|
||||
@@ -260,7 +260,7 @@ void ResizeTilemap::undo() {
|
||||
|
||||
///
|
||||
|
||||
ClearEntries::ClearEntries(RegionMap *map, QMap<QString, MapSectionEntry> entries, QUndoCommand *parent)
|
||||
ClearEntries::ClearEntries(RegionMap *map, QHash<QString, MapSectionEntry> entries, QUndoCommand *parent)
|
||||
: QUndoCommand(parent) {
|
||||
setText("Clear Entries");
|
||||
|
||||
|
||||
@@ -402,13 +402,13 @@ QHash<int, QString> Tileset::getHeaderMemberMap(bool usingAsm)
|
||||
return map;
|
||||
}
|
||||
|
||||
void Tileset::loadMetatiles() {
|
||||
bool Tileset::loadMetatiles() {
|
||||
clearMetatiles();
|
||||
|
||||
QFile metatiles_file(this->metatiles_path);
|
||||
if (!metatiles_file.open(QIODevice::ReadOnly)) {
|
||||
logError(QString("Could not open '%1' for reading.").arg(this->metatiles_path));
|
||||
return;
|
||||
logError(QString("Could not open '%1' for reading: %2").arg(this->metatiles_path).arg(metatiles_file.errorString()));
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray data = metatiles_file.readAll();
|
||||
@@ -425,13 +425,14 @@ void Tileset::loadMetatiles() {
|
||||
}
|
||||
m_metatiles.append(metatile);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Tileset::saveMetatiles() {
|
||||
bool Tileset::saveMetatiles() {
|
||||
QFile metatiles_file(this->metatiles_path);
|
||||
if (!metatiles_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
logError(QString("Could not open '%1' for writing.").arg(this->metatiles_path));
|
||||
return;
|
||||
logError(QString("Could not open '%1' for writing: %2").arg(this->metatiles_path).arg(metatiles_file.errorString()));
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray data;
|
||||
@@ -444,13 +445,14 @@ void Tileset::saveMetatiles() {
|
||||
}
|
||||
}
|
||||
metatiles_file.write(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Tileset::loadMetatileAttributes() {
|
||||
bool Tileset::loadMetatileAttributes() {
|
||||
QFile attrs_file(this->metatile_attrs_path);
|
||||
if (!attrs_file.open(QIODevice::ReadOnly)) {
|
||||
logError(QString("Could not open '%1' for reading.").arg(this->metatile_attrs_path));
|
||||
return;
|
||||
logError(QString("Could not open '%1' for reading: %2").arg(this->metatile_attrs_path).arg(attrs_file.errorString()));
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray data = attrs_file.readAll();
|
||||
@@ -467,13 +469,14 @@ void Tileset::loadMetatileAttributes() {
|
||||
attributes |= static_cast<unsigned char>(data.at(i * attrSize + j)) << (8 * j);
|
||||
m_metatiles.at(i)->setAttributes(attributes);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Tileset::saveMetatileAttributes() {
|
||||
bool Tileset::saveMetatileAttributes() {
|
||||
QFile attrs_file(this->metatile_attrs_path);
|
||||
if (!attrs_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
logError(QString("Could not open '%1' for writing.").arg(this->metatile_attrs_path));
|
||||
return;
|
||||
logError(QString("Could not open '%1' for writing: %2").arg(this->metatile_attrs_path).arg(attrs_file.errorString()));
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray data;
|
||||
@@ -483,9 +486,10 @@ void Tileset::saveMetatileAttributes() {
|
||||
data.append(static_cast<char>(attributes >> (8 * i)));
|
||||
}
|
||||
attrs_file.write(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Tileset::loadTilesImage(QImage *importedImage) {
|
||||
bool Tileset::loadTilesImage(QImage *importedImage) {
|
||||
QImage image;
|
||||
if (importedImage) {
|
||||
image = *importedImage;
|
||||
@@ -520,23 +524,25 @@ void Tileset::loadTilesImage(QImage *importedImage) {
|
||||
}
|
||||
this->tilesImage = image;
|
||||
this->tiles = tiles;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Tileset::saveTilesImage() {
|
||||
bool Tileset::saveTilesImage() {
|
||||
// Only write the tiles image if it was changed.
|
||||
// Porymap will only ever change an existing tiles image by importing a new one.
|
||||
if (!m_hasUnsavedTilesImage)
|
||||
return;
|
||||
return true;
|
||||
|
||||
if (!this->tilesImage.save(this->tilesImagePath, "PNG")) {
|
||||
logError(QString("Failed to save tiles image '%1'").arg(this->tilesImagePath));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_hasUnsavedTilesImage = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Tileset::loadPalettes() {
|
||||
bool Tileset::loadPalettes() {
|
||||
this->palettes.clear();
|
||||
this->palettePreviews.clear();
|
||||
|
||||
@@ -559,26 +565,34 @@ void Tileset::loadPalettes() {
|
||||
this->palettes.append(palette);
|
||||
this->palettePreviews.append(palette);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Tileset::savePalettes() {
|
||||
bool Tileset::savePalettes() {
|
||||
bool success = true;
|
||||
int numPalettes = qMin(this->palettePaths.length(), this->palettes.length());
|
||||
for (int i = 0; i < numPalettes; i++) {
|
||||
PaletteUtil::writeJASC(this->palettePaths.at(i), this->palettes.at(i).toVector(), 0, 16);
|
||||
if (!PaletteUtil::writeJASC(this->palettePaths.at(i), this->palettes.at(i).toVector(), 0, 16))
|
||||
success = false;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void Tileset::load() {
|
||||
loadMetatiles();
|
||||
loadMetatileAttributes();
|
||||
loadTilesImage();
|
||||
loadPalettes();
|
||||
bool Tileset::load() {
|
||||
bool success = true;
|
||||
if (!loadMetatiles()) success = false;
|
||||
if (!loadMetatileAttributes()) success = false;
|
||||
if (!loadTilesImage()) success = false;
|
||||
if (!loadPalettes()) success = false;
|
||||
return success;
|
||||
}
|
||||
|
||||
// Because metatile labels are global (and handled by the project) we don't save them here.
|
||||
void Tileset::save() {
|
||||
saveMetatiles();
|
||||
saveMetatileAttributes();
|
||||
saveTilesImage();
|
||||
savePalettes();
|
||||
bool Tileset::save() {
|
||||
bool success = true;
|
||||
if (!saveMetatiles()) success = false;
|
||||
if (!saveMetatileAttributes()) success = false;
|
||||
if (!saveTilesImage()) success = false;
|
||||
if (!savePalettes()) success = false;
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -42,3 +42,14 @@ QString Util::toDefineCase(QString input) {
|
||||
QString Util::toHexString(uint32_t value, int minLength) {
|
||||
return "0x" + QString("%1").arg(value, minLength, 16, QChar('0')).toUpper();
|
||||
}
|
||||
|
||||
QString Util::toHtmlParagraph(const QString &text) {
|
||||
return QString("<html><head/><body><p>%1</p></body></html>").arg(text);
|
||||
}
|
||||
|
||||
Qt::Orientations Util::getOrientation(bool xflip, bool yflip) {
|
||||
Qt::Orientations flags;
|
||||
if (xflip) flags |= Qt::Orientation::Horizontal;
|
||||
if (yflip) flags |= Qt::Orientation::Vertical;
|
||||
return flags;
|
||||
}
|
||||
|
||||
280
src/editor.cpp
280
src/editor.cpp
@@ -1,5 +1,5 @@
|
||||
#include "editor.h"
|
||||
#include "draggablepixmapitem.h"
|
||||
#include "eventpixmapitem.h"
|
||||
#include "imageproviders.h"
|
||||
#include "log.h"
|
||||
#include "connectionslistitem.h"
|
||||
@@ -30,7 +30,6 @@ Editor::Editor(Ui::MainWindow* ui)
|
||||
{
|
||||
this->ui = ui;
|
||||
this->settings = new Settings();
|
||||
this->playerViewRect = new MovableRect(&this->settings->playerViewRectEnabled, 30 * 8, 20 * 8, qRgb(255, 255, 255));
|
||||
this->cursorMapTileRect = new CursorTileRect(&this->settings->cursorTileRectEnabled, qRgb(255, 255, 255));
|
||||
this->map_ruler = new MapRuler(4);
|
||||
connect(this->map_ruler, &MapRuler::statusChanged, this, &Editor::mapRulerStatusChanged);
|
||||
@@ -54,6 +53,19 @@ Editor::Editor(Ui::MainWindow* ui)
|
||||
connect(ui->actionOpen_Project_in_Text_Editor, &QAction::triggered, this, &Editor::openProjectInTextEditor);
|
||||
connect(ui->checkBox_ToggleGrid, &QCheckBox::toggled, this, &Editor::toggleGrid);
|
||||
connect(ui->mapCustomAttributesFrame->table(), &CustomAttributesTable::edited, this, &Editor::updateCustomMapAttributes);
|
||||
|
||||
connect(ui->comboBox_DiveMap, &NoScrollComboBox::editingFinished, [this] {
|
||||
onDivingMapEditingFinished(this->ui->comboBox_DiveMap, "dive");
|
||||
});
|
||||
connect(ui->comboBox_EmergeMap, &NoScrollComboBox::editingFinished, [this] {
|
||||
onDivingMapEditingFinished(this->ui->comboBox_EmergeMap, "emerge");
|
||||
});
|
||||
connect(ui->comboBox_DiveMap, &NoScrollComboBox::currentTextChanged, [this] {
|
||||
updateDivingMapButton(this->ui->button_OpenDiveMap, this->ui->comboBox_DiveMap->currentText());
|
||||
});
|
||||
connect(ui->comboBox_EmergeMap, &NoScrollComboBox::currentTextChanged, [this] {
|
||||
updateDivingMapButton(this->ui->button_OpenEmergeMap, this->ui->comboBox_EmergeMap->currentText());
|
||||
});
|
||||
}
|
||||
|
||||
Editor::~Editor()
|
||||
@@ -68,30 +80,33 @@ Editor::~Editor()
|
||||
closeProject();
|
||||
}
|
||||
|
||||
void Editor::saveCurrent() {
|
||||
save(true);
|
||||
bool Editor::saveCurrent() {
|
||||
return save(true);
|
||||
}
|
||||
|
||||
void Editor::saveAll() {
|
||||
save(false);
|
||||
bool Editor::saveAll() {
|
||||
return save(false);
|
||||
}
|
||||
|
||||
void Editor::save(bool currentOnly) {
|
||||
bool Editor::save(bool currentOnly) {
|
||||
if (!this->project)
|
||||
return;
|
||||
return true;
|
||||
|
||||
saveEncounterTabData();
|
||||
|
||||
bool success = true;
|
||||
if (currentOnly) {
|
||||
if (this->map) {
|
||||
this->project->saveMap(this->map);
|
||||
success = this->project->saveMap(this->map);
|
||||
} else if (this->layout) {
|
||||
this->project->saveLayout(this->layout);
|
||||
success = this->project->saveLayout(this->layout);
|
||||
}
|
||||
this->project->saveGlobalData();
|
||||
if (!this->project->saveGlobalData())
|
||||
success = false;
|
||||
} else {
|
||||
this->project->saveAll();
|
||||
success = this->project->saveAll();
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void Editor::setProject(Project * project) {
|
||||
@@ -155,6 +170,7 @@ void Editor::setEditMode(EditMode editMode) {
|
||||
}
|
||||
this->cursorMapTileRect->setSingleTileMode();
|
||||
this->cursorMapTileRect->setActive(editingLayout);
|
||||
this->playerViewRect->setActive(editingLayout);
|
||||
this->editGroup.setActiveStack(editStack);
|
||||
setMapEditingButtonsEnabled(editingLayout);
|
||||
|
||||
@@ -296,8 +312,8 @@ void Editor::addNewWildMonGroup(QWidget *window) {
|
||||
form.addRow(new QLabel(monField.name), fieldCheckbox);
|
||||
}
|
||||
// Reading from ui here so not saving to disk before user.
|
||||
connect(copyCheckbox, &QCheckBox::stateChanged, [=](int state){
|
||||
if (state == Qt::Checked) {
|
||||
connect(copyCheckbox, &QCheckBox::toggled, [=](bool checked){
|
||||
if (checked) {
|
||||
int fieldIndex = 0;
|
||||
MonTabWidget *monWidget = static_cast<MonTabWidget *>(stack->widget(stack->currentIndex()));
|
||||
for (EncounterField monField : project->wildMonFields) {
|
||||
@@ -305,7 +321,7 @@ void Editor::addNewWildMonGroup(QWidget *window) {
|
||||
fieldCheckboxes[fieldIndex]->setEnabled(false);
|
||||
fieldIndex++;
|
||||
}
|
||||
} else if (state == Qt::Unchecked) {
|
||||
} else {
|
||||
int fieldIndex = 0;
|
||||
for (EncounterField monField : project->wildMonFields) {
|
||||
fieldCheckboxes[fieldIndex]->setEnabled(true);
|
||||
@@ -596,7 +612,7 @@ void Editor::configureEncounterJSON(QWidget *window) {
|
||||
if (newNameDialog.exec() == QDialog::Accepted) {
|
||||
QString newFieldName = newNameEdit->text();
|
||||
QVector<int> newFieldRates(1, 100);
|
||||
tempFields.append({newFieldName, newFieldRates, {}});
|
||||
tempFields.append({newFieldName, newFieldRates, {}, {}});
|
||||
fieldChoices->addItem(newFieldName);
|
||||
fieldChoices->setCurrentIndex(fieldChoices->count() - 1);
|
||||
}
|
||||
@@ -675,7 +691,7 @@ void Editor::saveEncounterTabData() {
|
||||
|
||||
if (!stack->count()) return;
|
||||
|
||||
tsl::ordered_map<QString, WildPokemonHeader> &encounterMap = project->wildMonData[map->constantName()];
|
||||
OrderedMap<QString, WildPokemonHeader> &encounterMap = project->wildMonData[map->constantName()];
|
||||
|
||||
for (int groupIndex = 0; groupIndex < stack->count(); groupIndex++) {
|
||||
MonTabWidget *tabWidget = static_cast<MonTabWidget *>(stack->widget(groupIndex));
|
||||
@@ -805,23 +821,41 @@ void Editor::displayConnection(MapConnection *connection) {
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::addConnection(MapConnection *connection) {
|
||||
if (!connection)
|
||||
void Editor::addNewConnection(const QString &mapName, const QString &direction) {
|
||||
if (!this->map)
|
||||
return;
|
||||
|
||||
MapConnection *connection = new MapConnection(mapName, direction);
|
||||
|
||||
// Mark this connection to be selected once its display elements have been created.
|
||||
// It's possible this is a Dive/Emerge connection, but that's ok (no selection will occur).
|
||||
connection_to_select = connection;
|
||||
this->connection_to_select = connection;
|
||||
|
||||
this->map->commit(new MapConnectionAdd(this->map, connection));
|
||||
}
|
||||
|
||||
void Editor::replaceConnection(const QString &mapName, const QString &direction) {
|
||||
if (!this->map)
|
||||
return;
|
||||
|
||||
MapConnection *connection = this->map->getConnection(direction);
|
||||
if (!connection || connection->targetMapName() == mapName)
|
||||
return;
|
||||
|
||||
this->map->commit(new MapConnectionChangeMap(connection, mapName));
|
||||
}
|
||||
|
||||
void Editor::removeConnection(MapConnection *connection) {
|
||||
if (!connection)
|
||||
if (!this->map || !connection)
|
||||
return;
|
||||
this->map->commit(new MapConnectionRemove(this->map, connection));
|
||||
}
|
||||
|
||||
void Editor::removeSelectedConnection() {
|
||||
if (selected_connection_item)
|
||||
removeConnection(selected_connection_item->connection);
|
||||
}
|
||||
|
||||
void Editor::removeConnectionPixmap(MapConnection *connection) {
|
||||
if (!connection)
|
||||
return;
|
||||
@@ -914,21 +948,18 @@ void Editor::removeDivingMapPixmap(MapConnection *connection) {
|
||||
updateDivingMapsVisibility();
|
||||
}
|
||||
|
||||
void Editor::updateDiveMap(QString mapName) {
|
||||
setDivingMapName(mapName, "dive");
|
||||
}
|
||||
bool Editor::setDivingMapName(const QString &mapName, const QString &direction) {
|
||||
if (!mapName.isEmpty() && !this->project->mapNames.contains(mapName))
|
||||
return false;
|
||||
if (!MapConnection::isDiving(direction))
|
||||
return false;
|
||||
|
||||
void Editor::updateEmergeMap(QString mapName) {
|
||||
setDivingMapName(mapName, "emerge");
|
||||
}
|
||||
|
||||
void Editor::setDivingMapName(QString mapName, QString direction) {
|
||||
auto pixmapItem = diving_map_items.value(direction);
|
||||
MapConnection *connection = pixmapItem ? pixmapItem->connection() : nullptr;
|
||||
|
||||
if (connection) {
|
||||
if (mapName == connection->targetMapName())
|
||||
return; // No change
|
||||
return true; // No change
|
||||
|
||||
// Update existing connection
|
||||
if (mapName.isEmpty()) {
|
||||
@@ -938,8 +969,25 @@ void Editor::setDivingMapName(QString mapName, QString direction) {
|
||||
}
|
||||
} else if (!mapName.isEmpty()) {
|
||||
// Create new connection
|
||||
addConnection(new MapConnection(mapName, direction));
|
||||
addNewConnection(mapName, direction);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QString Editor::getDivingMapName(const QString &direction) const {
|
||||
auto pixmapItem = diving_map_items.value(direction);
|
||||
return (pixmapItem && pixmapItem->connection()) ? pixmapItem->connection()->targetMapName() : QString();
|
||||
}
|
||||
|
||||
void Editor::onDivingMapEditingFinished(NoScrollComboBox *combo, const QString &direction) {
|
||||
if (!setDivingMapName(combo->currentText(), direction)) {
|
||||
// If user input was invalid, restore the combo to the previously-valid text.
|
||||
combo->setCurrentText(getDivingMapName(direction));
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::updateDivingMapButton(QToolButton* button, const QString &mapName) {
|
||||
if (this->project) button->setDisabled(!this->project->mapNames.contains(mapName));
|
||||
}
|
||||
|
||||
void Editor::updateDivingMapsVisibility() {
|
||||
@@ -1061,6 +1109,14 @@ void Editor::scaleMapView(int s) {
|
||||
ui->graphicsView_Connections->setTransform(transform);
|
||||
}
|
||||
|
||||
void Editor::setPlayerViewRect(const QRectF &rect) {
|
||||
delete this->playerViewRect;
|
||||
this->playerViewRect = new MovableRect(&this->settings->playerViewRectEnabled, rect, qRgb(255, 255, 255));
|
||||
this->playerViewRect->setActive(getEditingLayout());
|
||||
if (ui->graphicsView_Map->scene())
|
||||
ui->graphicsView_Map->scene()->update();
|
||||
}
|
||||
|
||||
void Editor::updateCursorRectPos(int x, int y) {
|
||||
if (this->playerViewRect)
|
||||
this->playerViewRect->updateLocation(x, y);
|
||||
@@ -1289,7 +1345,6 @@ void Editor::setStraightPathCursorMode(QGraphicsSceneMouseEvent *event) {
|
||||
}
|
||||
|
||||
void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *item) {
|
||||
// TODO: add event tab event painting tool buttons stuff here
|
||||
if (!item->getEditsEnabled()) {
|
||||
return;
|
||||
}
|
||||
@@ -1363,8 +1418,11 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *i
|
||||
if (event && event->getPixmapItem())
|
||||
event->getPixmapItem()->moveTo(pos);
|
||||
}
|
||||
} else if (eventEditAction == EditAction::Select) {
|
||||
// do nothing here, at least for now
|
||||
} else if (eventEditAction == EditAction::Select && event->type() == QEvent::GraphicsSceneMousePress) {
|
||||
if (!(event->modifiers() & Qt::ControlModifier) && this->selectedEvents.length() > 1) {
|
||||
// User is clearing group selection by clicking on the background
|
||||
selectMapEvent(this->selectedEvents.first());
|
||||
}
|
||||
} else if (eventEditAction == EditAction::Shift) {
|
||||
static QPoint selection_origin;
|
||||
|
||||
@@ -1482,7 +1540,7 @@ bool Editor::displayLayout() {
|
||||
scene->installEventFilter(filter);
|
||||
connect(filter, &MapSceneEventFilter::wheelZoom, this, &Editor::onWheelZoom);
|
||||
scene->installEventFilter(this->map_ruler);
|
||||
this->map_ruler->setZValue(1000);
|
||||
this->map_ruler->setZValue(ZValue::Ruler);
|
||||
scene->addItem(this->map_ruler);
|
||||
}
|
||||
|
||||
@@ -1560,14 +1618,8 @@ void Editor::displayMapMetatiles() {
|
||||
map_item->draw(true);
|
||||
scene->addItem(map_item);
|
||||
|
||||
int tw = 16;
|
||||
int th = 16;
|
||||
scene->setSceneRect(
|
||||
-BORDER_DISTANCE * tw,
|
||||
-BORDER_DISTANCE * th,
|
||||
map_item->pixmap().width() + BORDER_DISTANCE * 2 * tw,
|
||||
map_item->pixmap().height() + BORDER_DISTANCE * 2 * th
|
||||
);
|
||||
// Scene rect is the map plus a margin that gives enough space to scroll and see the edge of the player view rectangle.
|
||||
scene->setSceneRect(this->layout->getVisibleRect() + QMargins(3,3,3,3));
|
||||
}
|
||||
|
||||
void Editor::clearMapMovementPermissions() {
|
||||
@@ -1673,9 +1725,6 @@ void Editor::clearMapEvents() {
|
||||
if (events_group->scene()) {
|
||||
events_group->scene()->removeItem(events_group);
|
||||
}
|
||||
// events_group does not own its children, the childrens' parent
|
||||
// is set to the group's parent (and our group has no parent).
|
||||
qDeleteAll(events_group->childItems());
|
||||
delete events_group;
|
||||
events_group = nullptr;
|
||||
}
|
||||
@@ -1695,9 +1744,16 @@ void Editor::displayMapEvents() {
|
||||
events_group->setHandlesChildEvents(false);
|
||||
}
|
||||
|
||||
DraggablePixmapItem *Editor::addEventPixmapItem(Event *event) {
|
||||
EventPixmapItem *Editor::addEventPixmapItem(Event *event) {
|
||||
this->project->loadEventPixmap(event);
|
||||
auto item = new DraggablePixmapItem(event, this);
|
||||
auto item = new EventPixmapItem(event);
|
||||
connect(item, &EventPixmapItem::doubleClicked, this, &Editor::openEventMap);
|
||||
connect(item, &EventPixmapItem::dragged, this, &Editor::onEventDragged);
|
||||
connect(item, &EventPixmapItem::released, this, &Editor::onEventReleased);
|
||||
connect(item, &EventPixmapItem::selected, this, &Editor::selectMapEvent);
|
||||
connect(item, &EventPixmapItem::posChanged, [this, event] { updateWarpEventWarning(event); });
|
||||
connect(item, &EventPixmapItem::yChanged, [this, item] { updateEventPixmapItemZValue(item); });
|
||||
updateWarpEventWarning(event);
|
||||
redrawEventPixmapItem(item);
|
||||
this->events_group->addToGroup(item);
|
||||
return item;
|
||||
@@ -1722,8 +1778,6 @@ void Editor::clearMapConnections() {
|
||||
}
|
||||
connection_items.clear();
|
||||
|
||||
const QSignalBlocker blocker1(ui->comboBox_DiveMap);
|
||||
const QSignalBlocker blocker2(ui->comboBox_EmergeMap);
|
||||
ui->comboBox_DiveMap->setCurrentText("");
|
||||
ui->comboBox_EmergeMap->setCurrentText("");
|
||||
|
||||
@@ -1760,24 +1814,20 @@ void Editor::clearConnectionMask() {
|
||||
}
|
||||
}
|
||||
|
||||
// Hides connected map tiles that cannot be seen from the current map (beyond BORDER_DISTANCE).
|
||||
// Hides connected map tiles that cannot be seen from the current map
|
||||
void Editor::maskNonVisibleConnectionTiles() {
|
||||
clearConnectionMask();
|
||||
|
||||
QPainterPath mask;
|
||||
mask.addRect(scene->itemsBoundingRect().toRect());
|
||||
mask.addRect(
|
||||
-BORDER_DISTANCE * 16,
|
||||
-BORDER_DISTANCE * 16,
|
||||
(layout->getWidth() + BORDER_DISTANCE * 2) * 16,
|
||||
(layout->getHeight() + BORDER_DISTANCE * 2) * 16
|
||||
);
|
||||
mask.addRect(layout->getVisibleRect());
|
||||
|
||||
// Mask the tiles with the current theme's background color.
|
||||
QPen pen(ui->graphicsView_Map->palette().color(QPalette::Active, QPalette::Base));
|
||||
QBrush brush(ui->graphicsView_Map->palette().color(QPalette::Active, QPalette::Base));
|
||||
|
||||
connection_mask = scene->addPath(mask, pen, brush);
|
||||
connection_mask->setZValue(ZValue::MapConnectionMask);
|
||||
}
|
||||
|
||||
void Editor::clearMapBorder() {
|
||||
@@ -1793,17 +1843,14 @@ void Editor::clearMapBorder() {
|
||||
void Editor::displayMapBorder() {
|
||||
clearMapBorder();
|
||||
|
||||
int borderWidth = this->layout->getBorderWidth();
|
||||
int borderHeight = this->layout->getBorderHeight();
|
||||
int borderHorzDist = this->layout->getBorderDrawWidth();
|
||||
int borderVertDist = this->layout->getBorderDrawHeight();
|
||||
QPixmap pixmap = this->layout->renderBorder();
|
||||
for (int y = -borderVertDist; y < this->layout->getHeight() + borderVertDist; y += borderHeight)
|
||||
for (int x = -borderHorzDist; x < this->layout->getWidth() + borderHorzDist; x += borderWidth) {
|
||||
const QMargins borderMargins = layout->getBorderMargins();
|
||||
for (int y = -borderMargins.top(); y < this->layout->getHeight() + borderMargins.bottom(); y += this->layout->getBorderHeight())
|
||||
for (int x = -borderMargins.left(); x < this->layout->getWidth() + borderMargins.right(); x += this->layout->getBorderWidth()) {
|
||||
QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap);
|
||||
item->setX(x * 16);
|
||||
item->setY(y * 16);
|
||||
item->setZValue(-3);
|
||||
item->setZValue(ZValue::MapBorder);
|
||||
scene->addItem(item);
|
||||
borderItems.append(item);
|
||||
}
|
||||
@@ -1973,32 +2020,59 @@ qreal Editor::getEventOpacity(const Event *event) const {
|
||||
return event->getUsesDefaultPixmap() ? 0.7 : 1.0;
|
||||
}
|
||||
|
||||
void Editor::redrawEventPixmapItem(DraggablePixmapItem *item) {
|
||||
if (item && item->event && !item->event->getPixmap().isNull()) {
|
||||
item->setOpacity(getEventOpacity(item->event));
|
||||
project->loadEventPixmap(item->event, true);
|
||||
item->setPixmap(item->event->getPixmap());
|
||||
item->setShapeMode(porymapConfig.eventSelectionShapeMode);
|
||||
void Editor::redrawEventPixmapItem(EventPixmapItem *item) {
|
||||
if (!item) return;
|
||||
Event *event = item->getEvent();
|
||||
if (!event) return;
|
||||
|
||||
if (this->editMode == EditMode::Events) {
|
||||
if (this->selectedEvents.contains(item->event)) {
|
||||
// Draw the selection rectangle
|
||||
QImage image = item->pixmap().toImage();
|
||||
QPainter painter(&image);
|
||||
painter.setPen(QColor(255, 0, 255));
|
||||
painter.drawRect(0, 0, image.width() - 1, image.height() - 1);
|
||||
painter.end();
|
||||
item->setPixmap(QPixmap::fromImage(image));
|
||||
}
|
||||
item->setAcceptedMouseButtons(Qt::AllButtons);
|
||||
} else {
|
||||
// Can't interact with event pixmaps outside of event editing mode.
|
||||
// We could do setEnabled(false), but rather than ignoring the mouse events this
|
||||
// would reject them, which would prevent painting on the map behind the events.
|
||||
item->setAcceptedMouseButtons(Qt::NoButton);
|
||||
}
|
||||
item->updatePosition();
|
||||
if (this->editMode == EditMode::Events) {
|
||||
item->setAcceptedMouseButtons(Qt::AllButtons);
|
||||
item->setSelected(this->selectedEvents.contains(event));
|
||||
} else {
|
||||
// Can't interact with event pixmaps outside of event editing mode.
|
||||
// We could do setEnabled(false), but rather than ignoring the mouse events this
|
||||
// would reject them, which would prevent painting on the map behind the events.
|
||||
item->setAcceptedMouseButtons(Qt::NoButton);
|
||||
item->setSelected(false);
|
||||
}
|
||||
updateEventPixmapItemZValue(item);
|
||||
item->setOpacity(getEventOpacity(event));
|
||||
item->setShapeMode(porymapConfig.eventSelectionShapeMode);
|
||||
item->render(project);
|
||||
}
|
||||
|
||||
void Editor::updateEventPixmapItemZValue(EventPixmapItem *item) {
|
||||
if (!item) return;
|
||||
Event *event = item->getEvent();
|
||||
if (!event) return;
|
||||
|
||||
if (item->isSelected()) {
|
||||
item->setZValue(ZValue::EventMaximum);
|
||||
} else {
|
||||
item->setZValue(event->getY() + ((ZValue::EventMaximum - ZValue::EventMinimum) / 2));
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::onEventDragged(Event *event, const QPoint &oldPosition, const QPoint &newPosition) {
|
||||
if (!this->map || !this->map_item)
|
||||
return;
|
||||
|
||||
this->map_item->hoveredMapMetatileChanged(newPosition);
|
||||
|
||||
// Drag all the other selected events (if any) with it
|
||||
QList<Event*> draggedEvents;
|
||||
if (this->selectedEvents.contains(event)) {
|
||||
draggedEvents = this->selectedEvents;
|
||||
} else {
|
||||
draggedEvents.append(event);
|
||||
}
|
||||
|
||||
QPoint moveDistance = newPosition - oldPosition;
|
||||
this->map->commit(new EventMove(draggedEvents, moveDistance.x(), moveDistance.y(), this->eventMoveActionId));
|
||||
}
|
||||
|
||||
void Editor::onEventReleased(Event *, const QPoint &) {
|
||||
this->eventMoveActionId++;
|
||||
}
|
||||
|
||||
// Warp events display a warning if they're not positioned on a metatile with a warp behavior.
|
||||
@@ -2283,32 +2357,6 @@ bool Editor::startDetachedProcess(const QString &command, const QString &working
|
||||
return process.startDetached(pid);
|
||||
}
|
||||
|
||||
// It doesn't seem to be possible to prevent the mousePress event
|
||||
// from triggering both event's DraggablePixmapItem and the background mousePress.
|
||||
// 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::eventsView_onMousePress(QMouseEvent *event) {
|
||||
// make sure we are in event editing mode
|
||||
if (map_item && this->editMode != EditMode::Events) {
|
||||
return;
|
||||
}
|
||||
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);
|
||||
this->ui->toolButton_Select->setChecked(true);
|
||||
}
|
||||
|
||||
bool multiSelect = event->modifiers() & Qt::ControlModifier;
|
||||
if (!selectingEvent && !multiSelect && this->selectedEvents.length() > 1) {
|
||||
// User is clearing group selection by clicking on the background
|
||||
this->selectMapEvent(this->selectedEvents.first());
|
||||
}
|
||||
selectingEvent = false;
|
||||
}
|
||||
|
||||
void Editor::setCollisionTabSpinBoxes(uint16_t collision, uint16_t elevation) {
|
||||
const QSignalBlocker blocker1(ui->spinBox_SelectedCollision);
|
||||
const QSignalBlocker blocker2(ui->spinBox_SelectedElevation);
|
||||
@@ -2338,8 +2386,8 @@ void Editor::setCollisionGraphics() {
|
||||
|
||||
// Users are not required to provide an image that gives an icon for every elevation/collision combination.
|
||||
// Instead they tell us how many are provided in their image by specifying the number of columns and rows.
|
||||
const int imgColumns = projectConfig.collisionSheetWidth;
|
||||
const int imgRows = projectConfig.collisionSheetHeight;
|
||||
const int imgColumns = projectConfig.collisionSheetSize.width();
|
||||
const int imgRows = projectConfig.collisionSheetSize.height();
|
||||
|
||||
// Create a pixmap for the selector on the Collision tab. If a project was previously opened we'll also need to refresh the selector.
|
||||
this->collisionSheetPixmap = QPixmap::fromImage(imgSheet).scaled(MovementPermissionsSelector::CellWidth * imgColumns,
|
||||
|
||||
@@ -311,33 +311,26 @@ const Json & JsonArray::operator[] (int i) const {
|
||||
else return m_value[i];
|
||||
}
|
||||
|
||||
const Json Json::fromQJsonValue(QJsonValue value) {
|
||||
Json Json::fromQJsonValue(const QJsonValue &value) {
|
||||
switch (value.type())
|
||||
{
|
||||
case QJsonValue::String: return value.toString();
|
||||
case QJsonValue::Double: return value.toInt();
|
||||
case QJsonValue::Bool: return value.toBool();
|
||||
case QJsonValue::Array:
|
||||
{
|
||||
QJsonArray qArr = value.toArray();
|
||||
Json::array arr;
|
||||
for (const auto &i: qArr)
|
||||
arr.push_back(Json::fromQJsonValue(i));
|
||||
return arr;
|
||||
case QJsonValue::Array: {
|
||||
Json::array array;
|
||||
Json::append(&array, value.toArray());
|
||||
return array;
|
||||
}
|
||||
case QJsonValue::Object:
|
||||
{
|
||||
QJsonObject qObj = value.toObject();
|
||||
Json::object obj;
|
||||
for (auto it = qObj.constBegin(); it != qObj.constEnd(); it++)
|
||||
obj[it.key()] = Json::fromQJsonValue(it.value());
|
||||
return obj;
|
||||
case QJsonValue::Object: {
|
||||
Json::object object;
|
||||
Json::append(&object, value.toObject());
|
||||
return object;
|
||||
}
|
||||
default: return static_null();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * *
|
||||
* Comparison
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include "mainwindow.h"
|
||||
#include "loadingscreen.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@@ -6,8 +8,13 @@ int main(int argc, char *argv[])
|
||||
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round);
|
||||
QApplication a(argc, argv);
|
||||
a.setStyle("fusion");
|
||||
|
||||
porysplash = new PorymapLoadingScreen;
|
||||
|
||||
QObject::connect(&a, &QCoreApplication::aboutToQuit, [=]() { delete porysplash; });
|
||||
|
||||
MainWindow w(nullptr);
|
||||
w.show();
|
||||
w.initialize();
|
||||
|
||||
return a.exec();
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "customattributesframe.h"
|
||||
#include "scripting.h"
|
||||
#include "adjustingstackedwidget.h"
|
||||
#include "draggablepixmapitem.h"
|
||||
#include "eventpixmapitem.h"
|
||||
#include "editcommands.h"
|
||||
#include "flowlayout.h"
|
||||
#include "shortcut.h"
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "newmapgroupdialog.h"
|
||||
#include "newlocationdialog.h"
|
||||
#include "message.h"
|
||||
#include "loadingscreen.h"
|
||||
|
||||
#include <QClipboard>
|
||||
#include <QDirIterator>
|
||||
@@ -75,10 +76,13 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
|
||||
cleanupLargeLog();
|
||||
logInfo(QString("Launching Porymap v%1").arg(QCoreApplication::applicationVersion()));
|
||||
}
|
||||
|
||||
void MainWindow::initialize() {
|
||||
this->initWindow();
|
||||
if (porymapConfig.reopenOnLaunch && !porymapConfig.projectManuallyClosed && this->openProject(porymapConfig.getRecentProject(), true))
|
||||
if (porymapConfig.reopenOnLaunch && !porymapConfig.projectManuallyClosed && this->openProject(porymapConfig.getRecentProject(), true)) {
|
||||
on_toolButton_Paint_clicked();
|
||||
}
|
||||
|
||||
// there is a bug affecting macOS users, where the trackpad deilveres a bad touch-release gesture
|
||||
// the warning is a bit annoying, so it is disabled here
|
||||
@@ -86,6 +90,9 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
|
||||
if (porymapConfig.checkForUpdates)
|
||||
this->checkForUpdates(false);
|
||||
|
||||
this->restoreWindowState();
|
||||
this->show();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
@@ -142,7 +149,6 @@ void MainWindow::initWindow() {
|
||||
this->initMiscHeapObjects();
|
||||
this->initMapList();
|
||||
this->initShortcuts();
|
||||
this->restoreWindowState();
|
||||
|
||||
#ifndef RELEASE_PLATFORM
|
||||
ui->actionCheck_for_Updates->setVisible(false);
|
||||
@@ -153,7 +159,6 @@ void MainWindow::initWindow() {
|
||||
#endif
|
||||
|
||||
setWindowDisabled(true);
|
||||
show();
|
||||
}
|
||||
|
||||
void MainWindow::initShortcuts() {
|
||||
@@ -261,6 +266,10 @@ void MainWindow::initCustomUI() {
|
||||
// Create map header data widget
|
||||
this->mapHeaderForm = new MapHeaderForm();
|
||||
ui->layout_HeaderData->addWidget(this->mapHeaderForm);
|
||||
|
||||
// Center zooming on the mouse
|
||||
ui->graphicsView_Map->setTransformationAnchor(QGraphicsView::ViewportAnchor::AnchorUnderMouse);
|
||||
ui->graphicsView_Map->setResizeAnchor(QGraphicsView::ViewportAnchor::AnchorUnderMouse);
|
||||
}
|
||||
|
||||
void MainWindow::initExtraSignals() {
|
||||
@@ -299,6 +308,9 @@ void MainWindow::initExtraSignals() {
|
||||
connect(ui->action_NewLayout, &QAction::triggered, this, &MainWindow::openNewLayoutDialog);
|
||||
connect(ui->actionDuplicate_Current_Map_Layout, &QAction::triggered, this, &MainWindow::openDuplicateMapOrLayoutDialog);
|
||||
connect(ui->comboBox_LayoutSelector->lineEdit(), &QLineEdit::editingFinished, this, &MainWindow::onLayoutSelectorEditingFinished);
|
||||
connect(ui->checkBox_smartPaths, &QCheckBox::toggled, this, &MainWindow::setSmartPathsEnabled);
|
||||
connect(ui->checkBox_ToggleBorder, &QCheckBox::toggled, this, &MainWindow::setBorderVisibility);
|
||||
connect(ui->checkBox_MirrorConnections, &QCheckBox::toggled, this, &MainWindow::setMirrorConnectionsEnabled);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionCheck_for_Updates_triggered() {
|
||||
@@ -338,13 +350,14 @@ void MainWindow::initEditor() {
|
||||
this->editor = new Editor(ui);
|
||||
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::openEventMap, this, &MainWindow::openEventMap);
|
||||
connect(this->editor, &Editor::currentMetatilesSelectionChanged, this, &MainWindow::currentMetatilesSelectionChanged);
|
||||
connect(this->editor, &Editor::wildMonTableEdited, this, &MainWindow::markMapEdited);
|
||||
connect(this->editor, &Editor::wildMonTableEdited, [this] { markMapEdited(this->editor->map); });
|
||||
connect(this->editor, &Editor::mapRulerStatusChanged, this, &MainWindow::onMapRulerStatusChanged);
|
||||
connect(this->editor, &Editor::tilesetUpdated, this, &Scripting::cb_TilesetUpdated);
|
||||
connect(ui->newEventToolButton, &NewEventToolButton::newEventAdded, this->editor, &Editor::addNewEvent);
|
||||
connect(ui->toolButton_deleteEvent, &QAbstractButton::clicked, this->editor, &Editor::deleteSelectedEvents);
|
||||
connect(ui->graphicsView_Connections, &ConnectionsView::pressedDelete, this->editor, &Editor::removeSelectedConnection);
|
||||
|
||||
this->loadUserSettings();
|
||||
|
||||
@@ -520,11 +533,7 @@ void MainWindow::updateWindowTitle() {
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::markMapEdited() {
|
||||
if (editor) markSpecificMapEdited(editor->map);
|
||||
}
|
||||
|
||||
void MainWindow::markSpecificMapEdited(Map* map) {
|
||||
void MainWindow::markMapEdited(Map* map) {
|
||||
if (!map)
|
||||
return;
|
||||
map->setHasUnsavedDataChanges(true);
|
||||
@@ -584,6 +593,8 @@ void MainWindow::loadUserSettings() {
|
||||
ui->checkBox_ToggleBorder->setChecked(porymapConfig.showBorder);
|
||||
ui->actionShow_Events_In_Map_View->setChecked(porymapConfig.eventOverlayEnabled);
|
||||
|
||||
this->editor->gridSettings = porymapConfig.gridSettings;
|
||||
|
||||
setTheme(porymapConfig.theme);
|
||||
setDivingMapsVisible(porymapConfig.showDiveEmergeMaps);
|
||||
}
|
||||
@@ -651,11 +662,13 @@ bool MainWindow::openProject(QString dir, bool initial) {
|
||||
projectConfig.projectDir = dir;
|
||||
projectConfig.load();
|
||||
|
||||
porysplash->start();
|
||||
|
||||
Scripting::init(this);
|
||||
|
||||
// Create the project
|
||||
auto project = new Project(editor);
|
||||
project->set_root(dir);
|
||||
project->setRoot(dir);
|
||||
connect(project, &Project::fileChanged, this, &MainWindow::showFileWatcherWarning);
|
||||
connect(project, &Project::mapLoaded, this, &MainWindow::onMapLoaded);
|
||||
connect(project, &Project::mapCreated, this, &MainWindow::onNewMapCreated);
|
||||
@@ -670,6 +683,7 @@ bool MainWindow::openProject(QString dir, bool initial) {
|
||||
// Make sure project looks reasonable before attempting to load it
|
||||
if (isInvalidProject(this->editor->project)) {
|
||||
delete this->editor->project;
|
||||
porysplash->stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -679,6 +693,7 @@ bool MainWindow::openProject(QString dir, bool initial) {
|
||||
showProjectOpenFailure();
|
||||
delete this->editor->project;
|
||||
// TODO: Allow changing project settings at this point
|
||||
porysplash->stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -699,6 +714,7 @@ bool MainWindow::openProject(QString dir, bool initial) {
|
||||
editor->layout);
|
||||
Scripting::cb_ProjectOpened(dir);
|
||||
setWindowDisabled(false);
|
||||
porysplash->stop();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -712,7 +728,7 @@ bool MainWindow::isInvalidProject(Project *project) {
|
||||
if (!project->sanityCheck()) {
|
||||
logWarn(QString("The directory '%1' failed the project sanity check.").arg(project->root));
|
||||
|
||||
ErrorMessage msgBox(QStringLiteral("The selected directory appears to be invalid."), this);
|
||||
ErrorMessage msgBox(QStringLiteral("The selected directory appears to be invalid."), porysplash);
|
||||
msgBox.setInformativeText(QString("The directory '%1' is missing key files.\n\n"
|
||||
"Make sure you selected the correct project directory "
|
||||
"(the one used to make your .gba file, e.g. 'pokeemerald').").arg(project->root));
|
||||
@@ -764,14 +780,15 @@ void MainWindow::showProjectOpenFailure() {
|
||||
|
||||
// Alert the user that one or more maps have been excluded while loading the project.
|
||||
void MainWindow::showMapsExcludedAlert(const QStringList &excludedMapNames) {
|
||||
RecentErrorMessage msgBox("", this);
|
||||
auto msgBox = new RecentErrorMessage("", this);
|
||||
msgBox->setAttribute(Qt::WA_DeleteOnClose);
|
||||
if (excludedMapNames.length() == 1) {
|
||||
msgBox.setText(QString("Failed to load map '%1'. Saving will exclude this map from your project.").arg(excludedMapNames.first()));
|
||||
msgBox->setText(QString("Failed to load map '%1'. Saving will exclude this map from your project.").arg(excludedMapNames.first()));
|
||||
} else {
|
||||
msgBox.setText(QStringLiteral("Failed to load the maps listed below. Saving will exclude these maps from your project."));
|
||||
msgBox.setDetailedText(excludedMapNames.join("\n")); // Overwrites error details text, user will need to check the log.
|
||||
msgBox->setText(QStringLiteral("Failed to load the maps listed below. Saving will exclude these maps from your project."));
|
||||
msgBox->setDetailedText(excludedMapNames.join("\n")); // Overwrites error details text, user will need to check the log.
|
||||
}
|
||||
msgBox.exec();
|
||||
msgBox->open();
|
||||
}
|
||||
|
||||
bool MainWindow::isProjectOpen() {
|
||||
@@ -881,28 +898,28 @@ void MainWindow::showFileWatcherWarning() {
|
||||
path.remove(root);
|
||||
}
|
||||
|
||||
QuestionMessage msgBox("", this);
|
||||
QPointer msgBox = new QuestionMessage("", this);
|
||||
if (modifiedFiles.count() == 1) {
|
||||
msgBox.setText(QString("The file %1 has changed on disk. Would you like to reload the project?").arg(modifiedFiles.first()));
|
||||
msgBox->setText(QString("The file %1 has changed on disk. Would you like to reload the project?").arg(modifiedFiles.first()));
|
||||
} else {
|
||||
msgBox.setText(QStringLiteral("Some project files have changed on disk. Would you like to reload the project?"));
|
||||
msgBox.setDetailedText(QStringLiteral("The following files have changed:\n") + modifiedFiles.join("\n"));
|
||||
msgBox->setText(QStringLiteral("Some project files have changed on disk. Would you like to reload the project?"));
|
||||
msgBox->setDetailedText(QStringLiteral("The following files have changed:\n") + modifiedFiles.join("\n"));
|
||||
}
|
||||
msgBox->setCheckBox(new QCheckBox("Do not ask again."));
|
||||
|
||||
QCheckBox showAgainCheck("Do not ask again.");
|
||||
msgBox.setCheckBox(&showAgainCheck);
|
||||
|
||||
auto reply = msgBox.exec();
|
||||
if (reply == QMessageBox::Yes) {
|
||||
on_action_Reload_Project_triggered();
|
||||
} else if (reply == QMessageBox::No) {
|
||||
if (showAgainCheck.isChecked()) {
|
||||
porymapConfig.monitorFiles = false;
|
||||
if (this->preferenceEditor)
|
||||
this->preferenceEditor->updateFields();
|
||||
connect(msgBox, &QuestionMessage::accepted, this, &MainWindow::on_action_Reload_Project_triggered);
|
||||
connect(msgBox, &QuestionMessage::finished, [this, msgBox] {
|
||||
if (msgBox) {
|
||||
if (msgBox->checkBox() && msgBox->checkBox()->isChecked()) {
|
||||
porymapConfig.monitorFiles = false;
|
||||
if (this->preferenceEditor)
|
||||
this->preferenceEditor->updateFields();
|
||||
}
|
||||
msgBox->deleteLater();
|
||||
}
|
||||
}
|
||||
showing = false;
|
||||
showing = false;
|
||||
});
|
||||
msgBox->open();
|
||||
}
|
||||
|
||||
QString MainWindow::getExistingDirectory(QString dir) {
|
||||
@@ -917,7 +934,8 @@ void MainWindow::on_action_Open_Project_triggered()
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Reload_Project_triggered() {
|
||||
openProject(editor->project->root);
|
||||
if (this->editor && this->editor->project)
|
||||
openProject(this->editor->project->root);
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Close_Project_triggered() {
|
||||
@@ -942,9 +960,10 @@ bool MainWindow::userSetMap(QString map_name) {
|
||||
}
|
||||
|
||||
if (map_name == editor->project->getDynamicMapName()) {
|
||||
WarningMessage msgBox(QString("Cannot open map '%1'.").arg(map_name), this);
|
||||
msgBox.setInformativeText(QStringLiteral("This map name is a placeholder to indicate that the warp's map will be set programmatically."));
|
||||
msgBox.exec();
|
||||
auto msgBox = new WarningMessage(QString("Cannot open map '%1'.").arg(map_name), this);
|
||||
msgBox->setAttribute(Qt::WA_DeleteOnClose);
|
||||
msgBox->setInformativeText(QStringLiteral("This map name is a placeholder to indicate that the warp's map will be set programmatically."));
|
||||
msgBox->open();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -976,8 +995,6 @@ bool MainWindow::setMap(QString map_name) {
|
||||
updateMapList();
|
||||
resetMapListFilters();
|
||||
|
||||
connect(editor->map, &Map::modified, this, &MainWindow::markMapEdited, Qt::UniqueConnection);
|
||||
|
||||
// If the map's MAPSEC / layout changes, update the map's position in the map list.
|
||||
// These are doing more work than necessary, rather than rebuilding the entire list they should find and relocate the appropriate row.
|
||||
connect(editor->map, &Map::layoutChanged, this, &MainWindow::rebuildMapList_Layouts, Qt::UniqueConnection);
|
||||
@@ -1090,20 +1107,57 @@ void MainWindow::refreshCollisionSelector() {
|
||||
on_horizontalSlider_CollisionZoom_valueChanged(ui->horizontalSlider_CollisionZoom->value());
|
||||
}
|
||||
|
||||
void MainWindow::openWarpMap(QString map_name, int event_id, Event::Group event_group) {
|
||||
// Open the destination map.
|
||||
if (!userSetMap(map_name))
|
||||
// Some events (like warps) have data that refers to an event on a different map.
|
||||
// This function opens that map, and selects the event it's referring to.
|
||||
void MainWindow::openEventMap(Event *sourceEvent) {
|
||||
if (!sourceEvent || !this->editor->map) return;
|
||||
|
||||
QString targetMapName;
|
||||
QString targetEventIdName;
|
||||
Event::Group targetEventGroup;
|
||||
|
||||
Event::Type eventType = sourceEvent->getEventType();
|
||||
if (eventType == Event::Type::Warp) {
|
||||
// Warp events open to their destination warp event.
|
||||
WarpEvent *warp = dynamic_cast<WarpEvent *>(sourceEvent);
|
||||
targetMapName = warp->getDestinationMap();
|
||||
targetEventIdName = warp->getDestinationWarpID();
|
||||
targetEventGroup = Event::Group::Warp;
|
||||
} else if (eventType == Event::Type::CloneObject) {
|
||||
// Clone object events open to their target object event.
|
||||
CloneObjectEvent *clone = dynamic_cast<CloneObjectEvent *>(sourceEvent);
|
||||
targetMapName = clone->getTargetMap();
|
||||
targetEventIdName = clone->getTargetID();
|
||||
targetEventGroup = Event::Group::Object;
|
||||
} else if (eventType == Event::Type::SecretBase) {
|
||||
// Secret Bases open to their secret base entrance
|
||||
const QString mapPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix);
|
||||
SecretBaseEvent *base = dynamic_cast<SecretBaseEvent *>(sourceEvent);
|
||||
|
||||
// Extract the map name from the secret base ID.
|
||||
QString baseId = base->getBaseID();
|
||||
targetMapName = this->editor->project->mapConstantsToMapNames.value(mapPrefix + baseId.left(baseId.lastIndexOf("_")));
|
||||
|
||||
// Just select the first warp. Normally the only warp event on every secret base map is the entrance/exit, so this is usually correct.
|
||||
// The warp IDs for secret bases are specified in the project's C code, not in the map data, so we don't have an easy way to read the actual IDs.
|
||||
targetEventIdName = "0";
|
||||
targetEventGroup = Event::Group::Warp;
|
||||
} else if (eventType == Event::Type::HealLocation && projectConfig.healLocationRespawnDataEnabled) {
|
||||
// Heal location events open to their respawn NPC
|
||||
HealLocationEvent *heal = dynamic_cast<HealLocationEvent *>(sourceEvent);
|
||||
targetMapName = heal->getRespawnMapName();
|
||||
targetEventIdName = heal->getRespawnNPC();
|
||||
targetEventGroup = Event::Group::Object;
|
||||
} else {
|
||||
// Other event types have no target map to open.
|
||||
return;
|
||||
}
|
||||
if (!userSetMap(targetMapName))
|
||||
return;
|
||||
|
||||
// Select the target event.
|
||||
int index = event_id - Event::getIndexOffset(event_group);
|
||||
Event* event = this->editor->map->getEvent(event_group, index);
|
||||
if (event) {
|
||||
this->editor->selectMapEvent(event);
|
||||
} else {
|
||||
// Can still warp to this map, but can't select the specified event
|
||||
logWarn(QString("%1 %2 doesn't exist on map '%3'").arg(Event::groupToString(event_group)).arg(event_id).arg(map_name));
|
||||
}
|
||||
// Map opened successfully, now try to select the targeted event on that map.
|
||||
Event *targetEvent = this->editor->map->getEvent(targetEventGroup, targetEventIdName);
|
||||
this->editor->selectMapEvent(targetEvent);
|
||||
}
|
||||
|
||||
void MainWindow::displayMapProperties() {
|
||||
@@ -1143,7 +1197,7 @@ void MainWindow::on_comboBox_LayoutSelector_currentTextChanged(const QString &te
|
||||
}
|
||||
this->editor->map->setLayout(layout);
|
||||
setMap(this->editor->map->name());
|
||||
markMapEdited();
|
||||
markMapEdited(this->editor->map);
|
||||
}
|
||||
|
||||
void MainWindow::onLayoutSelectorEditingFinished() {
|
||||
@@ -1198,6 +1252,8 @@ bool MainWindow::setProjectUI() {
|
||||
ui->newEventToolButton->setEventTypeVisible(Event::Type::SecretBase, projectConfig.eventSecretBaseEnabled);
|
||||
ui->newEventToolButton->setEventTypeVisible(Event::Type::CloneObject, projectConfig.eventCloneObjectEnabled);
|
||||
|
||||
this->editor->setPlayerViewRect(QRectF(0, 0, 16, 16).marginsAdded(projectConfig.playerViewDistance));
|
||||
|
||||
editor->setCollisionGraphics();
|
||||
ui->spinBox_SelectedElevation->setMaximum(Block::getMaxElevation());
|
||||
ui->spinBox_SelectedCollision->setMaximum(Block::getMaxCollision());
|
||||
@@ -1227,7 +1283,7 @@ bool MainWindow::setProjectUI() {
|
||||
ui->layoutList->setModel(layoutListProxyModel);
|
||||
ui->layoutList->sortByColumn(0, Qt::SortOrder::AscendingOrder);
|
||||
|
||||
ui->mapCustomAttributesFrame->table()->setRestrictedKeys(project->topLevelMapFields);
|
||||
ui->mapCustomAttributesFrame->table()->setRestrictedKeys(project->getTopLevelMapFields());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1240,10 +1296,7 @@ void MainWindow::clearProjectUI() {
|
||||
const QSignalBlocker b_SecondaryTileset(ui->comboBox_SecondaryTileset);
|
||||
ui->comboBox_SecondaryTileset->clear();
|
||||
|
||||
const QSignalBlocker b_DiveMap(ui->comboBox_DiveMap);
|
||||
ui->comboBox_DiveMap->clear();
|
||||
|
||||
const QSignalBlocker b_EmergeMap(ui->comboBox_EmergeMap);
|
||||
ui->comboBox_EmergeMap->clear();
|
||||
|
||||
const QSignalBlocker b_LayoutSelector(ui->comboBox_LayoutSelector);
|
||||
@@ -1404,8 +1457,6 @@ void MainWindow::onNewMapCreated(Map *newMap, const QString &groupName) {
|
||||
// (other combo boxes like for warp destinations are repopulated when the map changes).
|
||||
int mapIndex = this->editor->project->mapNames.indexOf(newMap->name());
|
||||
if (mapIndex >= 0) {
|
||||
const QSignalBlocker b_DiveMap(ui->comboBox_DiveMap);
|
||||
const QSignalBlocker b_EmergeMap(ui->comboBox_EmergeMap);
|
||||
ui->comboBox_DiveMap->insertItem(mapIndex, newMap->name());
|
||||
ui->comboBox_EmergeMap->insertItem(mapIndex, newMap->name());
|
||||
}
|
||||
@@ -1661,16 +1712,15 @@ void MainWindow::on_action_Save_triggered() {
|
||||
save(true);
|
||||
}
|
||||
|
||||
void MainWindow::save(bool currentOnly) {
|
||||
if (currentOnly) {
|
||||
this->editor->saveCurrent();
|
||||
} else {
|
||||
this->editor->saveAll();
|
||||
bool MainWindow::save(bool currentOnly) {
|
||||
bool success = currentOnly ? this->editor->saveCurrent() : this->editor->saveAll();
|
||||
if (!success) {
|
||||
RecentErrorMessage::show(QStringLiteral("Failed to save some project changes."), this);
|
||||
}
|
||||
updateWindowTitle();
|
||||
updateMapList();
|
||||
|
||||
if (!porymapConfig.shownInGameReloadMessage) {
|
||||
if (success && !porymapConfig.shownInGameReloadMessage) {
|
||||
// Show a one-time warning that the user may need to reload their map to see their new changes.
|
||||
InfoMessage::show(QStringLiteral("Reload your map in-game!\n\nIf your game is currently saved on a map you have edited, "
|
||||
"the changes may not appear until you leave the map and return."),
|
||||
@@ -1679,6 +1729,7 @@ void MainWindow::save(bool currentOnly) {
|
||||
}
|
||||
|
||||
saveGlobalConfigs();
|
||||
return success;
|
||||
}
|
||||
|
||||
void MainWindow::duplicate() {
|
||||
@@ -1688,6 +1739,13 @@ void MainWindow::duplicate() {
|
||||
void MainWindow::copy() {
|
||||
auto focused = QApplication::focusWidget();
|
||||
if (focused) {
|
||||
// Allow copying text from selectable QLabels.
|
||||
auto label = dynamic_cast<QLabel*>(focused);
|
||||
if (label && !label->selectedText().isEmpty()) {
|
||||
setClipboardData(label->selectedText());
|
||||
return;
|
||||
}
|
||||
|
||||
QString objectName = focused->objectName();
|
||||
if (objectName == "graphicsView_currentMetatileSelection") {
|
||||
// copy the current metatile selection as json data
|
||||
@@ -1984,7 +2042,7 @@ void MainWindow::on_actionPlayer_View_Rectangle_triggered()
|
||||
this->editor->settings->playerViewRectEnabled = enabled;
|
||||
if ((this->editor->map_item && this->editor->map_item->has_mouse)
|
||||
|| (this->editor->collision_item && this->editor->collision_item->has_mouse)) {
|
||||
this->editor->playerViewRect->setVisible(enabled);
|
||||
this->editor->playerViewRect->setVisible(enabled && this->editor->playerViewRect->getActive());
|
||||
ui->graphicsView_Map->scene()->update();
|
||||
}
|
||||
}
|
||||
@@ -2014,6 +2072,7 @@ void MainWindow::on_actionGrid_Settings_triggered() {
|
||||
if (!this->gridSettingsDialog) {
|
||||
this->gridSettingsDialog = new GridSettingsDialog(&this->editor->gridSettings, this);
|
||||
connect(this->gridSettingsDialog, &GridSettingsDialog::changedGridSettings, this->editor, &Editor::updateMapGrid);
|
||||
connect(this->gridSettingsDialog, &GridSettingsDialog::accepted, [this] { porymapConfig.gridSettings = this->editor->gridSettings; });
|
||||
}
|
||||
openSubWindow(this->gridSettingsDialog);
|
||||
}
|
||||
@@ -2510,7 +2569,7 @@ void MainWindow::onOpenConnectedMap(MapConnection *connection) {
|
||||
}
|
||||
|
||||
void MainWindow::onMapLoaded(Map *map) {
|
||||
connect(map, &Map::modified, [this, map] { this->markSpecificMapEdited(map); });
|
||||
connect(map, &Map::modified, [this, map] { markMapEdited(map); });
|
||||
}
|
||||
|
||||
void MainWindow::onTilesetsSaved(QString primaryTilesetLabel, QString secondaryTilesetLabel) {
|
||||
@@ -2616,7 +2675,8 @@ void MainWindow::on_pushButton_AddConnection_clicked() {
|
||||
return;
|
||||
|
||||
auto dialog = new NewMapConnectionDialog(this, this->editor->map, this->editor->project->mapNames);
|
||||
connect(dialog, &NewMapConnectionDialog::accepted, this->editor, &Editor::addConnection);
|
||||
connect(dialog, &NewMapConnectionDialog::newConnectionedAdded, this->editor, &Editor::addNewConnection);
|
||||
connect(dialog, &NewMapConnectionDialog::connectionReplaced, this->editor, &Editor::replaceConnection);
|
||||
dialog->open();
|
||||
}
|
||||
|
||||
@@ -2669,17 +2729,6 @@ void MainWindow::on_button_OpenEmergeMap_clicked() {
|
||||
userSetMap(ui->comboBox_EmergeMap->currentText());
|
||||
}
|
||||
|
||||
void MainWindow::on_comboBox_DiveMap_currentTextChanged(const QString &mapName) {
|
||||
// Include empty names as an update (user is deleting the connection)
|
||||
if (mapName.isEmpty() || editor->project->mapNames.contains(mapName))
|
||||
editor->updateDiveMap(mapName);
|
||||
}
|
||||
|
||||
void MainWindow::on_comboBox_EmergeMap_currentTextChanged(const QString &mapName) {
|
||||
if (mapName.isEmpty() || editor->project->mapNames.contains(mapName))
|
||||
editor->updateEmergeMap(mapName);
|
||||
}
|
||||
|
||||
void MainWindow::on_comboBox_PrimaryTileset_currentTextChanged(const QString &tilesetLabel)
|
||||
{
|
||||
if (editor->project->primaryTilesetLabels.contains(tilesetLabel) && editor->layout) {
|
||||
@@ -2741,25 +2790,20 @@ void MainWindow::on_pushButton_ChangeDimensions_clicked() {
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_checkBox_smartPaths_stateChanged(int selected)
|
||||
void MainWindow::setSmartPathsEnabled(bool enabled)
|
||||
{
|
||||
bool enabled = selected == Qt::Checked;
|
||||
editor->settings->smartPathsEnabled = enabled;
|
||||
if (enabled) {
|
||||
editor->cursorMapTileRect->setSmartPathMode(true);
|
||||
} else {
|
||||
editor->cursorMapTileRect->setSmartPathMode(false);
|
||||
}
|
||||
this->editor->settings->smartPathsEnabled = enabled;
|
||||
this->editor->cursorMapTileRect->setSmartPathMode(enabled);
|
||||
}
|
||||
|
||||
void MainWindow::on_checkBox_ToggleBorder_stateChanged(int selected)
|
||||
void MainWindow::setBorderVisibility(bool visible)
|
||||
{
|
||||
editor->toggleBorderVisibility(selected != 0);
|
||||
editor->toggleBorderVisibility(visible);
|
||||
}
|
||||
|
||||
void MainWindow::on_checkBox_MirrorConnections_stateChanged(int selected)
|
||||
void MainWindow::setMirrorConnectionsEnabled(bool enabled)
|
||||
{
|
||||
porymapConfig.mirrorConnectingMaps = (selected == Qt::Checked);
|
||||
porymapConfig.mirrorConnectingMaps = enabled;
|
||||
}
|
||||
|
||||
void MainWindow::on_actionTileset_Editor_triggered()
|
||||
@@ -3080,7 +3124,8 @@ bool MainWindow::closeProject() {
|
||||
|
||||
auto reply = msgBox.exec();
|
||||
if (reply == QMessageBox::Yes) {
|
||||
save();
|
||||
if (!save())
|
||||
return false;
|
||||
} else if (reply == QMessageBox::No) {
|
||||
logWarn("Closing project with unsaved changes.");
|
||||
} else if (reply == QMessageBox::Cancel) {
|
||||
|
||||
797
src/project.cpp
797
src/project.cpp
File diff suppressed because it is too large
Load Diff
@@ -227,7 +227,7 @@ int MainWindow::getHeight() {
|
||||
void MainWindow::setDimensions(int width, int height) {
|
||||
if (!this->editor || !this->editor->layout)
|
||||
return;
|
||||
if (!Project::mapDimensionsValid(width, height))
|
||||
if (this->editor->project && !this->editor->project->mapDimensionsValid(width, height))
|
||||
return;
|
||||
this->editor->layout->setDimensions(width, height);
|
||||
this->tryCommitMapChanges(true);
|
||||
@@ -237,7 +237,7 @@ void MainWindow::setDimensions(int width, int height) {
|
||||
void MainWindow::setWidth(int width) {
|
||||
if (!this->editor || !this->editor->layout)
|
||||
return;
|
||||
if (!Project::mapDimensionsValid(width, this->editor->layout->getHeight()))
|
||||
if (this->editor->project && !this->editor->project->mapDimensionsValid(width, this->editor->layout->getHeight()))
|
||||
return;
|
||||
this->editor->layout->setDimensions(width, this->editor->layout->getHeight());
|
||||
this->tryCommitMapChanges(true);
|
||||
@@ -247,7 +247,7 @@ void MainWindow::setWidth(int width) {
|
||||
void MainWindow::setHeight(int height) {
|
||||
if (!this->editor || !this->editor->layout)
|
||||
return;
|
||||
if (!Project::mapDimensionsValid(this->editor->layout->getWidth(), height))
|
||||
if (this->editor->project && !this->editor->project->mapDimensionsValid(this->editor->layout->getWidth(), height))
|
||||
return;
|
||||
this->editor->layout->setDimensions(this->editor->layout->getWidth(), height);
|
||||
this->tryCommitMapChanges(true);
|
||||
|
||||
@@ -276,7 +276,12 @@ void MapView::addTileImage(int x, int y, int tileId, bool xflip, bool yflip, int
|
||||
this->editor->layout->tileset_primary,
|
||||
this->editor->layout->tileset_secondary,
|
||||
paletteId)
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 9, 0))
|
||||
.flipped(Util::getOrientation(xflip, yflip));
|
||||
#else
|
||||
.mirrored(xflip, yflip);
|
||||
#endif
|
||||
|
||||
if (setTransparency)
|
||||
image.setColor(0, qRgba(0, 0, 0, 0));
|
||||
if (this->getOverlay(layer)->addImage(x, y, image))
|
||||
|
||||
@@ -268,14 +268,13 @@ void Scripting::cb_LayoutOpened(QString layoutName) {
|
||||
instance->invokeCallback(OnLayoutOpened, args);
|
||||
}
|
||||
|
||||
void Scripting::cb_MapResized(int oldWidth, int oldHeight, int newWidth, int newHeight) {
|
||||
void Scripting::cb_MapResized(int oldWidth, int oldHeight, const QMargins &delta) {
|
||||
if (!instance) return;
|
||||
|
||||
QJSValueList args {
|
||||
oldWidth,
|
||||
oldHeight,
|
||||
newWidth,
|
||||
newHeight,
|
||||
Scripting::margins(delta),
|
||||
};
|
||||
instance->invokeCallback(OnMapResized, args);
|
||||
}
|
||||
@@ -356,6 +355,15 @@ QJSValue Scripting::dimensions(int width, int height) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
QJSValue Scripting::margins(const QMargins &margins) {
|
||||
QJSValue obj = instance->engine->newObject();
|
||||
obj.setProperty("left", margins.left());
|
||||
obj.setProperty("right", margins.right());
|
||||
obj.setProperty("top", margins.top());
|
||||
obj.setProperty("bottom", margins.bottom());
|
||||
return obj;
|
||||
}
|
||||
|
||||
QJSValue Scripting::position(int x, int y) {
|
||||
QJSValue obj = instance->engine->newObject();
|
||||
obj.setProperty("x", x);
|
||||
|
||||
@@ -9,15 +9,19 @@ AboutPorymap::AboutPorymap(QWidget *parent) :
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
static const QString commitHash = PORYMAP_LATEST_COMMIT;
|
||||
this->ui->label_Version->setText(QString("Version %1%2\nQt %3 (%4)\n%5")
|
||||
this->ui->label_Version->setText(getVersionString());
|
||||
|
||||
layout()->setSizeConstraint(QLayout::SetFixedSize);
|
||||
}
|
||||
|
||||
QString AboutPorymap::getVersionString() {
|
||||
static const QString commitHash = PORYMAP_LATEST_COMMIT;
|
||||
return QString("Version %1%2\nQt %3 (%4)\n%5")
|
||||
.arg(QCoreApplication::applicationVersion())
|
||||
.arg(commitHash.isEmpty() ? "" : QString(" (%1)").arg(commitHash))
|
||||
.arg(QStringLiteral(QT_VERSION_STR))
|
||||
.arg(QSysInfo::buildCpuArchitecture())
|
||||
.arg(QStringLiteral(__DATE__))
|
||||
);
|
||||
|
||||
layout()->setSizeConstraint(QLayout::SetFixedSize);
|
||||
.arg(QStringLiteral(__DATE__));
|
||||
}
|
||||
|
||||
AboutPorymap::~AboutPorymap()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "connectionpixmapitem.h"
|
||||
#include "editcommands.h"
|
||||
#include "map.h"
|
||||
#include "editor.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
@@ -9,7 +10,6 @@ ConnectionPixmapItem::ConnectionPixmapItem(MapConnection* connection)
|
||||
connection(connection)
|
||||
{
|
||||
this->setEditable(true);
|
||||
setFlag(ItemIsFocusable, true);
|
||||
this->basePixmap = pixmap();
|
||||
updateOrigin();
|
||||
render(false);
|
||||
@@ -31,7 +31,7 @@ void ConnectionPixmapItem::render(bool ignoreCache) {
|
||||
this->basePixmap = this->connection->render();
|
||||
|
||||
QPixmap pixmap = this->basePixmap.copy(0, 0, this->basePixmap.width(), this->basePixmap.height());
|
||||
this->setZValue(-1);
|
||||
this->setZValue(Editor::ZValue::MapConnectionActive);
|
||||
|
||||
// When editing is inactive the current selection is ignored, all connections should appear normal.
|
||||
if (this->getEditable()) {
|
||||
@@ -43,7 +43,7 @@ void ConnectionPixmapItem::render(bool ignoreCache) {
|
||||
painter.end();
|
||||
} else {
|
||||
// Darken the image
|
||||
this->setZValue(-2);
|
||||
this->setZValue(Editor::ZValue::MapConnectionInactive);
|
||||
QPainter painter(&pixmap);
|
||||
int alpha = static_cast<int>(255 * 0.25);
|
||||
painter.fillRect(0, 0, pixmap.width(), pixmap.height(), QColor(0, 0, 0, alpha));
|
||||
@@ -118,10 +118,6 @@ bool ConnectionPixmapItem::getEditable() {
|
||||
}
|
||||
|
||||
void ConnectionPixmapItem::setSelected(bool selected) {
|
||||
if (selected && !hasFocus()) {
|
||||
setFocus(Qt::OtherFocusReason);
|
||||
}
|
||||
|
||||
if (this->selected == selected)
|
||||
return;
|
||||
this->selected = selected;
|
||||
@@ -131,7 +127,7 @@ void ConnectionPixmapItem::setSelected(bool selected) {
|
||||
}
|
||||
|
||||
void ConnectionPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *) {
|
||||
setFocus(Qt::MouseFocusReason);
|
||||
this->setSelected(true);
|
||||
}
|
||||
|
||||
void ConnectionPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
|
||||
@@ -142,18 +138,3 @@ void ConnectionPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
|
||||
void ConnectionPixmapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) {
|
||||
emit connectionItemDoubleClicked(this->connection);
|
||||
}
|
||||
|
||||
void ConnectionPixmapItem::keyPressEvent(QKeyEvent* event) {
|
||||
if (event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace) {
|
||||
emit deleteRequested(this->connection);
|
||||
} else {
|
||||
QGraphicsPixmapItem::keyPressEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionPixmapItem::focusInEvent(QFocusEvent* event) {
|
||||
if (!this->getEditable())
|
||||
return;
|
||||
this->setSelected(true);
|
||||
QGraphicsPixmapItem::focusInEvent(event);
|
||||
}
|
||||
|
||||
@@ -7,44 +7,55 @@
|
||||
|
||||
ConnectionsListItem::ConnectionsListItem(QWidget *parent, MapConnection * connection, const QStringList &mapNames) :
|
||||
QFrame(parent),
|
||||
ui(new Ui::ConnectionsListItem)
|
||||
ui(new Ui::ConnectionsListItem),
|
||||
connection(connection),
|
||||
map(connection->parentMap())
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
|
||||
const QSignalBlocker blocker1(ui->comboBox_Direction);
|
||||
const QSignalBlocker blocker2(ui->comboBox_Map);
|
||||
const QSignalBlocker blocker3(ui->spinBox_Offset);
|
||||
|
||||
ui->comboBox_Direction->setEditable(false);
|
||||
// Direction
|
||||
const QSignalBlocker b_Direction(ui->comboBox_Direction);
|
||||
ui->comboBox_Direction->setMinimumContentsLength(0);
|
||||
ui->comboBox_Direction->addItems(MapConnection::cardinalDirections);
|
||||
ui->comboBox_Direction->installEventFilter(this);
|
||||
|
||||
connect(ui->comboBox_Direction, &NoScrollComboBox::editingFinished, this, &ConnectionsListItem::commitDirection);
|
||||
|
||||
// Map
|
||||
const QSignalBlocker b_Map(ui->comboBox_Map);
|
||||
ui->comboBox_Map->setMinimumContentsLength(6);
|
||||
ui->comboBox_Map->addItems(mapNames);
|
||||
ui->comboBox_Map->setFocusedScrollingEnabled(false); // Scrolling could cause rapid changes to many different maps
|
||||
ui->comboBox_Map->setInsertPolicy(QComboBox::NoInsert);
|
||||
ui->comboBox_Map->installEventFilter(this);
|
||||
|
||||
ui->spinBox_Offset->setMinimum(INT_MIN);
|
||||
ui->spinBox_Offset->setMaximum(INT_MAX);
|
||||
connect(ui->comboBox_Map, &QComboBox::currentTextChanged, this, &ConnectionsListItem::commitMap);
|
||||
|
||||
// Invalid map names are not considered a change. If editing finishes with an invalid name, restore the previous name.
|
||||
connect(ui->comboBox_Map->lineEdit(), &QLineEdit::editingFinished, [this] {
|
||||
const QSignalBlocker blocker(ui->comboBox_Map);
|
||||
if (ui->comboBox_Map->findText(ui->comboBox_Map->currentText()) < 0)
|
||||
const QSignalBlocker b(ui->comboBox_Map);
|
||||
if (this->connection && ui->comboBox_Map->findText(ui->comboBox_Map->currentText()) < 0)
|
||||
ui->comboBox_Map->setTextItem(this->connection->targetMapName());
|
||||
});
|
||||
|
||||
// Distinguish between move actions for the edit history
|
||||
connect(ui->spinBox_Offset, &QSpinBox::editingFinished, [this] { this->actionId++; });
|
||||
// Offset
|
||||
const QSignalBlocker b_Offset(ui->spinBox_Offset);
|
||||
ui->spinBox_Offset->setMinimum(INT_MIN);
|
||||
ui->spinBox_Offset->setMaximum(INT_MAX);
|
||||
ui->spinBox_Offset->installEventFilter(this);
|
||||
|
||||
connect(ui->spinBox_Offset, &QSpinBox::editingFinished, [this] { this->actionId++; }); // Distinguish between move actions for the edit history
|
||||
connect(ui->spinBox_Offset, QOverload<int>::of(&QSpinBox::valueChanged), this, &ConnectionsListItem::commitMove);
|
||||
|
||||
// If the connection changes externally we want to update to reflect the change.
|
||||
connect(connection, &MapConnection::offsetChanged, this, &ConnectionsListItem::updateUI);
|
||||
connect(connection, &MapConnection::directionChanged, this, &ConnectionsListItem::updateUI);
|
||||
connect(connection, &MapConnection::targetMapNameChanged, this, &ConnectionsListItem::updateUI);
|
||||
|
||||
this->connection = connection;
|
||||
this->map = connection->parentMap();
|
||||
connect(ui->button_Delete, &QToolButton::clicked, this, &ConnectionsListItem::commitRemove);
|
||||
connect(ui->button_OpenMap, &QToolButton::clicked, [this] { emit openMapClicked(this->connection); });
|
||||
|
||||
this->updateUI();
|
||||
}
|
||||
|
||||
@@ -66,13 +77,19 @@ void ConnectionsListItem::updateUI() {
|
||||
ui->spinBox_Offset->setValue(this->connection->offset());
|
||||
}
|
||||
|
||||
bool ConnectionsListItem::eventFilter(QObject*, QEvent *event) {
|
||||
if (event->type() == QEvent::FocusIn)
|
||||
this->setSelected(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
void ConnectionsListItem::setSelected(bool selected) {
|
||||
if (selected == this->isSelected)
|
||||
return;
|
||||
this->isSelected = selected;
|
||||
|
||||
this->setStyleSheet(selected ? ".ConnectionsListItem { border: 1px solid rgb(255, 0, 255); }"
|
||||
: ".ConnectionsListItem { border-width: 1px; }");
|
||||
this->setStyleSheet(selected ? QStringLiteral(".ConnectionsListItem { border: 1px solid rgb(255, 0, 255); }")
|
||||
: QStringLiteral(".ConnectionsListItem { border-width: 1px; }"));
|
||||
if (selected)
|
||||
emit this->selected();
|
||||
}
|
||||
@@ -81,42 +98,34 @@ void ConnectionsListItem::mousePressEvent(QMouseEvent *) {
|
||||
this->setSelected(true);
|
||||
}
|
||||
|
||||
void ConnectionsListItem::on_comboBox_Direction_currentTextChanged(QString direction) {
|
||||
this->setSelected(true);
|
||||
if (this->map)
|
||||
void ConnectionsListItem::commitDirection() {
|
||||
const QString direction = ui->comboBox_Direction->currentText();
|
||||
if (!this->connection || this->connection->direction() == direction)
|
||||
return;
|
||||
|
||||
if (MapConnection::isDiving(direction)) {
|
||||
// Diving maps are displayed separately, no support right now for replacing a list item with a diving map.
|
||||
// For now just restore the original direction.
|
||||
ui->comboBox_Direction->setCurrentText(this->connection->direction());
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->map) {
|
||||
this->map->commit(new MapConnectionChangeDirection(this->connection, direction));
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionsListItem::on_comboBox_Map_currentTextChanged(QString mapName) {
|
||||
this->setSelected(true);
|
||||
void ConnectionsListItem::commitMap(const QString &mapName) {
|
||||
if (this->map && ui->comboBox_Map->findText(mapName) >= 0)
|
||||
this->map->commit(new MapConnectionChangeMap(this->connection, mapName));
|
||||
}
|
||||
|
||||
void ConnectionsListItem::on_spinBox_Offset_valueChanged(int offset) {
|
||||
this->setSelected(true);
|
||||
void ConnectionsListItem::commitMove(int offset) {
|
||||
if (this->map)
|
||||
this->map->commit(new MapConnectionMove(this->connection, offset, this->actionId));
|
||||
}
|
||||
|
||||
void ConnectionsListItem::on_button_Delete_clicked() {
|
||||
void ConnectionsListItem::commitRemove() {
|
||||
if (this->map)
|
||||
this->map->commit(new MapConnectionRemove(this->map, this->connection));
|
||||
}
|
||||
|
||||
void ConnectionsListItem::on_button_OpenMap_clicked() {
|
||||
emit openMapClicked(this->connection);
|
||||
}
|
||||
|
||||
void ConnectionsListItem::focusInEvent(QFocusEvent* event) {
|
||||
this->setSelected(true);
|
||||
QFrame::focusInEvent(event);
|
||||
}
|
||||
|
||||
void ConnectionsListItem::keyPressEvent(QKeyEvent* event) {
|
||||
if (event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace) {
|
||||
on_button_Delete_clicked();
|
||||
} else {
|
||||
QFrame::keyPressEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "customattributestable.h"
|
||||
#include "parseutil.h"
|
||||
#include "noscrollspinbox.h"
|
||||
#include "utility.h"
|
||||
#include <QHeaderView>
|
||||
#include <QScrollBar>
|
||||
|
||||
@@ -39,8 +40,8 @@ CustomAttributesTable::CustomAttributesTable(QWidget *parent) :
|
||||
});
|
||||
}
|
||||
|
||||
QMap<QString, QJsonValue> CustomAttributesTable::getAttributes() const {
|
||||
QMap<QString, QJsonValue> fields;
|
||||
QJsonObject CustomAttributesTable::getAttributes() const {
|
||||
QJsonObject fields;
|
||||
for (int row = 0; row < this->rowCount(); row++) {
|
||||
auto keyValuePair = this->getAttribute(row);
|
||||
if (!keyValuePair.first.isEmpty())
|
||||
@@ -96,7 +97,7 @@ int CustomAttributesTable::addAttribute(const QString &key, const QJsonValue &va
|
||||
keyItem->setFlags(Qt::ItemIsEnabled);
|
||||
keyItem->setData(DataRole::JsonType, type); // Record the type for writing to the file
|
||||
keyItem->setTextAlignment(Qt::AlignCenter);
|
||||
keyItem->setToolTip(key); // Display name as tool tip in case it's too long to see in the cell
|
||||
keyItem->setToolTip(Util::toHtmlParagraph(key)); // Display name as tool tip in case it's too long to see in the cell
|
||||
this->setItem(rowIndex, Column::Key, keyItem);
|
||||
|
||||
// Add value to table
|
||||
@@ -145,10 +146,10 @@ void CustomAttributesTable::addNewAttribute(const QString &key, const QJsonValue
|
||||
}
|
||||
|
||||
// For programmatically populating the table
|
||||
void CustomAttributesTable::setAttributes(const QMap<QString, QJsonValue> &attributes) {
|
||||
void CustomAttributesTable::setAttributes(const QJsonObject &attributes) {
|
||||
m_keys.clear();
|
||||
this->setRowCount(0); // Clear old values
|
||||
for (auto it = attributes.cbegin(); it != attributes.cend(); it++)
|
||||
for (auto it = attributes.constBegin(); it != attributes.constEnd(); it++)
|
||||
this->addAttribute(it.key(), it.value());
|
||||
this->resizeVertically();
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ void CustomScriptsEditor::displayScript(const QString &filepath, bool enabled) {
|
||||
connect(widget->ui->b_Choose, &QAbstractButton::clicked, [this, item](bool) { this->replaceScript(item); });
|
||||
connect(widget->ui->b_Edit, &QAbstractButton::clicked, [this, item](bool) { this->openScript(item); });
|
||||
connect(widget->ui->b_Delete, &QAbstractButton::clicked, [this, item](bool) { this->removeScript(item); });
|
||||
connect(widget->ui->checkBox_Enable, &QCheckBox::stateChanged, this, &CustomScriptsEditor::markEdited);
|
||||
connect(widget->ui->checkBox_Enable, &QCheckBox::toggled, this, &CustomScriptsEditor::markEdited);
|
||||
connect(widget->ui->lineEdit_filepath, &QLineEdit::textEdited, this, &CustomScriptsEditor::markEdited);
|
||||
|
||||
// Per the Qt manual, for performance reasons QListWidget::setItemWidget shouldn't be used with non-static items.
|
||||
|
||||
@@ -38,9 +38,5 @@ void DivingMapPixmapItem::onTargetMapChanged() {
|
||||
}
|
||||
|
||||
void DivingMapPixmapItem::setComboText(const QString &text) {
|
||||
if (!m_combo)
|
||||
return;
|
||||
|
||||
const QSignalBlocker blocker(m_combo);
|
||||
m_combo->setCurrentText(text);
|
||||
if (m_combo) m_combo->setCurrentText(text);
|
||||
}
|
||||
|
||||
@@ -1,134 +0,0 @@
|
||||
#include "draggablepixmapitem.h"
|
||||
#include "editor.h"
|
||||
#include "editcommands.h"
|
||||
#include "mapruler.h"
|
||||
#include "metatile.h"
|
||||
|
||||
static unsigned currentActionId = 0;
|
||||
|
||||
|
||||
void DraggablePixmapItem::updatePosition() {
|
||||
int x = this->event->getPixelX();
|
||||
int y = this->event->getPixelY();
|
||||
setX(x);
|
||||
setY(y);
|
||||
if (this->editor->selectedEvents.contains(this->event)) {
|
||||
setZValue(event->getY() + 1);
|
||||
} else {
|
||||
setZValue(event->getY());
|
||||
}
|
||||
editor->updateWarpEventWarning(event);
|
||||
}
|
||||
|
||||
void DraggablePixmapItem::emitPositionChanged() {
|
||||
emit xChanged(event->getX());
|
||||
emit yChanged(event->getY());
|
||||
emit elevationChanged(event->getElevation());
|
||||
}
|
||||
|
||||
void DraggablePixmapItem::updatePixmap() {
|
||||
editor->project->loadEventPixmap(event, true);
|
||||
this->updatePosition();
|
||||
editor->redrawEventPixmapItem(this);
|
||||
emit spriteChanged(event->getPixmap());
|
||||
}
|
||||
|
||||
void DraggablePixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *mouse) {
|
||||
if (this->active)
|
||||
return;
|
||||
this->active = true;
|
||||
this->lastPos = Metatile::coordFromPixmapCoord(mouse->scenePos());
|
||||
|
||||
bool selectionToggle = mouse->modifiers() & Qt::ControlModifier;
|
||||
if (selectionToggle || !this->editor->selectedEvents.contains(this->event)) {
|
||||
// User is either toggling this selection on/off as part of a group selection,
|
||||
// or they're newly selecting just this item.
|
||||
this->editor->selectMapEvent(this->event, selectionToggle);
|
||||
} else {
|
||||
// This item is already selected and the user isn't toggling the selection, so there are 4 possibilities:
|
||||
// 1. This is the only selected event, and the selection is pointless.
|
||||
// 2. This is the only selected event, and they want to drag the item around.
|
||||
// 3. There's a group selection, and they want to start a new selection with just this item.
|
||||
// 4. There's a group selection, and they want to drag the group around.
|
||||
// 'selectMapEvent' will immediately clear the rest of the selection, which supports #1-3 but prevents #4.
|
||||
// To support #4 we set the flag below, and we only call 'selectMapEvent' on mouse release if no move occurred.
|
||||
this->releaseSelectionQueued = true;
|
||||
}
|
||||
this->editor->selectingEvent = true;
|
||||
}
|
||||
|
||||
void DraggablePixmapItem::move(int dx, int dy) {
|
||||
event->setX(event->getX() + dx);
|
||||
event->setY(event->getY() + dy);
|
||||
updatePosition();
|
||||
emitPositionChanged();
|
||||
}
|
||||
|
||||
void DraggablePixmapItem::moveTo(const QPoint &pos) {
|
||||
event->setX(pos.x());
|
||||
event->setY(pos.y());
|
||||
updatePosition();
|
||||
emitPositionChanged();
|
||||
}
|
||||
|
||||
void DraggablePixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *mouse) {
|
||||
if (!this->active)
|
||||
return;
|
||||
|
||||
QPoint pos = Metatile::coordFromPixmapCoord(mouse->scenePos());
|
||||
if (pos == this->lastPos)
|
||||
return;
|
||||
|
||||
QPoint moveDistance = pos - this->lastPos;
|
||||
this->lastPos = pos;
|
||||
emit this->editor->map_item->hoveredMapMetatileChanged(pos);
|
||||
|
||||
QList <Event *> selectedEvents;
|
||||
if (this->editor->selectedEvents.contains(this->event)) {
|
||||
selectedEvents = this->editor->selectedEvents;
|
||||
} else {
|
||||
selectedEvents.append(this->event);
|
||||
}
|
||||
editor->map->commit(new EventMove(selectedEvents, moveDistance.x(), moveDistance.y(), currentActionId));
|
||||
this->releaseSelectionQueued = false;
|
||||
}
|
||||
|
||||
void DraggablePixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouse) {
|
||||
if (!this->active)
|
||||
return;
|
||||
this->active = false;
|
||||
currentActionId++;
|
||||
if (this->releaseSelectionQueued) {
|
||||
this->releaseSelectionQueued = false;
|
||||
if (Metatile::coordFromPixmapCoord(mouse->scenePos()) == this->lastPos)
|
||||
this->editor->selectMapEvent(this->event);
|
||||
}
|
||||
}
|
||||
|
||||
// Events with properties that specify a map will open that map when double-clicked.
|
||||
void DraggablePixmapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) {
|
||||
Event::Type eventType = this->event->getEventType();
|
||||
if (eventType == Event::Type::Warp) {
|
||||
WarpEvent *warp = dynamic_cast<WarpEvent *>(this->event);
|
||||
QString destMap = warp->getDestinationMap();
|
||||
int warpId = ParseUtil::gameStringToInt(warp->getDestinationWarpID());
|
||||
emit editor->warpEventDoubleClicked(destMap, warpId, Event::Group::Warp);
|
||||
}
|
||||
else if (eventType == Event::Type::CloneObject) {
|
||||
CloneObjectEvent *clone = dynamic_cast<CloneObjectEvent *>(this->event);
|
||||
emit editor->warpEventDoubleClicked(clone->getTargetMap(), clone->getTargetID(), Event::Group::Object);
|
||||
}
|
||||
else if (eventType == Event::Type::SecretBase) {
|
||||
const QString mapPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix);
|
||||
SecretBaseEvent *base = dynamic_cast<SecretBaseEvent *>(this->event);
|
||||
QString baseId = base->getBaseID();
|
||||
QString destMap = editor->project->mapConstantsToMapNames.value(mapPrefix + baseId.left(baseId.lastIndexOf("_")));
|
||||
emit editor->warpEventDoubleClicked(destMap, 0, Event::Group::Warp);
|
||||
}
|
||||
else if (eventType == Event::Type::HealLocation && projectConfig.healLocationRespawnDataEnabled) {
|
||||
HealLocationEvent *heal = dynamic_cast<HealLocationEvent *>(this->event);
|
||||
const QString localIdName = heal->getRespawnNPC();
|
||||
int localId = 0; // TODO: Get value from localIdName
|
||||
emit editor->warpEventDoubleClicked(heal->getRespawnMapName(), localId, Event::Group::Object);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "eventframes.h"
|
||||
#include "customattributesframe.h"
|
||||
#include "editcommands.h"
|
||||
#include "draggablepixmapitem.h"
|
||||
#include "eventpixmapitem.h"
|
||||
|
||||
#include <limits>
|
||||
using std::numeric_limits;
|
||||
@@ -74,6 +74,7 @@ void EventFrame::setup() {
|
||||
this->label_id = new QLabel("event_type");
|
||||
l_vbox_1->addWidget(this->label_id);
|
||||
l_vbox_1->addLayout(l_layout_xyz);
|
||||
this->label_id->setText(Event::typeToString(this->event->getEventType()));
|
||||
|
||||
// icon / pixmap label
|
||||
this->label_icon = new QLabel(this);
|
||||
@@ -113,7 +114,7 @@ void EventFrame::connectSignals(MainWindow *) {
|
||||
}
|
||||
});
|
||||
|
||||
connect(this->event->getPixmapItem(), &DraggablePixmapItem::xChanged, this->spinner_x, &NoScrollSpinBox::setValue);
|
||||
connect(this->event->getPixmapItem(), &EventPixmapItem::xChanged, this->spinner_x, &NoScrollSpinBox::setValue);
|
||||
|
||||
this->spinner_y->disconnect();
|
||||
connect(this->spinner_y, QOverload<int>::of(&QSpinBox::valueChanged), [this](int value) {
|
||||
@@ -122,7 +123,7 @@ void EventFrame::connectSignals(MainWindow *) {
|
||||
this->event->getMap()->commit(new EventMove(QList<Event *>() << this->event, 0, delta, this->spinner_y->getActionId()));
|
||||
}
|
||||
});
|
||||
connect(this->event->getPixmapItem(), &DraggablePixmapItem::yChanged, this->spinner_y, &NoScrollSpinBox::setValue);
|
||||
connect(this->event->getPixmapItem(), &EventPixmapItem::yChanged, this->spinner_y, &NoScrollSpinBox::setValue);
|
||||
|
||||
this->spinner_z->disconnect();
|
||||
connect(this->spinner_z, QOverload<int>::of(&QSpinBox::valueChanged), [this](int value) {
|
||||
@@ -172,19 +173,31 @@ void EventFrame::setActive(bool active) {
|
||||
this->blockSignals(!active);
|
||||
}
|
||||
|
||||
void EventFrame::populateDropdown(NoScrollComboBox * combo, const QStringList &items) {
|
||||
// Set the items in the combo box. This may be called after the frame is initialized
|
||||
// if the frame needs to be repopulated, so ensure the text in the combo is preserved
|
||||
// and that we don't accidentally fire 'currentTextChanged'.
|
||||
const QSignalBlocker b(combo);
|
||||
const QString savedText = combo->currentText();
|
||||
combo->clear();
|
||||
combo->addItems(items);
|
||||
combo->setCurrentText(savedText);
|
||||
}
|
||||
|
||||
void EventFrame::populateScriptDropdown(NoScrollComboBox * combo, Project * project) {
|
||||
// The script dropdown and autocomplete are populated with scripts used by the map's events and from its scripts file.
|
||||
if (!this->event->getMap())
|
||||
return;
|
||||
|
||||
QStringList scripts = this->event->getMap()->getScriptLabels(this->event->getEventGroup());
|
||||
combo->addItems(scripts);
|
||||
populateDropdown(combo, scripts);
|
||||
|
||||
// Depending on the settings, the autocomplete may also contain all global scripts.
|
||||
if (porymapConfig.loadAllEventScripts) {
|
||||
project->insertGlobalScriptLabels(scripts);
|
||||
}
|
||||
|
||||
// Note: Because 'combo' is the parent, the old QCompleter will be deleted when a new one is set.
|
||||
auto completer = new QCompleter(scripts, combo);
|
||||
completer->setCaseSensitivity(Qt::CaseInsensitive);
|
||||
completer->setModelSorting(QCompleter::CaseInsensitivelySortedModel);
|
||||
@@ -197,27 +210,46 @@ void EventFrame::populateScriptDropdown(NoScrollComboBox * combo, Project * proj
|
||||
combo->setCompleter(completer);
|
||||
|
||||
// If the project changes the script labels, update the EventFrame.
|
||||
// TODO: At the moment this only happens when the user changes script settings (i.e. when 'porymapConfig.loadAllEventScripts' changes).
|
||||
// This should ultimately be connected to a file watcher so that we can also update the dropdown when the scripts file changes.
|
||||
connect(project, &Project::eventScriptLabelsRead, this, &EventFrame::invalidateValues, Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
void EventFrame::populateIdNameDropdown(NoScrollComboBox * combo, Project * project, const QString &mapName, Event::Group group) {
|
||||
if (!project->mapNames.contains(mapName))
|
||||
return;
|
||||
|
||||
Map *map = project->loadMap(mapName);
|
||||
if (map) populateDropdown(combo, map->getEventIdNames(group));
|
||||
}
|
||||
|
||||
|
||||
void ObjectFrame::setup() {
|
||||
EventFrame::setup();
|
||||
|
||||
this->label_id->setText("Object");
|
||||
// local id
|
||||
QFormLayout *l_form_local_id = new QFormLayout();
|
||||
this->line_edit_local_id = new QLineEdit(this);
|
||||
static const QString line_edit_local_id_toolTip = Util::toHtmlParagraph("An optional, unique name to use to refer to this object in scripts. "
|
||||
"If no name is given you can refer to this object using its 'object id' number.");
|
||||
this->line_edit_local_id->setToolTip(line_edit_local_id_toolTip);
|
||||
this->line_edit_local_id->setPlaceholderText("LOCALID_MY_NPC");
|
||||
l_form_local_id->addRow("Local ID", this->line_edit_local_id);
|
||||
this->layout_contents->addLayout(l_form_local_id);
|
||||
|
||||
// sprite combo
|
||||
QFormLayout *l_form_sprite = new QFormLayout();
|
||||
this->combo_sprite = new NoScrollComboBox(this);
|
||||
this->combo_sprite->setToolTip("The sprite graphics to use for this object.");
|
||||
static const QString combo_sprite_toolTip = Util::toHtmlParagraph("The sprite graphics to use for this object.");
|
||||
this->combo_sprite->setToolTip(combo_sprite_toolTip);
|
||||
l_form_sprite->addRow("Sprite", this->combo_sprite);
|
||||
this->layout_contents->addLayout(l_form_sprite);
|
||||
|
||||
// movement
|
||||
QFormLayout *l_form_movement = new QFormLayout();
|
||||
this->combo_movement = new NoScrollComboBox(this);
|
||||
this->combo_movement->setToolTip("The object's natural movement behavior when\n"
|
||||
"the player is not interacting with it.");
|
||||
static const QString combo_movement_toolTip = Util::toHtmlParagraph("The object's natural movement behavior when the player is not interacting with it.");
|
||||
this->combo_movement->setToolTip(combo_movement_toolTip);
|
||||
l_form_movement->addRow("Movement", this->combo_movement);
|
||||
this->layout_contents->addLayout(l_form_movement);
|
||||
|
||||
@@ -226,15 +258,15 @@ void ObjectFrame::setup() {
|
||||
this->spinner_radius_x = new NoScrollSpinBox(this);
|
||||
this->spinner_radius_x->setMinimum(0);
|
||||
this->spinner_radius_x->setMaximum(255);
|
||||
this->spinner_radius_x->setToolTip("The maximum number of metatiles this object\n"
|
||||
"is allowed to move left or right during its\n"
|
||||
"normal movement behavior actions.");
|
||||
static const QString spinner_radius_x_toolTip = Util::toHtmlParagraph("The maximum number of metatiles this object is allowed to move left "
|
||||
"or right during its normal movement behavior actions.");
|
||||
this->spinner_radius_x->setToolTip(spinner_radius_x_toolTip);
|
||||
this->spinner_radius_y = new NoScrollSpinBox(this);
|
||||
this->spinner_radius_y->setMinimum(0);
|
||||
this->spinner_radius_y->setMaximum(255);
|
||||
this->spinner_radius_y->setToolTip("The maximum number of metatiles this object\n"
|
||||
"is allowed to move up or down during its\n"
|
||||
"normal movement behavior actions.");
|
||||
static const QString spinner_radius_y_toolTip = Util::toHtmlParagraph("The maximum number of metatiles this object is allowed to move up "
|
||||
"or down during its normal movement behavior actions.");
|
||||
this->spinner_radius_y->setToolTip(spinner_radius_y_toolTip);
|
||||
l_form_radii_xy->addRow("Movement Radius X", this->spinner_radius_x);
|
||||
l_form_radii_xy->addRow("Movement Radius Y", this->spinner_radius_y);
|
||||
this->layout_contents->addLayout(l_form_radii_xy);
|
||||
@@ -242,11 +274,13 @@ void ObjectFrame::setup() {
|
||||
// script
|
||||
QFormLayout *l_form_script = new QFormLayout();
|
||||
this->combo_script = new NoScrollComboBox(this);
|
||||
this->combo_script->setToolTip("The script which is executed with this event.");
|
||||
static const QString combo_script_toolTip = Util::toHtmlParagraph("The script that is executed with this event.");
|
||||
this->combo_script->setToolTip(combo_script_toolTip);
|
||||
|
||||
// Add button next to combo which opens combo's current script.
|
||||
this->button_script = new QToolButton(this);
|
||||
this->button_script->setToolTip("Go to this script definition in text editor.");
|
||||
static const QString button_script_toolTip = Util::toHtmlParagraph("Go to this script definition in text editor.");
|
||||
this->button_script->setToolTip(button_script_toolTip);
|
||||
this->button_script->setFixedSize(this->combo_script->height(), this->combo_script->height());
|
||||
this->button_script->setIcon(QFileIconProvider().icon(QFileIconProvider::File));
|
||||
|
||||
@@ -261,24 +295,25 @@ void ObjectFrame::setup() {
|
||||
// event flag
|
||||
QFormLayout *l_form_flag = new QFormLayout();
|
||||
this->combo_flag = new NoScrollComboBox(this);
|
||||
this->combo_flag->setToolTip("The flag which hides the object when set.");
|
||||
static const QString combo_flag_toolTip = Util::toHtmlParagraph("The flag that hides the object when set.");
|
||||
this->combo_flag->setToolTip(combo_flag_toolTip);
|
||||
l_form_flag->addRow("Event Flag", this->combo_flag);
|
||||
this->layout_contents->addLayout(l_form_flag);
|
||||
|
||||
// trainer type
|
||||
QFormLayout *l_form_trainer = new QFormLayout();
|
||||
this->combo_trainer_type = new NoScrollComboBox(this);
|
||||
this->combo_trainer_type->setToolTip("The trainer type of this object event.\n"
|
||||
"If it is not a trainer, use NONE. SEE ALL DIRECTIONS\n"
|
||||
"should only be used with a sight radius of 1.");
|
||||
static const QString combo_trainer_type_toolTip = Util::toHtmlParagraph("The trainer type of this object event. If it is not a trainer, use NONE. "
|
||||
"SEE ALL DIRECTIONS should only be used with a sight radius of 1.");
|
||||
this->combo_trainer_type->setToolTip(combo_trainer_type_toolTip);
|
||||
l_form_trainer->addRow("Trainer Type", this->combo_trainer_type);
|
||||
this->layout_contents->addLayout(l_form_trainer);
|
||||
|
||||
// sight radius / berry tree id
|
||||
QFormLayout *l_form_radius_treeid = new QFormLayout();
|
||||
this->combo_radius_treeid = new NoScrollComboBox(this);
|
||||
this->combo_radius_treeid->setToolTip("The maximum sight range of a trainer,\n"
|
||||
"OR the unique id of the berry tree.");
|
||||
static const QString combo_radius_treeid_toolTip = Util::toHtmlParagraph("The maximum sight range of a trainer, OR the unique id of the berry tree.");
|
||||
this->combo_radius_treeid->setToolTip(combo_radius_treeid_toolTip);
|
||||
l_form_radius_treeid->addRow("Sight Radius / Berry Tree ID", this->combo_radius_treeid);
|
||||
this->layout_contents->addLayout(l_form_radius_treeid);
|
||||
|
||||
@@ -290,21 +325,29 @@ void ObjectFrame::connectSignals(MainWindow *window) {
|
||||
if (this->connected) return;
|
||||
|
||||
EventFrame::connectSignals(window);
|
||||
Project *project = window->editor->project;
|
||||
|
||||
// local id
|
||||
this->line_edit_local_id->disconnect();
|
||||
connect(this->line_edit_local_id, &QLineEdit::textChanged, [this](const QString &text) {
|
||||
this->object->setIdName(text);
|
||||
this->object->modify();
|
||||
});
|
||||
|
||||
// sprite update
|
||||
this->combo_sprite->disconnect();
|
||||
connect(this->combo_sprite, &QComboBox::currentTextChanged, [this](const QString &text) {
|
||||
connect(this->combo_sprite, &QComboBox::currentTextChanged, [this, project](const QString &text) {
|
||||
this->object->setGfx(text);
|
||||
this->object->getPixmapItem()->updatePixmap();
|
||||
this->object->getPixmapItem()->render(project);
|
||||
this->object->modify();
|
||||
});
|
||||
connect(this->object->getPixmapItem(), &DraggablePixmapItem::spriteChanged, this->label_icon, &QLabel::setPixmap);
|
||||
connect(this->object->getPixmapItem(), &EventPixmapItem::rendered, this->label_icon, &QLabel::setPixmap);
|
||||
|
||||
// movement
|
||||
this->combo_movement->disconnect();
|
||||
connect(this->combo_movement, &QComboBox::currentTextChanged, [this](const QString &text) {
|
||||
connect(this->combo_movement, &QComboBox::currentTextChanged, [this, project](const QString &text) {
|
||||
this->object->setMovement(text);
|
||||
this->object->getPixmapItem()->updatePixmap();
|
||||
this->object->getPixmapItem()->render(project);
|
||||
this->object->modify();
|
||||
});
|
||||
|
||||
@@ -362,6 +405,9 @@ void ObjectFrame::initialize() {
|
||||
const QSignalBlocker blocker(this);
|
||||
EventFrame::initialize();
|
||||
|
||||
// local id
|
||||
this->line_edit_local_id->setText(this->object->getIdName());
|
||||
|
||||
// sprite
|
||||
this->combo_sprite->setTextItem(this->object->getGfx());
|
||||
|
||||
@@ -393,12 +439,11 @@ void ObjectFrame::populate(Project *project) {
|
||||
const QSignalBlocker blocker(this);
|
||||
EventFrame::populate(project);
|
||||
|
||||
this->combo_sprite->addItems(project->gfxDefines.keys());
|
||||
this->combo_movement->addItems(project->movementTypes);
|
||||
this->combo_flag->addItems(project->flagNames);
|
||||
this->combo_trainer_type->addItems(project->trainerTypes);
|
||||
|
||||
this->populateScriptDropdown(this->combo_script, project);
|
||||
populateDropdown(this->combo_sprite, project->gfxDefines.keys());
|
||||
populateDropdown(this->combo_movement, project->movementTypes);
|
||||
populateDropdown(this->combo_flag, project->flagNames);
|
||||
populateDropdown(this->combo_trainer_type, project->trainerTypes);
|
||||
populateScriptDropdown(this->combo_script, project);
|
||||
}
|
||||
|
||||
|
||||
@@ -406,13 +451,25 @@ void ObjectFrame::populate(Project *project) {
|
||||
void CloneObjectFrame::setup() {
|
||||
EventFrame::setup();
|
||||
|
||||
this->label_id->setText("Clone Object");
|
||||
|
||||
this->spinner_z->setEnabled(false);
|
||||
|
||||
// local id
|
||||
QFormLayout *l_form_local_id = new QFormLayout();
|
||||
this->line_edit_local_id = new QLineEdit(this);
|
||||
static const QString line_edit_local_id_toolTip = Util::toHtmlParagraph("An optional, unique name to use to refer to this object in scripts. "
|
||||
"If no name is given you can refer to this object using its 'object id' number.");
|
||||
this->line_edit_local_id->setToolTip(line_edit_local_id_toolTip);
|
||||
this->line_edit_local_id->setPlaceholderText("LOCALID_MY_CLONE_NPC");
|
||||
l_form_local_id->addRow("Local ID", this->line_edit_local_id);
|
||||
this->layout_contents->addLayout(l_form_local_id);
|
||||
|
||||
// sprite combo (edits disabled)
|
||||
QFormLayout *l_form_sprite = new QFormLayout();
|
||||
this->combo_sprite = new NoScrollComboBox(this);
|
||||
static const QString combo_sprite_toolTip = Util::toHtmlParagraph("The sprite graphics to use for this object. This is updated automatically "
|
||||
"to match the target object, and so can't be edited. By default the games "
|
||||
"will get the graphics directly from the target object, so this field is ignored.");
|
||||
this->combo_sprite->setToolTip(combo_sprite_toolTip);
|
||||
l_form_sprite->addRow("Sprite", this->combo_sprite);
|
||||
this->combo_sprite->setEnabled(false);
|
||||
this->layout_contents->addLayout(l_form_sprite);
|
||||
@@ -420,15 +477,17 @@ void CloneObjectFrame::setup() {
|
||||
// clone map id combo
|
||||
QFormLayout *l_form_dest_map = new QFormLayout();
|
||||
this->combo_target_map = new NoScrollComboBox(this);
|
||||
this->combo_target_map->setToolTip("The name of the map that the object being cloned is on.");
|
||||
static const QString combo_target_map_toolTip = Util::toHtmlParagraph("The name of the map that the object being cloned is on.");
|
||||
this->combo_target_map->setToolTip(combo_target_map_toolTip);
|
||||
l_form_dest_map->addRow("Target Map", this->combo_target_map);
|
||||
this->layout_contents->addLayout(l_form_dest_map);
|
||||
|
||||
// clone local id spinbox
|
||||
// clone local id combo
|
||||
QFormLayout *l_form_dest_id = new QFormLayout();
|
||||
this->spinner_target_id = new NoScrollSpinBox(this);
|
||||
this->spinner_target_id->setToolTip("event_object ID of the object being cloned.");
|
||||
l_form_dest_id->addRow("Target Local ID", this->spinner_target_id);
|
||||
this->combo_target_id = new NoScrollComboBox(this);
|
||||
static const QString combo_target_id_toolTip = Util::toHtmlParagraph("The Local ID name or number of the object being cloned.");
|
||||
this->combo_target_id->setToolTip(combo_target_id_toolTip);
|
||||
l_form_dest_id->addRow("Target Local ID", this->combo_target_id);
|
||||
this->layout_contents->addLayout(l_form_dest_id);
|
||||
|
||||
// custom attributes
|
||||
@@ -439,27 +498,48 @@ void CloneObjectFrame::connectSignals(MainWindow *window) {
|
||||
if (this->connected) return;
|
||||
|
||||
EventFrame::connectSignals(window);
|
||||
Project *project = window->editor->project;
|
||||
|
||||
// local id
|
||||
this->line_edit_local_id->disconnect();
|
||||
connect(this->line_edit_local_id, &QLineEdit::textChanged, [this](const QString &text) {
|
||||
this->clone->setIdName(text);
|
||||
this->clone->modify();
|
||||
});
|
||||
|
||||
// update icon displayed in frame with target
|
||||
connect(this->clone->getPixmapItem(), &DraggablePixmapItem::spriteChanged, this->label_icon, &QLabel::setPixmap);
|
||||
connect(this->clone->getPixmapItem(), &EventPixmapItem::rendered, this->label_icon, &QLabel::setPixmap);
|
||||
|
||||
// target map
|
||||
this->combo_target_map->disconnect();
|
||||
connect(this->combo_target_map, &QComboBox::currentTextChanged, [this](const QString &text) {
|
||||
this->clone->setTargetMap(text);
|
||||
this->clone->getPixmapItem()->updatePixmap();
|
||||
connect(this->combo_target_map, &QComboBox::currentTextChanged, [this, project](const QString &mapName) {
|
||||
this->clone->setTargetMap(mapName);
|
||||
this->clone->getPixmapItem()->render(project);
|
||||
this->combo_sprite->setCurrentText(this->clone->getGfx());
|
||||
this->clone->modify();
|
||||
populateIdNameDropdown(this->combo_target_id, project, mapName, Event::Group::Object);
|
||||
});
|
||||
connect(window, &MainWindow::mapOpened, this, &CloneObjectFrame::tryInvalidateIdDropdown, Qt::UniqueConnection);
|
||||
|
||||
// target id
|
||||
this->combo_target_id->disconnect();
|
||||
connect(this->combo_target_id, &QComboBox::currentTextChanged, [this, project](const QString &text) {
|
||||
this->clone->setTargetID(text);
|
||||
this->clone->getPixmapItem()->render(project);
|
||||
this->combo_sprite->setCurrentText(this->clone->getGfx());
|
||||
this->clone->modify();
|
||||
});
|
||||
|
||||
// target id
|
||||
this->spinner_target_id->disconnect();
|
||||
connect(this->spinner_target_id, QOverload<int>::of(&QSpinBox::valueChanged), [this](int value) {
|
||||
this->clone->setTargetID(value);
|
||||
this->clone->getPixmapItem()->updatePixmap();
|
||||
this->combo_sprite->setCurrentText(this->clone->getGfx());
|
||||
this->clone->modify();
|
||||
});
|
||||
// This frame type displays map names, so when a new map is created we need to repopulate it.
|
||||
connect(project, &Project::mapCreated, this, &EventFrame::invalidateValues, Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
void CloneObjectFrame::tryInvalidateIdDropdown(Map *map) {
|
||||
// If the clone's target map is opened then the names in this frame's ID dropdown may be changed.
|
||||
// Make sure we update the frame next time it's opened.
|
||||
if (map && this->clone && map->name() == this->clone->getTargetMap()) {
|
||||
invalidateValues();
|
||||
}
|
||||
}
|
||||
|
||||
void CloneObjectFrame::initialize() {
|
||||
@@ -468,13 +548,14 @@ void CloneObjectFrame::initialize() {
|
||||
const QSignalBlocker blocker(this);
|
||||
EventFrame::initialize();
|
||||
|
||||
// local id
|
||||
this->line_edit_local_id->setText(this->clone->getIdName());
|
||||
|
||||
// sprite
|
||||
this->combo_sprite->setCurrentText(this->clone->getGfx());
|
||||
|
||||
// target id
|
||||
this->spinner_target_id->setMinimum(1);
|
||||
this->spinner_target_id->setMaximum(126);
|
||||
this->spinner_target_id->setValue(this->clone->getTargetID());
|
||||
this->combo_target_id->setCurrentText(this->clone->getTargetID());
|
||||
|
||||
// target map
|
||||
this->combo_target_map->setTextItem(this->clone->getTargetMap());
|
||||
@@ -486,32 +567,41 @@ void CloneObjectFrame::populate(Project *project) {
|
||||
const QSignalBlocker blocker(this);
|
||||
EventFrame::populate(project);
|
||||
|
||||
this->combo_target_map->addItems(project->mapNames);
|
||||
populateDropdown(this->combo_target_map, project->mapNames);
|
||||
populateIdNameDropdown(this->combo_target_id, project, this->clone->getTargetMap(), Event::Group::Object);
|
||||
}
|
||||
|
||||
void WarpFrame::setup() {
|
||||
EventFrame::setup();
|
||||
|
||||
this->label_id->setText("Warp");
|
||||
// ID
|
||||
QFormLayout *l_form_id = new QFormLayout();
|
||||
this->line_edit_id = new QLineEdit(this);
|
||||
static const QString line_edit_id_toolTip = Util::toHtmlParagraph("An optional, unique name to use to refer to this warp from other warps. "
|
||||
"If no name is given you can refer to this warp using its 'warp id' number.");
|
||||
this->line_edit_id->setToolTip(line_edit_id_toolTip);
|
||||
this->line_edit_id->setPlaceholderText("WARP_ID_MY_WARP");
|
||||
l_form_id->addRow("ID", this->line_edit_id);
|
||||
this->layout_contents->addLayout(l_form_id);
|
||||
|
||||
// desination map combo
|
||||
QFormLayout *l_form_dest_map = new QFormLayout();
|
||||
this->combo_dest_map = new NoScrollComboBox(this);
|
||||
this->combo_dest_map->setToolTip("The destination map name of the warp.");
|
||||
static const QString combo_dest_map_toolTip = Util::toHtmlParagraph("The destination map name of the warp.");
|
||||
this->combo_dest_map->setToolTip(combo_dest_map_toolTip);
|
||||
l_form_dest_map->addRow("Destination Map", this->combo_dest_map);
|
||||
this->layout_contents->addLayout(l_form_dest_map);
|
||||
|
||||
// desination warp id
|
||||
QFormLayout *l_form_dest_warp = new QFormLayout();
|
||||
this->combo_dest_warp = new NoScrollComboBox(this);
|
||||
this->combo_dest_warp->setToolTip("The warp id on the destination map.");
|
||||
static const QString combo_dest_warp_toolTip = Util::toHtmlParagraph("The warp id on the destination map.");
|
||||
this->combo_dest_warp->setToolTip(combo_dest_warp_toolTip);
|
||||
l_form_dest_warp->addRow("Destination Warp", this->combo_dest_warp);
|
||||
this->layout_contents->addLayout(l_form_dest_warp);
|
||||
|
||||
// warning
|
||||
static const QString warningText = "Warning:\n"
|
||||
"This warp event is not positioned on a metatile with a warp behavior.\n"
|
||||
"Click this warning for more details.";
|
||||
auto warningText = QStringLiteral("Warning:\nThis warp event is not positioned on a metatile with a warp behavior.\nClick this warning for more details.");
|
||||
QVBoxLayout *l_vbox_warning = new QVBoxLayout();
|
||||
this->warning = new QPushButton(warningText, this);
|
||||
this->warning->setFlat(true);
|
||||
@@ -528,13 +618,23 @@ void WarpFrame::connectSignals(MainWindow *window) {
|
||||
if (this->connected) return;
|
||||
|
||||
EventFrame::connectSignals(window);
|
||||
Project *project = window->editor->project;
|
||||
|
||||
// id
|
||||
this->line_edit_id->disconnect();
|
||||
connect(this->line_edit_id, &QLineEdit::textChanged, [this](const QString &text) {
|
||||
this->warp->setIdName(text);
|
||||
this->warp->modify();
|
||||
});
|
||||
|
||||
// dest map
|
||||
this->combo_dest_map->disconnect();
|
||||
connect(this->combo_dest_map, &QComboBox::currentTextChanged, [this](const QString &text) {
|
||||
this->warp->setDestinationMap(text);
|
||||
connect(this->combo_dest_map, &QComboBox::currentTextChanged, [this, project](const QString &mapName) {
|
||||
this->warp->setDestinationMap(mapName);
|
||||
this->warp->modify();
|
||||
populateIdNameDropdown(this->combo_dest_warp, project, mapName, Event::Group::Warp);
|
||||
});
|
||||
connect(window, &MainWindow::mapOpened, this, &WarpFrame::tryInvalidateIdDropdown, Qt::UniqueConnection);
|
||||
|
||||
// dest id
|
||||
this->combo_dest_warp->disconnect();
|
||||
@@ -546,6 +646,17 @@ void WarpFrame::connectSignals(MainWindow *window) {
|
||||
// warning
|
||||
this->warning->disconnect();
|
||||
connect(this->warning, &QPushButton::clicked, window, &MainWindow::onWarpBehaviorWarningClicked);
|
||||
|
||||
// This frame type displays map names, so when a new map is created we need to repopulate it.
|
||||
connect(project, &Project::mapCreated, this, &EventFrame::invalidateValues, Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
void WarpFrame::tryInvalidateIdDropdown(Map *map) {
|
||||
// If the warps's target map is opened then the names in this frame's ID dropdown may be changed.
|
||||
// Make sure we update the frame next time it's opened.
|
||||
if (map && this->warp && map->name() == this->warp->getDestinationMap()) {
|
||||
invalidateValues();
|
||||
}
|
||||
}
|
||||
|
||||
void WarpFrame::initialize() {
|
||||
@@ -554,6 +665,9 @@ void WarpFrame::initialize() {
|
||||
const QSignalBlocker blocker(this);
|
||||
EventFrame::initialize();
|
||||
|
||||
// id
|
||||
this->line_edit_id->setText(this->warp->getIdName());
|
||||
|
||||
// dest map
|
||||
this->combo_dest_map->setTextItem(this->warp->getDestinationMap());
|
||||
|
||||
@@ -567,7 +681,8 @@ void WarpFrame::populate(Project *project) {
|
||||
const QSignalBlocker blocker(this);
|
||||
EventFrame::populate(project);
|
||||
|
||||
this->combo_dest_map->addItems(project->mapNames);
|
||||
populateDropdown(this->combo_dest_map, project->mapNames);
|
||||
populateIdNameDropdown(this->combo_dest_warp, project, this->warp->getDestinationMap(), Event::Group::Warp);
|
||||
}
|
||||
|
||||
|
||||
@@ -575,27 +690,28 @@ void WarpFrame::populate(Project *project) {
|
||||
void TriggerFrame::setup() {
|
||||
EventFrame::setup();
|
||||
|
||||
this->label_id->setText("Trigger");
|
||||
|
||||
// script combo
|
||||
QFormLayout *l_form_script = new QFormLayout();
|
||||
this->combo_script = new NoScrollComboBox(this);
|
||||
this->combo_script->setToolTip("The script which is executed with this event.");
|
||||
static const QString combo_script_toolTip = Util::toHtmlParagraph("The script that is executed with this event.");
|
||||
this->combo_script->setToolTip(combo_script_toolTip);
|
||||
l_form_script->addRow("Script", this->combo_script);
|
||||
this->layout_contents->addLayout(l_form_script);
|
||||
|
||||
// var combo
|
||||
QFormLayout *l_form_var = new QFormLayout();
|
||||
this->combo_var = new NoScrollComboBox(this);
|
||||
this->combo_var->setToolTip("The variable by which the script is triggered.\n"
|
||||
"The script is triggered when this variable's value matches 'Var Value'.");
|
||||
static const QString combo_var_toolTip = Util::toHtmlParagraph("The variable by which the script is triggered. "
|
||||
"The script is triggered when this variable's value matches 'Var Value'.");
|
||||
this->combo_var->setToolTip(combo_var_toolTip);
|
||||
l_form_var->addRow("Var", this->combo_var);
|
||||
this->layout_contents->addLayout(l_form_var);
|
||||
|
||||
// var value combo
|
||||
QFormLayout *l_form_var_val = new QFormLayout();
|
||||
this->combo_var_value = new NoScrollComboBox(this);
|
||||
this->combo_var_value->setToolTip("The variable's value which triggers the script.");
|
||||
static const QString combo_var_value_toolTip = Util::toHtmlParagraph("The variable's value that triggers the script.");
|
||||
this->combo_var_value->setToolTip(combo_var_value_toolTip);
|
||||
l_form_var_val->addRow("Var Value", this->combo_var_value);
|
||||
this->layout_contents->addLayout(l_form_var_val);
|
||||
|
||||
@@ -652,10 +768,8 @@ void TriggerFrame::populate(Project *project) {
|
||||
const QSignalBlocker blocker(this);
|
||||
EventFrame::populate(project);
|
||||
|
||||
// var combo
|
||||
this->combo_var->addItems(project->varNames);
|
||||
|
||||
this->populateScriptDropdown(this->combo_script, project);
|
||||
populateDropdown(this->combo_var, project->varNames);
|
||||
populateScriptDropdown(this->combo_script, project);
|
||||
}
|
||||
|
||||
|
||||
@@ -663,12 +777,11 @@ void TriggerFrame::populate(Project *project) {
|
||||
void WeatherTriggerFrame::setup() {
|
||||
EventFrame::setup();
|
||||
|
||||
this->label_id->setText("Weather Trigger");
|
||||
|
||||
// weather combo
|
||||
QFormLayout *l_form_weather = new QFormLayout();
|
||||
this->combo_weather = new NoScrollComboBox(this);
|
||||
this->combo_weather->setToolTip("The weather that starts when the player steps on this spot.");
|
||||
static const QString combo_weather_toolTip = Util::toHtmlParagraph("The weather that starts when the player steps on this spot.");
|
||||
this->combo_weather->setToolTip(combo_weather_toolTip);
|
||||
l_form_weather->addRow("Weather", this->combo_weather);
|
||||
this->layout_contents->addLayout(l_form_weather);
|
||||
|
||||
@@ -705,8 +818,7 @@ void WeatherTriggerFrame::populate(Project *project) {
|
||||
const QSignalBlocker blocker(this);
|
||||
EventFrame::populate(project);
|
||||
|
||||
// weather
|
||||
this->combo_weather->addItems(project->coordEventWeatherNames);
|
||||
populateDropdown(this->combo_weather, project->coordEventWeatherNames);
|
||||
}
|
||||
|
||||
|
||||
@@ -714,20 +826,19 @@ void WeatherTriggerFrame::populate(Project *project) {
|
||||
void SignFrame::setup() {
|
||||
EventFrame::setup();
|
||||
|
||||
this->label_id->setText("Sign");
|
||||
|
||||
// facing dir combo
|
||||
QFormLayout *l_form_facing_dir = new QFormLayout();
|
||||
this->combo_facing_dir = new NoScrollComboBox(this);
|
||||
this->combo_facing_dir->setToolTip("The direction which the player must be facing\n"
|
||||
"to be able to interact with this event.");
|
||||
static const QString combo_facing_dir_toolTip = Util::toHtmlParagraph("The direction that the player must be facing to be able to interact with this event.");
|
||||
this->combo_facing_dir->setToolTip(combo_facing_dir_toolTip);
|
||||
l_form_facing_dir->addRow("Player Facing Direction", this->combo_facing_dir);
|
||||
this->layout_contents->addLayout(l_form_facing_dir);
|
||||
|
||||
// script combo
|
||||
QFormLayout *l_form_script = new QFormLayout();
|
||||
this->combo_script = new NoScrollComboBox(this);
|
||||
this->combo_script->setToolTip("The script which is executed with this event.");
|
||||
static const QString combo_script_toolTip = Util::toHtmlParagraph("The script that is executed with this event.");
|
||||
this->combo_script->setToolTip(combo_script_toolTip);
|
||||
l_form_script->addRow("Script", this->combo_script);
|
||||
this->layout_contents->addLayout(l_form_script);
|
||||
|
||||
@@ -774,10 +885,8 @@ void SignFrame::populate(Project *project) {
|
||||
const QSignalBlocker blocker(this);
|
||||
EventFrame::populate(project);
|
||||
|
||||
// facing dir
|
||||
this->combo_facing_dir->addItems(project->bgEventFacingDirections);
|
||||
|
||||
this->populateScriptDropdown(this->combo_script, project);
|
||||
populateDropdown(this->combo_facing_dir, project->bgEventFacingDirections);
|
||||
populateScriptDropdown(this->combo_script, project);
|
||||
}
|
||||
|
||||
|
||||
@@ -785,19 +894,19 @@ void SignFrame::populate(Project *project) {
|
||||
void HiddenItemFrame::setup() {
|
||||
EventFrame::setup();
|
||||
|
||||
this->label_id->setText("Hidden Item");
|
||||
|
||||
// item combo
|
||||
QFormLayout *l_form_item = new QFormLayout();
|
||||
this->combo_item = new NoScrollComboBox(this);
|
||||
this->combo_item->setToolTip("The item to be given.");
|
||||
static const QString combo_item_toolTip = Util::toHtmlParagraph("The item to be given.");
|
||||
this->combo_item->setToolTip(combo_item_toolTip);
|
||||
l_form_item->addRow("Item", this->combo_item);
|
||||
this->layout_contents->addLayout(l_form_item);
|
||||
|
||||
// flag combo
|
||||
QFormLayout *l_form_flag = new QFormLayout();
|
||||
this->combo_flag = new NoScrollComboBox(this);
|
||||
this->combo_flag->setToolTip("The flag which is set when the hidden item is picked up.");
|
||||
static const QString combo_flag_toolTip = Util::toHtmlParagraph("The flag that is set when the hidden item is picked up.");
|
||||
this->combo_flag->setToolTip(combo_flag_toolTip);
|
||||
l_form_flag->addRow("Flag", this->combo_flag);
|
||||
this->layout_contents->addLayout(l_form_flag);
|
||||
|
||||
@@ -806,7 +915,8 @@ void HiddenItemFrame::setup() {
|
||||
QFormLayout *l_form_quantity = new QFormLayout(hideable_quantity);
|
||||
l_form_quantity->setContentsMargins(0, 0, 0, 0);
|
||||
this->spinner_quantity = new NoScrollSpinBox(hideable_quantity);
|
||||
this->spinner_quantity->setToolTip("The number of items received when the hidden item is picked up.");
|
||||
static const QString spinner_quantity_toolTip = Util::toHtmlParagraph("The number of items received when the hidden item is picked up.");
|
||||
this->spinner_quantity->setToolTip(spinner_quantity_toolTip);
|
||||
this->spinner_quantity->setMinimum(0x01);
|
||||
this->spinner_quantity->setMaximum(0xFF);
|
||||
l_form_quantity->addRow("Quantity", this->spinner_quantity);
|
||||
@@ -817,7 +927,8 @@ void HiddenItemFrame::setup() {
|
||||
QFormLayout *l_form_itemfinder = new QFormLayout(hideable_itemfinder);
|
||||
l_form_itemfinder->setContentsMargins(0, 0, 0, 0);
|
||||
this->check_itemfinder = new QCheckBox(hideable_itemfinder);
|
||||
this->check_itemfinder->setToolTip("If checked, hidden item can only be picked up using the Itemfinder");
|
||||
static const QString check_itemfinder_toolTip = Util::toHtmlParagraph("If checked, hidden item can only be picked up using the Itemfinder");
|
||||
this->check_itemfinder->setToolTip(check_itemfinder_toolTip);
|
||||
l_form_itemfinder->addRow("Requires Itemfinder", this->check_itemfinder);
|
||||
this->layout_contents->addWidget(hideable_itemfinder);
|
||||
|
||||
@@ -853,8 +964,8 @@ void HiddenItemFrame::connectSignals(MainWindow *window) {
|
||||
|
||||
// underfoot
|
||||
this->check_itemfinder->disconnect();
|
||||
connect(this->check_itemfinder, &QCheckBox::stateChanged, [=](int state) {
|
||||
this->hiddenItem->setUnderfoot(state == Qt::Checked);
|
||||
connect(this->check_itemfinder, &QCheckBox::toggled, [=](bool checked) {
|
||||
this->hiddenItem->setUnderfoot(checked);
|
||||
this->hiddenItem->modify();
|
||||
});
|
||||
}
|
||||
@@ -890,8 +1001,8 @@ void HiddenItemFrame::populate(Project *project) {
|
||||
const QSignalBlocker blocker(this);
|
||||
EventFrame::populate(project);
|
||||
|
||||
this->combo_item->addItems(project->itemNames);
|
||||
this->combo_flag->addItems(project->flagNames);
|
||||
populateDropdown(this->combo_item, project->itemNames);
|
||||
populateDropdown(this->combo_flag, project->flagNames);
|
||||
}
|
||||
|
||||
|
||||
@@ -899,16 +1010,14 @@ void HiddenItemFrame::populate(Project *project) {
|
||||
void SecretBaseFrame::setup() {
|
||||
EventFrame::setup();
|
||||
|
||||
this->label_id->setText("Secret Base");
|
||||
|
||||
this->spinner_z->setEnabled(false);
|
||||
|
||||
// item combo
|
||||
QFormLayout *l_form_base_id = new QFormLayout();
|
||||
this->combo_base_id = new NoScrollComboBox(this);
|
||||
this->combo_base_id->setToolTip("The secret base id which is inside this secret\n"
|
||||
"base entrance. Secret base ids are meant to be\n"
|
||||
"unique to each and every secret base entrance.");
|
||||
static const QString combo_base_id_toolTip = Util::toHtmlParagraph("The secret base id that is inside this secret base entrance. "
|
||||
"Secret base ids are meant to be unique to each and every secret base entrance.");
|
||||
this->combo_base_id->setToolTip(combo_base_id_toolTip);
|
||||
l_form_base_id->addRow("Secret Base", this->combo_base_id);
|
||||
this->layout_contents->addLayout(l_form_base_id);
|
||||
|
||||
@@ -944,7 +1053,7 @@ void SecretBaseFrame::populate(Project *project) {
|
||||
const QSignalBlocker blocker(this);
|
||||
EventFrame::populate(project);
|
||||
|
||||
this->combo_base_id->addItems(project->secretBaseIds);
|
||||
populateDropdown(this->combo_base_id, project->secretBaseIds);
|
||||
}
|
||||
|
||||
|
||||
@@ -952,15 +1061,14 @@ void SecretBaseFrame::populate(Project *project) {
|
||||
void HealLocationFrame::setup() {
|
||||
EventFrame::setup();
|
||||
|
||||
this->label_id->setText("Heal Location");
|
||||
|
||||
this->hideable_label_z->setVisible(false);
|
||||
this->spinner_z->setVisible(false);
|
||||
|
||||
// ID
|
||||
QFormLayout *l_form_id = new QFormLayout();
|
||||
this->line_edit_id = new QLineEdit(this);
|
||||
this->line_edit_id->setToolTip("The unique identifier for this heal location.");
|
||||
static const QString line_edit_id_toolTip = Util::toHtmlParagraph("The unique identifier for this heal location.");
|
||||
this->line_edit_id->setToolTip(line_edit_id_toolTip);
|
||||
this->line_edit_id->setPlaceholderText(projectConfig.getIdentifier(ProjectIdentifier::define_heal_locations_prefix) + "MY_MAP");
|
||||
l_form_id->addRow("ID", this->line_edit_id);
|
||||
this->layout_contents->addLayout(l_form_id);
|
||||
@@ -970,7 +1078,8 @@ void HealLocationFrame::setup() {
|
||||
QFormLayout *l_form_respawn_map = new QFormLayout(hideable_respawn_map);
|
||||
l_form_respawn_map->setContentsMargins(0, 0, 0, 0);
|
||||
this->combo_respawn_map = new NoScrollComboBox(hideable_respawn_map);
|
||||
this->combo_respawn_map->setToolTip("The map where the player will respawn after whiteout.");
|
||||
static const QString combo_respawn_map_toolTip = Util::toHtmlParagraph("The map where the player will respawn after whiteout.");
|
||||
this->combo_respawn_map->setToolTip(combo_respawn_map_toolTip);
|
||||
l_form_respawn_map->addRow("Respawn Map", this->combo_respawn_map);
|
||||
this->layout_contents->addWidget(hideable_respawn_map);
|
||||
|
||||
@@ -979,8 +1088,9 @@ void HealLocationFrame::setup() {
|
||||
QFormLayout *l_form_respawn_npc = new QFormLayout(hideable_respawn_npc);
|
||||
l_form_respawn_npc->setContentsMargins(0, 0, 0, 0);
|
||||
this->combo_respawn_npc = new NoScrollComboBox(hideable_respawn_npc);
|
||||
this->combo_respawn_npc->setToolTip("event_object ID of the NPC the player interacts with\n"
|
||||
"upon respawning after whiteout.");
|
||||
static const QString combo_respawn_npc_toolTip = Util::toHtmlParagraph("The Local ID name or number of the NPC the player "
|
||||
"interacts with upon respawning after whiteout.");
|
||||
this->combo_respawn_npc->setToolTip(combo_respawn_npc_toolTip);
|
||||
l_form_respawn_npc->addRow("Respawn NPC", this->combo_respawn_npc);
|
||||
this->layout_contents->addWidget(hideable_respawn_npc);
|
||||
|
||||
@@ -992,6 +1102,7 @@ void HealLocationFrame::connectSignals(MainWindow *window) {
|
||||
if (this->connected) return;
|
||||
|
||||
EventFrame::connectSignals(window);
|
||||
Project *project = window->editor->project;
|
||||
|
||||
this->line_edit_id->disconnect();
|
||||
connect(this->line_edit_id, &QLineEdit::textChanged, [this](const QString &text) {
|
||||
@@ -1000,16 +1111,29 @@ void HealLocationFrame::connectSignals(MainWindow *window) {
|
||||
});
|
||||
|
||||
this->combo_respawn_map->disconnect();
|
||||
connect(this->combo_respawn_map, &QComboBox::currentTextChanged, [this](const QString &text) {
|
||||
this->healLocation->setRespawnMapName(text);
|
||||
connect(this->combo_respawn_map, &QComboBox::currentTextChanged, [this, project](const QString &mapName) {
|
||||
this->healLocation->setRespawnMapName(mapName);
|
||||
this->healLocation->modify();
|
||||
populateIdNameDropdown(this->combo_respawn_npc, project, mapName, Event::Group::Object);
|
||||
});
|
||||
connect(window, &MainWindow::mapOpened, this, &HealLocationFrame::tryInvalidateIdDropdown, Qt::UniqueConnection);
|
||||
|
||||
this->combo_respawn_npc->disconnect();
|
||||
connect(this->combo_respawn_npc, &QComboBox::currentTextChanged, [this](const QString &text) {
|
||||
this->healLocation->setRespawnNPC(text);
|
||||
this->healLocation->modify();
|
||||
});
|
||||
|
||||
// This frame type displays map names, so when a new map is created we need to repopulate it.
|
||||
connect(project, &Project::mapCreated, this, &EventFrame::invalidateValues, Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
void HealLocationFrame::tryInvalidateIdDropdown(Map *map) {
|
||||
// If the heal locations's target map is opened then the names in this frame's ID dropdown may be changed.
|
||||
// Make sure we update the frame next time it's opened.
|
||||
if (map && this->healLocation && map->name() == this->healLocation->getRespawnMapName()) {
|
||||
invalidateValues();
|
||||
}
|
||||
}
|
||||
|
||||
void HealLocationFrame::initialize() {
|
||||
@@ -1033,7 +1157,8 @@ void HealLocationFrame::populate(Project *project) {
|
||||
const QSignalBlocker blocker(this);
|
||||
EventFrame::populate(project);
|
||||
|
||||
this->combo_respawn_map->addItems(project->mapNames);
|
||||
// TODO: We should dynamically populate combo_respawn_npc with the local IDs of the respawn_map
|
||||
// Same for warp IDs.
|
||||
if (projectConfig.healLocationRespawnDataEnabled) {
|
||||
populateDropdown(this->combo_respawn_map, project->mapNames);
|
||||
populateIdNameDropdown(this->combo_respawn_npc, project, this->healLocation->getRespawnMapName(), Event::Group::Object);
|
||||
}
|
||||
}
|
||||
|
||||
115
src/ui/eventpixmapitem.cpp
Normal file
115
src/ui/eventpixmapitem.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
#include "eventpixmapitem.h"
|
||||
#include "project.h"
|
||||
#include "editcommands.h"
|
||||
#include "mapruler.h"
|
||||
#include "metatile.h"
|
||||
|
||||
EventPixmapItem::EventPixmapItem(Event *event)
|
||||
: QGraphicsPixmapItem(event->getPixmap()),
|
||||
m_basePixmap(pixmap()),
|
||||
m_event(event)
|
||||
{
|
||||
m_event->setPixmapItem(this);
|
||||
updatePixelPosition();
|
||||
}
|
||||
|
||||
void EventPixmapItem::render(Project *project) {
|
||||
if (!m_event)
|
||||
return;
|
||||
|
||||
m_basePixmap = m_event->loadPixmap(project);
|
||||
|
||||
// If the base pixmap changes, the event's pixel position may change.
|
||||
updatePixelPosition();
|
||||
|
||||
QPixmap pixmap = m_basePixmap;
|
||||
if (m_selected) {
|
||||
// Draw the selection rectangle
|
||||
QPainter painter(&pixmap);
|
||||
painter.setPen(Qt::magenta);
|
||||
painter.drawRect(0, 0, pixmap.width() - 1, pixmap.height() - 1);
|
||||
}
|
||||
setPixmap(pixmap);
|
||||
emit rendered(m_basePixmap);
|
||||
}
|
||||
|
||||
void EventPixmapItem::move(int dx, int dy) {
|
||||
moveTo(m_event->getX() + dx,
|
||||
m_event->getY() + dy);
|
||||
}
|
||||
|
||||
void EventPixmapItem::moveTo(const QPoint &pos) {
|
||||
moveTo(pos.x(), pos.y());
|
||||
}
|
||||
|
||||
void EventPixmapItem::moveTo(int x, int y) {
|
||||
bool changed = false;
|
||||
if (m_event->getX() != x) {
|
||||
m_event->setX(x);
|
||||
emit xChanged(x);
|
||||
changed = true;
|
||||
}
|
||||
if (m_event->getY() != y) {
|
||||
m_event->setY(y);
|
||||
emit yChanged(y);
|
||||
changed = true;
|
||||
}
|
||||
if (changed) {
|
||||
updatePixelPosition();
|
||||
emit posChanged(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
void EventPixmapItem::updatePixelPosition() {
|
||||
setPos(m_event->getPixelX(), m_event->getPixelY());
|
||||
}
|
||||
|
||||
void EventPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent) {
|
||||
if (m_active)
|
||||
return;
|
||||
m_active = true;
|
||||
m_lastPos = Metatile::coordFromPixmapCoord(mouseEvent->scenePos());
|
||||
|
||||
bool selectionToggle = mouseEvent->modifiers() & Qt::ControlModifier;
|
||||
if (selectionToggle || !m_selected) {
|
||||
// User is either toggling this selection on/off as part of a group selection,
|
||||
// or they're newly selecting just this item.
|
||||
m_selected = (selectionToggle) ? !m_selected : true;
|
||||
emit selected(m_event, selectionToggle);
|
||||
} else {
|
||||
// This item is already selected and the user isn't toggling the selection, so there are 4 possibilities:
|
||||
// 1. This is the only selected event, and the selection is pointless.
|
||||
// 2. This is the only selected event, and they want to drag the item around.
|
||||
// 3. There's a group selection, and they want to start a new selection with just this item.
|
||||
// 4. There's a group selection, and they want to drag the group around.
|
||||
// 'selectMapEvent' will immediately clear the rest of the selection, which supports #1-3 but prevents #4.
|
||||
// To support #4 we set the flag below, and we only call 'selectMapEvent' on mouse release if no move occurred.
|
||||
m_releaseSelectionQueued = true;
|
||||
}
|
||||
mouseEvent->accept();
|
||||
}
|
||||
|
||||
void EventPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) {
|
||||
if (!m_active || !m_selected)
|
||||
return;
|
||||
|
||||
QPoint pos = Metatile::coordFromPixmapCoord(mouseEvent->scenePos());
|
||||
if (pos == m_lastPos)
|
||||
return;
|
||||
|
||||
m_releaseSelectionQueued = false;
|
||||
emit dragged(m_event, m_lastPos, pos);
|
||||
m_lastPos = pos;
|
||||
}
|
||||
|
||||
void EventPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) {
|
||||
if (!m_active)
|
||||
return;
|
||||
m_active = false;
|
||||
if (m_releaseSelectionQueued) {
|
||||
m_releaseSelectionQueued = false;
|
||||
if (Metatile::coordFromPixmapCoord(mouseEvent->scenePos()) == m_lastPos)
|
||||
emit selected(m_event, false);
|
||||
}
|
||||
emit released(m_event, m_lastPos);
|
||||
}
|
||||
@@ -2,22 +2,7 @@
|
||||
#include "mapview.h"
|
||||
#include "editor.h"
|
||||
|
||||
void GraphicsView::mousePressEvent(QMouseEvent *event) {
|
||||
QGraphicsView::mousePressEvent(event);
|
||||
if (editor) {
|
||||
editor->eventsView_onMousePress(event);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphicsView::mouseMoveEvent(QMouseEvent *event) {
|
||||
QGraphicsView::mouseMoveEvent(event);
|
||||
}
|
||||
|
||||
void GraphicsView::mouseReleaseEvent(QMouseEvent *event) {
|
||||
QGraphicsView::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
void GraphicsView::moveEvent(QMoveEvent *event) {
|
||||
void MapView::moveEvent(QMoveEvent *event) {
|
||||
QGraphicsView::moveEvent(event);
|
||||
QLabel *label_MapRulerStatus = findChild<QLabel *>("label_MapRulerStatus", Qt::FindDirectChildrenOnly);
|
||||
if (label_MapRulerStatus && label_MapRulerStatus->isVisible())
|
||||
@@ -79,3 +64,12 @@ Overlay * MapView::getOverlay(int layer) {
|
||||
}
|
||||
return overlay;
|
||||
}
|
||||
|
||||
void ConnectionsView::keyPressEvent(QKeyEvent *event) {
|
||||
if (event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace) {
|
||||
emit pressedDelete();
|
||||
event->accept();
|
||||
} else {
|
||||
QGraphicsView::keyPressEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#include "ui_gridsettingsdialog.h"
|
||||
#include "gridsettings.h"
|
||||
|
||||
// TODO: Save settings in config
|
||||
|
||||
const QMap<GridSettings::Style, QString> GridSettings::styleToName = {
|
||||
{Style::Solid, "Solid"},
|
||||
{Style::LargeDashes, "Large Dashes"},
|
||||
|
||||
@@ -127,7 +127,12 @@ QImage getMetatileImage(
|
||||
color.setAlpha(0);
|
||||
tile_image.setColor(0, color.rgba());
|
||||
|
||||
metatile_painter.drawImage(origin, tile_image.mirrored(tile.xflip, tile.yflip));
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 9, 0))
|
||||
tile_image.flip(Util::getOrientation(tile.xflip, tile.yflip));
|
||||
#else
|
||||
tile_image = tile_image.mirrored(tile.xflip, tile.yflip);
|
||||
#endif
|
||||
metatile_painter.drawImage(origin, tile_image);
|
||||
}
|
||||
metatile_painter.end();
|
||||
|
||||
|
||||
@@ -714,19 +714,20 @@ void LayoutPixmapItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *) {
|
||||
}
|
||||
|
||||
void LayoutPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||
QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
|
||||
this->paint_tile_initial_x = this->straight_path_initial_x = pos.x();
|
||||
this->paint_tile_initial_y = this->straight_path_initial_y = pos.y();
|
||||
this->metatilePos = Metatile::coordFromPixmapCoord(event->pos());
|
||||
this->paint_tile_initial_x = this->straight_path_initial_x = this->metatilePos.x();
|
||||
this->paint_tile_initial_y = this->straight_path_initial_y = this->metatilePos.y();
|
||||
emit startPaint(event, this);
|
||||
emit mouseEvent(event, this);
|
||||
}
|
||||
|
||||
void LayoutPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
|
||||
QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
|
||||
if (pos != this->metatilePos) {
|
||||
this->metatilePos = pos;
|
||||
emit this->hoveredMapMetatileChanged(pos);
|
||||
}
|
||||
if (pos == this->metatilePos)
|
||||
return;
|
||||
|
||||
this->metatilePos = pos;
|
||||
emit hoveredMapMetatileChanged(pos);
|
||||
emit mouseEvent(event, this);
|
||||
}
|
||||
|
||||
|
||||
63
src/ui/loadingscreen.cpp
Normal file
63
src/ui/loadingscreen.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#include "loadingscreen.h"
|
||||
#include "aboutporymap.h"
|
||||
#include "ui_loadingscreen.h"
|
||||
#include "qgifimage.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
PorymapLoadingScreen *porysplash = nullptr;
|
||||
|
||||
|
||||
|
||||
PorymapLoadingScreen::~PorymapLoadingScreen() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
PorymapLoadingScreen::PorymapLoadingScreen(QWidget *parent) : QWidget(parent), ui(new Ui::LoadingScreen) {
|
||||
ui->setupUi(this);
|
||||
this->setWindowFlags(Qt::FramelessWindowHint);
|
||||
|
||||
this->splashImage.load(":/images/porysplash.gif");
|
||||
|
||||
connect(&this->timer, &QTimer::timeout, this, &PorymapLoadingScreen::updateFrame);
|
||||
}
|
||||
|
||||
void PorymapLoadingScreen::start() {
|
||||
static bool shownVersion = false;
|
||||
if (!shownVersion) {
|
||||
this->ui->labelVersion->setText(AboutPorymap::getVersionString());
|
||||
shownVersion = true;
|
||||
}
|
||||
|
||||
this->frame = 0;
|
||||
this->ui->labelPixmap->setPixmap(QPixmap::fromImage(this->splashImage.frame(this->frame)));
|
||||
|
||||
this->ui->labelText->setText("");
|
||||
|
||||
this->timer.start(120);
|
||||
this->show();
|
||||
}
|
||||
|
||||
void PorymapLoadingScreen::stop () {
|
||||
this->timer.stop();
|
||||
this->hide();
|
||||
}
|
||||
|
||||
void PorymapLoadingScreen::setPixmap(QPixmap pixmap) {
|
||||
if (!this->isVisible()) return;
|
||||
this->ui->labelPixmap->setPixmap(pixmap);
|
||||
}
|
||||
|
||||
void PorymapLoadingScreen::showMessage(QString text) {
|
||||
if (!this->isVisible()) return;
|
||||
this->ui->labelText->setText(text.mid(text.lastIndexOf("/") + 1));
|
||||
|
||||
QApplication::processEvents();
|
||||
}
|
||||
|
||||
void PorymapLoadingScreen::updateFrame() {
|
||||
this->frame = (this->frame + 1) % this->splashImage.frameCount();
|
||||
this->setPixmap(QPixmap::fromImage(this->splashImage.frame(this->frame)));
|
||||
|
||||
QApplication::processEvents();
|
||||
}
|
||||
@@ -20,12 +20,11 @@ MapHeaderForm::MapHeaderForm(QWidget *parent)
|
||||
connect(ui->comboBox_Weather, &QComboBox::currentTextChanged, this, &MapHeaderForm::onWeatherChanged);
|
||||
connect(ui->comboBox_Type, &QComboBox::currentTextChanged, this, &MapHeaderForm::onTypeChanged);
|
||||
connect(ui->comboBox_BattleScene, &QComboBox::currentTextChanged, this, &MapHeaderForm::onBattleSceneChanged);
|
||||
|
||||
connect(ui->checkBox_RequiresFlash, &QCheckBox::stateChanged, this, &MapHeaderForm::onRequiresFlashChanged);
|
||||
connect(ui->checkBox_ShowLocationName, &QCheckBox::stateChanged, this, &MapHeaderForm::onShowLocationNameChanged);
|
||||
connect(ui->checkBox_AllowRunning, &QCheckBox::stateChanged, this, &MapHeaderForm::onAllowRunningChanged);
|
||||
connect(ui->checkBox_AllowBiking, &QCheckBox::stateChanged, this, &MapHeaderForm::onAllowBikingChanged);
|
||||
connect(ui->checkBox_AllowEscaping, &QCheckBox::stateChanged, this, &MapHeaderForm::onAllowEscapingChanged);
|
||||
connect(ui->checkBox_RequiresFlash, &QCheckBox::toggled, this, &MapHeaderForm::onRequiresFlashChanged);
|
||||
connect(ui->checkBox_ShowLocationName, &QCheckBox::toggled, this, &MapHeaderForm::onShowLocationNameChanged);
|
||||
connect(ui->checkBox_AllowRunning, &QCheckBox::toggled, this, &MapHeaderForm::onAllowRunningChanged);
|
||||
connect(ui->checkBox_AllowBiking, &QCheckBox::toggled, this, &MapHeaderForm::onAllowBikingChanged);
|
||||
connect(ui->checkBox_AllowEscaping, &QCheckBox::toggled, this, &MapHeaderForm::onAllowEscapingChanged);
|
||||
|
||||
connect(ui->spinBox_FloorNumber, QOverload<int>::of(&QSpinBox::valueChanged), this, &MapHeaderForm::onFloorNumberChanged);
|
||||
|
||||
@@ -175,19 +174,29 @@ void MapHeaderForm::updateLocationName() {
|
||||
}
|
||||
|
||||
// Set data in UI
|
||||
void MapHeaderForm::setSong(const QString &song) { ui->comboBox_Song->setCurrentText(song); }
|
||||
void MapHeaderForm::setLocation(const QString &location) { ui->comboBox_Location->setCurrentText(location); }
|
||||
void MapHeaderForm::setLocationName(const QString &locationName) { ui->lineEdit_LocationName->setText(locationName); }
|
||||
void MapHeaderForm::setSong(const QString &song) { setText(ui->comboBox_Song, song); }
|
||||
void MapHeaderForm::setLocation(const QString &location) { setText(ui->comboBox_Location, location); }
|
||||
void MapHeaderForm::setLocationName(const QString &locationName) { setText(ui->lineEdit_LocationName, locationName); }
|
||||
void MapHeaderForm::setRequiresFlash(bool requiresFlash) { ui->checkBox_RequiresFlash->setChecked(requiresFlash); }
|
||||
void MapHeaderForm::setWeather(const QString &weather) { ui->comboBox_Weather->setCurrentText(weather); }
|
||||
void MapHeaderForm::setType(const QString &type) { ui->comboBox_Type->setCurrentText(type); }
|
||||
void MapHeaderForm::setBattleScene(const QString &battleScene) { ui->comboBox_BattleScene->setCurrentText(battleScene); }
|
||||
void MapHeaderForm::setWeather(const QString &weather) { setText(ui->comboBox_Weather, weather); }
|
||||
void MapHeaderForm::setType(const QString &type) { setText(ui->comboBox_Type, type); }
|
||||
void MapHeaderForm::setBattleScene(const QString &battleScene) { setText(ui->comboBox_BattleScene, battleScene); }
|
||||
void MapHeaderForm::setShowsLocationName(bool showsLocationName) { ui->checkBox_ShowLocationName->setChecked(showsLocationName); }
|
||||
void MapHeaderForm::setAllowsRunning(bool allowsRunning) { ui->checkBox_AllowRunning->setChecked(allowsRunning); }
|
||||
void MapHeaderForm::setAllowsBiking(bool allowsBiking) { ui->checkBox_AllowBiking->setChecked(allowsBiking); }
|
||||
void MapHeaderForm::setAllowsEscaping(bool allowsEscaping) { ui->checkBox_AllowEscaping->setChecked(allowsEscaping); }
|
||||
void MapHeaderForm::setFloorNumber(int floorNumber) { ui->spinBox_FloorNumber->setValue(floorNumber); }
|
||||
|
||||
// If we always call setText / setCurrentText the user's cursor may move to the end of the text while they're typing.
|
||||
void MapHeaderForm::setText(QComboBox *combo, const QString &text) const {
|
||||
if (combo->currentText() != text)
|
||||
combo->setCurrentText(text);
|
||||
}
|
||||
void MapHeaderForm::setText(QLineEdit *lineEdit, const QString &text) const {
|
||||
if (lineEdit->text() != text)
|
||||
lineEdit->setText(text);
|
||||
}
|
||||
|
||||
// Read data from UI
|
||||
QString MapHeaderForm::song() const { return ui->comboBox_Song->currentText(); }
|
||||
QString MapHeaderForm::location() const { return ui->comboBox_Location->currentText(); }
|
||||
@@ -207,11 +216,11 @@ void MapHeaderForm::onSongUpdated(const QString &song) { if (m_hea
|
||||
void MapHeaderForm::onWeatherChanged(const QString &weather) { if (m_header) m_header->setWeather(weather); }
|
||||
void MapHeaderForm::onTypeChanged(const QString &type) { if (m_header) m_header->setType(type); }
|
||||
void MapHeaderForm::onBattleSceneChanged(const QString &battleScene) { if (m_header) m_header->setBattleScene(battleScene); }
|
||||
void MapHeaderForm::onRequiresFlashChanged(int selected) { if (m_header) m_header->setRequiresFlash(selected == Qt::Checked); }
|
||||
void MapHeaderForm::onShowLocationNameChanged(int selected) { if (m_header) m_header->setShowsLocationName(selected == Qt::Checked); }
|
||||
void MapHeaderForm::onAllowRunningChanged(int selected) { if (m_header) m_header->setAllowsRunning(selected == Qt::Checked); }
|
||||
void MapHeaderForm::onAllowBikingChanged(int selected) { if (m_header) m_header->setAllowsBiking(selected == Qt::Checked); }
|
||||
void MapHeaderForm::onAllowEscapingChanged(int selected) { if (m_header) m_header->setAllowsEscaping(selected == Qt::Checked); }
|
||||
void MapHeaderForm::onRequiresFlashChanged(bool enabled) { if (m_header) m_header->setRequiresFlash(enabled); }
|
||||
void MapHeaderForm::onShowLocationNameChanged(bool enabled) { if (m_header) m_header->setShowsLocationName(enabled); }
|
||||
void MapHeaderForm::onAllowRunningChanged(bool enabled) { if (m_header) m_header->setAllowsRunning(enabled); }
|
||||
void MapHeaderForm::onAllowBikingChanged(bool enabled) { if (m_header) m_header->setAllowsBiking(enabled); }
|
||||
void MapHeaderForm::onAllowEscapingChanged(bool enabled) { if (m_header) m_header->setAllowsEscaping(enabled); }
|
||||
void MapHeaderForm::onFloorNumberChanged(int offset) { if (m_header) m_header->setFloorNumber(offset); }
|
||||
void MapHeaderForm::onLocationChanged(const QString &location) {
|
||||
if (m_header) m_header->setLocation(location);
|
||||
|
||||
@@ -55,10 +55,24 @@ MapImageExporter::MapImageExporter(QWidget *parent, Project *project, Map *map,
|
||||
connect(ui->pushButton_Save, &QPushButton::pressed, this, &MapImageExporter::saveImage);
|
||||
connect(ui->pushButton_Cancel, &QPushButton::pressed, this, &MapImageExporter::close);
|
||||
|
||||
// Update the map selector when the text changes.
|
||||
// We don't use QComboBox::currentTextChanged to avoid unnecessary re-rendering.
|
||||
connect(ui->comboBox_MapSelection, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &MapImageExporter::updateMapSelection);
|
||||
connect(ui->comboBox_MapSelection->lineEdit(), &QLineEdit::editingFinished, this, &MapImageExporter::updateMapSelection);
|
||||
connect(ui->comboBox_MapSelection, &NoScrollComboBox::editingFinished, this, &MapImageExporter::updateMapSelection);
|
||||
|
||||
connect(ui->checkBox_Objects, &QCheckBox::toggled, this, &MapImageExporter::setShowObjects);
|
||||
connect(ui->checkBox_Warps, &QCheckBox::toggled, this, &MapImageExporter::setShowWarps);
|
||||
connect(ui->checkBox_BGs, &QCheckBox::toggled, this, &MapImageExporter::setShowBgs);
|
||||
connect(ui->checkBox_Triggers, &QCheckBox::toggled, this, &MapImageExporter::setShowTriggers);
|
||||
connect(ui->checkBox_HealLocations, &QCheckBox::toggled, this, &MapImageExporter::setShowHealLocations);
|
||||
connect(ui->checkBox_AllEvents, &QCheckBox::toggled, this, &MapImageExporter::setShowAllEvents);
|
||||
connect(ui->checkBox_ConnectionUp, &QCheckBox::toggled, this, &MapImageExporter::setShowConnectionUp);
|
||||
connect(ui->checkBox_ConnectionDown, &QCheckBox::toggled, this, &MapImageExporter::setShowConnectionDown);
|
||||
connect(ui->checkBox_ConnectionLeft, &QCheckBox::toggled, this, &MapImageExporter::setShowConnectionLeft);
|
||||
connect(ui->checkBox_ConnectionRight, &QCheckBox::toggled, this, &MapImageExporter::setShowConnectionRight);
|
||||
connect(ui->checkBox_AllConnections, &QCheckBox::toggled, this, &MapImageExporter::setShowAllConnections);
|
||||
connect(ui->checkBox_Collision, &QCheckBox::toggled, this, &MapImageExporter::setShowCollision);
|
||||
connect(ui->checkBox_Grid, &QCheckBox::toggled, this, &MapImageExporter::setShowGrid);
|
||||
connect(ui->checkBox_Border, &QCheckBox::toggled, this, &MapImageExporter::setShowBorder);
|
||||
connect(ui->checkBox_DisablePreviewScaling, &QCheckBox::toggled, this, &MapImageExporter::setDisablePreviewScaling);
|
||||
connect(ui->checkBox_DisablePreviewUpdates, &QCheckBox::toggled, this, &MapImageExporter::setDisablePreviewUpdates);
|
||||
|
||||
ui->graphicsView_Preview->setFocus();
|
||||
}
|
||||
@@ -96,8 +110,7 @@ void MapImageExporter::setModeSpecificUi() {
|
||||
}
|
||||
|
||||
if (m_mode == ImageExporterMode::Timelapse) {
|
||||
// TODO: At the moment edit history for events (and the DraggablePixmapItem class)
|
||||
// explicitly depend on the editor and assume their map is currently open.
|
||||
// TODO: At the moment edit history for events explicitly depend on the editor and assume their map is currently open.
|
||||
// Other edit commands rely on this more subtly, like triggering API callbacks or
|
||||
// spending time rendering their layout (which can make creating timelapses very slow).
|
||||
// Until this is resolved, the selected map/layout must remain the same as in the editor.
|
||||
@@ -589,9 +602,7 @@ QPixmap MapImageExporter::getFormattedMapPixmap() {
|
||||
QMargins MapImageExporter::getMargins(const Map *map) {
|
||||
QMargins margins;
|
||||
if (m_settings.showBorder) {
|
||||
// The border may technically extend beyond BORDER_DISTANCE, but when the border is painted
|
||||
// we will be limiting it to the visible sight range.
|
||||
margins = QMargins(BORDER_DISTANCE, BORDER_DISTANCE, BORDER_DISTANCE, BORDER_DISTANCE) * 16;
|
||||
margins = m_project->getMetatileViewDistance() * 16;
|
||||
} else if (map && connectionsEnabled()) {
|
||||
for (const auto &connection : map->getConnections()) {
|
||||
const QString dir = connection->direction();
|
||||
@@ -632,15 +643,12 @@ void MapImageExporter::paintBorder(QPainter *painter, Layout *layout) {
|
||||
layout->renderBorder(true);
|
||||
|
||||
// Clip parts of the border that would be beyond player visibility.
|
||||
QRect visibleArea(0, 0, layout->getWidth() * 16, layout->getHeight() * 16);
|
||||
visibleArea += (QMargins(BORDER_DISTANCE, BORDER_DISTANCE, BORDER_DISTANCE, BORDER_DISTANCE) * 16);
|
||||
painter->save();
|
||||
painter->setClipRect(visibleArea);
|
||||
painter->setClipRect(layout->getVisibleRect());
|
||||
|
||||
int borderHorzDist = layout->getBorderDrawWidth();
|
||||
int borderVertDist = layout->getBorderDrawHeight();
|
||||
for (int y = -borderVertDist; y < layout->getHeight() + borderVertDist; y += layout->getBorderHeight())
|
||||
for (int x = -borderHorzDist; x < layout->getWidth() + borderHorzDist; x += layout->getBorderWidth()) {
|
||||
const QMargins borderMargins = layout->getBorderMargins();
|
||||
for (int y = -borderMargins.top(); y < layout->getHeight() + borderMargins.bottom(); y += layout->getBorderHeight())
|
||||
for (int x = -borderMargins.left(); x < layout->getWidth() + borderMargins.right(); x += layout->getBorderWidth()) {
|
||||
// Skip border painting if it would be fully covered by the rest of the map
|
||||
if (layout->isWithinBounds(QRect(x, y, layout->getBorderWidth(), layout->getBorderHeight())))
|
||||
continue;
|
||||
@@ -719,127 +727,123 @@ void MapImageExporter::setConnectionDirectionEnabled(const QString &dir, bool en
|
||||
}
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_Collision_stateChanged(int state) {
|
||||
m_settings.showCollision = (state == Qt::Checked);
|
||||
void MapImageExporter::setShowCollision(bool checked) {
|
||||
m_settings.showCollision = checked;
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_Grid_stateChanged(int state) {
|
||||
m_settings.showGrid = (state == Qt::Checked);
|
||||
void MapImageExporter::setShowGrid(bool checked) {
|
||||
m_settings.showGrid = checked;
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_Border_stateChanged(int state) {
|
||||
m_settings.showBorder = (state == Qt::Checked);
|
||||
void MapImageExporter::setShowBorder(bool checked) {
|
||||
m_settings.showBorder = checked;
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_Objects_stateChanged(int state) {
|
||||
setEventGroupEnabled(Event::Group::Object, state == Qt::Checked);
|
||||
void MapImageExporter::setShowObjects(bool checked) {
|
||||
setEventGroupEnabled(Event::Group::Object, checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_Warps_stateChanged(int state) {
|
||||
setEventGroupEnabled(Event::Group::Warp, state == Qt::Checked);
|
||||
void MapImageExporter::setShowWarps(bool checked) {
|
||||
setEventGroupEnabled(Event::Group::Warp, checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_BGs_stateChanged(int state) {
|
||||
setEventGroupEnabled(Event::Group::Bg, state == Qt::Checked);
|
||||
void MapImageExporter::setShowBgs(bool checked) {
|
||||
setEventGroupEnabled(Event::Group::Bg, checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_Triggers_stateChanged(int state) {
|
||||
setEventGroupEnabled(Event::Group::Coord, state == Qt::Checked);
|
||||
void MapImageExporter::setShowTriggers(bool checked) {
|
||||
setEventGroupEnabled(Event::Group::Coord, checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_HealLocations_stateChanged(int state) {
|
||||
setEventGroupEnabled(Event::Group::Heal, state == Qt::Checked);
|
||||
void MapImageExporter::setShowHealLocations(bool checked) {
|
||||
setEventGroupEnabled(Event::Group::Heal, checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
// Shortcut setting for enabling all events
|
||||
void MapImageExporter::on_checkBox_AllEvents_stateChanged(int state) {
|
||||
bool on = (state == Qt::Checked);
|
||||
|
||||
void MapImageExporter::setShowAllEvents(bool checked) {
|
||||
const QSignalBlocker b_Objects(ui->checkBox_Objects);
|
||||
ui->checkBox_Objects->setChecked(on);
|
||||
ui->checkBox_Objects->setDisabled(on);
|
||||
setEventGroupEnabled(Event::Group::Object, on);
|
||||
ui->checkBox_Objects->setChecked(checked);
|
||||
ui->checkBox_Objects->setDisabled(checked);
|
||||
setEventGroupEnabled(Event::Group::Object, checked);
|
||||
|
||||
const QSignalBlocker b_Warps(ui->checkBox_Warps);
|
||||
ui->checkBox_Warps->setChecked(on);
|
||||
ui->checkBox_Warps->setDisabled(on);
|
||||
setEventGroupEnabled(Event::Group::Warp, on);
|
||||
ui->checkBox_Warps->setChecked(checked);
|
||||
ui->checkBox_Warps->setDisabled(checked);
|
||||
setEventGroupEnabled(Event::Group::Warp, checked);
|
||||
|
||||
const QSignalBlocker b_BGs(ui->checkBox_BGs);
|
||||
ui->checkBox_BGs->setChecked(on);
|
||||
ui->checkBox_BGs->setDisabled(on);
|
||||
setEventGroupEnabled(Event::Group::Bg, on);
|
||||
ui->checkBox_BGs->setChecked(checked);
|
||||
ui->checkBox_BGs->setDisabled(checked);
|
||||
setEventGroupEnabled(Event::Group::Bg, checked);
|
||||
|
||||
const QSignalBlocker b_Triggers(ui->checkBox_Triggers);
|
||||
ui->checkBox_Triggers->setChecked(on);
|
||||
ui->checkBox_Triggers->setDisabled(on);
|
||||
setEventGroupEnabled(Event::Group::Coord, on);
|
||||
ui->checkBox_Triggers->setChecked(checked);
|
||||
ui->checkBox_Triggers->setDisabled(checked);
|
||||
setEventGroupEnabled(Event::Group::Coord, checked);
|
||||
|
||||
const QSignalBlocker b_HealLocations(ui->checkBox_HealLocations);
|
||||
ui->checkBox_HealLocations->setChecked(on);
|
||||
ui->checkBox_HealLocations->setDisabled(on);
|
||||
setEventGroupEnabled(Event::Group::Heal, on);
|
||||
ui->checkBox_HealLocations->setChecked(checked);
|
||||
ui->checkBox_HealLocations->setDisabled(checked);
|
||||
setEventGroupEnabled(Event::Group::Heal, checked);
|
||||
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_ConnectionUp_stateChanged(int state) {
|
||||
setConnectionDirectionEnabled("up", state == Qt::Checked);
|
||||
void MapImageExporter::setShowConnectionUp(bool checked) {
|
||||
setConnectionDirectionEnabled("up", checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_ConnectionDown_stateChanged(int state) {
|
||||
setConnectionDirectionEnabled("down", state == Qt::Checked);
|
||||
void MapImageExporter::setShowConnectionDown(bool checked) {
|
||||
setConnectionDirectionEnabled("down", checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_ConnectionLeft_stateChanged(int state) {
|
||||
setConnectionDirectionEnabled("left", state == Qt::Checked);
|
||||
void MapImageExporter::setShowConnectionLeft(bool checked) {
|
||||
setConnectionDirectionEnabled("left", checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_ConnectionRight_stateChanged(int state) {
|
||||
setConnectionDirectionEnabled("right", state == Qt::Checked);
|
||||
void MapImageExporter::setShowConnectionRight(bool checked) {
|
||||
setConnectionDirectionEnabled("right", checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
// Shortcut setting for enabling all connection directions
|
||||
void MapImageExporter::on_checkBox_AllConnections_stateChanged(int state) {
|
||||
bool on = (state == Qt::Checked);
|
||||
|
||||
void MapImageExporter::setShowAllConnections(bool checked) {
|
||||
const QSignalBlocker b_Up(ui->checkBox_ConnectionUp);
|
||||
ui->checkBox_ConnectionUp->setChecked(on);
|
||||
ui->checkBox_ConnectionUp->setDisabled(on);
|
||||
setConnectionDirectionEnabled("up", on);
|
||||
ui->checkBox_ConnectionUp->setChecked(checked);
|
||||
ui->checkBox_ConnectionUp->setDisabled(checked);
|
||||
setConnectionDirectionEnabled("up", checked);
|
||||
|
||||
const QSignalBlocker b_Down(ui->checkBox_ConnectionDown);
|
||||
ui->checkBox_ConnectionDown->setChecked(on);
|
||||
ui->checkBox_ConnectionDown->setDisabled(on);
|
||||
setConnectionDirectionEnabled("down", on);
|
||||
ui->checkBox_ConnectionDown->setChecked(checked);
|
||||
ui->checkBox_ConnectionDown->setDisabled(checked);
|
||||
setConnectionDirectionEnabled("down", checked);
|
||||
|
||||
const QSignalBlocker b_Left(ui->checkBox_ConnectionLeft);
|
||||
ui->checkBox_ConnectionLeft->setChecked(on);
|
||||
ui->checkBox_ConnectionLeft->setDisabled(on);
|
||||
setConnectionDirectionEnabled("left", on);
|
||||
ui->checkBox_ConnectionLeft->setChecked(checked);
|
||||
ui->checkBox_ConnectionLeft->setDisabled(checked);
|
||||
setConnectionDirectionEnabled("left", checked);
|
||||
|
||||
const QSignalBlocker b_Right(ui->checkBox_ConnectionRight);
|
||||
ui->checkBox_ConnectionRight->setChecked(on);
|
||||
ui->checkBox_ConnectionRight->setDisabled(on);
|
||||
setConnectionDirectionEnabled("right", on);
|
||||
ui->checkBox_ConnectionRight->setChecked(checked);
|
||||
ui->checkBox_ConnectionRight->setDisabled(checked);
|
||||
setConnectionDirectionEnabled("right", checked);
|
||||
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_DisablePreviewScaling_stateChanged(int state) {
|
||||
m_settings.disablePreviewScaling = (state == Qt::Checked);
|
||||
void MapImageExporter::setDisablePreviewScaling(bool checked) {
|
||||
m_settings.disablePreviewScaling = checked;
|
||||
if (m_settings.disablePreviewScaling) {
|
||||
ui->graphicsView_Preview->resetTransform();
|
||||
} else {
|
||||
@@ -847,8 +851,8 @@ void MapImageExporter::on_checkBox_DisablePreviewScaling_stateChanged(int state)
|
||||
}
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_DisablePreviewUpdates_stateChanged(int state) {
|
||||
m_settings.disablePreviewUpdates = (state == Qt::Checked);
|
||||
void MapImageExporter::setDisablePreviewUpdates(bool checked) {
|
||||
m_settings.disablePreviewUpdates = checked;
|
||||
if (m_settings.disablePreviewUpdates) {
|
||||
if (m_timelapseMovie) {
|
||||
m_timelapseMovie->stop();
|
||||
|
||||
@@ -93,7 +93,7 @@ void MapListToolBar::setEmptyFoldersVisible(bool visible) {
|
||||
}
|
||||
|
||||
// Update tool tip to reflect what will happen if the button is pressed.
|
||||
const QString toolTip = QString("%1 empty folders in the list.").arg(visible ? "Hide" : "Show");
|
||||
const QString toolTip = Util::toHtmlParagraph(QString("%1 empty folders in the list.").arg(visible ? "Hide" : "Show"));
|
||||
ui->button_ToggleEmptyFolders->setToolTip(toolTip);
|
||||
|
||||
const QSignalBlocker b(ui->button_ToggleEmptyFolders);
|
||||
@@ -121,7 +121,9 @@ void MapListToolBar::applyFilter(const QString &filterText) {
|
||||
return;
|
||||
|
||||
const QSignalBlocker b(ui->lineEdit_filterBox);
|
||||
ui->lineEdit_filterBox->setText(filterText);
|
||||
if (ui->lineEdit_filterBox->text() != filterText) {
|
||||
ui->lineEdit_filterBox->setText(filterText);
|
||||
}
|
||||
|
||||
// The clear button does not properly disappear when filterText is empty.
|
||||
// It seems like this is because blocking the QLineEdit's signals prevents
|
||||
|
||||
@@ -52,19 +52,22 @@ RecentErrorMessage::RecentErrorMessage(const QString &message, QWidget *parent)
|
||||
setDetailedText(getMostRecentError());
|
||||
}
|
||||
|
||||
int RecentErrorMessage::show(const QString &message, QWidget *parent) {
|
||||
RecentErrorMessage msgBox(message, parent);
|
||||
return msgBox.exec();
|
||||
void RecentErrorMessage::show(const QString &message, QWidget *parent) {
|
||||
auto msgBox = new RecentErrorMessage(message, parent);
|
||||
msgBox->setAttribute(Qt::WA_DeleteOnClose);
|
||||
msgBox->open();
|
||||
};
|
||||
|
||||
int ErrorMessage::show(const QString &message, QWidget *parent) {
|
||||
ErrorMessage msgBox(message, parent);
|
||||
return msgBox.exec();
|
||||
void ErrorMessage::show(const QString &message, QWidget *parent) {
|
||||
auto msgBox = new ErrorMessage(message, parent);
|
||||
msgBox->setAttribute(Qt::WA_DeleteOnClose);
|
||||
msgBox->open();
|
||||
};
|
||||
|
||||
int WarningMessage::show(const QString &message, QWidget *parent) {
|
||||
WarningMessage msgBox(message, parent);
|
||||
return msgBox.exec();
|
||||
void WarningMessage::show(const QString &message, QWidget *parent) {
|
||||
auto msgBox = new WarningMessage(message, parent);
|
||||
msgBox->setAttribute(Qt::WA_DeleteOnClose);
|
||||
msgBox->open();
|
||||
};
|
||||
|
||||
int QuestionMessage::show(const QString &message, QWidget *parent) {
|
||||
@@ -72,7 +75,8 @@ int QuestionMessage::show(const QString &message, QWidget *parent) {
|
||||
return msgBox.exec();
|
||||
};
|
||||
|
||||
int InfoMessage::show(const QString &message, QWidget *parent) {
|
||||
InfoMessage msgBox(message, parent);
|
||||
return msgBox.exec();
|
||||
void InfoMessage::show(const QString &message, QWidget *parent) {
|
||||
auto msgBox = new InfoMessage(message, parent);
|
||||
msgBox->setAttribute(Qt::WA_DeleteOnClose);
|
||||
msgBox->open();
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "config.h"
|
||||
#include "metatilelayersitem.h"
|
||||
#include "imageproviders.h"
|
||||
#include "utility.h"
|
||||
#include <QPainter>
|
||||
|
||||
static const QList<QPoint> tilePositions = {
|
||||
@@ -28,7 +29,11 @@ void MetatileLayersItem::draw() {
|
||||
for (int i = 0; i < numTiles; i++) {
|
||||
Tile tile = this->metatile->tiles.at(i);
|
||||
QImage tileImage = getPalettedTileImage(tile.tileId, this->primaryTileset, this->secondaryTileset, tile.palette, true)
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 9, 0))
|
||||
.flipped(Util::getOrientation(tile.xflip, tile.yflip))
|
||||
#else
|
||||
.mirrored(tile.xflip, tile.yflip)
|
||||
#endif
|
||||
.scaled(16, 16);
|
||||
painter.drawImage(tilePositions.at(i) * 16, tileImage);
|
||||
}
|
||||
|
||||
@@ -5,18 +5,31 @@
|
||||
#include "movablerect.h"
|
||||
#include "utility.h"
|
||||
|
||||
MovableRect::MovableRect(bool *enabled, int width, int height, QRgb color)
|
||||
: QGraphicsRectItem(0, 0, width, height)
|
||||
MovableRect::MovableRect(bool *enabled, const QRectF &rect, const QRgb &color)
|
||||
: QGraphicsRectItem(rect),
|
||||
enabled(enabled),
|
||||
baseRect(rect),
|
||||
color(color)
|
||||
{
|
||||
this->enabled = enabled;
|
||||
this->color = color;
|
||||
this->setVisible(*enabled);
|
||||
updateVisibility();
|
||||
}
|
||||
|
||||
/// 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);
|
||||
setRect(this->baseRect.x() + (x * 16),
|
||||
this->baseRect.y() + (y * 16),
|
||||
this->baseRect.width(),
|
||||
this->baseRect.height());
|
||||
updateVisibility();
|
||||
}
|
||||
|
||||
void MovableRect::setActive(bool active) {
|
||||
this->active = active;
|
||||
updateVisibility();
|
||||
}
|
||||
|
||||
void MovableRect::updateVisibility() {
|
||||
setVisible(*this->enabled && this->active);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@@ -25,9 +38,8 @@ void MovableRect::updateLocation(int x, int y) {
|
||||
|
||||
ResizableRect::ResizableRect(QObject *parent, bool *enabled, int width, int height, QRgb color)
|
||||
: QObject(parent),
|
||||
MovableRect(enabled, width * 16, height * 16, color)
|
||||
MovableRect(enabled, QRect(0, 0, width * 16, height * 16), color)
|
||||
{
|
||||
setZValue(0xFFFFFFFF); // ensure on top of view
|
||||
setAcceptHoverEvents(true);
|
||||
setFlags(this->flags() | QGraphicsItem::ItemIsMovable);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user