mirror of
https://github.com/huderlem/porymap.git
synced 2026-03-21 17:45:44 -05:00
Add new metatile image export window
This commit is contained in:
parent
b2798e77d4
commit
38e2772213
526
forms/metatileimageexporter.ui
Normal file
526
forms/metatileimageexporter.ui
Normal file
|
|
@ -0,0 +1,526 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MetatileImageExporter</class>
|
||||
<widget class="QDialog" name="MetatileImageExporter">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>649</width>
|
||||
<height>601</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Export Metatiles Image</string>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="1">
|
||||
<widget class="QFrame" name="frame_Options">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::FocusPolicy::ClickFocus</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_Options">
|
||||
<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="QScrollArea" name="scrollArea_Options">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents_Options">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>304</width>
|
||||
<height>532</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_Tilesets">
|
||||
<property name="title">
|
||||
<string>Tilesets</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="checkBox_SecondaryTileset">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If checked, automatically update the metatile range to include the full secondary tileset.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Secondary Tileset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_PrimaryTileset">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_SecondaryTileset">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="checkBox_PrimaryTileset">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If checked, automatically update the metatile range to include the full primary tileset.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Primary Tileset</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>1</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_MetatileRange">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Metatile Range</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_MetatileStart">
|
||||
<property name="text">
|
||||
<string>Start</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_MetatileStart">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The metatile ID to start the rendered image at.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_MetatileEnd">
|
||||
<property name="text">
|
||||
<string>End</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_MetatileEnd">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The metatile ID to end the rendered image at.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_Layers">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Each metatile consists of 3 layers of tiles. These layers can be toggled here by clicking the checkbox, or rearranged by clicking and dragging them up or down in the list.</p></body></html></string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Layers</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<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="ReorderableListWidget" name="listWidget_Layers">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::SizeAdjustPolicy::AdjustToContentsOnFirstShow</enum>
|
||||
</property>
|
||||
<property name="dragEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragDropMode::InternalMove</enum>
|
||||
</property>
|
||||
<property name="defaultDropAction">
|
||||
<enum>Qt::DropAction::MoveAction</enum>
|
||||
</property>
|
||||
<property name="resizeMode">
|
||||
<enum>QListView::ResizeMode::Adjust</enum>
|
||||
</property>
|
||||
<property name="itemAlignment">
|
||||
<set>Qt::AlignmentFlag::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_Transparency">
|
||||
<property name="title">
|
||||
<string>Transparency</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_TransparencyNormal">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If checked, transparent pixels in the image will be rendered with alpha of 0.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Normal</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_TransparencyBlack">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If checked, transparent pixels in the image will be rendered as black. This is the default in-game behavior.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Black</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_TransparencyFirst">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If checked, transparent pixels in the image will be rendered using the first color in tileset palette 0. This is the default behavior of the GBA.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>First palette color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_Misc">
|
||||
<property name="title">
|
||||
<string>Miscellaneous</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkBox_Placeholders">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If checked, display the placeholder tiles that are rendered for the unused layer in-game. For a given metatile only 2 of the 3 tile layers are used, and the 3rd layer is filled with these placeholder tiles. The unused layer and placeholder tile change depending on the metatile's layer type.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Render placeholder metatiles</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_WidthMetatiles">
|
||||
<property name="text">
|
||||
<string>Width (metatiles)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="UIntSpinBox" name="spinBox_WidthMetatiles">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Width of the output image in metatiles.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_WidthPixels">
|
||||
<property name="text">
|
||||
<string>Width (pixels)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="UIntSpinBox" name="spinBox_WidthPixels">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Width of the output image in pixels. Automatically rounded up to a multiple of a metatile's pixel width.</p></body></html></string>
|
||||
</property>
|
||||
<property name="minimum" stdset="0">
|
||||
<number>16</number>
|
||||
</property>
|
||||
<property name="maximum" stdset="0">
|
||||
<number>128</number>
|
||||
</property>
|
||||
<property name="singleStep" stdset="0">
|
||||
<number>16</number>
|
||||
</property>
|
||||
<property name="value" stdset="0">
|
||||
<number>128</number>
|
||||
</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>1</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_Buttons">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_Reset">
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</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_Close">
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_Save">
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_Preview">
|
||||
<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_Preview">
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::SizeAdjustPolicy::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents_Preview">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>285</width>
|
||||
<height>551</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="2" column="3">
|
||||
<widget class="QGraphicsView" name="graphicsView_Preview">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="mouseTracking">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::SizeAdjustPolicy::AdjustIgnored</enum>
|
||||
</property>
|
||||
<property name="dragMode">
|
||||
<enum>QGraphicsView::DragMode::NoDrag</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>NoScrollComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>noscrollcombobox.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>UIntSpinBox</class>
|
||||
<extends>QAbstractSpinBox</extends>
|
||||
<header>uintspinbox.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>UIntHexSpinBox</class>
|
||||
<extends>UIntSpinBox</extends>
|
||||
<header location="global">uintspinbox.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ReorderableListWidget</class>
|
||||
<extends>QListWidget</extends>
|
||||
<header>metatileimageexporter.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
</rect>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::FocusPolicy::ClickFocus</enum>
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Tileset Editor</string>
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="childrenCollapsible">
|
||||
<bool>false</bool>
|
||||
|
|
@ -34,10 +34,10 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Shadow::Plain</enum>
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="leftMargin">
|
||||
|
|
@ -58,14 +58,14 @@
|
|||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignHCenter|Qt::AlignmentFlag::AlignTop</set>
|
||||
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents_Metatiles">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>239</width>
|
||||
<width>253</width>
|
||||
<height>659</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
|
@ -88,17 +88,17 @@
|
|||
<item row="0" column="0">
|
||||
<widget class="NoScrollGraphicsView" name="graphicsView_Metatiles">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -121,7 +121,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -129,10 +129,10 @@
|
|||
</widget>
|
||||
<widget class="QFrame" name="frame_Editing">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
|
|
@ -162,14 +162,14 @@
|
|||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SizeConstraint::SetMinimumSize</enum>
|
||||
<enum>QLayout::SetMinimumSize</enum>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
|
|
@ -255,7 +255,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertPolicy::NoInsert</enum>
|
||||
<enum>QComboBox::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -274,10 +274,10 @@
|
|||
</size>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -290,17 +290,17 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertPolicy::NoInsert</enum>
|
||||
<enum>QComboBox::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Policy::Maximum</enum>
|
||||
<enum>QSizePolicy::Maximum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -319,7 +319,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertPolicy::NoInsert</enum>
|
||||
<enum>QComboBox::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -361,7 +361,7 @@
|
|||
<item row="16" column="0">
|
||||
<spacer name="verticalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -412,7 +412,7 @@
|
|||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_xFlip">
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LayoutDirection::LeftToRight</enum>
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
|
@ -436,10 +436,10 @@
|
|||
<item row="3" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Policy::Fixed</enum>
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -464,10 +464,10 @@
|
|||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Shadow::Plain</enum>
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="leftMargin">
|
||||
|
|
@ -510,13 +510,13 @@
|
|||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Shape::StyledPanel</enum>
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -526,7 +526,7 @@
|
|||
<item row="6" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -548,14 +548,14 @@
|
|||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignHCenter|Qt::AlignmentFlag::AlignTop</set>
|
||||
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents_Tiles">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>499</width>
|
||||
<width>446</width>
|
||||
<height>241</height>
|
||||
</rect>
|
||||
</property>
|
||||
|
|
@ -575,17 +575,17 @@
|
|||
<item row="0" column="0">
|
||||
<widget class="NoScrollGraphicsView" name="graphicsView_Tiles">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -602,7 +602,7 @@
|
|||
<item>
|
||||
<widget class="QSlider" name="horizontalSlider_TilesZoom">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -625,18 +625,34 @@
|
|||
<property name="title">
|
||||
<string>File</string>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuExport_Tiles_Image">
|
||||
<property name="title">
|
||||
<string>Export Tiles Image</string>
|
||||
</property>
|
||||
<addaction name="actionExport_Primary_Tiles_Image"/>
|
||||
<addaction name="actionExport_Secondary_Tiles_Image"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuImport_AdvanceMap_Metatiles">
|
||||
<property name="title">
|
||||
<string>Import Metatiles from Advance Map 1.92</string>
|
||||
</property>
|
||||
<addaction name="actionImport_Primary_AdvanceMap_Metatiles"/>
|
||||
<addaction name="actionImport_Secondary_AdvanceMap_Metatiles"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuImport_Tiles_Image">
|
||||
<property name="title">
|
||||
<string>Import Tiles Image</string>
|
||||
</property>
|
||||
<addaction name="actionImport_Primary_Tiles_Image"/>
|
||||
<addaction name="actionImport_Secondary_Tiles_Image"/>
|
||||
</widget>
|
||||
<addaction name="actionSave_Tileset"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionImport_Primary_Tiles"/>
|
||||
<addaction name="actionImport_Secondary_Tiles"/>
|
||||
<addaction name="menuImport_Tiles_Image"/>
|
||||
<addaction name="menuImport_AdvanceMap_Metatiles"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionImport_Primary_Metatiles"/>
|
||||
<addaction name="actionImport_Secondary_Metatiles"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionExport_Primary_Tiles_Image"/>
|
||||
<addaction name="actionExport_Secondary_Tiles_Image"/>
|
||||
<addaction name="actionExport_Primary_Metatiles_Image"/>
|
||||
<addaction name="actionExport_Secondary_Metatiles_Image"/>
|
||||
<addaction name="menuExport_Tiles_Image"/>
|
||||
<addaction name="actionExport_Metatiles_Image"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuTools">
|
||||
<property name="title">
|
||||
|
|
@ -685,16 +701,6 @@
|
|||
<string>Ctrl+S</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionImport_Primary_Tiles">
|
||||
<property name="text">
|
||||
<string>Import Primary Tiles Image...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionImport_Secondary_Tiles">
|
||||
<property name="text">
|
||||
<string>Import Secondary Tiles Image...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionChange_Metatiles_Count">
|
||||
<property name="text">
|
||||
<string>Change Number of Metatiles...</string>
|
||||
|
|
@ -745,36 +751,6 @@
|
|||
<string>Ctrl+Y</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExport_Primary_Tiles_Image">
|
||||
<property name="text">
|
||||
<string>Export Primary Tiles Image...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExport_Secondary_Tiles_Image">
|
||||
<property name="text">
|
||||
<string>Export Secondary Tiles Image...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionImport_Primary_Metatiles">
|
||||
<property name="text">
|
||||
<string>Import Primary Metatiles from Advance Map 1.92...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionImport_Secondary_Metatiles">
|
||||
<property name="text">
|
||||
<string>Import Secondary Metatiles from Advance Map 1.92...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExport_Primary_Metatiles_Image">
|
||||
<property name="text">
|
||||
<string>Export Primary Metatiles Image...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExport_Secondary_Metatiles_Image">
|
||||
<property name="text">
|
||||
<string>Export Secondary Metatiles Image...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCut">
|
||||
<property name="text">
|
||||
<string>Cut</string>
|
||||
|
|
@ -834,6 +810,41 @@
|
|||
<string>Show Raw Metatile Attributes</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExport_Primary_Tiles_Image">
|
||||
<property name="text">
|
||||
<string>Primary...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExport_Secondary_Tiles_Image">
|
||||
<property name="text">
|
||||
<string>Secondary...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionImport_Primary_AdvanceMap_Metatiles">
|
||||
<property name="text">
|
||||
<string>Primary...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionImport_Secondary_AdvanceMap_Metatiles">
|
||||
<property name="text">
|
||||
<string>Secondary...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionImport_Primary_Tiles_Image">
|
||||
<property name="text">
|
||||
<string>Primary...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionImport_Secondary_Tiles_Image">
|
||||
<property name="text">
|
||||
<string>Secondary...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExport_Metatiles_Image">
|
||||
<property name="text">
|
||||
<string>Export Metatiles Image...</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
|
|
|||
|
|
@ -54,7 +54,8 @@ protected:
|
|||
static bool getConfigBool(const QString &key, const QString &value);
|
||||
static int getConfigInteger(const QString &key, const QString &value, int min = INT_MIN, int max = INT_MAX, int defaultValue = 0);
|
||||
static uint32_t getConfigUint32(const QString &key, const QString &value, uint32_t min = 0, uint32_t max = UINT_MAX, uint32_t defaultValue = 0);
|
||||
static QColor getConfigColor(const QString &key, const QString &value, const QColor &defaultValue = Qt::black);
|
||||
static QColor getConfigColor(const QString &key, const QString &value, const QColor &defaultValue = QColor(Qt::black));
|
||||
static QString toConfigColor(const QColor &color);
|
||||
|
||||
QString m_root;
|
||||
QString m_filename;
|
||||
|
|
@ -82,7 +83,7 @@ public:
|
|||
this->collisionOpacity = 50;
|
||||
this->collisionZoom = 30;
|
||||
this->metatilesZoom = 30;
|
||||
this->tilesetEditorMetatilesZoom = 45;
|
||||
this->tilesetEditorMetatilesZoom = 30;
|
||||
this->tilesetEditorTilesZoom = 30;
|
||||
this->showPlayerView = false;
|
||||
this->showCursorTile = true;
|
||||
|
|
@ -351,7 +352,7 @@ public:
|
|||
this->prefabImportPrompted = false;
|
||||
this->tilesetsHaveCallback = true;
|
||||
this->tilesetsHaveIsCompressed = true;
|
||||
this->setTransparentPixelsBlack = true;
|
||||
this->transparencyColor = QColor(Qt::black);
|
||||
this->preserveMatchingOnlyData = false;
|
||||
this->filePaths.clear();
|
||||
this->eventIconPaths.clear();
|
||||
|
|
@ -426,7 +427,7 @@ public:
|
|||
bool prefabImportPrompted;
|
||||
bool tilesetsHaveCallback;
|
||||
bool tilesetsHaveIsCompressed;
|
||||
bool setTransparentPixelsBlack;
|
||||
QColor transparencyColor;
|
||||
bool preserveMatchingOnlyData;
|
||||
int metatileAttributesSize;
|
||||
uint32_t metatileBehaviorMask;
|
||||
|
|
|
|||
|
|
@ -65,14 +65,24 @@ public:
|
|||
} lastCommitBlocks; // to track map changes
|
||||
|
||||
void setMetatileLayerOrder(const QList<int> &layerOrder) { m_metatileLayerOrder = layerOrder; }
|
||||
QList<int> metatileLayerOrder() const;
|
||||
static void setDefaultMetatileLayerOrder(const QList<int> &layerOrder) { s_defaultMetatileLayerOrder = layerOrder; }
|
||||
static QList<int> defaultMetatileLayerOrder();
|
||||
const QList<int> &metatileLayerOrder() const {
|
||||
return !m_metatileLayerOrder.isEmpty() ? m_metatileLayerOrder : Layout::globalMetatileLayerOrder();
|
||||
}
|
||||
static void setGlobalMetatileLayerOrder(const QList<int> &layerOrder) { s_globalMetatileLayerOrder = layerOrder; }
|
||||
static const QList<int> &globalMetatileLayerOrder() {
|
||||
static const QList<int> defaultLayerOrder = {0, 1, 2};
|
||||
return !s_globalMetatileLayerOrder.isEmpty() ? s_globalMetatileLayerOrder : defaultLayerOrder;
|
||||
}
|
||||
|
||||
void setMetatileLayerOpacity(const QList<float> &layerOpacity) { m_metatileLayerOpacity = layerOpacity; }
|
||||
QList<float> metatileLayerOpacity() const;
|
||||
static void setDefaultMetatileLayerOpacity(const QList<float> &layerOpacity) { s_defaultMetatileLayerOpacity = layerOpacity; }
|
||||
static QList<float> defaultMetatileLayerOpacity();
|
||||
const QList<float> &metatileLayerOpacity() const {
|
||||
return !m_metatileLayerOpacity.isEmpty() ? m_metatileLayerOpacity : Layout::globalMetatileLayerOpacity();
|
||||
}
|
||||
static void setGlobalMetatileLayerOpacity(const QList<float> &layerOpacity) { s_globalMetatileLayerOpacity = layerOpacity; }
|
||||
static const QList<float> &globalMetatileLayerOpacity() {
|
||||
static const QList<float> defaultLayerOpacity = {1.0, 1.0, 1.0};
|
||||
return !s_globalMetatileLayerOpacity.isEmpty() ? s_globalMetatileLayerOpacity : defaultLayerOpacity;
|
||||
}
|
||||
|
||||
LayoutPixmapItem *layoutItem = nullptr;
|
||||
CollisionPixmapItem *collisionItem = nullptr;
|
||||
|
|
@ -166,8 +176,8 @@ private:
|
|||
|
||||
QList<int> m_metatileLayerOrder;
|
||||
QList<float> m_metatileLayerOpacity;
|
||||
static QList<int> s_defaultMetatileLayerOrder;
|
||||
static QList<float> s_defaultMetatileLayerOpacity;
|
||||
static QList<int> s_globalMetatileLayerOrder;
|
||||
static QList<float> s_globalMetatileLayerOpacity;
|
||||
|
||||
signals:
|
||||
void dimensionsChanged(const QSize &size);
|
||||
|
|
|
|||
|
|
@ -62,6 +62,14 @@ public:
|
|||
static void setLayout(Project*);
|
||||
static QString getMetatileIdString(uint16_t metatileId);
|
||||
static QString getMetatileIdStrings(const QList<uint16_t> metatileIds);
|
||||
static QString getLayerName(int layerNum);
|
||||
|
||||
static int tileWidth() { return 2; }
|
||||
static int tileHeight() { return 2; }
|
||||
static int tilesPerLayer() { return Metatile::tileWidth() * Metatile::tileHeight(); }
|
||||
static int pixelWidth() { return Metatile::tileWidth() * Tile::pixelWidth(); }
|
||||
static int pixelHeight() { return Metatile::tileHeight() * Tile::pixelHeight(); }
|
||||
static QSize pixelSize() { return QSize(pixelWidth(), pixelHeight()); }
|
||||
|
||||
inline bool operator==(const Metatile &other) {
|
||||
return this->tiles == other.tiles && this->attributes == other.attributes;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#define TILE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QSize>
|
||||
|
||||
class Tile
|
||||
{
|
||||
|
|
@ -24,6 +25,10 @@ public:
|
|||
static int getIndexInTileset(int);
|
||||
|
||||
static const uint16_t maxValue;
|
||||
|
||||
static int pixelWidth() { return 8; }
|
||||
static int pixelHeight() { return 8; }
|
||||
static QSize pixelSize() { return QSize(Tile::pixelWidth(), Tile::pixelHeight()); }
|
||||
};
|
||||
|
||||
inline bool operator==(const Tile &a, const Tile &b) {
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ public:
|
|||
QList<QList<QRgb>> palettes;
|
||||
QList<QList<QRgb>> palettePreviews;
|
||||
|
||||
static QString stripPrefix(const QString &fullName);
|
||||
static Tileset* getMetatileTileset(int, Tileset*, Tileset*);
|
||||
static Tileset* getTileTileset(int, Tileset*, Tileset*);
|
||||
static Metatile* getMetatile(int, Tileset*, Tileset*);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
namespace Util {
|
||||
void numericalModeSort(QStringList &list);
|
||||
int roundUp(int numToRound, int multiple);
|
||||
int roundUpToMultiple(int numToRound, int multiple);
|
||||
QString toDefineCase(QString input);
|
||||
QString toHexString(uint32_t value, int minLength = 0);
|
||||
QString toHtmlParagraph(const QString &text);
|
||||
|
|
|
|||
|
|
@ -12,8 +12,10 @@ QImage getCollisionMetatileImage(Block);
|
|||
QImage getCollisionMetatileImage(int, int);
|
||||
QImage getMetatileImage(uint16_t, Layout*, bool useTruePalettes = false);
|
||||
QImage getMetatileImage(Metatile*, Layout*, bool useTruePalettes = false);
|
||||
QImage getMetatileImage(uint16_t, Tileset*, Tileset*, const QList<int>&, const QList<float>&, bool useTruePalettes = false);
|
||||
QImage getMetatileImage(Metatile*, Tileset*, Tileset*, const QList<int>&, const QList<float>&, bool useTruePalettes = false);
|
||||
QImage getMetatileImage(uint16_t, Tileset*, Tileset*, const QList<int>&, const QList<float>& = {}, bool useTruePalettes = false);
|
||||
QImage getMetatileImage(Metatile*, Tileset*, Tileset*, const QList<int>&, const QList<float>& = {}, bool useTruePalettes = false);
|
||||
QImage getMetatileSheetImage(Layout *, int, bool useTruePalettes = false);
|
||||
QImage getMetatileSheetImage(Tileset *, Tileset *, uint16_t, int, int, const QList<int> &, const QList<float> & = {}, const QSize &size = Metatile::pixelSize(), bool useTruePalettes = false);
|
||||
QImage getTileImage(uint16_t, Tileset*, Tileset*);
|
||||
QImage getPalettedTileImage(uint16_t, Tileset*, Tileset*, int, bool useTruePalettes = false);
|
||||
QImage getGreyscaleTileImage(uint16_t tile, Tileset *primaryTileset, Tileset *secondaryTileset);
|
||||
|
|
|
|||
101
include/ui/metatileimageexporter.h
Normal file
101
include/ui/metatileimageexporter.h
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
#ifndef METATILEIMAGEEXPORTER_H
|
||||
#define METATILEIMAGEEXPORTER_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QGraphicsScene>
|
||||
#include <QShowEvent>
|
||||
#include <QCloseEvent>
|
||||
#include <QListWidget>
|
||||
#include <QDropEvent>
|
||||
#include <QRadioButton>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
class Tileset;
|
||||
|
||||
namespace Ui {
|
||||
class MetatileImageExporter;
|
||||
}
|
||||
|
||||
class ReorderableListWidget : public QListWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ReorderableListWidget(QWidget *parent = nullptr) : QListWidget(parent) {
|
||||
setDragEnabled(true);
|
||||
setDragDropMode(QAbstractItemView::InternalMove);
|
||||
setDefaultDropAction(Qt::MoveAction);
|
||||
};
|
||||
|
||||
signals:
|
||||
void reordered();
|
||||
|
||||
protected:
|
||||
virtual void dropEvent(QDropEvent *event) override {
|
||||
QListWidget::dropEvent(event);
|
||||
if (event->isAccepted()) {
|
||||
emit reordered();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class MetatileImageExporter : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
struct Settings {
|
||||
OrderedMap<int,bool> layerOrder = {
|
||||
{2, true},
|
||||
{1, true},
|
||||
{0, true},
|
||||
};
|
||||
uint16_t metatileStart = 0;
|
||||
uint16_t metatileEnd = 0xFFFF;
|
||||
uint16_t numMetatilesWide = 8;
|
||||
bool usePrimaryTileset = true;
|
||||
bool useSecondaryTileset = false;
|
||||
bool renderPlaceholders = false;
|
||||
int transparencyMode = 0;
|
||||
};
|
||||
|
||||
explicit MetatileImageExporter(QWidget *parent, Tileset *primaryTileset, Tileset *secondaryTileset, Settings *savedSettings = nullptr);
|
||||
~MetatileImageExporter();
|
||||
|
||||
protected:
|
||||
virtual void showEvent(QShowEvent *) override;
|
||||
virtual void closeEvent(QCloseEvent *) override;
|
||||
|
||||
private:
|
||||
Ui::MetatileImageExporter *ui;
|
||||
|
||||
Tileset *m_primaryTileset;
|
||||
Tileset *m_secondaryTileset;
|
||||
Settings *m_savedSettings;
|
||||
|
||||
QGraphicsScene *m_scene = nullptr;
|
||||
QGraphicsPixmapItem *m_preview = nullptr;
|
||||
bool m_previewUpdateQueued = false;
|
||||
QList<int> m_layerOrder;
|
||||
ProjectConfig m_savedConfig;
|
||||
QList<QRadioButton*> m_transparencyButtons;
|
||||
|
||||
void applySettings(const Settings &settings);
|
||||
void updatePreview();
|
||||
void tryUpdatePreview();
|
||||
void queuePreviewUpdate();
|
||||
void updateTilesetUI();
|
||||
void syncPixelWidth();
|
||||
void syncMetatileWidth();
|
||||
void validateMetatileStart();
|
||||
void validateMetatileEnd();
|
||||
uint16_t getExpectedMetatileStart();
|
||||
uint16_t getExpectedMetatileEnd();
|
||||
void updateMetatileRange();
|
||||
void copyRenderSettings();
|
||||
void restoreRenderSettings();
|
||||
void saveImage();
|
||||
void reset();
|
||||
};
|
||||
|
||||
#endif // METATILEIMAGEEXPORTER_H
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
#include "tileseteditormetatileselector.h"
|
||||
#include "tileseteditortileselector.h"
|
||||
#include "metatilelayersitem.h"
|
||||
#include "metatileimageexporter.h"
|
||||
|
||||
class NoScrollComboBox;
|
||||
class Layout;
|
||||
|
|
@ -71,10 +72,6 @@ private slots:
|
|||
|
||||
void on_spinBox_paletteSelector_valueChanged(int arg1);
|
||||
|
||||
void on_actionImport_Primary_Tiles_triggered();
|
||||
|
||||
void on_actionImport_Secondary_Tiles_triggered();
|
||||
|
||||
void on_actionChange_Metatiles_Count_triggered();
|
||||
|
||||
void on_actionChange_Palettes_triggered();
|
||||
|
|
@ -91,14 +88,6 @@ private slots:
|
|||
|
||||
void on_lineEdit_metatileLabel_editingFinished();
|
||||
|
||||
void on_actionExport_Primary_Tiles_Image_triggered();
|
||||
void on_actionExport_Secondary_Tiles_Image_triggered();
|
||||
void on_actionExport_Primary_Metatiles_Image_triggered();
|
||||
void on_actionExport_Secondary_Metatiles_Image_triggered();
|
||||
|
||||
void on_actionImport_Primary_Metatiles_triggered();
|
||||
void on_actionImport_Secondary_Metatiles_triggered();
|
||||
|
||||
void on_copyButton_metatileLabel_clicked();
|
||||
|
||||
void on_actionCut_triggered();
|
||||
|
|
@ -122,8 +111,10 @@ private:
|
|||
void drawSelectedTiles();
|
||||
void redrawTileSelector();
|
||||
void redrawMetatileSelector();
|
||||
void importTilesetTiles(Tileset*, bool);
|
||||
void importTilesetMetatiles(Tileset*, bool);
|
||||
void importTilesetTiles(Tileset*);
|
||||
void importAdvanceMapMetatiles(Tileset*);
|
||||
void exportTilesImage(Tileset*);
|
||||
void exportMetatilesImage();
|
||||
void refresh();
|
||||
void commitMetatileLabel();
|
||||
void closeEvent(QCloseEvent*);
|
||||
|
|
@ -170,6 +161,7 @@ private:
|
|||
QGraphicsScene *metatileLayersScene = nullptr;
|
||||
bool lockSelection = false;
|
||||
QSet<uint16_t> metatileReloadQueue;
|
||||
MetatileImageExporter::Settings *metatileImageExportSettings = nullptr;
|
||||
|
||||
bool save();
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,6 @@ public:
|
|||
uint16_t getSelectedMetatileId();
|
||||
void updateSelectedMetatile();
|
||||
QPoint getMetatileIdCoordsOnWidget(uint16_t metatileId);
|
||||
QImage buildPrimaryMetatilesImage();
|
||||
QImage buildSecondaryMetatilesImage();
|
||||
|
||||
QVector<uint16_t> usedMetatiles;
|
||||
bool selectorShowUnused = false;
|
||||
|
|
@ -56,8 +54,6 @@ private:
|
|||
void drawFilters();
|
||||
void drawUnused();
|
||||
void drawCounts();
|
||||
QImage buildAllMetatilesImage();
|
||||
QImage buildImage(int metatileIdStart, int numMetatiles);
|
||||
int numPrimaryMetatilesRounded() const;
|
||||
|
||||
signals:
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ public:
|
|||
uint32_t value() const { return m_value; }
|
||||
uint32_t minimum() const { return m_minimum; }
|
||||
uint32_t maximum() const { return m_maximum; }
|
||||
uint32_t singleStep() const { return m_singleStep; }
|
||||
QString prefix() const { return m_prefix; }
|
||||
int displayIntegerBase() const { return m_displayIntegerBase; }
|
||||
bool hasPadding() const { return m_hasPadding; }
|
||||
|
|
@ -28,6 +29,7 @@ public:
|
|||
void setMinimum(uint32_t min);
|
||||
void setMaximum(uint32_t max);
|
||||
void setRange(uint32_t min, uint32_t max);
|
||||
void setSingleStep(uint32_t val);
|
||||
void setPrefix(const QString &prefix);
|
||||
void setDisplayIntegerBase(int base);
|
||||
void setHasPadding(bool enabled);
|
||||
|
|
@ -36,6 +38,7 @@ private:
|
|||
uint32_t m_minimum;
|
||||
uint32_t m_maximum;
|
||||
uint32_t m_value;
|
||||
uint32_t m_singleStep;
|
||||
QString m_prefix;
|
||||
int m_displayIntegerBase;
|
||||
bool m_hasPadding;
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ SOURCES += src/core/advancemapparser.cpp \
|
|||
src/ui/regionmapeditor.cpp \
|
||||
src/ui/newmapdialog.cpp \
|
||||
src/ui/mapimageexporter.cpp \
|
||||
src/ui/metatileimageexporter.cpp \
|
||||
src/ui/newtilesetdialog.cpp \
|
||||
src/ui/flowlayout.cpp \
|
||||
src/ui/mapruler.cpp \
|
||||
|
|
@ -240,6 +241,7 @@ HEADERS += include/core/advancemapparser.h \
|
|||
include/ui/regionmapeditor.h \
|
||||
include/ui/newmapdialog.h \
|
||||
include/ui/mapimageexporter.h \
|
||||
include/ui/metatileimageexporter.h \
|
||||
include/ui/newtilesetdialog.h \
|
||||
include/ui/overlay.h \
|
||||
include/ui/flowlayout.h \
|
||||
|
|
@ -289,6 +291,7 @@ FORMS += forms/mainwindow.ui \
|
|||
forms/aboutporymap.ui \
|
||||
forms/newtilesetdialog.ui \
|
||||
forms/mapimageexporter.ui \
|
||||
forms/metatileimageexporter.ui \
|
||||
forms/shortcutseditor.ui \
|
||||
forms/preferenceeditor.ui \
|
||||
forms/regionmappropertiesdialog.ui \
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ int KeyValueConfigBase::getConfigInteger(const QString &key, const QString &valu
|
|||
logWarn(QString("Invalid config value for %1: '%2'. Must be an integer. Using default value '%3'.").arg(key).arg(value).arg(defaultValue));
|
||||
result = defaultValue;
|
||||
}
|
||||
return qMin(max, qMax(min, result));
|
||||
return qBound(min, result, max);
|
||||
}
|
||||
|
||||
uint32_t KeyValueConfigBase::getConfigUint32(const QString &key, const QString &value, uint32_t min, uint32_t max, uint32_t defaultValue) {
|
||||
|
|
@ -293,7 +293,7 @@ uint32_t KeyValueConfigBase::getConfigUint32(const QString &key, const QString &
|
|||
logWarn(QString("Invalid config value for %1: '%2'. Must be an integer. Using default value '%3'.").arg(key).arg(value).arg(defaultValue));
|
||||
result = defaultValue;
|
||||
}
|
||||
return qMin(max, qMax(min, result));
|
||||
return qBound(min, result, max);
|
||||
}
|
||||
|
||||
QColor KeyValueConfigBase::getConfigColor(const QString &key, const QString &value, const QColor &defaultValue) {
|
||||
|
|
@ -305,6 +305,10 @@ QColor KeyValueConfigBase::getConfigColor(const QString &key, const QString &val
|
|||
return color;
|
||||
}
|
||||
|
||||
QString KeyValueConfigBase::toConfigColor(const QColor &color) {
|
||||
return color.name().remove("#"); // Our text config treats '#' as the start of a comment.
|
||||
}
|
||||
|
||||
PorymapConfig porymapConfig;
|
||||
|
||||
PorymapConfig::PorymapConfig() : KeyValueConfigBase(QStringLiteral("porymap.cfg")) {
|
||||
|
|
@ -571,7 +575,7 @@ QMap<QString, QString> PorymapConfig::getKeyValueMap() {
|
|||
map.insert("grid_x", QString::number(this->gridSettings.offsetX));
|
||||
map.insert("grid_y", QString::number(this->gridSettings.offsetY));
|
||||
map.insert("grid_style", GridSettings::getStyleName(this->gridSettings.style));
|
||||
map.insert("grid_color", this->gridSettings.color.name().remove("#")); // Our text config treats '#' as the start of a comment.
|
||||
map.insert("grid_color", toConfigColor(this->gridSettings.color));
|
||||
|
||||
QStringList logTypesStrings;
|
||||
for (const auto &type : this->statusBarLogTypes) {
|
||||
|
|
@ -898,8 +902,8 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
|
|||
this->tilesetsHaveCallback = getConfigBool(key, value);
|
||||
} else if (key == "tilesets_have_is_compressed") {
|
||||
this->tilesetsHaveIsCompressed = getConfigBool(key, value);
|
||||
} else if (key == "set_transparent_pixels_black") {
|
||||
this->setTransparentPixelsBlack = getConfigBool(key, value);
|
||||
} else if (key == "transparency_color") {
|
||||
this->transparencyColor = getConfigColor(key, value);
|
||||
} else if (key == "preserve_matching_only_data") {
|
||||
this->preserveMatchingOnlyData = getConfigBool(key, value);
|
||||
} else if (key == "event_icon_path_object") {
|
||||
|
|
@ -1005,7 +1009,7 @@ QMap<QString, QString> ProjectConfig::getKeyValueMap() {
|
|||
}
|
||||
map.insert("tilesets_have_callback", QString::number(this->tilesetsHaveCallback));
|
||||
map.insert("tilesets_have_is_compressed", QString::number(this->tilesetsHaveIsCompressed));
|
||||
map.insert("set_transparent_pixels_black", QString::number(this->setTransparentPixelsBlack));
|
||||
map.insert("transparency_color", toConfigColor(this->transparencyColor));
|
||||
map.insert("preserve_matching_only_data", QString::number(this->preserveMatchingOnlyData));
|
||||
map.insert("metatile_attributes_size", QString::number(this->metatileAttributesSize));
|
||||
map.insert("metatile_behavior_mask", Util::toHexString(this->metatileBehaviorMask));
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@
|
|||
#include "imageproviders.h"
|
||||
#include "utility.h"
|
||||
|
||||
QList<int> Layout::s_globalMetatileLayerOrder;
|
||||
QList<float> Layout::s_globalMetatileLayerOpacity;
|
||||
|
||||
Layout::Layout(const Layout &other) : Layout() {
|
||||
copyFrom(&other);
|
||||
}
|
||||
|
|
@ -612,23 +615,3 @@ Blockdata Layout::readBlockdata(const QString &path, QString *error) {
|
|||
|
||||
return blockdata;
|
||||
}
|
||||
|
||||
QList<int> Layout::metatileLayerOrder() const {
|
||||
return !m_metatileLayerOrder.isEmpty() ? m_metatileLayerOrder : Layout::defaultMetatileLayerOrder();
|
||||
}
|
||||
|
||||
QList<int> Layout::s_defaultMetatileLayerOrder;
|
||||
QList<int> Layout::defaultMetatileLayerOrder() {
|
||||
static const QList<int> initialDefault = {0, 1, 2};
|
||||
return !s_defaultMetatileLayerOrder.isEmpty() ? s_defaultMetatileLayerOrder : initialDefault;
|
||||
}
|
||||
|
||||
QList<float> Layout::metatileLayerOpacity() const {
|
||||
return !m_metatileLayerOpacity.isEmpty() ? m_metatileLayerOpacity : Layout::defaultMetatileLayerOpacity();
|
||||
}
|
||||
|
||||
QList<float> Layout::s_defaultMetatileLayerOpacity;
|
||||
QList<float> Layout::defaultMetatileLayerOpacity() {
|
||||
static const QList<float> initialDefault = {1.0, 1.0, 1.0};
|
||||
return !s_defaultMetatileLayerOpacity.isEmpty() ? s_defaultMetatileLayerOpacity : initialDefault;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ int Metatile::getIndexInTileset(int metatileId) {
|
|||
}
|
||||
|
||||
QPoint Metatile::coordFromPixmapCoord(const QPointF &pixelCoord) {
|
||||
int x = static_cast<int>(pixelCoord.x()) / 16;
|
||||
int y = static_cast<int>(pixelCoord.y()) / 16;
|
||||
int x = static_cast<int>(pixelCoord.x()) / pixelWidth();
|
||||
int y = static_cast<int>(pixelCoord.y()) / pixelHeight();
|
||||
if (pixelCoord.x() < 0) x--;
|
||||
if (pixelCoord.y() < 0) y--;
|
||||
return QPoint(x, y);
|
||||
|
|
@ -55,6 +55,11 @@ QString Metatile::getMetatileIdStrings(const QList<uint16_t> metatileIds) {
|
|||
return metatiles.join(",");
|
||||
};
|
||||
|
||||
QString Metatile::getLayerName(int layerNum) {
|
||||
static const QStringList layerTitles = { "Bottom", "Middle", "Top"};
|
||||
return layerTitles.value(layerNum);
|
||||
}
|
||||
|
||||
// Read and pack together this metatile's attributes.
|
||||
uint32_t Metatile::getAttributes() const {
|
||||
uint32_t data = 0;
|
||||
|
|
|
|||
|
|
@ -200,9 +200,8 @@ QString Tileset::getMetatileLabelPrefix()
|
|||
QString Tileset::getMetatileLabelPrefix(const QString &name)
|
||||
{
|
||||
// Default is "gTileset_Name" --> "METATILE_Name_"
|
||||
const QString tilesetPrefix = projectConfig.getIdentifier(ProjectIdentifier::symbol_tilesets_prefix);
|
||||
const QString labelPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_metatile_label_prefix);
|
||||
return QString("%1%2_").arg(labelPrefix).arg(QString(name).replace(tilesetPrefix, ""));
|
||||
return QString("%1%2_").arg(labelPrefix).arg(Tileset::stripPrefix(name));
|
||||
}
|
||||
|
||||
bool Tileset::metatileIsValid(uint16_t metatileId, Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
|
|
@ -382,8 +381,7 @@ QString Tileset::getExpectedDir(QString tilesetName, bool isSecondary)
|
|||
: projectConfig.getFilePath(ProjectFilePath::data_primary_tilesets_folders);
|
||||
|
||||
static const QRegularExpression re("([a-z])([A-Z0-9])");
|
||||
const QString prefix = projectConfig.getIdentifier(ProjectIdentifier::symbol_tilesets_prefix);
|
||||
return basePath + tilesetName.replace(prefix, "").replace(re, "\\1_\\2").toLower();
|
||||
return basePath + Tileset::stripPrefix(tilesetName).replace(re, "\\1_\\2").toLower();
|
||||
}
|
||||
|
||||
// Get the expected positions of the members in struct Tileset.
|
||||
|
|
@ -600,3 +598,7 @@ bool Tileset::save() {
|
|||
if (!savePalettes()) success = false;
|
||||
return success;
|
||||
}
|
||||
|
||||
QString Tileset::stripPrefix(const QString &fullName) {
|
||||
return QString(fullName).replace(projectConfig.getIdentifier(ProjectIdentifier::symbol_tilesets_prefix), "");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ void Util::numericalModeSort(QStringList &list) {
|
|||
std::sort(list.begin(), list.end(), collator);
|
||||
}
|
||||
|
||||
int Util::roundUp(int numToRound, int multiple) {
|
||||
int Util::roundUpToMultiple(int numToRound, int multiple) {
|
||||
if (multiple <= 0)
|
||||
return numToRound;
|
||||
|
||||
|
|
|
|||
|
|
@ -1176,8 +1176,8 @@ void Editor::setPlayerViewRect(const QRectF &rect) {
|
|||
}
|
||||
|
||||
void Editor::setCursorRectPos(const QPoint &pos) {
|
||||
int x = qMax(0, qMin(pos.x(), this->layout ? this->layout->getWidth() - 1 : 0));
|
||||
int y = qMax(0, qMin(pos.y(), this->layout ? this->layout->getHeight() - 1 : 0));
|
||||
int x = qBound(0, pos.x(), this->layout ? this->layout->getWidth() - 1 : 0);
|
||||
int y = qBound(0, pos.y(), this->layout ? this->layout->getHeight() - 1 : 0);
|
||||
|
||||
if (this->playerViewRect)
|
||||
this->playerViewRect->updateLocation(x, y);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round);
|
||||
QCoreApplication::setAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles, true);
|
||||
|
||||
QApplication a(argc, argv);
|
||||
a.setStyle("fusion");
|
||||
|
||||
|
|
|
|||
|
|
@ -1618,7 +1618,7 @@ Tileset *Project::createNewTileset(QString name, bool secondary, bool checkerboa
|
|||
metatilesFilepath.append(projectConfig.getFilePath(ProjectFilePath::tilesets_metatiles));
|
||||
}
|
||||
ignoreWatchedFilesTemporarily({headersFilepath, graphicsFilepath, metatilesFilepath});
|
||||
name.remove(0, prefix.length()); // Strip prefix from name to get base name for use in other symbols.
|
||||
name = Tileset::stripPrefix(name);
|
||||
tileset->appendToHeaders(headersFilepath, name, this->usingAsmTilesets);
|
||||
tileset->appendToGraphics(graphicsFilepath, name, this->usingAsmTilesets);
|
||||
tileset->appendToMetatiles(metatilesFilepath, name, this->usingAsmTilesets);
|
||||
|
|
@ -3462,12 +3462,12 @@ void Project::applyParsedLimits() {
|
|||
Block::setLayout();
|
||||
Metatile::setLayout(this);
|
||||
|
||||
Project::num_metatiles_primary = qMin(qMax(Project::num_metatiles_primary, 1), Block::getMaxMetatileId() + 1);
|
||||
Project::num_metatiles_primary = qBound(1, Project::num_metatiles_primary, Block::getMaxMetatileId() + 1);
|
||||
projectConfig.defaultMetatileId = qMin(projectConfig.defaultMetatileId, Block::getMaxMetatileId());
|
||||
projectConfig.defaultElevation = qMin(projectConfig.defaultElevation, Block::getMaxElevation());
|
||||
projectConfig.defaultCollision = qMin(projectConfig.defaultCollision, Block::getMaxCollision());
|
||||
projectConfig.collisionSheetSize.setHeight(qMin(qMax(projectConfig.collisionSheetSize.height(), 1), Block::getMaxElevation() + 1));
|
||||
projectConfig.collisionSheetSize.setWidth(qMin(qMax(projectConfig.collisionSheetSize.width(), 1), Block::getMaxCollision() + 1));
|
||||
projectConfig.collisionSheetSize.setHeight(qBound(1, projectConfig.collisionSheetSize.height(), Block::getMaxElevation() + 1));
|
||||
projectConfig.collisionSheetSize.setWidth(qBound(1, projectConfig.collisionSheetSize.width(), Block::getMaxCollision() + 1));
|
||||
}
|
||||
|
||||
bool Project::hasUnsavedChanges() {
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ QList<QString> ScriptUtility::getCustomScripts() {
|
|||
}
|
||||
|
||||
QList<int> ScriptUtility::getMetatileLayerOrder() {
|
||||
return Layout::defaultMetatileLayerOrder();
|
||||
return Layout::globalMetatileLayerOrder();
|
||||
}
|
||||
|
||||
bool ScriptUtility::validateMetatileLayerOrder(const QList<int> &order) {
|
||||
|
|
@ -220,16 +220,16 @@ bool ScriptUtility::validateMetatileLayerOrder(const QList<int> &order) {
|
|||
void ScriptUtility::setMetatileLayerOrder(const QList<int> &order) {
|
||||
if (!validateMetatileLayerOrder(order))
|
||||
return;
|
||||
Layout::setDefaultMetatileLayerOrder(order);
|
||||
Layout::setGlobalMetatileLayerOrder(order);
|
||||
if (window) window->refreshAfterPalettePreviewChange();
|
||||
}
|
||||
|
||||
QList<float> ScriptUtility::getMetatileLayerOpacity() {
|
||||
return Layout::defaultMetatileLayerOpacity();
|
||||
return Layout::globalMetatileLayerOpacity();
|
||||
}
|
||||
|
||||
void ScriptUtility::setMetatileLayerOpacity(const QList<float> &opacities) {
|
||||
Layout::setDefaultMetatileLayerOpacity(opacities);
|
||||
Layout::setGlobalMetatileLayerOpacity(opacities);
|
||||
if (window) window->refreshAfterPalettePreviewChange();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,11 +56,9 @@ QImage getMetatileImage(
|
|||
const QList<float> &layerOpacity,
|
||||
bool useTruePalettes)
|
||||
{
|
||||
const int numTilesWide = 2;
|
||||
const int numTilesTall = 2;
|
||||
QImage metatile_image(8 * numTilesWide, 8 * numTilesTall, QImage::Format_RGBA8888);
|
||||
QImage metatile_image(Metatile::pixelWidth(), Metatile::pixelHeight(), QImage::Format_RGBA8888);
|
||||
if (!metatile) {
|
||||
metatile_image.fill(Qt::magenta);
|
||||
metatile_image.fill(projectConfig.transparencyColor == QColor(Qt::transparent) ? projectConfig.transparencyColor : QColor(Qt::magenta));
|
||||
return metatile_image;
|
||||
}
|
||||
|
||||
|
|
@ -70,21 +68,20 @@ QImage getMetatileImage(
|
|||
// tile pixels line up across layers we will still have something to render.
|
||||
// The GBA renders transparent pixels using palette 0 color 0. We have this color,
|
||||
// but all 3 games actually overwrite it with black when loading the tileset palettes,
|
||||
// so we have a setting to choose between these two behaviors.
|
||||
metatile_image.fill(projectConfig.setTransparentPixelsBlack ? QColor("black") : QColor(palettes.value(0).value(0)));
|
||||
// so we have a setting to specify an override transparency color.
|
||||
metatile_image.fill(projectConfig.transparencyColor.isValid() ? projectConfig.transparencyColor : QColor(palettes.value(0).value(0)));
|
||||
|
||||
QPainter metatile_painter(&metatile_image);
|
||||
|
||||
uint32_t layerType = metatile->layerType();
|
||||
const int numTilesPerLayer = numTilesWide * numTilesTall;
|
||||
for (const auto &layer : layerOrder)
|
||||
for (int y = 0; y < numTilesTall; y++)
|
||||
for (int x = 0; x < numTilesWide; x++) {
|
||||
for (int y = 0; y < Metatile::tileHeight(); y++)
|
||||
for (int x = 0; x < Metatile::tileWidth(); x++) {
|
||||
// Get the tile to render next
|
||||
Tile tile;
|
||||
int tileOffset = (y * numTilesWide) + x;
|
||||
int tileOffset = (y * Metatile::tileWidth()) + x;
|
||||
if (projectConfig.tripleLayerMetatilesEnabled) {
|
||||
tile = metatile->tiles.value(tileOffset + (layer * numTilesPerLayer));
|
||||
tile = metatile->tiles.value(tileOffset + (layer * Metatile::tilesPerLayer()));
|
||||
} else {
|
||||
// "Vanilla" metatiles only have 8 tiles, but render 12.
|
||||
// The remaining 4 tiles are rendered using user-specified tiles depending on layer type.
|
||||
|
|
@ -95,19 +92,19 @@ QImage getMetatileImage(
|
|||
if (layer == 0)
|
||||
tile = Tile(projectConfig.unusedTileNormal);
|
||||
else // Tiles are on layers 1 and 2
|
||||
tile = metatile->tiles.value(tileOffset + ((layer - 1) * numTilesPerLayer));
|
||||
tile = metatile->tiles.value(tileOffset + ((layer - 1) * Metatile::tilesPerLayer()));
|
||||
break;
|
||||
case Metatile::LayerType::Covered:
|
||||
if (layer == 2)
|
||||
tile = Tile(projectConfig.unusedTileCovered);
|
||||
else // Tiles are on layers 0 and 1
|
||||
tile = metatile->tiles.value(tileOffset + (layer * numTilesPerLayer));
|
||||
tile = metatile->tiles.value(tileOffset + (layer * Metatile::tilesPerLayer()));
|
||||
break;
|
||||
case Metatile::LayerType::Split:
|
||||
if (layer == 1)
|
||||
tile = Tile(projectConfig.unusedTileSplit);
|
||||
else // Tiles are on layers 0 and 2
|
||||
tile = metatile->tiles.value(tileOffset + ((layer == 0 ? 0 : 1) * numTilesPerLayer));
|
||||
tile = metatile->tiles.value(tileOffset + ((layer == 0 ? 0 : 1) * Metatile::tilesPerLayer()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -130,7 +127,7 @@ QImage getMetatileImage(
|
|||
logWarn(QString("Tile '%1' is referring to invalid palette number: '%2'").arg(tile.tileId).arg(tile.palette));
|
||||
}
|
||||
|
||||
QPoint origin = QPoint(x*8, y*8);
|
||||
QPoint origin = QPoint(x * Tile::pixelWidth(), y * Tile::pixelHeight());
|
||||
float opacity = layerOpacity.value(layer, 1.0);
|
||||
if (opacity < 1.0) {
|
||||
int alpha = 255 * opacity;
|
||||
|
|
@ -165,9 +162,9 @@ QImage getTileImage(uint16_t tileId, Tileset *primaryTileset, Tileset *secondary
|
|||
QImage getColoredTileImage(uint16_t tileId, Tileset *primaryTileset, Tileset *secondaryTileset, const QList<QRgb> &palette) {
|
||||
QImage tileImage = getTileImage(tileId, primaryTileset, secondaryTileset);
|
||||
if (tileImage.isNull()) {
|
||||
tileImage = QImage(8, 8, QImage::Format_RGBA8888);
|
||||
tileImage = QImage(Tile::pixelWidth(), Tile::pixelHeight(), QImage::Format_RGBA8888);
|
||||
QPainter painter(&tileImage);
|
||||
painter.fillRect(0, 0, 8, 8, palette.at(0));
|
||||
painter.fillRect(0, 0, tileImage.width(), tileImage.height(), palette.at(0));
|
||||
} else {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
tileImage.setColor(i, palette.at(i));
|
||||
|
|
@ -194,3 +191,57 @@ void flattenTo4bppImage(QImage * image) {
|
|||
for (int i = 0; i < image->sizeInBytes(); i++, pixel++)
|
||||
*pixel %= 16;
|
||||
}
|
||||
|
||||
QImage getMetatileSheetImage(Layout *layout, int numMetatilesWide, bool useTruePalettes) {
|
||||
return getMetatileSheetImage(layout->tileset_primary,
|
||||
layout->tileset_secondary,
|
||||
0,
|
||||
-1,
|
||||
numMetatilesWide,
|
||||
layout->metatileLayerOrder(),
|
||||
layout->metatileLayerOpacity(),
|
||||
Metatile::pixelSize(),
|
||||
useTruePalettes);
|
||||
}
|
||||
|
||||
QImage getMetatileSheetImage(Tileset *primaryTileset,
|
||||
Tileset *secondaryTileset,
|
||||
uint16_t metatileIdStart,
|
||||
int numMetatilesToDraw,
|
||||
int numMetatilesWide,
|
||||
const QList<int> &layerOrder,
|
||||
const QList<float> &layerOpacity,
|
||||
const QSize &metatileSize,
|
||||
bool useTruePalettes)
|
||||
{
|
||||
// We round up the number of primary metatiles to keep the tilesets on separate rows.
|
||||
int numPrimary = Util::roundUpToMultiple(primaryTileset ? primaryTileset->numMetatiles() : 0, numMetatilesWide);
|
||||
int maxPrimary = Project::getNumMetatilesPrimary();
|
||||
bool includesPrimary = metatileIdStart < maxPrimary;
|
||||
|
||||
// Negative values are used to indicate 'draw all metatiles'
|
||||
if (numMetatilesToDraw < 0) {
|
||||
numMetatilesToDraw = numPrimary + (secondaryTileset ? secondaryTileset->numMetatiles() : 0) - metatileIdStart;
|
||||
}
|
||||
|
||||
// Round up height for incomplete last row
|
||||
int numMetatilesTall = ceil((double)numMetatilesToDraw / numMetatilesWide);
|
||||
|
||||
QImage image(numMetatilesWide * metatileSize.width(), numMetatilesTall * metatileSize.height(), QImage::Format_RGBA8888);
|
||||
image.fill(projectConfig.transparencyColor == QColor(Qt::transparent) ? projectConfig.transparencyColor : QColor(Qt::magenta));
|
||||
|
||||
QPainter painter(&image);
|
||||
for (int i = 0; i < numMetatilesToDraw; i++) {
|
||||
uint16_t metatileId = i + metatileIdStart;
|
||||
if (includesPrimary && metatileId >= numPrimary)
|
||||
metatileId += maxPrimary - numPrimary; // Skip over unused region of primary tileset
|
||||
QImage metatile_image = getMetatileImage(metatileId, primaryTileset, secondaryTileset, layerOrder, layerOpacity, useTruePalettes)
|
||||
.scaled(metatileSize.width(), metatileSize.height());
|
||||
int map_y = i / numMetatilesWide;
|
||||
int map_x = i % numMetatilesWide;
|
||||
QPoint metatile_origin = QPoint(map_x * metatileSize.width(), map_y * metatileSize.height());
|
||||
painter.drawImage(metatile_origin, metatile_image);
|
||||
}
|
||||
painter.end();
|
||||
return image;
|
||||
}
|
||||
|
|
|
|||
321
src/ui/metatileimageexporter.cpp
Normal file
321
src/ui/metatileimageexporter.cpp
Normal file
|
|
@ -0,0 +1,321 @@
|
|||
#include "metatileimageexporter.h"
|
||||
#include "ui_metatileimageexporter.h"
|
||||
#include "filedialog.h"
|
||||
#include "imageproviders.h"
|
||||
#include "utility.h"
|
||||
#include "project.h"
|
||||
#include "metatile.h"
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
MetatileImageExporter::MetatileImageExporter(QWidget *parent, Tileset *primaryTileset, Tileset *secondaryTileset, Settings *savedSettings) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::MetatileImageExporter),
|
||||
m_primaryTileset(primaryTileset),
|
||||
m_secondaryTileset(secondaryTileset),
|
||||
m_savedSettings(savedSettings)
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
ui->setupUi(this);
|
||||
m_transparencyButtons = {
|
||||
ui->radioButton_TransparencyNormal,
|
||||
ui->radioButton_TransparencyBlack,
|
||||
ui->radioButton_TransparencyFirst,
|
||||
};
|
||||
|
||||
m_scene = new QGraphicsScene(this);
|
||||
m_preview = m_scene->addPixmap(QPixmap());
|
||||
ui->graphicsView_Preview->setScene(m_scene);
|
||||
|
||||
if (projectConfig.tripleLayerMetatilesEnabled) {
|
||||
// When triple-layer metatiles are enabled there is no unused layer,
|
||||
// so this setting becomes pointless. Disable it.
|
||||
ui->checkBox_Placeholders->setVisible(false);
|
||||
}
|
||||
|
||||
uint16_t maxMetatileId = Block::getMaxMetatileId();
|
||||
ui->spinBox_MetatileStart->setMaximum(maxMetatileId);
|
||||
ui->spinBox_MetatileEnd->setMaximum(maxMetatileId);
|
||||
ui->spinBox_WidthMetatiles->setRange(1, maxMetatileId);
|
||||
ui->spinBox_WidthPixels->setRange(1 * Metatile::pixelWidth(), maxMetatileId * Metatile::pixelWidth());
|
||||
|
||||
if (m_primaryTileset) {
|
||||
ui->comboBox_PrimaryTileset->setTextItem(m_primaryTileset->name);
|
||||
}
|
||||
if (m_secondaryTileset) {
|
||||
ui->comboBox_SecondaryTileset->setTextItem(m_secondaryTileset->name);
|
||||
}
|
||||
|
||||
if (m_savedSettings) {
|
||||
applySettings(*m_savedSettings);
|
||||
} else {
|
||||
applySettings({});
|
||||
}
|
||||
|
||||
connect(ui->listWidget_Layers, &ReorderableListWidget::itemChanged, this, &MetatileImageExporter::updatePreview);
|
||||
connect(ui->listWidget_Layers, &ReorderableListWidget::reordered, this, &MetatileImageExporter::updatePreview);
|
||||
|
||||
connect(ui->pushButton_Save, &QPushButton::pressed, this, &MetatileImageExporter::saveImage);
|
||||
connect(ui->pushButton_Close, &QPushButton::pressed, this, &MetatileImageExporter::close);
|
||||
connect(ui->pushButton_Reset, &QPushButton::pressed, this, &MetatileImageExporter::reset);
|
||||
|
||||
connect(ui->spinBox_WidthMetatiles, &UIntSpinBox::valueChanged, this, &MetatileImageExporter::syncPixelWidth);
|
||||
connect(ui->spinBox_WidthMetatiles, &UIntSpinBox::valueChanged, this, &MetatileImageExporter::queuePreviewUpdate);
|
||||
connect(ui->spinBox_WidthMetatiles, &UIntSpinBox::editingFinished, this, &MetatileImageExporter::tryUpdatePreview);
|
||||
|
||||
connect(ui->spinBox_WidthPixels, &UIntSpinBox::valueChanged, this, &MetatileImageExporter::syncMetatileWidth);
|
||||
connect(ui->spinBox_WidthPixels, &UIntSpinBox::valueChanged, this, &MetatileImageExporter::queuePreviewUpdate);
|
||||
connect(ui->spinBox_WidthPixels, &UIntSpinBox::editingFinished, this, &MetatileImageExporter::syncPixelWidth); // Round pixel width to multiple of 16
|
||||
connect(ui->spinBox_WidthPixels, &UIntSpinBox::editingFinished, this, &MetatileImageExporter::tryUpdatePreview);
|
||||
|
||||
connect(ui->spinBox_MetatileStart, &UIntHexSpinBox::valueChanged, this, &MetatileImageExporter::validateMetatileEnd);
|
||||
connect(ui->spinBox_MetatileStart, &UIntHexSpinBox::valueChanged, this, &MetatileImageExporter::queuePreviewUpdate);
|
||||
connect(ui->spinBox_MetatileStart, &UIntHexSpinBox::editingFinished, this, &MetatileImageExporter::tryUpdatePreview);
|
||||
|
||||
connect(ui->spinBox_MetatileEnd, &UIntHexSpinBox::valueChanged, this, &MetatileImageExporter::validateMetatileStart);
|
||||
connect(ui->spinBox_MetatileEnd, &UIntHexSpinBox::valueChanged, this, &MetatileImageExporter::queuePreviewUpdate);
|
||||
connect(ui->spinBox_MetatileEnd, &UIntHexSpinBox::editingFinished, this, &MetatileImageExporter::tryUpdatePreview);
|
||||
|
||||
// If we used toggled instead of clicked we'd get two preview updates instead of one when the setting changes.
|
||||
connect(ui->radioButton_TransparencyNormal, &QRadioButton::clicked, this, &MetatileImageExporter::updatePreview);
|
||||
connect(ui->radioButton_TransparencyBlack, &QRadioButton::clicked, this, &MetatileImageExporter::updatePreview);
|
||||
connect(ui->radioButton_TransparencyFirst, &QRadioButton::clicked, this, &MetatileImageExporter::updatePreview);
|
||||
|
||||
connect(ui->checkBox_Placeholders, &QCheckBox::toggled, this, &MetatileImageExporter::updatePreview);
|
||||
connect(ui->checkBox_PrimaryTileset, &QCheckBox::toggled, this, &MetatileImageExporter::updateTilesetUI);
|
||||
connect(ui->checkBox_PrimaryTileset, &QCheckBox::toggled, this, &MetatileImageExporter::updatePreview);
|
||||
connect(ui->checkBox_SecondaryTileset, &QCheckBox::toggled, this, &MetatileImageExporter::updateTilesetUI);
|
||||
connect(ui->checkBox_SecondaryTileset, &QCheckBox::toggled, this, &MetatileImageExporter::updatePreview);
|
||||
|
||||
ui->graphicsView_Preview->setFocus();
|
||||
}
|
||||
|
||||
MetatileImageExporter::~MetatileImageExporter() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
// Allow the window to open before displaying the preview.
|
||||
// Metatile sheet image creation is generally quick, so this only
|
||||
// really matters so that the graphics view can adjust the scale properly.
|
||||
void MetatileImageExporter::showEvent(QShowEvent *event) {
|
||||
QDialog::showEvent(event);
|
||||
if (!event->spontaneous()) {
|
||||
QTimer::singleShot(0, this, &MetatileImageExporter::updatePreview);
|
||||
}
|
||||
}
|
||||
|
||||
void MetatileImageExporter::closeEvent(QCloseEvent *event) {
|
||||
if (m_savedSettings) {
|
||||
m_savedSettings->metatileStart = ui->spinBox_MetatileStart->value();
|
||||
m_savedSettings->metatileEnd = ui->spinBox_MetatileEnd->value();
|
||||
m_savedSettings->numMetatilesWide = ui->spinBox_WidthMetatiles->value();
|
||||
m_savedSettings->usePrimaryTileset = ui->checkBox_PrimaryTileset->isChecked();
|
||||
m_savedSettings->useSecondaryTileset = ui->checkBox_SecondaryTileset->isChecked();
|
||||
m_savedSettings->renderPlaceholders = ui->checkBox_Placeholders->isChecked();
|
||||
for (int i = 0; i < m_transparencyButtons.length(); i++) {
|
||||
if (m_transparencyButtons.at(i)->isChecked()) {
|
||||
m_savedSettings->transparencyMode = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_savedSettings->layerOrder.clear();
|
||||
for (int i = 0; i < ui->listWidget_Layers->count(); i++) {
|
||||
auto item = ui->listWidget_Layers->item(i);
|
||||
int layerNum = item->data(Qt::UserRole).toInt();
|
||||
m_savedSettings->layerOrder[layerNum] = (item->checkState() == Qt::Checked);
|
||||
}
|
||||
}
|
||||
QDialog::closeEvent(event);
|
||||
}
|
||||
|
||||
void MetatileImageExporter::applySettings(const Settings &settings) {
|
||||
ui->spinBox_MetatileStart->setValue(settings.metatileStart);
|
||||
ui->spinBox_MetatileEnd->setValue(settings.metatileEnd);
|
||||
ui->spinBox_WidthMetatiles->setValue(settings.numMetatilesWide);
|
||||
ui->spinBox_WidthPixels->setValue(settings.numMetatilesWide * Metatile::pixelWidth());
|
||||
ui->checkBox_PrimaryTileset->setChecked(settings.usePrimaryTileset);
|
||||
ui->checkBox_SecondaryTileset->setChecked(settings.useSecondaryTileset);
|
||||
ui->checkBox_Placeholders->setChecked(settings.renderPlaceholders);
|
||||
if (m_transparencyButtons.value(settings.transparencyMode)) {
|
||||
m_transparencyButtons[settings.transparencyMode]->setChecked(true);
|
||||
}
|
||||
|
||||
// Build layer list from settings
|
||||
ui->listWidget_Layers->clear();
|
||||
for (auto it = settings.layerOrder.cbegin(); it != settings.layerOrder.cend(); it++) {
|
||||
int layerNum = it.key();
|
||||
bool enabled = it.value();
|
||||
|
||||
auto item = new QListWidgetItem(Metatile::getLayerName(layerNum));
|
||||
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsUserCheckable | Qt::ItemNeverHasChildren);
|
||||
item->setCheckState(enabled ? Qt::Checked : Qt::Unchecked);
|
||||
item->setData(Qt::UserRole, layerNum); // Save the original index to identify the layer
|
||||
ui->listWidget_Layers->addItem(item);
|
||||
}
|
||||
// Don't give extra unnecessary space to the list
|
||||
ui->listWidget_Layers->setFixedHeight(ui->listWidget_Layers->sizeHintForRow(0) * ui->listWidget_Layers->count() + 4);
|
||||
|
||||
updateTilesetUI();
|
||||
}
|
||||
|
||||
void MetatileImageExporter::reset() {
|
||||
applySettings({});
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MetatileImageExporter::saveImage() {
|
||||
// Ensure the image in the preview is up-to-date before exporting.
|
||||
updatePreview();
|
||||
|
||||
QString defaultFilename;
|
||||
if (m_layerOrder.length() == 1) {
|
||||
// Exporting a metatile layer image is an expected use case for Porytiles, which expects certain file names.
|
||||
// We can make the process a little easier by setting the default file name to those expected file names.
|
||||
static const QStringList layerFilenames = { "bottom", "middle", "top" };
|
||||
defaultFilename = (layerFilenames.at(m_layerOrder.constFirst()));
|
||||
} else {
|
||||
if (ui->checkBox_PrimaryTileset->isChecked() && m_primaryTileset) {
|
||||
defaultFilename.append(QString("%1_").arg(Tileset::stripPrefix(m_primaryTileset->name)));
|
||||
}
|
||||
if (ui->checkBox_SecondaryTileset->isChecked() && m_secondaryTileset) {
|
||||
defaultFilename.append(QString("%1_").arg(Tileset::stripPrefix(m_secondaryTileset->name)));
|
||||
}
|
||||
if (!m_layerOrder.isEmpty() && m_layerOrder != QList<int>({0,1,2})) {
|
||||
for (int i = m_layerOrder.length() - 1; i >= 0; i--) {
|
||||
defaultFilename.append(Metatile::getLayerName(m_layerOrder.at(i)));
|
||||
}
|
||||
defaultFilename.append("_");
|
||||
}
|
||||
defaultFilename.append("Metatiles");
|
||||
}
|
||||
|
||||
QString defaultFilepath = QString("%1/%2.png").arg(FileDialog::getDirectory()).arg(defaultFilename);
|
||||
QString filepath = FileDialog::getSaveFileName(this, windowTitle(), defaultFilepath, QStringLiteral("Image Files (*.png *.jpg *.bmp)"));
|
||||
if (!filepath.isEmpty()) {
|
||||
m_preview->pixmap().save(filepath);
|
||||
}
|
||||
}
|
||||
|
||||
void MetatileImageExporter::queuePreviewUpdate() {
|
||||
m_previewUpdateQueued = true;
|
||||
}
|
||||
|
||||
// For updating only when a change has been recorded.
|
||||
// Useful for something that might happen often, like an input widget losing focus.
|
||||
void MetatileImageExporter::tryUpdatePreview() {
|
||||
if (m_preview->pixmap().isNull() || m_previewUpdateQueued) {
|
||||
updatePreview();
|
||||
}
|
||||
}
|
||||
|
||||
void MetatileImageExporter::updatePreview() {
|
||||
copyRenderSettings();
|
||||
|
||||
int numMetatilesWide = ui->spinBox_WidthMetatiles->value();
|
||||
int metatileStart = ui->spinBox_MetatileStart->value();
|
||||
int numMetatiles = Util::roundUpToMultiple(ui->spinBox_MetatileEnd->value() - metatileStart + 1, numMetatilesWide);
|
||||
|
||||
m_layerOrder.clear();
|
||||
for (int i = 0; i < ui->listWidget_Layers->count(); i++) {
|
||||
auto item = ui->listWidget_Layers->item(i);
|
||||
if (item->checkState() == Qt::Checked) {
|
||||
int layerNum = item->data(Qt::UserRole).toInt();
|
||||
m_layerOrder.prepend(qBound(0, layerNum, 2));
|
||||
}
|
||||
}
|
||||
|
||||
QImage previewImage = getMetatileSheetImage(m_primaryTileset,
|
||||
m_secondaryTileset,
|
||||
metatileStart,
|
||||
numMetatiles,
|
||||
numMetatilesWide,
|
||||
m_layerOrder);
|
||||
m_preview->setPixmap(QPixmap::fromImage(previewImage));
|
||||
m_scene->setSceneRect(m_scene->itemsBoundingRect());
|
||||
m_previewUpdateQueued = false;
|
||||
|
||||
restoreRenderSettings();
|
||||
}
|
||||
|
||||
void MetatileImageExporter::validateMetatileStart() {
|
||||
const QSignalBlocker b(ui->spinBox_MetatileStart);
|
||||
ui->spinBox_MetatileStart->setValue(qMin(ui->spinBox_MetatileStart->value(),
|
||||
ui->spinBox_MetatileEnd->value()));
|
||||
}
|
||||
|
||||
void MetatileImageExporter::validateMetatileEnd() {
|
||||
const QSignalBlocker b(ui->spinBox_MetatileEnd);
|
||||
ui->spinBox_MetatileEnd->setValue(qMax(ui->spinBox_MetatileStart->value(),
|
||||
ui->spinBox_MetatileEnd->value()));
|
||||
}
|
||||
|
||||
uint16_t MetatileImageExporter::getExpectedMetatileStart() {
|
||||
if (ui->checkBox_PrimaryTileset->isChecked()) return 0;
|
||||
if (ui->checkBox_SecondaryTileset->isChecked()) return Project::getNumMetatilesPrimary();
|
||||
return ui->spinBox_MetatileStart->value();
|
||||
}
|
||||
|
||||
// TODO: Combining tilesets is not rendering the correct range of metatiles
|
||||
uint16_t MetatileImageExporter::getExpectedMetatileEnd() {
|
||||
if (ui->checkBox_SecondaryTileset->isChecked()) return Project::getNumMetatilesPrimary() + (m_secondaryTileset ? (m_secondaryTileset->numMetatiles() - 1) : 0);
|
||||
if (ui->checkBox_PrimaryTileset->isChecked()) return m_primaryTileset ? (m_primaryTileset->numMetatiles() - 1) : 0;
|
||||
return ui->spinBox_MetatileEnd->value();
|
||||
}
|
||||
|
||||
void MetatileImageExporter::updateMetatileRange() {
|
||||
const QSignalBlocker b_MetatileStart(ui->spinBox_MetatileStart);
|
||||
const QSignalBlocker b_MetatileEnd(ui->spinBox_MetatileEnd);
|
||||
ui->spinBox_MetatileStart->setValue(getExpectedMetatileStart());
|
||||
ui->spinBox_MetatileEnd->setValue(getExpectedMetatileEnd());
|
||||
}
|
||||
|
||||
void MetatileImageExporter::updateTilesetUI() {
|
||||
// Users can either specify which tileset(s) to render, or specify a range of metatiles, but not both.
|
||||
if (ui->checkBox_PrimaryTileset->isChecked() || ui->checkBox_SecondaryTileset->isChecked()) {
|
||||
updateMetatileRange();
|
||||
ui->groupBox_MetatileRange->setDisabled(true);
|
||||
} else {
|
||||
ui->groupBox_MetatileRange->setDisabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void MetatileImageExporter::syncPixelWidth() {
|
||||
const QSignalBlocker b(ui->spinBox_WidthPixels);
|
||||
ui->spinBox_WidthPixels->setValue(ui->spinBox_WidthMetatiles->value() * Metatile::pixelWidth());
|
||||
}
|
||||
|
||||
void MetatileImageExporter::syncMetatileWidth() {
|
||||
const QSignalBlocker b(ui->spinBox_WidthMetatiles);
|
||||
ui->spinBox_WidthMetatiles->setValue(Util::roundUpToMultiple(ui->spinBox_WidthPixels->value(), Metatile::pixelWidth()) / Metatile::pixelWidth());
|
||||
}
|
||||
|
||||
// These settings control some rendering behavior that make metatiles render accurately to their in-game appearance,
|
||||
// which may be undesirable when exporting metatile images for editing.
|
||||
// The settings are buried in getMetatileImage at the moment, to change them we'll temporarily overwrite them.
|
||||
void MetatileImageExporter::copyRenderSettings() {
|
||||
m_savedConfig.transparencyColor = projectConfig.transparencyColor;
|
||||
m_savedConfig.unusedTileNormal = projectConfig.unusedTileNormal;
|
||||
m_savedConfig.unusedTileCovered = projectConfig.unusedTileCovered;
|
||||
m_savedConfig.unusedTileSplit = projectConfig.unusedTileSplit;
|
||||
|
||||
if (ui->radioButton_TransparencyNormal->isChecked()) {
|
||||
projectConfig.transparencyColor = QColor(Qt::transparent);
|
||||
} else if (ui->radioButton_TransparencyBlack->isChecked()) {
|
||||
projectConfig.transparencyColor = QColor(Qt::black);
|
||||
} else {
|
||||
projectConfig.transparencyColor = QColor();
|
||||
}
|
||||
|
||||
if (!ui->checkBox_Placeholders->isChecked()) {
|
||||
projectConfig.unusedTileNormal = 0;
|
||||
projectConfig.unusedTileCovered = 0;
|
||||
projectConfig.unusedTileSplit = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MetatileImageExporter::restoreRenderSettings() {
|
||||
projectConfig.transparencyColor = m_savedConfig.transparencyColor;
|
||||
projectConfig.unusedTileNormal = m_savedConfig.unusedTileNormal;
|
||||
projectConfig.unusedTileCovered = m_savedConfig.unusedTileCovered;
|
||||
projectConfig.unusedTileSplit = m_savedConfig.unusedTileSplit;
|
||||
}
|
||||
|
|
@ -148,6 +148,6 @@ void MetatileLayersItem::clearLastHoveredCoords() {
|
|||
QPoint MetatileLayersItem::getBoundedPos(const QPointF &pos) {
|
||||
int x = static_cast<int>(pos.x()) / this->cellWidth;
|
||||
int y = static_cast<int>(pos.y()) / this->cellHeight;
|
||||
return QPoint( qMax(0, qMin(x, this->maxSelectionWidth - 1)),
|
||||
qMax(0, qMin(y, this->maxSelectionHeight - 1)) );
|
||||
return QPoint(qBound(0, x, this->maxSelectionWidth - 1),
|
||||
qBound(0, y, this->maxSelectionHeight - 1));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,28 +15,7 @@ int MetatileSelector::numPrimaryMetatilesRounded() const {
|
|||
}
|
||||
|
||||
void MetatileSelector::updateBasePixmap() {
|
||||
int primaryLength = this->numPrimaryMetatilesRounded();
|
||||
int length_ = primaryLength + this->secondaryTileset()->numMetatiles();
|
||||
int height_ = length_ / this->numMetatilesWide;
|
||||
if (length_ % this->numMetatilesWide != 0) {
|
||||
height_++;
|
||||
}
|
||||
QImage image(this->numMetatilesWide * this->cellWidth, height_ * this->cellHeight, QImage::Format_RGBA8888);
|
||||
image.fill(Qt::magenta);
|
||||
QPainter painter(&image);
|
||||
for (int i = 0; i < length_; i++) {
|
||||
int metatileId = i;
|
||||
if (i >= primaryLength) {
|
||||
metatileId += Project::getNumMetatilesPrimary() - primaryLength;
|
||||
}
|
||||
QImage metatile_image = getMetatileImage(metatileId, this->layout);
|
||||
int map_y = i / this->numMetatilesWide;
|
||||
int map_x = i % this->numMetatilesWide;
|
||||
QPoint metatile_origin = QPoint(map_x * this->cellWidth, map_y * this->cellHeight);
|
||||
painter.drawImage(metatile_origin, metatile_image);
|
||||
}
|
||||
painter.end();
|
||||
this->basePixmap = QPixmap::fromImage(image);
|
||||
this->basePixmap = QPixmap::fromImage(getMetatileSheetImage(this->layout, this->numMetatilesWide));
|
||||
}
|
||||
|
||||
void MetatileSelector::draw() {
|
||||
|
|
|
|||
|
|
@ -114,8 +114,8 @@ void ResizableRect::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
|||
}
|
||||
|
||||
void ResizableRect::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
|
||||
int dx = Util::roundUp(event->scenePos().x() - this->clickedPos.x(), 16);
|
||||
int dy = Util::roundUp(event->scenePos().y() - this->clickedPos.y(), 16);
|
||||
int dx = Util::roundUpToMultiple(event->scenePos().x() - this->clickedPos.x(), 16);
|
||||
int dy = Util::roundUpToMultiple(event->scenePos().y() - this->clickedPos.y(), 16);
|
||||
|
||||
QRect resizedRect = this->clickedRect;
|
||||
|
||||
|
|
|
|||
|
|
@ -475,10 +475,11 @@ void ProjectSettingsEditor::refresh() {
|
|||
ui->checkBox_PreserveMatchingOnlyData->setChecked(projectConfig.preserveMatchingOnlyData);
|
||||
|
||||
// Radio buttons
|
||||
if (projectConfig.setTransparentPixelsBlack)
|
||||
// TODO: Replace
|
||||
/*if (projectConfig.setTransparentPixelsBlack)
|
||||
ui->radioButton_RenderBlack->setChecked(true);
|
||||
else
|
||||
ui->radioButton_RenderFirstPalColor->setChecked(true);
|
||||
ui->radioButton_RenderFirstPalColor->setChecked(true);*/
|
||||
|
||||
// Set spin box values
|
||||
ui->spinBox_Elevation->setValue(projectConfig.defaultElevation);
|
||||
|
|
@ -574,7 +575,7 @@ void ProjectSettingsEditor::save() {
|
|||
projectConfig.tilesetsHaveCallback = ui->checkBox_OutputCallback->isChecked();
|
||||
projectConfig.tilesetsHaveIsCompressed = ui->checkBox_OutputIsCompressed->isChecked();
|
||||
porymapConfig.warpBehaviorWarningDisabled = ui->checkBox_DisableWarning->isChecked();
|
||||
projectConfig.setTransparentPixelsBlack = ui->radioButton_RenderBlack->isChecked();
|
||||
//projectConfig.setTransparentPixelsBlack = ui->radioButton_RenderBlack->isChecked(); // TODO
|
||||
projectConfig.preserveMatchingOnlyData = ui->checkBox_PreserveMatchingOnlyData->isChecked();
|
||||
|
||||
// Save spin box settings
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ void BoundedPixmapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem
|
|||
QVariant BoundedPixmapItem::itemChange(GraphicsItemChange change, const QVariant &value) {
|
||||
if (change == ItemPositionChange && scene()) {
|
||||
QPointF newPos = value.toPointF();
|
||||
return QPointF(Util::roundUp(newPos.x(), 16), Util::roundUp(newPos.y(), 16));
|
||||
return QPointF(Util::roundUpToMultiple(newPos.x(), 16), Util::roundUpToMultiple(newPos.y(), 16));
|
||||
}
|
||||
else
|
||||
return QGraphicsItem::itemChange(change, value);
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ void SelectablePixmapItem::select(int x, int y, int width, int height)
|
|||
{
|
||||
this->selectionInitialX = x;
|
||||
this->selectionInitialY = y;
|
||||
this->selectionOffsetX = qMax(0, qMin(width, this->maxSelectionWidth));
|
||||
this->selectionOffsetY = qMax(0, qMin(height, this->maxSelectionHeight));
|
||||
this->selectionOffsetX = qBound(0, width, this->maxSelectionWidth);
|
||||
this->selectionOffsetY = qBound(0, height, this->maxSelectionHeight);
|
||||
this->draw();
|
||||
emit this->selectionChanged(x, y, width, height);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,8 +24,10 @@ TilesetEditor::TilesetEditor(Project *project, Layout *layout, QWidget *parent)
|
|||
hasUnsavedChanges(false)
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
setTilesets(this->layout->tileset_primary_label, this->layout->tileset_secondary_label);
|
||||
ui->setupUi(this);
|
||||
|
||||
setTilesets(this->layout->tileset_primary_label, this->layout->tileset_secondary_label);
|
||||
|
||||
connect(ui->checkBox_xFlip, &QCheckBox::toggled, this, &TilesetEditor::setXFlip);
|
||||
connect(ui->checkBox_yFlip, &QCheckBox::toggled, this, &TilesetEditor::setYFlip);
|
||||
|
||||
|
|
@ -35,6 +37,17 @@ TilesetEditor::TilesetEditor(Project *project, Layout *layout, QWidget *parent)
|
|||
|
||||
connect(ui->actionSave_Tileset, &QAction::triggered, this, &TilesetEditor::save);
|
||||
|
||||
connect(ui->actionImport_Primary_Tiles_Image, &QAction::triggered, [this] { importTilesetTiles(this->primaryTileset); });
|
||||
connect(ui->actionImport_Secondary_Tiles_Image, &QAction::triggered, [this] { importTilesetTiles(this->secondaryTileset); });
|
||||
|
||||
connect(ui->actionImport_Primary_AdvanceMap_Metatiles, &QAction::triggered, [this] { importAdvanceMapMetatiles(this->primaryTileset); });
|
||||
connect(ui->actionImport_Secondary_AdvanceMap_Metatiles, &QAction::triggered, [this] { importAdvanceMapMetatiles(this->secondaryTileset); });
|
||||
|
||||
connect(ui->actionExport_Primary_Tiles_Image, &QAction::triggered, [this] { exportTilesImage(this->primaryTileset); });
|
||||
connect(ui->actionExport_Secondary_Tiles_Image, &QAction::triggered, [this] { exportTilesImage(this->secondaryTileset); });
|
||||
|
||||
connect(ui->actionExport_Metatiles_Image, &QAction::triggered, [this] { exportMetatilesImage(); });
|
||||
|
||||
ui->actionShow_Tileset_Divider->setChecked(porymapConfig.showTilesetEditorDivider);
|
||||
ui->actionShow_Raw_Metatile_Attributes->setChecked(porymapConfig.showTilesetEditorRawAttributes);
|
||||
|
||||
|
|
@ -74,6 +87,7 @@ TilesetEditor::~TilesetEditor()
|
|||
delete selectedTileScene;
|
||||
delete metatileLayersScene;
|
||||
delete copiedMetatile;
|
||||
delete metatileImageExportSettings;
|
||||
this->metatileHistory.clear();
|
||||
}
|
||||
|
||||
|
|
@ -694,17 +708,8 @@ bool TilesetEditor::save() {
|
|||
return success;
|
||||
}
|
||||
|
||||
void TilesetEditor::on_actionImport_Primary_Tiles_triggered()
|
||||
{
|
||||
this->importTilesetTiles(this->primaryTileset, true);
|
||||
}
|
||||
|
||||
void TilesetEditor::on_actionImport_Secondary_Tiles_triggered()
|
||||
{
|
||||
this->importTilesetTiles(this->secondaryTileset, false);
|
||||
}
|
||||
|
||||
void TilesetEditor::importTilesetTiles(Tileset *tileset, bool primary) {
|
||||
void TilesetEditor::importTilesetTiles(Tileset *tileset) {
|
||||
bool primary = !tileset->is_secondary;
|
||||
QString descriptor = primary ? "primary" : "secondary";
|
||||
QString descriptorCaps = primary ? "Primary" : "Secondary";
|
||||
|
||||
|
|
@ -968,62 +973,27 @@ void TilesetEditor::pasteMetatile(const Metatile * toPaste, QString newLabel)
|
|||
this->commitMetatileAndLabelChange(prevMetatile, prevLabel);
|
||||
}
|
||||
|
||||
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(FileDialog::getDirectory()).arg(defaultName);
|
||||
QString filepath = FileDialog::getSaveFileName(this, "Export Primary Tiles Image", defaultFilepath, "Image Files (*.png)");
|
||||
void TilesetEditor::exportTilesImage(Tileset *tileset) {
|
||||
bool primary = !tileset->is_secondary;
|
||||
QString defaultFilepath = QString("%1/%2_Tiles_Pal%3.png").arg(FileDialog::getDirectory()).arg(tileset->name).arg(this->paletteId);
|
||||
QString filepath = FileDialog::getSaveFileName(this, QString("Export %1 Tiles Image").arg(primary ? "Primary" : "Secondary"), defaultFilepath, "Image Files (*.png)");
|
||||
if (!filepath.isEmpty()) {
|
||||
QImage image = this->tileSelector->buildPrimaryTilesIndexedImage();
|
||||
QImage image = primary ? this->tileSelector->buildPrimaryTilesIndexedImage() : this->tileSelector->buildSecondaryTilesIndexedImage();
|
||||
exportIndexed4BPPPng(image, filepath);
|
||||
}
|
||||
}
|
||||
|
||||
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(FileDialog::getDirectory()).arg(defaultName);
|
||||
QString filepath = FileDialog::getSaveFileName(this, "Export Secondary Tiles Image", defaultFilepath, "Image Files (*.png)");
|
||||
if (!filepath.isEmpty()) {
|
||||
QImage image = this->tileSelector->buildSecondaryTilesIndexedImage();
|
||||
exportIndexed4BPPPng(image, filepath);
|
||||
// There are many more options for exporting metatile images than tile images, so we open a separate dialog to ask the user for settings.
|
||||
void TilesetEditor::exportMetatilesImage() {
|
||||
if (!this->metatileImageExportSettings) {
|
||||
this->metatileImageExportSettings = new MetatileImageExporter::Settings;
|
||||
}
|
||||
auto dialog = new MetatileImageExporter(this, this->primaryTileset, this->secondaryTileset, this->metatileImageExportSettings);
|
||||
dialog->open();
|
||||
}
|
||||
|
||||
void TilesetEditor::on_actionExport_Primary_Metatiles_Image_triggered()
|
||||
{
|
||||
QString defaultName = QString("%1_Metatiles").arg(this->primaryTileset->name);
|
||||
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()) {
|
||||
QImage image = this->metatileSelector->buildPrimaryMetatilesImage();
|
||||
image.save(filepath, "PNG");
|
||||
}
|
||||
}
|
||||
|
||||
void TilesetEditor::on_actionExport_Secondary_Metatiles_Image_triggered()
|
||||
{
|
||||
QString defaultName = QString("%1_Metatiles").arg(this->secondaryTileset->name);
|
||||
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()) {
|
||||
QImage image = this->metatileSelector->buildSecondaryMetatilesImage();
|
||||
image.save(filepath, "PNG");
|
||||
}
|
||||
}
|
||||
|
||||
void TilesetEditor::on_actionImport_Primary_Metatiles_triggered()
|
||||
{
|
||||
this->importTilesetMetatiles(this->primaryTileset, true);
|
||||
}
|
||||
|
||||
void TilesetEditor::on_actionImport_Secondary_Metatiles_triggered()
|
||||
{
|
||||
this->importTilesetMetatiles(this->secondaryTileset, false);
|
||||
}
|
||||
|
||||
void TilesetEditor::importTilesetMetatiles(Tileset *tileset, bool primary)
|
||||
{
|
||||
void TilesetEditor::importAdvanceMapMetatiles(Tileset *tileset) {
|
||||
bool primary = !tileset->is_secondary;
|
||||
QString descriptorCaps = primary ? "Primary" : "Secondary";
|
||||
|
||||
QString filepath = FileDialog::getOpenFileName(this, QString("Import %1 Tileset Metatiles from Advance Map 1.92").arg(descriptorCaps), "", "Advance Map 1.92 Metatile Files (*.bvd)");
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include <QPainter>
|
||||
|
||||
TilesetEditorMetatileSelector::TilesetEditorMetatileSelector(Tileset *primaryTileset, Tileset *secondaryTileset, Layout *layout)
|
||||
: SelectablePixmapItem(16, 16, 1, 1) {
|
||||
: SelectablePixmapItem(32, 32, 1, 1) {
|
||||
this->primaryTileset = primaryTileset;
|
||||
this->secondaryTileset = secondaryTileset;
|
||||
this->numMetatilesWide = 8;
|
||||
|
|
@ -31,48 +31,6 @@ int TilesetEditorMetatileSelector::numPrimaryMetatilesRounded() const {
|
|||
return ceil((double)this->primaryTileset->numMetatiles() / this->numMetatilesWide) * this->numMetatilesWide;
|
||||
}
|
||||
|
||||
QImage TilesetEditorMetatileSelector::buildAllMetatilesImage() {
|
||||
return this->buildImage(0, this->numPrimaryMetatilesRounded() + this->secondaryTileset->numMetatiles());
|
||||
}
|
||||
|
||||
QImage TilesetEditorMetatileSelector::buildPrimaryMetatilesImage() {
|
||||
return this->buildImage(0, this->primaryTileset->numMetatiles());
|
||||
}
|
||||
|
||||
QImage TilesetEditorMetatileSelector::buildSecondaryMetatilesImage() {
|
||||
return this->buildImage(Project::getNumMetatilesPrimary(), this->secondaryTileset->numMetatiles());
|
||||
}
|
||||
|
||||
QImage TilesetEditorMetatileSelector::buildImage(int metatileIdStart, int numMetatiles) {
|
||||
int numMetatilesHigh = this->numRows(numMetatiles);
|
||||
int numPrimary = this->numPrimaryMetatilesRounded();
|
||||
int maxPrimary = Project::getNumMetatilesPrimary();
|
||||
bool includesPrimary = metatileIdStart < maxPrimary;
|
||||
|
||||
QImage image(this->numMetatilesWide * this->cellWidth, numMetatilesHigh * this->cellHeight, QImage::Format_RGBA8888);
|
||||
image.fill(Qt::magenta);
|
||||
QPainter painter(&image);
|
||||
for (int i = 0; i < numMetatiles; i++) {
|
||||
int metatileId = i + metatileIdStart;
|
||||
if (includesPrimary && metatileId >= numPrimary)
|
||||
metatileId += maxPrimary - numPrimary; // Skip over unused region of primary tileset
|
||||
QImage metatile_image = getMetatileImage(
|
||||
metatileId,
|
||||
this->primaryTileset,
|
||||
this->secondaryTileset,
|
||||
this->layout->metatileLayerOrder(),
|
||||
this->layout->metatileLayerOpacity(),
|
||||
true)
|
||||
.scaled(this->cellWidth, this->cellHeight);
|
||||
int map_y = i / this->numMetatilesWide;
|
||||
int map_x = i % this->numMetatilesWide;
|
||||
QPoint metatile_origin = QPoint(map_x * this->cellWidth, map_y * this->cellHeight);
|
||||
painter.drawImage(metatile_origin, metatile_image);
|
||||
}
|
||||
painter.end();
|
||||
return image;
|
||||
}
|
||||
|
||||
void TilesetEditorMetatileSelector::drawMetatile(uint16_t metatileId) {
|
||||
QPoint pos = getMetatileIdCoords(metatileId);
|
||||
|
||||
|
|
@ -97,7 +55,15 @@ void TilesetEditorMetatileSelector::drawSelectedMetatile() {
|
|||
}
|
||||
|
||||
void TilesetEditorMetatileSelector::updateBasePixmap() {
|
||||
this->baseImage = buildAllMetatilesImage();
|
||||
this->baseImage = getMetatileSheetImage(this->primaryTileset,
|
||||
this->secondaryTileset,
|
||||
0,
|
||||
this->numPrimaryMetatilesRounded() + this->secondaryTileset->numMetatiles(),
|
||||
this->numMetatilesWide,
|
||||
this->layout->metatileLayerOrder(),
|
||||
this->layout->metatileLayerOpacity(),
|
||||
QSize(this->cellWidth, this->cellHeight),
|
||||
true);
|
||||
this->basePixmap = QPixmap::fromImage(this->baseImage);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,24 +2,24 @@
|
|||
#include <QWheelEvent>
|
||||
|
||||
UIntSpinBox::UIntSpinBox(QWidget *parent)
|
||||
: QAbstractSpinBox(parent)
|
||||
: QAbstractSpinBox(parent),
|
||||
m_minimum(0),
|
||||
m_maximum(99),
|
||||
m_value(m_minimum),
|
||||
m_singleStep(1),
|
||||
m_displayIntegerBase(10),
|
||||
m_hasPadding(false),
|
||||
m_numChars(2)
|
||||
{
|
||||
// Don't let scrolling hijack focus.
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
|
||||
m_minimum = 0;
|
||||
m_maximum = 99;
|
||||
m_value = m_minimum;
|
||||
m_displayIntegerBase = 10;
|
||||
m_numChars = 2;
|
||||
m_hasPadding = false;
|
||||
|
||||
this->updateEdit();
|
||||
connect(lineEdit(), SIGNAL(textEdited(QString)), this, SLOT(onEditFinished()));
|
||||
};
|
||||
|
||||
void UIntSpinBox::setValue(uint32_t val) {
|
||||
val = qMax(m_minimum, qMin(m_maximum, val));
|
||||
val = qBound(m_minimum, val, m_maximum);
|
||||
if (m_value != val) {
|
||||
m_value = val;
|
||||
emit valueChanged(m_value);
|
||||
|
|
@ -69,6 +69,12 @@ void UIntSpinBox::setRange(uint32_t min, uint32_t max) {
|
|||
this->updateEdit();
|
||||
}
|
||||
|
||||
void UIntSpinBox::setSingleStep(uint32_t val) {
|
||||
if (m_singleStep != val) {
|
||||
m_singleStep = val;
|
||||
}
|
||||
}
|
||||
|
||||
void UIntSpinBox::setPrefix(const QString &prefix) {
|
||||
if (m_prefix != prefix) {
|
||||
m_prefix = prefix;
|
||||
|
|
@ -127,6 +133,7 @@ void UIntSpinBox::onEditFinished() {
|
|||
}
|
||||
|
||||
void UIntSpinBox::stepBy(int steps) {
|
||||
steps *= m_singleStep;
|
||||
auto newValue = m_value;
|
||||
if (steps < 0 && newValue + steps > newValue) {
|
||||
newValue = 0;
|
||||
|
|
|
|||
|
|
@ -367,7 +367,7 @@ QChart* WildMonChart::createLevelDistributionChart() {
|
|||
series->attachAxis(axisY);
|
||||
|
||||
// We round the y-axis max up to a multiple of 5.
|
||||
axisY->setMax(Util::roundUp(qCeil(axisY->max()), 5));
|
||||
axisY->setMax(Util::roundUpToMultiple(qCeil(axisY->max()), 5));
|
||||
|
||||
return chart;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user