Merge branch 'master' of https://github.com/huderlem/porymap into commit-version

This commit is contained in:
GriffinR
2024-12-17 21:42:07 -05:00
142 changed files with 7342 additions and 8922 deletions

2
.gitignore vendored
View File

@@ -8,9 +8,11 @@ porymap.app*
porymap
porymap.cfg
porymap.log
build/
# Qt generated files
ui_*.h
moc_*.h
moc_*.cpp
qrc_*.cpp
.qtc_clangd

View File

@@ -9,10 +9,14 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
## [Unreleased]
### Added
- Redesigned the Connections tab, adding a number of new features including the option to open or display diving maps and a list UI for easier edit access.
- Add the ability to edit layouts with no corresponding map.
- Add a `Close Project` option
- Add charts to the `Wild Pokémon` tab that show species and level distributions.
- Add options for customizing the map grid under `View -> Grid Settings`.
- An alert will be displayed when attempting to open a seemingly invalid project.
- Add support for defining project values with `enum` where `#define` was expected.
- Add button to enable editing map groups including renaming groups and rearranging the maps within them.
- Add buttons to hide and show empty folders in each map tree view.
### Changed
- Edits to map connections now have Undo/Redo and can be viewed in exported timelapses.
@@ -22,6 +26,8 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
- 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` now shows a preview of the full image, not just the current map.
- Maps and layouts were internally separated.
### Fixed
- Fix `Add Region Map...` not updating the region map settings file.
@@ -45,6 +51,16 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
- Fix the map list filter retaining text between project open/close.
- Fix the map list mishandling value gaps when sorting by Area.
- Fix a freeze on startup if project values are defined with mismatched parentheses.
- Fix stitched map images sometimes rendering garbage
- Fix the `Reset` button on `Export Map Timelapse Image` not resetting the Timelapse settings.
- Stop sliders in the Palette Editor from creating a bunch of edit history when used.
- Fix scrolling on some containers locking up when the mouse stops over a spin box or combo box.
- Fix some file dialogs returning to an incorrect window when closed.
- Fix bug where reloading a layout would overwrite all unsaved changes.
- Fix bug where layout json and blockdata could be saved separately leading to inconsistent data.
- Fix crash when saving tilesets with fewer palettes than the maximum.
- Fix projects not opening on Windows if the project filepath contains certain characters.
- Fix exported tile images containing garbage pixels after the end of the tiles.
## [5.4.1] - 2024-03-21
### Fixed

View File

@@ -39,3 +39,14 @@ qmake
make
./porymap
```
## Arch Linux
You need to install Qt. You can check the version of your Qt packages with `qtdiag` or `qmake --version`.
```bash
sudo pacman -S qt6-declarative qt6-charts
qmake
make
./porymap
```

View File

@@ -59,7 +59,6 @@ The filepath that Porymap expects for each file can be overridden on the ``Files
include/constants/event_object_movement.h, yes, no, ``constants_obj_event_movement``,
include/constants/event_objects.h, yes, no, ``constants_obj_events``,
include/constants/event_bg.h, yes, no, ``constants_event_bg``,
include/constants/region_map_sections.h, yes, no, ``constants_region_map_sections``,
include/constants/metatile_labels.h, yes, yes, ``constants_metatile_labels``,
include/constants/metatile_behaviors.h, yes, no, ``constants_metatile_behaviors``,
include/constants/species.h, yes, no, ``constants_metatile_behaviors``, for the Wild Pokémon tab
@@ -122,7 +121,6 @@ In addition to these files, there are some specific symbol and macro names that
``define_map_empty``, ``UNDEFINED``, macro name after prefix for empty maps
``define_map_section_prefix``, ``MAPSEC_``, expected prefix for location macro names
``define_map_section_empty``, ``NONE``, macro name after prefix for empty region map sections
``define_map_section_count``, ``COUNT``, macro name after prefix for total number of region map sections
``define_species_prefix``, ``SPECIES_``, expected prefix for species macro names
``regex_behaviors``, ``\bMB_``, regex to find metatile behavior macro names
``regex_obj_event_gfx``, ``\bOBJ_EVENT_GFX_``, regex to find Object Event graphics ID macro names

310
forms/colorinputwidget.ui Normal file
View File

@@ -0,0 +1,310 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ColorInputWidget</class>
<widget class="QGroupBox" name="ColorInputWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>221</width>
<height>212</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" colspan="2">
<widget class="QFrame" name="frame_InputMain">
<property name="frameShape">
<enum>QFrame::Shape::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
</property>
<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>
<item>
<widget class="QFrame" name="frame_Labels">
<property name="frameShape">
<enum>QFrame::Shape::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<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>
<widget class="QLabel" name="label_Red">
<property name="text">
<string>Red</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_Green">
<property name="text">
<string>Green</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_Blue">
<property name="text">
<string>Blue</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_Sliders">
<property name="frameShape">
<enum>QFrame::Shape::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<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>
<widget class="QSlider" name="slider_Red">
<property name="maximum">
<number>31</number>
</property>
<property name="pageStep">
<number>4</number>
</property>
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="slider_Green">
<property name="maximum">
<number>31</number>
</property>
<property name="pageStep">
<number>4</number>
</property>
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="slider_Blue">
<property name="maximum">
<number>31</number>
</property>
<property name="pageStep">
<number>4</number>
</property>
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_SpinBoxes">
<property name="frameShape">
<enum>QFrame::Shape::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<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>
<widget class="QSpinBox" name="spinBox_Red">
<property name="maximum">
<number>255</number>
</property>
<property name="singleStep">
<number>8</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBox_Green">
<property name="maximum">
<number>255</number>
</property>
<property name="singleStep">
<number>8</number>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBox_Blue">
<property name="maximum">
<number>255</number>
</property>
<property name="singleStep">
<number>8</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QFrame" name="frame_ColorDisplay">
<property name="minimumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="1">
<widget class="QFrame" name="frame_InputTop">
<property name="frameShape">
<enum>QFrame::Shape::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_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>
<item row="0" column="0">
<widget class="QFrame" name="frame_Hex">
<property name="frameShape">
<enum>QFrame::Shape::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
</property>
<layout class="QFormLayout" name="formLayout_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>
<item row="0" column="0">
<widget class="QLabel" name="label_Hex">
<property name="text">
<string>#</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineEdit_Hex"/>
</item>
</layout>
</widget>
</item>
<item row="0" column="1">
<widget class="QToolButton" name="button_Eyedrop">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../resources/images.qrc">
<normaloff>:/icons/pipette.ico</normaloff>:/icons/pipette.ico</iconset>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../resources/images.qrc"/>
</resources>
<connections/>
</ui>

View File

@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>540</width>
<width>582</width>
<height>355</height>
</rect>
</property>
@@ -33,21 +33,30 @@
<item>
<widget class="QFrame" name="window">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
<enum>QFrame::Shape::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
<enum>QFrame::Shadow::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QFrame" name="header">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
<enum>QFrame::Shape::StyledPanel</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item>
<widget class="QPushButton" name="button_CreateNewScript">
<property name="toolTip">
@@ -91,9 +100,9 @@
</widget>
</item>
<item>
<spacer name="horizontalSpacer_header">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@@ -103,35 +112,33 @@
</property>
</spacer>
</item>
<item>
<spacer name="horizontalSpacer_header">
<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>
<widget class="QToolButton" name="button_Help">
<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>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="label_Manual">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://huderlem.github.io/porymap/manual/scripting-capabilities.html&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0069d9;&quot;&gt;Help&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_ListHeader">
<property name="text">
@@ -142,32 +149,32 @@
<item>
<widget class="QListWidget" name="list">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
<set>QAbstractItemView::EditTrigger::NoEditTriggers</set>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DragOnly</enum>
<enum>QAbstractItemView::DragDropMode::DragOnly</enum>
</property>
<property name="defaultDropAction">
<enum>Qt::IgnoreAction</enum>
<enum>Qt::DropAction::IgnoreAction</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
<enum>QAbstractItemView::SelectionMode::ExtendedSelection</enum>
</property>
<property name="textElideMode">
<enum>Qt::ElideLeft</enum>
<enum>Qt::TextElideMode::ElideLeft</enum>
</property>
<property name="movement">
<enum>QListView::Free</enum>
<enum>QListView::Movement::Free</enum>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
</property>
</widget>
</item>

275
forms/gridsettingsdialog.ui Normal file
View File

@@ -0,0 +1,275 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GridSettingsDialog</class>
<widget class="QDialog" name="GridSettingsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>331</width>
<height>467</height>
</rect>
</property>
<property name="windowTitle">
<string>Grid Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>305</width>
<height>401</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="4" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_Color">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Color</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="NoScrollComboBox" name="comboBox_Style">
<property name="editable">
<bool>false</bool>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::SizeAdjustPolicy::AdjustToContentsOnFirstShow</enum>
</property>
<property name="minimumContentsLength">
<number>0</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_Style">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Style</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox_Dimensions">
<property name="title">
<string>Dimensions (in pixels)</string>
</property>
<layout class="QGridLayout" name="gridLayout_2" columnstretch="1,1,5">
<item row="0" column="0" rowspan="2">
<widget class="QToolButton" name="button_LinkDimensions">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../resources/images.qrc">
<normaloff>:/icons/link_broken.ico</normaloff>
<normalon>:/icons/link.ico</normalon>:/icons/link_broken.ico</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="popupMode">
<enum>QToolButton::ToolButtonPopupMode::InstantPopup</enum>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="NoScrollSpinBox" name="spinBox_Height">
<property name="minimum">
<number>2</number>
</property>
<property name="maximum">
<number>999</number>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_Height">
<property name="text">
<string>Height</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_Width">
<property name="text">
<string>Width</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="NoScrollSpinBox" name="spinBox_Width">
<property name="minimum">
<number>2</number>
</property>
<property name="maximum">
<number>999</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox_Offset">
<property name="title">
<string>Offset (in pixels)</string>
</property>
<layout class="QGridLayout" name="gridLayout_3" columnstretch="1,1,5">
<item row="1" column="1">
<widget class="QLabel" name="label_Y">
<property name="text">
<string>Y</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_X">
<property name="text">
<string>X</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="NoScrollSpinBox" name="spinBox_Y">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>999</number>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="NoScrollSpinBox" name="spinBox_X">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>999</number>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="2">
<widget class="QToolButton" name="button_LinkOffsets">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../resources/images.qrc">
<normaloff>:/icons/link_broken.ico</normaloff>
<normalon>:/icons/link.ico</normalon>:/icons/link_broken.ico</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="popupMode">
<enum>QToolButton::ToolButtonPopupMode::InstantPopup</enum>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="1">
<widget class="ColorInputWidget" name="colorInput">
<property name="title">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
</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|QDialogButtonBox::StandardButton::RestoreDefaults</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>NoScrollSpinBox</class>
<extends>QSpinBox</extends>
<header>noscrollspinbox.h</header>
</customwidget>
<customwidget>
<class>NoScrollComboBox</class>
<extends>QComboBox</extends>
<header>noscrollcombobox.h</header>
</customwidget>
<customwidget>
<class>ColorInputWidget</class>
<extends>QGroupBox</extends>
<header>colorinputwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../resources/images.qrc"/>
</resources>
<connections/>
</ui>

File diff suppressed because it is too large Load Diff

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>696</width>
<height>396</height>
<width>817</width>
<height>535</height>
</rect>
</property>
<property name="windowTitle">
@@ -16,15 +16,313 @@
<property name="sizeGripEnabled">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<layout class="QGridLayout" name="gridLayout_4" columnstretch="2,1">
<item row="1" column="1">
<widget class="QFrame" name="frame_Options">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout_Options">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Map</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="NoScrollComboBox" name="comboBox_MapSelection">
<property name="sizeAdjustPolicy">
<enum>QComboBox::SizeAdjustPolicy::AdjustToContents</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBox_Events">
<property name="title">
<string>Events</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_Event_Options">
<item row="1" column="1">
<widget class="QCheckBox" name="checkBox_Triggers">
<property name="text">
<string>Triggers</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="checkBox_Objects">
<property name="text">
<string>Objects</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="checkBox_HealLocations">
<property name="text">
<string>Heal Locations</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="checkBox_Warps">
<property name="text">
<string>Warps</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="checkBox_AllEvents">
<property name="text">
<string>All</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox_BGs">
<property name="text">
<string>BGs</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_Connections">
<property name="title">
<string>Connections</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_Connection_Options">
<item row="1" column="2">
<widget class="QCheckBox" name="checkBox_ConnectionLeft">
<property name="text">
<string>Left</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox_ConnectionUp">
<property name="text">
<string>Up</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QCheckBox" name="checkBox_ConnectionRight">
<property name="text">
<string>Right</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="checkBox_ConnectionDown">
<property name="text">
<string>Down</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="checkBox_AllConnections">
<property name="text">
<string>All</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_Misc">
<property name="title">
<string>Miscellaneous</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_Misc_Options">
<item row="0" column="0">
<widget class="QCheckBox" name="checkBox_Grid">
<property name="text">
<string>Grid</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox_Elevation">
<property name="text">
<string>Collision</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="checkBox_Border">
<property name="text">
<string>Border</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_Timelapse">
<property name="title">
<string>Timelapse</string>
</property>
<layout class="QGridLayout" name="gridLayout_7">
<item row="2" column="1">
<widget class="QSpinBox" name="spinBox_TimelapseDelay">
<property name="specialValueText">
<string/>
</property>
<property name="suffix">
<string>ms</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>2000</number>
</property>
<property name="value">
<number>200</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Frame Delay</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="spinBox_FrameSkip">
<property name="suffix">
<string/>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>999</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Edit Frame Skip</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="checkBox_ActualSize">
<property name="text">
<string>Preview actual size</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="pushButton_Reset">
<property name="text">
<string>Reset</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<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>
<widget class="QPushButton" name="pushButton_Cancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_Save">
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox_Preview">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Preview</string>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="QScrollArea" name="scrollArea">
<widget class="QScrollArea" name="scrollArea_Preview">
<property name="widgetResizable">
<bool>true</bool>
</property>
@@ -33,12 +331,24 @@
<rect>
<x>0</x>
<y>0</y>
<width>403</width>
<height>343</height>
<width>469</width>
<height>464</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="4">
<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="2" column="3">
<widget class="QGraphicsView" name="graphicsView_Preview">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
@@ -53,65 +363,13 @@
<bool>false</bool>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustIgnored</enum>
<enum>QAbstractScrollArea::SizeAdjustPolicy::AdjustIgnored</enum>
</property>
<property name="dragMode">
<enum>QGraphicsView::NoDrag</enum>
<enum>QGraphicsView::DragMode::NoDrag</enum>
</property>
</widget>
</item>
<item row="4" column="4">
<spacer name="verticalSpacer_South">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>100</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="4">
<spacer name="verticalSpacer_North">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>100</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="5">
<spacer name="horizontalSpacer_West">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>100</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0">
<spacer name="horizontalSpacer_East">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>100</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
@@ -119,256 +377,18 @@
</layout>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_Options">
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Map</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="NoScrollComboBox" name="comboBox_MapSelection">
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBox_Events">
<property name="title">
<string>Events</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_Event_Options">
<item row="0" column="1">
<widget class="QCheckBox" name="checkBox_Warps">
<property name="text">
<string>Warps</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="checkBox_Objects">
<property name="text">
<string>Objects</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="checkBox_BGs">
<property name="text">
<string>BGs</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox_Triggers">
<property name="text">
<string>Triggers</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="checkBox_HealSpots">
<property name="text">
<string>Heal Spots</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_Connections">
<property name="title">
<string>Connections</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_Connection_Options">
<item row="0" column="0">
<widget class="QCheckBox" name="checkBox_ConnectionUp">
<property name="text">
<string>Up</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="checkBox_ConnectionDown">
<property name="text">
<string>Down</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="checkBox_ConnectionLeft">
<property name="text">
<string>Left</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QCheckBox" name="checkBox_ConnectionRight">
<property name="text">
<string>Right</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_Misc">
<property name="title">
<string>Miscellaneous</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_Misc_Options">
<item row="0" column="0">
<widget class="QCheckBox" name="checkBox_Grid">
<property name="text">
<string>Grid</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="checkBox_Elevation">
<property name="text">
<string>Collision</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="checkBox_Border">
<property name="text">
<string>Border</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_Timelapse">
<property name="title">
<string>Timelapse</string>
</property>
<layout class="QGridLayout" name="gridLayout_7">
<item row="2" column="1">
<widget class="QSpinBox" name="spinBox_TimelapseDelay">
<property name="specialValueText">
<string/>
</property>
<property name="suffix">
<string>ms</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>2000</number>
</property>
<property name="value">
<number>200</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Frame Delay</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="spinBox_FrameSkip">
<property name="suffix">
<string/>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>999</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Edit Frame Skip</string>
</property>
</widget>
</item>
</layout>
</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>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="pushButton_Reset">
<property name="text">
<string>Reset</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButton_Cancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_Save">
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_Description">
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>

175
forms/maplisttoolbar.ui Normal file
View File

@@ -0,0 +1,175 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MapListToolBar</class>
<widget class="QFrame" name="MapListToolBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>274</width>
<height>32</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QToolButton" name="button_AddFolder">
<property name="toolTip">
<string>Add a new folder to the list.</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources/images.qrc">
<normaloff>:/icons/folder_add.ico</normaloff>:/icons/folder_add.ico</iconset>
</property>
<property name="popupMode">
<enum>QToolButton::ToolButtonPopupMode::InstantPopup</enum>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="button_ToggleEmptyFolders">
<property name="text">
<string>Hide empty folders in the list.</string>
</property>
<property name="icon">
<iconset resource="../resources/images.qrc">
<normaloff>:/icons/folder_eye_open.ico</normaloff>
<normalon>:/icons/folder_eye_closed.ico</normalon>:/icons/folder_eye_open.ico</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="popupMode">
<enum>QToolButton::ToolButtonPopupMode::InstantPopup</enum>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="button_ExpandAll">
<property name="toolTip">
<string>Expand all folders in the list.</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources/images.qrc">
<normaloff>:/icons/expand_all.ico</normaloff>:/icons/expand_all.ico</iconset>
</property>
<property name="popupMode">
<enum>QToolButton::ToolButtonPopupMode::InstantPopup</enum>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="button_CollapseAll">
<property name="toolTip">
<string>Collapse all folders in the list.</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources/images.qrc">
<normaloff>:/icons/collapse_all.ico</normaloff>:/icons/collapse_all.ico</iconset>
</property>
<property name="popupMode">
<enum>QToolButton::ToolButtonPopupMode::InstantPopup</enum>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<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>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources/images.qrc">
<normaloff>:/icons/lock_edit.ico</normaloff>
<normalon>:/icons/unlock_edit.ico</normalon>:/icons/lock_edit.ico</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="popupMode">
<enum>QToolButton::ToolButtonPopupMode::InstantPopup</enum>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>12</width>
<height>19</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLineEdit" name="lineEdit_filterBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string/>
</property>
<property name="placeholderText">
<string>Filter...</string>
</property>
<property name="clearButtonEnabled">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../resources/images.qrc"/>
</resources>
<connections/>
</ui>

View File

@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>410</width>
<height>621</height>
<height>687</height>
</rect>
</property>
<property name="windowTitle">
@@ -73,14 +73,14 @@
</property>
</widget>
</item>
<item row="2" column="0">
<item row="4" column="0">
<widget class="QLabel" name="label_NewMap_Width">
<property name="text">
<string>Map Width</string>
</property>
</widget>
</item>
<item row="2" column="1">
<item row="4" column="1">
<widget class="QSpinBox" name="spinBox_NewMap_Width">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Width (in blocks) of the new map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -90,14 +90,14 @@
</property>
</widget>
</item>
<item row="3" column="0">
<item row="5" column="0">
<widget class="QLabel" name="label_NewMap_Height">
<property name="text">
<string>Map Height</string>
</property>
</widget>
</item>
<item row="3" column="1">
<item row="5" column="1">
<widget class="QSpinBox" name="spinBox_NewMap_Height">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Height (in blocks) of the new map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -107,14 +107,14 @@
</property>
</widget>
</item>
<item row="4" column="0">
<item row="6" column="0">
<widget class="QLabel" name="label_NewMap_BorderWidth">
<property name="text">
<string>Border Width</string>
</property>
</widget>
</item>
<item row="4" column="1">
<item row="6" column="1">
<widget class="QSpinBox" name="spinBox_NewMap_BorderWidth">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Width (in blocks) of the new map's border.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -124,14 +124,14 @@
</property>
</widget>
</item>
<item row="5" column="0">
<item row="7" column="0">
<widget class="QLabel" name="label_NewMap_BorderHeight">
<property name="text">
<string>Border Height</string>
</property>
</widget>
</item>
<item row="5" column="1">
<item row="7" column="1">
<widget class="QSpinBox" name="spinBox_NewMap_BorderHeight">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Height (in blocks) of the new map's border.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -141,14 +141,14 @@
</property>
</widget>
</item>
<item row="6" column="0">
<item row="8" column="0">
<widget class="QLabel" name="label_NewMap_Primary_Tileset">
<property name="text">
<string>Primary Tileset</string>
</property>
</widget>
</item>
<item row="6" column="1">
<item row="8" column="1">
<widget class="NoScrollComboBox" name="comboBox_NewMap_Primary_Tileset">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The primary tileset for the new map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -158,14 +158,14 @@
</property>
</widget>
</item>
<item row="7" column="0">
<item row="9" column="0">
<widget class="QLabel" name="label_NewMap_Secondary_Tileset">
<property name="text">
<string>Secondary Tileset</string>
</property>
</widget>
</item>
<item row="7" column="1">
<item row="9" column="1">
<widget class="NoScrollComboBox" name="comboBox_NewMap_Secondary_Tileset">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The secondary tileset for the new map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -175,14 +175,14 @@
</property>
</widget>
</item>
<item row="8" column="0">
<item row="10" column="0">
<widget class="QLabel" name="label_NewMap_Type">
<property name="text">
<string>Type</string>
</property>
</widget>
</item>
<item row="8" column="1">
<item row="10" column="1">
<widget class="NoScrollComboBox" name="comboBox_NewMap_Type">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The map type is a general attribute, which is used for many different things. For example. it determines whether biking or running is allowed.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -192,14 +192,14 @@
</property>
</widget>
</item>
<item row="9" column="0">
<item row="11" column="0">
<widget class="QLabel" name="label_NewMap_Location">
<property name="text">
<string>Location</string>
</property>
</widget>
</item>
<item row="9" column="1">
<item row="11" column="1">
<widget class="NoScrollComboBox" name="comboBox_NewMap_Location">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The section of the region map which the map is grouped under. This also determines the name of the map that is displayed when the player enters it.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -209,14 +209,14 @@
</property>
</widget>
</item>
<item row="10" column="0">
<item row="12" column="0">
<widget class="QLabel" name="label_Song">
<property name="text">
<string>Song</string>
</property>
</widget>
</item>
<item row="10" column="1">
<item row="12" column="1">
<widget class="NoScrollComboBox" name="comboBox_NewMap_Song">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The default background music for this map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -226,14 +226,14 @@
</property>
</widget>
</item>
<item row="11" column="0">
<item row="13" column="0">
<widget class="QLabel" name="label_NewMap_Flyable">
<property name="text">
<string>Can Fly To</string>
</property>
</widget>
</item>
<item row="11" column="1">
<item row="13" column="1">
<widget class="QCheckBox" name="checkBox_NewMap_Flyable">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Whether to add a heal location to the new map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -243,14 +243,14 @@
</property>
</widget>
</item>
<item row="12" column="0">
<item row="14" column="0">
<widget class="QLabel" name="label_NewMap_Show_Location">
<property name="text">
<string>Show Location Name</string>
</property>
</widget>
</item>
<item row="12" column="1">
<item row="14" column="1">
<widget class="QCheckBox" name="checkBox_NewMap_Show_Location">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Whether or not to display the location name when the player enters the map.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -260,14 +260,14 @@
</property>
</widget>
</item>
<item row="13" column="0">
<item row="15" column="0">
<widget class="QLabel" name="label_NewMap_Allow_Running">
<property name="text">
<string>Allow Running</string>
</property>
</widget>
</item>
<item row="13" column="1">
<item row="15" column="1">
<widget class="QCheckBox" name="checkBox_NewMap_Allow_Running">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Allows the player to use Running Shoes&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -277,14 +277,14 @@
</property>
</widget>
</item>
<item row="14" column="0">
<item row="16" column="0">
<widget class="QLabel" name="label_NewMap_Allow_Biking">
<property name="text">
<string>Allow Biking</string>
</property>
</widget>
</item>
<item row="14" column="1">
<item row="16" column="1">
<widget class="QCheckBox" name="checkBox_NewMap_Allow_Biking">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Allows the player to use a Bike&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -294,14 +294,14 @@
</property>
</widget>
</item>
<item row="15" column="0">
<item row="17" column="0">
<widget class="QLabel" name="label_NewMap_Allow_Escape_Rope">
<property name="text">
<string>Allow Dig &amp; Escape Rope</string>
</property>
</widget>
</item>
<item row="15" column="1">
<item row="17" column="1">
<widget class="QCheckBox" name="checkBox_NewMap_Allow_Escape_Rope">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Allows the player to use Dig or Escape Rope&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -311,14 +311,14 @@
</property>
</widget>
</item>
<item row="16" column="0">
<item row="18" column="0">
<widget class="QLabel" name="label_NewMap_Floor_Number">
<property name="text">
<string>Floor Number</string>
</property>
</widget>
</item>
<item row="16" column="1">
<item row="18" column="1">
<widget class="QSpinBox" name="spinBox_NewMap_Floor_Number">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Floor number to be used for maps with elevators.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@@ -328,6 +328,96 @@
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="NoScrollComboBox" name="comboBox_Layout">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Layout</string>
</property>
</widget>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Use Existing Layout</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="checkBox_UseExistingLayout">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<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>
<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>
</item>
</layout>
</widget>
</item>
@@ -396,7 +486,7 @@
<x>0</x>
<y>0</y>
<width>410</width>
<height>21</height>
<height>22</height>
</rect>
</property>
</widget>

File diff suppressed because it is too large Load Diff

View File

@@ -125,7 +125,7 @@
<item row="1" column="6">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@@ -194,10 +194,10 @@
<item row="1" column="3">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Maximum</enum>
<enum>QSizePolicy::Policy::Maximum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@@ -276,10 +276,10 @@
<string notr="true">.QFrame { border: 1px solid red; }</string>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
<enum>QFrame::Shape::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
<enum>QFrame::Shadow::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
@@ -287,7 +287,6 @@
<property name="font">
<font>
<pointsize>12</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
@@ -319,7 +318,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>
@@ -338,7 +337,7 @@
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@@ -567,10 +566,10 @@
<string notr="true">.QFrame { border: 1px solid red; }</string>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
<enum>QFrame::Shape::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
<enum>QFrame::Shadow::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_18">
<item>
@@ -578,7 +577,6 @@
<property name="font">
<font>
<pointsize>12</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
@@ -693,7 +691,7 @@
<item row="0" column="2">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@@ -712,7 +710,7 @@
<item>
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@@ -783,10 +781,10 @@
<string notr="true">.QFrame { border: 1px solid red; }</string>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
<enum>QFrame::Shape::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
<enum>QFrame::Shadow::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_13">
<item>
@@ -794,7 +792,6 @@
<property name="font">
<font>
<pointsize>12</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
@@ -839,10 +836,10 @@
<item row="1" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Maximum</enum>
<enum>QSizePolicy::Policy::Maximum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@@ -924,10 +921,10 @@
<item row="9" column="0">
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::MinimumExpanding</enum>
<enum>QSizePolicy::Policy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@@ -975,7 +972,7 @@
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@@ -1212,7 +1209,7 @@
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::NoTextInteraction</set>
<set>Qt::TextInteractionFlag::NoTextInteraction</set>
</property>
<property name="placeholderText">
<string>Use the dropbown and buttons to add behaviors to the list...</string>
@@ -1242,10 +1239,10 @@
<string notr="true">.QFrame { border: 1px solid red; }</string>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
<enum>QFrame::Shape::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
<enum>QFrame::Shadow::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_15">
<item>
@@ -1253,7 +1250,6 @@
<property name="font">
<font>
<pointsize>12</pointsize>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
@@ -1316,7 +1312,7 @@
<item row="0" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@@ -1335,7 +1331,7 @@
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
@@ -1372,18 +1368,13 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_10">
<item>
<widget class="QLabel" name="label_ProjectFilesHelp">
<widget class="QToolButton" name="button_HelpFiles">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://huderlem.github.io/porymap/manual/project-files.html#files&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0069d9;&quot;&gt;Help&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>...</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="alignment">
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
<property name="openExternalLinks">
<bool>true</bool>
<property name="icon">
<iconset resource="../resources/images.qrc">
<normaloff>:/icons/help.ico</normaloff>:/icons/help.ico</iconset>
</property>
</widget>
</item>
@@ -1419,7 +1410,7 @@
<x>0</x>
<y>0</y>
<width>533</width>
<height>440</height>
<height>428</height>
</rect>
</property>
<layout class="QFormLayout" name="layout_ProjectPaths">
@@ -1466,18 +1457,13 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout_19">
<item>
<widget class="QLabel" name="label_IdentifiersHelp">
<widget class="QToolButton" name="button_HelpIdentifiers">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://huderlem.github.io/porymap/manual/project-files.html#identifiers&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0069d9;&quot;&gt;Help&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>...</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
</property>
<property name="alignment">
<set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
</property>
<property name="openExternalLinks">
<bool>true</bool>
<property name="icon">
<iconset resource="../resources/images.qrc">
<normaloff>:/icons/help.ico</normaloff>:/icons/help.ico</iconset>
</property>
</widget>
</item>
@@ -1513,7 +1499,7 @@
<x>0</x>
<y>0</y>
<width>533</width>
<height>440</height>
<height>428</height>
</rect>
</property>
<layout class="QFormLayout" name="layout_Identifiers">
@@ -1544,7 +1530,7 @@
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults</set>
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok|QDialogButtonBox::StandardButton::RestoreDefaults</set>
</property>
</widget>
</item>

View File

@@ -22,12 +22,6 @@ static const QVersionNumber porymapVersion = QVersionNumber::fromString(PORYMAP_
#define CONFIG_BACKWARDS_COMPATABILITY
enum MapSortOrder {
Group = 0,
Area = 1,
Layout = 2,
};
class KeyValueConfigBase
{
public:
@@ -56,7 +50,7 @@ public:
this->recentProjects.clear();
this->projectManuallyClosed = false;
this->reopenOnLaunch = true;
this->mapSortOrder = MapSortOrder::Group;
this->mapListTab = 0;
this->prettyCursors = true;
this->mirrorConnectingMaps = true;
this->showDiveEmergeMaps = false;
@@ -107,7 +101,7 @@ public:
bool reopenOnLaunch;
bool projectManuallyClosed;
MapSortOrder mapSortOrder;
int mapListTab;
bool prettyCursors;
bool mirrorConnectingMaps;
bool showDiveEmergeMaps;
@@ -219,7 +213,6 @@ enum ProjectIdentifier {
define_map_empty,
define_map_section_prefix,
define_map_section_empty,
define_map_section_count,
define_species_prefix,
regex_behaviors,
regex_obj_event_gfx,
@@ -275,7 +268,6 @@ enum ProjectFilePath {
constants_obj_event_movement,
constants_obj_events,
constants_event_bg,
constants_region_map_sections,
constants_metatile_labels,
constants_metatile_behaviors,
constants_species,
@@ -406,7 +398,7 @@ public:
reset();
}
virtual void reset() override {
this->recentMap = QString();
this->recentMapOrLayout = QString();
this->useEncounterJson = true;
this->customScripts.clear();
this->readKeys.clear();
@@ -418,7 +410,7 @@ public:
QList<bool> getCustomScriptsEnabled();
QString projectDir;
QString recentMap;
QString recentMapOrLayout;
bool useEncounterJson;
protected:

View File

@@ -9,8 +9,8 @@
#include <QList>
#include <QPointer>
class MapPixmapItem;
class Map;
class Layout;
class Blockdata;
class Event;
class DraggablePixmapItem;
@@ -24,9 +24,9 @@ enum CommandId {
ID_PaintCollision,
ID_BucketFillCollision,
ID_MagicFillCollision,
ID_ResizeMap,
ID_ResizeLayout,
ID_PaintBorder,
ID_ScriptEditMap,
ID_ScriptEditLayout,
ID_EventMove,
ID_EventShift,
ID_EventCreate,
@@ -50,7 +50,7 @@ enum CommandId {
/// onto the map using the pencil tool.
class PaintMetatile : public QUndoCommand {
public:
PaintMetatile(Map *map,
PaintMetatile(Layout *layout,
const Blockdata &oldMetatiles, const Blockdata &newMetatiles,
unsigned actionId, QUndoCommand *parent = nullptr);
@@ -61,7 +61,7 @@ public:
int id() const override { return CommandId::ID_PaintMetatile; }
private:
Map *map;
Layout *layout;
Blockdata newMetatiles;
Blockdata oldMetatiles;
@@ -75,10 +75,10 @@ private:
/// on the metatile collision and elevation.
class PaintCollision : public PaintMetatile {
public:
PaintCollision(Map *map,
PaintCollision(Layout *layout,
const Blockdata &oldCollision, const Blockdata &newCollision,
unsigned actionId, QUndoCommand *parent = nullptr)
: PaintMetatile(map, oldCollision, newCollision, actionId, parent) {
: PaintMetatile(layout, oldCollision, newCollision, actionId, parent) {
setText("Paint Collision");
}
@@ -90,7 +90,7 @@ public:
/// Implements a command to commit paint actions on the map border.
class PaintBorder : public QUndoCommand {
public:
PaintBorder(Map *map,
PaintBorder(Layout *layout,
const Blockdata &oldBorder, const Blockdata &newBorder,
unsigned actionId, QUndoCommand *parent = nullptr);
@@ -101,7 +101,7 @@ public:
int id() const override { return CommandId::ID_PaintBorder; }
private:
Map *map;
Layout *layout;
Blockdata newBorder;
Blockdata oldBorder;
@@ -115,10 +115,10 @@ private:
/// with the bucket tool onto the map.
class BucketFillMetatile : public PaintMetatile {
public:
BucketFillMetatile(Map *map,
BucketFillMetatile(Layout *layout,
const Blockdata &oldMetatiles, const Blockdata &newMetatiles,
unsigned actionId, QUndoCommand *parent = nullptr)
: PaintMetatile(map, oldMetatiles, newMetatiles, actionId, parent) {
: PaintMetatile(layout, oldMetatiles, newMetatiles, actionId, parent) {
setText("Bucket Fill Metatiles");
}
@@ -131,10 +131,10 @@ public:
/// on the metatile collision and elevation.
class BucketFillCollision : public PaintCollision {
public:
BucketFillCollision(Map *map,
BucketFillCollision(Layout *layout,
const Blockdata &oldCollision, const Blockdata &newCollision,
QUndoCommand *parent = nullptr)
: PaintCollision(map, oldCollision, newCollision, -1, parent) {
: PaintCollision(layout, oldCollision, newCollision, -1, parent) {
setText("Flood Fill Collision");
}
@@ -148,10 +148,10 @@ public:
/// with the bucket or paint tool onto the map.
class MagicFillMetatile : public PaintMetatile {
public:
MagicFillMetatile(Map *map,
MagicFillMetatile(Layout *layout,
const Blockdata &oldMetatiles, const Blockdata &newMetatiles,
unsigned actionId, QUndoCommand *parent = nullptr)
: PaintMetatile(map, oldMetatiles, newMetatiles, actionId, parent) {
: PaintMetatile(layout, oldMetatiles, newMetatiles, actionId, parent) {
setText("Magic Fill Metatiles");
}
@@ -163,10 +163,10 @@ public:
/// Implements a command to commit magic fill collision actions.
class MagicFillCollision : public PaintCollision {
public:
MagicFillCollision(Map *map,
MagicFillCollision(Layout *layout,
const Blockdata &oldCollision, const Blockdata &newCollision,
QUndoCommand *parent = nullptr)
: PaintCollision(map, oldCollision, newCollision, -1, parent) {
: PaintCollision(layout, oldCollision, newCollision, -1, parent) {
setText("Magic Fill Collision");
}
@@ -179,7 +179,7 @@ public:
/// Implements a command to commit metatile shift actions.
class ShiftMetatiles : public QUndoCommand {
public:
ShiftMetatiles(Map *map,
ShiftMetatiles(Layout *layout,
const Blockdata &oldMetatiles, const Blockdata &newMetatiles,
unsigned actionId, QUndoCommand *parent = nullptr);
@@ -190,7 +190,7 @@ public:
int id() const override { return CommandId::ID_ShiftMetatiles; }
private:
Map *map;
Layout *layout= nullptr;
Blockdata newMetatiles;
Blockdata oldMetatiles;
@@ -201,9 +201,9 @@ private:
/// Implements a command to commit a map or border resize action.
class ResizeMap : public QUndoCommand {
class ResizeLayout : public QUndoCommand {
public:
ResizeMap(Map *map, QSize oldMapDimensions, QSize newMapDimensions,
ResizeLayout(Layout *layout, QSize oldLayoutDimensions, QSize newLayoutDimensions,
const Blockdata &oldMetatiles, const Blockdata &newMetatiles,
QSize oldBorderDimensions, QSize newBorderDimensions,
const Blockdata &oldBorder, const Blockdata &newBorder,
@@ -213,15 +213,15 @@ public:
void redo() override;
bool mergeWith(const QUndoCommand *) override { return false; }
int id() const override { return CommandId::ID_ResizeMap; }
int id() const override { return CommandId::ID_ResizeLayout; }
private:
Map *map;
Layout *layout = nullptr;
int oldMapWidth;
int oldMapHeight;
int newMapWidth;
int newMapHeight;
int oldLayoutWidth;
int oldLayoutHeight;
int newLayoutWidth;
int newLayoutHeight;
int oldBorderWidth;
int oldBorderHeight;
@@ -351,10 +351,10 @@ public:
/// Implements a command to commit map edits from the scripting API.
/// The scripting api can edit map/border blocks and dimensions.
class ScriptEditMap : public QUndoCommand {
class ScriptEditLayout : public QUndoCommand {
public:
ScriptEditMap(Map *map,
QSize oldMapDimensions, QSize newMapDimensions,
ScriptEditLayout(Layout *layout,
QSize oldLayoutDimensions, QSize newLayoutDimensions,
const Blockdata &oldMetatiles, const Blockdata &newMetatiles,
QSize oldBorderDimensions, QSize newBorderDimensions,
const Blockdata &oldBorder, const Blockdata &newBorder,
@@ -364,10 +364,10 @@ public:
void redo() override;
bool mergeWith(const QUndoCommand *) override { return false; }
int id() const override { return CommandId::ID_ScriptEditMap; }
int id() const override { return CommandId::ID_ScriptEditLayout; }
private:
Map *map;
Layout *layout = nullptr;
Blockdata newMetatiles;
Blockdata oldMetatiles;
@@ -375,10 +375,10 @@ private:
Blockdata newBorder;
Blockdata oldBorder;
int oldMapWidth;
int oldMapHeight;
int newMapWidth;
int newMapHeight;
int oldLayoutWidth;
int oldLayoutHeight;
int newLayoutWidth;
int newLayoutHeight;
int oldBorderWidth;
int oldBorderHeight;

View File

@@ -187,6 +187,7 @@ public:
static QString eventGroupToString(Event::Group group);
static QString eventTypeToString(Event::Type type);
static Event::Type eventTypeFromString(QString type);
static void clearIcons();
static void setIcons();
// protected attributes

65
include/core/filedialog.h Normal file
View File

@@ -0,0 +1,65 @@
#ifndef FILEDIALOG_H
#define FILEDIALOG_H
#include <QFileDialog>
/*
Static QFileDialog functions will (unless otherwise specified) use native file dialogs.
In general this is good (we want our file dialogs to be visually seamless) but unfortunately
the native file dialogs ignore the parent widget, so in some cases they'll return focus to
the main window rather than the window that opened the file dialog.
To make working around this a little easier we use this class, which will use the native
file dialog and manually return focus to the parent widget.
It will also save the directory of the previous file selected in a file dialog, and if
no 'dir' argument is specified it will open new dialogs at that directory.
*/
class FileDialog : public QFileDialog
{
public:
FileDialog(QWidget *parent, Qt::WindowFlags flags) : QFileDialog(parent, flags) {};
FileDialog(QWidget *parent = nullptr,
const QString &caption = QString(),
const QString &directory = QString(),
const QString &filter = QString()) : QFileDialog(parent, caption, directory, filter) {};
static void setDirectory(const QString &dir) { FileDialog::prevDirectory = dir; }
static QString getDirectory() { return FileDialog::prevDirectory; }
static QString getOpenFileName(QWidget *parent = nullptr,
const QString &caption = QString(),
const QString &dir = QString(),
const QString &filter = QString(),
QString *selectedFilter = nullptr,
QFileDialog::Options options = Options());
static QStringList getOpenFileNames(QWidget *parent = nullptr,
const QString &caption = QString(),
const QString &dir = QString(),
const QString &filter = QString(),
QString *selectedFilter = nullptr,
QFileDialog::Options options = Options());
static QString getExistingDirectory(QWidget *parent = nullptr,
const QString &caption = QString(),
const QString &dir = QString(),
QFileDialog::Options options = ShowDirsOnly);
static QString getSaveFileName(QWidget *parent = nullptr,
const QString &caption = QString(),
const QString &dir = QString(),
const QString &filter = QString(),
QString *selectedFilter = nullptr,
QFileDialog::Options options = Options());
private:
static QString prevDirectory;
static QString getDirectoryFromInput(const QString &dir);
static void setDirectoryFromFile(const QString &fileName);
static void restoreFocus(QWidget *parent);
};
#endif // FILEDIALOG_H

View File

@@ -25,7 +25,7 @@
// porymap will reflect changes to it, but the value is hard-coded in the projects at the moment
#define BORDER_DISTANCE 7
class MapPixmapItem;
class LayoutPixmapItem;
class CollisionPixmapItem;
class BorderMetatilesPixmapItem;
@@ -39,6 +39,7 @@ public:
public:
QString name;
QString constantName;
QString song;
QString layoutId;
QString location;
@@ -51,20 +52,22 @@ public:
bool allowEscaping;
int floorNumber = 0;
QString battle_scene;
QString sharedEventsMap = "";
QString sharedScriptsMap = "";
QStringList scriptsFileLabels;
QMap<QString, QJsonValue> customHeaders;
MapLayout *layout;
Layout *layout = nullptr;
void setLayout(Layout *layout);
bool isPersistedToFile = true;
bool hasUnsavedDataChanges = false;
bool needsLayoutDir = true;
bool needsHealLocation = false;
bool scriptsLoaded = false;
QImage collision_image;
QPixmap collision_pixmap;
QImage image;
QPixmap pixmap;
QMap<Event::Group, QList<Event *>> events;
QList<Event *> ownedEvents; // for memory management
@@ -74,64 +77,34 @@ public:
void setName(QString mapName);
static QString mapConstantFromName(QString mapName, bool includePrefix = true);
int getWidth();
int getHeight();
int getBorderWidth();
int getBorderHeight();
QPixmap render(bool ignoreCache = false, MapLayout *fromLayout = nullptr, QRect bounds = QRect(0, 0, -1, -1));
QPixmap renderCollision(bool ignoreCache);
bool mapBlockChanged(int i, const Blockdata &cache);
bool borderBlockChanged(int i, const Blockdata &cache);
void cacheBlockdata();
void cacheCollision();
bool getBlock(int x, int y, Block *out);
void setBlock(int x, int y, Block block, bool enableScriptCallback = false);
void setBlockdata(Blockdata blockdata, bool enableScriptCallback = false);
uint16_t getBorderMetatileId(int x, int y);
void setBorderMetatileId(int x, int y, uint16_t metatileId, bool enableScriptCallback = false);
void setBorderBlockData(Blockdata blockdata, bool enableScriptCallback = false);
void floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation);
void _floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation);
void magicFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation);
QList<Event *> getAllEvents() const;
QStringList getScriptLabels(Event::Group group = Event::Group::None);
QString getScriptsFilePath() const;
void openScript(QString label);
void removeEvent(Event *);
void addEvent(Event *);
void deleteConnections();
QList<MapConnection*> getConnections() const;
void removeConnection(MapConnection *);
void addConnection(MapConnection *);
void loadConnection(MapConnection *);
QRect getConnectionRect(const QString &direction, MapLayout *fromLayout = nullptr);
QPixmap renderConnection(const QString &direction, MapLayout *fromLayout = nullptr);
QPixmap renderBorder(bool ignoreCache = false);
void setDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false);
void setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false);
void clearBorderCache();
void cacheBorder();
bool hasUnsavedChanges();
bool isWithinBounds(int x, int y);
bool isWithinBorderBounds(int x, int y);
void openScript(QString label);
QString getScriptsFilePath() const;
MapPixmapItem *mapItem = nullptr;
void setMapItem(MapPixmapItem *item) { mapItem = item; }
CollisionPixmapItem *collisionItem = nullptr;
void setCollisionItem(CollisionPixmapItem *item) { collisionItem = item; }
BorderMetatilesPixmapItem *borderItem = nullptr;
void setBorderItem(BorderMetatilesPixmapItem *item) { borderItem = item; }
QRect getConnectionRect(const QString &direction, Layout *fromLayout = nullptr);
QPixmap renderConnection(const QString &direction, Layout *fromLayout = nullptr);
QUndoStack editHistory;
void modify();
void clean();
bool hasUnsavedChanges() const;
void pruneEditHistory();
private:
void setNewDimensionsBlockdata(int newWidth, int newHeight);
void setNewBorderDimensionsBlockdata(int newWidth, int newHeight);
void trackConnection(MapConnection*);
// MapConnections in 'ownedConnections' but not 'connections' persist in the edit history.
@@ -141,7 +114,6 @@ private:
signals:
void modified();
void mapDimensionsChanged(const QSize &size);
void mapNeedsRedrawing();
void openScriptRequested(QString label);
void connectionAdded(MapConnection*);
void connectionRemoved(MapConnection*);

View File

@@ -7,41 +7,135 @@
#include <QImage>
#include <QPixmap>
#include <QString>
#include <QUndoStack>
class MapLayout {
class Map;
class LayoutPixmapItem;
class CollisionPixmapItem;
class BorderMetatilesPixmapItem;
class Layout : public QObject {
Q_OBJECT
public:
MapLayout() {}
Layout() {}
static QString layoutConstantFromName(QString mapName);
bool loaded = false;
QString id;
QString name;
int width;
int height;
int border_width;
int border_height;
QString border_path;
QString blockdata_path;
QString tileset_primary_label;
QString tileset_secondary_label;
Tileset *tileset_primary = nullptr;
Tileset *tileset_secondary = nullptr;
Blockdata blockdata;
QImage image;
QPixmap pixmap;
QImage border_image;
QPixmap border_pixmap;
QImage collision_image;
QPixmap collision_pixmap;
Blockdata border;
Blockdata cached_blockdata;
Blockdata cached_collision;
Blockdata cached_border;
struct {
Blockdata blocks;
QSize mapDimensions;
QSize layoutDimensions;
Blockdata border;
QSize borderDimensions;
} lastCommitBlocks; // to track map changes
QList<int> metatileLayerOrder;
QList<float> metatileLayerOpacity;
LayoutPixmapItem *layoutItem = nullptr;
CollisionPixmapItem *collisionItem = nullptr;
BorderMetatilesPixmapItem *borderItem = nullptr;
QUndoStack editHistory;
// to simplify new layout settings transfer between functions
struct SimpleSettings {
QString id;
QString name;
int width;
int height;
QString tileset_primary_label;
QString tileset_secondary_label;
QString from_id = QString();
};
public:
Layout *copy();
void copyFrom(Layout *other);
int getWidth();
int getHeight();
int getBorderWidth();
int getBorderHeight();
bool isWithinBounds(int x, int y);
bool isWithinBorderBounds(int x, int y);
bool getBlock(int x, int y, Block *out);
void setBlock(int x, int y, Block block, bool enableScriptCallback = false);
void setBlockdata(Blockdata blockdata, bool enableScriptCallback = false);
void setDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false);
void setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata = true, bool enableScriptCallback = false);
void cacheBlockdata();
void cacheCollision();
void clearBorderCache();
void cacheBorder();
bool hasUnsavedChanges() const;
bool layoutBlockChanged(int i, const Blockdata &cache);
uint16_t getBorderMetatileId(int x, int y);
void setBorderMetatileId(int x, int y, uint16_t metatileId, bool enableScriptCallback = false);
void setBorderBlockData(Blockdata blockdata, bool enableScriptCallback = false);
void floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation);
void _floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation);
void magicFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation);
QPixmap render(bool ignoreCache = false, Layout *fromLayout = nullptr, QRect bounds = QRect(0, 0, -1, -1));
QPixmap renderCollision(bool ignoreCache);
// QPixmap renderConnection(MapConnection, Layout *);
QPixmap renderBorder(bool ignoreCache = false);
QPixmap getLayoutItemPixmap();
void setLayoutItem(LayoutPixmapItem *item) { layoutItem = item; }
void setCollisionItem(CollisionPixmapItem *item) { collisionItem = item; }
void setBorderItem(BorderMetatilesPixmapItem *item) { borderItem = item; }
private:
void setNewDimensionsBlockdata(int newWidth, int newHeight);
void setNewBorderDimensionsBlockdata(int newWidth, int newHeight);
signals:
void layoutChanged(Layout *layout);
//void modified();
void layoutDimensionsChanged(const QSize &size);
void needsRedrawing();
};
#endif // MAPLAYOUT_H

View File

@@ -10,7 +10,7 @@ class MapParser
{
public:
MapParser();
MapLayout *parse(QString filepath, bool *error, Project *project);
Layout *parse(QString filepath, bool *error, Project *project);
};
#endif // MAPPARSER_H

View File

@@ -104,7 +104,8 @@ private:
};
ParsedDefines readCDefines(const QString &filename, const QStringList &filterList, bool useRegex);
QMap<QString, int> evaluateCDefines(const QString &filename, const QStringList &filterList, bool useRegex);
bool defineNameMatchesFilter(const QString &name, const QStringList &filterList, bool useRegex);
bool defineNameMatchesFilter(const QString &name, const QStringList &filterList) const;
bool defineNameMatchesFilter(const QString &name, const QList<QRegularExpression> &filterList) const;
static const QRegularExpression re_incScriptLabel;
static const QRegularExpression re_globalIncScriptLabel;

View File

@@ -57,8 +57,8 @@ public:
bool loadLayout(poryjson::Json);
bool loadEntries();
void setEntries(tsl::ordered_map<QString, MapSectionEntry> *entries) { this->region_map_entries = entries; }
void setEntries(tsl::ordered_map<QString, MapSectionEntry> entries) { *(this->region_map_entries) = entries; }
void setEntries(QMap<QString, MapSectionEntry> *entries) { this->region_map_entries = entries; }
void setEntries(const QMap<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);
@@ -114,8 +114,6 @@ public:
void setLayer(QString layer) { this->current_layer = layer; }
QString getLayer() { return this->current_layer; }
QString fixCase(QString);
int padLeft() { return this->offset_left; }
int padTop() { return this->offset_top; }
int padRight() { return this->tilemap_width - this->layout_width - this->offset_left; }
@@ -149,14 +147,12 @@ public:
const QString section_prefix;
const QString default_map_section;
const QString count_map_section;
signals:
void mapNeedsDisplaying();
private:
// TODO: defaults needed?
tsl::ordered_map<QString, MapSectionEntry> *region_map_entries = nullptr;
QMap<QString, MapSectionEntry> *region_map_entries = nullptr;
QString alias = "";

View File

@@ -64,9 +64,9 @@ private:
/// Edit Layout Dimensions
class ResizeLayout : public QUndoCommand {
class ResizeRMLayout : public QUndoCommand {
public:
ResizeLayout(RegionMap *map, int oldWidth, int oldHeight, int newWidth, int newHeight,
ResizeRMLayout(RegionMap *map, int oldWidth, int oldHeight, int newWidth, int newHeight,
QMap<QString, QList<LayoutSquare>> oldLayouts, QMap<QString, QList<LayoutSquare>> newLayouts, QUndoCommand *parent = nullptr);
void undo() override;
@@ -153,7 +153,7 @@ private:
/// ClearEntries
class ClearEntries : public QUndoCommand {
public:
ClearEntries(RegionMap *map, tsl::ordered_map<QString, MapSectionEntry>, QUndoCommand *parent = nullptr);
ClearEntries(RegionMap *map, QMap<QString, MapSectionEntry>, QUndoCommand *parent = nullptr);
void undo() override;
void redo() override;
@@ -163,7 +163,7 @@ public:
private:
RegionMap *map;
tsl::ordered_map<QString, MapSectionEntry> entries;
QMap<QString, MapSectionEntry> entries;
};
#endif // REGIONMAPEDITCOMMANDS_H

View File

@@ -18,6 +18,7 @@ public:
Tileset() = default;
Tileset(const Tileset &other);
Tileset &operator=(const Tileset &other);
~Tileset();
public:
QString name;
@@ -33,7 +34,6 @@ public:
QStringList palettePaths;
QList<QImage> tiles;
QList<Metatile*> metatiles;
QHash<int, QString> metatileLabels;
QList<QList<QRgb>> palettes;
QList<QList<QRgb>> palettePreviews;
@@ -59,6 +59,19 @@ public:
bool appendToHeaders(QString root, QString friendlyName, bool usingAsm);
bool appendToGraphics(QString root, QString friendlyName, bool usingAsm);
bool appendToMetatiles(QString root, QString friendlyName, bool usingAsm);
void setMetatiles(const QList<Metatile*> &metatiles);
void addMetatile(Metatile* metatile);
QList<Metatile*> metatiles() const { return m_metatiles; }
Metatile* metatileAt(unsigned int i) const { return m_metatiles.at(i); }
void clearMetatiles();
void resizeMetatiles(unsigned int newNumMetatiles);
int numMetatiles() const { return m_metatiles.length(); }
private:
QList<Metatile*> m_metatiles;
};
#endif // TILESET_H

View File

@@ -8,7 +8,7 @@
struct WildPokemon {
int minLevel = 5;
int maxLevel = 5;
QString species = "SPECIES_NONE";
QString species = "SPECIES_NONE"; // TODO: Use define_species_prefix
};
struct WildMonInfo {

View File

@@ -10,6 +10,7 @@
#include <QCheckBox>
#include <QCursor>
#include <QUndoGroup>
#include <QPointer>
#include "mapconnection.h"
#include "metatileselector.h"
@@ -21,8 +22,9 @@
#include "divingmappixmapitem.h"
#include "currentselectedmetatilespixmapitem.h"
#include "collisionpixmapitem.h"
#include "mappixmapitem.h"
#include "layoutpixmapitem.h"
#include "settings.h"
#include "gridsettings.h"
#include "movablerect.h"
#include "cursortilerect.h"
#include "mapruler.h"
@@ -45,17 +47,33 @@ public:
public:
Ui::MainWindow* ui;
QObject *parent = nullptr;
QPointer<Project> project = nullptr;
Map *map = nullptr;
QPointer<Map> map = nullptr;
QPointer<Layout> layout = nullptr;
QUndoGroup editGroup; // Manages the undo history for each map
Settings *settings;
GridSettings gridSettings;
void setProject(Project * project);
void saveProject();
void save();
void closeProject();
bool setMap(QString map_name);
void saveProject();
void saveUiFields();
void saveEncounterTabData();
void closeProject();
bool setMap(QString map_name);
bool setLayout(QString layoutName);
void unsetMap();
Tileset *getCurrentMapPrimaryTileset();
bool displayMap();
bool displayLayout();
void displayMetatileSelector();
void displayMapMetatiles();
void displayMapMovementPermissions();
@@ -67,61 +85,60 @@ public:
void displayMapConnections();
void displayMapBorder();
void displayMapGrid();
void updateMapGrid();
void displayWildMonTables();
void updateMapBorder();
void updateMapConnections();
void setEditingMap();
void setEditingCollision();
void setEditingObjects();
void setEditingConnections();
void setMapEditingButtonsEnabled(bool enabled);
void setConnectionsVisibility(bool visible);
void updateDivingMapsVisibility();
void renderDivingConnections();
void addConnection(MapConnection* connection);
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);
void setSelectedConnection(MapConnection *connection);
void updatePrimaryTileset(QString tilesetLabel, bool forceLoad = false);
void updateSecondaryTileset(QString tilesetLabel, bool forceLoad = false);
void toggleBorderVisibility(bool visible, bool enableScriptCallback = true);
void updateCustomMapHeaderValues(QTableWidget *);
void configureEncounterJSON(QWidget *);
Tileset *getCurrentMapPrimaryTileset();
DraggablePixmapItem *addMapEvent(Event *event);
bool eventLimitReached(Map *, Event::Type);
void selectMapEvent(DraggablePixmapItem *object, bool toggle = false);
DraggablePixmapItem *addNewEvent(Event::Type type);
void updateSelectedEvents();
void duplicateSelectedEvents();
void redrawObject(DraggablePixmapItem *item);
QList<DraggablePixmapItem *> getObjects();
void updateCursorRectPos(int x, int y);
void setCursorRectVisible(bool visible);
void updateWarpEventWarning(Event *event);
void updateWarpEventWarnings();
bool eventLimitReached(Map *, Event::Type);
QPointer<QGraphicsScene> scene = nullptr;
QGraphicsPixmapItem *current_view = nullptr;
QPointer<MapPixmapItem> map_item = nullptr;
QPointer<LayoutPixmapItem> map_item = nullptr;
QList<QPointer<ConnectionPixmapItem>> connection_items;
QMap<QString, QPointer<DivingMapPixmapItem>> diving_map_items;
QGraphicsPathItem *connection_mask = nullptr;
QPointer<CollisionPixmapItem> collision_item = nullptr;
QGraphicsItemGroup *events_group = nullptr;
QList<QGraphicsPixmapItem*> borderItems;
QList<QGraphicsLineItem*> gridLines;
QGraphicsItemGroup *mapGrid = nullptr;
MapRuler *map_ruler = nullptr;
MovableRect *playerViewRect = nullptr;
CursorTileRect *cursorMapTileRect = nullptr;
MapRuler *map_ruler = nullptr;
QPointer<QGraphicsScene> scene_metatiles = nullptr;
QPointer<QGraphicsScene> scene_current_metatile_selection = nullptr;
@@ -137,8 +154,27 @@ public:
QPointer<ConnectionPixmapItem> selected_connection_item = nullptr;
QPointer<MapConnection> connection_to_select = nullptr;
QString map_edit_mode = "paint";
QString obj_edit_mode = "select";
enum class EditAction { None, Paint, Select, Fill, Shift, Pick, Move };
EditAction mapEditAction = EditAction::Paint;
EditAction objectEditAction = EditAction::Select;
enum class EditMode { None, Disabled, Metatiles, Collision, Header, Events, Connections, Encounters };
EditMode editMode = EditMode::None;
void setEditMode(EditMode mode) { this->editMode = mode; }
EditMode getEditMode() { return this->editMode; }
bool getEditingLayout();
void setEditorView();
void setEditingMetatiles();
void setEditingCollision();
void setEditingHeader();
void setEditingObjects();
void setEditingConnections();
void setEditingEncounters();
void setMapEditingButtonsEnabled(bool enabled);
int scaleIndex = 2;
qreal collisionOpacity = 0.5;
@@ -148,10 +184,9 @@ public:
int getBorderDrawDistance(int dimension);
QUndoGroup editGroup; // Manages the undo history for each map
bool selectingEvent = false;
void deleteSelectedEvents();
void shouldReselectEvents();
void scaleMapView(int);
static void openInTextEditor(const QString &path, int lineNum = 0);
@@ -165,6 +200,7 @@ public slots:
void maskNonVisibleConnectionTiles();
void onBorderMetatilesChanged();
void selectedEventIndexChanged(int index, Event::Group eventGroup);
void toggleGrid(bool);
private:
const QImage defaultCollisionImgSheet = QImage(":/images/collisions.png");
@@ -202,11 +238,11 @@ private:
qint64 *pid = nullptr);
private slots:
void onMapStartPaint(QGraphicsSceneMouseEvent *event, MapPixmapItem *item);
void onMapEndPaint(QGraphicsSceneMouseEvent *event, MapPixmapItem *item);
void onMapStartPaint(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *item);
void onMapEndPaint(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *item);
void setSmartPathCursorMode(QGraphicsSceneMouseEvent *event);
void setStraightPathCursorMode(QGraphicsSceneMouseEvent *event);
void mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item);
void mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *item);
void mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item);
void setSelectedConnectionItem(ConnectionPixmapItem *connectionItem);
void onHoveredMovementPermissionChanged(uint16_t, uint16_t);
@@ -219,7 +255,6 @@ private slots:
void onHoveredMapMovementPermissionCleared();
void onSelectedMetatilesChanged();
void onWheelZoom(int);
void onToggleGridClicked(bool);
signals:
void objectsChanged();
@@ -231,6 +266,7 @@ signals:
void currentMetatilesSelectionChanged();
void mapRulerStatusChanged(const QString &);
void tilesetUpdated(QString);
void gridToggled(bool);
};
#endif // EDITOR_H

View File

@@ -4,6 +4,7 @@
#include <cstdint>
#include <string>
#include <vector>
#include <QString>
namespace fex
{
@@ -89,9 +90,7 @@ namespace fex
Lexer() = default;
~Lexer() = default;
std::vector<Token> LexFile(const std::string &path);
std::vector<Token> LexString(const std::string &data);
void LexFileDumpTokens(const std::string &path, const std::string &out);
std::vector<Token> LexFile(const QString &path);
private:
std::vector<Token> Lex();

View File

@@ -21,7 +21,7 @@ namespace fex
std::vector<Array> ParseTopLevelArrays(std::vector<Token> tokens);
std::map<std::string, ArrayValue> ParseTopLevelObjects(std::vector<Token> tokens);
std::map<std::string, int> ReadDefines(const std::string &filename, std::vector<std::string> matching);
std::map<std::string, int> ReadDefines(const QString &filename, std::vector<std::string> matching);
private:
int EvaluateExpression(std::vector<Token> tokens);

View File

@@ -1,19 +0,0 @@
#ifndef PARSER_UTIL_H
#define PARSER_UTIL_H
#include <QString>
#include <QStringList>
class ParserUtil
{
public:
ParserUtil(QString root);
QStringList ReadDefines(QString filename, QString prefix);
QStringList ReadDefinesValueSort(QString filename, QString prefix);
private:
QString root_;
};
#endif // PARSER_UTIL_H

View File

@@ -21,11 +21,13 @@
#include "regionmapeditor.h"
#include "mapimageexporter.h"
#include "filterchildrenproxymodel.h"
#include "maplistmodels.h"
#include "newmappopup.h"
#include "newtilesetdialog.h"
#include "shortcutseditor.h"
#include "preferenceeditor.h"
#include "projectsettingseditor.h"
#include "gridsettings.h"
#include "customscriptseditor.h"
#include "wildmonchart.h"
#include "updatepromoter.h"
@@ -165,13 +167,14 @@ public slots:
void on_mainTabBar_tabBarClicked(int index);
void on_mapViewTab_tabBarClicked(int index);
void onWarpBehaviorWarningClicked();
void clearOverlay();
private slots:
void on_action_Open_Project_triggered();
void on_action_Reload_Project_triggered();
void on_action_Close_Project_triggered();
void on_mapList_activated(const QModelIndex &index);
void on_action_Save_Project_triggered();
void openWarpMap(QString map_name, int event_id, Event::Group event_group);
void duplicate();
@@ -180,16 +183,17 @@ private slots:
void copy();
void paste();
void onLayoutChanged(Layout *layout);
void onOpenConnectedMap(MapConnection*);
void onMapNeedsRedrawing();
void onTilesetsSaved(QString, QString);
void openNewMapPopupWindow();
void onNewMapCreated();
void onMapCacheCleared();
void onMapLoaded(Map *map);
void importMapFromAdvanceMap1_92();
void onMapRulerStatusChanged(const QString &);
void applyUserShortcuts();
void markMapEdited();
void markSpecificMapEdited(Map*);
void on_action_NewMap_triggered();
void on_actionNew_Tileset_triggered();
@@ -200,6 +204,7 @@ private slots:
void on_comboBox_Weather_currentTextChanged(const QString &arg1);
void on_comboBox_Type_currentTextChanged(const QString &arg1);
void on_comboBox_BattleScene_currentTextChanged(const QString &arg1);
void on_comboBox_LayoutSelector_currentTextChanged(const QString &arg1);
void on_checkBox_ShowLocation_stateChanged(int selected);
void on_checkBox_AllowRunning_stateChanged(int selected);
void on_checkBox_AllowBiking_stateChanged(int selected);
@@ -219,9 +224,6 @@ private slots:
void on_actionMove_triggered();
void on_actionMap_Shift_triggered();
void onDeleteKeyPressed();
void on_toolButton_deleteObject_clicked();
void addNewEvent(Event::Type type);
void tryAddEventTab(QWidget * tab);
void displayEventTabs();
@@ -236,9 +238,6 @@ private slots:
void on_toolButton_Shift_clicked();
void onOpenMapListContextMenu(const QPoint &point);
void onAddNewMapToGroupClick(QAction* triggeredAction);
void onAddNewMapToAreaClick(QAction* triggeredAction);
void onAddNewMapToLayoutClick(QAction* triggeredAction);
void currentMetatilesSelectionChanged();
void on_action_Export_Map_Image_triggered();
@@ -262,10 +261,6 @@ private slots:
void on_actionTileset_Editor_triggered();
void mapSortOrder_changed(QAction *action);
void on_lineEdit_filterBox_textChanged(const QString &arg1);
void moveEvent(QMoveEvent *event);
void closeEvent(QCloseEvent *);
@@ -278,8 +273,11 @@ private slots:
void on_slider_DiveMapOpacity_valueChanged(int value);
void on_slider_EmergeMapOpacity_valueChanged(int value);
void on_horizontalSlider_CollisionTransparency_valueChanged(int value);
void on_toolButton_ExpandAll_clicked();
void on_toolButton_CollapseAll_clicked();
void mapListShortcut_ToggleEmptyFolders();
void mapListShortcut_ExpandAll();
void mapListShortcut_CollapseAll();
void on_actionAbout_Porymap_triggered();
void on_actionOpen_Log_File_triggered();
void on_actionOpen_Config_Folder_triggered();
@@ -302,6 +300,8 @@ private slots:
void on_actionProject_Settings_triggered();
void on_actionCustom_Scripts_triggered();
void reloadScriptEngine();
void on_actionShow_Grid_triggered();
void on_actionGrid_Settings_triggered();
public:
Ui::MainWindow *ui;
@@ -316,16 +316,20 @@ private:
QPointer<NewMapPopup> newMapPrompt = nullptr;
QPointer<PreferenceEditor> preferenceEditor = nullptr;
QPointer<ProjectSettingsEditor> projectSettingsEditor = nullptr;
QPointer<GridSettingsDialog> gridSettingsDialog = nullptr;
QPointer<CustomScriptsEditor> customScriptsEditor = nullptr;
QPointer<FilterChildrenProxyModel> groupListProxyModel = nullptr;
QPointer<MapGroupModel> mapGroupModel = nullptr;
QPointer<FilterChildrenProxyModel> areaListProxyModel = nullptr;
QPointer<MapAreaModel> mapAreaModel = nullptr;
QPointer<FilterChildrenProxyModel> layoutListProxyModel = nullptr;
QPointer<LayoutTreeModel> layoutTreeModel = nullptr;
QPointer<UpdatePromoter> updatePromoter = nullptr;
QPointer<NetworkAccessManager> networkAccessManager = nullptr;
QPointer<AboutPorymap> aboutWindow = nullptr;
QPointer<WildMonChart> wildMonChart = nullptr;
FilterChildrenProxyModel *mapListProxyModel;
QStandardItemModel *mapListModel;
QList<QStandardItem*> *mapGroupItemsList;
QMap<QString, QModelIndex> mapListIndexes;
QIcon mapIcon;
QAction *undoAction = nullptr;
QAction *redoAction = nullptr;
@@ -337,48 +341,61 @@ private:
bool isProgrammaticEventTabChange;
bool newMapDefaultsSet = false;
bool tilesetNeedsRedraw = false;
bool userSetMap(QString, bool scrollTreeView = false);
bool setMap(QString, bool scrollTreeView = false);
bool setLayout(QString layoutId);
bool setMap(QString);
void unsetMap();
bool userSetLayout(QString layoutId);
bool userSetMap(QString);
void redrawMapScene();
void refreshMapScene();
void setLayoutOnlyMode(bool layoutOnly);
bool checkProjectSanity();
bool loadProjectData();
bool setProjectUI();
void clearProjectUI();
void sortMapList();
void openSubWindow(QWidget * window);
void scrollMapList(MapTree *list, QString itemName);
void scrollMapListToCurrentMap(MapTree *list);
void scrollMapListToCurrentLayout(MapTree *list);
void resetMapListFilters();
void showFileWatcherWarning(QString filepath);
QString getExistingDirectory(QString);
bool openProject(QString dir, bool initial = false);
bool closeProject();
void showProjectOpenFailure();
void saveGlobalConfigs();
bool setInitialMap();
QStandardItem* createMapItem(QString mapName, int groupNum, int inGroupNum);
void saveGlobalConfigs();
void refreshRecentProjectsMenu();
void updateMapListIcon(const QString &mapName);
void updateMapList();
void mapListAddGroup();
void mapListAddLayout();
void mapListAddArea();
void openMapListItem(const QModelIndex &index);
void saveMapListTab(int index);
void displayMapProperties();
void checkToolButtons();
void clickToolButtonFromEditMode(QString editMode);
void clickToolButtonFromEditAction(Editor::EditAction editAction);
void markMapEdited();
void markMapEdited(Map*);
void showWindowTitle();
void updateWindowTitle();
void initWindow();
void initCustomUI();
void initExtraSignals();
void initEditor();
void initMiscHeapObjects();
void initMapSortOrder();
void initMapList();
void initShortcuts();
void initExtraShortcuts();
void loadUserSettings();
void applyMapListFilter(QString filterText);
void restoreWindowState();
void setTheme(QString);
void updateTilesetEditor();
@@ -398,6 +415,9 @@ private:
double getMetatilesZoomScale();
void redrawMetatileSelection();
void scrollMetatileSelectorToSelection();
MapListToolBar* getCurrentMapListToolBar();
MapTree* getCurrentMapList();
void refreshLocationsComboBox();
QObjectList shortcutableObjects() const;
void addCustomHeaderValue(QString key, QJsonValue value, bool isNew = false);
@@ -407,12 +427,6 @@ private:
void setDivingMapsVisible(bool visible);
};
enum MapListUserRoles {
GroupRole = Qt::UserRole + 1, // Used to hold the map group number.
TypeRole, // Used to differentiate between the different layers of the map list tree view.
TypeRole2, // Used for various extra data needed.
};
// These are namespaced in a struct to avoid colliding with e.g. class Map.
struct MainTab {
enum {
@@ -432,4 +446,10 @@ struct MapViewTab {
};
};
struct MapListTab {
enum {
Groups = 0, Areas, Layouts
};
};
#endif // MAINWINDOW_H

View File

@@ -25,7 +25,7 @@ class Project : public QObject
{
Q_OBJECT
public:
Project(QWidget *parent = nullptr);
Project(QObject *parent = nullptr);
~Project();
Project(const Project &) = delete;
@@ -46,11 +46,9 @@ public:
QStringList mapLayoutsTable;
QStringList mapLayoutsTableMaster;
QString layoutsLabel;
QMap<QString, MapLayout*> mapLayouts;
QMap<QString, MapLayout*> mapLayoutsMaster;
QMap<QString, QString> mapSecToMapHoverName;
QMap<QString, int> mapSectionNameToValue;
QMap<int, QString> mapSectionValueToName;
QMap<QString, QString> layoutIdsToNames;
QMap<QString, Layout*> mapLayouts;
QMap<QString, Layout*> mapLayoutsMaster;
QMap<QString, EventGraphics*> eventGraphicsMap;
QMap<QString, int> gfxDefines;
QString defaultSong;
@@ -67,6 +65,8 @@ public:
QStringList bgEventFacingDirections;
QStringList trainerTypes;
QStringList globalScriptLabels;
QStringList mapSectionIdNames;
QMap<QString, MapSectionEntry> regionMapEntries;
QMap<QString, QMap<QString, uint16_t>> metatileLabelsMap;
QMap<QString, uint16_t> unusedMetatileLabels;
QMap<QString, uint32_t> metatileBehaviorMap;
@@ -76,19 +76,19 @@ public:
QFileSystemWatcher fileWatcher;
QMap<QString, qint64> modifiedFileTimestamps;
bool usingAsmTilesets;
QString importExportPath;
QSet<QString> disabledSettingsNames;
int pokemonMinLevel;
int pokemonMaxLevel;
int maxEncounterRate;
bool wildEncountersLoaded;
bool saveEmptyMapsec;
void set_root(QString);
void initSignals();
void clearMapCache();
void clearTilesetCache();
void clearMapLayouts();
void clearEventGraphics();
struct DataQualifiers
{
@@ -114,8 +114,8 @@ public:
QStringList tilesetLabelsOrdered;
Blockdata readBlockdata(QString);
bool loadBlockdata(MapLayout*);
bool loadLayoutBorder(MapLayout*);
bool loadBlockdata(Layout *);
bool loadLayoutBorder(Layout *);
void saveTextFile(QString path, QString text);
void appendTextFile(QString path, QString text);
@@ -139,12 +139,20 @@ public:
bool readSpeciesIconPaths();
QMap<QString, QString> speciesToIconPath;
void addNewMapsec(const QString &name);
void removeMapsec(const QString &name);
bool hasUnsavedChanges();
bool hasUnsavedDataChanges = false;
QSet<QString> getTopLevelMapFields();
bool loadMapData(Map*);
bool readMapLayouts();
bool loadLayout(MapLayout *);
Layout *loadLayout(QString layoutId);
Layout *createNewLayout(Layout::SimpleSettings &layoutSettings);
bool loadLayout(Layout *);
bool loadMapLayout(Map*);
bool loadLayoutTilesets(MapLayout*);
bool loadLayoutTilesets(Layout *);
void loadTilesetAssets(Tileset*);
void loadTilesetTiles(Tileset*, QImage);
void loadTilesetMetatiles(Tileset*);
@@ -152,15 +160,17 @@ public:
void loadTilesetPalettes(Tileset*);
void readTilesetPaths(Tileset* tileset);
void saveLayoutBlockdata(Map*);
void saveLayoutBorder(Map*);
void saveLayout(Layout *);
void saveLayoutBlockdata(Layout *);
void saveLayoutBorder(Layout *);
void writeBlockdata(QString, const Blockdata &);
void saveAllMaps();
void saveMap(Map*);
void saveMap(Map *);
void saveAllDataStructures();
void saveConfig();
void saveMapLayouts();
void saveMapGroups();
void saveRegionMapSections();
void saveWildMonData();
void saveMapConstantsHeader();
void saveHealLocations(Map*);
@@ -214,7 +224,6 @@ public:
QString buildMetatileLabelsText(const QMap<QString, uint16_t> defines);
QString findMetatileLabelsTileset(QString label);
void setImportExportPath(QString filename);
static QString getExistingFilepath(QString filepath);
void applyParsedLimits();
@@ -232,12 +241,13 @@ public:
static bool mapDimensionsValid(int width, int height);
bool calculateDefaultMapSize();
static int getMaxObjectEvents();
static QString getEmptyMapsecName();
private:
void updateMapLayout(Map*);
void updateLayout(Layout *);
void setNewMapBlockdata(Map* map);
void setNewMapBorder(Map *map);
void setNewLayoutBlockdata(Layout *layout);
void setNewLayoutBorder(Layout *layout);
void setNewMapEvents(Map *map);
void setNewMapConnections(Map *map);
@@ -256,9 +266,8 @@ private:
static int max_object_events;
signals:
void reloadProject();
void uncheckMonitorFilesAction();
void mapCacheCleared();
void fileChanged(QString filepath);
void mapSectionIdNamesChanged();
void mapLoaded(Map *map);
};

View File

@@ -1,21 +1,21 @@
#ifndef BORDERMETATILESPIXMAPITEM_H
#define BORDERMETATILESPIXMAPITEM_H
#include "map.h"
#include "maplayout.h"
#include "metatileselector.h"
#include <QGraphicsPixmapItem>
class BorderMetatilesPixmapItem : public QObject, public QGraphicsPixmapItem {
Q_OBJECT
public:
BorderMetatilesPixmapItem(Map *map_, MetatileSelector *metatileSelector) {
this->map = map_;
this->map->setBorderItem(this);
BorderMetatilesPixmapItem(Layout *layout, MetatileSelector *metatileSelector) {
this->layout = layout;
this->layout->setBorderItem(this);
this->metatileSelector = metatileSelector;
setAcceptHoverEvents(true);
}
MetatileSelector *metatileSelector;
Map *map;
Layout *layout;
void draw();
signals:
void hoveredBorderMetatileSelectionChanged(uint16_t);

View File

@@ -4,19 +4,20 @@
#include <QSpinBox>
#include "metatileselector.h"
#include "mappixmapitem.h"
#include "movementpermissionsselector.h"
#include "layoutpixmapitem.h"
#include "map.h"
#include "settings.h"
class CollisionPixmapItem : public MapPixmapItem {
class CollisionPixmapItem : public LayoutPixmapItem {
Q_OBJECT
public:
CollisionPixmapItem(Map *map, QSpinBox * selectedCollision, QSpinBox * selectedElevation, MetatileSelector *metatileSelector, Settings *settings, qreal *opacity)
: MapPixmapItem(map, metatileSelector, settings){
CollisionPixmapItem(Layout *layout, QSpinBox * selectedCollision, QSpinBox * selectedElevation, MetatileSelector *metatileSelector, Settings *settings, qreal *opacity)
: LayoutPixmapItem(layout, metatileSelector, settings){
this->selectedCollision = selectedCollision;
this->selectedElevation = selectedElevation;
this->opacity = opacity;
map->setCollisionItem(this);
layout->setCollisionItem(this);
}
QSpinBox * selectedCollision;
QSpinBox * selectedElevation;

View File

@@ -0,0 +1,46 @@
#ifndef COLORINPUTWIDGET_H
#define COLORINPUTWIDGET_H
#include <QGroupBox>
#include <QValidator>
namespace Ui {
class ColorInputWidget;
}
class ColorInputWidget : public QGroupBox {
Q_OBJECT
public:
explicit ColorInputWidget(QWidget *parent = nullptr);
explicit ColorInputWidget(const QString &title, QWidget *parent = nullptr);
~ColorInputWidget();
void setColor(QRgb color);
QRgb color() const { return m_color; }
bool setBitDepth(int bits);
int bitDepth() const { return m_bitDepth; }
signals:
void colorChanged(QRgb color);
void bitDepthChanged(int bits);
void editingFinished();
private:
Ui::ColorInputWidget *ui;
QRgb m_color = 0;
int m_bitDepth = 0;
void init();
void updateColorUi();
void pickColor();
void blockEditSignals(bool block);
void setRgbFromSliders();
void setRgbFromSpinners();
void setRgbFromHexString(const QString &);
};
#endif // COLORINPUTWIDGET_H

View File

@@ -5,6 +5,7 @@
#include <QGraphicsPixmapItem>
#include <QPainter>
#include <QPointer>
#include <QKeyEvent>
class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem {
Q_OBJECT
@@ -36,14 +37,17 @@ private:
static const int mHeight = 16;
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
void mousePressEvent(QGraphicsSceneMouseEvent*) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent*) override;
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*) override;
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
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*);
void selectionChanged(bool selected);
void deleteRequested(MapConnection*);
};
#endif // CONNECTIONPIXMAPITEM_H

View File

@@ -34,11 +34,12 @@ private:
unsigned actionId = 0;
protected:
void mousePressEvent(QMouseEvent*) override;
virtual void mousePressEvent(QMouseEvent*) override;
virtual void focusInEvent(QFocusEvent*) override;
virtual void keyPressEvent(QKeyEvent*) override;
signals:
void selected();
void removed(MapConnection*);
void openMapClicked(MapConnection*);
private slots:

View File

@@ -1,23 +1,24 @@
#ifndef CURRENTSELECTEDMETATILESPIXMAPITEM_H
#define CURRENTSELECTEDMETATILESPIXMAPITEM_H
#include "map.h"
#include "metatileselector.h"
#include <QGraphicsPixmapItem>
class Layout;
class CurrentSelectedMetatilesPixmapItem : public QGraphicsPixmapItem {
public:
CurrentSelectedMetatilesPixmapItem(Map *map, MetatileSelector *metatileSelector) {
this->map = map;
CurrentSelectedMetatilesPixmapItem(Layout *layout, MetatileSelector *metatileSelector) {
this->layout = layout;
this->metatileSelector = metatileSelector;
}
Map* map = nullptr;
Layout *layout = nullptr;
MetatileSelector *metatileSelector;
void draw();
void setMap(Map *map) { this->map = map; }
void setLayout(Layout *layout) { this->layout = layout; }
};
QPixmap drawMetatileSelection(MetatileSelection selection, Map *map);
QPixmap drawMetatileSelection(MetatileSelection selection, Layout *layout);
#endif // CURRENTSELECTEDMETATILESPIXMAPITEM_H

View File

@@ -31,7 +31,6 @@ private:
Ui::CustomScriptsEditor *ui;
bool hasUnsavedChanges = false;
QString fileDialogDir;
const QString baseDir;
void displayScript(const QString &filepath, bool enabled);
@@ -50,6 +49,7 @@ private:
void restoreWindowState();
void initShortcuts();
QObjectList shortcutableObjects() const;
void openManual();
private slots:
void dialogButtonClicked(QAbstractButton *button);

28
include/ui/eventfilters.h Normal file
View File

@@ -0,0 +1,28 @@
#include <QObject>
#include <QEvent>
/// Prevent wheel scroll
class WheelFilter : public QObject {
Q_OBJECT
public:
WheelFilter(QObject *parent) : QObject(parent) {}
virtual ~WheelFilter() {}
bool eventFilter(QObject *obj, QEvent *event) override;
};
/// Ctrl+Wheel = zoom
class MapSceneEventFilter : public QObject {
Q_OBJECT
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
public:
explicit MapSceneEventFilter(QObject *parent = nullptr) : QObject(parent) {}
signals:
void wheelZoom(int delta);
public slots:
};

View File

@@ -9,9 +9,11 @@ class FilterChildrenProxyModel : public QSortFilterProxyModel
public:
explicit FilterChildrenProxyModel(QObject *parent = nullptr);
void setHideEmpty(bool hidden) { this->hideEmpty = hidden; }
protected:
bool filterAcceptsRow(int source_row, const QModelIndex & source_parent) const;
private:
bool hideEmpty = false;
};
#endif // FILTERCHILDRENPROXYMODEL_H

View File

@@ -34,6 +34,7 @@ signals:
class Editor;
// TODO: This should just be MapView. It makes map-based assumptions, and no other class inherits GraphicsView.
class GraphicsView : public QGraphicsView
{
public:
@@ -44,10 +45,10 @@ public:
// GraphicsView_Object object;
Editor *editor;
protected:
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void moveEvent(QMoveEvent *event);
virtual void mousePressEvent(QMouseEvent *event) override;
virtual void mouseMoveEvent(QMouseEvent *event) override;
virtual void mouseReleaseEvent(QMouseEvent *event) override;
virtual void moveEvent(QMoveEvent *event) override;
};
//Q_DECLARE_METATYPE(GraphicsView)

99
include/ui/gridsettings.h Normal file
View File

@@ -0,0 +1,99 @@
#ifndef GRIDSETTINGS_H
#define GRIDSETTINGS_H
#include <QDialog>
#include <QAbstractButton>
class GridSettings {
public:
explicit GridSettings() {};
~GridSettings() {};
enum Style {
Solid,
LargeDashes,
SmallDashes,
Crosshairs,
Dots,
};
uint width = 16;
uint height = 16;
int offsetX = 0;
int offsetY = 0;
Style style = Style::Solid;
QColor color = Qt::black;
QVector<qreal> getHorizontalDashPattern() const { return this->getDashPattern(this->width); }
QVector<qreal> getVerticalDashPattern() const { return this->getDashPattern(this->height); }
static QString getStyleName(Style style);
static GridSettings::Style getStyleFromName(const QString &name);
private:
static const QMap<Style, QString> styleToName;
QVector<qreal> getCenteredDashPattern(uint length, qreal dashLength, qreal gapLength) const;
QVector<qreal> getDashPattern(uint length) const;
};
inline bool operator==(const GridSettings &a, const GridSettings &b) {
return a.width == b.width
&& a.height == b.height
&& a.offsetX == b.offsetX
&& a.offsetY == b.offsetY
&& a.style == b.style
&& a.color == b.color;
}
inline bool operator!=(const GridSettings &a, const GridSettings &b) {
return !(operator==(a, b));
}
namespace Ui {
class GridSettingsDialog;
}
class GridSettingsDialog : public QDialog {
Q_OBJECT
public:
explicit GridSettingsDialog(QWidget *parent = nullptr);
explicit GridSettingsDialog(GridSettings *settings, QWidget *parent = nullptr);
~GridSettingsDialog();
void setSettings(const GridSettings &settings);
GridSettings settings() const { return *m_settings; }
void setDefaultSettings(const GridSettings &settings);
GridSettings defaultSettings() const { return m_defaultSettings; }
signals:
void changedGridSettings();
private:
Ui::GridSettingsDialog *ui;
GridSettings *const m_settings;
const GridSettings m_originalSettings;
GridSettings m_defaultSettings;
bool m_dimensionsLinked = true;
bool m_offsetsLinked = true;
bool m_ownedSettings = false;
void init();
void updateInput();
void setWidth(int value);
void setHeight(int value);
void setOffsetX(int value);
void setOffsetY(int value);
private slots:
void dialogButtonClicked(QAbstractButton *button);
void on_spinBox_Width_valueChanged(int value);
void on_spinBox_Height_valueChanged(int value);
void on_spinBox_X_valueChanged(int value);
void on_spinBox_Y_valueChanged(int value);
void on_comboBox_Style_currentTextChanged(const QString &text);
void onColorChanged(QRgb color);
};
#endif // GRIDSETTINGS_H

View File

@@ -1,54 +1,58 @@
#ifndef MAPPIXMAPITEM_H
#define MAPPIXMAPITEM_H
#include "map.h"
#include "settings.h"
#include "metatileselector.h"
#include <QGraphicsPixmapItem>
class MapPixmapItem : public QObject, public QGraphicsPixmapItem {
class Layout;
class LayoutPixmapItem : public QObject, public QGraphicsPixmapItem {
Q_OBJECT
private:
using QGraphicsPixmapItem::paint;
public:
enum class PaintMode {
Disabled,
Metatiles,
EventObjects
};
MapPixmapItem(Map *map_, MetatileSelector *metatileSelector, Settings *settings) {
this->map = map_;
this->map->setMapItem(this);
LayoutPixmapItem(Layout *layout, MetatileSelector *metatileSelector, Settings *settings) {
this->layout = layout;
// this->map->setMapItem(this);
this->metatileSelector = metatileSelector;
this->settings = settings;
this->paintingMode = PaintMode::Metatiles;
this->lockedAxis = MapPixmapItem::Axis::None;
this->lockedAxis = LayoutPixmapItem::Axis::None;
this->prevStraightPathState = false;
setAcceptHoverEvents(true);
}
MapPixmapItem::PaintMode paintingMode;
Map *map;
Layout *layout;
MetatileSelector *metatileSelector;
Settings *settings;
bool active;
bool has_mouse = false;
bool right_click;
int paint_tile_initial_x;
int paint_tile_initial_y;
bool prevStraightPathState;
int straight_path_initial_x;
int straight_path_initial_y;
QPoint metatilePos;
enum Axis {
None = 0,
X,
Y
};
MapPixmapItem::Axis lockedAxis;
LayoutPixmapItem::Axis lockedAxis;
QPoint selection_origin;
QList<QPoint> selection;
virtual void paint(QGraphicsSceneMouseEvent*);
virtual void floodFill(QGraphicsSceneMouseEvent*);
virtual void magicFill(QGraphicsSceneMouseEvent*);
@@ -70,26 +74,33 @@ public:
QList<CollisionSelectionItem> selectedCollisions,
bool fromScriptCall = false);
void floodFillSmartPath(int initialX, int initialY, bool fromScriptCall = false);
virtual void pick(QGraphicsSceneMouseEvent*);
virtual void select(QGraphicsSceneMouseEvent*);
virtual void shift(QGraphicsSceneMouseEvent*);
void shift(int xDelta, int yDelta, bool fromScriptCall = false);
virtual void draw(bool ignoreCache = false);
void updateMetatileSelection(QGraphicsSceneMouseEvent *event);
void paintNormal(int x, int y, bool fromScriptCall = false);
void lockNondominantAxis(QGraphicsSceneMouseEvent *event);
QPoint adjustCoords(QPoint pos);
void setEditsEnabled(bool enabled) { this->editsEnabled = enabled; }
bool getEditsEnabled() { return this->editsEnabled; }
private:
void paintSmartPath(int x, int y, bool fromScriptCall = false);
static QList<int> smartPathTable;
unsigned actionId_ = 0;
bool editsEnabled = true;
signals:
void startPaint(QGraphicsSceneMouseEvent *, MapPixmapItem *);
void endPaint(QGraphicsSceneMouseEvent *, MapPixmapItem *);
void mouseEvent(QGraphicsSceneMouseEvent *, MapPixmapItem *);
void startPaint(QGraphicsSceneMouseEvent *, LayoutPixmapItem *);
void endPaint(QGraphicsSceneMouseEvent *, LayoutPixmapItem *);
void mouseEvent(QGraphicsSceneMouseEvent *, LayoutPixmapItem *);
void hoveredMapMetatileChanged(const QPoint &pos);
void hoveredMapMetatileCleared();

View File

@@ -16,6 +16,24 @@ enum ImageExporterMode {
Timelapse,
};
struct ImageExporterSettings {
bool showObjects = false;
bool showWarps = false;
bool showBGs = false;
bool showTriggers = false;
bool showHealLocations = false;
bool showUpConnections = false;
bool showDownConnections = false;
bool showLeftConnections = false;
bool showRightConnections = false;
bool showGrid = false;
bool showBorder = false;
bool showCollision = false;
bool previewActualSize = false;
int timelapseSkipAmount = 1;
int timelapseDelayMs = 200;
};
class MapImageExporter : public QDialog
{
Q_OBJECT
@@ -27,56 +45,51 @@ public:
private:
Ui::MapImageExporter *ui;
Layout *layout = nullptr;
Map *map = nullptr;
Editor *editor = nullptr;
QGraphicsScene *scene = nullptr;
QPixmap preview;
bool showObjects = false;
bool showWarps = false;
bool showBGs = false;
bool showTriggers = false;
bool showHealSpots = false;
bool showUpConnections = false;
bool showDownConnections = false;
bool showLeftConnections = false;
bool showRightConnections = false;
bool showGrid = false;
bool showBorder = false;
bool showCollision = false;
int timelapseSkipAmount = 1;
int timelapseDelayMs = 200;
ImageExporterSettings settings;
ImageExporterMode mode = ImageExporterMode::Normal;
void updatePreview();
void scalePreview();
void updateShowBorderState();
void saveImage();
QPixmap getStitchedImage(QProgressDialog *progress, bool includeBorder);
QPixmap getFormattedMapPixmap(Map *map, bool ignoreBorder = false);
bool historyItemAppliesToFrame(const QUndoCommand *command);
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_HealSpots_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_Elevation_stateChanged(int state);
void on_checkBox_Grid_stateChanged(int state);
void on_checkBox_Border_stateChanged(int state);
void on_pushButton_Save_pressed();
void on_pushButton_Reset_pressed();
void on_pushButton_Cancel_pressed();
void on_spinBox_TimelapseDelay_valueChanged(int delayMs);
void on_spinBox_FrameSkip_valueChanged(int skip);
void on_checkBox_ActualSize_stateChanged(int state);
};
#endif // MAPIMAGEEXPORTER_H

208
include/ui/maplistmodels.h Normal file
View File

@@ -0,0 +1,208 @@
#pragma once
#ifndef MAPLISTMODELS_H
#define MAPLISTMODELS_H
#include <QTreeView>
#include <QFontDatabase>
#include <QStyledItemDelegate>
#include <QStandardItemModel>
#include <QMap>
class Project;
enum MapListUserRoles {
GroupRole = Qt::UserRole + 1, // Used to hold the map group number.
TypeRole, // Used to differentiate between the different layers of the map list tree view.
TypeRole2, // Used for various extra data needed.
};
class MapTree : public QTreeView {
Q_OBJECT
public:
MapTree(QWidget *parent) : QTreeView(parent) {
this->setDropIndicatorShown(true);
this->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
this->setFocusPolicy(Qt::StrongFocus);
this->setContextMenuPolicy(Qt::CustomContextMenu);
}
protected:
virtual void keyPressEvent(QKeyEvent *event) override;
public slots:
void removeSelected();
};
class GroupNameDelegate : public QStyledItemDelegate {
Q_OBJECT
public:
GroupNameDelegate(Project *project, QObject *parent = nullptr) : QStyledItemDelegate(parent), project(project) {}
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
private:
Project *project = nullptr;
};
class QRegularExpressionValidator;
class MapListModel : public QStandardItemModel {
Q_OBJECT
public:
MapListModel(QObject *parent = nullptr) : QStandardItemModel(parent) {};
~MapListModel() { }
virtual QModelIndex indexOf(QString id) const = 0;
virtual void removeItemAt(const QModelIndex &index);
virtual QStandardItem *getItem(const QModelIndex &index) const = 0;
protected:
virtual void removeItem(QStandardItem *item) = 0;
};
class MapGroupModel : public MapListModel {
Q_OBJECT
public:
MapGroupModel(Project *project, QObject *parent = nullptr);
~MapGroupModel() { }
QVariant data(const QModelIndex &index, int role) const override;
Qt::DropActions supportedDropActions() const override;
QStringList mimeTypes() const override;
virtual QMimeData *mimeData(const QModelIndexList &indexes) const override;
virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
public:
void setMap(QString mapName) { this->openMap = mapName; }
QStandardItem *createGroupItem(QString groupName, int groupIndex, QStandardItem *fromItem = nullptr);
QStandardItem *createMapItem(QString mapName, QStandardItem *fromItem = nullptr);
QStandardItem *insertGroupItem(QString groupName);
QStandardItem *insertMapItem(QString mapName, QString groupName);
virtual QStandardItem *getItem(const QModelIndex &index) const override;
virtual QModelIndex indexOf(QString mapName) const override;
void initialize();
protected:
virtual void removeItem(QStandardItem *item) override;
private:
friend class MapTree;
void updateProject();
private:
Project *project;
QStandardItem *root = nullptr;
QMap<QString, QStandardItem *> groupItems;
QMap<QString, QStandardItem *> mapItems;
QString openMap;
signals:
void dragMoveCompleted();
};
class MapAreaModel : public MapListModel {
Q_OBJECT
public:
MapAreaModel(Project *project, QObject *parent = nullptr);
~MapAreaModel() {}
QVariant data(const QModelIndex &index, int role) const override;
public:
void setMap(QString mapName) { this->openMap = mapName; }
QStandardItem *createAreaItem(QString areaName);
QStandardItem *createMapItem(QString mapName, int areaIndex, int mapIndex);
QStandardItem *insertAreaItem(QString areaName);
QStandardItem *insertMapItem(QString mapName, QString areaName, int groupIndex);
virtual QStandardItem *getItem(const QModelIndex &index) const override;
virtual QModelIndex indexOf(QString mapName) const override;
void initialize();
protected:
virtual void removeItem(QStandardItem *item) override;
private:
Project *project;
QStandardItem *root = nullptr;
QMap<QString, QStandardItem *> areaItems;
QMap<QString, QStandardItem *> mapItems;
QString openMap;
signals:
void edited();
};
class LayoutTreeModel : public MapListModel {
Q_OBJECT
public:
LayoutTreeModel(Project *project, QObject *parent = nullptr);
~LayoutTreeModel() {}
QVariant data(const QModelIndex &index, int role) const override;
public:
void setLayout(QString layoutId) { this->openLayout = layoutId; }
QStandardItem *createLayoutItem(QString layoutId);
QStandardItem *createMapItem(QString mapName);
QStandardItem *insertLayoutItem(QString layoutId);
QStandardItem *insertMapItem(QString mapName, QString layoutId);
virtual QStandardItem *getItem(const QModelIndex &index) const override;
virtual QModelIndex indexOf(QString layoutName) const override;
void initialize();
protected:
virtual void removeItem(QStandardItem *item) override;
private:
Project *project;
QStandardItem *root = nullptr;
QMap<QString, QStandardItem *> layoutItems;
QMap<QString, QStandardItem *> mapItems;
QString openLayout;
signals:
void edited();
};
#endif // MAPLISTMODELS_H

View File

@@ -0,0 +1,52 @@
#ifndef MAPLISTTOOLBAR_H
#define MAPLISTTOOLBAR_H
#include "maplistmodels.h"
#include "filterchildrenproxymodel.h"
#include <QFrame>
#include <QPointer>
namespace Ui {
class MapListToolBar;
}
class MapListToolBar : public QFrame
{
Q_OBJECT
public:
explicit MapListToolBar(QWidget *parent = nullptr);
~MapListToolBar();
MapTree* list() const { return m_list; }
void setList(MapTree *list);
void setEditsAllowedButtonVisible(bool visible);
void setEditsAllowed(bool allowed);
void toggleEditsAllowed();
void setEmptyFoldersVisible(bool visible);
void toggleEmptyFolders();
void expandList();
void collapseList();
void applyFilter(const QString &filterText);
void clearFilter();
void setFilterLocked(bool locked) { m_filterLocked = locked; }
bool isFilterLocked() const { return m_filterLocked; }
signals:
void filterCleared(MapTree*);
void addFolderClicked();
private:
Ui::MapListToolBar *ui;
QPointer<MapTree> m_list;
bool m_filterLocked = false;
bool m_editsAllowed = false;
bool m_emptyFoldersVisible = true;
};
#endif // MAPLISTTOOLBAR_H

View File

@@ -1,19 +0,0 @@
#ifndef MAPSCENEEVENTFILTER_H
#define MAPSCENEEVENTFILTER_H
#include <QObject>
class MapSceneEventFilter : public QObject
{
Q_OBJECT
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
public:
explicit MapSceneEventFilter(QObject *parent = nullptr);
signals:
void wheelZoom(int delta);
public slots:
};
#endif // MAPSCENEEVENTFILTER_H

View File

@@ -73,7 +73,8 @@ public:
private:
QMap<int, Overlay*> overlayMap;
protected:
void drawForeground(QPainter *painter, const QRectF &rect);
virtual void drawForeground(QPainter *painter, const QRectF &rect) override;
virtual void keyPressEvent(QKeyEvent*) override;
};
#endif // GRAPHICSVIEW_H

View File

@@ -31,13 +31,13 @@ struct MetatileSelection
class MetatileSelector: public SelectablePixmapItem {
Q_OBJECT
public:
MetatileSelector(int numMetatilesWide, Map *map): SelectablePixmapItem(16, 16) {
MetatileSelector(int numMetatilesWide, Layout *layout): SelectablePixmapItem(16, 16) {
this->externalSelection = false;
this->prefabSelection = false;
this->numMetatilesWide = numMetatilesWide;
this->map = map;
this->primaryTileset = map->layout->tileset_primary;
this->secondaryTileset = map->layout->tileset_secondary;
this->layout = layout;
this->primaryTileset = layout->tileset_primary;
this->secondaryTileset = layout->tileset_secondary;
this->selection = MetatileSelection{};
this->cellPos = QPoint(-1, -1);
setAcceptHoverEvents(true);
@@ -51,7 +51,7 @@ public:
void setPrefabSelection(MetatileSelection selection);
void setExternalSelection(int, int, QList<uint16_t>, QList<QPair<uint16_t, uint16_t>>);
QPoint getMetatileIdCoordsOnWidget(uint16_t);
void setMap(Map*);
void setLayout(Layout *layout);
bool isInternalSelection() const { return (!this->externalSelection && !this->prefabSelection); }
Tileset *primaryTileset;
Tileset *secondaryTileset;
@@ -65,7 +65,7 @@ private:
bool externalSelection;
bool prefabSelection;
int numMetatilesWide;
Map *map;
Layout *layout;
int externalSelectionWidth;
int externalSelectionHeight;
QList<uint16_t> externalSelectedMetatiles;

View File

@@ -32,8 +32,6 @@ public slots:
void deactivateTab(int tabIndex);
private:
bool eventFilter(QObject *object, QEvent *event);
void actionCopyTab(int index);
void actionAddDeleteTab(int index);

View File

@@ -23,8 +23,9 @@ public:
bool importedMap;
QString layoutId;
void init();
void init(MapSortOrder type, QVariant data);
void init(MapLayout *);
void initUi();
void init(int tabIndex, QString data);
void init(Layout *);
static void setDefaultSettings(Project *project);
signals:
@@ -37,7 +38,7 @@ private:
bool checkNewMapGroup();
void saveSettings();
void useLayout(QString layoutId);
void useLayoutSettings(MapLayout *mapLayout);
void useLayoutSettings(Layout *mapLayout);
struct Settings {
QString group;
@@ -60,6 +61,8 @@ private:
static struct Settings settings;
private slots:
void on_checkBox_UseExistingLayout_stateChanged(int state);
void on_comboBox_Layout_currentTextChanged(const QString &text);
void on_pushButton_NewMap_Accept_clicked();
void on_lineEdit_NewMap_Name_textChanged(const QString &);
};

View File

@@ -50,19 +50,19 @@ private:
QColor fillColor;
};
class OverlayImage : public OverlayItem {
class OverlayPixmap : public OverlayItem {
public:
OverlayImage(int x, int y, QImage image) {
OverlayPixmap(int x, int y, QPixmap pixmap) {
this->x = x;
this->y = y;
this->image = image;
this->pixmap = pixmap;
}
~OverlayImage() {}
~OverlayPixmap() {}
virtual void render(QPainter *painter);
private:
int x;
int y;
QImage image;
QPixmap pixmap;
};
class Overlay

View File

@@ -2,10 +2,8 @@
#define PALETTEEDITOR_H
#include <QMainWindow>
#include <QValidator>
#include <QSlider>
#include <QFrame>
#include <QLabel>
#include "colorinputwidget.h"
#include "project.h"
#include "history.h"
@@ -32,43 +30,27 @@ public:
private:
Ui::PaletteEditor *ui;
Project *project = nullptr;
QList<QList<QSlider*>> sliders;
QList<QList<QSpinBox *>> spinners;
QList<QFrame*> frames;
QList<QToolButton *> pickButtons;
QList<QLineEdit *> hexEdits;
QList<ColorInputWidget*> colorInputs;
Tileset *primaryTileset;
Tileset *secondaryTileset;
QList<History<PaletteHistoryItem*>> palettesHistory;
void refreshColorUis();
void updateColorUi(int index, QRgb color);
void commitEditHistory(int paletteid);
Tileset* getTileset(int paletteId);
void refreshColorInputs();
void commitEditHistory();
void commitEditHistory(int paletteId);
void restoreWindowState();
void setSignalsEnabled(bool enabled);
void setColorsFromHistory(PaletteHistoryItem*, int);
void closeEvent(QCloseEvent*);
void pickColor(int i);
void setRgb(int index, QRgb rgb);
void setRgbFromSliders(int colorIndex);
void setRgbFromHexEdit(int colorIndex);
void setRgbFromSpinners(int colorIndex);
void setPalette(int paletteId, const QList<QRgb> &palette);
void setBitDepth(int bits);
int bitDepth = 24;
class HexCodeValidator : public QValidator {
virtual QValidator::State validate(QString &input, int &) const override {
input = input.toUpper();
return QValidator::Acceptable;
}
};
HexCodeValidator *hexValidator = nullptr;
static const int numColors = 16;
signals:
void closed();

View File

@@ -20,9 +20,9 @@ struct PrefabItem
class Prefab
{
public:
void initPrefabUI(MetatileSelector *selector, QWidget *prefabWidget, QLabel *emptyPrefabLabel, Map *map);
void addPrefab(MetatileSelection selection, Map *map, QString name);
void updatePrefabUi(Map *map);
void initPrefabUI(MetatileSelector *selector, QWidget *prefabWidget, QLabel *emptyPrefabLabel, Layout *layout);
void addPrefab(MetatileSelection selection, Layout *layout, QString name);
void updatePrefabUi(Layout *layout);
bool tryImportDefaultPrefabs(QWidget * parent, BaseGameVersion version, QString filepath = "");
private:

View File

@@ -2,10 +2,11 @@
#define PREFABCREATIONDIALOG_H
#include "metatileselector.h"
#include "map.h"
#include <QDialog>
class Layout;
namespace Ui {
class PrefabCreationDialog;
}
@@ -15,12 +16,12 @@ class PrefabCreationDialog : public QDialog
Q_OBJECT
public:
explicit PrefabCreationDialog(QWidget *parent, MetatileSelector *metatileSelector, Map *map);
explicit PrefabCreationDialog(QWidget *parent, MetatileSelector *metatileSelector, Layout *layout);
~PrefabCreationDialog();
void savePrefab();
private:
Map *map;
Layout *layout = nullptr;
Ui::PrefabCreationDialog *ui;
MetatileSelection selection;
};

View File

@@ -65,6 +65,8 @@ private:
void updateMaskOverlapWarning(QLabel * warning, QList<UIntSpinBox*> masks);
QStringList getWarpBehaviorsList();
void setWarpBehaviorsList(QStringList list);
void openFilesHelp();
void openIdentifiersHelp();
private slots:
void dialogButtonClicked(QAbstractButton *button);

View File

@@ -57,7 +57,6 @@ private:
tsl::ordered_map<QString, RegionMap *> region_maps;
QString configFilepath;
QString mapSectionFilepath;
poryjson::Json rmConfigJson;
@@ -96,7 +95,7 @@ private:
void saveConfig();
bool loadRegionMapEntries();
bool saveRegionMapEntries();
tsl::ordered_map<QString, MapSectionEntry> region_map_entries;
QMap<QString, MapSectionEntry> region_map_entries;
bool buildConfigDialog();
poryjson::Json configRegionMapDialog();

View File

@@ -4,7 +4,6 @@
#include "orderedjson.h"
#include <QDialog>
#include <QFileDialog>
class Project;
@@ -33,7 +32,7 @@ private:
void hideMessages();
QString browse(QString filter, QFileDialog::FileMode mode);
QString browse(QString filter);
private slots:
void on_browse_tilesetImagePath_clicked();

View File

@@ -8,7 +8,8 @@
#include "tileseteditormetatileselector.h"
#include "tileseteditortileselector.h"
#include "metatilelayersitem.h"
#include "map.h"
class Layout;
namespace Ui {
class TilesetEditor;
@@ -39,10 +40,10 @@ class TilesetEditor : public QMainWindow
Q_OBJECT
public:
explicit TilesetEditor(Project*, Map*, QWidget *parent = nullptr);
explicit TilesetEditor(Project *project, Layout *layout, QWidget *parent = nullptr);
~TilesetEditor();
void update(Map *map, QString primaryTilsetLabel, QString secondaryTilesetLabel);
void updateMap(Map *map);
void update(Layout *layout, QString primaryTilsetLabel, QString secondaryTilesetLabel);
void updateLayout(Layout *layout);
void updateTilesets(QString primaryTilsetLabel, QString secondaryTilesetLabel);
bool selectMetatile(uint16_t metatileId);
uint16_t getSelectedMetatileId();
@@ -155,7 +156,7 @@ private:
MetatileLayersItem *metatileLayersItem = nullptr;
PaletteEditor *paletteEditor = nullptr;
Project *project = nullptr;
Map *map = nullptr;
Layout *layout = nullptr;
Metatile *metatile = nullptr;
Metatile *copiedMetatile = nullptr;
QString copiedMetatileLabel;

View File

@@ -3,13 +3,14 @@
#include "selectablepixmapitem.h"
#include "tileset.h"
#include "map.h"
class Layout;
class TilesetEditorMetatileSelector: public SelectablePixmapItem {
Q_OBJECT
public:
TilesetEditorMetatileSelector(Tileset *primaryTileset, Tileset *secondaryTileset, Map *map);
Map *map = nullptr;
TilesetEditorMetatileSelector(Tileset *primaryTileset, Tileset *secondaryTileset, Layout *layout);
Layout *layout = nullptr;
void draw();
bool select(uint16_t metatileId);
void setTilesets(Tileset*, Tileset*, bool draw = true);

View File

@@ -61,6 +61,7 @@ private:
QPoint getTileCoords(uint16_t);
QList<QRgb> getCurPaletteTable();
QList<Tile> buildSelectedTiles(int, int, QList<Tile>);
QImage buildImage(int tileIdStart, int numTiles);
void drawUnused();

View File

@@ -17,7 +17,7 @@ class UpdatePromoter : public QDialog
public:
explicit UpdatePromoter(QWidget *parent, NetworkAccessManager *manager);
~UpdatePromoter() {};
~UpdatePromoter();
void checkForUpdates();
void updatePreferences();

View File

@@ -69,7 +69,7 @@ private:
void applySpeciesColors(const QList<QBarSet*> &);
QChart::ChartTheme currentTheme() const;
void updateTheme();
void limitChartAnimation(QChart*);
void limitChartAnimation();
void showHelpDialog();
};

View File

@@ -33,6 +33,7 @@ SOURCES += src/core/block.cpp \
src/core/bitpacker.cpp \
src/core/blockdata.cpp \
src/core/events.cpp \
src/core/filedialog.cpp \
src/core/heallocation.cpp \
src/core/imageexport.cpp \
src/core/map.cpp \
@@ -51,7 +52,6 @@ SOURCES += src/core/block.cpp \
src/core/editcommands.cpp \
src/lib/fex/lexer.cpp \
src/lib/fex/parser.cpp \
src/lib/fex/parser_util.cpp \
src/lib/orderedjson.cpp \
src/core/regionmapeditcommands.cpp \
src/scriptapi/apimap.cpp \
@@ -59,6 +59,7 @@ SOURCES += src/core/block.cpp \
src/scriptapi/apiutility.cpp \
src/scriptapi/scripting.cpp \
src/ui/aboutporymap.cpp \
src/ui/colorinputwidget.cpp \
src/ui/connectionslistitem.cpp \
src/ui/customscriptseditor.cpp \
src/ui/customscriptslistitem.cpp \
@@ -68,6 +69,7 @@ SOURCES += src/core/block.cpp \
src/ui/collisionpixmapitem.cpp \
src/ui/connectionpixmapitem.cpp \
src/ui/currentselectedmetatilespixmapitem.cpp \
src/ui/gridsettings.cpp \
src/ui/newmapconnectiondialog.cpp \
src/ui/overlay.cpp \
src/ui/prefab.cpp \
@@ -77,14 +79,16 @@ SOURCES += src/core/block.cpp \
src/ui/cursortilerect.cpp \
src/ui/customattributestable.cpp \
src/ui/eventframes.cpp \
src/ui/eventfilters.cpp \
src/ui/filterchildrenproxymodel.cpp \
src/ui/maplistmodels.cpp \
src/ui/maplisttoolbar.cpp \
src/ui/graphicsview.cpp \
src/ui/imageproviders.cpp \
src/ui/mappixmapitem.cpp \
src/ui/layoutpixmapitem.cpp \
src/ui/prefabcreationdialog.cpp \
src/ui/regionmappixmapitem.cpp \
src/ui/citymappixmapitem.cpp \
src/ui/mapsceneeventfilter.cpp \
src/ui/metatilelayersitem.cpp \
src/ui/metatileselector.cpp \
src/ui/movablerect.cpp \
@@ -129,6 +133,7 @@ HEADERS += include/core/block.h \
include/core/bitpacker.h \
include/core/blockdata.h \
include/core/events.h \
include/core/filedialog.h \
include/core/heallocation.h \
include/core/history.h \
include/core/imageexport.h \
@@ -152,7 +157,6 @@ HEADERS += include/core/block.h \
include/lib/fex/define_statement.h \
include/lib/fex/lexer.h \
include/lib/fex/parser.h \
include/lib/fex/parser_util.h \
include/lib/orderedmap.h \
include/lib/orderedjson.h \
include/ui/aboutporymap.h \
@@ -165,6 +169,7 @@ HEADERS += include/core/block.h \
include/ui/collisionpixmapitem.h \
include/ui/connectionpixmapitem.h \
include/ui/currentselectedmetatilespixmapitem.h \
include/ui/gridsettings.h \
include/ui/newmapconnectiondialog.h \
include/ui/prefabframe.h \
include/ui/projectsettingseditor.h \
@@ -173,15 +178,18 @@ HEADERS += include/core/block.h \
include/ui/cursortilerect.h \
include/ui/customattributestable.h \
include/ui/eventframes.h \
include/ui/eventfilters.h \
include/ui/filterchildrenproxymodel.h \
include/ui/maplistmodels.h \
include/ui/maplisttoolbar.h \
include/ui/graphicsview.h \
include/ui/imageproviders.h \
include/ui/mappixmapitem.h \
include/ui/layoutpixmapitem.h \
include/ui/mapview.h \
include/ui/prefabcreationdialog.h \
include/ui/regionmappixmapitem.h \
include/ui/citymappixmapitem.h \
include/ui/mapsceneeventfilter.h \
include/ui/colorinputwidget.h \
include/ui/metatilelayersitem.h \
include/ui/metatileselector.h \
include/ui/movablerect.h \
@@ -226,7 +234,10 @@ HEADERS += include/core/block.h \
include/ui/wildmonchart.h
FORMS += forms/mainwindow.ui \
forms/colorinputwidget.ui \
forms/connectionslistitem.ui \
forms/gridsettingsdialog.ui \
forms/maplisttoolbar.ui \
forms/newmapconnectiondialog.ui \
forms/prefabcreationdialog.ui \
forms/prefabframe.ui \

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
resources/icons/chart_bar.ico Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 B

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 B

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
resources/icons/folder_add.ico Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
resources/icons/link.ico Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
resources/icons/link_broken.ico Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
resources/icons/minimap.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -1,6 +1,7 @@
<RCC>
<qresource prefix="/">
<file>icons/add.ico</file>
<file>icons/chart_bar.ico</file>
<file>icons/collapse_all.ico</file>
<file>icons/cursor.ico</file>
<file>icons/delete.ico</file>
@@ -10,16 +11,24 @@
<file>icons/file_put.ico</file>
<file>icons/fill_color_cursor.ico</file>
<file>icons/fill_color.ico</file>
<file>icons/folder_add.ico</file>
<file>icons/folder_closed_map.ico</file>
<file>icons/folder_closed.ico</file>
<file>icons/folder_eye_closed.ico</file>
<file>icons/folder_eye_open.ico</file>
<file>icons/folder_map_edited.ico</file>
<file>icons/folder_map_opened.ico</file>
<file>icons/folder_map.ico</file>
<file>icons/folder.ico</file>
<file>icons/lock_edit.ico</file>
<file>icons/unlock_edit.ico</file>
<file>icons/help.ico</file>
<file>icons/link_broken.ico</file>
<file>icons/link.ico</file>
<file>icons/map_edited.ico</file>
<file>icons/map_opened.ico</file>
<file>icons/map.ico</file>
<file>icons/map_grayed.ico</file>
<file>icons/move.ico</file>
<file>icons/pencil_cursor.ico</file>
<file>icons/pencil.ico</file>
@@ -35,7 +44,10 @@
<file>icons/sort_map.ico</file>
<file>icons/sort_number.ico</file>
<file>icons/tall_grass.ico</file>
<file>icons/minimap.ico</file>
<file>icons/viewsprites.ico</file>
<file>icons/application_form_edit.ico</file>
<file>icons/connections.ico</file>
<file>icons/ui/dark_checkbox_checked_disabled.png</file>
<file>icons/ui/dark_checkbox_checked_disabled@2x.png</file>
<file>icons/ui/dark_checkbox_checked.png</file>

View File

@@ -110,7 +110,6 @@ const QMap<ProjectIdentifier, QPair<QString, QString>> ProjectConfig::defaultIde
{ProjectIdentifier::define_map_empty, {"define_map_empty", "UNDEFINED"}},
{ProjectIdentifier::define_map_section_prefix, {"define_map_section_prefix", "MAPSEC_"}},
{ProjectIdentifier::define_map_section_empty, {"define_map_section_empty", "NONE"}},
{ProjectIdentifier::define_map_section_count, {"define_map_section_count", "COUNT"}},
{ProjectIdentifier::define_species_prefix, {"define_species_prefix", "SPECIES_"}},
// Regex
{ProjectIdentifier::regex_behaviors, {"regex_behaviors", "\\bMB_"}},
@@ -167,7 +166,6 @@ const QMap<ProjectFilePath, QPair<QString, QString>> ProjectConfig::defaultPaths
{ProjectFilePath::constants_obj_event_movement, { "constants_obj_event_movement", "include/constants/event_object_movement.h"}},
{ProjectFilePath::constants_obj_events, { "constants_obj_events", "include/constants/event_objects.h"}},
{ProjectFilePath::constants_event_bg, { "constants_event_bg", "include/constants/event_bg.h"}},
{ProjectFilePath::constants_region_map_sections, { "constants_region_map_sections", "include/constants/region_map_sections.h"}},
{ProjectFilePath::constants_metatile_labels, { "constants_metatile_labels", "include/constants/metatile_labels.h"}},
{ProjectFilePath::constants_metatile_behaviors, { "constants_metatile_behaviors", "include/constants/metatile_behaviors.h"}},
{ProjectFilePath::constants_species, { "constants_species", "include/constants/species.h"}},
@@ -208,7 +206,6 @@ void KeyValueConfigBase::load() {
}
QTextStream in(&file);
QList<QString> configLines;
static const QRegularExpression re("^(?<key>[^=]+)=(?<value>.*)$");
while (!in.atEnd()) {
QString line = in.readLine().trimmed();
@@ -279,18 +276,6 @@ uint32_t KeyValueConfigBase::getConfigUint32(QString key, QString value, uint32_
return qMin(max, qMax(min, result));
}
const QMap<MapSortOrder, QString> mapSortOrderMap = {
{MapSortOrder::Group, "group"},
{MapSortOrder::Layout, "layout"},
{MapSortOrder::Area, "area"},
};
const QMap<QString, MapSortOrder> mapSortOrderReverseMap = {
{"group", MapSortOrder::Group},
{"layout", MapSortOrder::Layout},
{"area", MapSortOrder::Area},
};
PorymapConfig porymapConfig;
QString PorymapConfig::getConfigFilepath() {
@@ -315,14 +300,8 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) {
this->reopenOnLaunch = getConfigBool(key, value);
} else if (key == "pretty_cursors") {
this->prettyCursors = getConfigBool(key, value);
} else if (key == "map_sort_order") {
QString sortOrder = value.toLower();
if (mapSortOrderReverseMap.contains(sortOrder)) {
this->mapSortOrder = mapSortOrderReverseMap.value(sortOrder);
} else {
this->mapSortOrder = MapSortOrder::Group;
logWarn(QString("Invalid config value for map_sort_order: '%1'. Must be 'group', 'area', or 'layout'.").arg(value));
}
} else if (key == "map_list_tab") {
this->mapListTab = getConfigInteger(key, value, 0, 2, 0);
} else if (key == "main_window_geometry") {
this->mainWindowGeometry = bytesFromString(value);
} else if (key == "main_window_state") {
@@ -439,7 +418,7 @@ QMap<QString, QString> PorymapConfig::getKeyValueMap() {
map.insert("project_manually_closed", this->projectManuallyClosed ? "1" : "0");
map.insert("reopen_on_launch", this->reopenOnLaunch ? "1" : "0");
map.insert("pretty_cursors", this->prettyCursors ? "1" : "0");
map.insert("map_sort_order", mapSortOrderMap.value(this->mapSortOrder));
map.insert("map_list_tab", QString::number(this->mapListTab));
map.insert("main_window_geometry", stringFromByteArray(this->mainWindowGeometry));
map.insert("main_window_state", stringFromByteArray(this->mainWindowState));
map.insert("map_splitter_state", stringFromByteArray(this->mapSplitterState));
@@ -741,8 +720,8 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
} else if (key == "enable_map_allow_flags") {
this->mapAllowFlagsEnabled = getConfigBool(key, value);
#ifdef CONFIG_BACKWARDS_COMPATABILITY
} else if (key == "recent_map") {
userConfig.recentMap = value;
} else if (key == "recent_map_or_layout") {
userConfig.recentMapOrLayout = value;
} else if (key == "use_encounter_json") {
userConfig.useEncounterJson = getConfigBool(key, value);
} else if (key == "custom_scripts") {
@@ -1036,8 +1015,8 @@ QString UserConfig::getConfigFilepath() {
}
void UserConfig::parseConfigKeyValue(QString key, QString value) {
if (key == "recent_map") {
this->recentMap = value;
if (key == "recent_map_or_layout") {
this->recentMapOrLayout = value;
} else if (key == "use_encounter_json") {
this->useEncounterJson = getConfigBool(key, value);
} else if (key == "custom_scripts") {
@@ -1053,14 +1032,13 @@ void UserConfig::setUnreadKeys() {
QMap<QString, QString> UserConfig::getKeyValueMap() {
QMap<QString, QString> map;
map.insert("recent_map", this->recentMap);
map.insert("recent_map_or_layout", this->recentMapOrLayout);
map.insert("use_encounter_json", QString::number(this->useEncounterJson));
map.insert("custom_scripts", this->outputCustomScripts());
return map;
}
void UserConfig::init() {
QString dirName = QDir(this->projectDir).dirName().toLower();
this->useEncounterJson = true;
this->customScripts.clear();
}

View File

@@ -1,5 +1,4 @@
#include "editcommands.h"
#include "mappixmapitem.h"
#include "draggablepixmapitem.h"
#include "bordermetatilespixmapitem.h"
#include "editor.h"
@@ -25,17 +24,17 @@ int getEventTypeMask(QList<Event *> events) {
return eventTypeMask;
}
void renderMapBlocks(Map *map, bool ignoreCache = false) {
map->mapItem->draw(ignoreCache);
map->collisionItem->draw(ignoreCache);
void renderBlocks(Layout *layout, bool ignoreCache = false) {
layout->layoutItem->draw(ignoreCache);
layout->collisionItem->draw(ignoreCache);
}
PaintMetatile::PaintMetatile(Map *map,
PaintMetatile::PaintMetatile(Layout *layout,
const Blockdata &oldMetatiles, const Blockdata &newMetatiles,
unsigned actionId, QUndoCommand *parent) : QUndoCommand(parent) {
setText("Paint Metatiles");
this->map = map;
this->layout = layout;
this->oldMetatiles = oldMetatiles;
this->newMetatiles = newMetatiles;
@@ -45,23 +44,23 @@ PaintMetatile::PaintMetatile(Map *map,
void PaintMetatile::redo() {
QUndoCommand::redo();
if (!map) return;
if (!layout) return;
map->setBlockdata(newMetatiles, true);
layout->setBlockdata(newMetatiles, true);
map->layout->lastCommitBlocks.blocks = map->layout->blockdata;
layout->lastCommitBlocks.blocks = layout->blockdata;
renderMapBlocks(map);
renderBlocks(layout);
}
void PaintMetatile::undo() {
if (!map) return;
if (!layout) return;
map->setBlockdata(oldMetatiles, true);
layout->setBlockdata(oldMetatiles, true);
map->layout->lastCommitBlocks.blocks = map->layout->blockdata;
layout->lastCommitBlocks.blocks = layout->blockdata;
renderMapBlocks(map);
renderBlocks(layout);
QUndoCommand::undo();
}
@@ -69,7 +68,7 @@ void PaintMetatile::undo() {
bool PaintMetatile::mergeWith(const QUndoCommand *command) {
const PaintMetatile *other = static_cast<const PaintMetatile *>(command);
if (map != other->map)
if (layout != other->layout)
return false;
if (actionId != other->actionId)
@@ -84,12 +83,12 @@ bool PaintMetatile::mergeWith(const QUndoCommand *command) {
************************************************************************
******************************************************************************/
PaintBorder::PaintBorder(Map *map,
PaintBorder::PaintBorder(Layout *layout,
const Blockdata &oldBorder, const Blockdata &newBorder,
unsigned actionId, QUndoCommand *parent) : QUndoCommand(parent) {
setText("Paint Border");
this->map = map;
this->layout = layout;
this->oldBorder = oldBorder;
this->newBorder = newBorder;
@@ -99,23 +98,23 @@ PaintBorder::PaintBorder(Map *map,
void PaintBorder::redo() {
QUndoCommand::redo();
if (!map) return;
if (!layout) return;
map->setBorderBlockData(newBorder, true);
layout->setBorderBlockData(newBorder, true);
map->layout->lastCommitBlocks.border = map->layout->border;
layout->lastCommitBlocks.border = layout->border;
map->borderItem->draw();
layout->borderItem->draw();
}
void PaintBorder::undo() {
if (!map) return;
if (!layout) return;
map->setBorderBlockData(oldBorder, true);
layout->setBorderBlockData(oldBorder, true);
map->layout->lastCommitBlocks.border = map->layout->border;
layout->lastCommitBlocks.border = layout->border;
map->borderItem->draw();
layout->borderItem->draw();
QUndoCommand::undo();
}
@@ -124,12 +123,12 @@ void PaintBorder::undo() {
************************************************************************
******************************************************************************/
ShiftMetatiles::ShiftMetatiles(Map *map,
ShiftMetatiles::ShiftMetatiles(Layout *layout,
const Blockdata &oldMetatiles, const Blockdata &newMetatiles,
unsigned actionId, QUndoCommand *parent) : QUndoCommand(parent) {
setText("Shift Metatiles");
this->map = map;
this->layout = layout;
this->oldMetatiles = oldMetatiles;
this->newMetatiles = newMetatiles;
@@ -139,23 +138,23 @@ ShiftMetatiles::ShiftMetatiles(Map *map,
void ShiftMetatiles::redo() {
QUndoCommand::redo();
if (!map) return;
if (!layout) return;
map->setBlockdata(newMetatiles, true);
layout->setBlockdata(newMetatiles, true);
map->layout->lastCommitBlocks.blocks = map->layout->blockdata;
layout->lastCommitBlocks.blocks = layout->blockdata;
renderMapBlocks(map, true);
renderBlocks(layout, true);
}
void ShiftMetatiles::undo() {
if (!map) return;
if (!layout) return;
map->setBlockdata(oldMetatiles, true);
layout->setBlockdata(oldMetatiles, true);
map->layout->lastCommitBlocks.blocks = map->layout->blockdata;
layout->lastCommitBlocks.blocks = layout->blockdata;
renderMapBlocks(map, true);
renderBlocks(layout, true);
QUndoCommand::undo();
}
@@ -163,7 +162,7 @@ void ShiftMetatiles::undo() {
bool ShiftMetatiles::mergeWith(const QUndoCommand *command) {
const ShiftMetatiles *other = static_cast<const ShiftMetatiles *>(command);
if (this->map != other->map)
if (this->layout != other->layout)
return false;
if (actionId != other->actionId)
@@ -178,20 +177,20 @@ bool ShiftMetatiles::mergeWith(const QUndoCommand *command) {
************************************************************************
******************************************************************************/
ResizeMap::ResizeMap(Map *map, QSize oldMapDimensions, QSize newMapDimensions,
ResizeLayout::ResizeLayout(Layout *layout, QSize oldLayoutDimensions, QSize newLayoutDimensions,
const Blockdata &oldMetatiles, const Blockdata &newMetatiles,
QSize oldBorderDimensions, QSize newBorderDimensions,
const Blockdata &oldBorder, const Blockdata &newBorder,
QUndoCommand *parent) : QUndoCommand(parent) {
setText("Resize Map");
this->map = map;
this->layout = layout;
this->oldMapWidth = oldMapDimensions.width();
this->oldMapHeight = oldMapDimensions.height();
this->oldLayoutWidth = oldLayoutDimensions.width();
this->oldLayoutHeight = oldLayoutDimensions.height();
this->newMapWidth = newMapDimensions.width();
this->newMapHeight = newMapDimensions.height();
this->newLayoutWidth = newLayoutDimensions.width();
this->newLayoutHeight = newLayoutDimensions.height();
this->oldMetatiles = oldMetatiles;
this->newMetatiles = newMetatiles;
@@ -206,36 +205,36 @@ ResizeMap::ResizeMap(Map *map, QSize oldMapDimensions, QSize newMapDimensions,
this->newBorder = newBorder;
}
void ResizeMap::redo() {
void ResizeLayout::redo() {
QUndoCommand::redo();
if (!map) return;
if (!layout) return;
map->layout->blockdata = newMetatiles;
map->setDimensions(newMapWidth, newMapHeight, false, true);
layout->blockdata = newMetatiles;
layout->setDimensions(newLayoutWidth, newLayoutHeight, false, true);
map->layout->border = newBorder;
map->setBorderDimensions(newBorderWidth, newBorderHeight, false, true);
layout->border = newBorder;
layout->setBorderDimensions(newBorderWidth, newBorderHeight, false, true);
map->layout->lastCommitBlocks.mapDimensions = QSize(map->getWidth(), map->getHeight());
map->layout->lastCommitBlocks.borderDimensions = QSize(map->getBorderWidth(), map->getBorderHeight());
layout->lastCommitBlocks.layoutDimensions = QSize(layout->getWidth(), layout->getHeight());
layout->lastCommitBlocks.borderDimensions = QSize(layout->getBorderWidth(), layout->getBorderHeight());
map->mapNeedsRedrawing();
layout->needsRedrawing();
}
void ResizeMap::undo() {
if (!map) return;
void ResizeLayout::undo() {
if (!layout) return;
map->layout->blockdata = oldMetatiles;
map->setDimensions(oldMapWidth, oldMapHeight, false, true);
layout->blockdata = oldMetatiles;
layout->setDimensions(oldLayoutWidth, oldLayoutHeight, false, true);
map->layout->border = oldBorder;
map->setBorderDimensions(oldBorderWidth, oldBorderHeight, false, true);
layout->border = oldBorder;
layout->setBorderDimensions(oldBorderWidth, oldBorderHeight, false, true);
map->layout->lastCommitBlocks.mapDimensions = QSize(map->getWidth(), map->getHeight());
map->layout->lastCommitBlocks.borderDimensions = QSize(map->getBorderWidth(), map->getBorderHeight());
layout->lastCommitBlocks.layoutDimensions = QSize(layout->getWidth(), layout->getHeight());
layout->lastCommitBlocks.borderDimensions = QSize(layout->getBorderWidth(), layout->getBorderHeight());
map->mapNeedsRedrawing();
layout->needsRedrawing();
QUndoCommand::undo();
}
@@ -487,23 +486,23 @@ int EventPaste::id() const {
************************************************************************
******************************************************************************/
ScriptEditMap::ScriptEditMap(Map *map,
QSize oldMapDimensions, QSize newMapDimensions,
ScriptEditLayout::ScriptEditLayout(Layout *layout,
QSize oldLayoutDimensions, QSize newLayoutDimensions,
const Blockdata &oldMetatiles, const Blockdata &newMetatiles,
QSize oldBorderDimensions, QSize newBorderDimensions,
const Blockdata &oldBorder, const Blockdata &newBorder,
QUndoCommand *parent) : QUndoCommand(parent) {
setText("Script Edit Map");
setText("Script Edit Layout");
this->map = map;
this->layout = layout;
this->newMetatiles = newMetatiles;
this->oldMetatiles = oldMetatiles;
this->oldMapWidth = oldMapDimensions.width();
this->oldMapHeight = oldMapDimensions.height();
this->newMapWidth = newMapDimensions.width();
this->newMapHeight = newMapDimensions.height();
this->oldLayoutWidth = oldLayoutDimensions.width();
this->oldLayoutHeight = oldLayoutDimensions.height();
this->newLayoutWidth = newLayoutDimensions.width();
this->newLayoutHeight = newLayoutDimensions.height();
this->oldBorder = oldBorder;
this->newBorder = newBorder;
@@ -514,58 +513,58 @@ ScriptEditMap::ScriptEditMap(Map *map,
this->newBorderHeight = newBorderDimensions.height();
}
void ScriptEditMap::redo() {
void ScriptEditLayout::redo() {
QUndoCommand::redo();
if (!map) return;
if (!layout) return;
if (newMapWidth != map->getWidth() || newMapHeight != map->getHeight()) {
map->layout->blockdata = newMetatiles;
map->setDimensions(newMapWidth, newMapHeight, false);
if (newLayoutWidth != layout->getWidth() || newLayoutHeight != layout->getHeight()) {
layout->blockdata = newMetatiles;
layout->setDimensions(newLayoutWidth, newLayoutHeight, false);
} else {
map->setBlockdata(newMetatiles);
layout->setBlockdata(newMetatiles);
}
if (newBorderWidth != map->getBorderWidth() || newBorderHeight != map->getBorderHeight()) {
map->layout->border = newBorder;
map->setBorderDimensions(newBorderWidth, newBorderHeight, false);
if (newBorderWidth != layout->getBorderWidth() || newBorderHeight != layout->getBorderHeight()) {
layout->border = newBorder;
layout->setBorderDimensions(newBorderWidth, newBorderHeight, false);
} else {
map->setBorderBlockData(newBorder);
layout->setBorderBlockData(newBorder);
}
map->layout->lastCommitBlocks.blocks = newMetatiles;
map->layout->lastCommitBlocks.mapDimensions = QSize(newMapWidth, newMapHeight);
map->layout->lastCommitBlocks.border = newBorder;
map->layout->lastCommitBlocks.borderDimensions = QSize(newBorderWidth, newBorderHeight);
layout->lastCommitBlocks.blocks = newMetatiles;
layout->lastCommitBlocks.layoutDimensions = QSize(newLayoutWidth, newLayoutHeight);
layout->lastCommitBlocks.border = newBorder;
layout->lastCommitBlocks.borderDimensions = QSize(newBorderWidth, newBorderHeight);
renderMapBlocks(map);
map->borderItem->draw();
renderBlocks(layout, true);
layout->borderItem->draw();
}
void ScriptEditMap::undo() {
if (!map) return;
void ScriptEditLayout::undo() {
if (!layout) return;
if (oldMapWidth != map->getWidth() || oldMapHeight != map->getHeight()) {
map->layout->blockdata = oldMetatiles;
map->setDimensions(oldMapWidth, oldMapHeight, false);
if (oldLayoutWidth != layout->getWidth() || oldLayoutHeight != layout->getHeight()) {
layout->blockdata = oldMetatiles;
layout->setDimensions(oldLayoutWidth, oldLayoutHeight, false);
} else {
map->setBlockdata(oldMetatiles);
layout->setBlockdata(oldMetatiles);
}
if (oldBorderWidth != map->getBorderWidth() || oldBorderHeight != map->getBorderHeight()) {
map->layout->border = oldBorder;
map->setBorderDimensions(oldBorderWidth, oldBorderHeight, false);
if (oldBorderWidth != layout->getBorderWidth() || oldBorderHeight != layout->getBorderHeight()) {
layout->border = oldBorder;
layout->setBorderDimensions(oldBorderWidth, oldBorderHeight, false);
} else {
map->setBorderBlockData(oldBorder);
layout->setBorderBlockData(oldBorder);
}
map->layout->lastCommitBlocks.blocks = oldMetatiles;
map->layout->lastCommitBlocks.mapDimensions = QSize(oldMapWidth, oldMapHeight);
map->layout->lastCommitBlocks.border = oldBorder;
map->layout->lastCommitBlocks.borderDimensions = QSize(oldBorderWidth, oldBorderHeight);
layout->lastCommitBlocks.blocks = oldMetatiles;
layout->lastCommitBlocks.layoutDimensions = QSize(oldLayoutWidth, oldLayoutHeight);
layout->lastCommitBlocks.border = oldBorder;
layout->lastCommitBlocks.borderDimensions = QSize(oldBorderWidth, oldBorderHeight);
renderMapBlocks(map);
map->borderItem->draw();
renderBlocks(layout, true);
layout->borderItem->draw();
QUndoCommand::undo();
}

View File

@@ -146,10 +146,13 @@ void Event::loadPixmap(Project *) {
this->pixmap = pixmap ? *pixmap : QPixmap();
}
void Event::setIcons() {
void Event::clearIcons() {
qDeleteAll(icons);
icons.clear();
}
void Event::setIcons() {
clearIcons();
const int w = 16;
const int h = 16;
static const QPixmap defaultIcons = QPixmap(":/images/Entities_16x16.png");

51
src/core/filedialog.cpp Normal file
View File

@@ -0,0 +1,51 @@
#include "filedialog.h"
QString FileDialog::prevDirectory;
QString FileDialog::getDirectoryFromInput(const QString &dir) {
if (dir.isEmpty())
return FileDialog::prevDirectory;
return dir;
}
void FileDialog::setDirectoryFromFile(const QString &fileName) {
if (!fileName.isEmpty())
FileDialog::prevDirectory = QFileInfo(fileName).absolutePath();
}
void FileDialog::restoreFocus(QWidget *parent) {
if (parent) {
parent->raise();
parent->activateWindow();
}
}
QString FileDialog::getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options) {
const QString fileName = QFileDialog::getOpenFileName(parent, caption, getDirectoryFromInput(dir), filter, selectedFilter, options);
setDirectoryFromFile(fileName);
restoreFocus(parent);
return fileName;
}
QStringList FileDialog::getOpenFileNames(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options) {
const QStringList fileNames = QFileDialog::getOpenFileNames(parent, caption, getDirectoryFromInput(dir), filter, selectedFilter, options);
if (!fileNames.isEmpty())
setDirectoryFromFile(fileNames.last());
restoreFocus(parent);
return fileNames;
}
QString FileDialog::getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options) {
const QString fileName = QFileDialog::getSaveFileName(parent, caption, getDirectoryFromInput(dir), filter, selectedFilter, options);
setDirectoryFromFile(fileName);
restoreFocus(parent);
return fileName;
}
QString FileDialog::getExistingDirectory(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options) {
const QString existingDir = QFileDialog::getExistingDirectory(parent, caption, getDirectoryFromInput(dir), options);
if (!existingDir.isEmpty())
setDirectory(existingDir);
restoreFocus(parent);
return existingDir;
}

View File

@@ -28,6 +28,13 @@ void Map::setName(QString mapName) {
scriptsLoaded = false;
}
void Map::setLayout(Layout *layout) {
this->layout = layout;
if (layout) {
this->layoutId = layout->id;
}
}
QString Map::mapConstantFromName(QString mapName, bool includePrefix) {
// Transform map names of the form 'GraniteCave_B1F` into map constants like 'MAP_GRANITE_CAVE_B1F'.
static const QRegularExpression caseChange("([a-z])([A-Z])");
@@ -60,165 +67,10 @@ int Map::getBorderHeight() {
return layout->getBorderHeight();
}
bool Map::mapBlockChanged(int i, const Blockdata &cache) {
if (cache.length() <= i)
return true;
if (layout->blockdata.length() <= i)
return true;
return layout->blockdata.at(i) != cache.at(i);
}
bool Map::borderBlockChanged(int i, const Blockdata &cache) {
if (cache.length() <= i)
return true;
if (layout->border.length() <= i)
return true;
return layout->border.at(i) != cache.at(i);
}
void Map::clearBorderCache() {
layout->cached_border.clear();
}
void Map::cacheBorder() {
layout->cached_border.clear();
for (const auto &block : layout->border)
layout->cached_border.append(block);
}
void Map::cacheBlockdata() {
layout->cached_blockdata.clear();
for (const auto &block : layout->blockdata)
layout->cached_blockdata.append(block);
}
void Map::cacheCollision() {
layout->cached_collision.clear();
for (const auto &block : layout->blockdata)
layout->cached_collision.append(block);
}
QPixmap Map::renderCollision(bool ignoreCache) {
bool changed_any = false;
int width_ = getWidth();
int height_ = getHeight();
if (collision_image.isNull() || collision_image.width() != width_ * 16 || collision_image.height() != height_ * 16) {
collision_image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888);
changed_any = true;
}
if (layout->blockdata.isEmpty() || !width_ || !height_) {
collision_pixmap = collision_pixmap.fromImage(collision_image);
return collision_pixmap;
}
QPainter painter(&collision_image);
for (int i = 0; i < layout->blockdata.length(); i++) {
if (!ignoreCache && !mapBlockChanged(i, layout->cached_collision)) {
continue;
}
changed_any = true;
Block block = layout->blockdata.at(i);
QImage collision_metatile_image = getCollisionMetatileImage(block);
int map_y = width_ ? i / width_ : 0;
int map_x = width_ ? i % width_ : 0;
QPoint metatile_origin = QPoint(map_x * 16, map_y * 16);
painter.drawImage(metatile_origin, collision_metatile_image);
}
painter.end();
cacheCollision();
if (changed_any) {
collision_pixmap = collision_pixmap.fromImage(collision_image);
}
return collision_pixmap;
}
QPixmap Map::render(bool ignoreCache, MapLayout * fromLayout, QRect bounds) {
bool changed_any = false;
int width_ = getWidth();
int height_ = getHeight();
if (image.isNull() || image.width() != width_ * 16 || image.height() != height_ * 16) {
image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888);
changed_any = true;
}
if (layout->blockdata.isEmpty() || !width_ || !height_) {
pixmap = pixmap.fromImage(image);
return pixmap;
}
QPainter painter(&image);
for (int i = 0; i < layout->blockdata.length(); i++) {
if (!ignoreCache && !mapBlockChanged(i, layout->cached_blockdata)) {
continue;
}
changed_any = true;
int map_y = width_ ? i / width_ : 0;
int map_x = width_ ? i % width_ : 0;
if (bounds.isValid() && !bounds.contains(map_x, map_y)) {
continue;
}
QPoint metatile_origin = QPoint(map_x * 16, map_y * 16);
Block block = layout->blockdata.at(i);
QImage metatile_image = getMetatileImage(
block.metatileId(),
fromLayout ? fromLayout->tileset_primary : layout->tileset_primary,
fromLayout ? fromLayout->tileset_secondary : layout->tileset_secondary,
metatileLayerOrder,
metatileLayerOpacity
);
painter.drawImage(metatile_origin, metatile_image);
}
painter.end();
if (changed_any) {
cacheBlockdata();
pixmap = pixmap.fromImage(image);
}
return pixmap;
}
QPixmap Map::renderBorder(bool ignoreCache) {
bool changed_any = false, border_resized = false;
int width_ = getBorderWidth();
int height_ = getBorderHeight();
if (layout->border_image.isNull()) {
layout->border_image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888);
changed_any = true;
}
if (layout->border_image.width() != width_ * 16 || layout->border_image.height() != height_ * 16) {
layout->border_image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888);
border_resized = true;
}
if (layout->border.isEmpty()) {
layout->border_pixmap = layout->border_pixmap.fromImage(layout->border_image);
return layout->border_pixmap;
}
QPainter painter(&layout->border_image);
for (int i = 0; i < layout->border.length(); i++) {
if (!ignoreCache && (!border_resized && !borderBlockChanged(i, layout->cached_border))) {
continue;
}
changed_any = true;
Block block = layout->border.at(i);
uint16_t metatileId = block.metatileId();
QImage metatile_image = getMetatileImage(metatileId, layout->tileset_primary, layout->tileset_secondary, metatileLayerOrder, metatileLayerOpacity);
int map_y = width_ ? i / width_ : 0;
int map_x = width_ ? i % width_ : 0;
painter.drawImage(QPoint(map_x * 16, map_y * 16), metatile_image);
}
painter.end();
if (changed_any) {
cacheBorder();
layout->border_pixmap = layout->border_pixmap.fromImage(layout->border_image);
}
return layout->border_pixmap;
}
// Get the portion of the map that can be rendered when rendered as a map connection.
// Cardinal connections render the nearest segment of their map and within the bounds of the border draw distance,
// Dive/Emerge connections are rendered normally within the bounds of their parent map.
QRect Map::getConnectionRect(const QString &direction, MapLayout * fromLayout) {
QRect Map::getConnectionRect(const QString &direction, Layout * fromLayout) {
int x = 0, y = 0;
int w = getWidth(), h = getHeight();
@@ -244,7 +96,7 @@ QRect Map::getConnectionRect(const QString &direction, MapLayout * fromLayout) {
return QRect(x, y, w, h);
}
QPixmap Map::renderConnection(const QString &direction, MapLayout * fromLayout) {
QPixmap Map::renderConnection(const QString &direction, Layout * fromLayout) {
QRect bounds = getConnectionRect(direction, fromLayout);
if (!bounds.isValid())
return QPixmap();
@@ -254,214 +106,14 @@ QPixmap Map::renderConnection(const QString &direction, MapLayout * fromLayout)
if (MapConnection::isDiving(direction))
fromLayout = nullptr;
render(true, fromLayout, bounds);
QImage connection_image = image.copy(bounds.x() * 16, bounds.y() * 16, bounds.width() * 16, bounds.height() * 16);
return QPixmap::fromImage(connection_image);
}
void Map::setNewDimensionsBlockdata(int newWidth, int newHeight) {
int oldWidth = getWidth();
int oldHeight = getHeight();
Blockdata newBlockdata;
for (int y = 0; y < newHeight; y++)
for (int x = 0; x < newWidth; x++) {
if (x < oldWidth && y < oldHeight) {
int index = y * oldWidth + x;
newBlockdata.append(layout->blockdata.value(index));
} else {
newBlockdata.append(0);
}
}
layout->blockdata = newBlockdata;
}
void Map::setNewBorderDimensionsBlockdata(int newWidth, int newHeight) {
int oldWidth = getBorderWidth();
int oldHeight = getBorderHeight();
Blockdata newBlockdata;
for (int y = 0; y < newHeight; y++)
for (int x = 0; x < newWidth; x++) {
if (x < oldWidth && y < oldHeight) {
int index = y * oldWidth + x;
newBlockdata.append(layout->border.value(index));
} else {
newBlockdata.append(0);
}
}
layout->border = newBlockdata;
}
void Map::setDimensions(int newWidth, int newHeight, bool setNewBlockdata, bool enableScriptCallback) {
if (setNewBlockdata) {
setNewDimensionsBlockdata(newWidth, newHeight);
}
int oldWidth = layout->width;
int oldHeight = layout->height;
layout->width = newWidth;
layout->height = newHeight;
if (enableScriptCallback && (oldWidth != newWidth || oldHeight != newHeight)) {
Scripting::cb_MapResized(oldWidth, oldHeight, newWidth, newHeight);
}
emit mapDimensionsChanged(QSize(getWidth(), getHeight()));
modify();
}
void Map::setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata, bool enableScriptCallback) {
if (setNewBlockdata) {
setNewBorderDimensionsBlockdata(newWidth, newHeight);
}
int oldWidth = layout->border_width;
int oldHeight = layout->border_height;
layout->border_width = newWidth;
layout->border_height = newHeight;
if (enableScriptCallback && (oldWidth != newWidth || oldHeight != newHeight)) {
Scripting::cb_BorderResized(oldWidth, oldHeight, newWidth, newHeight);
}
modify();
QPixmap connectionPixmap = this->layout->render(true, fromLayout, bounds);
return connectionPixmap.copy(bounds.x() * 16, bounds.y() * 16, bounds.width() * 16, bounds.height() * 16);
}
void Map::openScript(QString label) {
emit openScriptRequested(label);
}
bool Map::getBlock(int x, int y, Block *out) {
if (isWithinBounds(x, y)) {
int i = y * getWidth() + x;
*out = layout->blockdata.value(i);
return true;
}
return false;
}
void Map::setBlock(int x, int y, Block block, bool enableScriptCallback) {
if (!isWithinBounds(x, y)) return;
int i = y * getWidth() + x;
if (i < layout->blockdata.size()) {
Block prevBlock = layout->blockdata.at(i);
layout->blockdata.replace(i, block);
if (enableScriptCallback) {
Scripting::cb_MetatileChanged(x, y, prevBlock, block);
}
}
}
void Map::setBlockdata(Blockdata blockdata, bool enableScriptCallback) {
int width = getWidth();
int size = qMin(blockdata.size(), layout->blockdata.size());
for (int i = 0; i < size; i++) {
Block prevBlock = layout->blockdata.at(i);
Block newBlock = blockdata.at(i);
if (prevBlock != newBlock) {
layout->blockdata.replace(i, newBlock);
if (enableScriptCallback)
Scripting::cb_MetatileChanged(i % width, i / width, prevBlock, newBlock);
}
}
}
uint16_t Map::getBorderMetatileId(int x, int y) {
int i = y * getBorderWidth() + x;
return layout->border[i].metatileId();
}
void Map::setBorderMetatileId(int x, int y, uint16_t metatileId, bool enableScriptCallback) {
int i = y * getBorderWidth() + x;
if (i < layout->border.size()) {
uint16_t prevMetatileId = layout->border[i].metatileId();
layout->border[i].setMetatileId(metatileId);
if (prevMetatileId != metatileId && enableScriptCallback) {
Scripting::cb_BorderMetatileChanged(x, y, prevMetatileId, metatileId);
}
}
}
void Map::setBorderBlockData(Blockdata blockdata, bool enableScriptCallback) {
int width = getBorderWidth();
int size = qMin(blockdata.size(), layout->border.size());
for (int i = 0; i < size; i++) {
Block prevBlock = layout->border.at(i);
Block newBlock = blockdata.at(i);
if (prevBlock != newBlock) {
layout->border.replace(i, newBlock);
if (enableScriptCallback)
Scripting::cb_BorderMetatileChanged(i % width, i / width, prevBlock.metatileId(), newBlock.metatileId());
}
}
}
void Map::_floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation) {
QList<QPoint> todo;
todo.append(QPoint(x, y));
while (todo.length()) {
QPoint point = todo.takeAt(0);
x = point.x();
y = point.y();
Block block;
if (!getBlock(x, y, &block)) {
continue;
}
uint old_coll = block.collision();
uint old_elev = block.elevation();
if (old_coll == collision && old_elev == elevation) {
continue;
}
block.setCollision(collision);
block.setElevation(elevation);
setBlock(x, y, block, true);
if (getBlock(x + 1, y, &block) && block.collision() == old_coll && block.elevation() == old_elev) {
todo.append(QPoint(x + 1, y));
}
if (getBlock(x - 1, y, &block) && block.collision() == old_coll && block.elevation() == old_elev) {
todo.append(QPoint(x - 1, y));
}
if (getBlock(x, y + 1, &block) && block.collision() == old_coll && block.elevation() == old_elev) {
todo.append(QPoint(x, y + 1));
}
if (getBlock(x, y - 1, &block) && block.collision() == old_coll && block.elevation() == old_elev) {
todo.append(QPoint(x, y - 1));
}
}
}
void Map::floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation) {
Block block;
if (getBlock(x, y, &block) && (block.collision() != collision || block.elevation() != elevation)) {
_floodFillCollisionElevation(x, y, collision, elevation);
}
}
void Map::magicFillCollisionElevation(int initialX, int initialY, uint16_t collision, uint16_t elevation) {
Block block;
if (getBlock(initialX, initialY, &block) && (block.collision() != collision || block.elevation() != elevation)) {
uint old_coll = block.collision();
uint old_elev = block.elevation();
for (int y = 0; y < getHeight(); y++) {
for (int x = 0; x < getWidth(); x++) {
if (getBlock(x, y, &block) && block.collision() == old_coll && block.elevation() == old_elev) {
block.setCollision(collision);
block.setElevation(elevation);
setBlock(x, y, block, true);
}
}
}
}
}
QList<Event *> Map::getAllEvents() const {
QList<Event *> all_events;
for (const auto &event_list : events) {
@@ -604,8 +256,8 @@ void Map::clean() {
this->hasUnsavedDataChanges = false;
}
bool Map::hasUnsavedChanges() {
return !editHistory.isClean() || hasUnsavedDataChanges || !isPersistedToFile;
bool Map::hasUnsavedChanges() const {
return !editHistory.isClean() || this->layout->hasUnsavedChanges() || hasUnsavedDataChanges || !isPersistedToFile;
}
void Map::pruneEditHistory() {
@@ -628,11 +280,3 @@ void Map::pruneEditHistory() {
command->setObsolete(true);
}
}
bool Map::isWithinBounds(int x, int y) {
return (x >= 0 && x < this->getWidth() && y >= 0 && y < this->getHeight());
}
bool Map::isWithinBorderBounds(int x, int y) {
return (x >= 0 && x < this->getBorderWidth() && y >= 0 && y < this->getBorderHeight());
}

View File

@@ -2,7 +2,35 @@
#include <QRegularExpression>
QString MapLayout::layoutConstantFromName(QString mapName) {
#include "scripting.h"
#include "imageproviders.h"
Layout *Layout::copy() {
Layout *layout = new Layout;
layout->copyFrom(this);
return layout;
}
void Layout::copyFrom(Layout *other) {
this->id = other->id;
this->name = other->name;
this->width = other->width;
this->height = other->height;
this->border_width = other->border_width;
this->border_height = other->border_height;
this->border_path = other->border_path;
this->blockdata_path = other->blockdata_path;
this->tileset_primary_label = other->tileset_primary_label;
this->tileset_secondary_label = other->tileset_secondary_label;
this->tileset_primary = other->tileset_primary;
this->tileset_secondary = other->tileset_secondary;
this->blockdata = other->blockdata;
this->border = other->border;
}
QString Layout::layoutConstantFromName(QString mapName) {
// Transform map names of the form 'GraniteCave_B1F` into layout constants like 'LAYOUT_GRANITE_CAVE_B1F'.
static const QRegularExpression caseChange("([a-z])([A-Z])");
QString nameWithUnderscores = mapName.replace(caseChange, "\\1_\\2");
@@ -17,18 +45,379 @@ QString MapLayout::layoutConstantFromName(QString mapName) {
return constantName;
}
int MapLayout::getWidth() {
int Layout::getWidth() {
return width;
}
int MapLayout::getHeight() {
int Layout::getHeight() {
return height;
}
int MapLayout::getBorderWidth() {
int Layout::getBorderWidth() {
return border_width;
}
int MapLayout::getBorderHeight() {
int Layout::getBorderHeight() {
return border_height;
}
bool Layout::isWithinBounds(int x, int y) {
return (x >= 0 && x < this->getWidth() && y >= 0 && y < this->getHeight());
}
bool Layout::isWithinBorderBounds(int x, int y) {
return (x >= 0 && x < this->getBorderWidth() && y >= 0 && y < this->getBorderHeight());
}
bool Layout::getBlock(int x, int y, Block *out) {
if (isWithinBounds(x, y)) {
int i = y * getWidth() + x;
*out = this->blockdata.value(i);
return true;
}
return false;
}
void Layout::setBlock(int x, int y, Block block, bool enableScriptCallback) {
if (!isWithinBounds(x, y)) return;
int i = y * getWidth() + x;
if (i < this->blockdata.size()) {
Block prevBlock = this->blockdata.at(i);
this->blockdata.replace(i, block);
if (enableScriptCallback) {
Scripting::cb_MetatileChanged(x, y, prevBlock, block);
}
}
}
void Layout::setBlockdata(Blockdata newBlockdata, bool enableScriptCallback) {
int width = getWidth();
int size = qMin(newBlockdata.size(), this->blockdata.size());
for (int i = 0; i < size; i++) {
Block prevBlock = this->blockdata.at(i);
Block newBlock = newBlockdata.at(i);
if (prevBlock != newBlock) {
this->blockdata.replace(i, newBlock);
if (enableScriptCallback)
Scripting::cb_MetatileChanged(i % width, i / width, prevBlock, newBlock);
}
}
}
void Layout::clearBorderCache() {
this->cached_border.clear();
}
void Layout::cacheBorder() {
this->cached_border.clear();
for (const auto &block : this->border)
this->cached_border.append(block);
}
void Layout::cacheBlockdata() {
this->cached_blockdata.clear();
for (const auto &block : this->blockdata)
this->cached_blockdata.append(block);
}
void Layout::cacheCollision() {
this->cached_collision.clear();
for (const auto &block : this->blockdata)
this->cached_collision.append(block);
}
bool Layout::layoutBlockChanged(int i, const Blockdata &cache) {
if (cache.length() <= i)
return true;
if (this->blockdata.length() <= i)
return true;
return this->blockdata.at(i) != cache.at(i);
}
uint16_t Layout::getBorderMetatileId(int x, int y) {
int i = y * getBorderWidth() + x;
return this->border[i].metatileId();
}
void Layout::setBorderMetatileId(int x, int y, uint16_t metatileId, bool enableScriptCallback) {
int i = y * getBorderWidth() + x;
if (i < this->border.size()) {
uint16_t prevMetatileId = this->border[i].metatileId();
this->border[i].setMetatileId(metatileId);
if (prevMetatileId != metatileId && enableScriptCallback) {
Scripting::cb_BorderMetatileChanged(x, y, prevMetatileId, metatileId);
}
}
}
void Layout::setBorderBlockData(Blockdata newBlockdata, bool enableScriptCallback) {
int width = getBorderWidth();
int size = qMin(newBlockdata.size(), this->border.size());
for (int i = 0; i < size; i++) {
Block prevBlock = this->border.at(i);
Block newBlock = newBlockdata.at(i);
if (prevBlock != newBlock) {
this->border.replace(i, newBlock);
if (enableScriptCallback)
Scripting::cb_BorderMetatileChanged(i % width, i / width, prevBlock.metatileId(), newBlock.metatileId());
}
}
}
void Layout::setDimensions(int newWidth, int newHeight, bool setNewBlockdata, bool enableScriptCallback) {
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 layoutChanged(this);
emit layoutDimensionsChanged(QSize(getWidth(), getHeight()));
}
void Layout::setBorderDimensions(int newWidth, int newHeight, bool setNewBlockdata, bool enableScriptCallback) {
if (setNewBlockdata) {
setNewBorderDimensionsBlockdata(newWidth, newHeight);
}
int oldWidth = this->border_width;
int oldHeight = this->border_height;
this->border_width = newWidth;
this->border_height = newHeight;
if (enableScriptCallback && (oldWidth != newWidth || oldHeight != newHeight)) {
Scripting::cb_BorderResized(oldWidth, oldHeight, newWidth, newHeight);
}
emit layoutChanged(this);
}
void Layout::setNewDimensionsBlockdata(int newWidth, int newHeight) {
int oldWidth = getWidth();
int oldHeight = getHeight();
Blockdata newBlockdata;
for (int y = 0; y < newHeight; y++)
for (int x = 0; x < newWidth; x++) {
if (x < oldWidth && y < oldHeight) {
int index = y * oldWidth + x;
newBlockdata.append(this->blockdata.value(index));
} else {
newBlockdata.append(0);
}
}
this->blockdata = newBlockdata;
}
void Layout::setNewBorderDimensionsBlockdata(int newWidth, int newHeight) {
int oldWidth = getBorderWidth();
int oldHeight = getBorderHeight();
Blockdata newBlockdata;
for (int y = 0; y < newHeight; y++)
for (int x = 0; x < newWidth; x++) {
if (x < oldWidth && y < oldHeight) {
int index = y * oldWidth + x;
newBlockdata.append(this->border.value(index));
} else {
newBlockdata.append(0);
}
}
this->border = newBlockdata;
}
void Layout::_floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation) {
QList<QPoint> todo;
todo.append(QPoint(x, y));
while (todo.length()) {
QPoint point = todo.takeAt(0);
x = point.x();
y = point.y();
Block block;
if (!getBlock(x, y, &block)) {
continue;
}
uint old_coll = block.collision();
uint old_elev = block.elevation();
if (old_coll == collision && old_elev == elevation) {
continue;
}
block.setCollision(collision);
block.setElevation(elevation);
setBlock(x, y, block, true);
if (getBlock(x + 1, y, &block) && block.collision() == old_coll && block.elevation() == old_elev) {
todo.append(QPoint(x + 1, y));
}
if (getBlock(x - 1, y, &block) && block.collision() == old_coll && block.elevation()== old_elev) {
todo.append(QPoint(x - 1, y));
}
if (getBlock(x, y + 1, &block) && block.collision() == old_coll && block.elevation() == old_elev) {
todo.append(QPoint(x, y + 1));
}
if (getBlock(x, y - 1, &block) && block.collision() == old_coll && block.elevation() == old_elev) {
todo.append(QPoint(x, y - 1));
}
}
}
void Layout::floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation) {
Block block;
if (getBlock(x, y, &block) && (block.collision() != collision || block.elevation() != elevation)) {
_floodFillCollisionElevation(x, y, collision, elevation);
}
}
void Layout::magicFillCollisionElevation(int initialX, int initialY, uint16_t collision, uint16_t elevation) {
Block block;
if (getBlock(initialX, initialY, &block) && (block.collision() != collision || block.elevation() != elevation)) {
uint old_coll = block.collision();
uint old_elev = block.elevation();
for (int y = 0; y < getHeight(); y++) {
for (int x = 0; x < getWidth(); x++) {
if (getBlock(x, y, &block) && block.collision() == old_coll && block.elevation() == old_elev) {
block.setCollision(collision);
block.setElevation(elevation);
setBlock(x, y, block, true);
}
}
}
}
}
QPixmap Layout::render(bool ignoreCache, Layout *fromLayout, QRect bounds) {
bool changed_any = false;
int width_ = getWidth();
int height_ = getHeight();
if (image.isNull() || image.width() != width_ * 16 || image.height() != height_ * 16) {
image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888);
changed_any = true;
}
if (this->blockdata.isEmpty() || !width_ || !height_) {
pixmap = pixmap.fromImage(image);
return pixmap;
}
QPainter painter(&image);
for (int i = 0; i < this->blockdata.length(); i++) {
if (!ignoreCache && !layoutBlockChanged(i, this->cached_blockdata)) {
continue;
}
changed_any = true;
int map_y = width_ ? i / width_ : 0;
int map_x = width_ ? i % width_ : 0;
if (bounds.isValid() && !bounds.contains(map_x, map_y)) {
continue;
}
QPoint metatile_origin = QPoint(map_x * 16, map_y * 16);
Block block = this->blockdata.at(i);
QImage metatile_image = getMetatileImage(
block.metatileId(),
fromLayout ? fromLayout->tileset_primary : this->tileset_primary,
fromLayout ? fromLayout->tileset_secondary : this->tileset_secondary,
metatileLayerOrder,
metatileLayerOpacity
);
painter.drawImage(metatile_origin, metatile_image);
}
painter.end();
if (changed_any) {
cacheBlockdata();
pixmap = pixmap.fromImage(image);
}
return pixmap;
}
QPixmap Layout::renderCollision(bool ignoreCache) {
bool changed_any = false;
int width_ = getWidth();
int height_ = getHeight();
if (collision_image.isNull() || collision_image.width() != width_ * 16 || collision_image.height() != height_ * 16) {
collision_image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888);
changed_any = true;
}
if (this->blockdata.isEmpty() || !width_ || !height_) {
collision_pixmap = collision_pixmap.fromImage(collision_image);
return collision_pixmap;
}
QPainter painter(&collision_image);
for (int i = 0; i < this->blockdata.length(); i++) {
if (!ignoreCache && !layoutBlockChanged(i, this->cached_collision)) {
continue;
}
changed_any = true;
Block block = this->blockdata.at(i);
QImage collision_metatile_image = getCollisionMetatileImage(block);
int map_y = width_ ? i / width_ : 0;
int map_x = width_ ? i % width_ : 0;
QPoint metatile_origin = QPoint(map_x * 16, map_y * 16);
painter.drawImage(metatile_origin, collision_metatile_image);
}
painter.end();
cacheCollision();
if (changed_any) {
collision_pixmap = collision_pixmap.fromImage(collision_image);
}
return collision_pixmap;
}
QPixmap Layout::renderBorder(bool ignoreCache) {
bool changed_any = false, border_resized = false;
int width_ = getBorderWidth();
int height_ = getBorderHeight();
if (this->border_image.isNull()) {
this->border_image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888);
changed_any = true;
}
if (this->border_image.width() != width_ * 16 || this->border_image.height() != height_ * 16) {
this->border_image = QImage(width_ * 16, height_ * 16, QImage::Format_RGBA8888);
border_resized = true;
}
if (this->border.isEmpty()) {
this->border_pixmap = this->border_pixmap.fromImage(this->border_image);
return this->border_pixmap;
}
QPainter painter(&this->border_image);
for (int i = 0; i < this->border.length(); i++) {
if (!ignoreCache && (!border_resized && !layoutBlockChanged(i, this->cached_border))) {
continue;
}
changed_any = true;
Block block = this->border.at(i);
uint16_t metatileId = block.metatileId();
QImage metatile_image = getMetatileImage(metatileId, this->tileset_primary, this->tileset_secondary, metatileLayerOrder, metatileLayerOpacity);
int map_y = width_ ? i / width_ : 0;
int map_x = width_ ? i % width_ : 0;
painter.drawImage(QPoint(map_x * 16, map_y * 16), metatile_image);
}
painter.end();
if (changed_any) {
cacheBorder();
this->border_pixmap = this->border_pixmap.fromImage(this->border_image);
}
return this->border_pixmap;
}
QPixmap Layout::getLayoutItemPixmap() {
return this->layoutItem ? this->layoutItem->pixmap() : QPixmap();
}
bool Layout::hasUnsavedChanges() const {
return !this->editHistory.isClean();
}

View File

@@ -7,7 +7,7 @@ MapParser::MapParser()
{
}
MapLayout *MapParser::parse(QString filepath, bool *error, Project *project)
Layout *MapParser::parse(QString filepath, bool *error, Project *project)
{
QFile file(filepath);
if (!file.open(QIODevice::ReadOnly)) {
@@ -69,7 +69,7 @@ MapLayout *MapParser::parse(QString filepath, bool *error, Project *project)
}
}
MapLayout *mapLayout = new MapLayout();
Layout *mapLayout = new Layout();
mapLayout->width = mapWidth;
mapLayout->height = mapHeight;
mapLayout->border_width = (borderWidth == 0) ? DEFAULT_BORDER_WIDTH : borderWidth;

View File

@@ -49,10 +49,10 @@ void ParseUtil::recordErrors(const QStringList &errors) {
}
void ParseUtil::logRecordedErrors() {
QStringList errors = this->errorMap.value(this->curDefine);
const QStringList errors = this->errorMap.value(this->curDefine);
if (errors.isEmpty()) return;
QString message = QString("Failed to parse '%1':").arg(this->curDefine);
for (const auto error : errors)
for (const auto &error : errors)
message.append(QString("\n%1").arg(error));
logError(message);
}
@@ -370,13 +370,14 @@ QStringList ParseUtil::readCIncbinArray(const QString &filename, const QString &
return paths;
}
bool ParseUtil::defineNameMatchesFilter(const QString &name, const QStringList &filterList, bool useRegex) {
bool ParseUtil::defineNameMatchesFilter(const QString &name, const QStringList &filterList) const {
return filterList.contains(name);
}
bool ParseUtil::defineNameMatchesFilter(const QString &name, const QList<QRegularExpression> &filterList) const {
for (auto filter : filterList) {
if (useRegex) {
// TODO: These QRegularExpression should probably be constructed beforehand,
// otherwise we recreate them for every define we check.
if (QRegularExpression(filter).match(name).hasMatch()) return true;
} else if (name == filter) return true;
if (filter.match(name).hasMatch())
return true;
}
return false;
}
@@ -405,6 +406,21 @@ ParseUtil::ParsedDefines ParseUtil::readCDefines(const QString &filename, const
if (this->text.isEmpty())
return result;
// If necessary, construct regular expressions from filter list
QList<QRegularExpression> filterList_Regex;
if (useRegex) {
for (auto filter : filterList) {
filterList_Regex.append(QRegularExpression(filter));
}
}
// Create lambda function to match the define name to the filter, depending on the filter type
auto matchesFilter = [this, &filterList, &filterList_Regex, useRegex](const QString &name) {
if (useRegex)
return defineNameMatchesFilter(name, filterList_Regex);
return defineNameMatchesFilter(name, filterList);
};
// Capture either the name and value of a #define, or everything between the braces of 'enum { }'
static const QRegularExpression re("#define\\s+(?<defineName>\\w+)[\\s\\n][^\\S\\n]*(?<defineValue>.+)?"
"|\\benum\\b[^{]*{(?<enumBody>[^}]*)}");
@@ -437,14 +453,14 @@ ParseUtil::ParsedDefines ParseUtil::readCDefines(const QString &filename, const
baseNum = 1;
}
result.expressions.insert(name, expression);
if (defineNameMatchesFilter(name, filterList, useRegex))
if (matchesFilter(name))
result.filteredNames.append(name);
}
} else {
// Encountered a #define
const QString name = match.captured("defineName");
result.expressions.insert(name, match.captured("defineValue"));
if (defineNameMatchesFilter(name, filterList, useRegex))
if (matchesFilter(name))
result.filteredNames.append(name);
}
}
@@ -580,7 +596,7 @@ bool ParseUtil::gameStringToBool(QString gameString, bool * ok) {
QMap<QString, QHash<QString, QString>> ParseUtil::readCStructs(const QString &filename, const QString &label, const QHash<int, QString> memberMap) {
QString filePath = this->root + "/" + filename;
auto cParser = fex::Parser();
auto tokens = fex::Lexer().LexFile(filePath.toStdString());
auto tokens = fex::Lexer().LexFile(filePath);
auto structs = cParser.ParseTopLevelObjects(tokens);
QMap<QString, QHash<QString, QString>> structMaps;
for (auto it = structs.begin(); it != structs.end(); it++) {

View File

@@ -19,8 +19,7 @@ using std::make_shared;
RegionMap::RegionMap(Project *project) :
section_prefix(projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix)),
default_map_section(section_prefix + projectConfig.getIdentifier(ProjectIdentifier::define_map_section_empty)),
count_map_section(section_prefix + projectConfig.getIdentifier(ProjectIdentifier::define_map_section_count))
default_map_section(project->getEmptyMapsecName())
{
this->project = project;
}
@@ -157,7 +156,7 @@ bool RegionMap::loadLayout(poryjson::Json layoutJson) {
for (int x = 0; x < this->layout_width; x++) {
int bin_index = x + y * this->layout_width;
uint8_t square_section_id = mapBinData.at(bin_index);
QString square_section_name = project->mapSectionValueToName.value(square_section_id);
QString square_section_name = project->mapSectionIdNames.value(square_section_id, this->default_map_section);
LayoutSquare square;
square.map_section = square_section_name;
@@ -401,7 +400,7 @@ void RegionMap::saveLayout() {
for (int m = 0; m < this->layout_height; m++) {
for (int n = 0; n < this->layout_width; n++) {
int i = n + this->layout_width * m;
data.append(this->project->mapSectionNameToValue.value(this->layouts["main"][i].map_section));
data.append(this->project->mapSectionIdNames.indexOf(this->layouts["main"][i].map_section));
}
}
QFile bfile(fullPath(this->layout_path));
@@ -760,18 +759,15 @@ bool RegionMap::squareInLayout(int x, int y) {
}
MapSectionEntry RegionMap::getEntry(QString section) {
if (this->region_map_entries->contains(section))
return this->region_map_entries->operator[](section);
else
return MapSectionEntry();
return this->region_map_entries->value(section, MapSectionEntry());
}
void RegionMap::setEntry(QString section, MapSectionEntry entry) {
this->region_map_entries->operator[](section) = entry;
this->region_map_entries->insert(section, entry);
}
void RegionMap::removeEntry(QString section) {
this->region_map_entries->erase(section);
this->region_map_entries->remove(section);
}
QString RegionMap::palPath() {
@@ -788,27 +784,6 @@ int RegionMap::getMapSquareIndex(int x, int y) {
return ((index < tilemap.length()) && (index >= 0)) ? index : 0;
}
// For turning a MAPSEC_NAME into a unique identifier sMapName-style variable.
// CAPS_WITH_UNDERSCORE to CamelCase
QString RegionMap::fixCase(QString caps) {
bool big = true;
QString camel;
static const QRegularExpression re_braced("({.*})");
for (auto ch : caps.remove(re_braced).remove(this->section_prefix)) {
if (ch == '_' || ch == ' ') {
big = true;
continue;
}
if (big) {
camel += ch.toUpper();
big = false;
}
else camel += ch.toLower();
}
return camel;
}
QString RegionMap::fullPath(QString local) {
return this->project->root + "/" + local;
}

View File

@@ -90,7 +90,7 @@ bool EditLayout::mergeWith(const QUndoCommand *command) {
///
ResizeLayout::ResizeLayout(RegionMap *map, int oldWidth, int oldHeight, int newWidth, int newHeight,
ResizeRMLayout::ResizeRMLayout(RegionMap *map, int oldWidth, int oldHeight, int newWidth, int newHeight,
QMap<QString, QList<LayoutSquare>> oldLayouts, QMap<QString, QList<LayoutSquare>> newLayouts, QUndoCommand *parent)
: QUndoCommand(parent) {
setText("Change Layout Dimensions");
@@ -104,7 +104,7 @@ ResizeLayout::ResizeLayout(RegionMap *map, int oldWidth, int oldHeight, int newW
this->newLayouts = newLayouts;
}
void ResizeLayout::redo() {
void ResizeRMLayout::redo() {
QUndoCommand::redo();
if (!map) return;
@@ -113,7 +113,7 @@ void ResizeLayout::redo() {
map->setAllLayouts(this->newLayouts);
}
void ResizeLayout::undo() {
void ResizeRMLayout::undo() {
if (!map) return;
map->setLayoutDimensions(oldWidth, oldHeight, false);
@@ -122,8 +122,8 @@ void ResizeLayout::undo() {
QUndoCommand::undo();
}
bool ResizeLayout::mergeWith(const QUndoCommand *command) {
const ResizeLayout *other = static_cast<const ResizeLayout *>(command);
bool ResizeRMLayout::mergeWith(const QUndoCommand *command) {
const ResizeRMLayout *other = static_cast<const ResizeRMLayout *>(command);
if (this->map != other->map)
return false;
@@ -260,7 +260,7 @@ void ResizeTilemap::undo() {
///
ClearEntries::ClearEntries(RegionMap *map, tsl::ordered_map<QString, MapSectionEntry> entries, QUndoCommand *parent)
ClearEntries::ClearEntries(RegionMap *map, QMap<QString, MapSectionEntry> entries, QUndoCommand *parent)
: QUndoCommand(parent) {
setText("Clear Entries");

View File

@@ -29,8 +29,8 @@ Tileset::Tileset(const Tileset &other)
tiles.append(tile.copy());
}
for (auto *metatile : other.metatiles) {
metatiles.append(new Metatile(*metatile));
for (auto *metatile : other.m_metatiles) {
m_metatiles.append(new Metatile(*metatile));
}
}
@@ -55,14 +55,42 @@ Tileset &Tileset::operator=(const Tileset &other) {
tiles.append(tile.copy());
}
metatiles.clear();
for (auto *metatile : other.metatiles) {
metatiles.append(new Metatile(*metatile));
clearMetatiles();
for (auto *metatile : other.m_metatiles) {
m_metatiles.append(new Metatile(*metatile));
}
return *this;
}
Tileset::~Tileset() {
clearMetatiles();
}
void Tileset::clearMetatiles() {
qDeleteAll(m_metatiles);
m_metatiles.clear();
}
void Tileset::setMetatiles(const QList<Metatile*> &metatiles) {
clearMetatiles();
m_metatiles = metatiles;
}
void Tileset::addMetatile(Metatile* metatile) {
m_metatiles.append(metatile);
}
void Tileset::resizeMetatiles(unsigned int newNumMetatiles) {
while (m_metatiles.length() > newNumMetatiles) {
delete m_metatiles.takeLast();
}
const int numTiles = projectConfig.getNumTilesInMetatile();
while (m_metatiles.length() < newNumMetatiles) {
m_metatiles.append(new Metatile(numTiles));
}
}
Tileset* Tileset::getTileTileset(int tileId, Tileset *primaryTileset, Tileset *secondaryTileset) {
if (tileId < Project::getNumTilesPrimary()) {
return primaryTileset;
@@ -89,7 +117,7 @@ Metatile* Tileset::getMetatile(int metatileId, Tileset *primaryTileset, Tileset
return nullptr;
}
int index = Metatile::getIndexInTileset(metatileId);
return tileset->metatiles.value(index, nullptr);
return tileset->m_metatiles.value(index, nullptr);
}
// Metatile labels are stored per-tileset. When looking for a metatile label, first search in the tileset
@@ -178,10 +206,10 @@ bool Tileset::metatileIsValid(uint16_t metatileId, Tileset *primaryTileset, Tile
if (metatileId >= Project::getNumMetatilesTotal())
return false;
if (metatileId < Project::getNumMetatilesPrimary() && metatileId >= primaryTileset->metatiles.length())
if (metatileId < Project::getNumMetatilesPrimary() && metatileId >= primaryTileset->numMetatiles())
return false;
if (metatileId >= Project::getNumMetatilesPrimary() + secondaryTileset->metatiles.length())
if (metatileId >= Project::getNumMetatilesPrimary() + secondaryTileset->numMetatiles())
return false;
return true;

View File

@@ -4,7 +4,7 @@
#include "log.h"
#include "connectionslistitem.h"
#include "currentselectedmetatilespixmapitem.h"
#include "mapsceneeventfilter.h"
#include "eventfilters.h"
#include "metatile.h"
#include "montabwidget.h"
#include "editcommands.h"
@@ -47,6 +47,10 @@ Editor::Editor(Ui::MainWindow* ui)
connect(ui->stackedWidget_WildMons, &QStackedWidget::currentChanged, [this] {
emit wildMonTableOpened(getCurrentWildMonTable());
});
connect(ui->toolButton_Open_Scripts, &QToolButton::pressed, this, &Editor::openMapScripts);
connect(ui->actionOpen_Project_in_Text_Editor, &QAction::triggered, this, &Editor::openProjectInTextEditor);
connect(ui->checkBox_ToggleGrid, &QCheckBox::toggled, this, &Editor::toggleGrid);
}
Editor::~Editor()
@@ -71,10 +75,14 @@ void Editor::saveProject() {
}
void Editor::save() {
if (project && map) {
if (this->project && this->map) {
saveUiFields();
project->saveMap(map);
project->saveAllDataStructures();
this->project->saveMap(this->map);
this->project->saveAllDataStructures();
}
else if (this->project && this->layout) {
this->project->saveLayout(this->layout);
this->project->saveAllDataStructures();
}
}
@@ -98,66 +106,103 @@ void Editor::closeProject() {
delete this->project;
}
void Editor::setEditingMap() {
current_view = map_item;
if (map_item) {
map_item->paintingMode = MapPixmapItem::PaintMode::Metatiles;
map_item->draw();
map_item->setVisible(true);
}
if (collision_item) {
collision_item->setVisible(false);
}
if (events_group) {
events_group->setVisible(false);
bool Editor::getEditingLayout() {
return this->editMode == EditMode::Metatiles || this->editMode == EditMode::Collision;
}
void Editor::setEditorView() {
// based on editMode
if (!map_item || !collision_item) return;
if (!this->layout) return;
map_item->setVisible(true); // is map item ever not visible
collision_item->setVisible(false);
switch (this->editMode) {
case EditMode::Metatiles:
case EditMode::Connections:
case EditMode::Events:
current_view = map_item;
break;
case EditMode::Collision:
current_view = collision_item;
break;
default:
current_view = nullptr;
return;
}
map_item->draw();
collision_item->draw();
current_view->setVisible(true);
updateBorderVisibility();
this->cursorMapTileRect->stopSingleTileMode();
this->cursorMapTileRect->setSingleTileMode();
this->cursorMapTileRect->setActive(true);
setMapEditingButtonsEnabled(true);
switch (this->editMode) {
case EditMode::Metatiles:
case EditMode::Collision:
map_item->setEditsEnabled(true);
this->editGroup.setActiveStack(&this->layout->editHistory);
break;
case EditMode::Connections:
this->cursorMapTileRect->setActive(false);
map_item->setEditsEnabled(false);
case EditMode::Events:
if (this->map) {
this->editGroup.setActiveStack(&this->map->editHistory);
}
break;
case EditMode::Header:
case EditMode::Encounters:
default:
this->editGroup.setActiveStack(nullptr);
break;
}
if (this->events_group) {
this->events_group->setVisible(this->editMode == EditMode::Events);
}
setMapEditingButtonsEnabled(this->editMode != EditMode::Events);
}
void Editor::setEditingMetatiles() {
this->editMode = EditMode::Metatiles;
setEditorView();
}
void Editor::setEditingCollision() {
current_view = collision_item;
if (collision_item) {
collision_item->draw();
collision_item->setVisible(true);
}
if (map_item) {
map_item->paintingMode = MapPixmapItem::PaintMode::Metatiles;
map_item->draw();
map_item->setVisible(true);
}
if (events_group) {
events_group->setVisible(false);
}
updateBorderVisibility();
this->cursorMapTileRect->setSingleTileMode();
this->cursorMapTileRect->setActive(true);
this->editMode = EditMode::Collision;
setMapEditingButtonsEnabled(true);
setEditorView();
}
void Editor::setEditingHeader() {
this->editMode = EditMode::Header;
setEditorView();
}
void Editor::setEditingObjects() {
current_view = map_item;
if (events_group) {
events_group->setVisible(true);
}
if (map_item) {
map_item->paintingMode = MapPixmapItem::PaintMode::EventObjects;
map_item->draw();
map_item->setVisible(true);
}
if (collision_item) {
collision_item->setVisible(false);
}
updateBorderVisibility();
this->cursorMapTileRect->setSingleTileMode();
this->cursorMapTileRect->setActive(false);
updateWarpEventWarnings();
this->editMode = EditMode::Events;
setMapEditingButtonsEnabled(false);
setEditorView();
updateWarpEventWarnings();
}
void Editor::setEditingConnections() {
this->editMode = EditMode::Connections;
setEditorView();
}
void Editor::setEditingEncounters() {
this->editMode = EditMode::Encounters;
setEditorView();
}
void Editor::setMapEditingButtonsEnabled(bool enabled) {
@@ -166,7 +211,7 @@ void Editor::setMapEditingButtonsEnabled(bool enabled) {
this->ui->pushButton_ChangeDimensions->setEnabled(enabled);
// If the fill button is pressed, unpress it and select the pointer.
if (!enabled && (this->ui->toolButton_Fill->isChecked() || this->ui->toolButton_Dropper->isChecked())) {
this->map_edit_mode = "select";
this->mapEditAction = EditAction::Select;
this->settings->mapCursor = QCursor();
this->cursorMapTileRect->setSingleTileMode();
this->ui->toolButton_Fill->setChecked(false);
@@ -176,24 +221,6 @@ void Editor::setMapEditingButtonsEnabled(bool enabled) {
this->ui->checkBox_smartPaths->setEnabled(enabled);
}
void Editor::setEditingConnections() {
current_view = map_item;
if (map_item) {
map_item->paintingMode = MapPixmapItem::PaintMode::Disabled;
map_item->draw();
map_item->setVisible(true);
}
if (collision_item) {
collision_item->setVisible(false);
}
if (events_group) {
events_group->setVisible(false);
}
updateBorderVisibility();
this->cursorMapTileRect->setSingleTileMode();
this->cursorMapTileRect->setActive(false);
}
void Editor::clearWildMonTables() {
QStackedWidget *stack = ui->stackedWidget_WildMons;
const QSignalBlocker blocker(stack);
@@ -784,6 +811,9 @@ void Editor::displayConnection(MapConnection *connection) {
connect(listItem, &ConnectionsListItem::openMapClicked, this, &Editor::openConnectedMap);
connect(pixmapItem, &ConnectionPixmapItem::connectionItemDoubleClicked, this, &Editor::openConnectedMap);
// Pressing the delete key on a selected connection's pixmap deletes it
connect(pixmapItem, &ConnectionPixmapItem::deleteRequested, this, &Editor::removeConnection);
// Sync the selection highlight between the list UI and the pixmap
connect(pixmapItem, &ConnectionPixmapItem::selectionChanged, [=](bool selected) {
listItem->setSelected(selected);
@@ -842,11 +872,6 @@ void Editor::removeConnection(MapConnection *connection) {
this->map->editHistory.push(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;
@@ -1055,8 +1080,8 @@ void Editor::onHoveredMovementPermissionCleared() {
}
QString Editor::getMetatileDisplayMessage(uint16_t metatileId) {
Metatile *metatile = Tileset::getMetatile(metatileId, map->layout->tileset_primary, map->layout->tileset_secondary);
QString label = Tileset::getMetatileLabel(metatileId, map->layout->tileset_primary, map->layout->tileset_secondary);
Metatile *metatile = Tileset::getMetatile(metatileId, this->layout->tileset_primary, this->layout->tileset_secondary);
QString label = Tileset::getMetatileLabel(metatileId, this->layout->tileset_primary, this->layout->tileset_secondary);
QString message = QString("Metatile: %1").arg(Metatile::getMetatileIdString(metatileId));
if (label.size())
message += QString(" \"%1\"").arg(label);
@@ -1142,46 +1167,46 @@ void Editor::setCursorRectVisible(bool visible) {
void Editor::onHoveredMapMetatileChanged(const QPoint &pos) {
int x = pos.x();
int y = pos.y();
if (!map->isWithinBounds(x, y))
if (!layout->isWithinBounds(x, y))
return;
this->updateCursorRectPos(x, y);
if (map_item->paintingMode == MapPixmapItem::PaintMode::Metatiles) {
int blockIndex = y * map->getWidth() + x;
int metatileId = map->layout->blockdata.at(blockIndex).metatileId();
if (this->getEditingLayout()) {
int blockIndex = y * layout->getWidth() + x;
int metatileId = layout->blockdata.at(blockIndex).metatileId();
this->ui->statusBar->showMessage(QString("X: %1, Y: %2, %3, Scale = %4x")
.arg(x)
.arg(y)
.arg(getMetatileDisplayMessage(metatileId))
.arg(QString::number(zoomLevels[this->scaleIndex], 'g', 2)));
}
else if (map_item->paintingMode == MapPixmapItem::PaintMode::EventObjects) {
else if (this->editMode == EditMode::Events) {
this->ui->statusBar->showMessage(QString("X: %1, Y: %2, Scale = %3x")
.arg(x)
.arg(y)
.arg(QString::number(zoomLevels[this->scaleIndex], 'g', 2)));
}
Scripting::cb_BlockHoverChanged(x, y);
}
void Editor::onHoveredMapMetatileCleared() {
this->setCursorRectVisible(false);
if (map_item->paintingMode == MapPixmapItem::PaintMode::Metatiles
|| map_item->paintingMode == MapPixmapItem::PaintMode::EventObjects) {
if (!map_item->getEditsEnabled()) {
this->ui->statusBar->clearMessage();
}
Scripting::cb_BlockHoverCleared();
}
void Editor::onHoveredMapMovementPermissionChanged(int x, int y) {
if (!map->isWithinBounds(x, y))
if (!layout->isWithinBounds(x, y))
return;
this->updateCursorRectPos(x, y);
if (map_item->paintingMode == MapPixmapItem::PaintMode::Metatiles) {
int blockIndex = y * map->getWidth() + x;
uint16_t collision = map->layout->blockdata.at(blockIndex).collision();
uint16_t elevation = map->layout->blockdata.at(blockIndex).elevation();
if (this->getEditingLayout()) {
int blockIndex = y * layout->getWidth() + x;
uint16_t collision = layout->blockdata.at(blockIndex).collision();
uint16_t elevation = layout->blockdata.at(blockIndex).elevation();
QString message = QString("X: %1, Y: %2, %3")
.arg(x)
.arg(y)
@@ -1193,7 +1218,7 @@ void Editor::onHoveredMapMovementPermissionChanged(int x, int y) {
void Editor::onHoveredMapMovementPermissionCleared() {
this->setCursorRectVisible(false);
if (map_item->paintingMode == MapPixmapItem::PaintMode::Metatiles) {
if (this->getEditingLayout()) {
this->ui->statusBar->clearMessage();
}
Scripting::cb_BlockHoverCleared();
@@ -1215,11 +1240,7 @@ QString Editor::getMovementPermissionText(uint16_t collision, uint16_t elevation
return message;
}
bool Editor::setMap(QString map_name) {
if (map_name.isEmpty()) {
return false;
}
void Editor::unsetMap() {
// disconnect previous map's signals so they are not firing
// multiple times if set again in the future
if (map) {
@@ -1228,47 +1249,90 @@ bool Editor::setMap(QString map_name) {
for (auto connection : map->getConnections())
disconnectMapConnection(connection);
}
clearMapConnections();
if (project) {
Map *loadedMap = project->loadMap(map_name);
if (!loadedMap) {
return false;
}
this->map = nullptr;
}
map = loadedMap;
editGroup.addStack(&map->editHistory);
editGroup.setActiveStack(&map->editHistory);
selected_events->clear();
if (!displayMap()) {
return false;
}
map_ruler->setMapDimensions(QSize(map->getWidth(), map->getHeight()));
connect(map, &Map::mapDimensionsChanged, map_ruler, &MapRuler::setMapDimensions);
connect(map, &Map::openScriptRequested, this, &Editor::openScript);
connect(map, &Map::connectionAdded, this, &Editor::displayConnection);
connect(map, &Map::connectionRemoved, this, &Editor::removeConnectionPixmap);
updateSelectedEvents();
bool Editor::setMap(QString map_name) {
if (!project || map_name.isEmpty()) {
return false;
}
unsetMap();
Map *loadedMap = project->loadMap(map_name);
if (!loadedMap) {
return false;
}
this->map = loadedMap;
setLayout(map->layout->id);
editGroup.addStack(&map->editHistory);
editGroup.setActiveStack(&map->editHistory);
selected_events->clear();
if (!displayMap()) {
return false;
}
displayWildMonTables();
connect(map, &Map::openScriptRequested, this, &Editor::openScript);
connect(map, &Map::connectionAdded, this, &Editor::displayConnection);
connect(map, &Map::connectionRemoved, this, &Editor::removeConnectionPixmap);
updateSelectedEvents();
return true;
}
void Editor::onMapStartPaint(QGraphicsSceneMouseEvent *event, MapPixmapItem *item) {
if (item->paintingMode != MapPixmapItem::PaintMode::Metatiles) {
bool Editor::setLayout(QString layoutId) {
if (!project || layoutId.isEmpty()) {
return false;
}
this->layout = this->project->loadLayout(layoutId);
if (!displayLayout()) {
return false;
}
editGroup.addStack(&layout->editHistory);
map_ruler->setMapDimensions(QSize(this->layout->getWidth(), this->layout->getHeight()));
connect(this->layout, &Layout::layoutDimensionsChanged, map_ruler, &MapRuler::setMapDimensions);
ui->comboBox_PrimaryTileset->blockSignals(true);
ui->comboBox_SecondaryTileset->blockSignals(true);
ui->comboBox_PrimaryTileset->setCurrentText(this->layout->tileset_primary_label);
ui->comboBox_SecondaryTileset->setCurrentText(this->layout->tileset_secondary_label);
ui->comboBox_PrimaryTileset->blockSignals(false);
ui->comboBox_SecondaryTileset->blockSignals(false);
const QSignalBlocker b0(this->ui->comboBox_LayoutSelector);
int index = this->ui->comboBox_LayoutSelector->findText(layoutId);
if (index < 0) index = 0;
this->ui->comboBox_LayoutSelector->setCurrentIndex(index);
return true;
}
void Editor::onMapStartPaint(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *) {
if (!this->getEditingLayout()) {
return;
}
QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
if (event->buttons() & Qt::RightButton && (map_edit_mode == "paint" || map_edit_mode == "fill")) {
if (event->buttons() & Qt::RightButton && (mapEditAction == EditAction::Paint || mapEditAction == EditAction::Fill)) {
this->cursorMapTileRect->initRightClickSelectionAnchor(pos.x(), pos.y());
} else {
this->cursorMapTileRect->initAnchor(pos.x(), pos.y());
}
}
void Editor::onMapEndPaint(QGraphicsSceneMouseEvent *, MapPixmapItem *item) {
if (!(item->paintingMode == MapPixmapItem::PaintMode::Metatiles)) {
void Editor::onMapEndPaint(QGraphicsSceneMouseEvent *, LayoutPixmapItem *) {
if (!this->getEditingLayout()) {
return;
}
this->cursorMapTileRect->stopRightClickSelectionAnchor();
@@ -1301,16 +1365,16 @@ void Editor::setStraightPathCursorMode(QGraphicsSceneMouseEvent *event) {
}
}
void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item) {
void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *item) {
// TODO: add event tab object painting tool buttons stuff here
if (item->paintingMode == MapPixmapItem::PaintMode::Disabled) {
if (!item->getEditsEnabled()) {
return;
}
QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
if (item->paintingMode == MapPixmapItem::PaintMode::Metatiles) {
if (map_edit_mode == "paint") {
if (this->getEditingLayout()) {
if (mapEditAction == EditAction::Paint) {
if (event->buttons() & Qt::RightButton) {
item->updateMetatileSelection(event);
} else if (event->buttons() & Qt::MiddleButton) {
@@ -1332,9 +1396,9 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item
}
item->paint(event);
}
} else if (map_edit_mode == "select") {
} else if (mapEditAction == EditAction::Select) {
item->select(event);
} else if (map_edit_mode == "fill") {
} else if (mapEditAction == EditAction::Fill) {
if (event->buttons() & Qt::RightButton) {
item->updateMetatileSelection(event);
} else if (event->modifiers() & Qt::ControlModifier) {
@@ -1342,13 +1406,13 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item
} else {
item->floodFill(event);
}
} else if (map_edit_mode == "pick") {
} else if (mapEditAction == EditAction::Pick) {
if (event->buttons() & Qt::RightButton) {
item->updateMetatileSelection(event);
} else {
item->pick(event);
}
} else if (map_edit_mode == "shift") {
} else if (mapEditAction == EditAction::Shift) {
this->setStraightPathCursorMode(event);
if (this->cursorMapTileRect->getStraightPathMode()) {
item->lockNondominantAxis(event);
@@ -1356,11 +1420,11 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item
}
item->shift(event);
}
} else if (item->paintingMode == MapPixmapItem::PaintMode::EventObjects) {
if (obj_edit_mode == "paint" && event->type() == QEvent::GraphicsSceneMousePress) {
} else if (this->editMode == EditMode::Events) {
if (objectEditAction == EditAction::Paint && event->type() == QEvent::GraphicsSceneMousePress) {
// Right-clicking while in paint mode will change mode to select.
if (event->buttons() & Qt::RightButton) {
this->obj_edit_mode = "select";
this->objectEditAction = EditAction::Select;
this->settings->mapCursor = QCursor();
this->cursorMapTileRect->setSingleTileMode();
this->ui->toolButton_Paint->setChecked(false);
@@ -1382,9 +1446,9 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item
}
}
}
} else if (obj_edit_mode == "select") {
} else if (objectEditAction == EditAction::Select) {
// do nothing here, at least for now
} else if (obj_edit_mode == "shift" && item->map) {
} else if (objectEditAction == EditAction::Shift) {
static QPoint selection_origin;
static unsigned actionId = 0;
@@ -1400,8 +1464,8 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item
QList<Event *> selectedEvents;
for (DraggablePixmapItem *item : getObjects()) {
selectedEvents.append(item->event);
for (DraggablePixmapItem *pixmapItem : getObjects()) {
selectedEvents.append(pixmapItem->event);
}
selection_origin = QPoint(pos.x(), pos.y());
@@ -1414,13 +1478,13 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item
}
void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item) {
if (item->paintingMode != MapPixmapItem::PaintMode::Metatiles) {
if (!item->getEditsEnabled()) {
return;
}
QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
if (map_edit_mode == "paint") {
if (mapEditAction == EditAction::Paint) {
if (event->buttons() & Qt::RightButton) {
item->updateMovementPermissionSelection(event);
} else if (event->buttons() & Qt::MiddleButton) {
@@ -1437,9 +1501,9 @@ void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixm
}
item->paint(event);
}
} else if (map_edit_mode == "select") {
} else if (mapEditAction == EditAction::Select) {
item->select(event);
} else if (map_edit_mode == "fill") {
} else if (mapEditAction == EditAction::Fill) {
if (event->buttons() & Qt::RightButton) {
item->pick(event);
} else if (event->modifiers() & Qt::ControlModifier) {
@@ -1447,9 +1511,9 @@ void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixm
} else {
item->floodFill(event);
}
} else if (map_edit_mode == "pick") {
} else if (mapEditAction == EditAction::Pick) {
item->pick(event);
} else if (map_edit_mode == "shift") {
} else if (mapEditAction == EditAction::Shift) {
this->setStraightPathCursorMode(event);
if (this->cursorMapTileRect->getStraightPathMode()) {
item->lockNondominantAxis(event);
@@ -1486,26 +1550,40 @@ void Editor::clearMap() {
}
bool Editor::displayMap() {
if (!this->map)
return false;
displayMapEvents();
displayMapConnections();
maskNonVisibleConnectionTiles();
if (events_group) {
events_group->setVisible(false);
}
return true;
}
bool Editor::displayLayout() {
if (!this->layout)
return false;
if (!scene) {
scene = new QGraphicsScene;
MapSceneEventFilter *filter = new MapSceneEventFilter();
MapSceneEventFilter *filter = new MapSceneEventFilter(scene);
scene->installEventFilter(filter);
connect(filter, &MapSceneEventFilter::wheelZoom, this, &Editor::onWheelZoom);
scene->installEventFilter(this->map_ruler);
}
clearConnectionMask();
displayMetatileSelector();
displayMovementPermissionSelector();
displayMapMetatiles();
displayMovementPermissionSelector();
displayMapMovementPermissions();
displayBorderMetatiles();
displayCurrentMetatilesSelection();
displayMapEvents();
displayMapConnections();
displayMapBorder();
displayMapGrid();
displayWildMonTables();
maskNonVisibleConnectionTiles();
this->map_ruler->setZValue(1000);
scene->addItem(this->map_ruler);
@@ -1516,9 +1594,7 @@ bool Editor::displayMap() {
if (collision_item) {
collision_item->setVisible(false);
}
if (events_group) {
events_group->setVisible(false);
}
return true;
}
@@ -1534,7 +1610,7 @@ void Editor::displayMetatileSelector() {
scene_metatiles = new QGraphicsScene;
if (!metatile_selector_item) {
metatile_selector_item = new MetatileSelector(8, map);
metatile_selector_item = new MetatileSelector(8, this->layout);
connect(metatile_selector_item, &MetatileSelector::hoveredMetatileSelectionChanged,
this, &Editor::onHoveredMetatileSelectionChanged);
connect(metatile_selector_item, &MetatileSelector::hoveredMetatileSelectionCleared,
@@ -1543,14 +1619,14 @@ void Editor::displayMetatileSelector() {
this, &Editor::onSelectedMetatilesChanged);
metatile_selector_item->select(0);
} else {
metatile_selector_item->setMap(map);
metatile_selector_item->setLayout(this->layout);
if (metatile_selector_item->primaryTileset
&& metatile_selector_item->primaryTileset != map->layout->tileset_primary)
emit tilesetUpdated(map->layout->tileset_primary->name);
&& metatile_selector_item->primaryTileset != this->layout->tileset_primary)
emit tilesetUpdated(this->layout->tileset_primary->name);
if (metatile_selector_item->secondaryTileset
&& metatile_selector_item->secondaryTileset != map->layout->tileset_secondary)
emit tilesetUpdated(map->layout->tileset_secondary->name);
metatile_selector_item->setTilesets(map->layout->tileset_primary, map->layout->tileset_secondary);
&& metatile_selector_item->secondaryTileset != this->layout->tileset_secondary)
emit tilesetUpdated(this->layout->tileset_secondary->name);
metatile_selector_item->setTilesets(this->layout->tileset_primary, this->layout->tileset_secondary);
}
scene_metatiles->addItem(metatile_selector_item);
@@ -1567,12 +1643,12 @@ void Editor::clearMapMetatiles() {
void Editor::displayMapMetatiles() {
clearMapMetatiles();
map_item = new MapPixmapItem(map, this->metatile_selector_item, this->settings);
connect(map_item, &MapPixmapItem::mouseEvent, this, &Editor::mouseEvent_map);
connect(map_item, &MapPixmapItem::startPaint, this, &Editor::onMapStartPaint);
connect(map_item, &MapPixmapItem::endPaint, this, &Editor::onMapEndPaint);
connect(map_item, &MapPixmapItem::hoveredMapMetatileChanged, this, &Editor::onHoveredMapMetatileChanged);
connect(map_item, &MapPixmapItem::hoveredMapMetatileCleared, this, &Editor::onHoveredMapMetatileCleared);
map_item = new LayoutPixmapItem(this->layout, this->metatile_selector_item, this->settings);
connect(map_item, &LayoutPixmapItem::mouseEvent, this, &Editor::mouseEvent_map);
connect(map_item, &LayoutPixmapItem::startPaint, this, &Editor::onMapStartPaint);
connect(map_item, &LayoutPixmapItem::endPaint, this, &Editor::onMapEndPaint);
connect(map_item, &LayoutPixmapItem::hoveredMapMetatileChanged, this, &Editor::onHoveredMapMetatileChanged);
connect(map_item, &LayoutPixmapItem::hoveredMapMetatileCleared, this, &Editor::onHoveredMapMetatileCleared);
map_item->draw(true);
scene->addItem(map_item);
@@ -1597,7 +1673,7 @@ void Editor::clearMapMovementPermissions() {
void Editor::displayMapMovementPermissions() {
clearMapMovementPermissions();
collision_item = new CollisionPixmapItem(map, ui->spinBox_SelectedCollision, ui->spinBox_SelectedElevation,
collision_item = new CollisionPixmapItem(this->layout, ui->spinBox_SelectedCollision, ui->spinBox_SelectedElevation,
this->metatile_selector_item, this->settings, &this->collisionOpacity);
connect(collision_item, &CollisionPixmapItem::mouseEvent, this, &Editor::mouseEvent_collision);
connect(collision_item, &CollisionPixmapItem::hoveredMapMovementPermissionChanged,
@@ -1621,7 +1697,7 @@ void Editor::displayBorderMetatiles() {
clearBorderMetatiles();
scene_selected_border_metatiles = new QGraphicsScene;
selected_border_metatiles_item = new BorderMetatilesPixmapItem(map, this->metatile_selector_item);
selected_border_metatiles_item = new BorderMetatilesPixmapItem(this->layout, this->metatile_selector_item);
selected_border_metatiles_item->draw();
scene_selected_border_metatiles->addItem(selected_border_metatiles_item);
@@ -1646,14 +1722,14 @@ void Editor::displayCurrentMetatilesSelection() {
clearCurrentMetatilesSelection();
scene_current_metatile_selection = new QGraphicsScene;
current_metatile_selection_item = new CurrentSelectedMetatilesPixmapItem(map, this->metatile_selector_item);
current_metatile_selection_item = new CurrentSelectedMetatilesPixmapItem(this->layout, this->metatile_selector_item);
current_metatile_selection_item->draw();
scene_current_metatile_selection->addItem(current_metatile_selection_item);
}
void Editor::redrawCurrentMetatilesSelection() {
if (current_metatile_selection_item) {
current_metatile_selection_item->setMap(map);
current_metatile_selection_item->setLayout(this->layout);
current_metatile_selection_item->draw();
emit currentMetatilesSelectionChanged();
}
@@ -1779,8 +1855,8 @@ void Editor::maskNonVisibleConnectionTiles() {
mask.addRect(
-BORDER_DISTANCE * 16,
-BORDER_DISTANCE * 16,
(map->getWidth() + BORDER_DISTANCE * 2) * 16,
(map->getHeight() + BORDER_DISTANCE * 2) * 16
(layout->getWidth() + BORDER_DISTANCE * 2) * 16,
(layout->getHeight() + BORDER_DISTANCE * 2) * 16
);
// Mask the tiles with the current theme's background color.
@@ -1803,13 +1879,13 @@ void Editor::clearMapBorder() {
void Editor::displayMapBorder() {
clearMapBorder();
int borderWidth = map->getBorderWidth();
int borderHeight = map->getBorderHeight();
int borderWidth = this->layout->getBorderWidth();
int borderHeight = this->layout->getBorderHeight();
int borderHorzDist = getBorderDrawDistance(borderWidth);
int borderVertDist = getBorderDrawDistance(borderHeight);
QPixmap pixmap = map->renderBorder();
for (int y = -borderVertDist; y < map->getHeight() + borderVertDist; y += borderHeight)
for (int x = -borderHorzDist; x < map->getWidth() + borderHorzDist; x += borderWidth) {
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) {
QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap);
item->setX(x * 16);
item->setY(y * 16);
@@ -1820,7 +1896,7 @@ void Editor::displayMapBorder() {
}
void Editor::updateMapBorder() {
QPixmap pixmap = this->map->renderBorder(true);
QPixmap pixmap = this->layout->renderBorder(true);
for (auto item : this->borderItems) {
item->setPixmap(pixmap);
}
@@ -1842,59 +1918,88 @@ int Editor::getBorderDrawDistance(int dimension) {
}
}
void Editor::onToggleGridClicked(bool checked) {
void Editor::toggleGrid(bool checked) {
if (porymapConfig.showGrid == checked)
return;
porymapConfig.showGrid = checked;
// Synchronize action and checkbox
const QSignalBlocker b_Action(ui->actionShow_Grid);
const QSignalBlocker b_Checkbox(ui->checkBox_ToggleGrid);
ui->actionShow_Grid->setChecked(checked);
ui->checkBox_ToggleGrid->setChecked(checked);
this->mapGrid->setVisible(checked);
if (ui->graphicsView_Map->scene())
ui->graphicsView_Map->scene()->update();
}
void Editor::clearMapGrid() {
for (QGraphicsLineItem* item : gridLines) {
if (item) delete item;
}
gridLines.clear();
delete this->mapGrid;
this->mapGrid = nullptr;
}
void Editor::displayMapGrid() {
clearMapGrid();
ui->checkBox_ToggleGrid->disconnect();
int pixelWidth = map->getWidth() * 16;
int pixelHeight = map->getHeight() * 16;
for (int i = 0; i <= map->getWidth(); i++) {
int x = i * 16;
QGraphicsLineItem *line = new QGraphicsLineItem(x, 0, x, pixelHeight);
line->setVisible(ui->checkBox_ToggleGrid->isChecked());
gridLines.append(line);
connect(ui->checkBox_ToggleGrid, &QCheckBox::toggled, [=](bool checked){line->setVisible(checked);});
// Note: The grid lines are not added to the scene. They need to be drawn on top of the overlay
// elements of the scripting API, so they're painted manually in MapView::drawForeground.
this->mapGrid = new QGraphicsItemGroup();
const int pixelMapWidth = this->layout->getWidth() * 16;
const int pixelMapHeight = this->layout->getHeight() * 16;
// The grid can be moved with a user-specified x/y offset. The grid's dash patterns will only wrap in full pattern increments,
// so we draw an additional row/column outside the map that can be revealed as the offset changes.
const int offsetX = (this->gridSettings.offsetX % this->gridSettings.width) - this->gridSettings.width;
const int offsetY = (this->gridSettings.offsetY % this->gridSettings.height) - this->gridSettings.height;
QPen pen;
pen.setColor(this->gridSettings.color);
// Create vertical lines
pen.setDashPattern(this->gridSettings.getVerticalDashPattern());
for (int i = offsetX; i <= pixelMapWidth; i += this->gridSettings.width) {
auto line = new QGraphicsLineItem(i, offsetY, i, pixelMapHeight);
line->setPen(pen);
this->mapGrid->addToGroup(line);
}
for (int j = 0; j <= map->getHeight(); j++) {
int y = j * 16;
QGraphicsLineItem *line = new QGraphicsLineItem(0, y, pixelWidth, y);
line->setVisible(ui->checkBox_ToggleGrid->isChecked());
gridLines.append(line);
connect(ui->checkBox_ToggleGrid, &QCheckBox::toggled, [=](bool checked){line->setVisible(checked);});
// Create horizontal lines
pen.setDashPattern(this->gridSettings.getHorizontalDashPattern());
for (int i = offsetY; i <= pixelMapHeight; i += this->gridSettings.height) {
auto line = new QGraphicsLineItem(offsetX, i, pixelMapWidth, i);
line->setPen(pen);
this->mapGrid->addToGroup(line);
}
connect(ui->checkBox_ToggleGrid, &QCheckBox::toggled, this, &Editor::onToggleGridClicked);
this->mapGrid->setVisible(porymapConfig.showGrid);
}
void Editor::updateMapGrid() {
displayMapGrid();
if (ui->graphicsView_Map->scene())
ui->graphicsView_Map->scene()->update();
}
void Editor::updatePrimaryTileset(QString tilesetLabel, bool forceLoad)
{
if (map->layout->tileset_primary_label != tilesetLabel || forceLoad)
if (this->layout->tileset_primary_label != tilesetLabel || forceLoad)
{
map->layout->tileset_primary_label = tilesetLabel;
map->layout->tileset_primary = project->getTileset(tilesetLabel, forceLoad);
map->clearBorderCache();
this->layout->tileset_primary_label = tilesetLabel;
this->layout->tileset_primary = project->getTileset(tilesetLabel, forceLoad);
layout->clearBorderCache();
}
}
void Editor::updateSecondaryTileset(QString tilesetLabel, bool forceLoad)
{
if (map->layout->tileset_secondary_label != tilesetLabel || forceLoad)
if (this->layout->tileset_secondary_label != tilesetLabel || forceLoad)
{
map->layout->tileset_secondary_label = tilesetLabel;
map->layout->tileset_secondary = project->getTileset(tilesetLabel, forceLoad);
map->clearBorderCache();
this->layout->tileset_secondary_label = tilesetLabel;
this->layout->tileset_secondary = project->getTileset(tilesetLabel, forceLoad);
layout->clearBorderCache();
}
}
@@ -1940,7 +2045,7 @@ void Editor::updateCustomMapHeaderValues(QTableWidget *table)
Tileset* Editor::getCurrentMapPrimaryTileset()
{
QString tilesetLabel = map->layout->tileset_primary_label;
QString tilesetLabel = this->layout->tileset_primary_label;
return project->getTileset(tilesetLabel);
}
@@ -1975,12 +2080,12 @@ void Editor::redrawObject(DraggablePixmapItem *item) {
void Editor::updateWarpEventWarning(Event *event) {
if (porymapConfig.warpBehaviorWarningDisabled)
return;
if (!project || !map || !event || event->getEventType() != Event::Type::Warp)
if (!project || !map || !map->layout || !event || event->getEventType() != Event::Type::Warp)
return;
Block block;
Metatile * metatile = nullptr;
WarpEvent * warpEvent = static_cast<WarpEvent*>(event);
if (map->getBlock(warpEvent->getX(), warpEvent->getY(), &block)) {
if (map->layout->getBlock(warpEvent->getX(), warpEvent->getY(), &block)) {
metatile = Tileset::getMetatile(block.metatileId(), map->layout->tileset_primary, map->layout->tileset_secondary);
}
// metatile may be null if the warp is in the map border. Display the warning in this case
@@ -2060,7 +2165,7 @@ void Editor::selectedEventIndexChanged(int index, Event::Group eventGroup) {
}
void Editor::duplicateSelectedEvents() {
if (!selected_events || !selected_events->length() || !map || !current_view || map_item->paintingMode != MapPixmapItem::PaintMode::EventObjects)
if (!selected_events || !selected_events->length() || !map || !current_view || this->getEditingLayout())
return;
QList<Event *> selectedEvents;
@@ -2117,6 +2222,50 @@ bool Editor::eventLimitReached(Event::Type event_type) {
return false;
}
void Editor::deleteSelectedEvents() {
if (!this->selected_events || this->selected_events->length() == 0 || !this->map || this->editMode != EditMode::Events)
return;
DraggablePixmapItem *nextSelectedEvent = nullptr;
QList<Event *> selectedEvents;
int numDeleted = 0;
for (DraggablePixmapItem *item : *this->selected_events) {
Event::Group event_group = item->event->getEventGroup();
if (event_group != Event::Group::Heal) {
numDeleted++;
item->event->setPixmapItem(item);
selectedEvents.append(item->event);
}
else { // don't allow deletion of heal locations
logWarn(QString("Cannot delete event of type '%1'").arg(Event::eventTypeToString(item->event->getEventType())));
}
}
if (numDeleted) {
// Get the index for the event that should be selected after this event has been deleted.
// Select event at next smallest index when deleting a single event.
// If deleting multiple events, just let editor work out next selected.
if (numDeleted == 1) {
Event::Group event_group = selectedEvents[0]->getEventGroup();
int index = this->map->events.value(event_group).indexOf(selectedEvents[0]);
if (index != this->map->events.value(event_group).size() - 1)
index++;
else
index--;
Event *event = nullptr;
if (index >= 0)
event = this->map->events.value(event_group).at(index);
for (QGraphicsItem *child : this->events_group->childItems()) {
DraggablePixmapItem *event_item = static_cast<DraggablePixmapItem *>(child);
if (event_item->event == event) {
nextSelectedEvent = event_item;
break;
}
}
}
this->map->editHistory.push(new EventDelete(this, this->map, selectedEvents, nextSelectedEvent ? nextSelectedEvent->event : nullptr));
}
}
void Editor::openMapScripts() const {
openInTextEditor(map->getScriptsFilePath());
}
@@ -2199,11 +2348,11 @@ bool Editor::startDetachedProcess(const QString &command, const QString &working
// is clicking on the background instead of an event.
void Editor::objectsView_onMousePress(QMouseEvent *event) {
// make sure we are in object editing mode
if (map_item && map_item->paintingMode != MapPixmapItem::PaintMode::EventObjects) {
if (map_item && this->editMode != EditMode::Events) {
return;
}
if (this->obj_edit_mode == "paint" && event->buttons() & Qt::RightButton) {
this->obj_edit_mode = "select";
if (this->objectEditAction == EditAction::Paint && event->buttons() & Qt::RightButton) {
this->objectEditAction = EditAction::Select;
this->settings->mapCursor = QCursor();
this->cursorMapTileRect->setSingleTileMode();
this->ui->toolButton_Paint->setChecked(false);

View File

@@ -3,6 +3,7 @@
#include <fstream>
#include <iostream>
#include <sstream>
#include <QFile>
namespace fex
{
@@ -155,48 +156,26 @@ namespace fex
return Token(Token::Type::kDefine, filename_, line_number_);
}
std::vector<Token> Lexer::LexString(const std::string &data)
std::vector<Token> Lexer::LexFile(const QString &path)
{
filename_ = "string literal";
line_number_ = 1;
index_ = 0;
data_ = data;
return Lex();
}
std::vector<Token> Lexer::LexFile(const std::string &path)
{
filename_ = path;
filename_ = path.toStdString();
line_number_ = 1;
std::ifstream file;
file.open(path);
// Note: Using QFile instead of ifstream to handle encoding differences between platforms
// (specifically to handle accented characters on Windows)
QFile file(path);
file.open(QIODevice::ReadOnly);
std::stringstream stream;
stream << file.rdbuf();
const QByteArray data = file.readAll();
index_ = 0;
data_ = stream.str();
data_ = data.toStdString();
file.close();
return Lex();
}
void Lexer::LexFileDumpTokens(const std::string &path, const std::string &out)
{
std::ofstream file;
file.open(out);
for (Token token : LexFile(path))
{
file << token.ToString() << std::endl;
}
file.close();
}
std::vector<Token> Lexer::Lex()
{
std::vector<Token> tokens;

View File

@@ -337,7 +337,7 @@ namespace fex
return DefineStatement(identifer, value);
}
std::map<std::string, int> Parser::ReadDefines(const std::string &filename, std::vector<std::string> matching)
std::map<std::string, int> Parser::ReadDefines(const QString &filename, std::vector<std::string> matching)
{
std::map<std::string, int> out;

View File

@@ -1,50 +0,0 @@
#include "lib/fex/parser_util.h"
#include <QMap>
#include "lib/fex/parser.h"
ParserUtil::ParserUtil(QString root): root_(root) {}
QStringList ParserUtil::ReadDefines(QString filename, QString prefix)
{
if (filename.isEmpty()) {
return QStringList();
}
QString filepath = root_ + "/" + filename;
fex::Parser parser;
std::vector<std::string> match_list = { prefix.toStdString() + ".*" };
std::map<std::string, int> defines = parser.ReadDefines(filepath.toStdString(), match_list);
QStringList out;
for(auto const& define : defines) {
out.append(QString::fromStdString(define.first));
}
return out;
}
QStringList ParserUtil::ReadDefinesValueSort(QString filename, QString prefix)
{
if (filename.isEmpty()) {
return QStringList();
}
QString filepath = root_ + "/" + filename;
fex::Parser parser;
std::vector<std::string> match_list = { prefix.toStdString() + ".*" };
std::map<std::string, int> defines = parser.ReadDefines(filepath.toStdString(), match_list);
QMultiMap<int, QString> defines_keyed_by_value;
for (const auto& pair : defines) {
defines_keyed_by_value.insert(pair.second, QString::fromStdString(pair.first));
}
return defines_keyed_by_value.values();
}

View File

@@ -33,7 +33,6 @@ static const int max_depth = 200;
using std::map;
using std::make_shared;
using std::initializer_list;
using std::move;
/* Helper for representing null - just a do-nothing struct, plus comparison
* operators so the helpers in JsonValue work. We can't use nullptr_t because
@@ -164,7 +163,7 @@ protected:
// Constructors
explicit Value(const T &value) : m_value(value) {}
explicit Value(T &&value) : m_value(move(value)) {}
explicit Value(T &&value) : m_value(std::move(value)) {}
// Get type tag
Json::Type type() const override {
@@ -211,7 +210,7 @@ class JsonString final : public Value<Json::STRING, QString> {
const QString &string_value() const override { return m_value; }
public:
explicit JsonString(const QString &value) : Value(value) {}
explicit JsonString(QString &&value) : Value(move(value)) {}
explicit JsonString(QString &&value) : Value(std::move(value)) {}
};
class JsonArray final : public Value<Json::ARRAY, Json::array> {
@@ -219,7 +218,7 @@ class JsonArray final : public Value<Json::ARRAY, Json::array> {
const Json & operator[](int i) const override;
public:
explicit JsonArray(const Json::array &value) : Value(value) {}
explicit JsonArray(Json::array &&value) : Value(move(value)) {}
explicit JsonArray(Json::array &&value) : Value(std::move(value)) {}
};
class JsonObject final : public Value<Json::OBJECT, Json::object> {
@@ -227,7 +226,7 @@ class JsonObject final : public Value<Json::OBJECT, Json::object> {
const Json & operator[](const QString &key) const override;
public:
explicit JsonObject(const Json::object &value) : Value(value) {}
explicit JsonObject(Json::object &&value) : Value(move(value)) {}
explicit JsonObject(Json::object &&value) : Value(std::move(value)) {}
};
class JsonNull final : public Value<Json::NUL, NullStruct> {
@@ -269,12 +268,12 @@ Json::Json(double value) : m_ptr(make_shared<JsonDouble>(value)) {
Json::Json(int value) : m_ptr(make_shared<JsonInt>(value)) {}
Json::Json(bool value) : m_ptr(value ? statics().t : statics().f) {}
Json::Json(const QString &value) : m_ptr(make_shared<JsonString>(value)) {}
Json::Json(QString &&value) : m_ptr(make_shared<JsonString>(move(value))) {}
Json::Json(QString &&value) : m_ptr(make_shared<JsonString>(std::move(value))) {}
Json::Json(const char * value) : m_ptr(make_shared<JsonString>(value)) {}
Json::Json(const Json::array &values) : m_ptr(make_shared<JsonArray>(values)) {}
Json::Json(Json::array &&values) : m_ptr(make_shared<JsonArray>(move(values))) {}
Json::Json(Json::array &&values) : m_ptr(make_shared<JsonArray>(std::move(values))) {}
Json::Json(const Json::object &values) : m_ptr(make_shared<JsonObject>(values)) {}
Json::Json(Json::object &&values) : m_ptr(make_shared<JsonObject>(move(values))) {}
Json::Json(Json::object &&values) : m_ptr(make_shared<JsonObject>(std::move(values))) {}
/* * * * * * * * * * * * * * * * * * * *
* Accessors
@@ -399,7 +398,7 @@ struct JsonParser final {
* Mark this parse as failed.
*/
Json fail(QString &&msg) {
return fail(move(msg), Json());
return fail(std::move(msg), Json());
}
template <typename T>

File diff suppressed because it is too large Load Diff

View File

@@ -7,6 +7,7 @@
#include "tile.h"
#include "tileset.h"
#include "map.h"
#include "filedialog.h"
#include "orderedjson.h"
@@ -34,60 +35,23 @@ int Project::max_map_data_size = 10240; // 0x2800
int Project::default_map_size = 20;
int Project::max_object_events = 64;
Project::Project(QWidget *parent) :
Project::Project(QObject *parent) :
QObject(parent)
{
initSignals();
QObject::connect(&this->fileWatcher, &QFileSystemWatcher::fileChanged, this, &Project::fileChanged);
}
Project::~Project()
{
clearMapCache();
clearTilesetCache();
}
void Project::initSignals() {
// detect changes to specific filepaths being monitored
QObject::connect(&fileWatcher, &QFileSystemWatcher::fileChanged, [this](QString changed){
if (!porymapConfig.monitorFiles) return;
if (modifiedFileTimestamps.contains(changed)) {
if (QDateTime::currentMSecsSinceEpoch() < modifiedFileTimestamps[changed]) {
return;
}
modifiedFileTimestamps.remove(changed);
}
static bool showing = false;
if (showing) return;
QMessageBox notice(this->parentWidget());
notice.setText("File Changed");
notice.setInformativeText(QString("The file %1 has changed on disk. Would you like to reload the project?")
.arg(changed.remove(this->root + "/")));
notice.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
notice.setDefaultButton(QMessageBox::No);
notice.setIcon(QMessageBox::Question);
QCheckBox showAgainCheck("Do not ask again.");
notice.setCheckBox(&showAgainCheck);
showing = true;
int choice = notice.exec();
if (choice == QMessageBox::Yes) {
emit reloadProject();
} else if (choice == QMessageBox::No) {
if (showAgainCheck.isChecked()) {
porymapConfig.monitorFiles = false;
emit uncheckMonitorFilesAction();
}
}
showing = false;
});
clearMapLayouts();
clearEventGraphics();
}
void Project::set_root(QString dir) {
this->root = dir;
this->importExportPath = dir;
FileDialog::setDirectory(dir);
this->parser.set_root(dir);
}
@@ -160,7 +124,6 @@ void Project::clearMapCache() {
delete map;
}
mapCache.clear();
emit mapCacheCleared();
}
void Project::clearTilesetCache() {
@@ -362,6 +325,7 @@ bool Project::loadMapData(Map* map) {
heal->setRespawnNPC(loc.respawnNPC);
}
map->events[Event::Group::Heal].append(heal);
map->ownedEvents.append(heal);
}
}
@@ -425,15 +389,87 @@ QString Project::readMapLocation(QString map_name) {
return ParseUtil::jsonToQString(mapObj["region_map_section"]);
}
bool Project::loadLayout(MapLayout *layout) {
// Force these to run even if one fails
bool loadedTilesets = loadLayoutTilesets(layout);
bool loadedBlockdata = loadBlockdata(layout);
bool loadedBorder = loadLayoutBorder(layout);
Layout *Project::createNewLayout(Layout::SimpleSettings &layoutSettings) {
QString basePath = projectConfig.getFilePath(ProjectFilePath::data_layouts_folders);
Layout *layout;
return loadedTilesets
&& loadedBlockdata
&& loadedBorder;
// Handle the case where we are copying from an existing layout first.
if (!layoutSettings.from_id.isEmpty()) {
// load from layout
loadLayout(mapLayouts[layoutSettings.from_id]);
layout = mapLayouts[layoutSettings.from_id]->copy();
layout->name = layoutSettings.name;
layout->id = layoutSettings.id;
layout->border_path = QString("%1%2/border.bin").arg(basePath, layoutSettings.name);
layout->blockdata_path = QString("%1%2/map.bin").arg(basePath, layoutSettings.name);
}
else {
layout = new Layout;
layout->name = layoutSettings.name;
layout->id = layoutSettings.id;
layout->width = layoutSettings.width;
layout->height = layoutSettings.height;
layout->border_width = DEFAULT_BORDER_WIDTH;
layout->border_height = DEFAULT_BORDER_HEIGHT;
layout->tileset_primary_label = layoutSettings.tileset_primary_label;
layout->tileset_secondary_label = layoutSettings.tileset_secondary_label;
layout->border_path = QString("%1%2/border.bin").arg(basePath, layoutSettings.name);
layout->blockdata_path = QString("%1%2/map.bin").arg(basePath, layoutSettings.name);
setNewLayoutBlockdata(layout);
setNewLayoutBorder(layout);
}
// Create a new directory for the layout
QString newLayoutDir = QString(root + "/%1%2").arg(projectConfig.getFilePath(ProjectFilePath::data_layouts_folders), layout->name);
if (!QDir::root().mkdir(newLayoutDir)) {
logError(QString("Error: failed to create directory for new layout: '%1'").arg(newLayoutDir));
delete layout;
return nullptr;
}
mapLayouts.insert(layout->id, layout);
mapLayoutsMaster.insert(layout->id, layout->copy());
mapLayoutsTable.append(layout->id);
mapLayoutsTableMaster.append(layout->id);
layoutIdsToNames.insert(layout->id, layout->name);
saveLayout(layout);
this->loadLayout(layout);
return layout;
}
bool Project::loadLayout(Layout *layout) {
if (!layout->loaded) {
// Force these to run even if one fails
bool loadedTilesets = loadLayoutTilesets(layout);
bool loadedBlockdata = loadBlockdata(layout);
bool loadedBorder = loadLayoutBorder(layout);
if (loadedTilesets && loadedBlockdata && loadedBorder) {
layout->loaded = true;
return true;
} else {
return false;
}
}
return true;
}
Layout *Project::loadLayout(QString layoutId) {
if (mapLayouts.contains(layoutId)) {
Layout *layout = mapLayouts[layoutId];
if (loadLayout(layout)) {
return layout;
}
}
logError(QString("Error: Failed to load layout '%1'").arg(layoutId));
return nullptr;
}
bool Project::loadMapLayout(Map* map) {
@@ -455,9 +491,17 @@ bool Project::loadMapLayout(Map* map) {
}
}
bool Project::readMapLayouts() {
void Project::clearMapLayouts() {
qDeleteAll(mapLayouts);
mapLayouts.clear();
qDeleteAll(mapLayoutsMaster);
mapLayoutsMaster.clear();
mapLayoutsTable.clear();
layoutIdsToNames.clear();
}
bool Project::readMapLayouts() {
clearMapLayouts();
QString layoutsFilepath = projectConfig.getFilePath(ProjectFilePath::json_layouts);
QString fullFilepath = QString("%1/%2").arg(root).arg(layoutsFilepath);
@@ -483,7 +527,7 @@ bool Project::readMapLayouts() {
.arg(layoutsLabel));
}
QList<QString> requiredFields = QList<QString>{
static const QList<QString> requiredFields = QList<QString>{
"id",
"name",
"width",
@@ -501,7 +545,7 @@ bool Project::readMapLayouts() {
logError(QString("Layout %1 is missing field(s) in %2.").arg(i).arg(layoutsFilepath));
return false;
}
MapLayout *layout = new MapLayout();
Layout *layout = new Layout();
layout->id = ParseUtil::jsonToQString(layoutObj["id"]);
if (layout->id.isEmpty()) {
logError(QString("Missing 'id' value on layout %1 in %2").arg(i).arg(layoutsFilepath));
@@ -577,14 +621,12 @@ bool Project::readMapLayouts() {
return false;
}
mapLayouts.insert(layout->id, layout);
mapLayoutsMaster.insert(layout->id, layout->copy());
mapLayoutsTable.append(layout->id);
mapLayoutsTableMaster.append(layout->id);
layoutIdsToNames.insert(layout->id, layout->name);
}
// Deep copy
mapLayoutsMaster = mapLayouts;
mapLayoutsMaster.detach();
mapLayoutsTableMaster = mapLayoutsTable;
mapLayoutsTableMaster.detach();
return true;
}
@@ -601,7 +643,7 @@ void Project::saveMapLayouts() {
OrderedJson::array layoutsArr;
for (QString layoutId : mapLayoutsTableMaster) {
MapLayout *layout = mapLayouts.value(layoutId);
Layout *layout = mapLayoutsMaster.value(layoutId);
OrderedJson::object layoutObj;
layoutObj["id"] = layout->id;
layoutObj["name"] = layout->name;
@@ -666,6 +708,47 @@ void Project::saveMapGroups() {
mapGroupsFile.close();
}
void Project::saveRegionMapSections() {
const QString filepath = QString("%1/%2").arg(this->root).arg(projectConfig.getFilePath(ProjectFilePath::json_region_map_entries));
QFile file(filepath);
if (!file.open(QIODevice::WriteOnly)) {
logError(QString("Could not open '%1' for writing").arg(filepath));
return;
}
const QString emptyMapsecName = getEmptyMapsecName();
OrderedJson::array mapSectionArray;
for (const auto &idName : this->mapSectionIdNames) {
// The 'empty' map section (MAPSEC_NONE) isn't normally present in the region map sections data file.
// We append this name to mapSectionIdNames ourselves if it isn't present, in which case we don't want to output data for it here.
if (!this->saveEmptyMapsec && idName == emptyMapsecName)
continue;
OrderedJson::object mapSectionObj;
mapSectionObj["id"] = idName;
if (this->regionMapEntries.contains(idName)) {
MapSectionEntry entry = this->regionMapEntries.value(idName);
mapSectionObj["name"] = entry.name;
mapSectionObj["x"] = entry.x;
mapSectionObj["y"] = entry.y;
mapSectionObj["width"] = entry.width;
mapSectionObj["height"] = entry.height;
}
mapSectionArray.append(mapSectionObj);
}
OrderedJson::object object;
object["map_sections"] = mapSectionArray;
ignoreWatchedFileTemporarily(filepath);
OrderedJson json(object);
OrderedJsonDoc jsonDoc(&json);
jsonDoc.dump(&file);
file.close();
}
void Project::saveWildMonData() {
if (!this->wildEncountersLoaded) return;
@@ -1004,7 +1087,7 @@ void Project::saveTilesetMetatileAttributes(Tileset *tileset) {
QFile attrs_file(tileset->metatile_attrs_path);
if (attrs_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
QByteArray data;
for (Metatile *metatile : tileset->metatiles) {
for (const auto &metatile : tileset->metatiles()) {
uint32_t attributes = metatile->getAttributes();
for (int i = 0; i < projectConfig.metatileAttributesSize; i++)
data.append(static_cast<char>(attributes >> (8 * i)));
@@ -1020,7 +1103,7 @@ void Project::saveTilesetMetatiles(Tileset *tileset) {
if (metatiles_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
QByteArray data;
int numTiles = projectConfig.getNumTilesInMetatile();
for (Metatile *metatile : tileset->metatiles) {
for (const auto &metatile : tileset->metatiles()) {
for (int i = 0; i < numTiles; i++) {
uint16_t tile = metatile->tiles.at(i).rawValue();
data.append(static_cast<char>(tile));
@@ -1029,7 +1112,7 @@ void Project::saveTilesetMetatiles(Tileset *tileset) {
}
metatiles_file.write(data);
} else {
tileset->metatiles.clear();
tileset->clearMetatiles();
logError(QString("Could not open tileset metatiles file '%1'").arg(tileset->metatiles_path));
}
}
@@ -1047,13 +1130,14 @@ void Project::saveTilesetTilesImage(Tileset *tileset) {
}
void Project::saveTilesetPalettes(Tileset *tileset) {
for (int i = 0; i < Project::getNumPalettesTotal(); i++) {
int numPalettes = qMin(tileset->palettePaths.length(), tileset->palettes.length());
for (int i = 0; i < numPalettes; i++) {
QString filepath = tileset->palettePaths.at(i);
PaletteUtil::writeJASC(filepath, tileset->palettes.at(i).toVector(), 0, 16);
}
}
bool Project::loadLayoutTilesets(MapLayout *layout) {
bool Project::loadLayoutTilesets(Layout *layout) {
layout->tileset_primary = getTileset(layout->tileset_primary_label);
if (!layout->tileset_primary) {
QString defaultTileset = this->getDefaultPrimaryTilesetLabel();
@@ -1121,11 +1205,11 @@ Tileset* Project::loadTileset(QString label, Tileset *tileset) {
return tileset;
}
bool Project::loadBlockdata(MapLayout *layout) {
bool Project::loadBlockdata(Layout *layout) {
QString path = QString("%1/%2").arg(root).arg(layout->blockdata_path);
layout->blockdata = readBlockdata(path);
layout->lastCommitBlocks.blocks = layout->blockdata;
layout->lastCommitBlocks.mapDimensions = QSize(layout->getWidth(), layout->getHeight());
layout->lastCommitBlocks.layoutDimensions = QSize(layout->getWidth(), layout->getHeight());
if (layout->blockdata.count() != layout->getWidth() * layout->getHeight()) {
logWarn(QString("Layout blockdata length %1 does not match dimensions %2x%3 (should be %4). Resizing blockdata.")
@@ -1138,19 +1222,19 @@ bool Project::loadBlockdata(MapLayout *layout) {
return true;
}
void Project::setNewMapBlockdata(Map *map) {
map->layout->blockdata.clear();
int width = map->getWidth();
int height = map->getHeight();
void Project::setNewLayoutBlockdata(Layout *layout) {
layout->blockdata.clear();
int width = layout->getWidth();
int height = layout->getHeight();
Block block(projectConfig.defaultMetatileId, projectConfig.defaultCollision, projectConfig.defaultElevation);
for (int i = 0; i < width * height; i++) {
map->layout->blockdata.append(block);
layout->blockdata.append(block);
}
map->layout->lastCommitBlocks.blocks = map->layout->blockdata;
map->layout->lastCommitBlocks.mapDimensions = QSize(width, height);
layout->lastCommitBlocks.blocks = layout->blockdata;
layout->lastCommitBlocks.layoutDimensions = QSize(width, height);
}
bool Project::loadLayoutBorder(MapLayout *layout) {
bool Project::loadLayoutBorder(Layout *layout) {
QString path = QString("%1/%2").arg(root).arg(layout->border_path);
layout->border = readBlockdata(path);
layout->lastCommitBlocks.border = layout->border;
@@ -1166,36 +1250,36 @@ bool Project::loadLayoutBorder(MapLayout *layout) {
return true;
}
void Project::setNewMapBorder(Map *map) {
map->layout->border.clear();
int width = map->getBorderWidth();
int height = map->getBorderHeight();
void Project::setNewLayoutBorder(Layout *layout) {
layout->border.clear();
int width = layout->getBorderWidth();
int height = layout->getBorderHeight();
if (projectConfig.newMapBorderMetatileIds.length() != width * height) {
// Border size doesn't match the number of default border metatiles.
// Fill the border with empty metatiles.
for (int i = 0; i < width * height; i++) {
map->layout->border.append(0);
layout->border.append(0);
}
} else {
// Fill the border with the default metatiles from the config.
for (int i = 0; i < width * height; i++) {
map->layout->border.append(projectConfig.newMapBorderMetatileIds.at(i));
layout->border.append(projectConfig.newMapBorderMetatileIds.at(i));
}
}
map->layout->lastCommitBlocks.border = map->layout->border;
map->layout->lastCommitBlocks.borderDimensions = QSize(width, height);
layout->lastCommitBlocks.border = layout->border;
layout->lastCommitBlocks.borderDimensions = QSize(width, height);
}
void Project::saveLayoutBorder(Map *map) {
QString path = QString("%1/%2").arg(root).arg(map->layout->border_path);
writeBlockdata(path, map->layout->border);
void Project::saveLayoutBorder(Layout *layout) {
QString path = QString("%1/%2").arg(root).arg(layout->border_path);
writeBlockdata(path, layout->border);
}
void Project::saveLayoutBlockdata(Map* map) {
QString path = QString("%1/%2").arg(root).arg(map->layout->blockdata_path);
writeBlockdata(path, map->layout->blockdata);
void Project::saveLayoutBlockdata(Layout *layout) {
QString path = QString("%1/%2").arg(root).arg(layout->blockdata_path);
writeBlockdata(path, layout->blockdata);
}
void Project::writeBlockdata(QString path, const Blockdata &blockdata) {
@@ -1350,36 +1434,46 @@ void Project::saveMap(Map *map) {
jsonDoc.dump(&mapFile);
mapFile.close();
saveLayoutBorder(map);
saveLayoutBlockdata(map);
saveLayout(map->layout);
saveHealLocations(map);
// Update global data structures with current map data.
updateMapLayout(map);
map->isPersistedToFile = true;
map->hasUnsavedDataChanges = false;
map->editHistory.setClean();
}
void Project::updateMapLayout(Map* map) {
if (!mapLayoutsTableMaster.contains(map->layoutId)) {
mapLayoutsTableMaster.append(map->layoutId);
void Project::saveLayout(Layout *layout) {
//
saveLayoutBorder(layout);
saveLayoutBlockdata(layout);
// Update global data structures with current map data.
updateLayout(layout);
layout->editHistory.setClean();
}
void Project::updateLayout(Layout *layout) {
if (!mapLayoutsTableMaster.contains(layout->id)) {
mapLayoutsTableMaster.append(layout->id);
}
// Deep copy
MapLayout *layout = mapLayouts.value(map->layoutId);
MapLayout *newLayout = new MapLayout();
*newLayout = *layout;
mapLayoutsMaster.insert(map->layoutId, newLayout);
if (mapLayoutsMaster.contains(layout->id)) {
mapLayoutsMaster[layout->id]->copyFrom(layout);
}
else {
mapLayoutsMaster.insert(layout->id, layout->copy());
}
}
void Project::saveAllDataStructures() {
saveMapLayouts();
saveMapGroups();
saveRegionMapSections();
saveMapConstantsHeader();
saveWildMonData();
saveConfig();
this->hasUnsavedDataChanges = false;
}
void Project::saveConfig() {
@@ -1513,16 +1607,16 @@ void Project::loadTilesetMetatiles(Tileset* tileset) {
}
metatiles.append(metatile);
}
tileset->metatiles = metatiles;
tileset->setMetatiles(metatiles);
} else {
tileset->metatiles.clear();
tileset->clearMetatiles();
logError(QString("Could not open tileset metatiles file '%1'").arg(tileset->metatiles_path));
}
QFile attrs_file(tileset->metatile_attrs_path);
if (attrs_file.open(QIODevice::ReadOnly)) {
QByteArray data = attrs_file.readAll();
int num_metatiles = tileset->metatiles.count();
int num_metatiles = tileset->numMetatiles();
int attrSize = projectConfig.metatileAttributesSize;
int num_metatileAttrs = data.length() / attrSize;
if (num_metatiles != num_metatileAttrs) {
@@ -1535,7 +1629,7 @@ void Project::loadTilesetMetatiles(Tileset* tileset) {
uint32_t attributes = 0;
for (int j = 0; j < attrSize; j++)
attributes |= static_cast<unsigned char>(data.at(i * attrSize + j)) << (8 * j);
tileset->metatiles.at(i)->setAttributes(attributes);
tileset->metatileAt(i)->setAttributes(attributes);
}
} else {
logError(QString("Could not open tileset metatile attributes file '%1'").arg(tileset->metatile_attrs_path));
@@ -1863,11 +1957,12 @@ Map* Project::addNewMapToGroup(QString mapName, int groupNum, Map *newMap, bool
if (!existingLayout) {
this->mapLayouts.insert(newMap->layoutId, newMap->layout);
this->mapLayoutsTable.append(newMap->layoutId);
this->layoutIdsToNames.insert(newMap->layout->id, newMap->layout->name);
if (!importedMap) {
setNewMapBlockdata(newMap);
setNewLayoutBlockdata(newMap->layout);
}
if (newMap->layout->border.isEmpty()) {
setNewMapBorder(newMap);
setNewLayoutBorder(newMap->layout);
}
}
@@ -1933,8 +2028,6 @@ void Project::appendTilesetLabel(QString label, QString isSecondaryStr) {
}
bool Project::readTilesetLabels() {
QStringList primaryTilesets;
QStringList secondaryTilesets;
this->primaryTilesetLabels.clear();
this->secondaryTilesetLabels.clear();
this->tilesetLabelsOrdered.clear();
@@ -1963,9 +2056,9 @@ bool Project::readTilesetLabels() {
} else {
this->usingAsmTilesets = false;
const auto structs = parser.readCStructs(filename, "", Tileset::getHeaderMemberMap(this->usingAsmTilesets));
QStringList labels = structs.keys();
const QStringList labels = structs.keys();
// TODO: This is alphabetical, AdvanceMap import wants the vanilla order in tilesetLabelsOrdered
for (const auto tilesetLabel : labels){
for (const auto &tilesetLabel : labels){
appendTilesetLabel(tilesetLabel, structs[tilesetLabel].value("isSecondary"));
}
}
@@ -2159,24 +2252,99 @@ bool Project::readFieldmapMasks() {
}
bool Project::readRegionMapSections() {
this->mapSectionNameToValue.clear();
this->mapSectionValueToName.clear();
this->mapSectionIdNames.clear();
this->regionMapEntries.clear();
this->saveEmptyMapsec = false;
const QString defaultName = getEmptyMapsecName();
const QString requiredPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix);
const QStringList regexList = {QString("\\b%1").arg(projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix))};
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_region_map_sections);
fileWatcher.addPath(root + "/" + filename);
this->mapSectionNameToValue = parser.readCDefinesByRegex(filename, regexList);
if (this->mapSectionNameToValue.isEmpty()) {
logError(QString("Failed to read region map sections from %1.").arg(filename));
QJsonDocument doc;
const QString filepath = QString("%1/%2").arg(this->root).arg(projectConfig.getFilePath(ProjectFilePath::json_region_map_entries));
if (!parser.tryParseJsonFile(&doc, filepath)) {
logError(QString("Failed to read region map sections from '%1'").arg(filepath));
return false;
}
fileWatcher.addPath(filepath);
for (QString defineName : this->mapSectionNameToValue.keys()) {
this->mapSectionValueToName.insert(this->mapSectionNameToValue[defineName], defineName);
QJsonArray mapSections = doc.object()["map_sections"].toArray();
for (int i = 0; i < mapSections.size(); i++) {
QJsonObject mapSectionObj = mapSections.at(i).toObject();
// For each map section, "id" is the only required field. This is the field we use to display the location names in various drop-downs.
const QString idField = "id";
if (!mapSectionObj.contains(idField)) {
logWarn(QString("Ignoring data for map section %1. Missing required field \"%2\"").arg(i).arg(idField));
continue;
}
const QString idName = ParseUtil::jsonToQString(mapSectionObj[idField]);
if (!idName.startsWith(requiredPrefix)) {
logWarn(QString("Ignoring data for map section '%1'. IDs must start with the prefix '%2'").arg(idName).arg(requiredPrefix));
continue;
}
this->mapSectionIdNames.append(idName);
if (idName == defaultName) {
// If the user has data for the 'empty' MAPSEC we need to know to output it later,
// because we will otherwise add a dummy entry for this value.
this->saveEmptyMapsec = true;
}
// Map sections may have additional data indicating their position on the region map.
// If they have this data, we can add them to the region map entry list.
bool hasRegionMapData = true;
static const QSet<QString> regionMapFieldNames = { "name", "x", "y", "width", "height" };
for (auto fieldName : regionMapFieldNames) {
if (!mapSectionObj.contains(fieldName)) {
hasRegionMapData = false;
break;
}
}
if (!hasRegionMapData)
continue;
MapSectionEntry entry;
entry.name = ParseUtil::jsonToQString(mapSectionObj["name"]);
entry.x = ParseUtil::jsonToInt(mapSectionObj["x"]);
entry.y = ParseUtil::jsonToInt(mapSectionObj["y"]);
entry.width = ParseUtil::jsonToInt(mapSectionObj["width"]);
entry.height = ParseUtil::jsonToInt(mapSectionObj["height"]);
entry.valid = true;
this->regionMapEntries[idName] = entry;
}
// Make sure the default name is present in the list.
if (!this->mapSectionIdNames.contains(defaultName)) {
this->mapSectionIdNames.append(defaultName);
}
return true;
}
QString Project::getEmptyMapsecName() {
return projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix) + projectConfig.getIdentifier(ProjectIdentifier::define_map_section_empty);
}
// This function assumes a valid and unique name
void Project::addNewMapsec(const QString &name) {
if (!this->mapSectionIdNames.isEmpty() && this->mapSectionIdNames.last() == getEmptyMapsecName()) {
// If the default map section name (MAPSEC_NONE) is last in the list we'll keep it last in the list.
this->mapSectionIdNames.insert(this->mapSectionIdNames.length() - 1, name);
} else {
this->mapSectionIdNames.append(name);
}
this->hasUnsavedDataChanges = true;
emit mapSectionIdNamesChanged();
}
void Project::removeMapsec(const QString &name) {
if (!this->mapSectionIdNames.contains(name) || name == getEmptyMapsecName())
return;
this->mapSectionIdNames.removeOne(name);
this->hasUnsavedDataChanges = true;
emit mapSectionIdNamesChanged();
}
// Read the constants to preserve any "unused" heal locations when writing the file later
bool Project::readHealLocationConstants() {
this->healLocationNameToValue.clear();
@@ -2242,7 +2410,7 @@ bool Project::readHealLocations() {
// Pattern for an x, y number pair
const QString coordPattern = "\\s*(?<x>[0-9A-Fa-fx]+),\\s*(?<y>[0-9A-Fa-fx]+)";
for (const auto idName : constants) {
for (const auto &idName : constants) {
// Create regex pattern for e.g. "SPAWN_PALLET_TOWN - 1] = "
const QString initializerPattern = QString("%1\\s*-\\s*1\\s*\\]\\s*=\\s*").arg(idName);
@@ -2556,7 +2724,14 @@ void Project::setEventPixmap(Event *event, bool forceLoad) {
event->loadPixmap(this);
}
void Project::clearEventGraphics() {
qDeleteAll(eventGraphicsMap);
eventGraphicsMap.clear();
}
bool Project::readEventGraphics() {
clearEventGraphics();
fileWatcher.addPaths(QStringList() << root + "/" + projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx_pointers)
<< root + "/" + projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx_info)
<< root + "/" + projectConfig.getFilePath(ProjectFilePath::data_obj_event_pic_tables)
@@ -2566,8 +2741,6 @@ bool Project::readEventGraphics() {
const QString pointersName = projectConfig.getIdentifier(ProjectIdentifier::symbol_obj_event_gfx_pointers);
QMap<QString, QString> pointerHash = parser.readNamedIndexCArray(pointersFilepath, pointersName);
qDeleteAll(eventGraphicsMap);
eventGraphicsMap.clear();
QStringList gfxNames = gfxDefines.keys();
// The positions of each of the required members for the gfx info struct.
@@ -2586,14 +2759,13 @@ bool Project::readEventGraphics() {
QMap<QString, QString> graphicIncbins = parser.readCIncbinMulti(projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx));
for (QString gfxName : gfxNames) {
EventGraphics * eventGraphics = new EventGraphics;
QString info_label = pointerHash[gfxName].replace("&", "");
if (!gfxInfos.contains(info_label))
continue;
const auto gfxInfoAttributes = gfxInfos[info_label];
auto eventGraphics = new EventGraphics;
eventGraphics->inanimate = ParseUtil::gameStringToBool(gfxInfoAttributes.value("inanimate"));
QString pic_label = gfxInfoAttributes.value("images");
QString dimensions_label = gfxInfoAttributes.value("oam");
@@ -2819,11 +2991,6 @@ QString Project::getDynamicMapDefineName() {
return prefix + projectConfig.getIdentifier(ProjectIdentifier::define_map_dynamic);
}
void Project::setImportExportPath(QString filename)
{
this->importExportPath = QFileInfo(filename).absolutePath();
}
// If the provided filepath is an absolute path to an existing file, return filepath.
// If not, and the provided filepath is a relative path from the project dir to an existing file, return the relative path.
// Otherwise return empty string.
@@ -2860,3 +3027,23 @@ void Project::applyParsedLimits() {
projectConfig.collisionSheetHeight = qMin(projectConfig.collisionSheetHeight, Block::getMaxElevation() + 1);
projectConfig.collisionSheetWidth = qMin(projectConfig.collisionSheetWidth, Block::getMaxCollision() + 1);
}
bool Project::hasUnsavedChanges() {
if (this->hasUnsavedDataChanges)
return true;
// Check layouts for unsaved changes
for (auto i = this->mapLayouts.constBegin(); i != this->mapLayouts.constEnd(); i++) {
auto layout = i.value();
if (layout && layout->hasUnsavedChanges())
return true;
}
// Check loaded maps for unsaved changes
for (auto i = this->mapCache.constBegin(); i != this->mapCache.constEnd(); i++) {
auto map = i.value();
if (map && map->hasUnsavedChanges())
return true;
}
return false;
}

View File

@@ -24,7 +24,7 @@ void MainWindow::tryRedrawMapArea(bool forceRedraw) {
this->editor->updateMapBorder();
this->editor->updateMapConnections();
if (this->tilesetEditor)
this->tilesetEditor->updateTilesets(this->editor->map->layout->tileset_primary_label, this->editor->map->layout->tileset_secondary_label);
this->tilesetEditor->updateTilesets(this->editor->layout->tileset_primary_label, this->editor->layout->tileset_secondary_label);
if (this->editor->metatile_selector_item)
this->editor->metatile_selector_item->draw();
if (this->editor->selected_border_metatiles_item)
@@ -42,13 +42,13 @@ void MainWindow::tryRedrawMapArea(bool forceRedraw) {
void MainWindow::tryCommitMapChanges(bool commitChanges) {
if (commitChanges) {
Map *map = this->editor->map;
if (map) {
map->editHistory.push(new ScriptEditMap(map,
map->layout->lastCommitBlocks.mapDimensions, QSize(map->getWidth(), map->getHeight()),
map->layout->lastCommitBlocks.blocks, map->layout->blockdata,
map->layout->lastCommitBlocks.borderDimensions, QSize(map->getBorderWidth(), map->getBorderHeight()),
map->layout->lastCommitBlocks.border, map->layout->border
Layout *layout = this->editor->layout;
if (layout) {
layout->editHistory.push(new ScriptEditLayout(layout,
layout->lastCommitBlocks.layoutDimensions, QSize(layout->getWidth(), layout->getHeight()),
layout->lastCommitBlocks.blocks, layout->blockdata,
layout->lastCommitBlocks.borderDimensions, QSize(layout->getBorderWidth(), layout->getBorderHeight()),
layout->lastCommitBlocks.border, layout->border
));
}
}
@@ -59,27 +59,27 @@ void MainWindow::tryCommitMapChanges(bool commitChanges) {
//=====================
QJSValue MainWindow::getBlock(int x, int y) {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return QJSValue();
Block block;
if (!this->editor->map->getBlock(x, y, &block)) {
if (!this->editor->layout->getBlock(x, y, &block)) {
return Scripting::fromBlock(Block());
}
return Scripting::fromBlock(block);
}
void MainWindow::setBlock(int x, int y, int metatileId, int collision, int elevation, bool forceRedraw, bool commitChanges) {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return;
this->editor->map->setBlock(x, y, Block(metatileId, collision, elevation));
this->editor->layout->setBlock(x, y, Block(metatileId, collision, elevation));
this->tryCommitMapChanges(commitChanges);
this->tryRedrawMapArea(forceRedraw);
}
void MainWindow::setBlock(int x, int y, int rawValue, bool forceRedraw, bool commitChanges) {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return;
this->editor->map->setBlock(x, y, Block(static_cast<uint16_t>(rawValue)));
this->editor->layout->setBlock(x, y, Block(static_cast<uint16_t>(rawValue)));
this->tryCommitMapChanges(commitChanges);
this->tryRedrawMapArea(forceRedraw);
}
@@ -93,73 +93,73 @@ void MainWindow::setBlocksFromSelection(int x, int y, bool forceRedraw, bool com
}
int MainWindow::getMetatileId(int x, int y) {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return 0;
Block block;
if (!this->editor->map->getBlock(x, y, &block)) {
if (!this->editor->layout->getBlock(x, y, &block)) {
return 0;
}
return block.metatileId();
}
void MainWindow::setMetatileId(int x, int y, int metatileId, bool forceRedraw, bool commitChanges) {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return;
Block block;
if (!this->editor->map->getBlock(x, y, &block)) {
if (!this->editor->layout->getBlock(x, y, &block)) {
return;
}
this->editor->map->setBlock(x, y, Block(metatileId, block.collision(), block.elevation()));
this->editor->layout->setBlock(x, y, Block(metatileId, block.collision(), block.elevation()));
this->tryCommitMapChanges(commitChanges);
this->tryRedrawMapArea(forceRedraw);
}
int MainWindow::getCollision(int x, int y) {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return 0;
Block block;
if (!this->editor->map->getBlock(x, y, &block)) {
if (!this->editor->layout->getBlock(x, y, &block)) {
return 0;
}
return block.collision();
}
void MainWindow::setCollision(int x, int y, int collision, bool forceRedraw, bool commitChanges) {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return;
Block block;
if (!this->editor->map->getBlock(x, y, &block)) {
if (!this->editor->layout->getBlock(x, y, &block)) {
return;
}
this->editor->map->setBlock(x, y, Block(block.metatileId(), collision, block.elevation()));
this->editor->layout->setBlock(x, y, Block(block.metatileId(), collision, block.elevation()));
this->tryCommitMapChanges(commitChanges);
this->tryRedrawMapArea(forceRedraw);
}
int MainWindow::getElevation(int x, int y) {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return 0;
Block block;
if (!this->editor->map->getBlock(x, y, &block)) {
if (!this->editor->layout->getBlock(x, y, &block)) {
return 0;
}
return block.elevation();
}
void MainWindow::setElevation(int x, int y, int elevation, bool forceRedraw, bool commitChanges) {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return;
Block block;
if (!this->editor->map->getBlock(x, y, &block)) {
if (!this->editor->layout->getBlock(x, y, &block)) {
return;
}
this->editor->map->setBlock(x, y, Block(block.metatileId(), block.collision(), elevation));
this->editor->layout->setBlock(x, y, Block(block.metatileId(), block.collision(), elevation));
this->tryCommitMapChanges(commitChanges);
this->tryRedrawMapArea(forceRedraw);
}
void MainWindow::bucketFill(int x, int y, int metatileId, bool forceRedraw, bool commitChanges) {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return;
this->editor->map_item->floodFill(x, y, metatileId, true);
this->tryCommitMapChanges(commitChanges);
@@ -167,7 +167,7 @@ void MainWindow::bucketFill(int x, int y, int metatileId, bool forceRedraw, bool
}
void MainWindow::bucketFillFromSelection(int x, int y, bool forceRedraw, bool commitChanges) {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return;
this->editor->map_item->floodFill(x, y, true);
this->tryCommitMapChanges(commitChanges);
@@ -175,7 +175,7 @@ void MainWindow::bucketFillFromSelection(int x, int y, bool forceRedraw, bool co
}
void MainWindow::magicFill(int x, int y, int metatileId, bool forceRedraw, bool commitChanges) {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return;
this->editor->map_item->magicFill(x, y, metatileId, true);
this->tryCommitMapChanges(commitChanges);
@@ -183,7 +183,7 @@ void MainWindow::magicFill(int x, int y, int metatileId, bool forceRedraw, bool
}
void MainWindow::magicFillFromSelection(int x, int y, bool forceRedraw, bool commitChanges) {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return;
this->editor->map_item->magicFill(x, y, true);
this->tryCommitMapChanges(commitChanges);
@@ -191,7 +191,7 @@ void MainWindow::magicFillFromSelection(int x, int y, bool forceRedraw, bool com
}
void MainWindow::shift(int xDelta, int yDelta, bool forceRedraw, bool commitChanges) {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return;
this->editor->map_item->shift(xDelta, yDelta, true);
this->tryCommitMapChanges(commitChanges);
@@ -207,51 +207,51 @@ void MainWindow::commit() {
}
QJSValue MainWindow::getDimensions() {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return QJSValue();
return Scripting::dimensions(this->editor->map->getWidth(), this->editor->map->getHeight());
return Scripting::dimensions(this->editor->layout->getWidth(), this->editor->layout->getHeight());
}
int MainWindow::getWidth() {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return 0;
return this->editor->map->getWidth();
return this->editor->layout->getWidth();
}
int MainWindow::getHeight() {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return 0;
return this->editor->map->getHeight();
return this->editor->layout->getHeight();
}
void MainWindow::setDimensions(int width, int height) {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return;
if (!Project::mapDimensionsValid(width, height))
return;
this->editor->map->setDimensions(width, height);
this->editor->layout->setDimensions(width, height);
this->tryCommitMapChanges(true);
this->onMapNeedsRedrawing();
this->redrawMapScene();
}
void MainWindow::setWidth(int width) {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return;
if (!Project::mapDimensionsValid(width, this->editor->map->getHeight()))
if (!Project::mapDimensionsValid(width, this->editor->layout->getHeight()))
return;
this->editor->map->setDimensions(width, this->editor->map->getHeight());
this->editor->layout->setDimensions(width, this->editor->layout->getHeight());
this->tryCommitMapChanges(true);
this->onMapNeedsRedrawing();
this->redrawMapScene();
}
void MainWindow::setHeight(int height) {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return;
if (!Project::mapDimensionsValid(this->editor->map->getWidth(), height))
if (!Project::mapDimensionsValid(this->editor->layout->getWidth(), height))
return;
this->editor->map->setDimensions(this->editor->map->getWidth(), height);
this->editor->layout->setDimensions(this->editor->layout->getWidth(), height);
this->tryCommitMapChanges(true);
this->onMapNeedsRedrawing();
this->redrawMapScene();
}
//=====================
@@ -259,69 +259,69 @@ void MainWindow::setHeight(int height) {
//=====================
int MainWindow::getBorderMetatileId(int x, int y) {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return 0;
if (!this->editor->map->isWithinBorderBounds(x, y))
if (!this->editor->layout->isWithinBorderBounds(x, y))
return 0;
return this->editor->map->getBorderMetatileId(x, y);
return this->editor->layout->getBorderMetatileId(x, y);
}
void MainWindow::setBorderMetatileId(int x, int y, int metatileId, bool forceRedraw, bool commitChanges) {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return;
if (!this->editor->map->isWithinBorderBounds(x, y))
if (!this->editor->layout->isWithinBorderBounds(x, y))
return;
this->editor->map->setBorderMetatileId(x, y, metatileId);
this->editor->layout->setBorderMetatileId(x, y, metatileId);
this->tryCommitMapChanges(commitChanges);
this->tryRedrawMapArea(forceRedraw);
}
QJSValue MainWindow::getBorderDimensions() {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return QJSValue();
return Scripting::dimensions(this->editor->map->getBorderWidth(), this->editor->map->getBorderHeight());
return Scripting::dimensions(this->editor->layout->getBorderWidth(), this->editor->layout->getBorderHeight());
}
int MainWindow::getBorderWidth() {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return 0;
return this->editor->map->getBorderWidth();
return this->editor->layout->getBorderWidth();
}
int MainWindow::getBorderHeight() {
if (!this->editor || !this->editor->map)
if (!this->editor || !this->editor->layout)
return 0;
return this->editor->map->getBorderHeight();
return this->editor->layout->getBorderHeight();
}
void MainWindow::setBorderDimensions(int width, int height) {
if (!this->editor || !this->editor->map || !projectConfig.useCustomBorderSize)
if (!this->editor || !this->editor->layout || !projectConfig.useCustomBorderSize)
return;
if (width < 1 || height < 1 || width > MAX_BORDER_WIDTH || height > MAX_BORDER_HEIGHT)
return;
this->editor->map->setBorderDimensions(width, height);
this->editor->layout->setBorderDimensions(width, height);
this->tryCommitMapChanges(true);
this->onMapNeedsRedrawing();
this->redrawMapScene();
}
void MainWindow::setBorderWidth(int width) {
if (!this->editor || !this->editor->map || !projectConfig.useCustomBorderSize)
if (!this->editor || !this->editor->layout || !projectConfig.useCustomBorderSize)
return;
if (width < 1 || width > MAX_BORDER_WIDTH)
return;
this->editor->map->setBorderDimensions(width, this->editor->map->getBorderHeight());
this->editor->layout->setBorderDimensions(width, this->editor->layout->getBorderHeight());
this->tryCommitMapChanges(true);
this->onMapNeedsRedrawing();
this->redrawMapScene();
}
void MainWindow::setBorderHeight(int height) {
if (!this->editor || !this->editor->map || !projectConfig.useCustomBorderSize)
if (!this->editor || !this->editor->layout || !projectConfig.useCustomBorderSize)
return;
if (height < 1 || height > MAX_BORDER_HEIGHT)
return;
this->editor->map->setBorderDimensions(this->editor->map->getBorderWidth(), height);
this->editor->layout->setBorderDimensions(this->editor->layout->getBorderWidth(), height);
this->tryCommitMapChanges(true);
this->onMapNeedsRedrawing();
this->redrawMapScene();
}
//======================
@@ -330,7 +330,7 @@ void MainWindow::setBorderHeight(int height) {
void MainWindow::refreshAfterPaletteChange(Tileset *tileset) {
if (this->tilesetEditor) {
this->tilesetEditor->updateTilesets(this->editor->map->layout->tileset_primary_label, this->editor->map->layout->tileset_secondary_label);
this->tilesetEditor->updateTilesets(this->editor->layout->tileset_primary_label, this->editor->layout->tileset_secondary_label);
}
this->editor->metatile_selector_item->draw();
this->editor->selected_border_metatiles_item->draw();
@@ -341,7 +341,7 @@ void MainWindow::refreshAfterPaletteChange(Tileset *tileset) {
}
void MainWindow::setTilesetPalette(Tileset *tileset, int paletteIndex, QList<QList<int>> colors) {
if (!this->editor || !this->editor->map || !this->editor->map->layout)
if (!this->editor || !this->editor->layout)
return;
if (paletteIndex >= tileset->palettes.size())
return;
@@ -357,42 +357,42 @@ void MainWindow::setTilesetPalette(Tileset *tileset, int paletteIndex, QList<QLi
}
void MainWindow::setPrimaryTilesetPalette(int paletteIndex, QList<QList<int>> colors, bool forceRedraw) {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary)
return;
this->setTilesetPalette(this->editor->map->layout->tileset_primary, paletteIndex, colors);
this->setTilesetPalette(this->editor->layout->tileset_primary, paletteIndex, colors);
if (forceRedraw) {
this->refreshAfterPaletteChange(this->editor->map->layout->tileset_primary);
this->refreshAfterPaletteChange(this->editor->layout->tileset_primary);
}
}
void MainWindow::setPrimaryTilesetPalettes(QList<QList<QList<int>>> palettes, bool forceRedraw) {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary)
return;
for (int i = 0; i < palettes.size(); i++) {
this->setTilesetPalette(this->editor->map->layout->tileset_primary, i, palettes[i]);
this->setTilesetPalette(this->editor->layout->tileset_primary, i, palettes[i]);
}
if (forceRedraw) {
this->refreshAfterPaletteChange(this->editor->map->layout->tileset_primary);
this->refreshAfterPaletteChange(this->editor->layout->tileset_primary);
}
}
void MainWindow::setSecondaryTilesetPalette(int paletteIndex, QList<QList<int>> colors, bool forceRedraw) {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary)
return;
this->setTilesetPalette(this->editor->map->layout->tileset_secondary, paletteIndex, colors);
this->setTilesetPalette(this->editor->layout->tileset_secondary, paletteIndex, colors);
if (forceRedraw) {
this->refreshAfterPaletteChange(this->editor->map->layout->tileset_secondary);
this->refreshAfterPaletteChange(this->editor->layout->tileset_secondary);
}
}
void MainWindow::setSecondaryTilesetPalettes(QList<QList<QList<int>>> palettes, bool forceRedraw) {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary)
return;
for (int i = 0; i < palettes.size(); i++) {
this->setTilesetPalette(this->editor->map->layout->tileset_secondary, i, palettes[i]);
this->setTilesetPalette(this->editor->layout->tileset_secondary, i, palettes[i]);
}
if (forceRedraw) {
this->refreshAfterPaletteChange(this->editor->map->layout->tileset_secondary);
this->refreshAfterPaletteChange(this->editor->layout->tileset_secondary);
}
}
@@ -420,27 +420,27 @@ QJSValue MainWindow::getTilesetPalettes(const QList<QList<QRgb>> &palettes) {
}
QJSValue MainWindow::getPrimaryTilesetPalette(int paletteIndex) {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary)
return QJSValue();
return this->getTilesetPalette(this->editor->map->layout->tileset_primary->palettes, paletteIndex);
return this->getTilesetPalette(this->editor->layout->tileset_primary->palettes, paletteIndex);
}
QJSValue MainWindow::getPrimaryTilesetPalettes() {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary)
return QJSValue();
return this->getTilesetPalettes(this->editor->map->layout->tileset_primary->palettes);
return this->getTilesetPalettes(this->editor->layout->tileset_primary->palettes);
}
QJSValue MainWindow::getSecondaryTilesetPalette(int paletteIndex) {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary)
return QJSValue();
return this->getTilesetPalette(this->editor->map->layout->tileset_secondary->palettes, paletteIndex);
return this->getTilesetPalette(this->editor->layout->tileset_secondary->palettes, paletteIndex);
}
QJSValue MainWindow::getSecondaryTilesetPalettes() {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary)
return QJSValue();
return this->getTilesetPalettes(this->editor->map->layout->tileset_secondary->palettes);
return this->getTilesetPalettes(this->editor->layout->tileset_secondary->palettes);
}
void MainWindow::refreshAfterPalettePreviewChange() {
@@ -452,7 +452,7 @@ void MainWindow::refreshAfterPalettePreviewChange() {
}
void MainWindow::setTilesetPalettePreview(Tileset *tileset, int paletteIndex, QList<QList<int>> colors) {
if (!this->editor || !this->editor->map || !this->editor->map->layout)
if (!this->editor || !this->editor->layout)
return;
if (paletteIndex >= tileset->palettePreviews.size())
return;
@@ -467,19 +467,19 @@ void MainWindow::setTilesetPalettePreview(Tileset *tileset, int paletteIndex, QL
}
void MainWindow::setPrimaryTilesetPalettePreview(int paletteIndex, QList<QList<int>> colors, bool forceRedraw) {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary)
return;
this->setTilesetPalettePreview(this->editor->map->layout->tileset_primary, paletteIndex, colors);
this->setTilesetPalettePreview(this->editor->layout->tileset_primary, paletteIndex, colors);
if (forceRedraw) {
this->refreshAfterPalettePreviewChange();
}
}
void MainWindow::setPrimaryTilesetPalettesPreview(QList<QList<QList<int>>> palettes, bool forceRedraw) {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary)
return;
for (int i = 0; i < palettes.size(); i++) {
this->setTilesetPalettePreview(this->editor->map->layout->tileset_primary, i, palettes[i]);
this->setTilesetPalettePreview(this->editor->layout->tileset_primary, i, palettes[i]);
}
if (forceRedraw) {
this->refreshAfterPalettePreviewChange();
@@ -487,19 +487,19 @@ void MainWindow::setPrimaryTilesetPalettesPreview(QList<QList<QList<int>>> palet
}
void MainWindow::setSecondaryTilesetPalettePreview(int paletteIndex, QList<QList<int>> colors, bool forceRedraw) {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary)
return;
this->setTilesetPalettePreview(this->editor->map->layout->tileset_secondary, paletteIndex, colors);
this->setTilesetPalettePreview(this->editor->layout->tileset_secondary, paletteIndex, colors);
if (forceRedraw) {
this->refreshAfterPalettePreviewChange();
}
}
void MainWindow::setSecondaryTilesetPalettesPreview(QList<QList<QList<int>>> palettes, bool forceRedraw) {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary)
return;
for (int i = 0; i < palettes.size(); i++) {
this->setTilesetPalettePreview(this->editor->map->layout->tileset_secondary, i, palettes[i]);
this->setTilesetPalettePreview(this->editor->layout->tileset_secondary, i, palettes[i]);
}
if (forceRedraw) {
this->refreshAfterPalettePreviewChange();
@@ -507,63 +507,63 @@ void MainWindow::setSecondaryTilesetPalettesPreview(QList<QList<QList<int>>> pal
}
QJSValue MainWindow::getPrimaryTilesetPalettePreview(int paletteIndex) {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary)
return QJSValue();
return this->getTilesetPalette(this->editor->map->layout->tileset_primary->palettePreviews, paletteIndex);
return this->getTilesetPalette(this->editor->layout->tileset_primary->palettePreviews, paletteIndex);
}
QJSValue MainWindow::getPrimaryTilesetPalettesPreview() {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary)
return QJSValue();
return this->getTilesetPalettes(this->editor->map->layout->tileset_primary->palettePreviews);
return this->getTilesetPalettes(this->editor->layout->tileset_primary->palettePreviews);
}
QJSValue MainWindow::getSecondaryTilesetPalettePreview(int paletteIndex) {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary)
return QJSValue();
return this->getTilesetPalette(this->editor->map->layout->tileset_secondary->palettePreviews, paletteIndex);
return this->getTilesetPalette(this->editor->layout->tileset_secondary->palettePreviews, paletteIndex);
}
QJSValue MainWindow::getSecondaryTilesetPalettesPreview() {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary)
return QJSValue();
return this->getTilesetPalettes(this->editor->map->layout->tileset_secondary->palettePreviews);
return this->getTilesetPalettes(this->editor->layout->tileset_secondary->palettePreviews);
}
int MainWindow::getNumPrimaryTilesetMetatiles() {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary)
return 0;
return this->editor->map->layout->tileset_primary->metatiles.length();
return this->editor->layout->tileset_primary->numMetatiles();
}
int MainWindow::getNumSecondaryTilesetMetatiles() {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary)
return 0;
return this->editor->map->layout->tileset_secondary->metatiles.length();
return this->editor->layout->tileset_secondary->numMetatiles();
}
int MainWindow::getNumPrimaryTilesetTiles() {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary)
return 0;
return this->editor->map->layout->tileset_primary->tiles.length();
return this->editor->layout->tileset_primary->tiles.length();
}
int MainWindow::getNumSecondaryTilesetTiles() {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary)
return 0;
return this->editor->map->layout->tileset_secondary->tiles.length();
return this->editor->layout->tileset_secondary->tiles.length();
}
QString MainWindow::getPrimaryTileset() {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_primary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary)
return QString();
return this->editor->map->layout->tileset_primary->name;
return this->editor->layout->tileset_primary->name;
}
QString MainWindow::getSecondaryTileset() {
if (!this->editor || !this->editor->map || !this->editor->map->layout || !this->editor->map->layout->tileset_secondary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_secondary)
return QString();
return this->editor->map->layout->tileset_secondary->name;
return this->editor->layout->tileset_secondary->name;
}
void MainWindow::setPrimaryTileset(QString tileset) {
@@ -575,13 +575,13 @@ void MainWindow::setSecondaryTileset(QString tileset) {
}
void MainWindow::saveMetatilesByMetatileId(int metatileId) {
Tileset * tileset = Tileset::getMetatileTileset(metatileId, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary);
Tileset * tileset = Tileset::getMetatileTileset(metatileId, this->editor->layout->tileset_primary, this->editor->layout->tileset_secondary);
if (this->editor->project && tileset)
this->editor->project->saveTilesetMetatiles(tileset);
}
void MainWindow::saveMetatileAttributesByMetatileId(int metatileId) {
Tileset * tileset = Tileset::getMetatileTileset(metatileId, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary);
Tileset * tileset = Tileset::getMetatileTileset(metatileId, this->editor->layout->tileset_primary, this->editor->layout->tileset_secondary);
if (this->editor->project && tileset)
this->editor->project->saveTilesetMetatileAttributes(tileset);
@@ -597,19 +597,19 @@ void MainWindow::saveMetatileAttributesByMetatileId(int metatileId) {
}
Metatile * MainWindow::getMetatile(int metatileId) {
if (!this->editor || !this->editor->map || !this->editor->map->layout)
if (!this->editor || !this->editor->layout)
return nullptr;
return Tileset::getMetatile(metatileId, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary);
return Tileset::getMetatile(metatileId, this->editor->layout->tileset_primary, this->editor->layout->tileset_secondary);
}
QString MainWindow::getMetatileLabel(int metatileId) {
if (!this->editor || !this->editor->map || !this->editor->map->layout)
if (!this->editor || !this->editor->layout)
return QString();
return Tileset::getMetatileLabel(metatileId, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary);
return Tileset::getMetatileLabel(metatileId, this->editor->layout->tileset_primary, this->editor->layout->tileset_secondary);
}
void MainWindow::setMetatileLabel(int metatileId, QString label) {
if (!this->editor || !this->editor->map || !this->editor->map->layout)
if (!this->editor || !this->editor->layout)
return;
// If the Tileset Editor is opened on this metatile we need to update the text box
@@ -618,13 +618,13 @@ void MainWindow::setMetatileLabel(int metatileId, QString label) {
return;
}
if (!Tileset::setMetatileLabel(metatileId, label, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary)) {
if (!Tileset::setMetatileLabel(metatileId, label, this->editor->layout->tileset_primary, this->editor->layout->tileset_secondary)) {
logError("Failed to set metatile label. Must be a valid metatile id and a label containing only letters, numbers, and underscores.");
return;
}
if (this->editor->project)
this->editor->project->saveTilesetMetatileLabels(this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary);
this->editor->project->saveTilesetMetatileLabels(this->editor->layout->tileset_primary, this->editor->layout->tileset_secondary);
}
int MainWindow::getMetatileLayerType(int metatileId) {
@@ -794,9 +794,9 @@ void MainWindow::setMetatileTile(int metatileId, int tileIndex, QJSValue tileObj
}
QJSValue MainWindow::getTilePixels(int tileId) {
if (tileId < 0 || !this->editor || !this->editor->project || !this->editor->map || !this->editor->map->layout)
if (tileId < 0 || !this->editor || !this->editor->project || !this->editor->map || !this->editor->layout)
return QJSValue();
QImage tileImage = getTileImage(tileId, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary);
QImage tileImage = getTileImage(tileId, this->editor->layout->tileset_primary, this->editor->layout->tileset_secondary);
if (tileImage.isNull() || tileImage.sizeInBytes() < 64)
return QJSValue();
const uchar * pixels = tileImage.constBits();
@@ -836,7 +836,7 @@ QString MainWindow::getLocation() {
void MainWindow::setLocation(QString location) {
if (!this->ui || !this->editor || !this->editor->project)
return;
if (!this->editor->project->mapSectionNameToValue.contains(location)) {
if (!this->editor->project->mapSectionIdNames.contains(location)) {
logError(QString("Unknown location '%1'").arg(location));
return;
}

View File

@@ -254,23 +254,21 @@ void MapView::addImage(int x, int y, QString filepath, int layer, bool useCache)
}
void MapView::createImage(int x, int y, QString filepath, int width, int height, int xOffset, int yOffset, qreal hScale, qreal vScale, int paletteId, bool setTransparency, int layer, bool useCache) {
if (!this->editor || !this->editor->map || !this->editor->map->layout
|| !this->editor->map->layout->tileset_primary || !this->editor->map->layout->tileset_secondary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary || !this->editor->layout->tileset_secondary)
return;
QList<QRgb> palette;
if (paletteId != -1)
palette = Tileset::getPalette(paletteId, this->editor->map->layout->tileset_primary, this->editor->map->layout->tileset_secondary);
palette = Tileset::getPalette(paletteId, this->editor->layout->tileset_primary, this->editor->layout->tileset_secondary);
if (this->getOverlay(layer)->addImage(x, y, filepath, useCache, width, height, xOffset, yOffset, hScale, vScale, palette, setTransparency))
this->scene()->update();
}
void MapView::addTileImage(int x, int y, int tileId, bool xflip, bool yflip, int paletteId, bool setTransparency, int layer) {
if (!this->editor || !this->editor->map || !this->editor->map->layout
|| !this->editor->map->layout->tileset_primary || !this->editor->map->layout->tileset_secondary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary || !this->editor->layout->tileset_secondary)
return;
QImage image = getPalettedTileImage(tileId,
this->editor->map->layout->tileset_primary,
this->editor->map->layout->tileset_secondary,
this->editor->layout->tileset_primary,
this->editor->layout->tileset_secondary,
paletteId)
.mirrored(xflip, yflip);
if (setTransparency)
@@ -285,14 +283,13 @@ void MapView::addTileImage(int x, int y, QJSValue tileObj, bool setTransparency,
}
void MapView::addMetatileImage(int x, int y, int metatileId, bool setTransparency, int layer) {
if (!this->editor || !this->editor->map || !this->editor->map->layout
|| !this->editor->map->layout->tileset_primary || !this->editor->map->layout->tileset_secondary)
if (!this->editor || !this->editor->layout || !this->editor->layout->tileset_primary || !this->editor->layout->tileset_secondary)
return;
QImage image = getMetatileImage(static_cast<uint16_t>(metatileId),
this->editor->map->layout->tileset_primary,
this->editor->map->layout->tileset_secondary,
this->editor->map->metatileLayerOrder,
this->editor->map->metatileLayerOpacity);
this->editor->layout->tileset_primary,
this->editor->layout->tileset_secondary,
this->editor->layout->metatileLayerOrder,
this->editor->layout->metatileLayerOpacity);
if (setTransparency)
image.setColor(0, qRgba(0, 0, 0, 0));
if (this->getOverlay(layer)->addImage(x, y, image))

Some files were not shown because too many files have changed in this diff Show More