mirror of
https://github.com/huderlem/porymap.git
synced 2026-04-18 15:47:31 -05:00
Merge pull request #706 from GriffinRichards/tileset-types
Read encounter/terrain types from the project
This commit is contained in:
commit
ec79ee4185
|
|
@ -6,12 +6,12 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>727</width>
|
||||
<height>700</height>
|
||||
<width>733</width>
|
||||
<height>784</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::ClickFocus</enum>
|
||||
<enum>Qt::FocusPolicy::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::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="childrenCollapsible">
|
||||
<bool>false</bool>
|
||||
|
|
@ -34,10 +34,10 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
<enum>QFrame::Shadow::Plain</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="leftMargin">
|
||||
|
|
@ -58,15 +58,15 @@
|
|||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||
<set>Qt::AlignmentFlag::AlignHCenter|Qt::AlignmentFlag::AlignTop</set>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents_Metatiles">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>223</width>
|
||||
<height>593</height>
|
||||
<width>239</width>
|
||||
<height>659</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
|
|
@ -88,17 +88,17 @@
|
|||
<item row="0" column="0">
|
||||
<widget class="NoScrollGraphicsView" name="graphicsView_Metatiles">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -121,7 +121,7 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -129,10 +129,10 @@
|
|||
</widget>
|
||||
<widget class="QFrame" name="frame_Editing">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
|
|
@ -162,14 +162,14 @@
|
|||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMinimumSize</enum>
|
||||
<enum>QLayout::SizeConstraint::SetMinimumSize</enum>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
|
|
@ -195,6 +195,70 @@
|
|||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="15" column="0" colspan="4">
|
||||
<widget class="QLineEdit" name="lineEdit_metatileLabel">
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="3">
|
||||
<widget class="NoScrollComboBox" name="comboBox_layerType">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>185</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0" colspan="5">
|
||||
<widget class="QLabel" name="label_metatileLabel">
|
||||
<property name="text">
|
||||
<string>Metatile Label (Optional)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_BottomTop">
|
||||
<property name="text">
|
||||
<string>Bottom/Top</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0" colspan="5">
|
||||
<widget class="QLabel" name="label_terrainType">
|
||||
<property name="text">
|
||||
<string>Terrain Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="3">
|
||||
<widget class="QLabel" name="label_layerType">
|
||||
<property name="text">
|
||||
<string>Layer Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="5">
|
||||
<widget class="NoScrollComboBox" name="comboBox_metatileBehaviors">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertPolicy::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGraphicsView" name="graphicsView_metatileLayers">
|
||||
<property name="sizePolicy">
|
||||
|
|
@ -216,10 +280,10 @@
|
|||
</size>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -231,17 +295,23 @@
|
|||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertPolicy::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0">
|
||||
<spacer name="verticalSpacer_7">
|
||||
<item row="1" column="1">
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Policy::Maximum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>1</height>
|
||||
<width>10</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
|
|
@ -254,16 +324,33 @@
|
|||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0" colspan="5">
|
||||
<widget class="QLabel" name="label_metatileLabel">
|
||||
<property name="text">
|
||||
<string>Metatile Label (Optional)</string>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertPolicy::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="4">
|
||||
<item row="2" column="0" colspan="5">
|
||||
<widget class="QLabel" name="label_metatileBehavior">
|
||||
<property name="text">
|
||||
<string>Metatile Behavior</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0" colspan="5">
|
||||
<widget class="QLabel" name="label_rawAttributesValue">
|
||||
<property name="text">
|
||||
<string>Raw Attributes Value</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="5">
|
||||
<widget class="QLabel" name="label_encounterType">
|
||||
<property name="text">
|
||||
<string>Encounter Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="4">
|
||||
<widget class="QToolButton" name="copyButton_metatileLabel">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Copies the full metatile label to the clipboard.</p></body></html></string>
|
||||
|
|
@ -277,89 +364,21 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="3">
|
||||
<widget class="NoScrollComboBox" name="comboBox_layerType">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>185</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="5">
|
||||
<widget class="NoScrollComboBox" name="comboBox_metatileBehaviors">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="3">
|
||||
<widget class="QLabel" name="label_layerType">
|
||||
<property name="text">
|
||||
<string>Layer Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="0" colspan="4">
|
||||
<widget class="QLineEdit" name="lineEdit_metatileLabel">
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="5">
|
||||
<widget class="QLabel" name="label_metatileBehavior">
|
||||
<property name="text">
|
||||
<string>Metatile Behavior</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<item row="16" column="0">
|
||||
<spacer name="verticalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Maximum</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>20</height>
|
||||
<width>20</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="5">
|
||||
<widget class="QLabel" name="label_encounterType">
|
||||
<property name="text">
|
||||
<string>Encounter Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0" colspan="5">
|
||||
<widget class="QLabel" name="label_terrainType">
|
||||
<property name="text">
|
||||
<string>Terrain Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_BottomTop">
|
||||
<property name="text">
|
||||
<string>Bottom/Top</string>
|
||||
</property>
|
||||
</widget>
|
||||
<item row="13" column="0" colspan="5">
|
||||
<widget class="UIntHexSpinBox" name="spinBox_rawAttributesValue"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
|
@ -399,7 +418,7 @@
|
|||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_xFlip">
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
<enum>Qt::LayoutDirection::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
|
|
@ -423,10 +442,10 @@
|
|||
<item row="3" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
<enum>QSizePolicy::Policy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -451,10 +470,10 @@
|
|||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
<enum>QFrame::Shadow::Plain</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="leftMargin">
|
||||
|
|
@ -497,13 +516,13 @@
|
|||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
<enum>QFrame::Shape::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -513,7 +532,7 @@
|
|||
<item row="6" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -535,15 +554,15 @@
|
|||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignHCenter|Qt::AlignTop</set>
|
||||
<set>Qt::AlignmentFlag::AlignHCenter|Qt::AlignmentFlag::AlignTop</set>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents_Tiles">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>455</width>
|
||||
<height>232</height>
|
||||
<width>445</width>
|
||||
<height>237</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
|
|
@ -562,17 +581,17 @@
|
|||
<item row="0" column="0">
|
||||
<widget class="NoScrollGraphicsView" name="graphicsView_Tiles">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -589,7 +608,7 @@
|
|||
<item>
|
||||
<widget class="QSlider" name="horizontalSlider_TilesZoom">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -604,8 +623,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>727</width>
|
||||
<height>22</height>
|
||||
<width>733</width>
|
||||
<height>37</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
|
|
@ -648,6 +667,7 @@
|
|||
<addaction name="actionLayer_Grid"/>
|
||||
<addaction name="actionMetatile_Grid"/>
|
||||
<addaction name="actionShow_Tileset_Divider"/>
|
||||
<addaction name="actionShow_Raw_Metatile_Attributes"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionShow_Counts"/>
|
||||
<addaction name="actionShow_Unused"/>
|
||||
|
|
@ -808,6 +828,14 @@
|
|||
<string>Show Tileset Divider</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionShow_Raw_Metatile_Attributes">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Raw Metatile Attributes</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
|
@ -820,6 +848,16 @@
|
|||
<extends>QGraphicsView</extends>
|
||||
<header>mapview.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>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../resources/images.qrc"/>
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ public:
|
|||
this->showTilesetEditorMetatileGrid = false;
|
||||
this->showTilesetEditorLayerGrid = true;
|
||||
this->showTilesetEditorDivider = false;
|
||||
this->showTilesetEditorRawAttributes = false;
|
||||
this->monitorFiles = true;
|
||||
this->tilesetCheckerboardFill = true;
|
||||
this->newMapHeaderSectionExpanded = false;
|
||||
|
|
@ -132,6 +133,7 @@ public:
|
|||
bool showTilesetEditorMetatileGrid;
|
||||
bool showTilesetEditorLayerGrid;
|
||||
bool showTilesetEditorDivider;
|
||||
bool showTilesetEditorRawAttributes;
|
||||
bool monitorFiles;
|
||||
bool tilesetCheckerboardFill;
|
||||
bool newMapHeaderSectionExpanded;
|
||||
|
|
@ -246,6 +248,8 @@ enum ProjectIdentifier {
|
|||
regex_sign_facing_directions,
|
||||
regex_trainer_types,
|
||||
regex_music,
|
||||
regex_encounter_types,
|
||||
regex_terrain_types,
|
||||
regex_gbapal,
|
||||
regex_bpp,
|
||||
pals_output_extension,
|
||||
|
|
|
|||
|
|
@ -11,27 +11,6 @@
|
|||
|
||||
class Project;
|
||||
|
||||
enum {
|
||||
METATILE_LAYER_MIDDLE_TOP,
|
||||
METATILE_LAYER_BOTTOM_MIDDLE,
|
||||
METATILE_LAYER_BOTTOM_TOP,
|
||||
NUM_METATILE_LAYER_TYPES
|
||||
};
|
||||
|
||||
enum {
|
||||
ENCOUNTER_NONE,
|
||||
ENCOUNTER_LAND,
|
||||
ENCOUNTER_WATER,
|
||||
NUM_METATILE_ENCOUNTER_TYPES
|
||||
};
|
||||
|
||||
enum {
|
||||
TERRAIN_NONE,
|
||||
TERRAIN_GRASS,
|
||||
TERRAIN_WATER,
|
||||
TERRAIN_WATERFALL,
|
||||
NUM_METATILE_TERRAIN_TYPES
|
||||
};
|
||||
|
||||
class Metatile
|
||||
{
|
||||
|
|
@ -41,6 +20,13 @@ public:
|
|||
Metatile &operator=(const Metatile &other) = default;
|
||||
Metatile(const int numTiles);
|
||||
|
||||
enum LayerType {
|
||||
Normal,
|
||||
Covered,
|
||||
Split,
|
||||
Count
|
||||
};
|
||||
|
||||
enum Attr {
|
||||
Behavior,
|
||||
TerrainType,
|
||||
|
|
|
|||
|
|
@ -45,7 +45,8 @@ public:
|
|||
ParseUtil();
|
||||
void set_root(const QString &dir);
|
||||
static QString readTextFile(const QString &path, QString *error = nullptr);
|
||||
void invalidateTextFile(const QString &path);
|
||||
bool cacheFile(const QString &path, QString *error = nullptr);
|
||||
void clearFileCache() { this->fileCache.clear(); }
|
||||
static int textFileLineCount(const QString &path);
|
||||
QList<QStringList> parseAsm(const QString &filename);
|
||||
QStringList readCArray(const QString &filename, const QString &label);
|
||||
|
|
@ -87,6 +88,7 @@ private:
|
|||
QString text;
|
||||
QString file;
|
||||
QString curDefine;
|
||||
QHash<QString, QString> fileCache;
|
||||
QHash<QString, QStringList> errorMap;
|
||||
int evaluateDefine(const QString&, const QString &, QMap<QString, int>*, QMap<QString, QString>*);
|
||||
QList<Token> tokenizeExpression(QString, QMap<QString, int>*, QMap<QString, QString>*);
|
||||
|
|
@ -105,6 +107,8 @@ private:
|
|||
QMap<QString, int> evaluateCDefines(const QString &filename, const QSet<QString> &filterList, bool useRegex, QString *error);
|
||||
bool defineNameMatchesFilter(const QString &name, const QSet<QString> &filterList) const;
|
||||
bool defineNameMatchesFilter(const QString &name, const QSet<QRegularExpression> &filterList) const;
|
||||
QString loadTextFile(const QString &path, QString *error = nullptr);
|
||||
QString pathWithRoot(const QString &path);
|
||||
|
||||
static const QRegularExpression re_incScriptLabel;
|
||||
static const QRegularExpression re_globalIncScriptLabel;
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ public:
|
|||
QStringList globalScriptLabels;
|
||||
QStringList mapSectionIdNamesSaveOrder;
|
||||
QStringList mapSectionIdNames;
|
||||
QMap<uint32_t, QString> encounterTypeToName;
|
||||
QMap<uint32_t, QString> terrainTypeToName;
|
||||
QMap<QString, MapSectionEntry> regionMapEntries;
|
||||
QMap<QString, QMap<QString, uint16_t>> metatileLabelsMap;
|
||||
QMap<QString, uint16_t> unusedMetatileLabels;
|
||||
|
|
@ -295,6 +297,7 @@ private:
|
|||
|
||||
void ignoreWatchedFileTemporarily(QString filepath);
|
||||
void recordFileChange(const QString &filepath);
|
||||
void resetFileCache();
|
||||
|
||||
QString findSpeciesIconPath(const QStringList &names) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "tileseteditortileselector.h"
|
||||
#include "metatilelayersitem.h"
|
||||
|
||||
class NoScrollComboBox;
|
||||
class Layout;
|
||||
|
||||
namespace Ui {
|
||||
|
|
@ -92,19 +93,10 @@ private slots:
|
|||
void on_actionShow_Tileset_Divider_triggered(bool checked);
|
||||
|
||||
void on_actionUndo_triggered();
|
||||
|
||||
void on_actionRedo_triggered();
|
||||
|
||||
void on_comboBox_metatileBehaviors_currentTextChanged(const QString &arg1);
|
||||
|
||||
void on_lineEdit_metatileLabel_editingFinished();
|
||||
|
||||
void on_comboBox_layerType_activated(int arg1);
|
||||
|
||||
void on_comboBox_encounterType_activated(int arg1);
|
||||
|
||||
void on_comboBox_terrainType_activated(int arg1);
|
||||
|
||||
void on_actionExport_Primary_Tiles_Image_triggered();
|
||||
void on_actionExport_Secondary_Tiles_Image_triggered();
|
||||
void on_actionExport_Primary_Metatiles_Image_triggered();
|
||||
|
|
@ -122,7 +114,7 @@ private slots:
|
|||
void on_horizontalSlider_TilesZoom_valueChanged(int value);
|
||||
|
||||
private:
|
||||
void setAttributesUi();
|
||||
void initAttributesUi();
|
||||
void initMetatileSelector();
|
||||
void initTileSelector();
|
||||
void initSelectedTileItem();
|
||||
|
|
@ -148,6 +140,15 @@ private:
|
|||
bool replaceMetatile(uint16_t metatileId, const Metatile * src, QString label);
|
||||
void commitMetatileChange(Metatile * prevMetatile);
|
||||
void commitMetatileAndLabelChange(Metatile * prevMetatile, QString prevLabel);
|
||||
uint32_t attributeNameToValue(Metatile::Attr attribute, const QString &text, bool *ok);
|
||||
void commitAttributeFromComboBox(Metatile::Attr attribute, NoScrollComboBox *combo);
|
||||
void onRawAttributesEdited();
|
||||
void refreshMetatileAttributes();
|
||||
void commitMetatileBehavior();
|
||||
void commitEncounterType();
|
||||
void commitTerrainType();
|
||||
void commitLayerType();
|
||||
void setRawAttributesVisible(bool visible);
|
||||
|
||||
Ui::TilesetEditor *ui;
|
||||
History<MetatileHistoryItem*> metatileHistory;
|
||||
|
|
|
|||
|
|
@ -125,6 +125,8 @@ const QMap<ProjectIdentifier, QPair<QString, QString>> ProjectConfig::defaultIde
|
|||
{ProjectIdentifier::regex_sign_facing_directions, {"regex_sign_facing_directions", "\\bBG_EVENT_PLAYER_FACING_"}},
|
||||
{ProjectIdentifier::regex_trainer_types, {"regex_trainer_types", "\\bTRAINER_TYPE_"}},
|
||||
{ProjectIdentifier::regex_music, {"regex_music", "\\b(SE|MUS)_"}},
|
||||
{ProjectIdentifier::regex_encounter_types, {"regex_encounter_types", "\\bTILE_ENCOUNTER_"}},
|
||||
{ProjectIdentifier::regex_terrain_types, {"regex_terrain_types", "\\bTILE_TERRAIN_"}},
|
||||
{ProjectIdentifier::regex_gbapal, {"regex_gbapal", "\\.gbapal(\\.[\\w]+)?$"}},
|
||||
{ProjectIdentifier::regex_bpp, {"regex_bpp", "\\.[\\d]+bpp(\\.[\\w]+)?$"}},
|
||||
// Other
|
||||
|
|
@ -386,6 +388,8 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) {
|
|||
this->showTilesetEditorLayerGrid = getConfigBool(key, value);
|
||||
} else if (key == "show_tileset_editor_divider") {
|
||||
this->showTilesetEditorDivider = getConfigBool(key, value);
|
||||
} else if (key == "show_tileset_editor_raw_attributes") {
|
||||
this->showTilesetEditorRawAttributes = getConfigBool(key, value);
|
||||
} else if (key == "monitor_files") {
|
||||
this->monitorFiles = getConfigBool(key, value);
|
||||
} else if (key == "tileset_checkerboard_fill") {
|
||||
|
|
@ -495,6 +499,7 @@ QMap<QString, QString> PorymapConfig::getKeyValueMap() {
|
|||
map.insert("show_tileset_editor_metatile_grid", this->showTilesetEditorMetatileGrid ? "1" : "0");
|
||||
map.insert("show_tileset_editor_layer_grid", this->showTilesetEditorLayerGrid ? "1" : "0");
|
||||
map.insert("show_tileset_editor_divider", this->showTilesetEditorDivider ? "1" : "0");
|
||||
map.insert("show_tileset_editor_raw_attributes", this->showTilesetEditorRawAttributes ? "1" : "0");
|
||||
map.insert("monitor_files", this->monitorFiles ? "1" : "0");
|
||||
map.insert("tileset_checkerboard_fill", this->tilesetCheckerboardFill ? "1" : "0");
|
||||
map.insert("new_map_header_section_expanded", this->newMapHeaderSectionExpanded ? "1" : "0");
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ static const QMap<Metatile::Attr, BitPacker> attributePackersFRLG = {
|
|||
{Metatile::Attr::TerrainType, BitPacker(0x00003E00) },
|
||||
{Metatile::Attr::EncounterType, BitPacker(0x07000000) },
|
||||
{Metatile::Attr::LayerType, BitPacker(0x60000000) },
|
||||
//{Metatile::Attr::Unused, BitPacker(0x98FFC000) },
|
||||
{Metatile::Attr::Unused, BitPacker(0x98FFC000) },
|
||||
};
|
||||
static const QMap<Metatile::Attr, BitPacker> attributePackersRSE = {
|
||||
{Metatile::Attr::Behavior, BitPacker(0x00FF) },
|
||||
//{Metatile::Attr::Unused, BitPacker(0x0F00) },
|
||||
{Metatile::Attr::Unused, BitPacker(0x0F00) },
|
||||
{Metatile::Attr::LayerType, BitPacker(0xF000) },
|
||||
};
|
||||
|
||||
|
|
@ -128,34 +128,39 @@ void Metatile::setLayout(Project * project) {
|
|||
if (behaviorMask && !project->metatileBehaviorMapInverse.isEmpty()) {
|
||||
uint32_t maxBehavior = project->metatileBehaviorMapInverse.lastKey();
|
||||
if (packer.clamp(maxBehavior) != maxBehavior)
|
||||
logWarn(QString("Metatile Behavior mask '%1' is insufficient to contain all available options.")
|
||||
.arg(Util::toHexString(behaviorMask)));
|
||||
logWarn(QString("Metatile Behavior mask '%1' is insufficient to contain largest value '%2'.")
|
||||
.arg(Util::toHexString(behaviorMask))
|
||||
.arg(Util::toHexString(maxBehavior)));
|
||||
}
|
||||
attributePackers.insert(Metatile::Attr::Behavior, packer);
|
||||
|
||||
// Validate terrain type mask
|
||||
packer.setMask(terrainTypeMask);
|
||||
const uint32_t maxTerrainType = NUM_METATILE_TERRAIN_TYPES - 1;
|
||||
if (terrainTypeMask && packer.clamp(maxTerrainType) != maxTerrainType) {
|
||||
logWarn(QString("Metatile Terrain Type mask '%1' is insufficient to contain all %2 available options.")
|
||||
if (terrainTypeMask && !project->terrainTypeToName.isEmpty()) {
|
||||
uint32_t maxTerrainType = project->terrainTypeToName.lastKey();
|
||||
if (packer.clamp(maxTerrainType) != maxTerrainType) {
|
||||
logWarn(QString("Metatile Terrain Type mask '%1' is insufficient to contain largest value '%2'.")
|
||||
.arg(Util::toHexString(terrainTypeMask))
|
||||
.arg(maxTerrainType + 1));
|
||||
.arg(Util::toHexString(maxTerrainType)));
|
||||
}
|
||||
}
|
||||
attributePackers.insert(Metatile::Attr::TerrainType, packer);
|
||||
|
||||
// Validate encounter type mask
|
||||
packer.setMask(encounterTypeMask);
|
||||
const uint32_t maxEncounterType = NUM_METATILE_ENCOUNTER_TYPES - 1;
|
||||
if (encounterTypeMask && packer.clamp(maxEncounterType) != maxEncounterType) {
|
||||
logWarn(QString("Metatile Encounter Type mask '%1' is insufficient to contain all %2 available options.")
|
||||
if (encounterTypeMask && !project->encounterTypeToName.isEmpty()) {
|
||||
uint32_t maxEncounterType = project->encounterTypeToName.lastKey();
|
||||
if (packer.clamp(maxEncounterType) != maxEncounterType) {
|
||||
logWarn(QString("Metatile Encounter Type mask '%1' is insufficient to contain largest value '%2'.")
|
||||
.arg(Util::toHexString(encounterTypeMask))
|
||||
.arg(maxEncounterType + 1));
|
||||
.arg(Util::toHexString(maxEncounterType)));
|
||||
}
|
||||
}
|
||||
attributePackers.insert(Metatile::Attr::EncounterType, packer);
|
||||
|
||||
// Validate terrain type mask
|
||||
// Validate layer type mask
|
||||
packer.setMask(layerTypeMask);
|
||||
const uint32_t maxLayerType = NUM_METATILE_LAYER_TYPES - 1;
|
||||
const uint32_t maxLayerType = Metatile::LayerType::Count - 1;
|
||||
if (layerTypeMask && packer.clamp(maxLayerType) != maxLayerType) {
|
||||
logWarn(QString("Metatile Layer Type mask '%1' is insufficient to contain all %2 available options.")
|
||||
.arg(Util::toHexString(layerTypeMask))
|
||||
|
|
|
|||
|
|
@ -37,6 +37,12 @@ void ParseUtil::set_root(const QString &dir) {
|
|||
this->root = dir;
|
||||
}
|
||||
|
||||
QString ParseUtil::pathWithRoot(const QString &path) {
|
||||
if (this->root.isEmpty()) return path;
|
||||
if (path.startsWith(this->root)) return path;
|
||||
return QString("%1/%2").arg(this->root).arg(path);
|
||||
}
|
||||
|
||||
void ParseUtil::recordError(const QString &message) {
|
||||
this->errorMap[this->curDefine].append(message);
|
||||
}
|
||||
|
|
@ -85,6 +91,23 @@ QString ParseUtil::readTextFile(const QString &path, QString *error) {
|
|||
return text;
|
||||
}
|
||||
|
||||
// Load the specified text file, either from the cache or by reading the file.
|
||||
// Note that this doesn't insert any parsed files into the file cache, and we don't
|
||||
// want it to (we read a lot of files only once, storing them all is a waste of memory).
|
||||
QString ParseUtil::loadTextFile(const QString &path, QString *error) {
|
||||
auto it = this->fileCache.constFind(path);
|
||||
if (it != this->fileCache.constEnd()) {
|
||||
// Load text file from cache
|
||||
return it.value();
|
||||
}
|
||||
return readTextFile(pathWithRoot(path), error);
|
||||
}
|
||||
|
||||
bool ParseUtil::cacheFile(const QString &path, QString *error) {
|
||||
this->fileCache.insert(path, readTextFile(pathWithRoot(path), error));
|
||||
return !error || error->isEmpty();
|
||||
}
|
||||
|
||||
int ParseUtil::textFileLineCount(const QString &path) {
|
||||
const QString text = readTextFile(path);
|
||||
return text.split('\n').count() + 1;
|
||||
|
|
@ -93,7 +116,7 @@ int ParseUtil::textFileLineCount(const QString &path) {
|
|||
QList<QStringList> ParseUtil::parseAsm(const QString &filename) {
|
||||
QList<QStringList> parsed;
|
||||
|
||||
this->text = readTextFile(this->root + '/' + filename);
|
||||
this->text = loadTextFile(filename);
|
||||
const QStringList lines = removeLineComments(this->text, "@").split('\n');
|
||||
for (const auto &line : lines) {
|
||||
const QString trimmedLine = line.trimmed();
|
||||
|
|
@ -295,7 +318,7 @@ QString ParseUtil::readCIncbin(const QString &filename, const QString &label) {
|
|||
return path;
|
||||
}
|
||||
|
||||
this->text = readTextFile(this->root + "/" + filename);
|
||||
this->text = loadTextFile(filename);
|
||||
|
||||
QRegularExpression re(QString(
|
||||
"\\b%1\\b"
|
||||
|
|
@ -316,7 +339,7 @@ QMap<QString, QString> ParseUtil::readCIncbinMulti(const QString &filepath) {
|
|||
QMap<QString, QString> incbinMap;
|
||||
|
||||
this->file = filepath;
|
||||
this->text = readTextFile(this->root + "/" + filepath);
|
||||
this->text = loadTextFile(filepath);
|
||||
|
||||
static const QRegularExpression regex("(?<label>[A-Za-z0-9_]+)\\s*\\[?\\s*\\]?\\s*=\\s*INCBIN_[US][0-9][0-9]?\\(\\s*\\\"(?<path>[^\\\\\"]*)\\\"\\s*\\)");
|
||||
|
||||
|
|
@ -338,7 +361,7 @@ QStringList ParseUtil::readCIncbinArray(const QString &filename, const QString &
|
|||
return paths;
|
||||
}
|
||||
|
||||
this->text = readTextFile(this->root + "/" + filename);
|
||||
this->text = loadTextFile(filename);
|
||||
|
||||
bool found = false;
|
||||
QString arrayText;
|
||||
|
|
@ -388,8 +411,7 @@ ParseUtil::ParsedDefines ParseUtil::readCDefines(const QString &filename, const
|
|||
return result;
|
||||
}
|
||||
|
||||
QString filepath = this->root + "/" + this->file;
|
||||
this->text = readTextFile(filepath, error);
|
||||
this->text = loadTextFile(filename, error);
|
||||
if (this->text.isNull())
|
||||
return result;
|
||||
|
||||
|
|
@ -507,7 +529,7 @@ QStringList ParseUtil::readCArray(const QString &filename, const QString &label)
|
|||
}
|
||||
|
||||
this->file = filename;
|
||||
this->text = readTextFile(this->root + "/" + filename);
|
||||
this->text = loadTextFile(filename);
|
||||
|
||||
QRegularExpression re(QString(R"(\b%1\b\s*(\[?[^\]]*\])?\s*=\s*\{([^\}]*)\})").arg(label));
|
||||
QRegularExpressionMatch match = re.match(this->text);
|
||||
|
|
@ -530,7 +552,7 @@ QMap<QString, QStringList> ParseUtil::readCArrayMulti(const QString &filename) {
|
|||
QMap<QString, QStringList> map;
|
||||
|
||||
this->file = filename;
|
||||
this->text = readTextFile(this->root + "/" + filename);
|
||||
this->text = loadTextFile(filename);
|
||||
|
||||
static const QRegularExpression regex(R"((?<label>\b[A-Za-z0-9_]+\b)\s*(\[[^\]]*\])?\s*=\s*\{(?<body>[^\}]*)\})");
|
||||
|
||||
|
|
@ -556,7 +578,7 @@ QMap<QString, QStringList> ParseUtil::readCArrayMulti(const QString &filename) {
|
|||
}
|
||||
|
||||
QMap<QString, QString> ParseUtil::readNamedIndexCArray(const QString &filename, const QString &label, QString *error) {
|
||||
this->text = readTextFile(this->root + "/" + filename, error);
|
||||
this->text = loadTextFile(filename, error);
|
||||
QMap<QString, QString> map;
|
||||
|
||||
QRegularExpression re_text(QString(R"(\b%1\b\s*(\[?[^\]]*\])?\s*=\s*\{([^\}]*)\})").arg(label));
|
||||
|
|
@ -589,7 +611,7 @@ bool ParseUtil::gameStringToBool(const QString &gameString, bool * ok) {
|
|||
}
|
||||
|
||||
tsl::ordered_map<QString, QHash<QString, QString>> ParseUtil::readCStructs(const QString &filename, const QString &label, const QHash<int, QString> &memberMap) {
|
||||
QString filePath = this->root + "/" + filename;
|
||||
QString filePath = pathWithRoot(filename);
|
||||
auto cParser = fex::Parser();
|
||||
auto tokens = fex::Lexer().LexFile(filePath);
|
||||
auto topLevelObjects = cParser.ParseTopLevelObjects(tokens);
|
||||
|
|
@ -657,7 +679,7 @@ QStringList ParseUtil::getLabelValues(const QList<QStringList> &list, const QStr
|
|||
}
|
||||
|
||||
bool ParseUtil::tryParseJsonFile(QJsonDocument *out, const QString &filepath, QString *error) {
|
||||
QFile file(filepath);
|
||||
QFile file(pathWithRoot(filepath));
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
if (error) *error = file.errorString();
|
||||
return false;
|
||||
|
|
@ -677,7 +699,7 @@ bool ParseUtil::tryParseJsonFile(QJsonDocument *out, const QString &filepath, QS
|
|||
}
|
||||
|
||||
bool ParseUtil::tryParseOrderedJsonFile(poryjson::Json::object *out, const QString &filepath, QString *error) {
|
||||
QString jsonTxt = readTextFile(filepath, error);
|
||||
QString jsonTxt = loadTextFile(filepath, error);
|
||||
if (error && !error->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ bool Project::sanityCheck() {
|
|||
}
|
||||
|
||||
bool Project::load() {
|
||||
resetFileCache();
|
||||
this->disabledSettingsNames.clear();
|
||||
bool success = readMapLayouts()
|
||||
&& readRegionMapSections()
|
||||
|
|
@ -119,6 +120,27 @@ bool Project::load() {
|
|||
return success;
|
||||
}
|
||||
|
||||
void Project::resetFileCache() {
|
||||
this->parser.clearFileCache();
|
||||
|
||||
const QSet<QString> filepaths = {
|
||||
// Whenever we load a tileset we'll need to parse some data from these files, so we cache them to avoid the overhead of opening the files.
|
||||
// We don't know yet whether the project uses C or asm tileset data, so try to cache both (we'll ignore errors from missing files).
|
||||
projectConfig.getFilePath(ProjectFilePath::tilesets_headers_asm),
|
||||
projectConfig.getFilePath(ProjectFilePath::tilesets_graphics_asm),
|
||||
projectConfig.getFilePath(ProjectFilePath::tilesets_metatiles_asm),
|
||||
projectConfig.getFilePath(ProjectFilePath::tilesets_headers),
|
||||
projectConfig.getFilePath(ProjectFilePath::tilesets_graphics),
|
||||
projectConfig.getFilePath(ProjectFilePath::tilesets_metatiles),
|
||||
// We need separate sets of constants from these files
|
||||
projectConfig.getFilePath(ProjectFilePath::constants_map_types),
|
||||
projectConfig.getFilePath(ProjectFilePath::global_fieldmap),
|
||||
};
|
||||
for (const auto &path : filepaths) {
|
||||
this->parser.cacheFile(path);
|
||||
}
|
||||
}
|
||||
|
||||
QString Project::getProjectTitle() const {
|
||||
if (!root.isNull()) {
|
||||
return root.section('/', -1);
|
||||
|
|
@ -189,7 +211,7 @@ void Project::initTopLevelMapFields() {
|
|||
bool Project::readMapJson(const QString &mapName, QJsonDocument * out) {
|
||||
const QString mapFilepath = QString("%1%2/map.json").arg(projectConfig.getFilePath(ProjectFilePath::data_map_folders)).arg(mapName);
|
||||
QString error;
|
||||
if (!parser.tryParseJsonFile(out, QString("%1/%2").arg(this->root).arg(mapFilepath), &error)) {
|
||||
if (!parser.tryParseJsonFile(out, mapFilepath, &error)) {
|
||||
logError(QString("Failed to read map data from '%1': %2").arg(mapFilepath).arg(error));
|
||||
return false;
|
||||
}
|
||||
|
|
@ -457,12 +479,11 @@ bool Project::readMapLayouts() {
|
|||
clearMapLayouts();
|
||||
|
||||
const QString layoutsFilepath = projectConfig.getFilePath(ProjectFilePath::json_layouts);
|
||||
const QString fullFilepath = QString("%1/%2").arg(this->root).arg(layoutsFilepath);
|
||||
fileWatcher.addPath(fullFilepath);
|
||||
fileWatcher.addPath(QString("%1/%2").arg(this->root).arg(layoutsFilepath));
|
||||
QJsonDocument layoutsDoc;
|
||||
QString error;
|
||||
if (!parser.tryParseJsonFile(&layoutsDoc, fullFilepath, &error)) {
|
||||
logError(QString("Failed to read map layouts from '%1': %2").arg(fullFilepath).arg(error));
|
||||
if (!parser.tryParseJsonFile(&layoutsDoc, layoutsFilepath, &error)) {
|
||||
logError(QString("Failed to read map layouts from '%1': %2").arg(layoutsFilepath).arg(error));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -961,9 +982,6 @@ bool Project::loadLayoutTilesets(Layout *layout) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// TODO: We are parsing the tileset headers file whenever we load a tileset for the first time.
|
||||
// At a minimum this means we're parsing the file three times per session (twice here for the first map's tilesets, once on launch in Project::readTilesetLabels).
|
||||
// We can cache the header data instead and only parse it once on launch.
|
||||
Tileset* Project::loadTileset(QString label, Tileset *tileset) {
|
||||
auto memberMap = Tileset::getHeaderMemberMap(this->usingAsmTilesets);
|
||||
if (this->usingAsmTilesets) {
|
||||
|
|
@ -1612,15 +1630,14 @@ bool Project::readWildMonData() {
|
|||
this->pokemonMaxLevel = qMax(this->pokemonMinLevel, this->pokemonMaxLevel);
|
||||
|
||||
// Read encounter data
|
||||
const QString wildMonJsonBaseFilepath = projectConfig.getFilePath(ProjectFilePath::json_wild_encounters);
|
||||
QString wildMonJsonFilepath = QString("%1/%2").arg(root).arg(wildMonJsonBaseFilepath);
|
||||
fileWatcher.addPath(wildMonJsonFilepath);
|
||||
const QString wildMonJsonFilepath = projectConfig.getFilePath(ProjectFilePath::json_wild_encounters);
|
||||
fileWatcher.addPath(QString("%1/%2").arg(this->root).arg(wildMonJsonFilepath));
|
||||
|
||||
OrderedJson::object wildMonObj;
|
||||
QString error;
|
||||
if (!parser.tryParseOrderedJsonFile(&wildMonObj, wildMonJsonFilepath, &error)) {
|
||||
// Failing to read wild encounters data is not a critical error, the encounter editor will just be disabled
|
||||
logWarn(QString("Failed to read wild encounters from '%1': %2").arg(wildMonJsonBaseFilepath).arg(error));
|
||||
logWarn(QString("Failed to read wild encounters from '%1': %2").arg(wildMonJsonFilepath).arg(error));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1746,8 +1763,8 @@ bool Project::readMapGroups() {
|
|||
|
||||
this->initTopLevelMapFields();
|
||||
|
||||
const QString filepath = root + "/" + projectConfig.getFilePath(ProjectFilePath::json_map_groups);
|
||||
fileWatcher.addPath(filepath);
|
||||
const QString filepath = projectConfig.getFilePath(ProjectFilePath::json_map_groups);
|
||||
fileWatcher.addPath(root + "/" + filepath);
|
||||
QJsonDocument mapGroupsDoc;
|
||||
QString error;
|
||||
if (!parser.tryParseJsonFile(&mapGroupsDoc, filepath, &error)) {
|
||||
|
|
@ -2159,6 +2176,9 @@ bool Project::readFieldmapProperties() {
|
|||
|
||||
// Read data masks for Blocks and metatile attributes.
|
||||
bool Project::readFieldmapMasks() {
|
||||
this->encounterTypeToName.clear();
|
||||
this->terrainTypeToName.clear();
|
||||
|
||||
const QString metatileIdMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_metatile);
|
||||
const QString collisionMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_collision);
|
||||
const QString elevationMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_elevation);
|
||||
|
|
@ -2171,7 +2191,7 @@ bool Project::readFieldmapMasks() {
|
|||
behaviorMaskName,
|
||||
layerTypeMaskName,
|
||||
};
|
||||
QString globalFieldmap = projectConfig.getFilePath(ProjectFilePath::global_fieldmap);
|
||||
const QString globalFieldmap = projectConfig.getFilePath(ProjectFilePath::global_fieldmap);
|
||||
fileWatcher.addPath(root + "/" + globalFieldmap);
|
||||
QMap<QString, int> defines = parser.readCDefinesByName(globalFieldmap, searchNames);
|
||||
|
||||
|
|
@ -2255,6 +2275,32 @@ bool Project::readFieldmapMasks() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read #defines for encounter and terrain types to populate in the Tileset Editor dropdowns (if necessary)
|
||||
QString error;
|
||||
if (projectConfig.metatileEncounterTypeMask) {
|
||||
QMap<QString, int> defines = parser.readCDefinesByRegex(globalFieldmap, {projectConfig.getIdentifier(ProjectIdentifier::regex_encounter_types)}, &error);
|
||||
if (!error.isEmpty()) {
|
||||
logWarn(QString("Failed to read encounter type constants from '%1': %2").arg(globalFieldmap).arg(error));
|
||||
error = QString();
|
||||
} else {
|
||||
for (auto i = defines.constBegin(); i != defines.constEnd(); i++) {
|
||||
this->encounterTypeToName.insert(static_cast<uint32_t>(i.value()), i.key());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (projectConfig.metatileTerrainTypeMask) {
|
||||
QMap<QString, int> defines = parser.readCDefinesByRegex(globalFieldmap, {projectConfig.getIdentifier(ProjectIdentifier::regex_terrain_types)}, &error);
|
||||
if (!error.isEmpty()) {
|
||||
logWarn(QString("Failed to read terrain type constants from '%1': %2").arg(globalFieldmap).arg(error));
|
||||
error = QString();
|
||||
} else {
|
||||
for (auto i = defines.constBegin(); i != defines.constEnd(); i++) {
|
||||
this->terrainTypeToName.insert(static_cast<uint32_t>(i.value()), i.key());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2267,14 +2313,13 @@ bool Project::readRegionMapSections() {
|
|||
const QString requiredPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix);
|
||||
|
||||
QJsonDocument doc;
|
||||
const QString baseFilepath = projectConfig.getFilePath(ProjectFilePath::json_region_map_entries);
|
||||
const QString filepath = QString("%1/%2").arg(this->root).arg(baseFilepath);
|
||||
const QString filepath = projectConfig.getFilePath(ProjectFilePath::json_region_map_entries);
|
||||
QString error;
|
||||
if (!parser.tryParseJsonFile(&doc, filepath, &error)) {
|
||||
logError(QString("Failed to read region map sections from '%1': %2").arg(baseFilepath).arg(error));
|
||||
logError(QString("Failed to read region map sections from '%1': %2").arg(filepath).arg(error));
|
||||
return false;
|
||||
}
|
||||
fileWatcher.addPath(filepath);
|
||||
fileWatcher.addPath(QString("%1/%2").arg(this->root).arg(filepath));
|
||||
|
||||
QJsonArray mapSections = doc.object()["map_sections"].toArray();
|
||||
for (int i = 0; i < mapSections.size(); i++) {
|
||||
|
|
@ -2290,13 +2335,13 @@ bool Project::readRegionMapSections() {
|
|||
// ignoring everything here and then wiping the file's data when we save later.
|
||||
idField = oldIdField;
|
||||
} else {
|
||||
logWarn(QString("Ignoring data for map section %1 in '%2'. Missing required field \"%3\"").arg(i).arg(baseFilepath).arg(idField));
|
||||
logWarn(QString("Ignoring data for map section %1 in '%2'. Missing required field \"%3\"").arg(i).arg(filepath).arg(idField));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const QString idName = ParseUtil::jsonToQString(mapSectionObj[idField]);
|
||||
if (!idName.startsWith(requiredPrefix)) {
|
||||
logWarn(QString("Ignoring data for map section '%1' in '%2'. IDs must start with the prefix '%3'").arg(idName).arg(baseFilepath).arg(requiredPrefix));
|
||||
logWarn(QString("Ignoring data for map section '%1' in '%2'. IDs must start with the prefix '%3'").arg(idName).arg(filepath).arg(requiredPrefix));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -2406,21 +2451,20 @@ bool Project::readHealLocations() {
|
|||
clearHealLocations();
|
||||
|
||||
QJsonDocument doc;
|
||||
const QString baseFilepath = projectConfig.getFilePath(ProjectFilePath::json_heal_locations);
|
||||
const QString filepath = QString("%1/%2").arg(this->root).arg(baseFilepath);
|
||||
const QString filepath = projectConfig.getFilePath(ProjectFilePath::json_heal_locations);
|
||||
QString error;
|
||||
if (!parser.tryParseJsonFile(&doc, filepath, &error)) {
|
||||
logError(QString("Failed to read heal locations from '%1': %2").arg(baseFilepath).arg(error));
|
||||
logError(QString("Failed to read heal locations from '%1': %2").arg(filepath).arg(error));
|
||||
return false;
|
||||
}
|
||||
fileWatcher.addPath(filepath);
|
||||
fileWatcher.addPath(QString("%1/%2").arg(this->root).arg(filepath));
|
||||
|
||||
QJsonArray healLocations = doc.object()["heal_locations"].toArray();
|
||||
for (int i = 0; i < healLocations.size(); i++) {
|
||||
QJsonObject healLocationObj = healLocations.at(i).toObject();
|
||||
static const QString mapField = QStringLiteral("map");
|
||||
if (!healLocationObj.contains(mapField)) {
|
||||
logWarn(QString("Ignoring data for heal location %1 in '%2'. Missing required field \"%3\"").arg(i).arg(baseFilepath).arg(mapField));
|
||||
logWarn(QString("Ignoring data for heal location %1 in '%2'. Missing required field \"%3\"").arg(i).arg(filepath).arg(mapField));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,19 +72,19 @@ QImage getMetatileImage(
|
|||
switch (layerType)
|
||||
{
|
||||
default:
|
||||
case METATILE_LAYER_MIDDLE_TOP:
|
||||
case Metatile::LayerType::Normal:
|
||||
if (l == 0)
|
||||
tile = Tile(projectConfig.unusedTileNormal);
|
||||
else // Tiles are on layers 1 and 2
|
||||
tile = metatile->tiles.value(tileOffset + ((l - 1) * 4));
|
||||
break;
|
||||
case METATILE_LAYER_BOTTOM_MIDDLE:
|
||||
case Metatile::LayerType::Covered:
|
||||
if (l == 2)
|
||||
tile = Tile(projectConfig.unusedTileCovered);
|
||||
else // Tiles are on layers 0 and 1
|
||||
tile = metatile->tiles.value(tileOffset + (l * 4));
|
||||
break;
|
||||
case METATILE_LAYER_BOTTOM_TOP:
|
||||
case Metatile::LayerType::Split:
|
||||
if (l == 1)
|
||||
tile = Tile(projectConfig.unusedTileSplit);
|
||||
else // Tiles are on layers 0 and 2
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ TilesetEditor::TilesetEditor(Project *project, Layout *layout, QWidget *parent)
|
|||
this->paletteId = ui->spinBox_paletteSelector->value();
|
||||
|
||||
ui->actionShow_Tileset_Divider->setChecked(porymapConfig.showTilesetEditorDivider);
|
||||
ui->actionShow_Raw_Metatile_Attributes->setChecked(porymapConfig.showTilesetEditorRawAttributes);
|
||||
|
||||
ui->spinBox_paletteSelector->setMinimum(0);
|
||||
ui->spinBox_paletteSelector->setMaximum(Project::getNumPalettesTotal() - 1);
|
||||
|
||||
|
|
@ -43,7 +45,7 @@ TilesetEditor::TilesetEditor(Project *project, Layout *layout, QWidget *parent)
|
|||
connect(filter, &ActiveWindowFilter::activated, this, &TilesetEditor::onWindowActivated);
|
||||
this->installEventFilter(filter);
|
||||
|
||||
setAttributesUi();
|
||||
initAttributesUi();
|
||||
initMetatileSelector();
|
||||
initMetatileLayersItem();
|
||||
initTileSelector();
|
||||
|
|
@ -120,7 +122,18 @@ void TilesetEditor::setTilesets(QString primaryTilesetLabel, QString secondaryTi
|
|||
this->initMetatileHistory();
|
||||
}
|
||||
|
||||
void TilesetEditor::setAttributesUi() {
|
||||
void TilesetEditor::initAttributesUi() {
|
||||
// Update the metatile's attributes values when the attribute combo boxes are edited.
|
||||
// We avoid using the 'currentTextChanged' signal here, we want to know when we can clean up the input field and commit changes.
|
||||
connect(ui->comboBox_metatileBehaviors->lineEdit(), &QLineEdit::editingFinished, this, &TilesetEditor::commitMetatileBehavior);
|
||||
connect(ui->comboBox_encounterType->lineEdit(), &QLineEdit::editingFinished, this, &TilesetEditor::commitEncounterType);
|
||||
connect(ui->comboBox_terrainType->lineEdit(), &QLineEdit::editingFinished, this, &TilesetEditor::commitTerrainType);
|
||||
connect(ui->comboBox_layerType->lineEdit(), &QLineEdit::editingFinished, this, &TilesetEditor::commitLayerType);
|
||||
connect(ui->comboBox_metatileBehaviors, QOverload<int>::of(&QComboBox::activated), this, &TilesetEditor::commitMetatileBehavior);
|
||||
connect(ui->comboBox_encounterType, QOverload<int>::of(&QComboBox::activated), this, &TilesetEditor::commitEncounterType);
|
||||
connect(ui->comboBox_terrainType, QOverload<int>::of(&QComboBox::activated), this, &TilesetEditor::commitTerrainType);
|
||||
connect(ui->comboBox_layerType, QOverload<int>::of(&QComboBox::activated), this, &TilesetEditor::commitLayerType);
|
||||
|
||||
// Behavior
|
||||
if (projectConfig.metatileBehaviorMask) {
|
||||
for (auto i = project->metatileBehaviorMapInverse.constBegin(); i != project->metatileBehaviorMapInverse.constEnd(); i++) {
|
||||
|
|
@ -134,11 +147,9 @@ void TilesetEditor::setAttributesUi() {
|
|||
|
||||
// Terrain Type
|
||||
if (projectConfig.metatileTerrainTypeMask) {
|
||||
this->ui->comboBox_terrainType->addItem("Normal", TERRAIN_NONE);
|
||||
this->ui->comboBox_terrainType->addItem("Grass", TERRAIN_GRASS);
|
||||
this->ui->comboBox_terrainType->addItem("Water", TERRAIN_WATER);
|
||||
this->ui->comboBox_terrainType->addItem("Waterfall", TERRAIN_WATERFALL);
|
||||
this->ui->comboBox_terrainType->setEditable(false);
|
||||
for (auto i = project->terrainTypeToName.constBegin(); i != project->terrainTypeToName.constEnd(); i++) {
|
||||
this->ui->comboBox_terrainType->addItem(i.value(), i.key());
|
||||
}
|
||||
this->ui->comboBox_terrainType->setMinimumContentsLength(0);
|
||||
} else {
|
||||
this->ui->comboBox_terrainType->setVisible(false);
|
||||
|
|
@ -147,10 +158,9 @@ void TilesetEditor::setAttributesUi() {
|
|||
|
||||
// Encounter Type
|
||||
if (projectConfig.metatileEncounterTypeMask) {
|
||||
this->ui->comboBox_encounterType->addItem("None", ENCOUNTER_NONE);
|
||||
this->ui->comboBox_encounterType->addItem("Land", ENCOUNTER_LAND);
|
||||
this->ui->comboBox_encounterType->addItem("Water", ENCOUNTER_WATER);
|
||||
this->ui->comboBox_encounterType->setEditable(false);
|
||||
for (auto i = project->encounterTypeToName.constBegin(); i != project->encounterTypeToName.constEnd(); i++) {
|
||||
this->ui->comboBox_encounterType->addItem(i.value(), i.key());
|
||||
}
|
||||
this->ui->comboBox_encounterType->setMinimumContentsLength(0);
|
||||
} else {
|
||||
this->ui->comboBox_encounterType->setVisible(false);
|
||||
|
|
@ -159,9 +169,9 @@ void TilesetEditor::setAttributesUi() {
|
|||
|
||||
// Layer Type
|
||||
if (!projectConfig.tripleLayerMetatilesEnabled) {
|
||||
this->ui->comboBox_layerType->addItem("Normal - Middle/Top", METATILE_LAYER_MIDDLE_TOP);
|
||||
this->ui->comboBox_layerType->addItem("Covered - Bottom/Middle", METATILE_LAYER_BOTTOM_MIDDLE);
|
||||
this->ui->comboBox_layerType->addItem("Split - Bottom/Top", METATILE_LAYER_BOTTOM_TOP);
|
||||
this->ui->comboBox_layerType->addItem("Normal - Middle/Top", Metatile::LayerType::Normal);
|
||||
this->ui->comboBox_layerType->addItem("Covered - Bottom/Middle", Metatile::LayerType::Covered);
|
||||
this->ui->comboBox_layerType->addItem("Split - Bottom/Top", Metatile::LayerType::Split);
|
||||
this->ui->comboBox_layerType->setEditable(false);
|
||||
this->ui->comboBox_layerType->setMinimumContentsLength(0);
|
||||
if (!projectConfig.metatileLayerTypeMask) {
|
||||
|
|
@ -176,9 +186,22 @@ void TilesetEditor::setAttributesUi() {
|
|||
this->ui->label_layerType->setVisible(false);
|
||||
this->ui->label_BottomTop->setText("Bottom/Middle/Top");
|
||||
}
|
||||
|
||||
// Raw attributes value
|
||||
ui->spinBox_rawAttributesValue->setMaximum(Metatile::getMaxAttributesMask());
|
||||
setRawAttributesVisible(ui->actionShow_Raw_Metatile_Attributes->isChecked());
|
||||
connect(ui->spinBox_rawAttributesValue, &UIntHexSpinBox::editingFinished, this, &TilesetEditor::onRawAttributesEdited);
|
||||
connect(ui->actionShow_Raw_Metatile_Attributes, &QAction::toggled, this, &TilesetEditor::setRawAttributesVisible);
|
||||
|
||||
this->ui->frame_Properties->adjustSize();
|
||||
}
|
||||
|
||||
void TilesetEditor::setRawAttributesVisible(bool visible) {
|
||||
porymapConfig.showTilesetEditorRawAttributes = visible;
|
||||
ui->label_rawAttributesValue->setVisible(visible);
|
||||
ui->spinBox_rawAttributesValue->setVisible(visible);
|
||||
}
|
||||
|
||||
void TilesetEditor::initMetatileSelector()
|
||||
{
|
||||
this->metatileSelector = new TilesetEditorMetatileSelector(this->primaryTileset, this->secondaryTileset, this->layout);
|
||||
|
|
@ -413,10 +436,7 @@ void TilesetEditor::onSelectedMetatileChanged(uint16_t metatileId) {
|
|||
this->ui->lineEdit_metatileLabel->setText(labels.owned);
|
||||
this->ui->lineEdit_metatileLabel->setPlaceholderText(labels.shared);
|
||||
|
||||
this->ui->comboBox_metatileBehaviors->setHexItem(this->metatile->behavior());
|
||||
this->ui->comboBox_layerType->setHexItem(this->metatile->layerType());
|
||||
this->ui->comboBox_encounterType->setHexItem(this->metatile->encounterType());
|
||||
this->ui->comboBox_terrainType->setHexItem(this->metatile->terrainType());
|
||||
refreshMetatileAttributes();
|
||||
}
|
||||
|
||||
void TilesetEditor::queueMetatileReload(uint16_t metatileId) {
|
||||
|
|
@ -536,30 +556,6 @@ void TilesetEditor::on_checkBox_yFlip_stateChanged(int checked)
|
|||
this->metatileLayersItem->clearLastModifiedCoords();
|
||||
}
|
||||
|
||||
void TilesetEditor::on_comboBox_metatileBehaviors_currentTextChanged(const QString &metatileBehavior)
|
||||
{
|
||||
if (this->metatile) {
|
||||
uint32_t behavior;
|
||||
if (project->metatileBehaviorMap.contains(metatileBehavior)) {
|
||||
behavior = project->metatileBehaviorMap[metatileBehavior];
|
||||
} else {
|
||||
// Check if user has entered a number value instead
|
||||
bool ok;
|
||||
behavior = metatileBehavior.toUInt(&ok, 0);
|
||||
if (!ok) return;
|
||||
}
|
||||
|
||||
// This function can also be called when the user selects
|
||||
// a different metatile. Stop this from being considered a change.
|
||||
if (this->metatile->behavior() == behavior)
|
||||
return;
|
||||
|
||||
Metatile *prevMetatile = new Metatile(*this->metatile);
|
||||
this->metatile->setBehavior(behavior);
|
||||
this->commitMetatileChange(prevMetatile);
|
||||
}
|
||||
}
|
||||
|
||||
void TilesetEditor::setMetatileLabel(QString label)
|
||||
{
|
||||
this->ui->lineEdit_metatileLabel->setText(label);
|
||||
|
|
@ -597,32 +593,92 @@ void TilesetEditor::commitMetatileChange(Metatile * prevMetatile)
|
|||
this->commitMetatileAndLabelChange(prevMetatile, this->ui->lineEdit_metatileLabel->text());
|
||||
}
|
||||
|
||||
void TilesetEditor::on_comboBox_layerType_activated(int layerType)
|
||||
{
|
||||
if (this->metatile) {
|
||||
Metatile *prevMetatile = new Metatile(*this->metatile);
|
||||
this->metatile->setLayerType(layerType);
|
||||
this->commitMetatileChange(prevMetatile);
|
||||
this->metatileSelector->drawSelectedMetatile(); // Changing the layer type can affect how fully transparent metatiles appear
|
||||
uint32_t TilesetEditor::attributeNameToValue(Metatile::Attr attribute, const QString &text, bool *ok) {
|
||||
if (ok) *ok = true;
|
||||
if (attribute == Metatile::Attr::Behavior) {
|
||||
auto it = project->metatileBehaviorMap.constFind(text);
|
||||
if (it != project->metatileBehaviorMap.constEnd())
|
||||
return it.value();
|
||||
} else if (attribute == Metatile::Attr::EncounterType) {
|
||||
for (auto i = project->encounterTypeToName.constBegin(); i != project->encounterTypeToName.constEnd(); i++) {
|
||||
if (i.value() == text) return i.key();
|
||||
}
|
||||
} else if (attribute == Metatile::Attr::TerrainType) {
|
||||
for (auto i = project->terrainTypeToName.constBegin(); i != project->terrainTypeToName.constEnd(); i++) {
|
||||
if (i.value() == text) return i.key();
|
||||
}
|
||||
} else if (attribute == Metatile::Attr::LayerType) {
|
||||
// The layer type text is not editable, it uses special display names. Just get the index of the display name.
|
||||
int i = ui->comboBox_layerType->findText(text);
|
||||
if (i >= 0) return i;
|
||||
}
|
||||
return text.toUInt(ok, 0);
|
||||
}
|
||||
|
||||
void TilesetEditor::on_comboBox_encounterType_activated(int encounterType)
|
||||
{
|
||||
if (this->metatile) {
|
||||
void TilesetEditor::commitAttributeFromComboBox(Metatile::Attr attribute, NoScrollComboBox *combo) {
|
||||
if (!this->metatile)
|
||||
return;
|
||||
|
||||
bool ok;
|
||||
uint32_t newValue = this->attributeNameToValue(attribute, combo->currentText(), &ok);
|
||||
if (ok && newValue != this->metatile->getAttribute(attribute)) {
|
||||
Metatile *prevMetatile = new Metatile(*this->metatile);
|
||||
this->metatile->setEncounterType(encounterType);
|
||||
this->metatile->setAttribute(attribute, newValue);
|
||||
this->commitMetatileChange(prevMetatile);
|
||||
|
||||
// When an attribute changes we also need to update the raw value display.
|
||||
const QSignalBlocker b_RawAttributesValue(ui->spinBox_rawAttributesValue);
|
||||
ui->spinBox_rawAttributesValue->setValue(this->metatile->getAttributes());
|
||||
}
|
||||
|
||||
// Update the text in the combo box to reflect the final value.
|
||||
// The text may change if the input text was invalid, the value was too large to fit, or if a number was entered that we know an identifier for.
|
||||
const QSignalBlocker b(combo);
|
||||
combo->setHexItem(this->metatile->getAttribute(attribute));
|
||||
}
|
||||
|
||||
void TilesetEditor::on_comboBox_terrainType_activated(int terrainType)
|
||||
{
|
||||
if (this->metatile) {
|
||||
void TilesetEditor::onRawAttributesEdited() {
|
||||
uint32_t newAttributes = ui->spinBox_rawAttributesValue->value();
|
||||
if (newAttributes != this->metatile->getAttributes()) {
|
||||
Metatile *prevMetatile = new Metatile(*this->metatile);
|
||||
this->metatile->setTerrainType(terrainType);
|
||||
this->metatile->setAttributes(newAttributes);
|
||||
this->commitMetatileChange(prevMetatile);
|
||||
}
|
||||
refreshMetatileAttributes();
|
||||
}
|
||||
|
||||
void TilesetEditor::refreshMetatileAttributes() {
|
||||
if (!this->metatile) return;
|
||||
|
||||
const QSignalBlocker b_MetatileBehaviors(ui->comboBox_metatileBehaviors);
|
||||
const QSignalBlocker b_EncounterType(ui->comboBox_encounterType);
|
||||
const QSignalBlocker b_TerrainType(ui->comboBox_terrainType);
|
||||
const QSignalBlocker b_LayerType(ui->comboBox_layerType);
|
||||
const QSignalBlocker b_RawAttributesValue(ui->spinBox_rawAttributesValue);
|
||||
ui->comboBox_metatileBehaviors->setHexItem(this->metatile->behavior());
|
||||
ui->comboBox_encounterType->setHexItem(this->metatile->encounterType());
|
||||
ui->comboBox_terrainType->setHexItem(this->metatile->terrainType());
|
||||
ui->comboBox_layerType->setHexItem(this->metatile->layerType());
|
||||
ui->spinBox_rawAttributesValue->setValue(this->metatile->getAttributes());
|
||||
|
||||
this->metatileSelector->drawSelectedMetatile();
|
||||
}
|
||||
|
||||
void TilesetEditor::commitMetatileBehavior() {
|
||||
commitAttributeFromComboBox(Metatile::Attr::Behavior, ui->comboBox_metatileBehaviors);
|
||||
}
|
||||
|
||||
void TilesetEditor::commitEncounterType() {
|
||||
commitAttributeFromComboBox(Metatile::Attr::EncounterType, ui->comboBox_encounterType);
|
||||
}
|
||||
|
||||
void TilesetEditor::commitTerrainType() {
|
||||
commitAttributeFromComboBox(Metatile::Attr::TerrainType, ui->comboBox_terrainType);
|
||||
};
|
||||
|
||||
void TilesetEditor::commitLayerType() {
|
||||
commitAttributeFromComboBox(Metatile::Attr::LayerType, ui->comboBox_layerType);
|
||||
this->metatileSelector->drawSelectedMetatile(); // Changing the layer type can affect how fully transparent metatiles appear
|
||||
}
|
||||
|
||||
void TilesetEditor::on_actionSave_Tileset_triggered()
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user