Merge branch 'master' of https://github.com/huderlem/porymap into slam
This commit is contained in:
commit
b5c50e7660
39 changed files with 2206 additions and 5929 deletions
|
@ -11,6 +11,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
|
|||
- 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 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.
|
||||
|
||||
|
@ -22,6 +23,7 @@ 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.
|
||||
|
||||
### Fixed
|
||||
- Fix `Add Region Map...` not updating the region map settings file.
|
||||
|
@ -46,6 +48,10 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
|
|||
- 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.
|
||||
|
||||
## [5.4.1] - 2024-03-21
|
||||
### Fixed
|
||||
|
|
310
forms/colorinputwidget.ui
Normal file
310
forms/colorinputwidget.ui
Normal 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>
|
275
forms/gridsettingsdialog.ui
Normal file
275
forms/gridsettingsdialog.ui
Normal 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>
|
|
@ -2939,12 +2939,6 @@
|
|||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
|
@ -3459,10 +3453,13 @@
|
|||
</property>
|
||||
<addaction name="actionZoom_In"/>
|
||||
<addaction name="actionZoom_Out"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionCursor_Tile_Outline"/>
|
||||
<addaction name="actionPlayer_View_Rectangle"/>
|
||||
<addaction name="actionBetter_Cursors"/>
|
||||
<addaction name="actionDive_Emerge_Map"/>
|
||||
<addaction name="actionShow_Grid"/>
|
||||
<addaction name="actionGrid_Settings"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuTools">
|
||||
<property name="title">
|
||||
|
@ -3694,7 +3691,7 @@
|
|||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Player View Rectangle</string>
|
||||
<string>Show Player View Rectangle</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Show the player's view rectangle on the map based on the cursor's position.</p></body></html></string>
|
||||
|
@ -3711,7 +3708,7 @@
|
|||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Cursor Tile Outline</string>
|
||||
<string>Show Cursor Tile Outline</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>C</string>
|
||||
|
@ -3810,7 +3807,26 @@
|
|||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Dive/Emerge Map</string>
|
||||
<string>Show Dive/Emerge Map</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionShow_Grid">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Grid</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+G</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGrid_Settings">
|
||||
<property name="text">
|
||||
<string>Grid Settings...</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
|
|
|
@ -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>
|
||||
|
|
File diff suppressed because it is too large
Load diff
65
include/core/filedialog.h
Normal file
65
include/core/filedialog.h
Normal 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
|
|
@ -24,6 +24,7 @@
|
|||
#include "collisionpixmapitem.h"
|
||||
#include "layoutpixmapitem.h"
|
||||
#include "settings.h"
|
||||
#include "gridsettings.h"
|
||||
#include "movablerect.h"
|
||||
#include "cursortilerect.h"
|
||||
#include "mapruler.h"
|
||||
|
@ -54,6 +55,7 @@ public:
|
|||
QUndoGroup editGroup; // Manages the undo history for each map
|
||||
|
||||
Settings *settings;
|
||||
GridSettings gridSettings;
|
||||
|
||||
void setProject(Project * project);
|
||||
void save();
|
||||
|
@ -83,6 +85,7 @@ public:
|
|||
void displayMapConnections();
|
||||
void displayMapBorder();
|
||||
void displayMapGrid();
|
||||
void updateMapGrid();
|
||||
void displayWildMonTables();
|
||||
|
||||
void updateMapBorder();
|
||||
|
@ -132,7 +135,7 @@ public:
|
|||
QGraphicsItemGroup *events_group = nullptr;
|
||||
|
||||
QList<QGraphicsPixmapItem*> borderItems;
|
||||
QList<QGraphicsLineItem*> gridLines;
|
||||
QGraphicsItemGroup *mapGrid = nullptr;
|
||||
MapRuler *map_ruler = nullptr;
|
||||
|
||||
MovableRect *playerViewRect = nullptr;
|
||||
|
@ -197,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");
|
||||
|
@ -251,7 +255,6 @@ private slots:
|
|||
void onHoveredMapMovementPermissionCleared();
|
||||
void onSelectedMetatilesChanged();
|
||||
void onWheelZoom(int);
|
||||
void onToggleGridClicked(bool);
|
||||
|
||||
signals:
|
||||
void objectsChanged();
|
||||
|
@ -263,6 +266,7 @@ signals:
|
|||
void currentMetatilesSelectionChanged();
|
||||
void mapRulerStatusChanged(const QString &);
|
||||
void tilesetUpdated(QString);
|
||||
void gridToggled(bool);
|
||||
};
|
||||
|
||||
#endif // EDITOR_H
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "shortcutseditor.h"
|
||||
#include "preferenceeditor.h"
|
||||
#include "projectsettingseditor.h"
|
||||
#include "gridsettings.h"
|
||||
#include "customscriptseditor.h"
|
||||
#include "wildmonchart.h"
|
||||
#include "updatepromoter.h"
|
||||
|
@ -326,6 +327,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;
|
||||
|
@ -340,6 +343,7 @@ private:
|
|||
QPointer<NewMapPopup> newMapPrompt = nullptr;
|
||||
QPointer<PreferenceEditor> preferenceEditor = nullptr;
|
||||
QPointer<ProjectSettingsEditor> projectSettingsEditor = nullptr;
|
||||
QPointer<GridSettingsDialog> gridSettingsDialog = nullptr;
|
||||
QPointer<CustomScriptsEditor> customScriptsEditor = nullptr;
|
||||
|
||||
FilterChildrenProxyModel *groupListProxyModel;
|
||||
|
|
|
@ -77,7 +77,6 @@ public:
|
|||
QFileSystemWatcher fileWatcher;
|
||||
QMap<QString, qint64> modifiedFileTimestamps;
|
||||
bool usingAsmTilesets;
|
||||
QString importExportPath;
|
||||
QSet<QString> disabledSettingsNames;
|
||||
int pokemonMinLevel;
|
||||
int pokemonMaxLevel;
|
||||
|
@ -227,7 +226,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();
|
||||
|
||||
|
|
46
include/ui/colorinputwidget.h
Normal file
46
include/ui/colorinputwidget.h
Normal 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
|
|
@ -31,7 +31,6 @@ private:
|
|||
Ui::CustomScriptsEditor *ui;
|
||||
|
||||
bool hasUnsavedChanges = false;
|
||||
QString fileDialogDir;
|
||||
const QString baseDir;
|
||||
|
||||
void displayScript(const QString &filepath, bool enabled);
|
||||
|
|
99
include/ui/gridsettings.h
Normal file
99
include/ui/gridsettings.h
Normal 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
|
|
@ -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
|
||||
|
@ -34,50 +52,44 @@ private:
|
|||
|
||||
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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -69,7 +69,7 @@ private:
|
|||
void applySpeciesColors(const QList<QBarSet*> &);
|
||||
QChart::ChartTheme currentTheme() const;
|
||||
void updateTheme();
|
||||
void limitChartAnimation(QChart*);
|
||||
void limitChartAnimation();
|
||||
|
||||
void showHelpDialog();
|
||||
};
|
||||
|
|
|
@ -25,6 +25,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,6 +52,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 \
|
||||
|
@ -60,6 +62,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 \
|
||||
|
@ -122,6 +125,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 \
|
||||
|
@ -158,6 +162,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 \
|
||||
|
@ -176,6 +181,7 @@ HEADERS += include/core/block.h \
|
|||
include/ui/prefabcreationdialog.h \
|
||||
include/ui/regionmappixmapitem.h \
|
||||
include/ui/citymappixmapitem.h \
|
||||
include/ui/colorinputwidget.h \
|
||||
include/ui/metatilelayersitem.h \
|
||||
include/ui/metatileselector.h \
|
||||
include/ui/movablerect.h \
|
||||
|
@ -220,7 +226,9 @@ HEADERS += include/core/block.h \
|
|||
include/ui/wildmonchart.h
|
||||
|
||||
FORMS += forms/mainwindow.ui \
|
||||
forms/colorinputwidget.ui \
|
||||
forms/connectionslistitem.ui \
|
||||
forms/gridsettingsdialog.ui \
|
||||
forms/newmapconnectiondialog.ui \
|
||||
forms/prefabcreationdialog.ui \
|
||||
forms/prefabframe.ui \
|
||||
|
|
BIN
resources/icons/link.ico
Executable file
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
BIN
resources/icons/link_broken.ico
Executable file
Binary file not shown.
After Width: | Height: | Size: 2 KiB |
|
@ -21,6 +21,8 @@
|
|||
<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>
|
||||
|
|
51
src/core/filedialog.cpp
Normal file
51
src/core/filedialog.cpp
Normal 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;
|
||||
}
|
|
@ -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()
|
||||
|
@ -1913,40 +1917,69 @@ 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 = this->layout->getWidth() * 16;
|
||||
int pixelHeight = this->layout->getHeight() * 16;
|
||||
for (int i = 0; i <= this->layout->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 <= this->layout->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)
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
#include "eventfilters.h"
|
||||
#include "newmapconnectiondialog.h"
|
||||
#include "config.h"
|
||||
#include "filedialog.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QClipboard>
|
||||
#include <QDirIterator>
|
||||
#include <QStandardItemModel>
|
||||
|
@ -149,10 +149,6 @@ void MainWindow::initExtraShortcuts() {
|
|||
shortcutReset_Zoom->setObjectName("shortcutZoom_Reset");
|
||||
shortcutReset_Zoom->setWhatsThis("Zoom Reset");
|
||||
|
||||
auto *shortcutToggle_Grid = new Shortcut(QKeySequence("Ctrl+G"), ui->checkBox_ToggleGrid, SLOT(toggle()));
|
||||
shortcutToggle_Grid->setObjectName("shortcutToggle_Grid");
|
||||
shortcutToggle_Grid->setWhatsThis("Toggle Grid");
|
||||
|
||||
auto *shortcutDuplicate_Events = new Shortcut(QKeySequence("Ctrl+D"), this, SLOT(duplicate()));
|
||||
shortcutDuplicate_Events->setObjectName("shortcutDuplicate_Events");
|
||||
shortcutDuplicate_Events->setWhatsThis("Duplicate Selected Event(s)");
|
||||
|
@ -358,8 +354,6 @@ void MainWindow::initEditor() {
|
|||
connect(this->editor, &Editor::wildMonTableEdited, [this] { this->markMapEdited(); });
|
||||
connect(this->editor, &Editor::mapRulerStatusChanged, this, &MainWindow::onMapRulerStatusChanged);
|
||||
connect(this->editor, &Editor::tilesetUpdated, this, &Scripting::cb_TilesetUpdated);
|
||||
connect(ui->toolButton_Open_Scripts, &QToolButton::pressed, this->editor, &Editor::openMapScripts);
|
||||
connect(ui->actionOpen_Project_in_Text_Editor, &QAction::triggered, this->editor, &Editor::openProjectInTextEditor);
|
||||
|
||||
this->loadUserSettings();
|
||||
|
||||
|
@ -501,27 +495,45 @@ void MainWindow::applyMapListFilter(QString filterText) {
|
|||
}
|
||||
|
||||
void MainWindow::loadUserSettings() {
|
||||
const QSignalBlocker blocker1(ui->horizontalSlider_CollisionTransparency);
|
||||
const QSignalBlocker blocker2(ui->slider_DiveEmergeMapOpacity);
|
||||
const QSignalBlocker blocker3(ui->slider_DiveMapOpacity);
|
||||
const QSignalBlocker blocker4(ui->slider_EmergeMapOpacity);
|
||||
const QSignalBlocker blocker5(ui->horizontalSlider_MetatileZoom);
|
||||
const QSignalBlocker blocker6(ui->horizontalSlider_CollisionZoom);
|
||||
|
||||
// Better Cursors
|
||||
ui->actionBetter_Cursors->setChecked(porymapConfig.prettyCursors);
|
||||
this->editor->settings->betterCursors = porymapConfig.prettyCursors;
|
||||
|
||||
// Player view rectangle
|
||||
ui->actionPlayer_View_Rectangle->setChecked(porymapConfig.showPlayerView);
|
||||
this->editor->settings->playerViewRectEnabled = porymapConfig.showPlayerView;
|
||||
|
||||
// Cursor tile outline
|
||||
ui->actionCursor_Tile_Outline->setChecked(porymapConfig.showCursorTile);
|
||||
this->editor->settings->cursorTileRectEnabled = porymapConfig.showCursorTile;
|
||||
|
||||
// Border
|
||||
ui->checkBox_ToggleBorder->setChecked(porymapConfig.showBorder);
|
||||
|
||||
// Grid
|
||||
const QSignalBlocker b_Grid(ui->checkBox_ToggleGrid);
|
||||
ui->actionShow_Grid->setChecked(porymapConfig.showGrid);
|
||||
ui->checkBox_ToggleGrid->setChecked(porymapConfig.showGrid);
|
||||
|
||||
// Mirror connections
|
||||
ui->checkBox_MirrorConnections->setChecked(porymapConfig.mirrorConnectingMaps);
|
||||
|
||||
// Collision opacity/transparency
|
||||
const QSignalBlocker b_CollisionTransparency(ui->horizontalSlider_CollisionTransparency);
|
||||
this->editor->collisionOpacity = static_cast<qreal>(porymapConfig.collisionOpacity) / 100;
|
||||
ui->horizontalSlider_CollisionTransparency->setValue(porymapConfig.collisionOpacity);
|
||||
|
||||
// Dive map opacity/transparency
|
||||
const QSignalBlocker b_DiveEmergeOpacity(ui->slider_DiveEmergeMapOpacity);
|
||||
const QSignalBlocker b_DiveMapOpacity(ui->slider_DiveMapOpacity);
|
||||
const QSignalBlocker b_EmergeMapOpacity(ui->slider_EmergeMapOpacity);
|
||||
ui->slider_DiveEmergeMapOpacity->setValue(porymapConfig.diveEmergeMapOpacity);
|
||||
ui->slider_DiveMapOpacity->setValue(porymapConfig.diveMapOpacity);
|
||||
ui->slider_EmergeMapOpacity->setValue(porymapConfig.emergeMapOpacity);
|
||||
|
||||
// Zoom
|
||||
const QSignalBlocker b_MetatileZoom(ui->horizontalSlider_MetatileZoom);
|
||||
const QSignalBlocker b_CollisionZoom(ui->horizontalSlider_CollisionZoom);
|
||||
ui->horizontalSlider_MetatileZoom->setValue(porymapConfig.metatilesZoom);
|
||||
ui->horizontalSlider_CollisionZoom->setValue(porymapConfig.collisionZoom);
|
||||
|
||||
|
@ -825,7 +837,7 @@ QString MainWindow::getDefaultLayout() {
|
|||
}
|
||||
|
||||
QString MainWindow::getExistingDirectory(QString dir) {
|
||||
return QFileDialog::getExistingDirectory(this, "Open Directory", dir, QFileDialog::ShowDirsOnly);
|
||||
return FileDialog::getExistingDirectory(this, "Open Directory", dir, QFileDialog::ShowDirsOnly);
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Open_Project_triggered()
|
||||
|
@ -2332,6 +2344,18 @@ void MainWindow::on_actionCursor_Tile_Outline_triggered()
|
|||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionShow_Grid_triggered() {
|
||||
this->editor->toggleGrid(ui->actionShow_Grid->isChecked());
|
||||
}
|
||||
|
||||
void MainWindow::on_actionGrid_Settings_triggered() {
|
||||
if (!this->gridSettingsDialog) {
|
||||
this->gridSettingsDialog = new GridSettingsDialog(&this->editor->gridSettings, this);
|
||||
connect(this->gridSettingsDialog, &GridSettingsDialog::changedGridSettings, this->editor, &Editor::updateMapGrid);
|
||||
}
|
||||
openSubWindow(this->gridSettingsDialog);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionShortcuts_triggered()
|
||||
{
|
||||
if (!shortcutsEditor)
|
||||
|
@ -3011,15 +3035,11 @@ void MainWindow::on_actionImport_Map_from_Advance_Map_1_92_triggered(){
|
|||
|
||||
void MainWindow::importMapFromAdvanceMap1_92()
|
||||
{
|
||||
QString filepath = QFileDialog::getOpenFileName(
|
||||
this,
|
||||
QString("Import Map from Advance Map 1.92"),
|
||||
this->editor->project->importExportPath,
|
||||
"Advance Map 1.92 Map Files (*.map)");
|
||||
QString filepath = FileDialog::getOpenFileName(this, "Import Map from Advance Map 1.92", "", "Advance Map 1.92 Map Files (*.map)");
|
||||
if (filepath.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
this->editor->project->setImportExportPath(filepath);
|
||||
|
||||
MapParser parser;
|
||||
bool error = false;
|
||||
Layout *mapLayout = parser.parse(filepath, &error, editor->project);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "tile.h"
|
||||
#include "tileset.h"
|
||||
#include "map.h"
|
||||
#include "filedialog.h"
|
||||
|
||||
#include "orderedjson.h"
|
||||
|
||||
|
@ -89,7 +90,7 @@ void Project::initSignals() {
|
|||
|
||||
void Project::set_root(QString dir) {
|
||||
this->root = dir;
|
||||
this->importExportPath = dir;
|
||||
FileDialog::setDirectory(dir);
|
||||
this->parser.set_root(dir);
|
||||
}
|
||||
|
||||
|
@ -2980,11 +2981,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.
|
||||
|
|
229
src/ui/colorinputwidget.cpp
Normal file
229
src/ui/colorinputwidget.cpp
Normal file
|
@ -0,0 +1,229 @@
|
|||
#include "colorinputwidget.h"
|
||||
#include "ui_colorinputwidget.h"
|
||||
#include "colorpicker.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
class HexCodeValidator : public QValidator {
|
||||
virtual QValidator::State validate(QString &input, int &) const override {
|
||||
input = input.toUpper();
|
||||
return QValidator::Acceptable;
|
||||
}
|
||||
};
|
||||
|
||||
static inline int rgb5(int rgb) { return round(static_cast<double>(rgb * 31) / 255.0); }
|
||||
static inline int rgb8(int rgb) { return round(rgb * 255. / 31.); }
|
||||
static inline int gbaRed(int rgb) { return rgb & 0x1f; }
|
||||
static inline int gbaGreen(int rgb) { return (rgb >> 5) & 0x1f; }
|
||||
static inline int gbaBlue(int rgb) { return (rgb >> 10) & 0x1f; }
|
||||
|
||||
ColorInputWidget::ColorInputWidget(QWidget *parent) :
|
||||
QGroupBox(parent),
|
||||
ui(new Ui::ColorInputWidget)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
ColorInputWidget::ColorInputWidget(const QString &title, QWidget *parent) :
|
||||
QGroupBox(title, parent),
|
||||
ui(new Ui::ColorInputWidget)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
void ColorInputWidget::init() {
|
||||
ui->setupUi(this);
|
||||
|
||||
// Connect color change signals
|
||||
connect(ui->slider_Red, &QSlider::valueChanged, this, &ColorInputWidget::setRgbFromSliders);
|
||||
connect(ui->slider_Green, &QSlider::valueChanged, this, &ColorInputWidget::setRgbFromSliders);
|
||||
connect(ui->slider_Blue, &QSlider::valueChanged, this, &ColorInputWidget::setRgbFromSliders);
|
||||
|
||||
connect(ui->spinBox_Red, QOverload<int>::of(&QSpinBox::valueChanged), this, &ColorInputWidget::setRgbFromSpinners);
|
||||
connect(ui->spinBox_Green, QOverload<int>::of(&QSpinBox::valueChanged), this, &ColorInputWidget::setRgbFromSpinners);
|
||||
connect(ui->spinBox_Blue, QOverload<int>::of(&QSpinBox::valueChanged), this, &ColorInputWidget::setRgbFromSpinners);
|
||||
|
||||
static const HexCodeValidator hexValidator;
|
||||
ui->lineEdit_Hex->setValidator(&hexValidator);
|
||||
connect(ui->lineEdit_Hex, &QLineEdit::textEdited, this, &ColorInputWidget::setRgbFromHexString);
|
||||
|
||||
// We have separate signals for when color input editing finishes.
|
||||
// This is mostly useful for external commit histories, esp. for the sliders which can rapidly emit color change signals.
|
||||
connect(ui->slider_Red, &QSlider::sliderReleased, this, &ColorInputWidget::editingFinished);
|
||||
connect(ui->slider_Green, &QSlider::sliderReleased, this, &ColorInputWidget::editingFinished);
|
||||
connect(ui->slider_Blue, &QSlider::sliderReleased, this, &ColorInputWidget::editingFinished);
|
||||
|
||||
connect(ui->spinBox_Red, &QSpinBox::editingFinished, this, &ColorInputWidget::editingFinished);
|
||||
connect(ui->spinBox_Green, &QSpinBox::editingFinished, this, &ColorInputWidget::editingFinished);
|
||||
connect(ui->spinBox_Blue, &QSpinBox::editingFinished, this, &ColorInputWidget::editingFinished);
|
||||
|
||||
connect(ui->lineEdit_Hex, &QLineEdit::editingFinished, this, &ColorInputWidget::editingFinished);
|
||||
|
||||
// Connect color picker
|
||||
connect(ui->button_Eyedrop, &QToolButton::clicked, this, &ColorInputWidget::pickColor);
|
||||
|
||||
setBitDepth(24);
|
||||
}
|
||||
|
||||
ColorInputWidget::~ColorInputWidget() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ColorInputWidget::updateColorUi() {
|
||||
blockEditSignals(true);
|
||||
|
||||
int red = qRed(m_color);
|
||||
int green = qGreen(m_color);
|
||||
int blue = qBlue(m_color);
|
||||
|
||||
if (m_bitDepth == 15) {
|
||||
// Sliders
|
||||
ui->slider_Red->setValue(rgb5(red));
|
||||
ui->slider_Green->setValue(rgb5(green));
|
||||
ui->slider_Blue->setValue(rgb5(blue));
|
||||
|
||||
// Hex
|
||||
int hex15 = (rgb5(blue) << 10) | (rgb5(green) << 5) | rgb5(red);
|
||||
ui->lineEdit_Hex->setText(QString("%1").arg(hex15, 4, 16, QLatin1Char('0')).toUpper());
|
||||
|
||||
// Spinners
|
||||
ui->spinBox_Red->setValue(rgb5(red));
|
||||
ui->spinBox_Green->setValue(rgb5(green));
|
||||
ui->spinBox_Blue->setValue(rgb5(blue));
|
||||
} else {
|
||||
// Sliders
|
||||
ui->slider_Red->setValue(red);
|
||||
ui->slider_Green->setValue(green);
|
||||
ui->slider_Blue->setValue(blue);
|
||||
|
||||
// Hex
|
||||
QColor color(red, green, blue);
|
||||
ui->lineEdit_Hex->setText(color.name().remove(0, 1).toUpper());
|
||||
|
||||
// Spinners
|
||||
ui->spinBox_Red->setValue(red);
|
||||
ui->spinBox_Green->setValue(green);
|
||||
ui->spinBox_Blue->setValue(blue);
|
||||
}
|
||||
|
||||
ui->frame_ColorDisplay->setStyleSheet(QString("background-color: rgb(%1, %2, %3);").arg(red).arg(green).arg(blue));
|
||||
|
||||
blockEditSignals(false);
|
||||
}
|
||||
|
||||
void ColorInputWidget::blockEditSignals(bool block) {
|
||||
ui->slider_Red->blockSignals(block);
|
||||
ui->slider_Green->blockSignals(block);
|
||||
ui->slider_Blue->blockSignals(block);
|
||||
|
||||
ui->spinBox_Red->blockSignals(block);
|
||||
ui->spinBox_Green->blockSignals(block);
|
||||
ui->spinBox_Blue->blockSignals(block);
|
||||
|
||||
ui->lineEdit_Hex->blockSignals(block);
|
||||
}
|
||||
|
||||
bool ColorInputWidget::setBitDepth(int bits) {
|
||||
if (m_bitDepth == bits)
|
||||
return true;
|
||||
|
||||
int singleStep, pageStep, maximum;
|
||||
QString hexInputMask;
|
||||
if (bits == 15) {
|
||||
singleStep = 1;
|
||||
pageStep = 4;
|
||||
maximum = 31;
|
||||
hexInputMask = "HHHH";
|
||||
} else if (bits == 24) {
|
||||
singleStep = 8;
|
||||
pageStep = 24;
|
||||
maximum = 255;
|
||||
hexInputMask = "HHHHHH";
|
||||
} else {
|
||||
// Unsupported bit depth
|
||||
return false;
|
||||
}
|
||||
m_bitDepth = bits;
|
||||
|
||||
blockEditSignals(true);
|
||||
ui->slider_Red->setSingleStep(singleStep);
|
||||
ui->slider_Green->setSingleStep(singleStep);
|
||||
ui->slider_Blue->setSingleStep(singleStep);
|
||||
ui->slider_Red->setPageStep(pageStep);
|
||||
ui->slider_Green->setPageStep(pageStep);
|
||||
ui->slider_Blue->setPageStep(pageStep);
|
||||
ui->slider_Red->setMaximum(maximum);
|
||||
ui->slider_Green->setMaximum(maximum);
|
||||
ui->slider_Blue->setMaximum(maximum);
|
||||
|
||||
ui->spinBox_Red->setSingleStep(singleStep);
|
||||
ui->spinBox_Green->setSingleStep(singleStep);
|
||||
ui->spinBox_Blue->setSingleStep(singleStep);
|
||||
ui->spinBox_Red->setMaximum(maximum);
|
||||
ui->spinBox_Green->setMaximum(maximum);
|
||||
ui->spinBox_Blue->setMaximum(maximum);
|
||||
|
||||
ui->lineEdit_Hex->setInputMask(hexInputMask);
|
||||
ui->lineEdit_Hex->setMaxLength(hexInputMask.length());
|
||||
|
||||
updateColorUi();
|
||||
blockEditSignals(false);
|
||||
emit bitDepthChanged(m_bitDepth);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ColorInputWidget::setColor(QRgb rgb) {
|
||||
if (m_color == rgb)
|
||||
return;
|
||||
m_color = rgb;
|
||||
updateColorUi();
|
||||
emit colorChanged(m_color);
|
||||
}
|
||||
|
||||
void ColorInputWidget::setRgbFromSliders() {
|
||||
if (m_bitDepth == 15) {
|
||||
setColor(qRgb(rgb8(ui->slider_Red->value()),
|
||||
rgb8(ui->slider_Green->value()),
|
||||
rgb8(ui->slider_Blue->value())));
|
||||
} else {
|
||||
setColor(qRgb(ui->slider_Red->value(),
|
||||
ui->slider_Green->value(),
|
||||
ui->slider_Blue->value()));
|
||||
}
|
||||
}
|
||||
|
||||
void ColorInputWidget::setRgbFromSpinners() {
|
||||
if (m_bitDepth == 15) {
|
||||
setColor(qRgb(rgb8(ui->spinBox_Red->value()), rgb8(ui->spinBox_Green->value()), rgb8(ui->spinBox_Blue->value())));
|
||||
} else {
|
||||
setColor(qRgb(ui->spinBox_Red->value(), ui->spinBox_Green->value(), ui->spinBox_Blue->value()));
|
||||
}
|
||||
}
|
||||
|
||||
void ColorInputWidget::setRgbFromHexString(const QString &text) {
|
||||
if ((m_bitDepth == 24 && text.length() != 6)
|
||||
|| (m_bitDepth == 15 && text.length() != 4))
|
||||
return;
|
||||
|
||||
bool ok = false;
|
||||
int rgb = text.toInt(&ok, 16);
|
||||
if (!ok) rgb = 0xFFFFFFFF;
|
||||
|
||||
if (m_bitDepth == 15) {
|
||||
int rc = gbaRed(rgb);
|
||||
int gc = gbaGreen(rgb);
|
||||
int bc = gbaBlue(rgb);
|
||||
setColor(qRgb(rgb8(rc), rgb8(gc), rgb8(bc)));
|
||||
} else {
|
||||
setColor(qRgb(qRed(rgb), qGreen(rgb), qBlue(rgb)));
|
||||
}
|
||||
}
|
||||
|
||||
void ColorInputWidget::pickColor() {
|
||||
ColorPicker picker(this);
|
||||
if (picker.exec() == QDialog::Accepted) {
|
||||
QColor c = picker.getColor();
|
||||
setColor(c.rgb());
|
||||
emit editingFinished();
|
||||
}
|
||||
}
|
|
@ -4,9 +4,9 @@
|
|||
#include "config.h"
|
||||
#include "editor.h"
|
||||
#include "shortcut.h"
|
||||
#include "filedialog.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFileDialog>
|
||||
|
||||
CustomScriptsEditor::CustomScriptsEditor(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
|
@ -23,8 +23,6 @@ CustomScriptsEditor::CustomScriptsEditor(QWidget *parent) :
|
|||
for (int i = 0; i < paths.length(); i++)
|
||||
this->displayScript(paths.at(i), enabled.at(i));
|
||||
|
||||
this->fileDialogDir = userConfig.projectDir;
|
||||
|
||||
connect(ui->button_CreateNewScript, &QAbstractButton::clicked, this, &CustomScriptsEditor::createNewScript);
|
||||
connect(ui->button_LoadScript, &QAbstractButton::clicked, this, &CustomScriptsEditor::loadScript);
|
||||
connect(ui->button_RefreshScripts, &QAbstractButton::clicked, this, &CustomScriptsEditor::userRefreshScripts);
|
||||
|
@ -147,19 +145,13 @@ bool CustomScriptsEditor::getScriptEnabled(QListWidgetItem * item) const {
|
|||
}
|
||||
|
||||
QString CustomScriptsEditor::chooseScript(QString dir) {
|
||||
return QFileDialog::getOpenFileName(this, "Choose Custom Script File", dir, "JavaScript Files (*.js)");
|
||||
return FileDialog::getOpenFileName(this, "Choose Custom Script File", dir, "JavaScript Files (*.js)");
|
||||
}
|
||||
|
||||
void CustomScriptsEditor::createNewScript() {
|
||||
QString filepath = QFileDialog::getSaveFileName(this, "Create New Script File", this->fileDialogDir + "/new_script.js", "JavaScript Files (*.js)");
|
||||
|
||||
// QFileDialog::getSaveFileName returns focus to the main editor window when closed. Workaround for this below
|
||||
this->raise();
|
||||
this->activateWindow();
|
||||
|
||||
const QString filepath = FileDialog::getSaveFileName(this, "Create New Script File", FileDialog::getDirectory() + "/new_script.js", "JavaScript Files (*.js)");
|
||||
if (filepath.isEmpty())
|
||||
return;
|
||||
this->fileDialogDir = filepath;
|
||||
|
||||
QFile scriptFile(filepath);
|
||||
if (!scriptFile.open(QIODevice::WriteOnly)) {
|
||||
|
@ -179,10 +171,9 @@ void CustomScriptsEditor::createNewScript() {
|
|||
}
|
||||
|
||||
void CustomScriptsEditor::loadScript() {
|
||||
QString filepath = this->chooseScript(this->fileDialogDir);
|
||||
QString filepath = this->chooseScript(FileDialog::getDirectory());
|
||||
if (filepath.isEmpty())
|
||||
return;
|
||||
this->fileDialogDir = filepath;
|
||||
this->displayNewScript(filepath);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,10 +31,24 @@ void MapView::drawForeground(QPainter *painter, const QRectF&) {
|
|||
if (!editor) return;
|
||||
|
||||
QStyleOptionGraphicsItem option;
|
||||
for (QGraphicsLineItem* line : editor->gridLines) {
|
||||
if (line && line->isVisible())
|
||||
line->paint(painter, &option, this);
|
||||
|
||||
// Draw elements of the map view that should always render on top of anything added by the user with the scripting API.
|
||||
|
||||
// Draw map grid
|
||||
if (editor->mapGrid && editor->mapGrid->isVisible()) {
|
||||
painter->save();
|
||||
if (editor->map) {
|
||||
// We're clipping here to hide parts of the grid that are outside the map.
|
||||
const QRectF mapRect(-0.5, -0.5, editor->map->getWidth() * 16 + 1.5, editor->map->getHeight() * 16 + 1.5);
|
||||
painter->setClipping(true);
|
||||
painter->setClipRect(mapRect);
|
||||
}
|
||||
for (auto item : editor->mapGrid->childItems())
|
||||
item->paint(painter, &option, this);
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
// Draw cursor rectangles
|
||||
if (editor->playerViewRect && editor->playerViewRect->isVisible())
|
||||
editor->playerViewRect->paint(painter, &option, this);
|
||||
if (editor->cursorMapTileRect && editor->cursorMapTileRect->isVisible())
|
||||
|
|
230
src/ui/gridsettings.cpp
Normal file
230
src/ui/gridsettings.cpp
Normal file
|
@ -0,0 +1,230 @@
|
|||
#include "ui_gridsettingsdialog.h"
|
||||
#include "gridsettings.h"
|
||||
|
||||
// TODO: Save settings in config
|
||||
|
||||
const QMap<GridSettings::Style, QString> GridSettings::styleToName = {
|
||||
{Style::Solid, "Solid"},
|
||||
{Style::LargeDashes, "Large Dashes"},
|
||||
{Style::SmallDashes, "Small Dashes"},
|
||||
{Style::Crosshairs, "Crosshairs"},
|
||||
{Style::Dots, "Dots"},
|
||||
};
|
||||
|
||||
QString GridSettings::getStyleName(GridSettings::Style style) {
|
||||
return styleToName.value(style);
|
||||
}
|
||||
|
||||
GridSettings::Style GridSettings::getStyleFromName(const QString &name) {
|
||||
return styleToName.key(name, GridSettings::Style::Solid);
|
||||
}
|
||||
|
||||
// We do some extra work here to A: try and center the dashes away from the intersections, and B: keep the dash pattern's total
|
||||
// length equal to the length of a grid square. This keeps the patterns looking reasonable regardless of the grid size.
|
||||
// Otherwise, the dashes can start to intersect in weird ways and create grid patterns that don't look like a rectangular grid.
|
||||
QVector<qreal> GridSettings::getCenteredDashPattern(uint length, qreal dashLength, qreal gapLength) const {
|
||||
const qreal minEdgesLength = 0.6*2;
|
||||
if (length <= dashLength + minEdgesLength)
|
||||
return {dashLength};
|
||||
|
||||
// Every dash after the first one needs to have room for a 'gapLength' segment.
|
||||
const int numDashes = 1 + ((length - minEdgesLength) - dashLength) / (dashLength + gapLength);
|
||||
|
||||
// Total length of the pattern excluding the centering edges. There are always 1 fewer gap segments than dashes.
|
||||
const qreal mainLength = (dashLength * numDashes) + (gapLength * (numDashes-1));
|
||||
|
||||
const qreal edgeLength = (length - mainLength) / 2;
|
||||
|
||||
// Fill the pattern
|
||||
QVector<qreal> pattern = {0, edgeLength};
|
||||
for (int i = 0; i < numDashes-1; i++) {
|
||||
pattern.append(dashLength);
|
||||
pattern.append(gapLength);
|
||||
}
|
||||
pattern.append(dashLength);
|
||||
pattern.append(edgeLength);
|
||||
|
||||
return pattern;
|
||||
}
|
||||
|
||||
QVector<qreal> GridSettings::getDashPattern(uint length) const {
|
||||
switch (this->style) {
|
||||
|
||||
// Equivalent to setting Qt::PenStyle::Solid with no dash pattern.
|
||||
case Style::Solid: return {1, 0};
|
||||
|
||||
// Roughly equivalent to Qt::PenStyle::DashLine but with centering.
|
||||
case Style::LargeDashes: return getCenteredDashPattern(length, 3.0, 2.0);
|
||||
|
||||
// Roughly equivalent to Qt::PenStyle::DotLine but with centering.
|
||||
case Style::SmallDashes: return getCenteredDashPattern(length, 1.0, 2.5);
|
||||
|
||||
// Dashes only at intersections, in the shape of a crosshair.
|
||||
case Style::Crosshairs: {
|
||||
const qreal crosshairLength = 2.0;
|
||||
return {crosshairLength / 2, length - crosshairLength, crosshairLength / 2, 0};
|
||||
}
|
||||
|
||||
// Dots only at intersections.
|
||||
case Style::Dots: {
|
||||
const qreal dotLength = 0.1;
|
||||
return {dotLength, length - dotLength};
|
||||
}
|
||||
|
||||
// Invalid
|
||||
default: return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
GridSettingsDialog::GridSettingsDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::GridSettingsDialog),
|
||||
m_settings(new GridSettings),
|
||||
m_originalSettings(*m_settings)
|
||||
{
|
||||
m_ownedSettings = true;
|
||||
init();
|
||||
}
|
||||
|
||||
GridSettingsDialog::GridSettingsDialog(GridSettings *settings, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::GridSettingsDialog),
|
||||
m_settings(settings),
|
||||
m_originalSettings(*settings)
|
||||
{
|
||||
m_ownedSettings = false;
|
||||
init();
|
||||
}
|
||||
|
||||
void GridSettingsDialog::init() {
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
// Populate the styles combo box
|
||||
const QSignalBlocker b_Style(ui->comboBox_Style);
|
||||
ui->comboBox_Style->addItem(GridSettings::getStyleName(GridSettings::Style::Solid));
|
||||
ui->comboBox_Style->addItem(GridSettings::getStyleName(GridSettings::Style::LargeDashes));
|
||||
ui->comboBox_Style->addItem(GridSettings::getStyleName(GridSettings::Style::SmallDashes));
|
||||
ui->comboBox_Style->addItem(GridSettings::getStyleName(GridSettings::Style::Crosshairs));
|
||||
ui->comboBox_Style->addItem(GridSettings::getStyleName(GridSettings::Style::Dots));
|
||||
|
||||
ui->button_LinkDimensions->setChecked(m_dimensionsLinked);
|
||||
ui->button_LinkOffsets->setChecked(m_offsetsLinked);
|
||||
|
||||
connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &GridSettingsDialog::dialogButtonClicked);
|
||||
connect(ui->button_LinkDimensions, &QAbstractButton::toggled, [this](bool on) { m_dimensionsLinked = on; });
|
||||
connect(ui->button_LinkOffsets, &QAbstractButton::toggled, [this](bool on) { m_offsetsLinked = on; });
|
||||
connect(ui->colorInput, &ColorInputWidget::colorChanged, this, &GridSettingsDialog::onColorChanged);
|
||||
|
||||
updateInput();
|
||||
}
|
||||
|
||||
GridSettingsDialog::~GridSettingsDialog() {
|
||||
delete ui;
|
||||
if (m_ownedSettings)
|
||||
delete m_settings;
|
||||
}
|
||||
|
||||
void GridSettingsDialog::setSettings(const GridSettings &settings) {
|
||||
if (*m_settings == settings)
|
||||
return;
|
||||
*m_settings = settings;
|
||||
updateInput();
|
||||
emit changedGridSettings();
|
||||
}
|
||||
|
||||
void GridSettingsDialog::updateInput() {
|
||||
setWidth(m_settings->width);
|
||||
setHeight(m_settings->height);
|
||||
setOffsetX(m_settings->offsetX);
|
||||
setOffsetY(m_settings->offsetY);
|
||||
|
||||
const QSignalBlocker b_Color(ui->colorInput);
|
||||
ui->colorInput->setColor(m_settings->color.rgb());
|
||||
|
||||
const QSignalBlocker b_Style(ui->comboBox_Style);
|
||||
ui->comboBox_Style->setCurrentText(GridSettings::getStyleName(m_settings->style));
|
||||
}
|
||||
|
||||
void GridSettingsDialog::setWidth(int value) {
|
||||
const QSignalBlocker b(ui->spinBox_Width);
|
||||
ui->spinBox_Width->setValue(value);
|
||||
m_settings->width = value;
|
||||
}
|
||||
|
||||
void GridSettingsDialog::setHeight(int value) {
|
||||
const QSignalBlocker b(ui->spinBox_Height);
|
||||
ui->spinBox_Height->setValue(value);
|
||||
m_settings->height = value;
|
||||
}
|
||||
|
||||
void GridSettingsDialog::setOffsetX(int value) {
|
||||
const QSignalBlocker b(ui->spinBox_X);
|
||||
ui->spinBox_X->setValue(value);
|
||||
m_settings->offsetX = value;
|
||||
}
|
||||
|
||||
void GridSettingsDialog::setOffsetY(int value) {
|
||||
const QSignalBlocker b(ui->spinBox_Y);
|
||||
ui->spinBox_Y->setValue(value);
|
||||
m_settings->offsetY = value;
|
||||
}
|
||||
|
||||
void GridSettingsDialog::on_spinBox_Width_valueChanged(int value) {
|
||||
setWidth(value);
|
||||
if (m_dimensionsLinked)
|
||||
setHeight(value);
|
||||
|
||||
emit changedGridSettings();
|
||||
}
|
||||
|
||||
void GridSettingsDialog::on_spinBox_Height_valueChanged(int value) {
|
||||
setHeight(value);
|
||||
if (m_dimensionsLinked)
|
||||
setWidth(value);
|
||||
|
||||
emit changedGridSettings();
|
||||
}
|
||||
|
||||
void GridSettingsDialog::on_spinBox_X_valueChanged(int value) {
|
||||
setOffsetX(value);
|
||||
if (m_offsetsLinked)
|
||||
setOffsetY(value);
|
||||
|
||||
emit changedGridSettings();
|
||||
}
|
||||
|
||||
void GridSettingsDialog::on_spinBox_Y_valueChanged(int value) {
|
||||
setOffsetY(value);
|
||||
if (m_offsetsLinked)
|
||||
setOffsetX(value);
|
||||
|
||||
emit changedGridSettings();
|
||||
}
|
||||
|
||||
void GridSettingsDialog::on_comboBox_Style_currentTextChanged(const QString &text) {
|
||||
m_settings->style = GridSettings::getStyleFromName(text);
|
||||
emit changedGridSettings();
|
||||
}
|
||||
|
||||
void GridSettingsDialog::onColorChanged(QRgb color) {
|
||||
m_settings->color = QColor::fromRgb(color);
|
||||
emit changedGridSettings();
|
||||
}
|
||||
|
||||
void GridSettingsDialog::dialogButtonClicked(QAbstractButton *button) {
|
||||
auto role = ui->buttonBox->buttonRole(button);
|
||||
if (role == QDialogButtonBox::AcceptRole) {
|
||||
// "OK"
|
||||
close();
|
||||
} else if (role == QDialogButtonBox::RejectRole) {
|
||||
// "Cancel"
|
||||
setSettings(m_originalSettings);
|
||||
close();
|
||||
} else if (role == QDialogButtonBox::ResetRole) {
|
||||
// "Restore Defaults"
|
||||
setSettings(m_defaultSettings);
|
||||
}
|
||||
}
|
|
@ -2,8 +2,8 @@
|
|||
#include "ui_mapimageexporter.h"
|
||||
#include "qgifimage.h"
|
||||
#include "editcommands.h"
|
||||
#include "filedialog.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QImage>
|
||||
#include <QPainter>
|
||||
#include <QPoint>
|
||||
|
@ -23,6 +23,19 @@ QString getTitle(ImageExporterMode mode) {
|
|||
return "";
|
||||
}
|
||||
|
||||
QString getDescription(ImageExporterMode mode) {
|
||||
switch (mode)
|
||||
{
|
||||
case ImageExporterMode::Normal:
|
||||
return "Exports an image of the selected map.";
|
||||
case ImageExporterMode::Stitch:
|
||||
return "Exports a combined image of all the maps connected to the selected map.";
|
||||
case ImageExporterMode::Timelapse:
|
||||
return "Exports a GIF of the edit history for the selected map.";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
MapImageExporter::MapImageExporter(QWidget *parent_, Editor *editor_, ImageExporterMode mode) :
|
||||
QDialog(parent_),
|
||||
ui(new Ui::MapImageExporter)
|
||||
|
@ -34,6 +47,7 @@ MapImageExporter::MapImageExporter(QWidget *parent_, Editor *editor_, ImageExpor
|
|||
this->editor = editor_;
|
||||
this->mode = mode;
|
||||
this->setWindowTitle(getTitle(this->mode));
|
||||
this->ui->label_Description->setText(getDescription(this->mode));
|
||||
this->ui->groupBox_Connections->setVisible(this->mode != ImageExporterMode::Stitch);
|
||||
this->ui->groupBox_Timelapse->setVisible(this->mode == ImageExporterMode::Timelapse);
|
||||
|
||||
|
@ -43,7 +57,8 @@ MapImageExporter::MapImageExporter(QWidget *parent_, Editor *editor_, ImageExpor
|
|||
this->ui->comboBox_MapSelection->setEnabled(false);// TODO: allow selecting map from drop-down
|
||||
}
|
||||
|
||||
updatePreview();
|
||||
connect(ui->pushButton_Save, &QPushButton::pressed, this, &MapImageExporter::saveImage);
|
||||
connect(ui->pushButton_Cancel, &QPushButton::pressed, this, &MapImageExporter::close);
|
||||
}
|
||||
|
||||
MapImageExporter::~MapImageExporter() {
|
||||
|
@ -51,7 +66,25 @@ MapImageExporter::~MapImageExporter() {
|
|||
delete ui;
|
||||
}
|
||||
|
||||
// Allow the window to open before displaying the preview.
|
||||
void MapImageExporter::showEvent(QShowEvent *event) {
|
||||
QWidget::showEvent(event);
|
||||
if (!event->spontaneous())
|
||||
QTimer::singleShot(0, this, &MapImageExporter::updatePreview);
|
||||
}
|
||||
|
||||
void MapImageExporter::resizeEvent(QResizeEvent *event) {
|
||||
QDialog::resizeEvent(event);
|
||||
scalePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::saveImage() {
|
||||
// Make sure preview is up-to-date before we save.
|
||||
if (this->preview.isNull())
|
||||
updatePreview();
|
||||
if (this->preview.isNull())
|
||||
return;
|
||||
|
||||
QString title = getTitle(this->mode);
|
||||
QString defaultFilename;
|
||||
switch (this->mode)
|
||||
|
@ -68,40 +101,27 @@ void MapImageExporter::saveImage() {
|
|||
}
|
||||
|
||||
QString defaultFilepath = QString("%1/%2.%3")
|
||||
.arg(editor->project->importExportPath)
|
||||
.arg(FileDialog::getDirectory())
|
||||
.arg(defaultFilename)
|
||||
.arg(this->mode == ImageExporterMode::Timelapse ? "gif" : "png");
|
||||
QString filter = this->mode == ImageExporterMode::Timelapse ? "Image Files (*.gif)" : "Image Files (*.png *.jpg *.bmp)";
|
||||
QString filepath = QFileDialog::getSaveFileName(this, title, defaultFilepath, filter);
|
||||
QString filepath = FileDialog::getSaveFileName(this, title, defaultFilepath, filter);
|
||||
if (!filepath.isEmpty()) {
|
||||
editor->project->setImportExportPath(filepath);
|
||||
switch (this->mode) {
|
||||
case ImageExporterMode::Normal:
|
||||
case ImageExporterMode::Stitch:
|
||||
// Normal and Stitch modes already have the image ready to go in the preview.
|
||||
this->preview.save(filepath);
|
||||
break;
|
||||
case ImageExporterMode::Stitch: {
|
||||
QProgressDialog progress("Building map stitch...", "Cancel", 0, 1, this);
|
||||
progress.setAutoClose(true);
|
||||
progress.setWindowModality(Qt::WindowModal);
|
||||
progress.setModal(true);
|
||||
QPixmap pixmap = this->getStitchedImage(&progress, this->showBorder);
|
||||
if (progress.wasCanceled()) {
|
||||
progress.close();
|
||||
return;
|
||||
}
|
||||
pixmap.save(filepath);
|
||||
progress.close();
|
||||
break;
|
||||
}
|
||||
case ImageExporterMode::Timelapse:
|
||||
// Timelapse will play in order of layout changes then map changes (events)
|
||||
// TODO: potentially update in the future?
|
||||
QGifImage timelapseImg;
|
||||
timelapseImg.setDefaultDelay(timelapseDelayMs);
|
||||
timelapseImg.setDefaultDelay(this->settings.timelapseDelayMs);
|
||||
timelapseImg.setDefaultTransparentColor(QColor(0, 0, 0));
|
||||
|
||||
// lambda to avoid redundancy
|
||||
auto generateTimelapseFromHistory = [=, this, &timelapseImg](QString progressText, QUndoStack &historyStack){
|
||||
auto generateTimelapseFromHistory = [this, &timelapseImg](QString progressText, QUndoStack &historyStack){
|
||||
QProgressDialog progress(progressText, "Cancel", 0, 1, this);
|
||||
progress.setAutoClose(true);
|
||||
progress.setWindowModality(Qt::WindowModal);
|
||||
|
@ -111,7 +131,7 @@ void MapImageExporter::saveImage() {
|
|||
|
||||
int maxWidth = this->layout->getWidth() * 16;
|
||||
int maxHeight = this->layout->getHeight() * 16;
|
||||
if (showBorder) {
|
||||
if (this->settings.showBorder) {
|
||||
maxWidth += 2 * STITCH_MODE_BORDER_DISTANCE * 16;
|
||||
maxHeight += 2 * STITCH_MODE_BORDER_DISTANCE * 16;
|
||||
}
|
||||
|
@ -122,7 +142,7 @@ void MapImageExporter::saveImage() {
|
|||
historyStack.undo();
|
||||
int width = this->layout->getWidth() * 16;
|
||||
int height = this->layout->getHeight() * 16;
|
||||
if (showBorder) {
|
||||
if (this->settings.showBorder) {
|
||||
width += 2 * STITCH_MODE_BORDER_DISTANCE * 16;
|
||||
height += 2 * STITCH_MODE_BORDER_DISTANCE * 16;
|
||||
}
|
||||
|
@ -153,7 +173,7 @@ void MapImageExporter::saveImage() {
|
|||
historyStack.redo();
|
||||
}
|
||||
progress.setValue(progress.maximum() - i);
|
||||
QPixmap pixmap = this->getFormattedMapPixmap(this->map, !this->showBorder);
|
||||
QPixmap pixmap = this->getFormattedMapPixmap(this->map);
|
||||
if (pixmap.width() < maxWidth || pixmap.height() < maxHeight) {
|
||||
QPixmap pixmap2 = QPixmap(maxWidth, maxHeight);
|
||||
QPainter painter(&pixmap2);
|
||||
|
@ -163,7 +183,7 @@ void MapImageExporter::saveImage() {
|
|||
pixmap = pixmap2;
|
||||
}
|
||||
timelapseImg.addFrame(pixmap.toImage());
|
||||
for (int j = 0; j < timelapseSkipAmount; j++) {
|
||||
for (int j = 0; j < this->settings.timelapseSkipAmount; j++) {
|
||||
if (i > 0) {
|
||||
i--;
|
||||
historyStack.redo();
|
||||
|
@ -209,26 +229,26 @@ bool MapImageExporter::historyItemAppliesToFrame(const QUndoCommand *command) {
|
|||
case CommandId::ID_PaintCollision:
|
||||
case CommandId::ID_BucketFillCollision:
|
||||
case CommandId::ID_MagicFillCollision:
|
||||
return this->showCollision;
|
||||
return this->settings.showCollision;
|
||||
case CommandId::ID_PaintBorder:
|
||||
return this->showBorder;
|
||||
return this->settings.showBorder;
|
||||
case CommandId::ID_MapConnectionMove:
|
||||
case CommandId::ID_MapConnectionChangeDirection:
|
||||
case CommandId::ID_MapConnectionChangeMap:
|
||||
case CommandId::ID_MapConnectionAdd:
|
||||
case CommandId::ID_MapConnectionRemove:
|
||||
return this->showUpConnections || this->showDownConnections || this->showLeftConnections || this->showRightConnections;
|
||||
return this->settings.showUpConnections || this->settings.showDownConnections || this->settings.showLeftConnections || this->settings.showRightConnections;
|
||||
case CommandId::ID_EventMove:
|
||||
case CommandId::ID_EventShift:
|
||||
case CommandId::ID_EventCreate:
|
||||
case CommandId::ID_EventDelete:
|
||||
case CommandId::ID_EventDuplicate: {
|
||||
bool eventTypeIsApplicable =
|
||||
(this->showObjects && (command->id() & IDMask_EventType_Object) != 0)
|
||||
|| (this->showWarps && (command->id() & IDMask_EventType_Warp) != 0)
|
||||
|| (this->showBGs && (command->id() & IDMask_EventType_BG) != 0)
|
||||
|| (this->showTriggers && (command->id() & IDMask_EventType_Trigger) != 0)
|
||||
|| (this->showHealSpots && (command->id() & IDMask_EventType_Heal) != 0);
|
||||
(this->settings.showObjects && (command->id() & IDMask_EventType_Object) != 0)
|
||||
|| (this->settings.showWarps && (command->id() & IDMask_EventType_Warp) != 0)
|
||||
|| (this->settings.showBGs && (command->id() & IDMask_EventType_BG) != 0)
|
||||
|| (this->settings.showTriggers && (command->id() & IDMask_EventType_Trigger) != 0)
|
||||
|| (this->settings.showHealLocations && (command->id() & IDMask_EventType_Heal) != 0);
|
||||
return eventTypeIsApplicable;
|
||||
}
|
||||
default:
|
||||
|
@ -371,19 +391,33 @@ QPixmap MapImageExporter::getStitchedImage(QProgressDialog *progress, bool inclu
|
|||
}
|
||||
|
||||
void MapImageExporter::updatePreview() {
|
||||
if (scene) {
|
||||
delete scene;
|
||||
scene = nullptr;
|
||||
if (this->scene) {
|
||||
delete this->scene;
|
||||
this->scene = nullptr;
|
||||
}
|
||||
this->scene = new QGraphicsScene;
|
||||
|
||||
preview = getFormattedMapPixmap(this->map);
|
||||
scene = new QGraphicsScene;
|
||||
scene->addPixmap(preview);
|
||||
this->scene->setSceneRect(this->scene->itemsBoundingRect());
|
||||
if (this->mode == ImageExporterMode::Stitch) {
|
||||
QProgressDialog progress("Building map stitch...", "Cancel", 0, 1, this);
|
||||
progress.setAutoClose(true);
|
||||
progress.setWindowModality(Qt::WindowModal);
|
||||
progress.setModal(true);
|
||||
progress.setMinimumDuration(1000);
|
||||
this->preview = getStitchedImage(&progress, this->settings.showBorder);
|
||||
progress.close();
|
||||
} else {
|
||||
// Timelapse mode doesn't currently have a real preview. It just displays the current map as in Normal mode.
|
||||
this->preview = getFormattedMapPixmap(this->map);
|
||||
}
|
||||
this->scene->addPixmap(this->preview);
|
||||
ui->graphicsView_Preview->setScene(scene);
|
||||
scalePreview();
|
||||
}
|
||||
|
||||
this->ui->graphicsView_Preview->setScene(scene);
|
||||
this->ui->graphicsView_Preview->setFixedSize(scene->itemsBoundingRect().width() + 2,
|
||||
scene->itemsBoundingRect().height() + 2);
|
||||
void MapImageExporter::scalePreview() {
|
||||
if (this->scene && !this->settings.previewActualSize){
|
||||
ui->graphicsView_Preview->fitInView(this->scene->sceneRect(), Qt::KeepAspectRatioByExpanding);
|
||||
}
|
||||
}
|
||||
|
||||
// THIS
|
||||
|
@ -403,7 +437,7 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) {
|
|||
pixmap = map->layout->pixmap;
|
||||
}
|
||||
|
||||
if (showCollision) {
|
||||
if (this->settings.showCollision) {
|
||||
QPainter collisionPainter(&pixmap);
|
||||
layout->renderCollision(true);
|
||||
collisionPainter.setOpacity(editor->collisionOpacity);
|
||||
|
@ -414,7 +448,7 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) {
|
|||
// draw map border
|
||||
// note: this will break when allowing map to be selected from drop down maybe
|
||||
int borderHeight = 0, borderWidth = 0;
|
||||
if (!ignoreBorder && this->showBorder) {
|
||||
if (!ignoreBorder && this->settings.showBorder) {
|
||||
int borderDistance = this->mode ? STITCH_MODE_BORDER_DISTANCE : BORDER_DISTANCE;
|
||||
layout->renderBorder();
|
||||
int borderHorzDist = editor->getBorderDrawDistance(layout->getBorderWidth());
|
||||
|
@ -437,15 +471,16 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) {
|
|||
return pixmap;
|
||||
}
|
||||
|
||||
if (!ignoreBorder && (this->showUpConnections || this->showDownConnections || this->showLeftConnections || this->showRightConnections)) {
|
||||
if (!ignoreBorder && (this->settings.showUpConnections || this->settings.showDownConnections || this->settings.showLeftConnections || this->settings.showRightConnections)) {
|
||||
// if showing connections, draw on outside of image
|
||||
QPainter connectionPainter(&pixmap);
|
||||
// TODO: Reading the connections from the editor and not 'map' is incorrect.
|
||||
for (auto connectionItem : editor->connection_items) {
|
||||
const QString direction = connectionItem->connection->direction();
|
||||
if ((showUpConnections && direction == "up")
|
||||
|| (showDownConnections && direction == "down")
|
||||
|| (showLeftConnections && direction == "left")
|
||||
|| (showRightConnections && direction == "right"))
|
||||
if ((this->settings.showUpConnections && direction == "up")
|
||||
|| (this->settings.showDownConnections && direction == "down")
|
||||
|| (this->settings.showLeftConnections && direction == "left")
|
||||
|| (this->settings.showRightConnections && direction == "right"))
|
||||
connectionPainter.drawImage(connectionItem->x() + borderWidth, connectionItem->y() + borderHeight,
|
||||
connectionItem->connection->getPixmap().toImage());
|
||||
}
|
||||
|
@ -453,27 +488,30 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) {
|
|||
}
|
||||
|
||||
// draw events
|
||||
QPainter eventPainter(&pixmap);
|
||||
QList<Event *> events = map->getAllEvents();
|
||||
int pixelOffset = 0;
|
||||
if (!ignoreBorder && this->showBorder) {
|
||||
pixelOffset = this->mode == ImageExporterMode::Normal ? BORDER_DISTANCE * 16 : STITCH_MODE_BORDER_DISTANCE * 16;
|
||||
if (this->settings.showObjects || this->settings.showWarps || this->settings.showBGs || this->settings.showTriggers || this->settings.showHealLocations) {
|
||||
QPainter eventPainter(&pixmap);
|
||||
int pixelOffset = 0;
|
||||
if (!ignoreBorder && this->settings.showBorder) {
|
||||
pixelOffset = this->mode == ImageExporterMode::Normal ? BORDER_DISTANCE * 16 : STITCH_MODE_BORDER_DISTANCE * 16;
|
||||
}
|
||||
const QList<Event *> events = map->getAllEvents();
|
||||
for (const auto &event : events) {
|
||||
Event::Group group = event->getEventGroup();
|
||||
if ((this->settings.showObjects && group == Event::Group::Object)
|
||||
|| (this->settings.showWarps && group == Event::Group::Warp)
|
||||
|| (this->settings.showBGs && group == Event::Group::Bg)
|
||||
|| (this->settings.showTriggers && group == Event::Group::Coord)
|
||||
|| (this->settings.showHealLocations && group == Event::Group::Heal)) {
|
||||
editor->project->setEventPixmap(event);
|
||||
eventPainter.drawImage(QPoint(event->getPixelX() + pixelOffset, event->getPixelY() + pixelOffset), event->getPixmap().toImage());
|
||||
}
|
||||
}
|
||||
eventPainter.end();
|
||||
}
|
||||
for (Event *event : events) {
|
||||
editor->project->setEventPixmap(event);
|
||||
Event::Group group = event->getEventGroup();
|
||||
if ((showObjects && group == Event::Group::Object)
|
||||
|| (showWarps && group == Event::Group::Warp)
|
||||
|| (showBGs && group == Event::Group::Bg)
|
||||
|| (showTriggers && group == Event::Group::Coord)
|
||||
|| (showHealSpots && group == Event::Group::Heal))
|
||||
eventPainter.drawImage(QPoint(event->getPixelX() + pixelOffset, event->getPixelY() + pixelOffset), event->getPixmap().toImage());
|
||||
}
|
||||
eventPainter.end();
|
||||
|
||||
// draw grid directly onto the pixmap
|
||||
// since the last grid lines are outside of the pixmap, add a pixel to the bottom and right
|
||||
if (showGrid) {
|
||||
if (this->settings.showGrid) {
|
||||
int addX = 1, addY = 1;
|
||||
if (borderHeight) addY = 0;
|
||||
if (borderWidth) addX = 0;
|
||||
|
@ -496,97 +534,161 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) {
|
|||
|
||||
void MapImageExporter::updateShowBorderState() {
|
||||
// If any of the Connections settings are enabled then this setting is locked (it's implicitly enabled)
|
||||
bool on = (this->settings.showUpConnections || this->settings.showDownConnections || this->settings.showLeftConnections || this->settings.showRightConnections);
|
||||
const QSignalBlocker blocker(ui->checkBox_Border);
|
||||
if (showUpConnections || showDownConnections || showLeftConnections || showRightConnections) {
|
||||
ui->checkBox_Border->setChecked(true);
|
||||
ui->checkBox_Border->setDisabled(true);
|
||||
showBorder = true;
|
||||
} else {
|
||||
ui->checkBox_Border->setDisabled(false);
|
||||
}
|
||||
ui->checkBox_Border->setChecked(on);
|
||||
ui->checkBox_Border->setDisabled(on);
|
||||
this->settings.showBorder = on;
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_Elevation_stateChanged(int state) {
|
||||
showCollision = (state == Qt::Checked);
|
||||
this->settings.showCollision = (state == Qt::Checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_Grid_stateChanged(int state) {
|
||||
showGrid = (state == Qt::Checked);
|
||||
this->settings.showGrid = (state == Qt::Checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_Border_stateChanged(int state) {
|
||||
showBorder = (state == Qt::Checked);
|
||||
this->settings.showBorder = (state == Qt::Checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_Objects_stateChanged(int state) {
|
||||
showObjects = (state == Qt::Checked);
|
||||
this->settings.showObjects = (state == Qt::Checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_Warps_stateChanged(int state) {
|
||||
showWarps = (state == Qt::Checked);
|
||||
this->settings.showWarps = (state == Qt::Checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_BGs_stateChanged(int state) {
|
||||
showBGs = (state == Qt::Checked);
|
||||
this->settings.showBGs = (state == Qt::Checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_Triggers_stateChanged(int state) {
|
||||
showTriggers = (state == Qt::Checked);
|
||||
this->settings.showTriggers = (state == Qt::Checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_HealSpots_stateChanged(int state) {
|
||||
showHealSpots = (state == Qt::Checked);
|
||||
void MapImageExporter::on_checkBox_HealLocations_stateChanged(int state) {
|
||||
this->settings.showHealLocations = (state == Qt::Checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
// Shortcut setting for enabling all events
|
||||
void MapImageExporter::on_checkBox_AllEvents_stateChanged(int state) {
|
||||
bool on = (state == Qt::Checked);
|
||||
|
||||
const QSignalBlocker b_Objects(ui->checkBox_Objects);
|
||||
ui->checkBox_Objects->setChecked(on);
|
||||
ui->checkBox_Objects->setDisabled(on);
|
||||
this->settings.showObjects = on;
|
||||
|
||||
const QSignalBlocker b_Warps(ui->checkBox_Warps);
|
||||
ui->checkBox_Warps->setChecked(on);
|
||||
ui->checkBox_Warps->setDisabled(on);
|
||||
this->settings.showWarps = on;
|
||||
|
||||
const QSignalBlocker b_BGs(ui->checkBox_BGs);
|
||||
ui->checkBox_BGs->setChecked(on);
|
||||
ui->checkBox_BGs->setDisabled(on);
|
||||
this->settings.showBGs = on;
|
||||
|
||||
const QSignalBlocker b_Triggers(ui->checkBox_Triggers);
|
||||
ui->checkBox_Triggers->setChecked(on);
|
||||
ui->checkBox_Triggers->setDisabled(on);
|
||||
this->settings.showTriggers = on;
|
||||
|
||||
const QSignalBlocker b_HealLocations(ui->checkBox_HealLocations);
|
||||
ui->checkBox_HealLocations->setChecked(on);
|
||||
ui->checkBox_HealLocations->setDisabled(on);
|
||||
this->settings.showHealLocations = on;
|
||||
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_ConnectionUp_stateChanged(int state) {
|
||||
showUpConnections = (state == Qt::Checked);
|
||||
this->settings.showUpConnections = (state == Qt::Checked);
|
||||
updateShowBorderState();
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_ConnectionDown_stateChanged(int state) {
|
||||
showDownConnections = (state == Qt::Checked);
|
||||
this->settings.showDownConnections = (state == Qt::Checked);
|
||||
updateShowBorderState();
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_ConnectionLeft_stateChanged(int state) {
|
||||
showLeftConnections = (state == Qt::Checked);
|
||||
this->settings.showLeftConnections = (state == Qt::Checked);
|
||||
updateShowBorderState();
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_ConnectionRight_stateChanged(int state) {
|
||||
showRightConnections = (state == Qt::Checked);
|
||||
this->settings.showRightConnections = (state == Qt::Checked);
|
||||
updateShowBorderState();
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_pushButton_Save_pressed() {
|
||||
saveImage();
|
||||
// Shortcut setting for enabling all connection directions
|
||||
void MapImageExporter::on_checkBox_AllConnections_stateChanged(int state) {
|
||||
bool on = (state == Qt::Checked);
|
||||
|
||||
const QSignalBlocker b_Up(ui->checkBox_ConnectionUp);
|
||||
ui->checkBox_ConnectionUp->setChecked(on);
|
||||
ui->checkBox_ConnectionUp->setDisabled(on);
|
||||
this->settings.showUpConnections = on;
|
||||
|
||||
const QSignalBlocker b_Down(ui->checkBox_ConnectionDown);
|
||||
ui->checkBox_ConnectionDown->setChecked(on);
|
||||
ui->checkBox_ConnectionDown->setDisabled(on);
|
||||
this->settings.showDownConnections = on;
|
||||
|
||||
const QSignalBlocker b_Left(ui->checkBox_ConnectionLeft);
|
||||
ui->checkBox_ConnectionLeft->setChecked(on);
|
||||
ui->checkBox_ConnectionLeft->setDisabled(on);
|
||||
this->settings.showLeftConnections = on;
|
||||
|
||||
const QSignalBlocker b_Right(ui->checkBox_ConnectionRight);
|
||||
ui->checkBox_ConnectionRight->setChecked(on);
|
||||
ui->checkBox_ConnectionRight->setDisabled(on);
|
||||
this->settings.showRightConnections = on;
|
||||
|
||||
updateShowBorderState();
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_ActualSize_stateChanged(int state) {
|
||||
this->settings.previewActualSize = (state == Qt::Checked);
|
||||
if (this->settings.previewActualSize) {
|
||||
ui->graphicsView_Preview->resetTransform();
|
||||
} else {
|
||||
scalePreview();
|
||||
}
|
||||
}
|
||||
|
||||
void MapImageExporter::on_pushButton_Reset_pressed() {
|
||||
for (auto widget : this->findChildren<QCheckBox *>())
|
||||
this->settings = {};
|
||||
for (auto widget : this->findChildren<QCheckBox *>()) {
|
||||
const QSignalBlocker b(widget); // Prevent calls to updatePreview
|
||||
widget->setChecked(false);
|
||||
}
|
||||
|
||||
void MapImageExporter::on_pushButton_Cancel_pressed() {
|
||||
this->close();
|
||||
}
|
||||
ui->spinBox_TimelapseDelay->setValue(this->settings.timelapseDelayMs);
|
||||
ui->spinBox_FrameSkip->setValue(this->settings.timelapseSkipAmount);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_spinBox_TimelapseDelay_valueChanged(int delayMs) {
|
||||
timelapseDelayMs = delayMs;
|
||||
this->settings.timelapseDelayMs = delayMs;
|
||||
}
|
||||
|
||||
void MapImageExporter::on_spinBox_FrameSkip_valueChanged(int skip) {
|
||||
timelapseSkipAmount = skip;
|
||||
this->settings.timelapseSkipAmount = skip;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include "newtilesetdialog.h"
|
||||
#include "ui_newtilesetdialog.h"
|
||||
#include <QFileDialog>
|
||||
#include "project.h"
|
||||
|
||||
NewTilesetDialog::NewTilesetDialog(Project* project, QWidget *parent) :
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <QCompleter>
|
||||
#include <QLineEdit>
|
||||
#include <QWheelEvent>
|
||||
|
||||
NoScrollComboBox::NoScrollComboBox(QWidget *parent)
|
||||
: QComboBox(parent)
|
||||
|
@ -39,8 +40,11 @@ void NoScrollComboBox::wheelEvent(QWheelEvent *event)
|
|||
{
|
||||
// By default NoScrollComboBoxes will allow scrolling to modify its contents only when it explicitly has focus.
|
||||
// If focusedScrollingEnabled is false it won't allow scrolling even with focus.
|
||||
if (this->focusedScrollingEnabled && hasFocus())
|
||||
if (this->focusedScrollingEnabled && hasFocus()) {
|
||||
QComboBox::wheelEvent(event);
|
||||
} else {
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
void NoScrollComboBox::setFocusedScrollingEnabled(bool enabled)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "noscrollspinbox.h"
|
||||
#include <QWheelEvent>
|
||||
|
||||
unsigned actionId = 0xffff;
|
||||
|
||||
|
@ -12,8 +13,11 @@ NoScrollSpinBox::NoScrollSpinBox(QWidget *parent)
|
|||
void NoScrollSpinBox::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
// Only allow scrolling to modify contents when it explicitly has focus.
|
||||
if (hasFocus())
|
||||
if (hasFocus()) {
|
||||
QSpinBox::wheelEvent(event);
|
||||
} else {
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
void NoScrollSpinBox::focusOutEvent(QFocusEvent *event) {
|
||||
|
|
|
@ -1,19 +1,12 @@
|
|||
#include "paletteeditor.h"
|
||||
#include "ui_paletteeditor.h"
|
||||
#include "colorpicker.h"
|
||||
#include "paletteutil.h"
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "filedialog.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
static inline int rgb5(int rgb) { return round(static_cast<double>(rgb * 31) / 255.0); }
|
||||
static inline int rgb8(int rgb) { return round(rgb * 255. / 31.); }
|
||||
static inline int gbaRed(int rgb) { return rgb & 0x1f; }
|
||||
static inline int gbaGreen(int rgb) { return (rgb >> 5) & 0x1f; }
|
||||
static inline int gbaBlue(int rgb) { return (rgb >> 10) & 0x1f; }
|
||||
|
||||
PaletteEditor::PaletteEditor(Project *project, Tileset *primaryTileset, Tileset *secondaryTileset, int paletteId, QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
|
@ -26,55 +19,14 @@ PaletteEditor::PaletteEditor(Project *project, Tileset *primaryTileset, Tileset
|
|||
this->ui->spinBox_PaletteId->setMinimum(0);
|
||||
this->ui->spinBox_PaletteId->setMaximum(Project::getNumPalettesTotal() - 1);
|
||||
|
||||
this->sliders.clear();
|
||||
for (int i = 0; i < 16; i++) {
|
||||
QList<QSlider *> rgbSliders;
|
||||
rgbSliders.append(this->ui->container->findChild<QSlider *>("slider_red_" + QString::number(i)));
|
||||
rgbSliders.append(this->ui->container->findChild<QSlider *>("slider_green_" + QString::number(i)));
|
||||
rgbSliders.append(this->ui->container->findChild<QSlider *>("slider_blue_" + QString::number(i)));
|
||||
this->sliders.append(rgbSliders);
|
||||
|
||||
connect(this->sliders[i][0], &QSlider::valueChanged, [=](int) { setRgbFromSliders(i); });
|
||||
connect(this->sliders[i][1], &QSlider::valueChanged, [=](int) { setRgbFromSliders(i); });
|
||||
connect(this->sliders[i][2], &QSlider::valueChanged, [=](int) { setRgbFromSliders(i); });
|
||||
}
|
||||
|
||||
this->spinners.clear();
|
||||
for (int i = 0; i < 16; i++) {
|
||||
QList<QSpinBox *> rgbSpinners;
|
||||
rgbSpinners.append(this->ui->container->findChild<QSpinBox *>("spin_red_" + QString::number(i)));
|
||||
rgbSpinners.append(this->ui->container->findChild<QSpinBox *>("spin_green_" + QString::number(i)));
|
||||
rgbSpinners.append(this->ui->container->findChild<QSpinBox *>("spin_blue_" + QString::number(i)));
|
||||
this->spinners.append(rgbSpinners);
|
||||
|
||||
connect(this->spinners[i][0], QOverload<int>::of(&QSpinBox::valueChanged), [=](int) { setRgbFromSpinners(i); });
|
||||
connect(this->spinners[i][1], QOverload<int>::of(&QSpinBox::valueChanged), [=](int) { setRgbFromSpinners(i); });
|
||||
connect(this->spinners[i][2], QOverload<int>::of(&QSpinBox::valueChanged), [=](int) { setRgbFromSpinners(i); });
|
||||
}
|
||||
|
||||
this->frames.clear();
|
||||
for (int i = 0; i < 16; i++) {
|
||||
this->frames.append(this->ui->container->findChild<QFrame *>("colorFrame_" + QString::number(i)));
|
||||
this->frames[i]->setFrameStyle(QFrame::NoFrame);
|
||||
}
|
||||
|
||||
this->pickButtons.clear();
|
||||
for (int i = 0; i < 16; i++) {
|
||||
this->pickButtons.append(this->ui->container->findChild<QToolButton *>("pick_" + QString::number(i)));
|
||||
}
|
||||
|
||||
this->hexValidator = new HexCodeValidator;
|
||||
this->hexEdits.clear();
|
||||
for (int i = 0; i < 16; i++) {
|
||||
this->hexEdits.append(this->ui->container->findChild<QLineEdit *>("hex_" + QString::number(i)));
|
||||
this->hexEdits[i]->setValidator(hexValidator);
|
||||
}
|
||||
|
||||
// Connect to function that will update color when hex edit is changed
|
||||
for (int i = 0; i < this->hexEdits.length(); i++) {
|
||||
connect(this->hexEdits[i], &QLineEdit::textEdited, [this, i](QString text){
|
||||
if ((this->bitDepth == 24 && text.length() == 6) || (this->bitDepth == 15 && text.length() == 4)) setRgbFromHexEdit(i);
|
||||
});
|
||||
this->colorInputs.clear();
|
||||
const int numColorsPerRow = 4;
|
||||
for (int i = 0; i < this->numColors; i++) {
|
||||
auto colorInput = new ColorInputWidget(QString("Color %1").arg(i));
|
||||
connect(colorInput, &ColorInputWidget::colorChanged, [this, i](QRgb color) { setRgb(i, color); });
|
||||
connect(colorInput, &ColorInputWidget::editingFinished, [this] { commitEditHistory(); });
|
||||
this->colorInputs.append(colorInput);
|
||||
ui->layout_Colors->addWidget(colorInput, i / numColorsPerRow, i % numColorsPerRow);
|
||||
}
|
||||
|
||||
// Setup edit-undo history for each of the palettes.
|
||||
|
@ -82,11 +34,6 @@ PaletteEditor::PaletteEditor(Project *project, Tileset *primaryTileset, Tileset
|
|||
this->palettesHistory.append(History<PaletteHistoryItem*>());
|
||||
}
|
||||
|
||||
// Connect the color picker's selection to the correct color index
|
||||
for (int i = 0; i < 16; i++) {
|
||||
connect(this->pickButtons[i], &QToolButton::clicked, [this, i](){ this->pickColor(i); });
|
||||
}
|
||||
|
||||
int bitDepth = porymapConfig.paletteEditorBitDepth;
|
||||
if (bitDepth == 15) {
|
||||
this->ui->bit_depth_15->setChecked(true);
|
||||
|
@ -100,246 +47,87 @@ PaletteEditor::PaletteEditor(Project *project, Tileset *primaryTileset, Tileset
|
|||
connect(this->ui->bit_depth_24, &QRadioButton::toggled, [this](bool checked){ if (checked) this->setBitDepth(24); });
|
||||
|
||||
this->setPaletteId(paletteId);
|
||||
this->commitEditHistory(this->ui->spinBox_PaletteId->value());
|
||||
this->commitEditHistory();
|
||||
this->restoreWindowState();
|
||||
}
|
||||
|
||||
PaletteEditor::~PaletteEditor()
|
||||
{
|
||||
delete ui;
|
||||
delete this->hexValidator;
|
||||
}
|
||||
|
||||
void PaletteEditor::updateColorUi(int colorIndex, QRgb rgb) {
|
||||
setSignalsEnabled(false);
|
||||
|
||||
int red = qRed(rgb);
|
||||
int green = qGreen(rgb);
|
||||
int blue = qBlue(rgb);
|
||||
|
||||
if (this->bitDepth == 15) {
|
||||
// sliders
|
||||
this->sliders[colorIndex][0]->setValue(rgb5(red));
|
||||
this->sliders[colorIndex][1]->setValue(rgb5(green));
|
||||
this->sliders[colorIndex][2]->setValue(rgb5(blue));
|
||||
|
||||
// hex
|
||||
int hex15 = (rgb5(blue) << 10) | (rgb5(green) << 5) | rgb5(red);
|
||||
QString hexcode = QString("%1").arg(hex15, 4, 16, QLatin1Char('0')).toUpper();
|
||||
this->hexEdits[colorIndex]->setText(hexcode);
|
||||
|
||||
// spinners
|
||||
this->spinners[colorIndex][0]->setValue(rgb5(red));
|
||||
this->spinners[colorIndex][1]->setValue(rgb5(green));
|
||||
this->spinners[colorIndex][2]->setValue(rgb5(blue));
|
||||
} else {
|
||||
// sliders
|
||||
this->sliders[colorIndex][0]->setValue(red);
|
||||
this->sliders[colorIndex][1]->setValue(green);
|
||||
this->sliders[colorIndex][2]->setValue(blue);
|
||||
|
||||
// hex
|
||||
QColor color(red, green, blue);
|
||||
QString hexcode = color.name().remove(0, 1).toUpper();
|
||||
this->hexEdits[colorIndex]->setText(hexcode);
|
||||
|
||||
// spinners
|
||||
this->spinners[colorIndex][0]->setValue(red);
|
||||
this->spinners[colorIndex][1]->setValue(green);
|
||||
this->spinners[colorIndex][2]->setValue(blue);
|
||||
}
|
||||
|
||||
// frame
|
||||
QString stylesheet = QString("background-color: rgb(%1, %2, %3);").arg(red).arg(green).arg(blue);
|
||||
this->frames[colorIndex]->setStyleSheet(stylesheet);
|
||||
|
||||
setSignalsEnabled(true);
|
||||
}
|
||||
|
||||
void PaletteEditor::setSignalsEnabled(bool enabled) {
|
||||
// spinners, sliders, hexbox
|
||||
for (int i = 0; i < this->sliders.length(); i++) {
|
||||
this->sliders.at(i).at(0)->blockSignals(!enabled);
|
||||
this->sliders.at(i).at(1)->blockSignals(!enabled);
|
||||
this->sliders.at(i).at(2)->blockSignals(!enabled);
|
||||
}
|
||||
|
||||
for (int i = 0; i < this->spinners.length(); i++) {
|
||||
this->spinners.at(i).at(0)->blockSignals(!enabled);
|
||||
this->spinners.at(i).at(1)->blockSignals(!enabled);
|
||||
this->spinners.at(i).at(2)->blockSignals(!enabled);
|
||||
}
|
||||
|
||||
for (int i = 0; i < this->hexEdits.length(); i++) {
|
||||
this->hexEdits.at(i)->blockSignals(!enabled);
|
||||
}
|
||||
Tileset* PaletteEditor::getTileset(int paletteId) {
|
||||
return (paletteId < Project::getNumPalettesPrimary())
|
||||
? this->primaryTileset
|
||||
: this->secondaryTileset;
|
||||
}
|
||||
|
||||
void PaletteEditor::setBitDepth(int bits) {
|
||||
setSignalsEnabled(false);
|
||||
switch (bits) {
|
||||
case 15:
|
||||
for (int i = 0; i < 16; i++) {
|
||||
// sliders ranged [0, 31] with 1 single step and 4 page step
|
||||
this->sliders[i][0]->setSingleStep(1);
|
||||
this->sliders[i][1]->setSingleStep(1);
|
||||
this->sliders[i][2]->setSingleStep(1);
|
||||
this->sliders[i][0]->setPageStep(4);
|
||||
this->sliders[i][1]->setPageStep(4);
|
||||
this->sliders[i][2]->setPageStep(4);
|
||||
this->sliders[i][0]->setMaximum(31);
|
||||
this->sliders[i][1]->setMaximum(31);
|
||||
this->sliders[i][2]->setMaximum(31);
|
||||
|
||||
// spinners limited [0, 31] with 1 step
|
||||
this->spinners[i][0]->setSingleStep(1);
|
||||
this->spinners[i][1]->setSingleStep(1);
|
||||
this->spinners[i][2]->setSingleStep(1);
|
||||
this->spinners[i][0]->setMaximum(31);
|
||||
this->spinners[i][1]->setMaximum(31);
|
||||
this->spinners[i][2]->setMaximum(31);
|
||||
|
||||
// hex box now 4 digits
|
||||
this->hexEdits[i]->setInputMask("HHHH");
|
||||
this->hexEdits[i]->setMaxLength(4);
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
default:
|
||||
for (int i = 0; i < 16; i++) {
|
||||
// sliders ranged [0, 31] with 1 single step and 4 page step
|
||||
this->sliders[i][0]->setSingleStep(8);
|
||||
this->sliders[i][1]->setSingleStep(8);
|
||||
this->sliders[i][2]->setSingleStep(8);
|
||||
this->sliders[i][0]->setPageStep(24);
|
||||
this->sliders[i][1]->setPageStep(24);
|
||||
this->sliders[i][2]->setPageStep(24);
|
||||
this->sliders[i][0]->setMaximum(255);
|
||||
this->sliders[i][1]->setMaximum(255);
|
||||
this->sliders[i][2]->setMaximum(255);
|
||||
|
||||
// spinners limited [0, 31] with 1 step
|
||||
this->spinners[i][0]->setSingleStep(8);
|
||||
this->spinners[i][1]->setSingleStep(8);
|
||||
this->spinners[i][2]->setSingleStep(8);
|
||||
this->spinners[i][0]->setMaximum(255);
|
||||
this->spinners[i][1]->setMaximum(255);
|
||||
this->spinners[i][2]->setMaximum(255);
|
||||
|
||||
// hex box now 4 digits
|
||||
this->hexEdits[i]->setInputMask("HHHHHH");
|
||||
this->hexEdits[i]->setMaxLength(6);
|
||||
}
|
||||
break;
|
||||
}
|
||||
this->bitDepth = bits;
|
||||
porymapConfig.paletteEditorBitDepth = bits;
|
||||
refreshColorUis();
|
||||
setSignalsEnabled(true);
|
||||
for (const auto &colorInput : this->colorInputs) {
|
||||
colorInput->setBitDepth(bits);
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteEditor::setRgb(int colorIndex, QRgb rgb) {
|
||||
int paletteNum = this->ui->spinBox_PaletteId->value();
|
||||
const int paletteId = this->ui->spinBox_PaletteId->value();
|
||||
|
||||
Tileset *tileset = paletteNum < Project::getNumPalettesPrimary()
|
||||
? this->primaryTileset
|
||||
: this->secondaryTileset;
|
||||
tileset->palettes[paletteNum][colorIndex] = rgb;
|
||||
tileset->palettePreviews[paletteNum][colorIndex] = rgb;
|
||||
Tileset *tileset = getTileset(paletteId);
|
||||
tileset->palettes[paletteId][colorIndex] = rgb;
|
||||
tileset->palettePreviews[paletteId][colorIndex] = rgb;
|
||||
|
||||
this->updateColorUi(colorIndex, rgb);
|
||||
|
||||
this->commitEditHistory(paletteNum);
|
||||
emit this->changedPaletteColor();
|
||||
emit changedPaletteColor();
|
||||
}
|
||||
|
||||
void PaletteEditor::setRgbFromSliders(int colorIndex) {
|
||||
if (this->bitDepth == 15) {
|
||||
setRgb(colorIndex, qRgb(rgb8(this->sliders[colorIndex][0]->value()),
|
||||
rgb8(this->sliders[colorIndex][1]->value()),
|
||||
rgb8(this->sliders[colorIndex][2]->value())));
|
||||
} else {
|
||||
setRgb(colorIndex, qRgb(this->sliders[colorIndex][0]->value(),
|
||||
this->sliders[colorIndex][1]->value(),
|
||||
this->sliders[colorIndex][2]->value()));
|
||||
void PaletteEditor::setPalette(int paletteId, const QList<QRgb> &palette) {
|
||||
Tileset *tileset = getTileset(paletteId);
|
||||
for (int i = 0; i < this->numColors; i++) {
|
||||
tileset->palettes[paletteId][i] = palette.at(i);
|
||||
tileset->palettePreviews[paletteId][i] = palette.at(i);
|
||||
}
|
||||
refreshColorInputs();
|
||||
emit changedPaletteColor();
|
||||
}
|
||||
|
||||
void PaletteEditor::setRgbFromHexEdit(int colorIndex) {
|
||||
QString text = this->hexEdits[colorIndex]->text();
|
||||
bool ok = false;
|
||||
int rgb = text.toInt(&ok, 16);
|
||||
if (!ok) rgb = 0xFFFFFFFF;
|
||||
if (this->bitDepth == 15) {
|
||||
int rc = gbaRed(rgb);
|
||||
int gc = gbaGreen(rgb);
|
||||
int bc = gbaBlue(rgb);
|
||||
setRgb(colorIndex, qRgb(rgb8(rc), rgb8(gc), rgb8(bc)));
|
||||
} else {
|
||||
setRgb(colorIndex, qRgb(qRed(rgb), qGreen(rgb), qBlue(rgb)));
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteEditor::setRgbFromSpinners(int colorIndex) {
|
||||
if (this->bitDepth == 15) {
|
||||
setRgb(colorIndex, qRgb(rgb8(this->spinners[colorIndex][0]->value()),
|
||||
rgb8(this->spinners[colorIndex][1]->value()),
|
||||
rgb8(this->spinners[colorIndex][2]->value())));
|
||||
} else {
|
||||
setRgb(colorIndex, qRgb(this->spinners[colorIndex][0]->value(),
|
||||
this->spinners[colorIndex][1]->value(),
|
||||
this->spinners[colorIndex][2]->value()));
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteEditor::refreshColorUis() {
|
||||
int paletteNum = this->ui->spinBox_PaletteId->value();
|
||||
for (int i = 0; i < 16; i++) {
|
||||
QRgb color;
|
||||
if (paletteNum < Project::getNumPalettesPrimary()) {
|
||||
color = this->primaryTileset->palettes.at(paletteNum).at(i);
|
||||
} else {
|
||||
color = this->secondaryTileset->palettes.at(paletteNum).at(i);
|
||||
}
|
||||
|
||||
this->updateColorUi(i, color);
|
||||
void PaletteEditor::refreshColorInputs() {
|
||||
const int paletteId = ui->spinBox_PaletteId->value();
|
||||
Tileset *tileset = getTileset(paletteId);
|
||||
for (int i = 0; i < this->numColors; i++) {
|
||||
auto colorInput = this->colorInputs.at(i);
|
||||
const QSignalBlocker b(colorInput);
|
||||
colorInput->setColor(tileset->palettes.at(paletteId).at(i));
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteEditor::setPaletteId(int paletteId) {
|
||||
this->ui->spinBox_PaletteId->blockSignals(true);
|
||||
const QSignalBlocker b(ui->spinBox_PaletteId);
|
||||
this->ui->spinBox_PaletteId->setValue(paletteId);
|
||||
this->refreshColorUis();
|
||||
this->ui->spinBox_PaletteId->blockSignals(false);
|
||||
this->refreshColorInputs();
|
||||
}
|
||||
|
||||
void PaletteEditor::setTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
this->primaryTileset = primaryTileset;
|
||||
this->secondaryTileset = secondaryTileset;
|
||||
this->refreshColorUis();
|
||||
}
|
||||
|
||||
void PaletteEditor::pickColor(int index) {
|
||||
ColorPicker picker(this);
|
||||
if (picker.exec() == QDialog::Accepted) {
|
||||
QColor c = picker.getColor();
|
||||
this->setRgb(index, c.rgb());
|
||||
}
|
||||
return;
|
||||
this->refreshColorInputs();
|
||||
}
|
||||
|
||||
void PaletteEditor::on_spinBox_PaletteId_valueChanged(int paletteId) {
|
||||
this->refreshColorUis();
|
||||
this->refreshColorInputs();
|
||||
if (!this->palettesHistory[paletteId].current()) {
|
||||
this->commitEditHistory(paletteId);
|
||||
}
|
||||
emit this->changedPalette(paletteId);
|
||||
}
|
||||
|
||||
void PaletteEditor::commitEditHistory() {
|
||||
commitEditHistory(ui->spinBox_PaletteId->value());
|
||||
}
|
||||
|
||||
void PaletteEditor::commitEditHistory(int paletteId) {
|
||||
QList<QRgb> colors;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
colors.append(qRgb(this->spinners[i][0]->value(), this->spinners[i][1]->value(), this->spinners[i][2]->value()));
|
||||
for (int i = 0; i < this->numColors; i++) {
|
||||
colors.append(this->colorInputs.at(i)->color());
|
||||
}
|
||||
PaletteHistoryItem *commit = new PaletteHistoryItem(colors);
|
||||
this->palettesHistory[paletteId].push(commit);
|
||||
|
@ -356,44 +144,24 @@ void PaletteEditor::on_actionUndo_triggered()
|
|||
{
|
||||
int paletteId = this->ui->spinBox_PaletteId->value();
|
||||
PaletteHistoryItem *prev = this->palettesHistory[paletteId].back();
|
||||
this->setColorsFromHistory(prev, paletteId);
|
||||
if (prev)
|
||||
setPalette(paletteId, prev->colors);
|
||||
}
|
||||
|
||||
void PaletteEditor::on_actionRedo_triggered()
|
||||
{
|
||||
int paletteId = this->ui->spinBox_PaletteId->value();
|
||||
PaletteHistoryItem *next = this->palettesHistory[paletteId].next();
|
||||
this->setColorsFromHistory(next, paletteId);
|
||||
}
|
||||
|
||||
void PaletteEditor::setColorsFromHistory(PaletteHistoryItem *history, int paletteId) {
|
||||
if (!history) return;
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (paletteId < Project::getNumPalettesPrimary()) {
|
||||
this->primaryTileset->palettes[paletteId][i] = history->colors.at(i);
|
||||
this->primaryTileset->palettePreviews[paletteId][i] = history->colors.at(i);
|
||||
} else {
|
||||
this->secondaryTileset->palettes[paletteId][i] = history->colors.at(i);
|
||||
this->secondaryTileset->palettePreviews[paletteId][i] = history->colors.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
this->refreshColorUis();
|
||||
emit this->changedPaletteColor();
|
||||
if (next)
|
||||
setPalette(paletteId, next->colors);
|
||||
}
|
||||
|
||||
void PaletteEditor::on_actionImport_Palette_triggered()
|
||||
{
|
||||
QString filepath = QFileDialog::getOpenFileName(
|
||||
this,
|
||||
QString("Import Tileset Palette"),
|
||||
this->project->importExportPath,
|
||||
"Palette Files (*.pal *.act *tpl *gpl)");
|
||||
QString filepath = FileDialog::getOpenFileName(this, "Import Tileset Palette", "", "Palette Files (*.pal *.act *tpl *gpl)");
|
||||
if (filepath.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
this->project->setImportExportPath(filepath);
|
||||
bool error = false;
|
||||
QList<QRgb> palette = PaletteUtil::parse(filepath, &error);
|
||||
if (error) {
|
||||
|
@ -407,10 +175,12 @@ void PaletteEditor::on_actionImport_Palette_triggered()
|
|||
return;
|
||||
}
|
||||
|
||||
if (palette.length() < 16) {
|
||||
if (palette.length() < this->numColors) {
|
||||
QMessageBox msgBox(this);
|
||||
msgBox.setText("Failed to import palette.");
|
||||
QString message = QString("The palette file has %1 colors, but it must have 16 colors.").arg(palette.length());
|
||||
QString message = QString("The palette file has %1 colors, but it must have %2 colors.")
|
||||
.arg(palette.length())
|
||||
.arg(this->numColors);
|
||||
msgBox.setInformativeText(message);
|
||||
msgBox.setDefaultButton(QMessageBox::Ok);
|
||||
msgBox.setIcon(QMessageBox::Icon::Critical);
|
||||
|
@ -418,20 +188,9 @@ void PaletteEditor::on_actionImport_Palette_triggered()
|
|||
return;
|
||||
}
|
||||
|
||||
int paletteId = this->ui->spinBox_PaletteId->value();
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (paletteId < Project::getNumPalettesPrimary()) {
|
||||
this->primaryTileset->palettes[paletteId][i] = palette.at(i);
|
||||
this->primaryTileset->palettePreviews[paletteId][i] = palette.at(i);
|
||||
} else {
|
||||
this->secondaryTileset->palettes[paletteId][i] = palette.at(i);
|
||||
this->secondaryTileset->palettePreviews[paletteId][i] = palette.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
this->refreshColorUis();
|
||||
this->commitEditHistory(paletteId);
|
||||
emit this->changedPaletteColor();
|
||||
const int paletteId = ui->spinBox_PaletteId->value();
|
||||
setPalette(paletteId, palette);
|
||||
commitEditHistory(paletteId);
|
||||
}
|
||||
|
||||
void PaletteEditor::closeEvent(QCloseEvent*) {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "config.h"
|
||||
#include "noscrollcombobox.h"
|
||||
#include "prefab.h"
|
||||
#include "filedialog.h"
|
||||
|
||||
#include <QAbstractButton>
|
||||
#include <QFormLayout>
|
||||
|
@ -383,10 +384,10 @@ QString ProjectSettingsEditor::chooseProjectFile(const QString &defaultFilepath)
|
|||
QString path;
|
||||
if (defaultFilepath.endsWith("/")){
|
||||
// Default filepath is a folder, choose a new folder
|
||||
path = QFileDialog::getExistingDirectory(this, "Choose Project File Folder", startDir) + QDir::separator();
|
||||
path = FileDialog::getExistingDirectory(this, "Choose Project File Folder", startDir) + QDir::separator();
|
||||
} else{
|
||||
// Default filepath is not a folder, choose a new file
|
||||
path = QFileDialog::getOpenFileName(this, "Choose Project File", startDir);
|
||||
path = FileDialog::getOpenFileName(this, "Choose Project File", startDir);
|
||||
}
|
||||
|
||||
if (!path.startsWith(this->baseDir)){
|
||||
|
@ -573,10 +574,9 @@ void ProjectSettingsEditor::chooseImageFile(QLineEdit * filepathEdit) {
|
|||
}
|
||||
|
||||
void ProjectSettingsEditor::chooseFile(QLineEdit * filepathEdit, const QString &description, const QString &extensions) {
|
||||
QString filepath = QFileDialog::getOpenFileName(this, description, this->project->importExportPath, extensions);
|
||||
QString filepath = FileDialog::getOpenFileName(this, description, "", extensions);
|
||||
if (filepath.isEmpty())
|
||||
return;
|
||||
this->project->setImportExportPath(filepath);
|
||||
|
||||
if (filepathEdit)
|
||||
filepathEdit->setText(this->stripProjectDir(filepath));
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include <QDir>
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QFileDialog>
|
||||
#include <QFormLayout>
|
||||
#include <QLineEdit>
|
||||
#include <QSpinBox>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "project.h"
|
||||
#include "regionmappropertiesdialog.h"
|
||||
#include "ui_regionmappropertiesdialog.h"
|
||||
#include "filedialog.h"
|
||||
|
||||
RegionMapPropertiesDialog::RegionMapPropertiesDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
|
@ -30,13 +31,9 @@ void RegionMapPropertiesDialog::hideMessages() {
|
|||
this->adjustSize();
|
||||
}
|
||||
|
||||
QString RegionMapPropertiesDialog::browse(QString filter, QFileDialog::FileMode mode) {
|
||||
QString RegionMapPropertiesDialog::browse(QString filter) {
|
||||
if (!this->project) return QString();
|
||||
QFileDialog browser;
|
||||
browser.setFileMode(mode);
|
||||
QString filepath = browser.getOpenFileName(this, "Select a File", this->project->importExportPath, filter);
|
||||
if (!filepath.isEmpty())
|
||||
this->project->setImportExportPath(filepath);
|
||||
QString filepath = FileDialog::getOpenFileName(this, "Select a File", "", filter);
|
||||
|
||||
// remove the project root from the filepath
|
||||
return filepath.replace(this->project->root + "/", "");
|
||||
|
@ -107,21 +104,21 @@ poryjson::Json RegionMapPropertiesDialog::saveToJson() {
|
|||
}
|
||||
|
||||
void RegionMapPropertiesDialog::on_browse_tilesetImagePath_clicked() {
|
||||
QString path = browse("Images (*.png *.bmp)", QFileDialog::ExistingFile);
|
||||
QString path = browse("Images (*.png *.bmp)");
|
||||
if (!path.isEmpty()) {
|
||||
ui->config_tilemapImagePath->setText(path);
|
||||
}
|
||||
}
|
||||
|
||||
void RegionMapPropertiesDialog::on_browse_tilemapBinPath_clicked() {
|
||||
QString path = browse("Binary (*.bin *.tilemap *.4bpp *.8bpp)", QFileDialog::AnyFile);
|
||||
QString path = browse("Binary (*.bin *.tilemap *.4bpp *.8bpp)");
|
||||
if (!path.isEmpty()) {
|
||||
ui->config_tilemapBinPath->setText(path);
|
||||
}
|
||||
}
|
||||
|
||||
void RegionMapPropertiesDialog::on_browse_tilemapPalettePath_clicked() {
|
||||
QString path = browse("Text (*.pal)", QFileDialog::AnyFile);
|
||||
QString path = browse("Text (*.pal)");
|
||||
if (!path.isEmpty()) {
|
||||
ui->config_tilemapPalettePath->setText(path);
|
||||
}
|
||||
|
@ -129,12 +126,12 @@ void RegionMapPropertiesDialog::on_browse_tilemapPalettePath_clicked() {
|
|||
|
||||
void RegionMapPropertiesDialog::on_browse_layoutPath_clicked() {
|
||||
if (ui->config_layoutFormat->currentIndex() == 0) {
|
||||
QString path = browse("Text File (*.h *.c *.inc *.txt)", QFileDialog::AnyFile);
|
||||
QString path = browse("Text File (*.h *.c *.inc *.txt)");
|
||||
if (!path.isEmpty()) {
|
||||
ui->config_layoutPath->setText(path);
|
||||
}
|
||||
} else {
|
||||
QString path = browse("Binary (*.bin)", QFileDialog::AnyFile);
|
||||
QString path = browse("Binary (*.bin)");
|
||||
if (!path.isEmpty()) {
|
||||
ui->config_layoutPath->setText(path);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "imageexport.h"
|
||||
#include "config.h"
|
||||
#include "shortcut.h"
|
||||
#include <QFileDialog>
|
||||
#include "filedialog.h"
|
||||
#include <QMessageBox>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QCloseEvent>
|
||||
|
@ -637,15 +637,11 @@ void TilesetEditor::importTilesetTiles(Tileset *tileset, bool primary) {
|
|||
QString descriptor = primary ? "primary" : "secondary";
|
||||
QString descriptorCaps = primary ? "Primary" : "Secondary";
|
||||
|
||||
QString filepath = QFileDialog::getOpenFileName(
|
||||
this,
|
||||
QString("Import %1 Tileset Tiles Image").arg(descriptorCaps),
|
||||
this->project->importExportPath,
|
||||
"Image Files (*.png *.bmp *.jpg *.dib)");
|
||||
QString filepath = FileDialog::getOpenFileName(this, QString("Import %1 Tileset Tiles Image").arg(descriptorCaps), "", "Image Files (*.png *.bmp *.jpg *.dib)");
|
||||
if (filepath.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
this->project->setImportExportPath(filepath);
|
||||
|
||||
logInfo(QString("Importing %1 tileset tiles '%2'").arg(descriptor).arg(filepath));
|
||||
|
||||
// Read image data from buffer so that the built-in QImage doesn't try to detect file format
|
||||
|
@ -698,15 +694,11 @@ void TilesetEditor::importTilesetTiles(Tileset *tileset, bool primary) {
|
|||
msgBox.setIcon(QMessageBox::Icon::Warning);
|
||||
msgBox.exec();
|
||||
|
||||
QString filepath = QFileDialog::getOpenFileName(
|
||||
this,
|
||||
QString("Select Palette for Tiles Image").arg(descriptorCaps),
|
||||
this->project->importExportPath,
|
||||
"Palette Files (*.pal *.act *tpl *gpl)");
|
||||
QString filepath = FileDialog::getOpenFileName(this, "Select Palette for Tiles Image", "", "Palette Files (*.pal *.act *tpl *gpl)");
|
||||
if (filepath.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
this->project->setImportExportPath(filepath);
|
||||
|
||||
bool error = false;
|
||||
QList<QRgb> palette = PaletteUtil::parse(filepath, &error);
|
||||
if (error) {
|
||||
|
@ -939,10 +931,9 @@ void TilesetEditor::pasteMetatile(const Metatile * toPaste, QString newLabel)
|
|||
void TilesetEditor::on_actionExport_Primary_Tiles_Image_triggered()
|
||||
{
|
||||
QString defaultName = QString("%1_Tiles_Pal%2").arg(this->primaryTileset->name).arg(this->paletteId);
|
||||
QString defaultFilepath = QString("%1/%2.png").arg(this->project->importExportPath).arg(defaultName);
|
||||
QString filepath = QFileDialog::getSaveFileName(this, "Export Primary Tiles Image", defaultFilepath, "Image Files (*.png)");
|
||||
QString defaultFilepath = QString("%1/%2.png").arg(FileDialog::getDirectory()).arg(defaultName);
|
||||
QString filepath = FileDialog::getSaveFileName(this, "Export Primary Tiles Image", defaultFilepath, "Image Files (*.png)");
|
||||
if (!filepath.isEmpty()) {
|
||||
this->project->setImportExportPath(filepath);
|
||||
QImage image = this->tileSelector->buildPrimaryTilesIndexedImage();
|
||||
exportIndexed4BPPPng(image, filepath);
|
||||
}
|
||||
|
@ -951,10 +942,9 @@ void TilesetEditor::on_actionExport_Primary_Tiles_Image_triggered()
|
|||
void TilesetEditor::on_actionExport_Secondary_Tiles_Image_triggered()
|
||||
{
|
||||
QString defaultName = QString("%1_Tiles_Pal%2").arg(this->secondaryTileset->name).arg(this->paletteId);
|
||||
QString defaultFilepath = QString("%1/%2.png").arg(this->project->importExportPath).arg(defaultName);
|
||||
QString filepath = QFileDialog::getSaveFileName(this, "Export Secondary Tiles Image", defaultFilepath, "Image Files (*.png)");
|
||||
QString defaultFilepath = QString("%1/%2.png").arg(FileDialog::getDirectory()).arg(defaultName);
|
||||
QString filepath = FileDialog::getSaveFileName(this, "Export Secondary Tiles Image", defaultFilepath, "Image Files (*.png)");
|
||||
if (!filepath.isEmpty()) {
|
||||
this->project->setImportExportPath(filepath);
|
||||
QImage image = this->tileSelector->buildSecondaryTilesIndexedImage();
|
||||
exportIndexed4BPPPng(image, filepath);
|
||||
}
|
||||
|
@ -963,10 +953,9 @@ void TilesetEditor::on_actionExport_Secondary_Tiles_Image_triggered()
|
|||
void TilesetEditor::on_actionExport_Primary_Metatiles_Image_triggered()
|
||||
{
|
||||
QString defaultName = QString("%1_Metatiles").arg(this->primaryTileset->name);
|
||||
QString defaultFilepath = QString("%1/%2.png").arg(this->project->importExportPath).arg(defaultName);
|
||||
QString filepath = QFileDialog::getSaveFileName(this, "Export Primary Metatiles Image", defaultFilepath, "Image Files (*.png)");
|
||||
QString defaultFilepath = QString("%1/%2.png").arg(FileDialog::getDirectory()).arg(defaultName);
|
||||
QString filepath = FileDialog::getSaveFileName(this, "Export Primary Metatiles Image", defaultFilepath, "Image Files (*.png)");
|
||||
if (!filepath.isEmpty()) {
|
||||
this->project->setImportExportPath(filepath);
|
||||
QImage image = this->metatileSelector->buildPrimaryMetatilesImage();
|
||||
image.save(filepath, "PNG");
|
||||
}
|
||||
|
@ -975,10 +964,9 @@ void TilesetEditor::on_actionExport_Primary_Metatiles_Image_triggered()
|
|||
void TilesetEditor::on_actionExport_Secondary_Metatiles_Image_triggered()
|
||||
{
|
||||
QString defaultName = QString("%1_Metatiles").arg(this->secondaryTileset->name);
|
||||
QString defaultFilepath = QString("%1/%2.png").arg(this->project->importExportPath).arg(defaultName);
|
||||
QString filepath = QFileDialog::getSaveFileName(this, "Export Secondary Metatiles Image", defaultFilepath, "Image Files (*.png)");
|
||||
QString defaultFilepath = QString("%1/%2.png").arg(FileDialog::getDirectory()).arg(defaultName);
|
||||
QString filepath = FileDialog::getSaveFileName(this, "Export Secondary Metatiles Image", defaultFilepath, "Image Files (*.png)");
|
||||
if (!filepath.isEmpty()) {
|
||||
this->project->setImportExportPath(filepath);
|
||||
QImage image = this->metatileSelector->buildSecondaryMetatilesImage();
|
||||
image.save(filepath, "PNG");
|
||||
}
|
||||
|
@ -998,15 +986,11 @@ void TilesetEditor::importTilesetMetatiles(Tileset *tileset, bool primary)
|
|||
{
|
||||
QString descriptorCaps = primary ? "Primary" : "Secondary";
|
||||
|
||||
QString filepath = QFileDialog::getOpenFileName(
|
||||
this,
|
||||
QString("Import %1 Tileset Metatiles from Advance Map 1.92").arg(descriptorCaps),
|
||||
this->project->importExportPath,
|
||||
"Advance Map 1.92 Metatile Files (*.bvd)");
|
||||
QString filepath = FileDialog::getOpenFileName(this, QString("Import %1 Tileset Metatiles from Advance Map 1.92").arg(descriptorCaps), "", "Advance Map 1.92 Metatile Files (*.bvd)");
|
||||
if (filepath.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
this->project->setImportExportPath(filepath);
|
||||
|
||||
bool error = false;
|
||||
QList<Metatile*> metatiles = MetatileParser::parse(filepath, &error, primary);
|
||||
if (error) {
|
||||
|
|
|
@ -31,6 +31,8 @@ WildMonChart::WildMonChart(QWidget *parent, const EncounterTableModel *table) :
|
|||
connect(ui->comboBox_Species, &QComboBox::currentTextChanged, this, &WildMonChart::refreshLevelDistributionChart);
|
||||
connect(ui->comboBox_Group, &QComboBox::currentTextChanged, this, &WildMonChart::refreshLevelDistributionChart);
|
||||
|
||||
connect(ui->tabWidget, &QTabWidget::currentChanged, this, &WildMonChart::limitChartAnimation);
|
||||
|
||||
// Set up Theme combo box
|
||||
for (auto i : themes)
|
||||
ui->comboBox_Theme->addItem(i.first, i.second);
|
||||
|
@ -176,14 +178,16 @@ void WildMonChart::refreshSpeciesDistributionChart() {
|
|||
if (ui->chartView_SpeciesDistribution->chart())
|
||||
ui->chartView_SpeciesDistribution->chart()->deleteLater();
|
||||
ui->chartView_SpeciesDistribution->setChart(createSpeciesDistributionChart());
|
||||
limitChartAnimation(ui->chartView_SpeciesDistribution->chart());
|
||||
if (ui->tabWidget->currentWidget() == ui->tabSpecies)
|
||||
limitChartAnimation();
|
||||
}
|
||||
|
||||
void WildMonChart::refreshLevelDistributionChart() {
|
||||
if (ui->chartView_LevelDistribution->chart())
|
||||
ui->chartView_LevelDistribution->chart()->deleteLater();
|
||||
ui->chartView_LevelDistribution->setChart(createLevelDistributionChart());
|
||||
limitChartAnimation(ui->chartView_LevelDistribution->chart());
|
||||
if (ui->tabWidget->currentWidget() == ui->tabLevels)
|
||||
limitChartAnimation();
|
||||
}
|
||||
|
||||
QStringList WildMonChart::getSpeciesNamesAlphabetical() const {
|
||||
|
@ -408,17 +412,27 @@ void WildMonChart::applySpeciesColors(const QList<QBarSet*> &barSets) {
|
|||
set->setColor(this->speciesToColor.value(set->label()));
|
||||
}
|
||||
|
||||
// Turn off the animation once it's played, otherwise it replays any time the window changes size.
|
||||
void WildMonChart::limitChartAnimation(QChart *chart) {
|
||||
// Turn off the chart animation once it's played, otherwise it replays any time the window changes size.
|
||||
// The animation only begins when it's first displayed, so we'll only ever consider the chart for the current tab,
|
||||
// and when the tab changes we'll call this again.
|
||||
void WildMonChart::limitChartAnimation() {
|
||||
// Chart may be destroyed before the animation finishes
|
||||
QPointer<QChart> safeChart = chart;
|
||||
QPointer<QChart> chart;
|
||||
if (ui->tabWidget->currentWidget() == ui->tabSpecies) {
|
||||
chart = ui->chartView_SpeciesDistribution->chart();
|
||||
} else if (ui->tabWidget->currentWidget() == ui->tabLevels) {
|
||||
chart = ui->chartView_LevelDistribution->chart();
|
||||
}
|
||||
|
||||
if (!chart || chart->animationOptions() == QChart::NoAnimation)
|
||||
return;
|
||||
|
||||
// QChart has no signal for when the animation is finished, so we use a timer to stop the animation.
|
||||
// It is technically possible to get the chart to freeze mid-animation by resizing the window after
|
||||
// the timer starts but before it finishes, but 1. animations are short so this is difficult to do,
|
||||
// and 2. the issue resolves if the window is resized afterwards, so it's probably fine.
|
||||
QTimer::singleShot(chart->animationDuration() + 500, [safeChart] {
|
||||
if (safeChart) safeChart->setAnimationOptions(QChart::NoAnimation);
|
||||
QTimer::singleShot(chart->animationDuration(), Qt::PreciseTimer, [chart] {
|
||||
if (chart) chart->setAnimationOptions(QChart::NoAnimation);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue