mirror of
https://github.com/huderlem/porymap.git
synced 2026-08-09 19:37:45 -05:00
Merge pull request #652 from GriffinRichards/new-map-dialog
Redesign creation dialogs
This commit is contained in:
commit
9047cb8a28
|
|
@ -45,7 +45,6 @@ The filepath that Porymap expects for each file can be overridden on the ``Files
|
|||
src/data/region_map/region_map_sections.json, yes, yes, ``json_region_map_entries``,
|
||||
src/data/region_map/porymap_config.json, yes, yes, ``json_region_porymap_cfg``,
|
||||
include/constants/global.h, yes, no, ``constants_global``, reads ``define_obj_event_count``
|
||||
include/constants/map_groups.h, no, yes, ``constants_map_groups``,
|
||||
include/constants/items.h, yes, no, ``constants_items``, for Hidden Item events
|
||||
include/constants/flags.h, yes, no, ``constants_flags``, for Object and Hidden Item events
|
||||
include/constants/vars.h, yes, no, ``constants_vars``, for Trigger events
|
||||
|
|
@ -93,6 +92,7 @@ In addition to these files, there are some specific symbol and macro names that
|
|||
``symbol_spawn_npcs``, ``u8 sWhiteoutRespawnHealerNpcIds``, the type and table name for Heal Location ``Respawn NPC`` values
|
||||
``symbol_attribute_table``, ``sMetatileAttrMasks``, optionally read to get settings on ``Tilesets`` tab
|
||||
``symbol_tilesets_prefix``, ``gTileset_``, for new tileset names and to extract base tileset names
|
||||
``symbol_dynamic_map_name``, ``Dynamic``, reserved map name to display for ``define_map_dynamic``
|
||||
``define_obj_event_count``, ``OBJECT_EVENT_TEMPLATES_COUNT``, to limit total Object Events
|
||||
``define_min_level``, ``MIN_LEVEL``, minimum wild encounters level
|
||||
``define_max_level``, ``MAX_LEVEL``, maximum wild encounters level
|
||||
|
|
|
|||
|
|
@ -95,11 +95,11 @@
|
|||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="mapListPage_Areas">
|
||||
<widget class="QWidget" name="mapListPage_Locations">
|
||||
<attribute name="title">
|
||||
<string>Areas</string>
|
||||
<string>Locations</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_Areas">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_Locations">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
|
|
@ -116,10 +116,10 @@
|
|||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="MapListToolBar" name="mapListToolBar_Areas"/>
|
||||
<widget class="MapListToolBar" name="mapListToolBar_Locations"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="MapTree" name="areaList">
|
||||
<widget class="MapTree" name="locationList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
|
|
@ -1155,7 +1155,7 @@
|
|||
<number>2</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_16">
|
||||
<widget class="QLabel" name="label_Layout">
|
||||
<property name="text">
|
||||
<string>Layout</string>
|
||||
</property>
|
||||
|
|
@ -1740,7 +1740,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>100</width>
|
||||
<height>16</height>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
|
@ -1834,7 +1834,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>100</width>
|
||||
<height>16</height>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
|
@ -1928,7 +1928,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>100</width>
|
||||
<height>16</height>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
|
@ -2028,7 +2028,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>100</width>
|
||||
<height>16</height>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
|
@ -2122,7 +2122,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>100</width>
|
||||
<height>16</height>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
|
@ -2220,7 +2220,7 @@
|
|||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_3">
|
||||
<widget class="QFrame" name="frame_HeaderData">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
|
|
@ -2236,206 +2236,10 @@
|
|||
<property name="frameShadow">
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::FieldGrowthPolicy::FieldsStayAtSizeHint</enum>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="layout_HeaderData">
|
||||
<property name="bottomMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Song</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_Song">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The default background music for this map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Location</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_Location">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The section of the region map which the map is grouped under. This also determines the name of the map that is display when the player enters it.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Requires Flash</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_Visibility">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Whether or not the map is dark and requires Flash to illuminate.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Weather</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_Weather">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The default weather for this map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_Type">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The map type is a general attribute, which is used for many different things. For example. it determines whether biking or running is allowed.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Battle scene</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_BattleScene">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Determines the type of battle scene graphics to use.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string>Show Location Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_ShowLocation">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Whether or not to display the location name when the player enters the map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_AllowRunning">
|
||||
<property name="text">
|
||||
<string>Allow Running</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_AllowRunning">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Allows the player to use Running Shoes</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_AllowBiking">
|
||||
<property name="text">
|
||||
<string>Allow Biking</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_AllowBiking">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Allows the player to use a Bike</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_AllowEscaping">
|
||||
<property name="text">
|
||||
<string>Allow Dig & Escape Rope</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_AllowEscaping">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Allows the player to use Dig or Escape Rope</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_FloorNumber">
|
||||
<property name="text">
|
||||
<string>Floor Number</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_FloorNumber">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Floor number to be used for maps with elevators.</p></body></html></string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-128</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>127</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -2896,8 +2700,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>204</width>
|
||||
<height>16</height>
|
||||
<width>100</width>
|
||||
<height>30</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="layout_ConnectionsList">
|
||||
|
|
@ -3126,7 +2930,9 @@
|
|||
<addaction name="actionMap_Shift"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_NewMap"/>
|
||||
<addaction name="action_NewLayout"/>
|
||||
<addaction name="actionNew_Tileset"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionTileset_Editor"/>
|
||||
<addaction name="actionRegion_Map_Editor"/>
|
||||
<addaction name="separator"/>
|
||||
|
|
@ -3295,7 +3101,7 @@
|
|||
<string>Ctrl+T</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSort_by_Area">
|
||||
<action name="actionSort_by_Location">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
|
|
@ -3304,7 +3110,7 @@
|
|||
<normaloff>:/icons/sort_alphabet.ico</normaloff>:/icons/sort_alphabet.ico</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sort by &Area</string>
|
||||
<string>Sort by &Location</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSort_by_Group">
|
||||
|
|
@ -3482,6 +3288,11 @@
|
|||
<string>Grid Settings...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_NewLayout">
|
||||
<property name="text">
|
||||
<string>New Layout...</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
|
|
|
|||
245
forms/mapheaderform.ui
Normal file
245
forms/mapheaderform.ui
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MapHeaderForm</class>
|
||||
<widget class="QWidget" name="MapHeaderForm">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>407</width>
|
||||
<height>349</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::FieldGrowthPolicy::FieldsStayAtSizeHint</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_Song">
|
||||
<property name="text">
|
||||
<string>Song</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_Song">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The default background music for this map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertPolicy::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_Location">
|
||||
<property name="text">
|
||||
<string>Location</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_Location">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The section of the region map which the map is grouped under. This also determines the name of the map that is displayed when the player enters it.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertPolicy::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_RequiresFlash">
|
||||
<property name="text">
|
||||
<string>Requires Flash</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_RequiresFlash">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If checked, the player will need to use Flash to see fully on this map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_Weather">
|
||||
<property name="text">
|
||||
<string>Weather</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_Weather">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The default weather on this map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertPolicy::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_Type">
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_Type">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The map type is a general attribute, which is used for many different things. For example, underground type maps will have a special transition effect when the player enters/exits the map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertPolicy::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_BattleScene">
|
||||
<property name="text">
|
||||
<string>Battle Scene</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_BattleScene">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>This field is used to help determine what graphics to use in the background of battles on this map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertPolicy::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_ShowLocationName">
|
||||
<property name="text">
|
||||
<string>Show Location Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_ShowLocationName">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If checked, a map name popup will appear when the player enters this map. The name that appears on this popup depends on the Location field.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_AllowRunning">
|
||||
<property name="text">
|
||||
<string>Allow Running</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_AllowRunning">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If checked, the player will be allowed to run on this map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_AllowBiking">
|
||||
<property name="text">
|
||||
<string>Allow Biking</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_AllowBiking">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If checked, the player will be allowed to get on their bike on this map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_AllowEscaping">
|
||||
<property name="text">
|
||||
<string>Allow Dig & Escape Rope</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_AllowEscaping">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If checked, the player will be allowed to use Dig or Escape Rope on this map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_FloorNumber">
|
||||
<property name="text">
|
||||
<string>Floor Number</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="NoScrollSpinBox" name="spinBox_FloorNumber">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Floor number to be used for maps with elevators.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_LocationName">
|
||||
<property name="text">
|
||||
<string>Location Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_LocationName"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>NoScrollComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>noscrollcombobox.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>NoScrollSpinBox</class>
|
||||
<extends>QSpinBox</extends>
|
||||
<header>noscrollspinbox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
174
forms/newlayoutdialog.ui
Normal file
174
forms/newlayoutdialog.ui
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>NewLayoutDialog</class>
|
||||
<widget class="QDialog" name="NewLayoutDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>264</width>
|
||||
<height>173</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>New Layout Options</string>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Shadow::Plain</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>240</width>
|
||||
<height>109</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="verticalSpacing">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_NameError">
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: rgb(255, 0, 0)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="NewLayoutForm" name="newLayoutForm" native="true"/>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_LayoutID">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The constant that will be used to refer to this layout. It cannot be the same as any other existing layout.</p></body></html></string>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>LAYOUT_MY_NEW_LAYOUT</string>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_Name">
|
||||
<property name="text">
|
||||
<string>Layout Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_LayoutID">
|
||||
<property name="text">
|
||||
<string>Layout ID</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_Name">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The name of the new layout. The name cannot be the same as any other existing layout.</p></body></html></string>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>MyNewLayout</string>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_LayoutIDError">
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: rgb(255, 0, 0)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_GenericError">
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: rgb(255, 0, 0)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok|QDialogButtonBox::StandardButton::Reset</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>NewLayoutForm</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>newlayoutform.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
244
forms/newlayoutform.ui
Normal file
244
forms/newlayoutform.ui
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>NewLayoutForm</class>
|
||||
<widget class="QWidget" name="NewLayoutForm">
|
||||
<property name="windowTitle">
|
||||
<string>Form</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="QGroupBox" name="groupBox_MapDimensions">
|
||||
<property name="title">
|
||||
<string>Map Dimensions</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_7">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_MapWidth">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Width</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="NoScrollSpinBox" name="spinBox_MapWidth">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Width (in metatiles) of the new map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_MapHeight">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Height</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="NoScrollSpinBox" name="spinBox_MapHeight">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Height (in metatiles) of the new map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_MapDimensionsError">
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: rgb(255, 0, 0)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_BorderDimensions">
|
||||
<property name="title">
|
||||
<string>Border Dimensions</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_6">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_BorderWidth">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Width</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="NoScrollSpinBox" name="spinBox_BorderWidth">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Width (in metatiles) of the new map's border.</p></body></html></string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="NoScrollSpinBox" name="spinBox_BorderHeight">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Height (in metatiles) of the new map's border.</p></body></html></string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_BorderHeight">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Height</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_Tilesets">
|
||||
<property name="title">
|
||||
<string>Tilesets</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_5">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_PrimaryTileset">
|
||||
<property name="text">
|
||||
<string>Primary</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_PrimaryTileset">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The primary tileset for the new map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertPolicy::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_PrimaryTilesetError">
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: rgb(255, 0, 0)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_SecondaryTileset">
|
||||
<property name="text">
|
||||
<string>Secondary</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_SecondaryTileset">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The secondary tileset for the new map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertPolicy::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_SecondaryTilesetError">
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: rgb(255, 0, 0)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>NoScrollComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>noscrollcombobox.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>NoScrollSpinBox</class>
|
||||
<extends>QSpinBox</extends>
|
||||
<header>noscrollspinbox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
89
forms/newlocationdialog.ui
Normal file
89
forms/newlocationdialog.ui
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>NewLocationDialog</class>
|
||||
<widget class="QDialog" name="NewLocationDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>252</width>
|
||||
<height>124</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QFrame" name="form">
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_IdName">
|
||||
<property name="text">
|
||||
<string>Location ID</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_IdName">
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_IdNameError">
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: rgb(255, 0, 0)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_DisplayName"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_DisplayName">
|
||||
<property name="text">
|
||||
<string>Location Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
|
||||
</property>
|
||||
<property name="centerButtons">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
253
forms/newmapdialog.ui
Normal file
253
forms/newmapdialog.ui
Normal file
|
|
@ -0,0 +1,253 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>NewMapDialog</class>
|
||||
<widget class="QDialog" name="NewMapDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>559</width>
|
||||
<height>614</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>New Map Options</string>
|
||||
</property>
|
||||
<property name="sizeGripEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Shadow::Plain</enum>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::SizeAdjustPolicy::AdjustToContents</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>535</width>
|
||||
<height>550</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<property name="verticalSpacing">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_Name">
|
||||
<property name="text">
|
||||
<string>Map Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0" colspan="2">
|
||||
<widget class="QWidget" name="widget_HeaderData" native="true">
|
||||
<layout class="QVBoxLayout" name="layout_HeaderData">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SizeConstraint::SetMinAndMaxSize</enum>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_GroupError">
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: rgb(255, 0, 0)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_NameError">
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: rgb(255, 0, 0)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_LayoutID">
|
||||
<property name="text">
|
||||
<string>Layout ID</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_Group">
|
||||
<property name="text">
|
||||
<string>Map Group</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_LayoutID">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertPolicy::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_CanFlyTo">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>If checked, a Heal Location will be added to this map automatically.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QLabel" name="label_LayoutIDError">
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: rgb(255, 0, 0)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<widget class="NewLayoutForm" name="newLayoutForm" native="true"/>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_Group">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The name of the group this map will be added to.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertPolicy::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_CanFlyTo">
|
||||
<property name="text">
|
||||
<string>Can Fly To</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_Name">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The name of the new map. The name cannot be the same as any other existing map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>MyNewMap</string>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_GenericError">
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: rgb(255, 0, 0)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok|QDialogButtonBox::StandardButton::Reset</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>NewLayoutForm</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>newlayoutform.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>NoScrollComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>noscrollcombobox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
79
forms/newmapgroupdialog.ui
Normal file
79
forms/newmapgroupdialog.ui
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>NewMapGroupDialog</class>
|
||||
<widget class="QDialog" name="NewMapGroupDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>252</width>
|
||||
<height>87</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QFrame" name="form">
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_Name">
|
||||
<property name="text">
|
||||
<string>Map Group Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_Name">
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_NameError">
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: rgb(255, 0, 0)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
|
||||
</property>
|
||||
<property name="centerButtons">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
@ -1,504 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>NewMapPopup</class>
|
||||
<widget class="QMainWindow" name="NewMapPopup">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>410</width>
|
||||
<height>687</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>New Map Options</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="1">
|
||||
<widget class="QFrame" name="frame_NewMap_Options">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_newMap_Name">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_NewMap_Name">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The name of the new map. If the name is invalid (red), it will be replaced with the default name of a new map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Group">
|
||||
<property name="text">
|
||||
<string>Group</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_NewMap_Group">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>New map group.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Width">
|
||||
<property name="text">
|
||||
<string>Map Width</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_NewMap_Width">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Width (in blocks) of the new map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Height">
|
||||
<property name="text">
|
||||
<string>Map Height</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_NewMap_Height">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Height (in blocks) of the new map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>200</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_BorderWidth">
|
||||
<property name="text">
|
||||
<string>Border Width</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_NewMap_BorderWidth">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Width (in blocks) of the new map's border.</p></body></html></string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>255</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_BorderHeight">
|
||||
<property name="text">
|
||||
<string>Border Height</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_NewMap_BorderHeight">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Height (in blocks) of the new map's border.</p></body></html></string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>255</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Primary_Tileset">
|
||||
<property name="text">
|
||||
<string>Primary Tileset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_NewMap_Primary_Tileset">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The primary tileset for the new map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Secondary_Tileset">
|
||||
<property name="text">
|
||||
<string>Secondary Tileset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="9" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_NewMap_Secondary_Tileset">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The secondary tileset for the new map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Type">
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_NewMap_Type">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The map type is a general attribute, which is used for many different things. For example. it determines whether biking or running is allowed.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Location">
|
||||
<property name="text">
|
||||
<string>Location</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_NewMap_Location">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The section of the region map which the map is grouped under. This also determines the name of the map that is displayed when the player enters it.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="0">
|
||||
<widget class="QLabel" name="label_Song">
|
||||
<property name="text">
|
||||
<string>Song</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_NewMap_Song">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The default background music for this map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Flyable">
|
||||
<property name="text">
|
||||
<string>Can Fly To</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_NewMap_Flyable">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Whether to add a heal location to the new map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Show_Location">
|
||||
<property name="text">
|
||||
<string>Show Location Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="14" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_NewMap_Show_Location">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Whether or not to display the location name when the player enters the map.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Allow_Running">
|
||||
<property name="text">
|
||||
<string>Allow Running</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="15" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_NewMap_Allow_Running">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Allows the player to use Running Shoes</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Allow_Biking">
|
||||
<property name="text">
|
||||
<string>Allow Biking</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="16" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_NewMap_Allow_Biking">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Allows the player to use a Bike</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="17" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Allow_Escape_Rope">
|
||||
<property name="text">
|
||||
<string>Allow Dig & Escape Rope</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="17" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_NewMap_Allow_Escape_Rope">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Allows the player to use Dig or Escape Rope</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="18" column="0">
|
||||
<widget class="QLabel" name="label_NewMap_Floor_Number">
|
||||
<property name="text">
|
||||
<string>Floor Number</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="18" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_NewMap_Floor_Number">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Floor number to be used for maps with elevators.</p></body></html></string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>127</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_Layout">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Layout</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Use Existing Layout</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_UseExistingLayout">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="pushButton_NewMap_Accept">
|
||||
<property name="text">
|
||||
<string>Accept</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QFrame" name="frame_NewMap_Warning">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QToolButton" name="toolButton_NewMap_DimensionWarning">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>!</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_NewMap_WarningMessage">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: rgb(255, 0, 0)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>410</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>NoScrollComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>noscrollcombobox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
@ -6,238 +6,147 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>216</height>
|
||||
<width>450</width>
|
||||
<height>209</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Add new Tileset</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="gridWidget" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>216</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="4" column="0">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QFrame" name="form">
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>380</width>
|
||||
<height>161</height>
|
||||
</size>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="formLayoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>380</width>
|
||||
<height>155</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="horizontalSpacing">
|
||||
<number>6</number>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_Name">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>10</number>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_Name">
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>10</number>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_NameError">
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>10</number>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: rgb(255, 0, 0)</string>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="nameLabel">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_Type">
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_Type">
|
||||
<property name="editable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Primary</string>
|
||||
</property>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="nameLineEdit">
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Secondary</string>
|
||||
</property>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="typeLabel">
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="typeComboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Primary</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Secondary</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="pathLabel">
|
||||
<property name="text">
|
||||
<string>Path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="pathLineEdit">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="symbolNameLabel">
|
||||
<property name="text">
|
||||
<string>Symbol Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="symbolNameLineEdit">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="clearButtonEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="fillLabel">
|
||||
<property name="text">
|
||||
<string>Checkerboard Fill</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="fillCheckBox">
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
<property name="centerButtons">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_CheckerboardFill">
|
||||
<property name="text">
|
||||
<string>Checkerboard Fill</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_CheckerboardFill"/>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_GenericError">
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">color: rgb(255, 0, 0)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
|
||||
</property>
|
||||
<property name="centerButtons">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>NoScrollComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>noscrollcombobox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>NewTilesetDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>NewTilesetDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
|
|||
|
|
@ -18,10 +18,10 @@
|
|||
<item row="0" column="1">
|
||||
<widget class="QFrame" name="frame_regionSelector">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
<enum>QFrame::Shadow::Plain</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
|
|
@ -46,14 +46,14 @@
|
|||
<item>
|
||||
<widget class="QComboBox" name="comboBox_regionSelector">
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToContents</enum>
|
||||
<enum>QComboBox::SizeAdjustPolicy::AdjustToContents</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -83,7 +83,7 @@
|
|||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
<enum>Qt::FocusPolicy::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>10</number>
|
||||
|
|
@ -95,10 +95,10 @@
|
|||
<number>30</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::NoTicks</enum>
|
||||
<enum>QSlider::TickPosition::NoTicks</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>1</number>
|
||||
|
|
@ -108,7 +108,7 @@
|
|||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -123,7 +123,7 @@
|
|||
<item row="1" column="1">
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="childrenCollapsible">
|
||||
<bool>false</bool>
|
||||
|
|
@ -160,7 +160,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>466</width>
|
||||
<height>351</height>
|
||||
<height>336</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_18">
|
||||
|
|
@ -182,7 +182,7 @@
|
|||
<item row="1" column="2">
|
||||
<spacer name="horizontalSpacer_RMBI_East">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -207,17 +207,17 @@
|
|||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustIgnored</enum>
|
||||
<enum>QAbstractScrollArea::SizeAdjustPolicy::AdjustIgnored</enum>
|
||||
</property>
|
||||
<property name="dragMode">
|
||||
<enum>QGraphicsView::NoDrag</enum>
|
||||
<enum>QGraphicsView::DragMode::NoDrag</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="verticalSpacer_RMBI_North">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -230,7 +230,7 @@
|
|||
<item row="2" column="1">
|
||||
<spacer name="verticalSpacer_RMBI_South">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -243,7 +243,7 @@
|
|||
<item row="1" column="0">
|
||||
<spacer name="horizontalSpacer_RMBI_West">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -281,7 +281,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>466</width>
|
||||
<height>351</height>
|
||||
<height>336</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_19">
|
||||
|
|
@ -315,17 +315,17 @@
|
|||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustIgnored</enum>
|
||||
<enum>QAbstractScrollArea::SizeAdjustPolicy::AdjustIgnored</enum>
|
||||
</property>
|
||||
<property name="dragMode">
|
||||
<enum>QGraphicsView::NoDrag</enum>
|
||||
<enum>QGraphicsView::DragMode::NoDrag</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="horizontalSpacer_RML_West">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -338,7 +338,7 @@
|
|||
<item row="2" column="1">
|
||||
<spacer name="verticalSpacer_RML_South">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -351,7 +351,7 @@
|
|||
<item row="1" column="2">
|
||||
<spacer name="horizontalSpacer_RML_East">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -364,7 +364,7 @@
|
|||
<item row="0" column="1">
|
||||
<spacer name="verticalSpacer_RML_North">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -402,7 +402,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>466</width>
|
||||
<height>351</height>
|
||||
<height>336</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_24">
|
||||
|
|
@ -436,17 +436,17 @@
|
|||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustIgnored</enum>
|
||||
<enum>QAbstractScrollArea::SizeAdjustPolicy::AdjustIgnored</enum>
|
||||
</property>
|
||||
<property name="dragMode">
|
||||
<enum>QGraphicsView::NoDrag</enum>
|
||||
<enum>QGraphicsView::DragMode::NoDrag</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="horizontalSpacer_RME_West">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -459,7 +459,7 @@
|
|||
<item row="2" column="1">
|
||||
<spacer name="verticalSpacer_RME_South">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -472,7 +472,7 @@
|
|||
<item row="1" column="2">
|
||||
<spacer name="horizontalSpacer_RME_East">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -485,7 +485,7 @@
|
|||
<item row="0" column="1">
|
||||
<spacer name="verticalSpacer_RME_North">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -529,19 +529,19 @@
|
|||
</size>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||
<enum>Qt::ScrollBarPolicy::ScrollBarAlwaysOn</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
<enum>Qt::ScrollBarPolicy::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustIgnored</enum>
|
||||
<enum>QAbstractScrollArea::SizeAdjustPolicy::AdjustIgnored</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<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_RM_Metatiles">
|
||||
<property name="enabled">
|
||||
|
|
@ -552,7 +552,7 @@
|
|||
<x>8</x>
|
||||
<y>0</y>
|
||||
<width>278</width>
|
||||
<height>342</height>
|
||||
<height>327</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
|
@ -563,7 +563,7 @@
|
|||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_21">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
<enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
|
|
@ -583,7 +583,7 @@
|
|||
<item row="1" column="1">
|
||||
<spacer name="verticalSpacer_RMM_South">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -596,7 +596,7 @@
|
|||
<item row="0" column="2">
|
||||
<spacer name="horizontalSpacer_RMM_East">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -618,20 +618,20 @@
|
|||
</sizepolicy>
|
||||
</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>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustIgnored</enum>
|
||||
<enum>QAbstractScrollArea::SizeAdjustPolicy::AdjustIgnored</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<spacer name="horizontalSpacer_RMM_West">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -648,10 +648,10 @@
|
|||
<item row="0" column="0">
|
||||
<widget class="QFrame" name="frame_tileOptions">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Panel</enum>
|
||||
<enum>QFrame::Shape::Panel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
<enum>QFrame::Shadow::Sunken</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
|
|
@ -681,7 +681,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBox_tilePalette">
|
||||
<widget class="NoScrollSpinBox" name="spinBox_tilePalette">
|
||||
<property name="maximum">
|
||||
<number>15</number>
|
||||
</property>
|
||||
|
|
@ -719,10 +719,10 @@
|
|||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
<enum>QFrame::Shape::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>1</number>
|
||||
|
|
@ -747,7 +747,7 @@
|
|||
<item>
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -760,10 +760,10 @@
|
|||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_22">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetNoConstraint</enum>
|
||||
<enum>QLayout::SizeConstraint::SetNoConstraint</enum>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_RM_ConnectedMap" native="true">
|
||||
<widget class="NoScrollComboBox" name="comboBox_RM_ConnectedMap">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
|
|
@ -771,10 +771,10 @@
|
|||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The section of the region map which the map is grouped under. This also determines the name of the map that is display when the player enters it.</p></body></html></string>
|
||||
<string><html><head/><body><p>The section of the region map which the map is grouped under. This also determines the name of the map that is displayed when the player enters it.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable" stdset="0">
|
||||
<bool>true</bool>
|
||||
<property name="editable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
@ -803,7 +803,7 @@
|
|||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -816,10 +816,10 @@
|
|||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_8">
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_RM_LayoutHeight"/>
|
||||
<widget class="NoScrollSpinBox" name="spinBox_RM_LayoutHeight"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_RM_LayoutWidth"/>
|
||||
<widget class="NoScrollSpinBox" name="spinBox_RM_LayoutWidth"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
|
|
@ -862,10 +862,10 @@
|
|||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
<enum>QFrame::Shape::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>1</number>
|
||||
|
|
@ -874,15 +874,15 @@
|
|||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_23">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetNoConstraint</enum>
|
||||
<enum>QLayout::SizeConstraint::SetNoConstraint</enum>
|
||||
</property>
|
||||
<item row="3" column="1">
|
||||
<item row="2" column="1">
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
<enum>QFrame::Shape::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
|
|
@ -893,10 +893,10 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_RM_Entry_width"/>
|
||||
<widget class="NoScrollSpinBox" name="spinBox_RM_Entry_width"/>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_RM_Entry_height"/>
|
||||
<widget class="NoScrollSpinBox" name="spinBox_RM_Entry_height"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
|
|
@ -909,7 +909,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="NoScrollComboBox" name="comboBox_RM_Entry_MapSection" native="true">
|
||||
<widget class="NoScrollComboBox" name="comboBox_RM_Entry_MapSection">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
|
|
@ -922,25 +922,25 @@
|
|||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The section of the region map which the map is grouped under. This also determines the name of the map that is display when the player enters it.</p></body></html></string>
|
||||
</property>
|
||||
<property name="editable" stdset="0">
|
||||
<bool>true</bool>
|
||||
<property name="editable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_RM_CityMap_2">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_Dimensions">
|
||||
<property name="text">
|
||||
<string>Dimensions</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<item row="1" column="1">
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
<enum>QFrame::Shape::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
|
|
@ -951,10 +951,10 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_RM_Entry_x"/>
|
||||
<widget class="NoScrollSpinBox" name="spinBox_RM_Entry_x"/>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_RM_Entry_y"/>
|
||||
<widget class="NoScrollSpinBox" name="spinBox_RM_Entry_y"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
|
|
@ -966,7 +966,7 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_RM_Location">
|
||||
<property name="text">
|
||||
<string>Location</string>
|
||||
|
|
@ -980,16 +980,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>Map Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineEdit_RM_MapName"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
|
@ -1002,7 +992,7 @@
|
|||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -1037,7 +1027,7 @@
|
|||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
<enum>Qt::FocusPolicy::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>10</number>
|
||||
|
|
@ -1049,10 +1039,10 @@
|
|||
<number>30</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="tickPosition">
|
||||
<enum>QSlider::NoTicks</enum>
|
||||
<enum>QSlider::TickPosition::NoTicks</enum>
|
||||
</property>
|
||||
<property name="tickInterval">
|
||||
<number>1</number>
|
||||
|
|
@ -1062,7 +1052,7 @@
|
|||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
|
|
@ -1082,7 +1072,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>957</width>
|
||||
<height>22</height>
|
||||
<height>37</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
|
|
@ -1180,9 +1170,14 @@
|
|||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>NoScrollComboBox</class>
|
||||
<extends>QWidget</extends>
|
||||
<extends>QComboBox</extends>
|
||||
<header>noscrollcombobox.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>NoScrollSpinBox</class>
|
||||
<extends>QSpinBox</extends>
|
||||
<header>noscrollspinbox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ public:
|
|||
this->showTilesetEditorDivider = false;
|
||||
this->monitorFiles = true;
|
||||
this->tilesetCheckerboardFill = true;
|
||||
this->newMapHeaderSectionExpanded = false;
|
||||
this->theme = "default";
|
||||
this->wildMonChartTheme = "";
|
||||
this->textEditorOpenFolder = "";
|
||||
|
|
@ -123,6 +124,7 @@ public:
|
|||
bool showTilesetEditorDivider;
|
||||
bool monitorFiles;
|
||||
bool tilesetCheckerboardFill;
|
||||
bool newMapHeaderSectionExpanded;
|
||||
QString theme;
|
||||
QString wildMonChartTheme;
|
||||
QString textEditorOpenFolder;
|
||||
|
|
@ -135,6 +137,8 @@ public:
|
|||
QVersionNumber lastUpdateCheckVersion;
|
||||
QMap<QUrl, QDateTime> rateLimitTimes;
|
||||
QByteArray wildMonChartGeometry;
|
||||
QByteArray newMapDialogGeometry;
|
||||
QByteArray newLayoutDialogGeometry;
|
||||
|
||||
protected:
|
||||
virtual QString getConfigFilepath() override;
|
||||
|
|
@ -187,6 +191,7 @@ enum ProjectIdentifier {
|
|||
symbol_spawn_npcs,
|
||||
symbol_attribute_table,
|
||||
symbol_tilesets_prefix,
|
||||
symbol_dynamic_map_name,
|
||||
define_obj_event_count,
|
||||
define_min_level,
|
||||
define_max_level,
|
||||
|
|
@ -256,7 +261,6 @@ enum ProjectFilePath {
|
|||
data_pokemon_gfx,
|
||||
data_heal_locations,
|
||||
constants_global,
|
||||
constants_map_groups,
|
||||
constants_items,
|
||||
constants_flags,
|
||||
constants_vars,
|
||||
|
|
@ -328,7 +332,7 @@ public:
|
|||
QString getCustomFilePath(ProjectFilePath pathId);
|
||||
QString getCustomFilePath(const QString &pathId);
|
||||
QString getFilePath(ProjectFilePath pathId);
|
||||
void setIdentifier(ProjectIdentifier id, const QString &text);
|
||||
void setIdentifier(ProjectIdentifier id, QString text);
|
||||
void setIdentifier(const QString &id, const QString &text);
|
||||
QString getCustomIdentifier(ProjectIdentifier id);
|
||||
QString getCustomIdentifier(const QString &id);
|
||||
|
|
|
|||
18
include/core/advancemapparser.h
Normal file
18
include/core/advancemapparser.h
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef ADVANCEMAPPARSER_H
|
||||
#define ADVANCEMAPPARSER_H
|
||||
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QRgb>
|
||||
|
||||
class Project;
|
||||
class Layout;
|
||||
class Metatile;
|
||||
|
||||
namespace AdvanceMapParser {
|
||||
Layout *parseLayout(const QString &filepath, bool *error, const Project *project);
|
||||
QList<Metatile*> parseMetatiles(const QString &filepath, bool *error, bool primaryTileset);
|
||||
QList<QRgb> parsePalette(const QString &filepath, bool *error);
|
||||
};
|
||||
|
||||
#endif // ADVANCEMAPPARSER_H
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
#include "maplayout.h"
|
||||
#include "tileset.h"
|
||||
#include "events.h"
|
||||
#include "mapheader.h"
|
||||
|
||||
#include <QUndoStack>
|
||||
#include <QPixmap>
|
||||
|
|
@ -34,61 +35,56 @@ class Map : public QObject
|
|||
Q_OBJECT
|
||||
public:
|
||||
explicit Map(QObject *parent = nullptr);
|
||||
explicit Map(const Map &other, QObject *parent = nullptr);
|
||||
~Map();
|
||||
|
||||
public:
|
||||
QString name;
|
||||
QString constantName;
|
||||
void setName(const QString &mapName) { m_name = mapName; }
|
||||
QString name() const { return m_name; }
|
||||
|
||||
QString song;
|
||||
QString layoutId;
|
||||
QString location;
|
||||
bool requiresFlash;
|
||||
QString weather;
|
||||
QString type;
|
||||
bool show_location;
|
||||
bool allowRunning;
|
||||
bool allowBiking;
|
||||
bool allowEscaping;
|
||||
int floorNumber = 0;
|
||||
QString battle_scene;
|
||||
void setConstantName(const QString &constantName) { m_constantName = constantName; }
|
||||
QString constantName() const { return m_constantName; }
|
||||
|
||||
QString sharedEventsMap = "";
|
||||
QString sharedScriptsMap = "";
|
||||
|
||||
QStringList scriptsFileLabels;
|
||||
QMap<QString, QJsonValue> customHeaders;
|
||||
|
||||
Layout *layout = nullptr;
|
||||
void setLayout(Layout *layout);
|
||||
|
||||
bool isPersistedToFile = true;
|
||||
bool hasUnsavedDataChanges = false;
|
||||
|
||||
bool needsLayoutDir = true;
|
||||
bool needsHealLocation = false;
|
||||
bool scriptsLoaded = false;
|
||||
|
||||
QMap<Event::Group, QList<Event *>> events;
|
||||
QList<Event *> ownedEvents; // for memory management
|
||||
|
||||
QList<int> metatileLayerOrder;
|
||||
QList<float> metatileLayerOpacity;
|
||||
|
||||
void setName(QString mapName);
|
||||
static QString mapConstantFromName(QString mapName, bool includePrefix = true);
|
||||
|
||||
int getWidth();
|
||||
int getHeight();
|
||||
int getBorderWidth();
|
||||
int getBorderHeight();
|
||||
void setLayout(Layout *layout);
|
||||
Layout* layout() const { return m_layout; }
|
||||
|
||||
QList<Event *> getAllEvents() const;
|
||||
void setLayoutId(const QString &layoutId) { m_layoutId = layoutId; }
|
||||
QString layoutId() const { return m_layoutId; }
|
||||
|
||||
int getWidth() const;
|
||||
int getHeight() const;
|
||||
int getBorderWidth() const;
|
||||
int getBorderHeight() const;
|
||||
|
||||
void setHeader(const MapHeader &header) { *m_header = header; }
|
||||
MapHeader* header() const { return m_header; }
|
||||
|
||||
void setSharedEventsMap(const QString &sharedEventsMap) { m_sharedEventsMap = sharedEventsMap; }
|
||||
void setSharedScriptsMap(const QString &sharedScriptsMap) { m_sharedScriptsMap = sharedScriptsMap; }
|
||||
|
||||
QString sharedEventsMap() const { return m_sharedEventsMap; }
|
||||
QString sharedScriptsMap() const { return m_sharedScriptsMap; }
|
||||
|
||||
void setNeedsHealLocation(bool needsHealLocation) { m_needsHealLocation = needsHealLocation; }
|
||||
void setIsPersistedToFile(bool persistedToFile) { m_isPersistedToFile = persistedToFile; }
|
||||
void setHasUnsavedDataChanges(bool unsavedDataChanges) { m_hasUnsavedDataChanges = unsavedDataChanges; }
|
||||
|
||||
bool needsHealLocation() const { return m_needsHealLocation; }
|
||||
bool isPersistedToFile() const { return m_isPersistedToFile; }
|
||||
bool hasUnsavedDataChanges() const { return m_hasUnsavedDataChanges; }
|
||||
|
||||
void resetEvents();
|
||||
QList<Event *> getEvents(Event::Group group = Event::Group::None) const;
|
||||
Event* getEvent(Event::Group group, int index) const;
|
||||
int getNumEvents(Event::Group group = Event::Group::None) const;
|
||||
QStringList getScriptLabels(Event::Group group = Event::Group::None);
|
||||
QString getScriptsFilePath() const;
|
||||
void openScript(QString label);
|
||||
void removeEvent(Event *);
|
||||
void addEvent(Event *);
|
||||
int getIndexOfEvent(Event *) const;
|
||||
|
||||
void deleteConnections();
|
||||
QList<MapConnection*> getConnections() const;
|
||||
|
|
@ -98,18 +94,47 @@ public:
|
|||
QRect getConnectionRect(const QString &direction, Layout *fromLayout = nullptr);
|
||||
QPixmap renderConnection(const QString &direction, Layout *fromLayout = nullptr);
|
||||
|
||||
QUndoStack editHistory;
|
||||
QUndoStack* editHistory() const { return m_editHistory; }
|
||||
void commit(QUndoCommand*);
|
||||
void modify();
|
||||
void clean();
|
||||
void setClean();
|
||||
bool hasUnsavedChanges() const;
|
||||
void pruneEditHistory();
|
||||
|
||||
void setCustomAttributes(const QMap<QString, QJsonValue> &attributes) { m_customAttributes = attributes; }
|
||||
QMap<QString, QJsonValue> customAttributes() const { return m_customAttributes; }
|
||||
|
||||
private:
|
||||
QString m_name;
|
||||
QString m_constantName;
|
||||
QString m_layoutId;
|
||||
QString m_sharedEventsMap = "";
|
||||
QString m_sharedScriptsMap = "";
|
||||
|
||||
QStringList m_scriptsFileLabels;
|
||||
QMap<QString, QJsonValue> m_customAttributes;
|
||||
|
||||
MapHeader *m_header = nullptr;
|
||||
Layout *m_layout = nullptr;
|
||||
|
||||
bool m_isPersistedToFile = true;
|
||||
bool m_hasUnsavedDataChanges = false;
|
||||
bool m_needsHealLocation = false;
|
||||
bool m_scriptsLoaded = false;
|
||||
|
||||
QMap<Event::Group, QList<Event *>> m_events;
|
||||
QSet<Event *> m_ownedEvents; // for memory management
|
||||
|
||||
QList<int> m_metatileLayerOrder;
|
||||
QList<float> m_metatileLayerOpacity;
|
||||
|
||||
void trackConnection(MapConnection*);
|
||||
|
||||
// MapConnections in 'ownedConnections' but not 'connections' persist in the edit history.
|
||||
QList<MapConnection*> connections;
|
||||
QSet<MapConnection*> ownedConnections;
|
||||
QList<MapConnection*> m_connections;
|
||||
QSet<MapConnection*> m_ownedConnections;
|
||||
|
||||
QUndoStack *m_editHistory = nullptr;
|
||||
|
||||
signals:
|
||||
void modified();
|
||||
|
|
|
|||
83
include/core/mapheader.h
Normal file
83
include/core/mapheader.h
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
#ifndef MAPHEADER_H
|
||||
#define MAPHEADER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class MapHeader : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MapHeader(QObject *parent = nullptr) : QObject(parent) {};
|
||||
~MapHeader() {};
|
||||
MapHeader(const MapHeader& other);
|
||||
MapHeader& operator=(const MapHeader& other);
|
||||
bool operator==(const MapHeader& other) const {
|
||||
return m_song == other.m_song
|
||||
&& m_location == other.m_location
|
||||
&& m_requiresFlash == other.m_requiresFlash
|
||||
&& m_weather == other.m_weather
|
||||
&& m_type == other.m_type
|
||||
&& m_showsLocationName == other.m_showsLocationName
|
||||
&& m_allowsRunning == other.m_allowsRunning
|
||||
&& m_allowsBiking == other.m_allowsBiking
|
||||
&& m_allowsEscaping == other.m_allowsEscaping
|
||||
&& m_floorNumber == other.m_floorNumber
|
||||
&& m_battleScene == other.m_battleScene;
|
||||
}
|
||||
bool operator!=(const MapHeader& other) const {
|
||||
return !(operator==(other));
|
||||
}
|
||||
|
||||
void setSong(const QString &song);
|
||||
void setLocation(const QString &location);
|
||||
void setRequiresFlash(bool requiresFlash);
|
||||
void setWeather(const QString &weather);
|
||||
void setType(const QString &type);
|
||||
void setShowsLocationName(bool showsLocationName);
|
||||
void setAllowsRunning(bool allowsRunning);
|
||||
void setAllowsBiking(bool allowsBiking);
|
||||
void setAllowsEscaping(bool allowsEscaping);
|
||||
void setFloorNumber(int floorNumber);
|
||||
void setBattleScene(const QString &battleScene);
|
||||
|
||||
QString song() const { return m_song; }
|
||||
QString location() const { return m_location; }
|
||||
bool requiresFlash() const { return m_requiresFlash; }
|
||||
QString weather() const { return m_weather; }
|
||||
QString type() const { return m_type; }
|
||||
bool showsLocationName() const { return m_showsLocationName; }
|
||||
bool allowsRunning() const { return m_allowsRunning; }
|
||||
bool allowsBiking() const { return m_allowsBiking; }
|
||||
bool allowsEscaping() const { return m_allowsEscaping; }
|
||||
int floorNumber() const { return m_floorNumber; }
|
||||
QString battleScene() const { return m_battleScene; }
|
||||
|
||||
signals:
|
||||
void songChanged(QString);
|
||||
void locationChanged(QString);
|
||||
void requiresFlashChanged(bool);
|
||||
void weatherChanged(QString);
|
||||
void typeChanged(QString);
|
||||
void showsLocationNameChanged(bool);
|
||||
void allowsRunningChanged(bool);
|
||||
void allowsBikingChanged(bool);
|
||||
void allowsEscapingChanged(bool);
|
||||
void floorNumberChanged(int);
|
||||
void battleSceneChanged(QString);
|
||||
void modified();
|
||||
|
||||
private:
|
||||
QString m_song;
|
||||
QString m_location;
|
||||
bool m_requiresFlash = false;
|
||||
QString m_weather;
|
||||
QString m_type;
|
||||
bool m_showsLocationName = false;
|
||||
bool m_allowsRunning = false;
|
||||
bool m_allowsBiking = false;
|
||||
bool m_allowsEscaping = false;
|
||||
int m_floorNumber = 0;
|
||||
QString m_battleScene;
|
||||
};
|
||||
|
||||
#endif // MAPHEADER_H
|
||||
|
|
@ -18,8 +18,11 @@ class Layout : public QObject {
|
|||
Q_OBJECT
|
||||
public:
|
||||
Layout() {}
|
||||
Layout(const Layout &other);
|
||||
|
||||
static QString layoutConstantFromName(QString mapName);
|
||||
static QString defaultSuffix();
|
||||
|
||||
|
||||
bool loaded = false;
|
||||
|
||||
|
|
@ -70,24 +73,28 @@ public:
|
|||
QUndoStack editHistory;
|
||||
|
||||
// to simplify new layout settings transfer between functions
|
||||
struct SimpleSettings {
|
||||
struct Settings {
|
||||
QString id;
|
||||
QString name;
|
||||
// The name of a new layout's folder in `data/layouts/` is not always the same as the layout's name
|
||||
// (e.g. the majority of the default layouts use the name of their associated map).
|
||||
QString folderName;
|
||||
int width;
|
||||
int height;
|
||||
QString tileset_primary_label;
|
||||
QString tileset_secondary_label;
|
||||
QString from_id = QString();
|
||||
int borderWidth;
|
||||
int borderHeight;
|
||||
QString primaryTilesetLabel;
|
||||
QString secondaryTilesetLabel;
|
||||
};
|
||||
Settings settings() const;
|
||||
|
||||
public:
|
||||
Layout *copy();
|
||||
void copyFrom(Layout *other);
|
||||
Layout *copy() const;
|
||||
void copyFrom(const Layout *other);
|
||||
|
||||
int getWidth();
|
||||
int getHeight();
|
||||
int getBorderWidth();
|
||||
int getBorderHeight();
|
||||
int getWidth() const { return width; }
|
||||
int getHeight() const { return height; }
|
||||
int getBorderWidth() const { return border_width; }
|
||||
int getBorderHeight() const { return border_height; }
|
||||
|
||||
bool isWithinBounds(int x, int y);
|
||||
bool isWithinBorderBounds(int x, int y);
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
#ifndef MAPPARSER_H
|
||||
#define MAPPARSER_H
|
||||
|
||||
#include "maplayout.h"
|
||||
#include "project.h"
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
class MapParser
|
||||
{
|
||||
public:
|
||||
MapParser();
|
||||
Layout *parse(QString filepath, bool *error, Project *project);
|
||||
};
|
||||
|
||||
#endif // MAPPARSER_H
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
#pragma once
|
||||
#ifndef METATILEPARSER_H
|
||||
#define METATILEPARSER_H
|
||||
|
||||
#include "metatile.h"
|
||||
#include <QList>
|
||||
|
||||
namespace MetatileParser {
|
||||
QList<Metatile*> parse(QString filepath, bool *error, bool primaryTileset);
|
||||
}
|
||||
|
||||
#endif // METATILEPARSER_H
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
#include "heallocation.h"
|
||||
#include "log.h"
|
||||
#include "orderedjson.h"
|
||||
#include "orderedmap.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
|
|
@ -57,7 +58,7 @@ public:
|
|||
QMap<QString, int> readCDefinesByRegex(const QString &filename, const QStringList ®exList);
|
||||
QMap<QString, int> readCDefinesByName(const QString &filename, const QStringList &names);
|
||||
QStringList readCDefineNames(const QString &filename, const QStringList ®exList);
|
||||
QMap<QString, QHash<QString, QString>> readCStructs(const QString &, const QString & = "", const QHash<int, QString> = { });
|
||||
tsl::ordered_map<QString, QHash<QString, QString>> readCStructs(const QString &, const QString & = "", const QHash<int, QString>& = {});
|
||||
QList<QStringList> getLabelMacros(const QList<QStringList>&, const QString&);
|
||||
QStringList getLabelValues(const QList<QStringList>&, const QString&);
|
||||
bool tryParseJsonFile(QJsonDocument *out, const QString &filepath);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ struct LayoutSquare
|
|||
|
||||
struct MapSectionEntry
|
||||
{
|
||||
QString name = "";
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int width = 1;
|
||||
|
|
|
|||
|
|
@ -38,8 +38,6 @@ public:
|
|||
QList<QList<QRgb>> palettes;
|
||||
QList<QList<QRgb>> palettePreviews;
|
||||
|
||||
bool hasUnsavedTilesImage;
|
||||
|
||||
static Tileset* getMetatileTileset(int, Tileset*, Tileset*);
|
||||
static Tileset* getTileTileset(int, Tileset*, Tileset*);
|
||||
static Metatile* getMetatile(int, Tileset*, Tileset*);
|
||||
|
|
@ -56,10 +54,25 @@ public:
|
|||
static QHash<int, QString> getHeaderMemberMap(bool usingAsm);
|
||||
static QString getExpectedDir(QString tilesetName, bool isSecondary);
|
||||
QString getExpectedDir();
|
||||
|
||||
void load();
|
||||
void loadMetatiles();
|
||||
void loadMetatileAttributes();
|
||||
void loadTilesImage(QImage *importedImage = nullptr);
|
||||
void loadPalettes();
|
||||
|
||||
void save();
|
||||
void saveMetatileAttributes();
|
||||
void saveMetatiles();
|
||||
void saveTilesImage();
|
||||
void savePalettes();
|
||||
|
||||
bool appendToHeaders(QString root, QString friendlyName, bool usingAsm);
|
||||
bool appendToGraphics(QString root, QString friendlyName, bool usingAsm);
|
||||
bool appendToMetatiles(QString root, QString friendlyName, bool usingAsm);
|
||||
|
||||
void setTilesImage(const QImage &image);
|
||||
|
||||
void setMetatiles(const QList<Metatile*> &metatiles);
|
||||
void addMetatile(Metatile* metatile);
|
||||
|
||||
|
|
@ -72,6 +85,7 @@ public:
|
|||
|
||||
private:
|
||||
QList<Metatile*> m_metatiles;
|
||||
bool m_hasUnsavedTilesImage = false;
|
||||
};
|
||||
|
||||
#endif // TILESET_H
|
||||
|
|
|
|||
66
include/core/validator.h
Normal file
66
include/core/validator.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
#ifndef VALIDATOR_H
|
||||
#define VALIDATOR_H
|
||||
|
||||
/*
|
||||
This file contains our subclasses of QValidator.
|
||||
|
||||
- PrefixValidator is for input widgets that want to enforce a particular prefix.
|
||||
It differs from a QRegularExpressionValidator with a prefix in the regex because
|
||||
it will automatically enforce the prefix in fixup() if it isn't present.
|
||||
It's preferable to QLineEdit's input mask because it won't affect cursor behavior.
|
||||
|
||||
- IdentifierValidator is for validating that input text can be used for the name of an identifier in the project.
|
||||
(i.e., starts with a letter or underscore, then may continue with letters, numbers, or underscores).
|
||||
Unless a prefix is specified this is a normal QRegularExpressionValidator, we only have a subclass because we use it so often.
|
||||
|
||||
- UppercaseValidator is just a validator that uppercases input text.
|
||||
*/
|
||||
|
||||
#include <QValidator>
|
||||
|
||||
class PrefixValidator : public QRegularExpressionValidator {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PrefixValidator(const QString &prefix, QObject *parent = nullptr)
|
||||
: QRegularExpressionValidator(parent), m_prefix(prefix) {};
|
||||
explicit PrefixValidator(const QString &prefix, const QRegularExpression &re, QObject *parent = nullptr)
|
||||
: QRegularExpressionValidator(re, parent), m_prefix(prefix) {};
|
||||
~PrefixValidator() {};
|
||||
|
||||
virtual QValidator::State validate(QString &input, int &) const override;
|
||||
virtual void fixup(QString &input) const override;
|
||||
|
||||
QString prefix() const { return m_prefix; }
|
||||
void setPrefix(const QString &prefix);
|
||||
|
||||
bool isValid(QString &input) const;
|
||||
|
||||
private:
|
||||
QString m_prefix;
|
||||
|
||||
bool missingPrefix(const QString &input) const;
|
||||
};
|
||||
|
||||
class IdentifierValidator : public PrefixValidator {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit IdentifierValidator(QObject *parent = nullptr)
|
||||
: PrefixValidator("", re_identifier, parent) {};
|
||||
explicit IdentifierValidator(const QString &prefix, QObject *parent = nullptr)
|
||||
: PrefixValidator(prefix, re_identifier, parent) {};
|
||||
~IdentifierValidator() {};
|
||||
|
||||
private:
|
||||
static const QRegularExpression re_identifier;
|
||||
};
|
||||
|
||||
class UppercaseValidator : public QValidator {
|
||||
virtual QValidator::State validate(QString &input, int &) const override {
|
||||
input = input.toUpper();
|
||||
return QValidator::Acceptable;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // VALIDATOR_H
|
||||
69
include/lib/collapsiblesection.h
Normal file
69
include/lib/collapsiblesection.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
Elypson/qt-collapsible-section
|
||||
(c) 2016 Michael A. Voelkel - michael.alexander.voelkel@gmail.com
|
||||
|
||||
This file is part of Elypson/qt-collapsible section.
|
||||
|
||||
Elypson/qt-collapsible-section is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Elypson/qt-collapsible-section is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Elypson/qt-collapsible-section. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
PORYMAP NOTE: Modified to support having the section expanded by default, to stop the contents
|
||||
squashing during the collapse animation, and to add some guard rails against crashes.
|
||||
*/
|
||||
|
||||
#ifndef COLLAPSIBLESECTION_H
|
||||
#define COLLAPSIBLESECTION_H
|
||||
|
||||
#include <QFrame>
|
||||
#include <QGridLayout>
|
||||
#include <QParallelAnimationGroup>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QSet>
|
||||
#include <QScrollArea>
|
||||
#include <QToolButton>
|
||||
#include <QWidget>
|
||||
|
||||
class CollapsibleSection : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CollapsibleSection(const QString& title = "", const bool expanded = false, const int animationDuration = 0, QWidget* parent = 0);
|
||||
|
||||
void setContentLayout(QLayout* contentLayout);
|
||||
void setTitle(const QString &title);
|
||||
bool isExpanded() const { return this->expanded; }
|
||||
|
||||
public slots:
|
||||
void toggle(bool collapsed);
|
||||
|
||||
private:
|
||||
QGridLayout* mainLayout;
|
||||
QToolButton* toggleButton;
|
||||
QFrame* headerLine;
|
||||
QParallelAnimationGroup* toggleAnimation;
|
||||
QSet<QPropertyAnimation*> sectionAnimations;
|
||||
QPropertyAnimation* contentAnimation;
|
||||
QScrollArea* contentArea;
|
||||
int animationDuration;
|
||||
int collapsedHeight;
|
||||
bool expanded;
|
||||
|
||||
void updateToggleButton();
|
||||
void updateAnimationTargets();
|
||||
int getContentHeight() const;
|
||||
|
||||
};
|
||||
|
||||
#endif // COLLAPSIBLESECTION_H
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
#include "array_value.h"
|
||||
#include "define_statement.h"
|
||||
#include "lexer.h"
|
||||
#include "orderedmap.h"
|
||||
|
||||
namespace fex
|
||||
{
|
||||
|
|
@ -19,9 +20,9 @@ namespace fex
|
|||
|
||||
std::vector<DefineStatement> Parse(std::vector<Token> tokens);
|
||||
std::vector<Array> ParseTopLevelArrays(std::vector<Token> tokens);
|
||||
std::map<std::string, ArrayValue> ParseTopLevelObjects(std::vector<Token> tokens);
|
||||
tsl::ordered_map<std::string, ArrayValue> ParseTopLevelObjects(std::vector<Token> tokens);
|
||||
|
||||
std::map<std::string, int> ReadDefines(const QString &filename, std::vector<std::string> matching);
|
||||
tsl::ordered_map<std::string, int> ReadDefines(const QString &filename, std::vector<std::string> matching);
|
||||
|
||||
private:
|
||||
int EvaluateExpression(std::vector<Token> tokens);
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@
|
|||
#include "mapimageexporter.h"
|
||||
#include "filterchildrenproxymodel.h"
|
||||
#include "maplistmodels.h"
|
||||
#include "newmappopup.h"
|
||||
#include "newtilesetdialog.h"
|
||||
#include "shortcutseditor.h"
|
||||
#include "preferenceeditor.h"
|
||||
#include "projectsettingseditor.h"
|
||||
|
|
@ -32,6 +30,8 @@
|
|||
#include "wildmonchart.h"
|
||||
#include "updatepromoter.h"
|
||||
#include "aboutporymap.h"
|
||||
#include "mapheaderform.h"
|
||||
#include "newlayoutdialog.h"
|
||||
|
||||
|
||||
|
||||
|
|
@ -180,36 +180,29 @@ private slots:
|
|||
void duplicate();
|
||||
void setClipboardData(poryjson::Json::object);
|
||||
void setClipboardData(QImage);
|
||||
void setClipboardData(const QString &text);
|
||||
void copy();
|
||||
void paste();
|
||||
|
||||
void onLayoutChanged(Layout *layout);
|
||||
void onOpenConnectedMap(MapConnection*);
|
||||
void onTilesetsSaved(QString, QString);
|
||||
void openNewMapPopupWindow();
|
||||
void onNewMapCreated();
|
||||
void onNewMapCreated(Map *newMap, const QString &groupName);
|
||||
void onNewMapGroupCreated(const QString &groupName);
|
||||
void onNewMapSectionCreated(const QString &idName);
|
||||
void onMapSectionDisplayNameChanged(const QString &idName, const QString &displayName);
|
||||
void onNewLayoutCreated(Layout *layout);
|
||||
void onNewTilesetCreated(Tileset *tileset);
|
||||
void onMapLoaded(Map *map);
|
||||
void importMapFromAdvanceMap1_92();
|
||||
void onMapRulerStatusChanged(const QString &);
|
||||
void applyUserShortcuts();
|
||||
void markMapEdited();
|
||||
void markSpecificMapEdited(Map*);
|
||||
|
||||
void on_action_NewMap_triggered();
|
||||
void on_actionNew_Tileset_triggered();
|
||||
void on_action_Save_triggered();
|
||||
void on_action_Exit_triggered();
|
||||
void on_comboBox_Song_currentTextChanged(const QString &arg1);
|
||||
void on_comboBox_Location_currentTextChanged(const QString &arg1);
|
||||
void on_comboBox_Weather_currentTextChanged(const QString &arg1);
|
||||
void on_comboBox_Type_currentTextChanged(const QString &arg1);
|
||||
void on_comboBox_BattleScene_currentTextChanged(const QString &arg1);
|
||||
void on_comboBox_LayoutSelector_currentTextChanged(const QString &arg1);
|
||||
void on_checkBox_ShowLocation_stateChanged(int selected);
|
||||
void on_checkBox_AllowRunning_stateChanged(int selected);
|
||||
void on_checkBox_AllowBiking_stateChanged(int selected);
|
||||
void on_checkBox_AllowEscaping_stateChanged(int selected);
|
||||
void on_spinBox_FloorNumber_valueChanged(int offset);
|
||||
void on_comboBox_LayoutSelector_currentTextChanged(const QString &text);
|
||||
void on_actionShortcuts_triggered();
|
||||
|
||||
void on_actionZoom_In_triggered();
|
||||
|
|
@ -254,7 +247,6 @@ private slots:
|
|||
void on_comboBox_SecondaryTileset_currentTextChanged(const QString &arg1);
|
||||
void on_pushButton_ChangeDimensions_clicked();
|
||||
void on_checkBox_smartPaths_stateChanged(int selected);
|
||||
void on_checkBox_Visibility_stateChanged(int selected);
|
||||
void on_checkBox_ToggleBorder_stateChanged(int selected);
|
||||
|
||||
void resetMapViewScale();
|
||||
|
|
@ -313,7 +305,6 @@ private:
|
|||
QPointer<RegionMapEditor> regionMapEditor = nullptr;
|
||||
QPointer<ShortcutsEditor> shortcutsEditor = nullptr;
|
||||
QPointer<MapImageExporter> mapImageExporter = nullptr;
|
||||
QPointer<NewMapPopup> newMapPrompt = nullptr;
|
||||
QPointer<PreferenceEditor> preferenceEditor = nullptr;
|
||||
QPointer<ProjectSettingsEditor> projectSettingsEditor = nullptr;
|
||||
QPointer<GridSettingsDialog> gridSettingsDialog = nullptr;
|
||||
|
|
@ -321,8 +312,8 @@ private:
|
|||
|
||||
QPointer<FilterChildrenProxyModel> groupListProxyModel = nullptr;
|
||||
QPointer<MapGroupModel> mapGroupModel = nullptr;
|
||||
QPointer<FilterChildrenProxyModel> areaListProxyModel = nullptr;
|
||||
QPointer<MapAreaModel> mapAreaModel = nullptr;
|
||||
QPointer<FilterChildrenProxyModel> locationListProxyModel = nullptr;
|
||||
QPointer<MapLocationModel> mapLocationModel = nullptr;
|
||||
QPointer<FilterChildrenProxyModel> layoutListProxyModel = nullptr;
|
||||
QPointer<LayoutTreeModel> layoutTreeModel = nullptr;
|
||||
|
||||
|
|
@ -337,10 +328,11 @@ private:
|
|||
QAction *copyAction = nullptr;
|
||||
QAction *pasteAction = nullptr;
|
||||
|
||||
MapHeaderForm *mapHeaderForm = nullptr;
|
||||
|
||||
QMap<Event::Group, DraggablePixmapItem*> lastSelectedEvent;
|
||||
|
||||
bool isProgrammaticEventTabChange;
|
||||
bool newMapDefaultsSet = false;
|
||||
|
||||
bool tilesetNeedsRedraw = false;
|
||||
|
||||
|
|
@ -360,8 +352,15 @@ private:
|
|||
bool setProjectUI();
|
||||
void clearProjectUI();
|
||||
|
||||
void openNewMapDialog();
|
||||
void openDuplicateMapDialog(const QString &mapName);
|
||||
NewLayoutDialog* createNewLayoutDialog(const Layout *layoutToCopy = nullptr);
|
||||
void openNewLayoutDialog();
|
||||
void openDuplicateLayoutDialog(const QString &layoutId);
|
||||
void openNewMapGroupDialog();
|
||||
void openNewLocationDialog();
|
||||
void openSubWindow(QWidget * window);
|
||||
void scrollMapList(MapTree *list, QString itemName);
|
||||
void scrollMapList(MapTree *list, const QString &itemName);
|
||||
void scrollMapListToCurrentMap(MapTree *list);
|
||||
void scrollMapListToCurrentLayout(MapTree *list);
|
||||
void resetMapListFilters();
|
||||
|
|
@ -369,7 +368,9 @@ private:
|
|||
QString getExistingDirectory(QString);
|
||||
bool openProject(QString dir, bool initial = false);
|
||||
bool closeProject();
|
||||
void showRecentError(const QString &baseMessage);
|
||||
void showProjectOpenFailure();
|
||||
void showMapsExcludedAlert(const QStringList &excludedMapNames);
|
||||
|
||||
bool setInitialMap();
|
||||
void saveGlobalConfigs();
|
||||
|
|
@ -377,9 +378,6 @@ private:
|
|||
void refreshRecentProjectsMenu();
|
||||
|
||||
void updateMapList();
|
||||
void mapListAddGroup();
|
||||
void mapListAddLayout();
|
||||
void mapListAddArea();
|
||||
void openMapListItem(const QModelIndex &index);
|
||||
void saveMapListTab(int index);
|
||||
|
||||
|
|
@ -419,11 +417,10 @@ private:
|
|||
void scrollMetatileSelectorToSelection();
|
||||
MapListToolBar* getCurrentMapListToolBar();
|
||||
MapTree* getCurrentMapList();
|
||||
void refreshLocationsComboBox();
|
||||
void setLocationComboBoxes(const QStringList &locations);
|
||||
|
||||
QObjectList shortcutableObjects() const;
|
||||
void addCustomHeaderValue(QString key, QJsonValue value, bool isNew = false);
|
||||
int insertTilesetLabel(QStringList * list, QString label);
|
||||
|
||||
void checkForUpdates(bool requestedByUser);
|
||||
void setDivingMapsVisible(bool visible);
|
||||
|
|
@ -450,7 +447,7 @@ struct MapViewTab {
|
|||
|
||||
struct MapListTab {
|
||||
enum {
|
||||
Groups = 0, Areas, Layouts
|
||||
Groups = 0, Locations, Layouts
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -18,9 +18,6 @@
|
|||
#include <QVariant>
|
||||
#include <QFileSystemWatcher>
|
||||
|
||||
// The displayed name of the special map value used by warps with multiple potential destinations
|
||||
static QString DYNAMIC_MAP_NAME = "Dynamic";
|
||||
|
||||
class Project : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -35,18 +32,18 @@ public:
|
|||
|
||||
public:
|
||||
QString root;
|
||||
QStringList groupNames;
|
||||
QMap<QString, int> mapGroups;
|
||||
QList<QStringList> groupedMapNames;
|
||||
QStringList mapNames;
|
||||
QStringList groupNames;
|
||||
QMap<QString, QStringList> groupNameToMapNames;
|
||||
QList<HealLocation> healLocations;
|
||||
QMap<QString, int> healLocationNameToValue;
|
||||
QMap<QString, QString> mapConstantsToMapNames;
|
||||
QMap<QString, QString> mapNamesToMapConstants;
|
||||
QStringList mapLayoutsTable;
|
||||
QStringList mapLayoutsTableMaster;
|
||||
QMap<QString, QString> mapNameToLayoutId;
|
||||
QMap<QString, QString> mapNameToMapSectionName;
|
||||
QString layoutsLabel;
|
||||
QMap<QString, QString> layoutIdsToNames;
|
||||
QStringList layoutIds;
|
||||
QStringList layoutIdsMaster;
|
||||
QMap<QString, Layout*> mapLayouts;
|
||||
QMap<QString, Layout*> mapLayoutsMaster;
|
||||
QMap<QString, EventGraphics*> eventGraphicsMap;
|
||||
|
|
@ -65,6 +62,7 @@ public:
|
|||
QStringList bgEventFacingDirections;
|
||||
QStringList trainerTypes;
|
||||
QStringList globalScriptLabels;
|
||||
QStringList mapSectionIdNamesSaveOrder;
|
||||
QStringList mapSectionIdNames;
|
||||
QMap<QString, MapSectionEntry> regionMapEntries;
|
||||
QMap<QString, QMap<QString, uint16_t>> metatileLabelsMap;
|
||||
|
|
@ -77,11 +75,11 @@ public:
|
|||
QMap<QString, qint64> modifiedFileTimestamps;
|
||||
bool usingAsmTilesets;
|
||||
QSet<QString> disabledSettingsNames;
|
||||
QSet<QString> topLevelMapFields;
|
||||
int pokemonMinLevel;
|
||||
int pokemonMaxLevel;
|
||||
int maxEncounterRate;
|
||||
bool wildEncountersLoaded;
|
||||
bool saveEmptyMapsec;
|
||||
|
||||
void set_root(QString);
|
||||
|
||||
|
|
@ -113,7 +111,7 @@ public:
|
|||
QStringList secondaryTilesetLabels;
|
||||
QStringList tilesetLabelsOrdered;
|
||||
|
||||
Blockdata readBlockdata(QString);
|
||||
Blockdata readBlockdata(QString, bool *ok = nullptr);
|
||||
bool loadBlockdata(Layout *);
|
||||
bool loadLayoutBorder(Layout *);
|
||||
|
||||
|
|
@ -122,12 +120,29 @@ public:
|
|||
void deleteFile(QString path);
|
||||
|
||||
bool readMapGroups();
|
||||
Map* addNewMapToGroup(QString, int, Map*, bool, bool);
|
||||
QString getNewMapName();
|
||||
QString getProjectTitle();
|
||||
void addNewMapGroup(const QString &groupName);
|
||||
QString mapNameToMapGroup(const QString &mapName);
|
||||
|
||||
QString readMapLayoutId(QString map_name);
|
||||
QString readMapLocation(QString map_name);
|
||||
struct NewMapSettings {
|
||||
QString name;
|
||||
QString group;
|
||||
bool canFlyTo;
|
||||
Layout::Settings layout;
|
||||
MapHeader header;
|
||||
};
|
||||
NewMapSettings newMapSettings;
|
||||
Layout::Settings newLayoutSettings;
|
||||
|
||||
void initNewMapSettings();
|
||||
void initNewLayoutSettings();
|
||||
|
||||
Map *createNewMap(const Project::NewMapSettings &mapSettings, const Map* toDuplicate = nullptr);
|
||||
Layout *createNewLayout(const Layout::Settings &layoutSettings, const Layout* toDuplicate = nullptr);
|
||||
Tileset *createNewTileset(QString name, bool secondary, bool checkerboardFill);
|
||||
bool isIdentifierUnique(const QString &identifier) const;
|
||||
bool isValidNewIdentifier(QString identifier) const;
|
||||
QString toUniqueIdentifier(const QString &identifier) const;
|
||||
QString getProjectTitle();
|
||||
|
||||
bool readWildMonData();
|
||||
tsl::ordered_map<QString, tsl::ordered_map<QString, WildPokemonHeader>> wildMonData;
|
||||
|
|
@ -139,25 +154,24 @@ public:
|
|||
bool readSpeciesIconPaths();
|
||||
QMap<QString, QString> speciesToIconPath;
|
||||
|
||||
void addNewMapsec(const QString &name);
|
||||
void removeMapsec(const QString &name);
|
||||
void addNewMapsec(const QString &idName);
|
||||
void removeMapsec(const QString &idName);
|
||||
QString getMapsecDisplayName(const QString &idName) const { return this->mapSectionDisplayNames.value(idName); }
|
||||
void setMapsecDisplayName(const QString &idName, const QString &displayName);
|
||||
|
||||
bool hasUnsavedChanges();
|
||||
bool hasUnsavedDataChanges = false;
|
||||
|
||||
QSet<QString> getTopLevelMapFields();
|
||||
void initTopLevelMapFields();
|
||||
bool readMapJson(const QString &mapName, QJsonDocument * out);
|
||||
bool loadMapData(Map*);
|
||||
bool readMapLayouts();
|
||||
Layout *loadLayout(QString layoutId);
|
||||
Layout *createNewLayout(Layout::SimpleSettings &layoutSettings);
|
||||
bool loadLayout(Layout *);
|
||||
bool loadMapLayout(Map*);
|
||||
bool loadLayoutTilesets(Layout *);
|
||||
void loadTilesetAssets(Tileset*);
|
||||
void loadTilesetTiles(Tileset*, QImage);
|
||||
void loadTilesetMetatiles(Tileset*);
|
||||
void loadTilesetMetatileLabels(Tileset*);
|
||||
void loadTilesetPalettes(Tileset*);
|
||||
void readTilesetPaths(Tileset* tileset);
|
||||
|
||||
void saveLayout(Layout *);
|
||||
|
|
@ -172,15 +186,10 @@ public:
|
|||
void saveMapGroups();
|
||||
void saveRegionMapSections();
|
||||
void saveWildMonData();
|
||||
void saveMapConstantsHeader();
|
||||
void saveHealLocations(Map*);
|
||||
void saveTilesets(Tileset*, Tileset*);
|
||||
void saveTilesetMetatileLabels(Tileset*, Tileset*);
|
||||
void saveTilesetMetatileAttributes(Tileset*);
|
||||
void saveTilesetMetatiles(Tileset*);
|
||||
void saveTilesetTilesImage(Tileset*);
|
||||
void saveTilesetPalettes(Tileset*);
|
||||
void appendTilesetLabel(QString label, QString isSecondaryStr);
|
||||
void appendTilesetLabel(const QString &label, const QString &isSecondaryStr);
|
||||
bool readTilesetLabels();
|
||||
bool readTilesetMetatileLabels();
|
||||
bool readRegionMapSections();
|
||||
|
|
@ -217,9 +226,8 @@ public:
|
|||
QString getScriptDefaultString(bool usePoryScript, QString mapName) const;
|
||||
QStringList getEventScriptsFilePaths() const;
|
||||
|
||||
QString getDefaultPrimaryTilesetLabel();
|
||||
QString getDefaultSecondaryTilesetLabel();
|
||||
QString getDynamicMapDefineName();
|
||||
QString getDefaultPrimaryTilesetLabel() const;
|
||||
QString getDefaultSecondaryTilesetLabel() const;
|
||||
void updateTilesetMetatileLabels(Tileset *tileset);
|
||||
QString buildMetatileLabelsText(const QMap<QString, uint16_t> defines);
|
||||
QString findMetatileLabelsTileset(QString label);
|
||||
|
|
@ -227,6 +235,9 @@ public:
|
|||
static QString getExistingFilepath(QString filepath);
|
||||
void applyParsedLimits();
|
||||
|
||||
static QString getEmptyMapDefineName();
|
||||
static QString getDynamicMapDefineName();
|
||||
static QString getDynamicMapName();
|
||||
static int getNumTilesPrimary();
|
||||
static int getNumTilesTotal();
|
||||
static int getNumMetatilesPrimary();
|
||||
|
|
@ -234,7 +245,7 @@ public:
|
|||
static int getNumPalettesPrimary();
|
||||
static int getNumPalettesTotal();
|
||||
static int getMaxMapDataSize();
|
||||
static int getDefaultMapSize();
|
||||
static int getDefaultMapDimension();
|
||||
static int getMaxMapWidth();
|
||||
static int getMaxMapHeight();
|
||||
static int getMapDataSize(int width, int height);
|
||||
|
|
@ -242,14 +253,17 @@ public:
|
|||
bool calculateDefaultMapSize();
|
||||
static int getMaxObjectEvents();
|
||||
static QString getEmptyMapsecName();
|
||||
static QString getMapGroupPrefix();
|
||||
|
||||
static void numericalModeSort(QStringList &list);
|
||||
|
||||
private:
|
||||
QMap<QString, QString> mapSectionDisplayNames;
|
||||
|
||||
void updateLayout(Layout *);
|
||||
|
||||
void setNewLayoutBlockdata(Layout *layout);
|
||||
void setNewLayoutBorder(Layout *layout);
|
||||
void setNewMapEvents(Map *map);
|
||||
void setNewMapConnections(Map *map);
|
||||
|
||||
void saveHealLocationsData(Map *map);
|
||||
void saveHealLocationsConstants();
|
||||
|
|
@ -262,13 +276,20 @@ private:
|
|||
static int num_pals_primary;
|
||||
static int num_pals_total;
|
||||
static int max_map_data_size;
|
||||
static int default_map_size;
|
||||
static int default_map_dimension;
|
||||
static int max_object_events;
|
||||
|
||||
signals:
|
||||
void fileChanged(QString filepath);
|
||||
void mapSectionIdNamesChanged();
|
||||
void mapLoaded(Map *map);
|
||||
void mapCreated(Map *newMap, const QString &groupName);
|
||||
void layoutCreated(Layout *newLayout);
|
||||
void tilesetCreated(Tileset *newTileset);
|
||||
void mapGroupAdded(const QString &groupName);
|
||||
void mapSectionAdded(const QString &idName);
|
||||
void mapSectionDisplayNameChanged(const QString &idName, const QString &displayName);
|
||||
void mapSectionIdNamesChanged(const QStringList &idNames);
|
||||
void mapsExcluded(const QStringList &excludedMapNames);
|
||||
};
|
||||
|
||||
#endif // PROJECT_H
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
#define ABOUTPORYMAP_H
|
||||
|
||||
#include <QString>
|
||||
#include <QRegularExpression>
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
#define COLORINPUTWIDGET_H
|
||||
|
||||
#include <QGroupBox>
|
||||
#include <QValidator>
|
||||
|
||||
namespace Ui {
|
||||
class ColorInputWidget;
|
||||
|
|
|
|||
84
include/ui/mapheaderform.h
Normal file
84
include/ui/mapheaderform.h
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
#ifndef MAPHEADERFORM_H
|
||||
#define MAPHEADERFORM_H
|
||||
|
||||
/*
|
||||
This is the UI class used to edit the fields in a map's header.
|
||||
It's intended to be used anywhere the UI needs to present an editor for a map's header,
|
||||
e.g. for the current map in the main editor or in the new map dialog.
|
||||
*/
|
||||
|
||||
#include <QWidget>
|
||||
#include <QPointer>
|
||||
#include "mapheader.h"
|
||||
|
||||
class Project;
|
||||
|
||||
namespace Ui {
|
||||
class MapHeaderForm;
|
||||
}
|
||||
|
||||
class MapHeaderForm : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MapHeaderForm(QWidget *parent = nullptr);
|
||||
~MapHeaderForm();
|
||||
|
||||
void setProject(Project * project, bool allowProjectChanges = true);
|
||||
void clear();
|
||||
|
||||
void setHeader(MapHeader *header);
|
||||
void setHeaderData(const MapHeader &header);
|
||||
MapHeader headerData() const;
|
||||
|
||||
void setSong(const QString &song);
|
||||
void setLocation(const QString &location);
|
||||
void setLocationName(const QString &locationName);
|
||||
void setRequiresFlash(bool requiresFlash);
|
||||
void setWeather(const QString &weather);
|
||||
void setType(const QString &type);
|
||||
void setBattleScene(const QString &battleScene);
|
||||
void setShowsLocationName(bool showsLocationName);
|
||||
void setAllowsRunning(bool allowsRunning);
|
||||
void setAllowsBiking(bool allowsBiking);
|
||||
void setAllowsEscaping(bool allowsEscaping);
|
||||
void setFloorNumber(int floorNumber);
|
||||
|
||||
QString song() const;
|
||||
QString location() const;
|
||||
QString locationName() const;
|
||||
bool requiresFlash() const;
|
||||
QString weather() const;
|
||||
QString type() const;
|
||||
QString battleScene() const;
|
||||
bool showsLocationName() const;
|
||||
bool allowsRunning() const;
|
||||
bool allowsBiking() const;
|
||||
bool allowsEscaping() const;
|
||||
int floorNumber() const;
|
||||
|
||||
private:
|
||||
Ui::MapHeaderForm *ui;
|
||||
QPointer<MapHeader> m_header = nullptr;
|
||||
QPointer<Project> m_project = nullptr;
|
||||
bool m_allowProjectChanges = true;
|
||||
|
||||
void setLocations(const QStringList &locations);
|
||||
void updateLocationName();
|
||||
|
||||
void onSongUpdated(const QString &song);
|
||||
void onLocationChanged(const QString &location);
|
||||
void onLocationNameChanged(const QString &locationName);
|
||||
void onWeatherChanged(const QString &weather);
|
||||
void onTypeChanged(const QString &type);
|
||||
void onBattleSceneChanged(const QString &battleScene);
|
||||
void onRequiresFlashChanged(int selected);
|
||||
void onShowLocationNameChanged(int selected);
|
||||
void onAllowRunningChanged(int selected);
|
||||
void onAllowBikingChanged(int selected);
|
||||
void onAllowEscapingChanged(int selected);
|
||||
void onFloorNumberChanged(int offset);
|
||||
};
|
||||
|
||||
#endif // MAPHEADERFORM_H
|
||||
|
|
@ -45,22 +45,25 @@ public:
|
|||
private:
|
||||
Ui::MapImageExporter *ui;
|
||||
|
||||
Layout *layout = nullptr;
|
||||
Map *map = nullptr;
|
||||
Editor *editor = nullptr;
|
||||
QGraphicsScene *scene = nullptr;
|
||||
Layout *m_layout = nullptr;
|
||||
Map *m_map = nullptr;
|
||||
Editor *m_editor = nullptr;
|
||||
QGraphicsScene *m_scene = nullptr;
|
||||
|
||||
QPixmap preview;
|
||||
QPixmap m_preview;
|
||||
|
||||
ImageExporterSettings settings;
|
||||
ImageExporterMode mode = ImageExporterMode::Normal;
|
||||
ImageExporterSettings m_settings;
|
||||
ImageExporterMode m_mode = ImageExporterMode::Normal;
|
||||
|
||||
void updatePreview();
|
||||
void scalePreview();
|
||||
void updateShowBorderState();
|
||||
void saveImage();
|
||||
QPixmap getStitchedImage(QProgressDialog *progress, bool includeBorder);
|
||||
QPixmap getFormattedMapPixmap();
|
||||
QPixmap getFormattedMapPixmap(Map *map, bool ignoreBorder = false);
|
||||
QPixmap getFormattedLayoutPixmap(Layout *layout, bool ignoreBorder = false, bool ignoreGrid = false);
|
||||
void paintGrid(QPixmap *pixmap, bool ignoreBorder = false);
|
||||
bool historyItemAppliesToFrame(const QUndoCommand *command);
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -13,9 +13,8 @@
|
|||
class Project;
|
||||
|
||||
enum MapListUserRoles {
|
||||
GroupRole = Qt::UserRole + 1, // Used to hold the map group number.
|
||||
TypeRole, // Used to differentiate between the different layers of the map list tree view.
|
||||
TypeRole2, // Used for various extra data needed.
|
||||
NameRole = Qt::UserRole, // Holds the name of the item in the list
|
||||
TypeRole, // Used to differentiate between the different layers of the map list tree view.
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -55,22 +54,47 @@ private:
|
|||
};
|
||||
|
||||
|
||||
|
||||
class QRegularExpressionValidator;
|
||||
|
||||
class MapListModel : public QStandardItemModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MapListModel(QObject *parent = nullptr) : QStandardItemModel(parent) {};
|
||||
MapListModel(Project *project, QObject *parent = nullptr);
|
||||
~MapListModel() { }
|
||||
|
||||
virtual QModelIndex indexOf(QString id) const = 0;
|
||||
void setActiveItem(const QString &itemName) { this->activeItemName = itemName; }
|
||||
|
||||
virtual QStandardItem *insertMapItem(const QString &mapName, const QString &folderName);
|
||||
virtual QStandardItem *insertMapFolderItem(const QString &folderName);
|
||||
|
||||
virtual QModelIndex indexOf(const QString &itemName) const;
|
||||
virtual void removeItemAt(const QModelIndex &index);
|
||||
virtual QStandardItem *getItem(const QModelIndex &index) const = 0;
|
||||
virtual QStandardItem *itemAt(const QModelIndex &index) const;
|
||||
virtual QStandardItem *itemAt(const QString &itemName) const;
|
||||
|
||||
virtual QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
protected:
|
||||
virtual void removeItem(QStandardItem *item) = 0;
|
||||
Project *project;
|
||||
QStandardItem *root = nullptr;
|
||||
|
||||
QString activeItemName;
|
||||
QString folderTypeName;
|
||||
bool sortingEnabled = false;
|
||||
bool editable = false;
|
||||
|
||||
QIcon mapGrayIcon;
|
||||
QIcon mapIcon;
|
||||
QIcon mapEditedIcon;
|
||||
QIcon mapOpenedIcon;
|
||||
QIcon mapFolderIcon;
|
||||
QIcon emptyMapFolderIcon;
|
||||
|
||||
QMap<QString, QStandardItem *> mapFolderItems;
|
||||
QMap<QString, QStandardItem *> mapItems;
|
||||
|
||||
virtual QStandardItem *createMapItem(const QString &mapName, QStandardItem *map = nullptr);
|
||||
virtual QStandardItem *createMapFolderItem(const QString &groupName, QStandardItem *fromItem = nullptr);
|
||||
virtual void removeItem(QStandardItem *item) = 0;
|
||||
};
|
||||
|
||||
class MapGroupModel : public MapListModel {
|
||||
|
|
@ -81,87 +105,37 @@ public:
|
|||
~MapGroupModel() { }
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||
|
||||
Qt::DropActions supportedDropActions() const override;
|
||||
QStringList mimeTypes() const override;
|
||||
virtual QMimeData *mimeData(const QModelIndexList &indexes) const override;
|
||||
virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
|
||||
|
||||
virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
|
||||
|
||||
public:
|
||||
void setMap(QString mapName) { this->openMap = mapName; }
|
||||
|
||||
QStandardItem *createGroupItem(QString groupName, int groupIndex, QStandardItem *fromItem = nullptr);
|
||||
QStandardItem *createMapItem(QString mapName, QStandardItem *fromItem = nullptr);
|
||||
|
||||
QStandardItem *insertGroupItem(QString groupName);
|
||||
QStandardItem *insertMapItem(QString mapName, QString groupName);
|
||||
|
||||
virtual QStandardItem *getItem(const QModelIndex &index) const override;
|
||||
virtual QModelIndex indexOf(QString mapName) const override;
|
||||
|
||||
void initialize();
|
||||
QMimeData *mimeData(const QModelIndexList &indexes) const override;
|
||||
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
|
||||
|
||||
protected:
|
||||
virtual void removeItem(QStandardItem *item) override;
|
||||
void removeItem(QStandardItem *item) override;
|
||||
|
||||
private:
|
||||
friend class MapTree;
|
||||
void updateProject();
|
||||
|
||||
private:
|
||||
Project *project;
|
||||
QStandardItem *root = nullptr;
|
||||
|
||||
QMap<QString, QStandardItem *> groupItems;
|
||||
QMap<QString, QStandardItem *> mapItems;
|
||||
|
||||
QString openMap;
|
||||
|
||||
signals:
|
||||
void dragMoveCompleted();
|
||||
};
|
||||
|
||||
|
||||
|
||||
class MapAreaModel : public MapListModel {
|
||||
class MapLocationModel : public MapListModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MapAreaModel(Project *project, QObject *parent = nullptr);
|
||||
~MapAreaModel() {}
|
||||
MapLocationModel(Project *project, QObject *parent = nullptr);
|
||||
~MapLocationModel() {}
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
public:
|
||||
void setMap(QString mapName) { this->openMap = mapName; }
|
||||
|
||||
QStandardItem *createAreaItem(QString areaName);
|
||||
QStandardItem *createMapItem(QString mapName, int areaIndex, int mapIndex);
|
||||
|
||||
QStandardItem *insertAreaItem(QString areaName);
|
||||
QStandardItem *insertMapItem(QString mapName, QString areaName, int groupIndex);
|
||||
|
||||
virtual QStandardItem *getItem(const QModelIndex &index) const override;
|
||||
virtual QModelIndex indexOf(QString mapName) const override;
|
||||
|
||||
void initialize();
|
||||
QStandardItem *createMapFolderItem(const QString &folderName, QStandardItem *folder) override;
|
||||
|
||||
protected:
|
||||
virtual void removeItem(QStandardItem *item) override;
|
||||
|
||||
private:
|
||||
Project *project;
|
||||
QStandardItem *root = nullptr;
|
||||
|
||||
QMap<QString, QStandardItem *> areaItems;
|
||||
QMap<QString, QStandardItem *> mapItems;
|
||||
|
||||
QString openMap;
|
||||
|
||||
signals:
|
||||
void edited();
|
||||
void removeItem(QStandardItem *item) override;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -174,35 +148,10 @@ public:
|
|||
~LayoutTreeModel() {}
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
public:
|
||||
void setLayout(QString layoutId) { this->openLayout = layoutId; }
|
||||
|
||||
QStandardItem *createLayoutItem(QString layoutId);
|
||||
QStandardItem *createMapItem(QString mapName);
|
||||
|
||||
QStandardItem *insertLayoutItem(QString layoutId);
|
||||
QStandardItem *insertMapItem(QString mapName, QString layoutId);
|
||||
|
||||
virtual QStandardItem *getItem(const QModelIndex &index) const override;
|
||||
virtual QModelIndex indexOf(QString layoutName) const override;
|
||||
|
||||
void initialize();
|
||||
QStandardItem *createMapFolderItem(const QString &folderName, QStandardItem *folder) override;
|
||||
|
||||
protected:
|
||||
virtual void removeItem(QStandardItem *item) override;
|
||||
|
||||
private:
|
||||
Project *project;
|
||||
QStandardItem *root = nullptr;
|
||||
|
||||
QMap<QString, QStandardItem *> layoutItems;
|
||||
QMap<QString, QStandardItem *> mapItems;
|
||||
|
||||
QString openLayout;
|
||||
|
||||
signals:
|
||||
void edited();
|
||||
void removeItem(QStandardItem *item) override;
|
||||
};
|
||||
|
||||
#endif // MAPLISTMODELS_H
|
||||
|
|
|
|||
60
include/ui/message.h
Normal file
60
include/ui/message.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#pragma once
|
||||
#ifndef MESSAGE_H
|
||||
#define MESSAGE_H
|
||||
|
||||
/*
|
||||
These classes are thin wrappers around QMessageBox for convenience.
|
||||
The base Message class is a regular window-modal QMessageBox with "porymap" as the window title.
|
||||
|
||||
QMessageBox's static functions enforce application modality (among other things), which changes the style of the message boxes on macOS.
|
||||
With these equivalent static functions we have more control over the appearance and behavior of the window,
|
||||
and we keep the convenience of not needing to provide all the arguments.
|
||||
|
||||
If more control is needed (like adding custom buttons to the window) use the constructors as you would for a normal QMessageBox.
|
||||
*/
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
class Message : public QMessageBox {
|
||||
public:
|
||||
Message(QMessageBox::Icon icon, const QString &text, QMessageBox::StandardButtons buttons, QWidget *parent);
|
||||
};
|
||||
|
||||
// Basic error message with an 'Ok' button.
|
||||
class ErrorMessage : public Message {
|
||||
public:
|
||||
ErrorMessage(const QString &message, QWidget *parent);
|
||||
static int show(const QString &message, QWidget *parent);
|
||||
};
|
||||
|
||||
// Basic warning message with an 'Ok' button.
|
||||
class WarningMessage : public Message {
|
||||
public:
|
||||
WarningMessage(const QString &message, QWidget *parent);
|
||||
static int show(const QString &message, QWidget *parent);
|
||||
};
|
||||
|
||||
// Basic informational message with a 'Close' button.
|
||||
class InfoMessage : public Message {
|
||||
public:
|
||||
InfoMessage(const QString &message, QWidget *parent);
|
||||
static int show(const QString &message, QWidget *parent);
|
||||
};
|
||||
|
||||
// Basic question message with a 'Yes' and 'No' button.
|
||||
class QuestionMessage : public Message {
|
||||
public:
|
||||
QuestionMessage(const QString &message, QWidget *parent);
|
||||
static int show(const QString &message, QWidget *parent);
|
||||
};
|
||||
|
||||
// Error message directing users to their log file.
|
||||
// Shows the most recent error as detailed text.
|
||||
class RecentErrorMessage : public ErrorMessage {
|
||||
public:
|
||||
RecentErrorMessage(const QString &message, QWidget *parent);
|
||||
static int show(const QString &message, QWidget *parent);
|
||||
};
|
||||
|
||||
|
||||
#endif // MESSAGE_H
|
||||
49
include/ui/newlayoutdialog.h
Normal file
49
include/ui/newlayoutdialog.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#ifndef NEWLAYOUTDIALOG_H
|
||||
#define NEWLAYOUTDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QString>
|
||||
#include "editor.h"
|
||||
#include "project.h"
|
||||
#include "map.h"
|
||||
#include "mapheaderform.h"
|
||||
#include "newlayoutform.h"
|
||||
#include "lib/collapsiblesection.h"
|
||||
|
||||
namespace Ui {
|
||||
class NewLayoutDialog;
|
||||
}
|
||||
|
||||
class NewLayoutDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit NewLayoutDialog(Project *project, QWidget *parent = nullptr);
|
||||
explicit NewLayoutDialog(Project *project, const Layout *layoutToCopy, QWidget *parent = nullptr);
|
||||
~NewLayoutDialog();
|
||||
|
||||
virtual void accept() override;
|
||||
|
||||
signals:
|
||||
void applied(const QString &newLayoutId);
|
||||
|
||||
private:
|
||||
Ui::NewLayoutDialog *ui;
|
||||
Project *project;
|
||||
const Layout *layoutToCopy;
|
||||
|
||||
// Each of these validation functions will allow empty names up until `OK` is selected,
|
||||
// because clearing the text during editing is common and we don't want to flash errors for this.
|
||||
bool validateLayoutID(bool allowEmpty = false);
|
||||
bool validateName(bool allowEmpty = false);
|
||||
|
||||
void refresh();
|
||||
void saveSettings();
|
||||
|
||||
private slots:
|
||||
void dialogButtonClicked(QAbstractButton *button);
|
||||
void on_lineEdit_Name_textChanged(const QString &);
|
||||
void on_lineEdit_LayoutID_textChanged(const QString &);
|
||||
};
|
||||
|
||||
#endif // NEWLAYOUTDIALOG_H
|
||||
40
include/ui/newlayoutform.h
Normal file
40
include/ui/newlayoutform.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef NEWLAYOUTFORM_H
|
||||
#define NEWLAYOUTFORM_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "maplayout.h"
|
||||
|
||||
class Project;
|
||||
|
||||
namespace Ui {
|
||||
class NewLayoutForm;
|
||||
}
|
||||
|
||||
class NewLayoutForm : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NewLayoutForm(QWidget *parent = nullptr);
|
||||
~NewLayoutForm();
|
||||
|
||||
void initUi(Project *project);
|
||||
|
||||
void setSettings(const Layout::Settings &settings);
|
||||
Layout::Settings settings() const;
|
||||
|
||||
void setDisabled(bool disabled);
|
||||
|
||||
bool validate();
|
||||
|
||||
private:
|
||||
Ui::NewLayoutForm *ui;
|
||||
Project *m_project;
|
||||
|
||||
bool validateMapDimensions();
|
||||
bool validatePrimaryTileset(bool allowEmpty = false);
|
||||
bool validateSecondaryTileset(bool allowEmpty = false);
|
||||
};
|
||||
|
||||
#endif // NEWLAYOUTFORM_H
|
||||
34
include/ui/newlocationdialog.h
Normal file
34
include/ui/newlocationdialog.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#ifndef NEWLOCATIONDIALOG_H
|
||||
#define NEWLOCATIONDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QAbstractButton>
|
||||
#include <QPointer>
|
||||
|
||||
class Project;
|
||||
|
||||
namespace Ui {
|
||||
class NewLocationDialog;
|
||||
}
|
||||
|
||||
class NewLocationDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NewLocationDialog(Project *project = nullptr, QWidget *parent = nullptr);
|
||||
~NewLocationDialog();
|
||||
|
||||
virtual void accept() override;
|
||||
|
||||
private:
|
||||
Ui::NewLocationDialog *ui;
|
||||
QPointer<Project> project = nullptr;
|
||||
const QString namePrefix;
|
||||
|
||||
bool validateIdName(bool allowEmpty = false);
|
||||
void onIdNameChanged(const QString &name);
|
||||
void dialogButtonClicked(QAbstractButton *button);
|
||||
};
|
||||
|
||||
#endif // NEWLOCATIONDIALOG_H
|
||||
51
include/ui/newmapdialog.h
Normal file
51
include/ui/newmapdialog.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#ifndef NEWMAPDIALOG_H
|
||||
#define NEWMAPDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QString>
|
||||
#include "editor.h"
|
||||
#include "project.h"
|
||||
#include "map.h"
|
||||
#include "mapheaderform.h"
|
||||
#include "newlayoutform.h"
|
||||
#include "lib/collapsiblesection.h"
|
||||
|
||||
namespace Ui {
|
||||
class NewMapDialog;
|
||||
}
|
||||
|
||||
class NewMapDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit NewMapDialog(Project *project, QWidget *parent = nullptr);
|
||||
explicit NewMapDialog(Project *project, const Map *mapToCopy = nullptr, QWidget *parent = nullptr);
|
||||
explicit NewMapDialog(Project *project, int mapListTab, const QString &mapListItem, QWidget *parent = nullptr);
|
||||
~NewMapDialog();
|
||||
|
||||
virtual void accept() override;
|
||||
|
||||
private:
|
||||
Ui::NewMapDialog *ui;
|
||||
Project *project;
|
||||
CollapsibleSection *headerSection;
|
||||
MapHeaderForm *headerForm;
|
||||
const Map *mapToCopy;
|
||||
|
||||
// Each of these validation functions will allow empty names up until `OK` is selected,
|
||||
// because clearing the text during editing is common and we don't want to flash errors for this.
|
||||
bool validateName(bool allowEmpty = false);
|
||||
bool validateGroup(bool allowEmpty = false);
|
||||
bool validateLayoutID(bool allowEmpty = false);
|
||||
|
||||
void refresh();
|
||||
void saveSettings();
|
||||
|
||||
private slots:
|
||||
void dialogButtonClicked(QAbstractButton *button);
|
||||
void on_lineEdit_Name_textChanged(const QString &);
|
||||
void on_comboBox_Group_currentTextChanged(const QString &text);
|
||||
void on_comboBox_LayoutID_currentTextChanged(const QString &text);
|
||||
};
|
||||
|
||||
#endif // NEWMAPDIALOG_H
|
||||
36
include/ui/newmapgroupdialog.h
Normal file
36
include/ui/newmapgroupdialog.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#ifndef NEWMAPGROUPDIALOG_H
|
||||
#define NEWMAPGROUPDIALOG_H
|
||||
|
||||
/*
|
||||
This is a generic dialog for requesting a new unique name from the user.
|
||||
*/
|
||||
|
||||
#include <QDialog>
|
||||
#include <QAbstractButton>
|
||||
|
||||
class Project;
|
||||
|
||||
namespace Ui {
|
||||
class NewMapGroupDialog;
|
||||
}
|
||||
|
||||
class NewMapGroupDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit NewMapGroupDialog(Project *project = nullptr, QWidget *parent = nullptr);
|
||||
~NewMapGroupDialog();
|
||||
|
||||
virtual void accept() override;
|
||||
|
||||
private:
|
||||
Ui::NewMapGroupDialog *ui;
|
||||
Project *project = nullptr;
|
||||
|
||||
bool validateName(bool allowEmpty = false);
|
||||
void onNameChanged(const QString &name);
|
||||
void dialogButtonClicked(QAbstractButton *button);
|
||||
};
|
||||
|
||||
#endif // NEWMAPGROUPDIALOG_H
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
#ifndef NEWMAPPOPUP_H
|
||||
#define NEWMAPPOPUP_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QString>
|
||||
#include "editor.h"
|
||||
#include "project.h"
|
||||
#include "map.h"
|
||||
|
||||
namespace Ui {
|
||||
class NewMapPopup;
|
||||
}
|
||||
|
||||
class NewMapPopup : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit NewMapPopup(QWidget *parent = nullptr, Project *project = nullptr);
|
||||
~NewMapPopup();
|
||||
Map *map;
|
||||
int group;
|
||||
bool existingLayout;
|
||||
bool importedMap;
|
||||
QString layoutId;
|
||||
void init();
|
||||
void initUi();
|
||||
void init(int tabIndex, QString data);
|
||||
void init(Layout *);
|
||||
static void setDefaultSettings(Project *project);
|
||||
|
||||
signals:
|
||||
void applied();
|
||||
|
||||
private:
|
||||
Ui::NewMapPopup *ui;
|
||||
Project *project;
|
||||
bool checkNewMapDimensions();
|
||||
bool checkNewMapGroup();
|
||||
void saveSettings();
|
||||
void useLayout(QString layoutId);
|
||||
void useLayoutSettings(Layout *mapLayout);
|
||||
|
||||
struct Settings {
|
||||
QString group;
|
||||
int width;
|
||||
int height;
|
||||
int borderWidth;
|
||||
int borderHeight;
|
||||
QString primaryTilesetLabel;
|
||||
QString secondaryTilesetLabel;
|
||||
QString type;
|
||||
QString location;
|
||||
QString song;
|
||||
bool canFlyTo;
|
||||
bool showLocationName;
|
||||
bool allowRunning;
|
||||
bool allowBiking;
|
||||
bool allowEscaping;
|
||||
int floorNumber;
|
||||
};
|
||||
static struct Settings settings;
|
||||
|
||||
private slots:
|
||||
void on_checkBox_UseExistingLayout_stateChanged(int state);
|
||||
void on_comboBox_Layout_currentTextChanged(const QString &text);
|
||||
void on_pushButton_NewMap_Accept_clicked();
|
||||
void on_lineEdit_NewMap_Name_textChanged(const QString &);
|
||||
};
|
||||
|
||||
#endif // NEWMAPPOPUP_H
|
||||
|
|
@ -2,7 +2,10 @@
|
|||
#define NEWTILESETDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include "project.h"
|
||||
#include <QAbstractButton>
|
||||
|
||||
class Project;
|
||||
class Tileset;
|
||||
|
||||
namespace Ui {
|
||||
class NewTilesetDialog;
|
||||
|
|
@ -15,20 +18,20 @@ class NewTilesetDialog : public QDialog
|
|||
public:
|
||||
explicit NewTilesetDialog(Project *project, QWidget *parent = nullptr);
|
||||
~NewTilesetDialog();
|
||||
QString path;
|
||||
QString fullSymbolName;
|
||||
QString friendlyName;
|
||||
bool isSecondary;
|
||||
bool checkerboardFill;
|
||||
|
||||
private slots:
|
||||
void NameOrSecondaryChanged();
|
||||
void SecondaryChanged();
|
||||
void FillChanged();
|
||||
virtual void accept() override;
|
||||
|
||||
signals:
|
||||
void applied(Tileset *tileset);
|
||||
|
||||
private:
|
||||
Ui::NewTilesetDialog *ui;
|
||||
Project *project = nullptr;
|
||||
const QString symbolPrefix;
|
||||
|
||||
bool validateName(bool allowEmpty = false);
|
||||
void onNameChanged(const QString &name);
|
||||
void dialogButtonClicked(QAbstractButton *button);
|
||||
};
|
||||
|
||||
#endif // NEWTILESETDIALOG_H
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ private:
|
|||
void displayRegionMapEntryOptions();
|
||||
void updateRegionMapEntryOptions(QString);
|
||||
void setRegionMap(RegionMap *map);
|
||||
void setLocations(const QStringList &locations);
|
||||
|
||||
void restoreWindowState();
|
||||
void closeEvent(QCloseEvent* event);
|
||||
|
|
@ -133,7 +134,7 @@ private slots:
|
|||
void on_tabWidget_Region_Map_currentChanged(int);
|
||||
void on_pushButton_RM_Options_delete_clicked();
|
||||
void on_comboBox_RM_ConnectedMap_textActivated(const QString &);
|
||||
void on_comboBox_RM_Entry_MapSection_textActivated(const QString &);
|
||||
void on_comboBox_RM_Entry_MapSection_currentTextChanged(const QString &);
|
||||
void on_comboBox_regionSelector_textActivated(const QString &);
|
||||
void on_comboBox_layoutLayer_textActivated(const QString &);
|
||||
void on_spinBox_RM_Entry_x_valueChanged(int);
|
||||
|
|
@ -148,7 +149,6 @@ private slots:
|
|||
void on_checkBox_tileVFlip_stateChanged(int);
|
||||
void on_verticalSlider_Zoom_Map_Image_valueChanged(int);
|
||||
void on_verticalSlider_Zoom_Image_Tiles_valueChanged(int);
|
||||
void on_lineEdit_RM_MapName_textEdited(const QString &);
|
||||
void onHoveredRegionMapTileChanged(int x, int y);
|
||||
void onHoveredRegionMapTileCleared();
|
||||
void mouseEvent_region_map(QGraphicsSceneMouseEvent *event, RegionMapPixmapItem *item);
|
||||
|
|
|
|||
|
|
@ -121,9 +121,7 @@ private slots:
|
|||
void on_horizontalSlider_TilesZoom_valueChanged(int value);
|
||||
|
||||
private:
|
||||
void initUi();
|
||||
void setAttributesUi();
|
||||
void setMetatileLabelValidator();
|
||||
void initMetatileSelector();
|
||||
void initTileSelector();
|
||||
void initSelectedTileItem();
|
||||
|
|
|
|||
39
porymap.pro
39
porymap.pro
|
|
@ -33,7 +33,8 @@ DEFINES += PORYMAP_LATEST_COMMIT=\\\"$$LATEST_COMMIT\\\"
|
|||
VERSION = 5.4.1
|
||||
DEFINES += PORYMAP_VERSION=\\\"$$VERSION\\\"
|
||||
|
||||
SOURCES += src/core/block.cpp \
|
||||
SOURCES += src/core/advancemapparser.cpp \
|
||||
src/core/block.cpp \
|
||||
src/core/bitpacker.cpp \
|
||||
src/core/blockdata.cpp \
|
||||
src/core/events.cpp \
|
||||
|
|
@ -42,20 +43,21 @@ SOURCES += src/core/block.cpp \
|
|||
src/core/imageexport.cpp \
|
||||
src/core/map.cpp \
|
||||
src/core/mapconnection.cpp \
|
||||
src/core/mapheader.cpp \
|
||||
src/core/maplayout.cpp \
|
||||
src/core/mapparser.cpp \
|
||||
src/core/metatile.cpp \
|
||||
src/core/metatileparser.cpp \
|
||||
src/core/network.cpp \
|
||||
src/core/paletteutil.cpp \
|
||||
src/core/parseutil.cpp \
|
||||
src/core/tile.cpp \
|
||||
src/core/tileset.cpp \
|
||||
src/core/validator.cpp \
|
||||
src/core/regionmap.cpp \
|
||||
src/core/wildmoninfo.cpp \
|
||||
src/core/editcommands.cpp \
|
||||
src/lib/fex/lexer.cpp \
|
||||
src/lib/fex/parser.cpp \
|
||||
src/lib/collapsiblesection.cpp \
|
||||
src/lib/orderedjson.cpp \
|
||||
src/core/regionmapeditcommands.cpp \
|
||||
src/scriptapi/apimap.cpp \
|
||||
|
|
@ -87,17 +89,23 @@ SOURCES += src/core/block.cpp \
|
|||
src/ui/filterchildrenproxymodel.cpp \
|
||||
src/ui/maplistmodels.cpp \
|
||||
src/ui/maplisttoolbar.cpp \
|
||||
src/ui/message.cpp \
|
||||
src/ui/graphicsview.cpp \
|
||||
src/ui/imageproviders.cpp \
|
||||
src/ui/layoutpixmapitem.cpp \
|
||||
src/ui/prefabcreationdialog.cpp \
|
||||
src/ui/regionmappixmapitem.cpp \
|
||||
src/ui/citymappixmapitem.cpp \
|
||||
src/ui/mapheaderform.cpp \
|
||||
src/ui/metatilelayersitem.cpp \
|
||||
src/ui/metatileselector.cpp \
|
||||
src/ui/movablerect.cpp \
|
||||
src/ui/movementpermissionsselector.cpp \
|
||||
src/ui/neweventtoolbutton.cpp \
|
||||
src/ui/newlayoutdialog.cpp \
|
||||
src/ui/newlayoutform.cpp \
|
||||
src/ui/newlocationdialog.cpp \
|
||||
src/ui/newmapgroupdialog.cpp \
|
||||
src/ui/noscrollcombobox.cpp \
|
||||
src/ui/noscrollspinbox.cpp \
|
||||
src/ui/montabwidget.cpp \
|
||||
|
|
@ -110,7 +118,7 @@ SOURCES += src/core/block.cpp \
|
|||
src/ui/tileseteditortileselector.cpp \
|
||||
src/ui/tilemaptileselector.cpp \
|
||||
src/ui/regionmapeditor.cpp \
|
||||
src/ui/newmappopup.cpp \
|
||||
src/ui/newmapdialog.cpp \
|
||||
src/ui/mapimageexporter.cpp \
|
||||
src/ui/newtilesetdialog.cpp \
|
||||
src/ui/flowlayout.cpp \
|
||||
|
|
@ -133,7 +141,8 @@ SOURCES += src/core/block.cpp \
|
|||
src/ui/updatepromoter.cpp \
|
||||
src/ui/wildmonchart.cpp
|
||||
|
||||
HEADERS += include/core/block.h \
|
||||
HEADERS += include/core/advancemapparser.h \
|
||||
include/core/block.h \
|
||||
include/core/bitpacker.h \
|
||||
include/core/blockdata.h \
|
||||
include/core/events.h \
|
||||
|
|
@ -143,15 +152,15 @@ HEADERS += include/core/block.h \
|
|||
include/core/imageexport.h \
|
||||
include/core/map.h \
|
||||
include/core/mapconnection.h \
|
||||
include/core/mapheader.h \
|
||||
include/core/maplayout.h \
|
||||
include/core/mapparser.h \
|
||||
include/core/metatile.h \
|
||||
include/core/metatileparser.h \
|
||||
include/core/network.h \
|
||||
include/core/paletteutil.h \
|
||||
include/core/parseutil.h \
|
||||
include/core/tile.h \
|
||||
include/core/tileset.h \
|
||||
include/core/validator.h \
|
||||
include/core/regionmap.h \
|
||||
include/core/wildmoninfo.h \
|
||||
include/core/editcommands.h \
|
||||
|
|
@ -161,6 +170,7 @@ HEADERS += include/core/block.h \
|
|||
include/lib/fex/define_statement.h \
|
||||
include/lib/fex/lexer.h \
|
||||
include/lib/fex/parser.h \
|
||||
include/lib/collapsiblesection.h \
|
||||
include/lib/orderedmap.h \
|
||||
include/lib/orderedjson.h \
|
||||
include/ui/aboutporymap.h \
|
||||
|
|
@ -174,6 +184,7 @@ HEADERS += include/core/block.h \
|
|||
include/ui/connectionpixmapitem.h \
|
||||
include/ui/currentselectedmetatilespixmapitem.h \
|
||||
include/ui/gridsettings.h \
|
||||
include/ui/mapheaderform.h \
|
||||
include/ui/newmapconnectiondialog.h \
|
||||
include/ui/prefabframe.h \
|
||||
include/ui/projectsettingseditor.h \
|
||||
|
|
@ -186,6 +197,7 @@ HEADERS += include/core/block.h \
|
|||
include/ui/filterchildrenproxymodel.h \
|
||||
include/ui/maplistmodels.h \
|
||||
include/ui/maplisttoolbar.h \
|
||||
include/ui/message.h \
|
||||
include/ui/graphicsview.h \
|
||||
include/ui/imageproviders.h \
|
||||
include/ui/layoutpixmapitem.h \
|
||||
|
|
@ -199,6 +211,10 @@ HEADERS += include/core/block.h \
|
|||
include/ui/movablerect.h \
|
||||
include/ui/movementpermissionsselector.h \
|
||||
include/ui/neweventtoolbutton.h \
|
||||
include/ui/newlayoutdialog.h \
|
||||
include/ui/newlayoutform.h \
|
||||
include/ui/newlocationdialog.h \
|
||||
include/ui/newmapgroupdialog.h \
|
||||
include/ui/noscrollcombobox.h \
|
||||
include/ui/noscrollspinbox.h \
|
||||
include/ui/montabwidget.h \
|
||||
|
|
@ -212,7 +228,7 @@ HEADERS += include/core/block.h \
|
|||
include/ui/tileseteditortileselector.h \
|
||||
include/ui/tilemaptileselector.h \
|
||||
include/ui/regionmapeditor.h \
|
||||
include/ui/newmappopup.h \
|
||||
include/ui/newmapdialog.h \
|
||||
include/ui/mapimageexporter.h \
|
||||
include/ui/newtilesetdialog.h \
|
||||
include/ui/overlay.h \
|
||||
|
|
@ -241,14 +257,19 @@ FORMS += forms/mainwindow.ui \
|
|||
forms/colorinputwidget.ui \
|
||||
forms/connectionslistitem.ui \
|
||||
forms/gridsettingsdialog.ui \
|
||||
forms/mapheaderform.ui \
|
||||
forms/maplisttoolbar.ui \
|
||||
forms/newlayoutdialog.ui \
|
||||
forms/newlayoutform.ui \
|
||||
forms/newlocationdialog.ui \
|
||||
forms/newmapconnectiondialog.ui \
|
||||
forms/newmapgroupdialog.ui \
|
||||
forms/prefabcreationdialog.ui \
|
||||
forms/prefabframe.ui \
|
||||
forms/tileseteditor.ui \
|
||||
forms/paletteeditor.ui \
|
||||
forms/regionmapeditor.ui \
|
||||
forms/newmappopup.ui \
|
||||
forms/newmapdialog.ui \
|
||||
forms/aboutporymap.ui \
|
||||
forms/newtilesetdialog.ui \
|
||||
forms/mapimageexporter.ui \
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include "log.h"
|
||||
#include "shortcut.h"
|
||||
#include "map.h"
|
||||
#include "validator.h"
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFormLayout>
|
||||
|
|
@ -81,6 +82,7 @@ const QMap<ProjectIdentifier, QPair<QString, QString>> ProjectConfig::defaultIde
|
|||
{ProjectIdentifier::symbol_spawn_npcs, {"symbol_spawn_npcs", "u8 sWhiteoutRespawnHealerNpcIds"}},
|
||||
{ProjectIdentifier::symbol_attribute_table, {"symbol_attribute_table", "sMetatileAttrMasks"}},
|
||||
{ProjectIdentifier::symbol_tilesets_prefix, {"symbol_tilesets_prefix", "gTileset_"}},
|
||||
{ProjectIdentifier::symbol_dynamic_map_name, {"symbol_dynamic_map_name", "Dynamic"}},
|
||||
// Defines
|
||||
{ProjectIdentifier::define_obj_event_count, {"define_obj_event_count", "OBJECT_EVENT_TEMPLATES_COUNT"}},
|
||||
{ProjectIdentifier::define_min_level, {"define_min_level", "MIN_LEVEL"}},
|
||||
|
|
@ -152,7 +154,6 @@ const QMap<ProjectFilePath, QPair<QString, QString>> ProjectConfig::defaultPaths
|
|||
{ProjectFilePath::data_pokemon_gfx, { "data_pokemon_gfx", "src/data/graphics/pokemon.h"}},
|
||||
{ProjectFilePath::data_heal_locations, { "data_heal_locations", "src/data/heal_locations.h"}},
|
||||
{ProjectFilePath::constants_global, { "constants_global", "include/constants/global.h"}},
|
||||
{ProjectFilePath::constants_map_groups, { "constants_map_groups", "include/constants/map_groups.h"}},
|
||||
{ProjectFilePath::constants_items, { "constants_items", "include/constants/items.h"}},
|
||||
{ProjectFilePath::constants_flags, { "constants_flags", "include/constants/flags.h"}},
|
||||
{ProjectFilePath::constants_vars, { "constants_vars", "include/constants/vars.h"}},
|
||||
|
|
@ -348,6 +349,10 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) {
|
|||
this->customScriptsEditorState = bytesFromString(value);
|
||||
} else if (key == "wild_mon_chart_geometry") {
|
||||
this->wildMonChartGeometry = bytesFromString(value);
|
||||
} else if (key == "new_map_dialog_geometry") {
|
||||
this->newMapDialogGeometry = bytesFromString(value);
|
||||
} else if (key == "new_layout_dialog_geometry") {
|
||||
this->newLayoutDialogGeometry = bytesFromString(value);
|
||||
} else if (key == "metatiles_zoom") {
|
||||
this->metatilesZoom = getConfigInteger(key, value, 10, 100, 30);
|
||||
} else if (key == "collision_zoom") {
|
||||
|
|
@ -374,6 +379,8 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) {
|
|||
this->monitorFiles = getConfigBool(key, value);
|
||||
} else if (key == "tileset_checkerboard_fill") {
|
||||
this->tilesetCheckerboardFill = getConfigBool(key, value);
|
||||
} else if (key == "new_map_header_section_expanded") {
|
||||
this->newMapHeaderSectionExpanded = getConfigBool(key, value);
|
||||
} else if (key == "theme") {
|
||||
this->theme = value;
|
||||
} else if (key == "wild_mon_chart_theme") {
|
||||
|
|
@ -438,6 +445,8 @@ QMap<QString, QString> PorymapConfig::getKeyValueMap() {
|
|||
map.insert("custom_scripts_editor_geometry", stringFromByteArray(this->customScriptsEditorGeometry));
|
||||
map.insert("custom_scripts_editor_state", stringFromByteArray(this->customScriptsEditorState));
|
||||
map.insert("wild_mon_chart_geometry", stringFromByteArray(this->wildMonChartGeometry));
|
||||
map.insert("new_map_dialog_geometry", stringFromByteArray(this->newMapDialogGeometry));
|
||||
map.insert("new_layout_dialog_geometry", stringFromByteArray(this->newLayoutDialogGeometry));
|
||||
map.insert("mirror_connecting_maps", this->mirrorConnectingMaps ? "1" : "0");
|
||||
map.insert("show_dive_emerge_maps", this->showDiveEmergeMaps ? "1" : "0");
|
||||
map.insert("dive_emerge_map_opacity", QString::number(this->diveEmergeMapOpacity));
|
||||
|
|
@ -457,6 +466,7 @@ QMap<QString, QString> PorymapConfig::getKeyValueMap() {
|
|||
map.insert("show_tileset_editor_divider", this->showTilesetEditorDivider ? "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");
|
||||
map.insert("theme", this->theme);
|
||||
map.insert("wild_mon_chart_theme", this->wildMonChartTheme);
|
||||
map.insert("text_editor_open_directory", this->textEditorOpenFolder);
|
||||
|
|
@ -954,13 +964,23 @@ QString ProjectConfig::getFilePath(ProjectFilePath pathId) {
|
|||
|
||||
}
|
||||
|
||||
void ProjectConfig::setIdentifier(ProjectIdentifier id, const QString &text) {
|
||||
if (!defaultIdentifiers.contains(id)) return;
|
||||
QString copy(text);
|
||||
if (copy.isEmpty()) {
|
||||
void ProjectConfig::setIdentifier(ProjectIdentifier id, QString text) {
|
||||
if (!defaultIdentifiers.contains(id))
|
||||
return;
|
||||
|
||||
if (text.isEmpty()) {
|
||||
this->identifiers.remove(id);
|
||||
} else {
|
||||
this->identifiers[id] = copy;
|
||||
const QString idName = defaultIdentifiers.value(id).first;
|
||||
if (idName.startsWith("define_") || idName.startsWith("symbol_")) {
|
||||
// Validate the input for the identifier, depending on the type.
|
||||
IdentifierValidator validator;
|
||||
if (!validator.isValid(text)) {
|
||||
logError(QString("The name '%1' for project identifier '%2' is invalid. It must only contain word characters, and cannot start with a digit.").arg(text).arg(idName));
|
||||
return;
|
||||
}
|
||||
}
|
||||
this->identifiers[id] = text;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
217
src/core/advancemapparser.cpp
Normal file
217
src/core/advancemapparser.cpp
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
#include "advancemapparser.h"
|
||||
#include "log.h"
|
||||
#include "project.h"
|
||||
#include "maplayout.h"
|
||||
|
||||
Layout *AdvanceMapParser::parseLayout(const QString &filepath, bool *error, const Project *project)
|
||||
{
|
||||
QFile file(filepath);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
*error = true;
|
||||
logError(QString("Could not open Advance Map 1.92 Map .map file '%1': ").arg(filepath) + file.errorString());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QByteArray in = file.readAll();
|
||||
file.close();
|
||||
|
||||
if (in.length() < 20 || in.length() % 2 != 0) {
|
||||
*error = true;
|
||||
logError(QString("Advance Map 1.92 Map .map file '%1' is an unexpected size.").arg(filepath));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int borderWidth = static_cast<unsigned char>(in.at(16)); // 0 in RSE .map files
|
||||
int borderHeight = static_cast<unsigned char>(in.at(17)); // 0 in RSE .map files
|
||||
int numBorderTiles = borderWidth * borderHeight; // 0 if RSE
|
||||
|
||||
int mapDataOffset = 20 + (numBorderTiles * 2); // FRLG .map files store border metatile data after the header
|
||||
int mapWidth = static_cast<unsigned char>(in.at(0)) |
|
||||
(static_cast<unsigned char>(in.at(1)) << 8) |
|
||||
(static_cast<unsigned char>(in.at(2)) << 16) |
|
||||
(static_cast<unsigned char>(in.at(3)) << 24);
|
||||
int mapHeight = static_cast<unsigned char>(in.at(4)) |
|
||||
(static_cast<unsigned char>(in.at(5)) << 8) |
|
||||
(static_cast<unsigned char>(in.at(6)) << 16) |
|
||||
(static_cast<unsigned char>(in.at(7)) << 24);
|
||||
int mapPrimaryTilesetNum = static_cast<unsigned char>(in.at(8)) |
|
||||
(static_cast<unsigned char>(in.at(9)) << 8) |
|
||||
(static_cast<unsigned char>(in.at(10)) << 16) |
|
||||
(static_cast<unsigned char>(in.at(11)) << 24);
|
||||
int mapSecondaryTilesetNum = static_cast<unsigned char>(in.at(12)) |
|
||||
(static_cast<unsigned char>(in.at(13)) << 8) |
|
||||
(static_cast<unsigned char>(in.at(14)) << 16) |
|
||||
(static_cast<unsigned char>(in.at(15)) << 24);
|
||||
|
||||
int numMetatiles = mapWidth * mapHeight;
|
||||
int expectedFileSize = 20 + (numBorderTiles * 2) + (numMetatiles * 2);
|
||||
if (in.length() != expectedFileSize) {
|
||||
*error = true;
|
||||
logError(QString(".map file is an unexpected size. Expected %1 bytes, but it has %2 bytes.").arg(expectedFileSize).arg(in.length()));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Blockdata blockdata;
|
||||
for (int i = mapDataOffset; (i + 1) < in.length(); i += 2) {
|
||||
uint16_t word = static_cast<uint16_t>((in[i] & 0xff) + ((in[i + 1] & 0xff) << 8));
|
||||
blockdata.append(word);
|
||||
}
|
||||
|
||||
Blockdata border;
|
||||
if (numBorderTiles != 0) {
|
||||
for (int i = 20; (i + 1) < mapDataOffset; i += 2) {
|
||||
uint16_t word = static_cast<uint16_t>((in[i] & 0xff) + ((in[i + 1] & 0xff) << 8));
|
||||
border.append(word);
|
||||
}
|
||||
}
|
||||
|
||||
Layout *mapLayout = new Layout();
|
||||
mapLayout->width = mapWidth;
|
||||
mapLayout->height = mapHeight;
|
||||
mapLayout->border_width = (borderWidth == 0) ? DEFAULT_BORDER_WIDTH : borderWidth;
|
||||
mapLayout->border_height = (borderHeight == 0) ? DEFAULT_BORDER_HEIGHT : borderHeight;
|
||||
|
||||
const QList<QString> tilesets = project->tilesetLabelsOrdered;
|
||||
|
||||
if (mapPrimaryTilesetNum > tilesets.size())
|
||||
mapLayout->tileset_primary_label = project->getDefaultPrimaryTilesetLabel();
|
||||
else
|
||||
mapLayout->tileset_primary_label = tilesets.at(mapPrimaryTilesetNum);
|
||||
|
||||
if (mapSecondaryTilesetNum > tilesets.size())
|
||||
mapLayout->tileset_secondary_label = project->getDefaultSecondaryTilesetLabel();
|
||||
else
|
||||
mapLayout->tileset_secondary_label = tilesets.at(mapSecondaryTilesetNum);
|
||||
|
||||
mapLayout->blockdata = blockdata;
|
||||
|
||||
if (!border.isEmpty()) {
|
||||
mapLayout->border = border;
|
||||
}
|
||||
|
||||
return mapLayout;
|
||||
}
|
||||
|
||||
QList<Metatile*> AdvanceMapParser::parseMetatiles(const QString &filepath, bool *error, bool primaryTileset)
|
||||
{
|
||||
QFile file(filepath);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
*error = true;
|
||||
logError(QString("Could not open Advance Map 1.92 Metatile .bvd file '%1': ").arg(filepath) + file.errorString());
|
||||
return { };
|
||||
}
|
||||
|
||||
QByteArray in = file.readAll();
|
||||
file.close();
|
||||
|
||||
if (in.length() < 9 || in.length() % 2 != 0) {
|
||||
*error = true;
|
||||
logError(QString("Advance Map 1.92 Metatile .bvd file '%1' is an unexpected size.").arg(filepath));
|
||||
return { };
|
||||
}
|
||||
|
||||
int projIdOffset = in.length() - 4;
|
||||
int metatileSize = 16;
|
||||
BaseGameVersion version;
|
||||
if (in.at(projIdOffset + 0) == 'R'
|
||||
&& in.at(projIdOffset + 1) == 'S'
|
||||
&& in.at(projIdOffset + 2) == 'E'
|
||||
&& in.at(projIdOffset + 3) == ' ') {
|
||||
// ruby and emerald are handled equally here.
|
||||
version = BaseGameVersion::pokeemerald;
|
||||
} else if (in.at(projIdOffset + 0) == 'F'
|
||||
&& in.at(projIdOffset + 1) == 'R'
|
||||
&& in.at(projIdOffset + 2) == 'L'
|
||||
&& in.at(projIdOffset + 3) == 'G') {
|
||||
version = BaseGameVersion::pokefirered;
|
||||
} else {
|
||||
*error = true;
|
||||
logError(QString("Detected unsupported game type from .bvd file. Last 4 bytes of file must be 'RSE ' or 'FRLG'."));
|
||||
return { };
|
||||
}
|
||||
|
||||
int attrSize = Metatile::getDefaultAttributesSize(version);
|
||||
int maxMetatiles = primaryTileset ? Project::getNumMetatilesPrimary() : Project::getNumMetatilesTotal() - Project::getNumMetatilesPrimary();
|
||||
int numMetatiles = static_cast<unsigned char>(in.at(0)) |
|
||||
(static_cast<unsigned char>(in.at(1)) << 8) |
|
||||
(static_cast<unsigned char>(in.at(2)) << 16) |
|
||||
(static_cast<unsigned char>(in.at(3)) << 24);
|
||||
if (numMetatiles > maxMetatiles) {
|
||||
*error = true;
|
||||
logError(QString(".bvd file contains data for %1 metatiles, but the maximum number of metatiles is %2.").arg(numMetatiles).arg(maxMetatiles));
|
||||
return { };
|
||||
}
|
||||
if (numMetatiles < 1) {
|
||||
*error = true;
|
||||
logError(QString(".bvd file contains no data for metatiles."));
|
||||
return { };
|
||||
}
|
||||
|
||||
int expectedFileSize = 4 + (metatileSize * numMetatiles) + (attrSize * numMetatiles) + 4;
|
||||
if (in.length() != expectedFileSize) {
|
||||
*error = true;
|
||||
logError(QString(".bvd file is an unexpected size. Expected %1 bytes, but it has %2 bytes.").arg(expectedFileSize).arg(in.length()));
|
||||
return { };
|
||||
}
|
||||
|
||||
QList<Metatile*> metatiles;
|
||||
for (int i = 0; i < numMetatiles; i++) {
|
||||
Metatile *metatile = new Metatile();
|
||||
QList<Tile> tiles;
|
||||
for (int j = 0; j < 8; j++) {
|
||||
int metatileOffset = 4 + i * metatileSize + j * 2;
|
||||
Tile tile(static_cast<uint16_t>(
|
||||
static_cast<unsigned char>(in.at(metatileOffset)) |
|
||||
(static_cast<unsigned char>(in.at(metatileOffset + 1)) << 8)));
|
||||
tiles.append(tile);
|
||||
}
|
||||
|
||||
// AdvanceMap .bvd files only contain 8 tiles of data per metatile.
|
||||
// If the user has triple-layer metatiles enabled we need to fill the remaining 4 tiles ourselves.
|
||||
if (projectConfig.tripleLayerMetatilesEnabled) {
|
||||
Tile tile = Tile();
|
||||
for (int j = 0; j < 4; j++)
|
||||
tiles.append(tile);
|
||||
}
|
||||
|
||||
int attrOffset = 4 + (numMetatiles * metatileSize) + (i * attrSize);
|
||||
uint32_t attributes = 0;
|
||||
for (int j = 0; j < attrSize; j++)
|
||||
attributes |= static_cast<unsigned char>(in.at(attrOffset + j)) << (8 * j);
|
||||
metatile->setAttributes(attributes, version);
|
||||
metatile->tiles = tiles;
|
||||
metatiles.append(metatile);
|
||||
}
|
||||
|
||||
return metatiles;
|
||||
}
|
||||
|
||||
QList<QRgb> AdvanceMapParser::parsePalette(const QString &filepath, bool *error) {
|
||||
QFile file(filepath);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
*error = true;
|
||||
logError(QString("Could not open Advance Map 1.92 palette file '%1': ").arg(filepath) + file.errorString());
|
||||
return QList<QRgb>();
|
||||
}
|
||||
|
||||
QByteArray in = file.readAll();
|
||||
file.close();
|
||||
|
||||
if (in.length() % 4 != 0) {
|
||||
*error = true;
|
||||
logError(QString("Advance Map 1.92 palette file '%1' had an unexpected format. File's length must be a multiple of 4, but the length is %2.").arg(filepath).arg(in.length()));
|
||||
return QList<QRgb>();
|
||||
}
|
||||
|
||||
QList<QRgb> palette;
|
||||
int i = 0;
|
||||
while (i < in.length()) {
|
||||
unsigned char red = static_cast<unsigned char>(in.at(i + 0));
|
||||
unsigned char green = static_cast<unsigned char>(in.at(i + 1));
|
||||
unsigned char blue = static_cast<unsigned char>(in.at(i + 2));
|
||||
palette.append(qRgb(red, green, blue));
|
||||
i += 4;
|
||||
}
|
||||
|
||||
return palette;
|
||||
}
|
||||
|
|
@ -44,7 +44,7 @@ void Event::setPixmapItem(DraggablePixmapItem *item) {
|
|||
}
|
||||
|
||||
int Event::getEventIndex() {
|
||||
return this->map->events.value(this->getEventGroup()).indexOf(this);
|
||||
return this->map->getIndexOfEvent(this);
|
||||
}
|
||||
|
||||
void Event::setDefaultValues(Project *) {
|
||||
|
|
@ -392,7 +392,8 @@ OrderedJson::object CloneObjectEvent::buildEventJson(Project *project) {
|
|||
cloneJson["x"] = this->getX();
|
||||
cloneJson["y"] = this->getY();
|
||||
cloneJson["target_local_id"] = this->getTargetID();
|
||||
cloneJson["target_map"] = project->mapNamesToMapConstants.value(this->getTargetMap());
|
||||
const QString mapName = this->getTargetMap();
|
||||
cloneJson["target_map"] = project->mapNamesToMapConstants.value(mapName, mapName);
|
||||
this->addCustomValuesTo(&cloneJson);
|
||||
|
||||
return cloneJson;
|
||||
|
|
@ -404,17 +405,11 @@ bool CloneObjectEvent::loadFromJson(QJsonObject json, Project *project) {
|
|||
this->setGfx(ParseUtil::jsonToQString(json["graphics_id"]));
|
||||
this->setTargetID(ParseUtil::jsonToInt(json["target_local_id"]));
|
||||
|
||||
// Ensure the target map constant is valid before adding it to the events.
|
||||
const QString dynamicMapConstant = project->getDynamicMapDefineName();
|
||||
QString mapConstant = ParseUtil::jsonToQString(json["target_map"]);
|
||||
if (project->mapConstantsToMapNames.contains(mapConstant)) {
|
||||
this->setTargetMap(project->mapConstantsToMapNames.value(mapConstant));
|
||||
} else if (mapConstant == dynamicMapConstant) {
|
||||
this->setTargetMap(DYNAMIC_MAP_NAME);
|
||||
} else {
|
||||
logWarn(QString("Target Map constant '%1' is invalid. Using default '%2'.").arg(mapConstant).arg(dynamicMapConstant));
|
||||
this->setTargetMap(DYNAMIC_MAP_NAME);
|
||||
}
|
||||
// Log a warning if "target_map" isn't a known map ID, but don't overwrite user data.
|
||||
const QString mapConstant = ParseUtil::jsonToQString(json["target_map"]);
|
||||
if (!project->mapConstantsToMapNames.contains(mapConstant))
|
||||
logWarn(QString("Unknown Target Map constant '%1'.").arg(mapConstant));
|
||||
this->setTargetMap(project->mapConstantsToMapNames.value(mapConstant, mapConstant));
|
||||
|
||||
this->readCustomValues(json);
|
||||
|
||||
|
|
@ -424,7 +419,7 @@ bool CloneObjectEvent::loadFromJson(QJsonObject json, Project *project) {
|
|||
void CloneObjectEvent::setDefaultValues(Project *project) {
|
||||
this->setGfx(project->gfxDefines.keys().value(0, "0"));
|
||||
this->setTargetID(1);
|
||||
if (this->getMap()) this->setTargetMap(this->getMap()->name);
|
||||
if (this->getMap()) this->setTargetMap(this->getMap()->name());
|
||||
}
|
||||
|
||||
const QSet<QString> expectedCloneObjectFields = {
|
||||
|
|
@ -445,7 +440,7 @@ void CloneObjectEvent::loadPixmap(Project *project) {
|
|||
// Try to get the targeted object to clone
|
||||
int eventIndex = this->targetID - 1;
|
||||
Map *clonedMap = project->getMap(this->targetMap);
|
||||
Event *clonedEvent = clonedMap ? clonedMap->events[Event::Group::Object].value(eventIndex, nullptr) : nullptr;
|
||||
Event *clonedEvent = clonedMap ? clonedMap->getEvent(Event::Group::Object, eventIndex) : nullptr;
|
||||
|
||||
if (clonedEvent && clonedEvent->getEventType() == Event::Type::Object) {
|
||||
// Get graphics data from cloned object
|
||||
|
|
@ -502,7 +497,8 @@ OrderedJson::object WarpEvent::buildEventJson(Project *project) {
|
|||
warpJson["x"] = this->getX();
|
||||
warpJson["y"] = this->getY();
|
||||
warpJson["elevation"] = this->getElevation();
|
||||
warpJson["dest_map"] = project->mapNamesToMapConstants.value(this->getDestinationMap());
|
||||
const QString mapName = this->getDestinationMap();
|
||||
warpJson["dest_map"] = project->mapNamesToMapConstants.value(mapName, mapName);
|
||||
warpJson["dest_warp_id"] = this->getDestinationWarpID();
|
||||
|
||||
this->addCustomValuesTo(&warpJson);
|
||||
|
|
@ -516,17 +512,11 @@ bool WarpEvent::loadFromJson(QJsonObject json, Project *project) {
|
|||
this->setElevation(ParseUtil::jsonToInt(json["elevation"]));
|
||||
this->setDestinationWarpID(ParseUtil::jsonToQString(json["dest_warp_id"]));
|
||||
|
||||
// Ensure the warp destination map constant is valid before adding it to the warps.
|
||||
const QString dynamicMapConstant = project->getDynamicMapDefineName();
|
||||
QString mapConstant = ParseUtil::jsonToQString(json["dest_map"]);
|
||||
if (project->mapConstantsToMapNames.contains(mapConstant)) {
|
||||
this->setDestinationMap(project->mapConstantsToMapNames.value(mapConstant));
|
||||
} else if (mapConstant == dynamicMapConstant) {
|
||||
this->setDestinationMap(DYNAMIC_MAP_NAME);
|
||||
} else {
|
||||
logWarn(QString("Destination Map constant '%1' is invalid. Using default '%2'.").arg(mapConstant).arg(dynamicMapConstant));
|
||||
this->setDestinationMap(DYNAMIC_MAP_NAME);
|
||||
}
|
||||
// Log a warning if "dest_map" isn't a known map ID, but don't overwrite user data.
|
||||
const QString mapConstant = ParseUtil::jsonToQString(json["dest_map"]);
|
||||
if (!project->mapConstantsToMapNames.contains(mapConstant))
|
||||
logWarn(QString("Unknown Destination Map constant '%1'.").arg(mapConstant));
|
||||
this->setDestinationMap(project->mapConstantsToMapNames.value(mapConstant, mapConstant));
|
||||
|
||||
this->readCustomValues(json);
|
||||
|
||||
|
|
@ -534,7 +524,7 @@ bool WarpEvent::loadFromJson(QJsonObject json, Project *project) {
|
|||
}
|
||||
|
||||
void WarpEvent::setDefaultValues(Project *) {
|
||||
if (this->getMap()) this->setDestinationMap(this->getMap()->name);
|
||||
if (this->getMap()) this->setDestinationMap(this->getMap()->name());
|
||||
this->setDestinationWarpID("0");
|
||||
this->setElevation(0);
|
||||
}
|
||||
|
|
@ -949,16 +939,16 @@ OrderedJson::object HealLocationEvent::buildEventJson(Project *) {
|
|||
|
||||
void HealLocationEvent::setDefaultValues(Project *) {
|
||||
this->setElevation(projectConfig.defaultElevation);
|
||||
if (!this->getMap())
|
||||
if (!this->map)
|
||||
return;
|
||||
|
||||
bool respawnEnabled = projectConfig.healLocationRespawnDataEnabled;
|
||||
const QString mapConstant = Map::mapConstantFromName(this->getMap()->name, false);
|
||||
const QString prefix = projectConfig.getIdentifier(respawnEnabled ? ProjectIdentifier::define_spawn_prefix
|
||||
: ProjectIdentifier::define_heal_locations_prefix);
|
||||
this->setLocationName(mapConstant);
|
||||
this->setIdName(prefix + mapConstant);
|
||||
this->setLocationName(this->map->constantName());
|
||||
this->setIdName(prefix + this->map->constantName());
|
||||
if (respawnEnabled) {
|
||||
this->setRespawnMap(this->getMap()->name);
|
||||
this->setRespawnMap(this->map->name());
|
||||
this->setRespawnNPC(1);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
#include "events.h"
|
||||
#include "map.h"
|
||||
|
||||
// TODO: Remove
|
||||
|
||||
HealLocation::HealLocation(QString id, QString map,
|
||||
int i, int16_t x, int16_t y,
|
||||
QString respawnMap, uint8_t respawnNPC) {
|
||||
|
|
|
|||
184
src/core/map.cpp
184
src/core/map.cpp
|
|
@ -13,25 +13,51 @@
|
|||
|
||||
Map::Map(QObject *parent) : QObject(parent)
|
||||
{
|
||||
editHistory.setClean();
|
||||
m_editHistory = new QUndoStack(this);
|
||||
resetEvents();
|
||||
|
||||
m_header = new MapHeader(this);
|
||||
connect(m_header, &MapHeader::modified, this, &Map::modified);
|
||||
}
|
||||
|
||||
Map::Map(const Map &other, QObject *parent) : Map(parent) {
|
||||
m_name = other.m_name;
|
||||
m_constantName = other.m_constantName;
|
||||
m_layoutId = other.m_layoutId;
|
||||
m_sharedEventsMap = other.m_sharedEventsMap;
|
||||
m_sharedScriptsMap = other.m_sharedScriptsMap;
|
||||
m_customAttributes = other.m_customAttributes;
|
||||
*m_header = *other.m_header;
|
||||
m_layout = other.m_layout;
|
||||
m_isPersistedToFile = false;
|
||||
m_metatileLayerOrder = other.m_metatileLayerOrder;
|
||||
m_metatileLayerOpacity = other.m_metatileLayerOpacity;
|
||||
|
||||
// Copy events
|
||||
for (auto i = other.m_events.constBegin(); i != other.m_events.constEnd(); i++) {
|
||||
QList<Event*> newEvents;
|
||||
for (const auto &event : i.value()) {
|
||||
auto newEvent = event->duplicate();
|
||||
m_ownedEvents.insert(newEvent);
|
||||
newEvents.append(newEvent);
|
||||
}
|
||||
m_events[i.key()] = newEvents;
|
||||
}
|
||||
|
||||
// Duplicating the map connections is probably not desirable, so we skip them.
|
||||
}
|
||||
|
||||
Map::~Map() {
|
||||
qDeleteAll(ownedEvents);
|
||||
ownedEvents.clear();
|
||||
qDeleteAll(m_ownedEvents);
|
||||
m_ownedEvents.clear();
|
||||
deleteConnections();
|
||||
}
|
||||
|
||||
void Map::setName(QString mapName) {
|
||||
name = mapName;
|
||||
constantName = mapConstantFromName(mapName);
|
||||
scriptsLoaded = false;
|
||||
}
|
||||
|
||||
// Note: Map does not take ownership of layout
|
||||
void Map::setLayout(Layout *layout) {
|
||||
this->layout = layout;
|
||||
m_layout = layout;
|
||||
if (layout) {
|
||||
this->layoutId = layout->id;
|
||||
m_layoutId = layout->id;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -42,29 +68,23 @@ QString Map::mapConstantFromName(QString mapName, bool includePrefix) {
|
|||
const QString prefix = includePrefix ? projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix) : "";
|
||||
QString withMapAndUppercase = prefix + nameWithUnderscores.toUpper();
|
||||
static const QRegularExpression underscores("_+");
|
||||
QString constantName = withMapAndUppercase.replace(underscores, "_");
|
||||
|
||||
// Handle special cases.
|
||||
// SSTidal needs to be SS_TIDAL, rather than SSTIDAL
|
||||
constantName = constantName.replace("SSTIDAL", "SS_TIDAL");
|
||||
|
||||
return constantName;
|
||||
return withMapAndUppercase.replace(underscores, "_");
|
||||
}
|
||||
|
||||
int Map::getWidth() {
|
||||
return layout->getWidth();
|
||||
int Map::getWidth() const {
|
||||
return m_layout->getWidth();
|
||||
}
|
||||
|
||||
int Map::getHeight() {
|
||||
return layout->getHeight();
|
||||
int Map::getHeight() const {
|
||||
return m_layout->getHeight();
|
||||
}
|
||||
|
||||
int Map::getBorderWidth() {
|
||||
return layout->getBorderWidth();
|
||||
int Map::getBorderWidth() const {
|
||||
return m_layout->getBorderWidth();
|
||||
}
|
||||
|
||||
int Map::getBorderHeight() {
|
||||
return layout->getBorderHeight();
|
||||
int Map::getBorderHeight() const {
|
||||
return m_layout->getBorderHeight();
|
||||
}
|
||||
|
||||
// Get the portion of the map that can be rendered when rendered as a map connection.
|
||||
|
|
@ -106,7 +126,7 @@ QPixmap Map::renderConnection(const QString &direction, Layout * fromLayout) {
|
|||
if (MapConnection::isDiving(direction))
|
||||
fromLayout = nullptr;
|
||||
|
||||
QPixmap connectionPixmap = this->layout->render(true, fromLayout, bounds);
|
||||
QPixmap connectionPixmap = m_layout->render(true, fromLayout, bounds);
|
||||
return connectionPixmap.copy(bounds.x() * 16, bounds.y() * 16, bounds.width() * 16, bounds.height() * 16);
|
||||
}
|
||||
|
||||
|
|
@ -114,18 +134,10 @@ void Map::openScript(QString label) {
|
|||
emit openScriptRequested(label);
|
||||
}
|
||||
|
||||
QList<Event *> Map::getAllEvents() const {
|
||||
QList<Event *> all_events;
|
||||
for (const auto &event_list : events) {
|
||||
all_events << event_list;
|
||||
}
|
||||
return all_events;
|
||||
}
|
||||
|
||||
QStringList Map::getScriptLabels(Event::Group group) {
|
||||
if (!this->scriptsLoaded) {
|
||||
this->scriptsFileLabels = ParseUtil::getGlobalScriptLabels(this->getScriptsFilePath());
|
||||
this->scriptsLoaded = true;
|
||||
if (!m_scriptsLoaded) {
|
||||
m_scriptsFileLabels = ParseUtil::getGlobalScriptLabels(getScriptsFilePath());
|
||||
m_scriptsLoaded = true;
|
||||
}
|
||||
|
||||
QStringList scriptLabels;
|
||||
|
|
@ -133,20 +145,20 @@ QStringList Map::getScriptLabels(Event::Group group) {
|
|||
// Get script labels currently in-use by the map's events
|
||||
if (group == Event::Group::None) {
|
||||
ScriptTracker scriptTracker;
|
||||
for (Event *event : this->getAllEvents()) {
|
||||
for (const auto &event : getEvents()) {
|
||||
event->accept(&scriptTracker);
|
||||
}
|
||||
scriptLabels = scriptTracker.getScripts();
|
||||
} else {
|
||||
ScriptTracker scriptTracker;
|
||||
for (Event *event : events.value(group)) {
|
||||
for (const auto &event : m_events.value(group)) {
|
||||
event->accept(&scriptTracker);
|
||||
}
|
||||
scriptLabels = scriptTracker.getScripts();
|
||||
}
|
||||
|
||||
// Add scripts from map's scripts file, and empty names.
|
||||
scriptLabels.append(this->scriptsFileLabels);
|
||||
scriptLabels.append(m_scriptsFileLabels);
|
||||
scriptLabels.sort(Qt::CaseInsensitive);
|
||||
scriptLabels.prepend("0x0");
|
||||
scriptLabels.prepend("NULL");
|
||||
|
|
@ -162,7 +174,7 @@ QString Map::getScriptsFilePath() const {
|
|||
auto path = QDir::cleanPath(QString("%1/%2/%3/scripts")
|
||||
.arg(projectConfig.projectDir)
|
||||
.arg(projectConfig.getFilePath(ProjectFilePath::data_map_folders))
|
||||
.arg(this->name));
|
||||
.arg(m_name));
|
||||
auto extension = Project::getScriptFileExtension(usePoryscript);
|
||||
if (usePoryscript && !QFile::exists(path + extension))
|
||||
extension = Project::getScriptFileExtension(false);
|
||||
|
|
@ -170,37 +182,77 @@ QString Map::getScriptsFilePath() const {
|
|||
return path;
|
||||
}
|
||||
|
||||
void Map::resetEvents() {
|
||||
m_events[Event::Group::Object].clear();
|
||||
m_events[Event::Group::Warp].clear();
|
||||
m_events[Event::Group::Coord].clear();
|
||||
m_events[Event::Group::Bg].clear();
|
||||
m_events[Event::Group::Heal].clear();
|
||||
}
|
||||
|
||||
QList<Event *> Map::getEvents(Event::Group group) const {
|
||||
if (group == Event::Group::None) {
|
||||
// Get all events
|
||||
QList<Event *> all_events;
|
||||
for (const auto &event_list : m_events) {
|
||||
all_events << event_list;
|
||||
}
|
||||
return all_events;
|
||||
}
|
||||
return m_events[group];
|
||||
}
|
||||
|
||||
Event* Map::getEvent(Event::Group group, int index) const {
|
||||
return m_events[group].value(index, nullptr);
|
||||
}
|
||||
|
||||
int Map::getNumEvents(Event::Group group) const {
|
||||
if (group == Event::Group::None) {
|
||||
// Total number of events
|
||||
int numEvents = 0;
|
||||
for (auto i = m_events.constBegin(); i != m_events.constEnd(); i++) {
|
||||
numEvents += i.value().length();
|
||||
}
|
||||
return numEvents;
|
||||
}
|
||||
return m_events[group].length();
|
||||
}
|
||||
|
||||
void Map::removeEvent(Event *event) {
|
||||
for (Event::Group key : events.keys()) {
|
||||
events[key].removeAll(event);
|
||||
for (auto i = m_events.begin(); i != m_events.end(); i++) {
|
||||
i.value().removeAll(event);
|
||||
}
|
||||
}
|
||||
|
||||
void Map::addEvent(Event *event) {
|
||||
event->setMap(this);
|
||||
events[event->getEventGroup()].append(event);
|
||||
if (!ownedEvents.contains(event)) ownedEvents.append(event);
|
||||
m_events[event->getEventGroup()].append(event);
|
||||
if (!m_ownedEvents.contains(event)) m_ownedEvents.insert(event);
|
||||
}
|
||||
|
||||
int Map::getIndexOfEvent(Event *event) const {
|
||||
return m_events.value(event->getEventGroup()).indexOf(event);
|
||||
}
|
||||
|
||||
void Map::deleteConnections() {
|
||||
qDeleteAll(this->ownedConnections);
|
||||
this->ownedConnections.clear();
|
||||
this->connections.clear();
|
||||
qDeleteAll(m_ownedConnections);
|
||||
m_ownedConnections.clear();
|
||||
m_connections.clear();
|
||||
}
|
||||
|
||||
QList<MapConnection*> Map::getConnections() const {
|
||||
return this->connections;
|
||||
return m_connections;
|
||||
}
|
||||
|
||||
void Map::addConnection(MapConnection *connection) {
|
||||
if (!connection || this->connections.contains(connection))
|
||||
if (!connection || m_connections.contains(connection))
|
||||
return;
|
||||
|
||||
// Maps should only have one Dive/Emerge connection at a time.
|
||||
// (Users can technically have more by editing their data manually, but we will only display one at a time)
|
||||
// Any additional connections being added (this can happen via mirroring) are tracked for deleting but otherwise ignored.
|
||||
if (MapConnection::isDiving(connection->direction())) {
|
||||
for (auto i : this->connections) {
|
||||
for (const auto &i : m_connections) {
|
||||
if (i->direction() == connection->direction()) {
|
||||
trackConnection(connection);
|
||||
return;
|
||||
|
|
@ -218,8 +270,8 @@ void Map::loadConnection(MapConnection *connection) {
|
|||
if (!connection)
|
||||
return;
|
||||
|
||||
if (!this->connections.contains(connection))
|
||||
this->connections.append(connection);
|
||||
if (!m_connections.contains(connection))
|
||||
m_connections.append(connection);
|
||||
|
||||
trackConnection(connection);
|
||||
}
|
||||
|
|
@ -227,12 +279,12 @@ void Map::loadConnection(MapConnection *connection) {
|
|||
void Map::trackConnection(MapConnection *connection) {
|
||||
connection->setParentMap(this, false);
|
||||
|
||||
if (!this->ownedConnections.contains(connection)) {
|
||||
this->ownedConnections.insert(connection);
|
||||
if (!m_ownedConnections.contains(connection)) {
|
||||
m_ownedConnections.insert(connection);
|
||||
connect(connection, &MapConnection::parentMapChanged, [=](Map *, Map *after) {
|
||||
if (after != this && after != nullptr) {
|
||||
// MapConnection's parent has been reassigned, it's no longer our responsibility
|
||||
this->ownedConnections.remove(connection);
|
||||
m_ownedConnections.remove(connection);
|
||||
QObject::disconnect(connection, &MapConnection::parentMapChanged, this, nullptr);
|
||||
}
|
||||
});
|
||||
|
|
@ -241,23 +293,29 @@ void Map::trackConnection(MapConnection *connection) {
|
|||
|
||||
// We retain ownership of this MapConnection until it's assigned to a new parent map.
|
||||
void Map::removeConnection(MapConnection *connection) {
|
||||
if (!this->connections.removeOne(connection))
|
||||
if (!m_connections.removeOne(connection))
|
||||
return;
|
||||
connection->setParentMap(nullptr, false);
|
||||
modify();
|
||||
emit connectionRemoved(connection);
|
||||
}
|
||||
|
||||
void Map::commit(QUndoCommand *cmd) {
|
||||
m_editHistory->push(cmd);
|
||||
}
|
||||
|
||||
void Map::modify() {
|
||||
emit modified();
|
||||
}
|
||||
|
||||
void Map::clean() {
|
||||
this->hasUnsavedDataChanges = false;
|
||||
void Map::setClean() {
|
||||
m_editHistory->setClean();
|
||||
m_hasUnsavedDataChanges = false;
|
||||
m_isPersistedToFile = true;
|
||||
}
|
||||
|
||||
bool Map::hasUnsavedChanges() const {
|
||||
return !editHistory.isClean() || this->layout->hasUnsavedChanges() || hasUnsavedDataChanges || !isPersistedToFile;
|
||||
return !m_editHistory->isClean() || m_layout->hasUnsavedChanges() || m_hasUnsavedDataChanges || !m_isPersistedToFile;
|
||||
}
|
||||
|
||||
void Map::pruneEditHistory() {
|
||||
|
|
@ -271,11 +329,11 @@ void Map::pruneEditHistory() {
|
|||
ID_MapConnectionAdd,
|
||||
ID_MapConnectionRemove
|
||||
};
|
||||
for (int i = 0; i < this->editHistory.count(); i++) {
|
||||
for (int i = 0; i < m_editHistory->count(); i++) {
|
||||
// Qt really doesn't expect editing commands in the stack to be valid (fair).
|
||||
// A better future design might be to have separate edit histories per map tab,
|
||||
// and dumping the entire Connections tab history with QUndoStack::clear.
|
||||
auto command = const_cast<QUndoCommand*>(this->editHistory.command(i));
|
||||
auto command = const_cast<QUndoCommand*>(m_editHistory->command(i));
|
||||
if (mapConnectionIds.contains(command->id()))
|
||||
command->setObsolete(true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ QPixmap MapConnection::getPixmap() {
|
|||
if (!map)
|
||||
return QPixmap();
|
||||
|
||||
return map->renderConnection(m_direction, m_parentMap ? m_parentMap->layout : nullptr);
|
||||
return map->renderConnection(m_direction, m_parentMap ? m_parentMap->layout() : nullptr);
|
||||
}
|
||||
|
||||
void MapConnection::setParentMap(Map* map, bool mirror) {
|
||||
|
|
@ -75,7 +75,7 @@ void MapConnection::setParentMap(Map* map, bool mirror) {
|
|||
if (mirror) {
|
||||
auto connection = findMirror();
|
||||
if (connection)
|
||||
connection->setTargetMapName(map ? map->name : QString(), false);
|
||||
connection->setTargetMapName(map ? map->name() : QString(), false);
|
||||
}
|
||||
|
||||
if (m_parentMap)
|
||||
|
|
@ -91,7 +91,7 @@ void MapConnection::setParentMap(Map* map, bool mirror) {
|
|||
}
|
||||
|
||||
QString MapConnection::parentMapName() const {
|
||||
return m_parentMap ? m_parentMap->name : QString();
|
||||
return m_parentMap ? m_parentMap->name() : QString();
|
||||
}
|
||||
|
||||
void MapConnection::setTargetMapName(const QString &targetMapName, bool mirror) {
|
||||
|
|
|
|||
121
src/core/mapheader.cpp
Normal file
121
src/core/mapheader.cpp
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
#include "mapheader.h"
|
||||
|
||||
MapHeader::MapHeader(const MapHeader& other) : MapHeader() {
|
||||
m_song = other.m_song;
|
||||
m_location = other.m_location;
|
||||
m_requiresFlash = other.m_requiresFlash;
|
||||
m_weather = other.m_weather;
|
||||
m_type = other.m_type;
|
||||
m_showsLocationName = other.m_showsLocationName;
|
||||
m_allowsRunning = other.m_allowsRunning;
|
||||
m_allowsBiking = other.m_allowsBiking;
|
||||
m_allowsEscaping = other.m_allowsEscaping;
|
||||
m_floorNumber = other.m_floorNumber;
|
||||
m_battleScene = other.m_battleScene;
|
||||
}
|
||||
|
||||
MapHeader &MapHeader::operator=(const MapHeader &other) {
|
||||
// We want to call each set function here to ensure any fieldChanged signals
|
||||
// are sent as necessary. This does also mean the modified signal can be sent
|
||||
// repeatedly (but for now at least that's not a big issue).
|
||||
setSong(other.m_song);
|
||||
setLocation(other.m_location);
|
||||
setRequiresFlash(other.m_requiresFlash);
|
||||
setWeather(other.m_weather);
|
||||
setType(other.m_type);
|
||||
setShowsLocationName(other.m_showsLocationName);
|
||||
setAllowsRunning(other.m_allowsRunning);
|
||||
setAllowsBiking(other.m_allowsBiking);
|
||||
setAllowsEscaping(other.m_allowsEscaping);
|
||||
setFloorNumber(other.m_floorNumber);
|
||||
setBattleScene(other.m_battleScene);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void MapHeader::setSong(const QString &song) {
|
||||
if (m_song == song)
|
||||
return;
|
||||
m_song = song;
|
||||
emit songChanged(m_song);
|
||||
emit modified();
|
||||
}
|
||||
|
||||
void MapHeader::setLocation(const QString &location) {
|
||||
if (m_location == location)
|
||||
return;
|
||||
m_location = location;
|
||||
emit locationChanged(m_location);
|
||||
emit modified();
|
||||
}
|
||||
|
||||
void MapHeader::setRequiresFlash(bool requiresFlash) {
|
||||
if (m_requiresFlash == requiresFlash)
|
||||
return;
|
||||
m_requiresFlash = requiresFlash;
|
||||
emit requiresFlashChanged(m_requiresFlash);
|
||||
emit modified();
|
||||
}
|
||||
|
||||
void MapHeader::setWeather(const QString &weather) {
|
||||
if (m_weather == weather)
|
||||
return;
|
||||
m_weather = weather;
|
||||
emit weatherChanged(m_weather);
|
||||
emit modified();
|
||||
}
|
||||
|
||||
void MapHeader::setType(const QString &type) {
|
||||
if (m_type == type)
|
||||
return;
|
||||
m_type = type;
|
||||
emit typeChanged(m_type);
|
||||
emit modified();
|
||||
}
|
||||
|
||||
void MapHeader::setShowsLocationName(bool showsLocationName) {
|
||||
if (m_showsLocationName == showsLocationName)
|
||||
return;
|
||||
m_showsLocationName = showsLocationName;
|
||||
emit showsLocationNameChanged(m_showsLocationName);
|
||||
emit modified();
|
||||
}
|
||||
|
||||
void MapHeader::setAllowsRunning(bool allowsRunning) {
|
||||
if (m_allowsRunning == allowsRunning)
|
||||
return;
|
||||
m_allowsRunning = allowsRunning;
|
||||
emit allowsRunningChanged(m_allowsRunning);
|
||||
emit modified();
|
||||
}
|
||||
|
||||
void MapHeader::setAllowsBiking(bool allowsBiking) {
|
||||
if (m_allowsBiking == allowsBiking)
|
||||
return;
|
||||
m_allowsBiking = allowsBiking;
|
||||
emit allowsBikingChanged(m_allowsBiking);
|
||||
emit modified();
|
||||
}
|
||||
|
||||
void MapHeader::setAllowsEscaping(bool allowsEscaping) {
|
||||
if (m_allowsEscaping == allowsEscaping)
|
||||
return;
|
||||
m_allowsEscaping = allowsEscaping;
|
||||
emit allowsEscapingChanged(m_allowsEscaping);
|
||||
emit modified();
|
||||
}
|
||||
|
||||
void MapHeader::setFloorNumber(int floorNumber) {
|
||||
if (m_floorNumber == floorNumber)
|
||||
return;
|
||||
m_floorNumber = floorNumber;
|
||||
emit floorNumberChanged(m_floorNumber);
|
||||
emit modified();
|
||||
}
|
||||
|
||||
void MapHeader::setBattleScene(const QString &battleScene) {
|
||||
if (m_battleScene == battleScene)
|
||||
return;
|
||||
m_battleScene = battleScene;
|
||||
emit battleSceneChanged(m_battleScene);
|
||||
emit modified();
|
||||
}
|
||||
|
|
@ -5,15 +5,17 @@
|
|||
#include "scripting.h"
|
||||
#include "imageproviders.h"
|
||||
|
||||
Layout::Layout(const Layout &other) : Layout() {
|
||||
copyFrom(&other);
|
||||
}
|
||||
|
||||
|
||||
Layout *Layout::copy() {
|
||||
Layout *Layout::copy() const {
|
||||
Layout *layout = new Layout;
|
||||
layout->copyFrom(this);
|
||||
return layout;
|
||||
}
|
||||
|
||||
void Layout::copyFrom(Layout *other) {
|
||||
void Layout::copyFrom(const Layout *other) {
|
||||
this->id = other->id;
|
||||
this->name = other->name;
|
||||
this->width = other->width;
|
||||
|
|
@ -36,29 +38,20 @@ QString Layout::layoutConstantFromName(QString mapName) {
|
|||
QString nameWithUnderscores = mapName.replace(caseChange, "\\1_\\2");
|
||||
QString withMapAndUppercase = "LAYOUT_" + nameWithUnderscores.toUpper();
|
||||
static const QRegularExpression underscores("_+");
|
||||
QString constantName = withMapAndUppercase.replace(underscores, "_");
|
||||
|
||||
// Handle special cases.
|
||||
// SSTidal should be SS_TIDAL, rather than SSTIDAL
|
||||
constantName = constantName.replace("SSTIDAL", "SS_TIDAL");
|
||||
|
||||
return constantName;
|
||||
return withMapAndUppercase.replace(underscores, "_");
|
||||
}
|
||||
|
||||
int Layout::getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
int Layout::getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
int Layout::getBorderWidth() {
|
||||
return border_width;
|
||||
}
|
||||
|
||||
int Layout::getBorderHeight() {
|
||||
return border_height;
|
||||
Layout::Settings Layout::settings() const {
|
||||
Layout::Settings settings;
|
||||
settings.id = this->id;
|
||||
settings.name = this->name;
|
||||
settings.width = this->width;
|
||||
settings.height = this->height;
|
||||
settings.borderWidth = this->border_width;
|
||||
settings.borderHeight = this->border_height;
|
||||
settings.primaryTilesetLabel = this->tileset_primary_label;
|
||||
settings.secondaryTilesetLabel = this->tileset_secondary_label;
|
||||
return settings;
|
||||
}
|
||||
|
||||
bool Layout::isWithinBounds(int x, int y) {
|
||||
|
|
|
|||
|
|
@ -1,97 +0,0 @@
|
|||
#include "mapparser.h"
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "project.h"
|
||||
|
||||
MapParser::MapParser()
|
||||
{
|
||||
}
|
||||
|
||||
Layout *MapParser::parse(QString filepath, bool *error, Project *project)
|
||||
{
|
||||
QFile file(filepath);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
*error = true;
|
||||
logError(QString("Could not open Advance Map 1.92 Map .map file '%1': ").arg(filepath) + file.errorString());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QByteArray in = file.readAll();
|
||||
file.close();
|
||||
|
||||
if (in.length() < 20 || in.length() % 2 != 0) {
|
||||
*error = true;
|
||||
logError(QString("Advance Map 1.92 Map .map file '%1' is an unexpected size.").arg(filepath));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int borderWidth = static_cast<unsigned char>(in.at(16)); // 0 in RSE .map files
|
||||
int borderHeight = static_cast<unsigned char>(in.at(17)); // 0 in RSE .map files
|
||||
int numBorderTiles = borderWidth * borderHeight; // 0 if RSE
|
||||
|
||||
int mapDataOffset = 20 + (numBorderTiles * 2); // FRLG .map files store border metatile data after the header
|
||||
int mapWidth = static_cast<unsigned char>(in.at(0)) |
|
||||
(static_cast<unsigned char>(in.at(1)) << 8) |
|
||||
(static_cast<unsigned char>(in.at(2)) << 16) |
|
||||
(static_cast<unsigned char>(in.at(3)) << 24);
|
||||
int mapHeight = static_cast<unsigned char>(in.at(4)) |
|
||||
(static_cast<unsigned char>(in.at(5)) << 8) |
|
||||
(static_cast<unsigned char>(in.at(6)) << 16) |
|
||||
(static_cast<unsigned char>(in.at(7)) << 24);
|
||||
int mapPrimaryTilesetNum = static_cast<unsigned char>(in.at(8)) |
|
||||
(static_cast<unsigned char>(in.at(9)) << 8) |
|
||||
(static_cast<unsigned char>(in.at(10)) << 16) |
|
||||
(static_cast<unsigned char>(in.at(11)) << 24);
|
||||
int mapSecondaryTilesetNum = static_cast<unsigned char>(in.at(12)) |
|
||||
(static_cast<unsigned char>(in.at(13)) << 8) |
|
||||
(static_cast<unsigned char>(in.at(14)) << 16) |
|
||||
(static_cast<unsigned char>(in.at(15)) << 24);
|
||||
|
||||
int numMetatiles = mapWidth * mapHeight;
|
||||
int expectedFileSize = 20 + (numBorderTiles * 2) + (numMetatiles * 2);
|
||||
if (in.length() != expectedFileSize) {
|
||||
*error = true;
|
||||
logError(QString(".map file is an unexpected size. Expected %1 bytes, but it has %2 bytes.").arg(expectedFileSize).arg(in.length()));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Blockdata blockdata;
|
||||
for (int i = mapDataOffset; (i + 1) < in.length(); i += 2) {
|
||||
uint16_t word = static_cast<uint16_t>((in[i] & 0xff) + ((in[i + 1] & 0xff) << 8));
|
||||
blockdata.append(word);
|
||||
}
|
||||
|
||||
Blockdata border;
|
||||
if (numBorderTiles != 0) {
|
||||
for (int i = 20; (i + 1) < mapDataOffset; i += 2) {
|
||||
uint16_t word = static_cast<uint16_t>((in[i] & 0xff) + ((in[i + 1] & 0xff) << 8));
|
||||
border.append(word);
|
||||
}
|
||||
}
|
||||
|
||||
Layout *mapLayout = new Layout();
|
||||
mapLayout->width = mapWidth;
|
||||
mapLayout->height = mapHeight;
|
||||
mapLayout->border_width = (borderWidth == 0) ? DEFAULT_BORDER_WIDTH : borderWidth;
|
||||
mapLayout->border_height = (borderHeight == 0) ? DEFAULT_BORDER_HEIGHT : borderHeight;
|
||||
|
||||
QList<QString> tilesets = project->tilesetLabelsOrdered;
|
||||
|
||||
if (mapPrimaryTilesetNum > tilesets.size())
|
||||
mapLayout->tileset_primary_label = tilesets.at(0);
|
||||
else
|
||||
mapLayout->tileset_primary_label = tilesets.at(mapPrimaryTilesetNum);
|
||||
|
||||
if (mapSecondaryTilesetNum > tilesets.size())
|
||||
mapLayout->tileset_secondary_label = tilesets.at(1);
|
||||
else
|
||||
mapLayout->tileset_secondary_label = tilesets.at(mapSecondaryTilesetNum);
|
||||
|
||||
mapLayout->blockdata = blockdata;
|
||||
|
||||
if (!border.isEmpty()) {
|
||||
mapLayout->border = border;
|
||||
}
|
||||
|
||||
return mapLayout;
|
||||
}
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
#include "metatileparser.h"
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "project.h"
|
||||
#include <QString>
|
||||
|
||||
QList<Metatile*> MetatileParser::parse(QString filepath, bool *error, bool primaryTileset)
|
||||
{
|
||||
QFile file(filepath);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
*error = true;
|
||||
logError(QString("Could not open Advance Map 1.92 Metatile .bvd file '%1': ").arg(filepath) + file.errorString());
|
||||
return { };
|
||||
}
|
||||
|
||||
QByteArray in = file.readAll();
|
||||
file.close();
|
||||
|
||||
if (in.length() < 9 || in.length() % 2 != 0) {
|
||||
*error = true;
|
||||
logError(QString("Advance Map 1.92 Metatile .bvd file '%1' is an unexpected size.").arg(filepath));
|
||||
return { };
|
||||
}
|
||||
|
||||
int projIdOffset = in.length() - 4;
|
||||
int metatileSize = 16;
|
||||
BaseGameVersion version;
|
||||
if (in.at(projIdOffset + 0) == 'R'
|
||||
&& in.at(projIdOffset + 1) == 'S'
|
||||
&& in.at(projIdOffset + 2) == 'E'
|
||||
&& in.at(projIdOffset + 3) == ' ') {
|
||||
// ruby and emerald are handled equally here.
|
||||
version = BaseGameVersion::pokeemerald;
|
||||
} else if (in.at(projIdOffset + 0) == 'F'
|
||||
&& in.at(projIdOffset + 1) == 'R'
|
||||
&& in.at(projIdOffset + 2) == 'L'
|
||||
&& in.at(projIdOffset + 3) == 'G') {
|
||||
version = BaseGameVersion::pokefirered;
|
||||
} else {
|
||||
*error = true;
|
||||
logError(QString("Detected unsupported game type from .bvd file. Last 4 bytes of file must be 'RSE ' or 'FRLG'."));
|
||||
return { };
|
||||
}
|
||||
|
||||
int attrSize = Metatile::getDefaultAttributesSize(version);
|
||||
int maxMetatiles = primaryTileset ? Project::getNumMetatilesPrimary() : Project::getNumMetatilesTotal() - Project::getNumMetatilesPrimary();
|
||||
int numMetatiles = static_cast<unsigned char>(in.at(0)) |
|
||||
(static_cast<unsigned char>(in.at(1)) << 8) |
|
||||
(static_cast<unsigned char>(in.at(2)) << 16) |
|
||||
(static_cast<unsigned char>(in.at(3)) << 24);
|
||||
if (numMetatiles > maxMetatiles) {
|
||||
*error = true;
|
||||
logError(QString(".bvd file contains data for %1 metatiles, but the maximum number of metatiles is %2.").arg(numMetatiles).arg(maxMetatiles));
|
||||
return { };
|
||||
}
|
||||
if (numMetatiles < 1) {
|
||||
*error = true;
|
||||
logError(QString(".bvd file contains no data for metatiles."));
|
||||
return { };
|
||||
}
|
||||
|
||||
int expectedFileSize = 4 + (metatileSize * numMetatiles) + (attrSize * numMetatiles) + 4;
|
||||
if (in.length() != expectedFileSize) {
|
||||
*error = true;
|
||||
logError(QString(".bvd file is an unexpected size. Expected %1 bytes, but it has %2 bytes.").arg(expectedFileSize).arg(in.length()));
|
||||
return { };
|
||||
}
|
||||
|
||||
QList<Metatile*> metatiles;
|
||||
for (int i = 0; i < numMetatiles; i++) {
|
||||
Metatile *metatile = new Metatile();
|
||||
QList<Tile> tiles;
|
||||
for (int j = 0; j < 8; j++) {
|
||||
int metatileOffset = 4 + i * metatileSize + j * 2;
|
||||
Tile tile(static_cast<uint16_t>(
|
||||
static_cast<unsigned char>(in.at(metatileOffset)) |
|
||||
(static_cast<unsigned char>(in.at(metatileOffset + 1)) << 8)));
|
||||
tiles.append(tile);
|
||||
}
|
||||
|
||||
// AdvanceMap .bvd files only contain 8 tiles of data per metatile.
|
||||
// If the user has triple-layer metatiles enabled we need to fill the remaining 4 tiles ourselves.
|
||||
if (projectConfig.tripleLayerMetatilesEnabled) {
|
||||
Tile tile = Tile();
|
||||
for (int j = 0; j < 4; j++)
|
||||
tiles.append(tile);
|
||||
}
|
||||
|
||||
int attrOffset = 4 + (numMetatiles * metatileSize) + (i * attrSize);
|
||||
uint32_t attributes = 0;
|
||||
for (int j = 0; j < attrSize; j++)
|
||||
attributes |= static_cast<unsigned char>(in.at(attrOffset + j)) << (8 * j);
|
||||
metatile->setAttributes(attributes, version);
|
||||
metatile->tiles = tiles;
|
||||
metatiles.append(metatile);
|
||||
}
|
||||
|
||||
return metatiles;
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
#include "paletteutil.h"
|
||||
#include "advancemapparser.h"
|
||||
#include "log.h"
|
||||
#include <QFileInfo>
|
||||
#include <QRegularExpression>
|
||||
|
|
@ -6,7 +7,6 @@
|
|||
|
||||
QList<QRgb> parsePal(QString filepath, bool *error);
|
||||
QList<QRgb> parseJASC(QString filepath, bool *error);
|
||||
QList<QRgb> parseAdvanceMapPal(QString filepath, bool *error);
|
||||
QList<QRgb> parseAdobeColorTable(QString filepath, bool *error);
|
||||
QList<QRgb> parseTileLayerPro(QString filepath, bool *error);
|
||||
QList<QRgb> parseAdvancePaletteEditor(QString filepath, bool *error);
|
||||
|
|
@ -81,7 +81,7 @@ QList<QRgb> parsePal(QString filepath, bool *error) {
|
|||
return parseJASC(filepath, error);
|
||||
} else {
|
||||
file.close();
|
||||
return parseAdvanceMapPal(filepath, error);
|
||||
return AdvanceMapParser::parsePalette(filepath, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -152,38 +152,6 @@ QList<QRgb> parseJASC(QString filepath, bool *error) {
|
|||
return palette;
|
||||
}
|
||||
|
||||
QList<QRgb> parseAdvanceMapPal(QString filepath, bool *error) {
|
||||
QFile file(filepath);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
*error = true;
|
||||
logError(QString("Could not open Advance Map 1.92 palette file '%1': ").arg(filepath) + file.errorString());
|
||||
return QList<QRgb>();
|
||||
}
|
||||
|
||||
QByteArray in = file.readAll();
|
||||
file.close();
|
||||
|
||||
if (in.length() % 4 != 0) {
|
||||
*error = true;
|
||||
logError(QString("Advance Map 1.92 palette file '%1' had an unexpected format. File's length must be a multiple of 4, but the length is %2.").arg(filepath).arg(in.length()));
|
||||
return QList<QRgb>();
|
||||
}
|
||||
|
||||
QList<QRgb> palette;
|
||||
int i = 0;
|
||||
while (i < in.length()) {
|
||||
unsigned char red = static_cast<unsigned char>(in.at(i));
|
||||
unsigned char green = static_cast<unsigned char>(in.at(i + 1));
|
||||
unsigned char blue = static_cast<unsigned char>(in.at(i + 2));
|
||||
palette.append(qRgb(clampColorValue(red),
|
||||
clampColorValue(green),
|
||||
clampColorValue(blue)));
|
||||
i += 4;
|
||||
}
|
||||
|
||||
return palette;
|
||||
}
|
||||
|
||||
QList<QRgb> parseAdobeColorTable(QString filepath, bool *error) {
|
||||
QFile file(filepath);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
|
|
|
|||
|
|
@ -593,13 +593,13 @@ bool ParseUtil::gameStringToBool(QString gameString, bool * ok) {
|
|||
return gameStringToInt(gameString, ok) != 0;
|
||||
}
|
||||
|
||||
QMap<QString, QHash<QString, QString>> ParseUtil::readCStructs(const QString &filename, const QString &label, const QHash<int, QString> memberMap) {
|
||||
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;
|
||||
auto cParser = fex::Parser();
|
||||
auto tokens = fex::Lexer().LexFile(filePath);
|
||||
auto structs = cParser.ParseTopLevelObjects(tokens);
|
||||
QMap<QString, QHash<QString, QString>> structMaps;
|
||||
for (auto it = structs.begin(); it != structs.end(); it++) {
|
||||
auto topLevelObjects = cParser.ParseTopLevelObjects(tokens);
|
||||
tsl::ordered_map<QString, QHash<QString, QString>> structs;
|
||||
for (auto it = topLevelObjects.begin(); it != topLevelObjects.end(); it++) {
|
||||
QString structLabel = QString::fromStdString(it->first);
|
||||
if (structLabel.isEmpty()) continue;
|
||||
if (!label.isEmpty() && label != structLabel) continue; // Speed up parsing if only looking for a particular symbol
|
||||
|
|
@ -617,9 +617,9 @@ QMap<QString, QHash<QString, QString>> ParseUtil::readCStructs(const QString &fi
|
|||
}
|
||||
i++;
|
||||
}
|
||||
structMaps.insert(structLabel, values);
|
||||
structs[structLabel] = values;
|
||||
}
|
||||
return structMaps;
|
||||
return structs;
|
||||
}
|
||||
|
||||
QList<QStringList> ParseUtil::getLabelMacros(const QList<QStringList> &list, const QString &label) {
|
||||
|
|
|
|||
|
|
@ -397,10 +397,15 @@ void RegionMap::saveLayout() {
|
|||
case LayoutFormat::Binary:
|
||||
{
|
||||
QByteArray data;
|
||||
int defaultValue = this->project->mapSectionIdNames.indexOf(this->default_map_section);
|
||||
for (int m = 0; m < this->layout_height; m++) {
|
||||
for (int n = 0; n < this->layout_width; n++) {
|
||||
int i = n + this->layout_width * m;
|
||||
data.append(this->project->mapSectionIdNames.indexOf(this->layouts["main"][i].map_section));
|
||||
int mapSectionValue = this->project->mapSectionIdNames.indexOf(this->layouts["main"][i].map_section);
|
||||
if (mapSectionValue < 0){
|
||||
mapSectionValue = defaultValue;
|
||||
}
|
||||
data.append(mapSectionValue);
|
||||
}
|
||||
}
|
||||
QFile bfile(fullPath(this->layout_path));
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
#include "project.h"
|
||||
#include "log.h"
|
||||
#include "config.h"
|
||||
#include "imageproviders.h"
|
||||
#include "validator.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QImage>
|
||||
|
|
@ -23,7 +25,7 @@ Tileset::Tileset(const Tileset &other)
|
|||
metatileLabels(other.metatileLabels),
|
||||
palettes(other.palettes),
|
||||
palettePreviews(other.palettePreviews),
|
||||
hasUnsavedTilesImage(false)
|
||||
m_hasUnsavedTilesImage(other.m_hasUnsavedTilesImage)
|
||||
{
|
||||
for (auto tile : other.tiles) {
|
||||
tiles.append(tile.copy());
|
||||
|
|
@ -179,10 +181,8 @@ bool Tileset::setMetatileLabel(int metatileId, QString label, Tileset *primaryTi
|
|||
if (!tileset)
|
||||
return false;
|
||||
|
||||
static const QRegularExpression expression("[_A-Za-z0-9]*$");
|
||||
QRegularExpressionValidator validator(expression);
|
||||
int pos = 0;
|
||||
if (validator.validate(label, pos) != QValidator::Acceptable)
|
||||
IdentifierValidator validator;
|
||||
if (!validator.isValid(label))
|
||||
return false;
|
||||
|
||||
tileset->metatileLabels[metatileId] = label;
|
||||
|
|
@ -397,3 +397,184 @@ QHash<int, QString> Tileset::getHeaderMemberMap(bool usingAsm)
|
|||
map.insert(metatileAttrPosition, "metatileAttributes");
|
||||
return map;
|
||||
}
|
||||
|
||||
void Tileset::loadMetatiles() {
|
||||
clearMetatiles();
|
||||
|
||||
QFile metatiles_file(this->metatiles_path);
|
||||
if (!metatiles_file.open(QIODevice::ReadOnly)) {
|
||||
logError(QString("Could not open '%1' for reading.").arg(this->metatiles_path));
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray data = metatiles_file.readAll();
|
||||
int tilesPerMetatile = projectConfig.getNumTilesInMetatile();
|
||||
int bytesPerMetatile = 2 * tilesPerMetatile;
|
||||
int num_metatiles = data.length() / bytesPerMetatile;
|
||||
for (int i = 0; i < num_metatiles; i++) {
|
||||
auto metatile = new Metatile;
|
||||
int index = i * bytesPerMetatile;
|
||||
for (int j = 0; j < tilesPerMetatile; j++) {
|
||||
uint16_t tileRaw = static_cast<unsigned char>(data[index++]);
|
||||
tileRaw |= static_cast<unsigned char>(data[index++]) << 8;
|
||||
metatile->tiles.append(Tile(tileRaw));
|
||||
}
|
||||
m_metatiles.append(metatile);
|
||||
}
|
||||
}
|
||||
|
||||
void Tileset::saveMetatiles() {
|
||||
QFile metatiles_file(this->metatiles_path);
|
||||
if (!metatiles_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
logError(QString("Could not open '%1' for writing.").arg(this->metatiles_path));
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray data;
|
||||
int numTiles = projectConfig.getNumTilesInMetatile();
|
||||
for (const auto &metatile : m_metatiles) {
|
||||
for (int i = 0; i < numTiles; i++) {
|
||||
uint16_t tile = metatile->tiles.at(i).rawValue();
|
||||
data.append(static_cast<char>(tile));
|
||||
data.append(static_cast<char>(tile >> 8));
|
||||
}
|
||||
}
|
||||
metatiles_file.write(data);
|
||||
}
|
||||
|
||||
void Tileset::loadMetatileAttributes() {
|
||||
QFile attrs_file(this->metatile_attrs_path);
|
||||
if (!attrs_file.open(QIODevice::ReadOnly)) {
|
||||
logError(QString("Could not open '%1' for reading.").arg(this->metatile_attrs_path));
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray data = attrs_file.readAll();
|
||||
int attrSize = projectConfig.metatileAttributesSize;
|
||||
int numMetatiles = m_metatiles.length();
|
||||
int numMetatileAttrs = data.length() / attrSize;
|
||||
if (numMetatiles != numMetatileAttrs) {
|
||||
logWarn(QString("Metatile count %1 does not match metatile attribute count %2 in %3").arg(numMetatiles).arg(numMetatileAttrs).arg(this->name));
|
||||
}
|
||||
|
||||
for (int i = 0; i < qMin(numMetatiles, numMetatileAttrs); i++) {
|
||||
uint32_t attributes = 0;
|
||||
for (int j = 0; j < attrSize; j++)
|
||||
attributes |= static_cast<unsigned char>(data.at(i * attrSize + j)) << (8 * j);
|
||||
m_metatiles.at(i)->setAttributes(attributes);
|
||||
}
|
||||
}
|
||||
|
||||
void Tileset::saveMetatileAttributes() {
|
||||
QFile attrs_file(this->metatile_attrs_path);
|
||||
if (!attrs_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
logError(QString("Could not open '%1' for writing.").arg(this->metatile_attrs_path));
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray data;
|
||||
for (const auto &metatile : m_metatiles) {
|
||||
uint32_t attributes = metatile->getAttributes();
|
||||
for (int i = 0; i < projectConfig.metatileAttributesSize; i++)
|
||||
data.append(static_cast<char>(attributes >> (8 * i)));
|
||||
}
|
||||
attrs_file.write(data);
|
||||
}
|
||||
|
||||
void Tileset::loadTilesImage(QImage *importedImage) {
|
||||
QImage image;
|
||||
if (importedImage) {
|
||||
image = *importedImage;
|
||||
m_hasUnsavedTilesImage = true;
|
||||
} else if (QFile::exists(this->tilesImagePath)) {
|
||||
// No image provided, load from file path.
|
||||
image = QImage(this->tilesImagePath).convertToFormat(QImage::Format_Indexed8, Qt::ThresholdDither);
|
||||
} else {
|
||||
// Use default image
|
||||
image = QImage(8, 8, QImage::Format_Indexed8);
|
||||
}
|
||||
|
||||
// Validate image contains 16 colors.
|
||||
int colorCount = image.colorCount();
|
||||
if (colorCount > 16) {
|
||||
flattenTo4bppImage(&image);
|
||||
} else if (colorCount < 16) {
|
||||
QVector<QRgb> colorTable = image.colorTable();
|
||||
for (int i = colorTable.length(); i < 16; i++) {
|
||||
colorTable.append(Qt::black);
|
||||
}
|
||||
image.setColorTable(colorTable);
|
||||
}
|
||||
|
||||
QList<QImage> tiles;
|
||||
int w = 8;
|
||||
int h = 8;
|
||||
for (int y = 0; y < image.height(); y += h)
|
||||
for (int x = 0; x < image.width(); x += w) {
|
||||
QImage tile = image.copy(x, y, w, h);
|
||||
tiles.append(tile);
|
||||
}
|
||||
this->tilesImage = image;
|
||||
this->tiles = tiles;
|
||||
}
|
||||
|
||||
void Tileset::saveTilesImage() {
|
||||
// Only write the tiles image if it was changed.
|
||||
// Porymap will only ever change an existing tiles image by importing a new one.
|
||||
if (!m_hasUnsavedTilesImage)
|
||||
return;
|
||||
|
||||
if (!this->tilesImage.save(this->tilesImagePath, "PNG")) {
|
||||
logError(QString("Failed to save tiles image '%1'").arg(this->tilesImagePath));
|
||||
return;
|
||||
}
|
||||
|
||||
m_hasUnsavedTilesImage = false;
|
||||
}
|
||||
|
||||
void Tileset::loadPalettes() {
|
||||
this->palettes.clear();
|
||||
this->palettePreviews.clear();
|
||||
|
||||
for (int i = 0; i < Project::getNumPalettesTotal(); i++) {
|
||||
QList<QRgb> palette;
|
||||
QString path = this->palettePaths.value(i);
|
||||
if (!path.isEmpty()) {
|
||||
bool error = false;
|
||||
palette = PaletteUtil::parse(path, &error);
|
||||
if (error) palette.clear();
|
||||
}
|
||||
if (palette.isEmpty()) {
|
||||
// Either the palette failed to load, or no palette exists.
|
||||
// We expect tilesets to have a certain number of palettes,
|
||||
// so fill this palette with dummy colors.
|
||||
for (int j = 0; j < 16; j++) {
|
||||
palette.append(qRgb(j * 16, j * 16, j * 16));
|
||||
}
|
||||
}
|
||||
this->palettes.append(palette);
|
||||
this->palettePreviews.append(palette);
|
||||
}
|
||||
}
|
||||
|
||||
void Tileset::savePalettes() {
|
||||
int numPalettes = qMin(this->palettePaths.length(), this->palettes.length());
|
||||
for (int i = 0; i < numPalettes; i++) {
|
||||
PaletteUtil::writeJASC(this->palettePaths.at(i), this->palettes.at(i).toVector(), 0, 16);
|
||||
}
|
||||
}
|
||||
|
||||
void Tileset::load() {
|
||||
loadMetatiles();
|
||||
loadMetatileAttributes();
|
||||
loadTilesImage();
|
||||
loadPalettes();
|
||||
}
|
||||
|
||||
// Because metatile labels are global (and handled by the project) we don't save them here.
|
||||
void Tileset::save() {
|
||||
saveMetatiles();
|
||||
saveMetatileAttributes();
|
||||
saveTilesImage();
|
||||
savePalettes();
|
||||
}
|
||||
|
|
|
|||
30
src/core/validator.cpp
Normal file
30
src/core/validator.cpp
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#include "validator.h"
|
||||
|
||||
// Identifiers must only contain word characters, and cannot start with a digit.
|
||||
const QRegularExpression IdentifierValidator::re_identifier = QRegularExpression("[A-Za-z_]+[\\w]*");
|
||||
|
||||
|
||||
bool PrefixValidator::missingPrefix(const QString &input) const {
|
||||
return !m_prefix.isEmpty() && !input.startsWith(m_prefix);
|
||||
}
|
||||
|
||||
QValidator::State PrefixValidator::validate(QString &input, int &pos) const {
|
||||
auto state = QRegularExpressionValidator::validate(input, pos);
|
||||
if (state == QValidator::Acceptable) {
|
||||
// This input could be valid. If there's a prefix we should require it now.
|
||||
if (missingPrefix(input))
|
||||
state = QValidator::Intermediate;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
void PrefixValidator::fixup(QString &input) const {
|
||||
QRegularExpressionValidator::fixup(input);
|
||||
if (missingPrefix(input))
|
||||
input.prepend(m_prefix);
|
||||
}
|
||||
|
||||
bool PrefixValidator::isValid(QString &input) const {
|
||||
int pos = 0;
|
||||
return validate(input, pos) == QValidator::Acceptable;
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
#include "config.h"
|
||||
#include "scripting.h"
|
||||
#include "customattributestable.h"
|
||||
#include "validator.h"
|
||||
#include <QCheckBox>
|
||||
#include <QPainter>
|
||||
#include <QMouseEvent>
|
||||
|
|
@ -152,7 +153,7 @@ void Editor::setEditorView() {
|
|||
map_item->setEditsEnabled(false);
|
||||
case EditMode::Events:
|
||||
if (this->map) {
|
||||
this->editGroup.setActiveStack(&this->map->editHistory);
|
||||
this->editGroup.setActiveStack(this->map->editHistory());
|
||||
}
|
||||
break;
|
||||
case EditMode::Header:
|
||||
|
|
@ -240,23 +241,23 @@ void Editor::displayWildMonTables() {
|
|||
clearWildMonTables();
|
||||
|
||||
// Don't try to read encounter data if it doesn't exist on disk for this map.
|
||||
if (!project->wildMonData.contains(map->constantName)) {
|
||||
if (!project->wildMonData.contains(map->constantName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
QComboBox *labelCombo = ui->comboBox_EncounterGroupLabel;
|
||||
for (auto groupPair : project->wildMonData[map->constantName])
|
||||
for (auto groupPair : project->wildMonData[map->constantName()])
|
||||
labelCombo->addItem(groupPair.first);
|
||||
|
||||
labelCombo->setCurrentText(labelCombo->itemText(0));
|
||||
|
||||
QStackedWidget *stack = ui->stackedWidget_WildMons;
|
||||
int labelIndex = 0;
|
||||
for (auto labelPair : project->wildMonData[map->constantName]) {
|
||||
for (auto labelPair : project->wildMonData[map->constantName()]) {
|
||||
|
||||
QString label = labelPair.first;
|
||||
|
||||
WildPokemonHeader header = project->wildMonData[map->constantName][label];
|
||||
WildPokemonHeader header = project->wildMonData[map->constantName()][label];
|
||||
|
||||
MonTabWidget *tabWidget = new MonTabWidget(this);
|
||||
stack->insertWidget(labelIndex++, tabWidget);
|
||||
|
|
@ -267,7 +268,7 @@ void Editor::displayWildMonTables() {
|
|||
|
||||
tabWidget->clearTableAt(tabIndex);
|
||||
|
||||
if (project->wildMonData.contains(map->constantName) && header.wildMons[fieldName].active) {
|
||||
if (project->wildMonData.contains(map->constantName()) && header.wildMons[fieldName].active) {
|
||||
tabWidget->populateTab(tabIndex, header.wildMons[fieldName]);
|
||||
} else {
|
||||
tabWidget->setTabActive(tabIndex, false);
|
||||
|
|
@ -299,9 +300,7 @@ void Editor::addNewWildMonGroup(QWidget *window) {
|
|||
QLineEdit *lineEdit = new QLineEdit();
|
||||
lineEdit->setClearButtonEnabled(true);
|
||||
form.addRow(new QLabel("Group Base Label:"), lineEdit);
|
||||
static const QRegularExpression re_validChars("[_A-Za-z0-9]*");
|
||||
QRegularExpressionValidator *validator = new QRegularExpressionValidator(re_validChars);
|
||||
lineEdit->setValidator(validator);
|
||||
lineEdit->setValidator(new IdentifierValidator(lineEdit));
|
||||
connect(lineEdit, &QLineEdit::textChanged, [this, &lineEdit, &buttonBox](QString text){
|
||||
if (this->project->encounterGroupLabels.contains(text)) {
|
||||
lineEdit->setStyleSheet("QLineEdit { background-color: rgba(255, 0, 0, 25%) }");
|
||||
|
|
@ -312,7 +311,7 @@ void Editor::addNewWildMonGroup(QWidget *window) {
|
|||
}
|
||||
});
|
||||
// Give a default value to the label.
|
||||
lineEdit->setText(QString("g%1%2").arg(map->name).arg(stack->count()));
|
||||
lineEdit->setText(QString("g%1%2").arg(map->name()).arg(stack->count()));
|
||||
|
||||
// Fields [x] copy from existing
|
||||
QLabel *fieldsLabel = new QLabel("Fields:");
|
||||
|
|
@ -415,9 +414,9 @@ void Editor::deleteWildMonGroup() {
|
|||
msgBox.exec();
|
||||
|
||||
if (msgBox.clickedButton() == deleteButton) {
|
||||
auto it = project->wildMonData.find(map->constantName);
|
||||
auto it = project->wildMonData.find(map->constantName());
|
||||
if (it == project->wildMonData.end()) {
|
||||
logError(QString("Failed to find data for map %1. Unable to delete").arg(map->constantName));
|
||||
logError(QString("Failed to find data for map %1. Unable to delete").arg(map->constantName()));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -698,7 +697,7 @@ void Editor::saveEncounterTabData() {
|
|||
|
||||
if (!stack->count()) return;
|
||||
|
||||
tsl::ordered_map<QString, WildPokemonHeader> &encounterMap = project->wildMonData[map->constantName];
|
||||
tsl::ordered_map<QString, WildPokemonHeader> &encounterMap = project->wildMonData[map->constantName()];
|
||||
|
||||
for (int groupIndex = 0; groupIndex < stack->count(); groupIndex++) {
|
||||
MonTabWidget *tabWidget = static_cast<MonTabWidget *>(stack->widget(groupIndex));
|
||||
|
|
@ -863,13 +862,13 @@ void Editor::addConnection(MapConnection *connection) {
|
|||
// It's possible this is a Dive/Emerge connection, but that's ok (no selection will occur).
|
||||
connection_to_select = connection;
|
||||
|
||||
this->map->editHistory.push(new MapConnectionAdd(this->map, connection));
|
||||
this->map->commit(new MapConnectionAdd(this->map, connection));
|
||||
}
|
||||
|
||||
void Editor::removeConnection(MapConnection *connection) {
|
||||
if (!connection)
|
||||
return;
|
||||
this->map->editHistory.push(new MapConnectionRemove(this->map, connection));
|
||||
this->map->commit(new MapConnectionRemove(this->map, connection));
|
||||
}
|
||||
|
||||
void Editor::removeConnectionPixmap(MapConnection *connection) {
|
||||
|
|
@ -986,7 +985,7 @@ void Editor::setDivingMapName(QString mapName, QString direction) {
|
|||
if (mapName.isEmpty()) {
|
||||
removeConnection(connection);
|
||||
} else {
|
||||
map->editHistory.push(new MapConnectionChangeMap(connection, mapName));
|
||||
map->commit(new MapConnectionChangeMap(connection, mapName));
|
||||
}
|
||||
} else if (!mapName.isEmpty()) {
|
||||
// Create new connection
|
||||
|
|
@ -1167,7 +1166,7 @@ void Editor::setCursorRectVisible(bool visible) {
|
|||
void Editor::onHoveredMapMetatileChanged(const QPoint &pos) {
|
||||
int x = pos.x();
|
||||
int y = pos.y();
|
||||
if (!layout->isWithinBounds(x, y))
|
||||
if (!layout || !layout->isWithinBounds(x, y))
|
||||
return;
|
||||
|
||||
this->updateCursorRectPos(x, y);
|
||||
|
|
@ -1199,7 +1198,7 @@ void Editor::onHoveredMapMetatileCleared() {
|
|||
}
|
||||
|
||||
void Editor::onHoveredMapMovementPermissionChanged(int x, int y) {
|
||||
if (!layout->isWithinBounds(x, y))
|
||||
if (!layout || !layout->isWithinBounds(x, y))
|
||||
return;
|
||||
|
||||
this->updateCursorRectPos(x, y);
|
||||
|
|
@ -1243,10 +1242,10 @@ QString Editor::getMovementPermissionText(uint16_t collision, uint16_t elevation
|
|||
void Editor::unsetMap() {
|
||||
// disconnect previous map's signals so they are not firing
|
||||
// multiple times if set again in the future
|
||||
if (map) {
|
||||
map->pruneEditHistory();
|
||||
map->disconnect(this);
|
||||
for (auto connection : map->getConnections())
|
||||
if (this->map) {
|
||||
this->map->pruneEditHistory();
|
||||
this->map->disconnect(this);
|
||||
for (const auto &connection : this->map->getConnections())
|
||||
disconnectMapConnection(connection);
|
||||
}
|
||||
clearMapConnections();
|
||||
|
|
@ -1259,19 +1258,18 @@ bool Editor::setMap(QString map_name) {
|
|||
return false;
|
||||
}
|
||||
|
||||
unsetMap();
|
||||
|
||||
Map *loadedMap = project->loadMap(map_name);
|
||||
if (!loadedMap) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unsetMap();
|
||||
this->map = loadedMap;
|
||||
|
||||
setLayout(map->layout->id);
|
||||
setLayout(map->layout()->id);
|
||||
|
||||
editGroup.addStack(&map->editHistory);
|
||||
editGroup.setActiveStack(&map->editHistory);
|
||||
editGroup.addStack(map->editHistory());
|
||||
editGroup.setActiveStack(map->editHistory());
|
||||
|
||||
selected_events->clear();
|
||||
if (!displayMap()) {
|
||||
|
|
@ -1292,13 +1290,17 @@ bool Editor::setLayout(QString layoutId) {
|
|||
return false;
|
||||
}
|
||||
|
||||
this->layout = this->project->loadLayout(layoutId);
|
||||
Layout *loadedLayout = this->project->loadLayout(layoutId);
|
||||
if (!loadedLayout) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this->layout = loadedLayout;
|
||||
if (!displayLayout()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
editGroup.addStack(&layout->editHistory);
|
||||
editGroup.addStack(&this->layout->editHistory);
|
||||
|
||||
map_ruler->setMapDimensions(QSize(this->layout->getWidth(), this->layout->getHeight()));
|
||||
connect(this->layout, &Layout::layoutDimensionsChanged, map_ruler, &MapRuler::setMapDimensions);
|
||||
|
|
@ -1469,7 +1471,7 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *i
|
|||
}
|
||||
selection_origin = QPoint(pos.x(), pos.y());
|
||||
|
||||
map->editHistory.push(new EventShift(selectedEvents, xDelta, yDelta, actionId));
|
||||
map->commit(new EventShift(selectedEvents, xDelta, yDelta, actionId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1784,8 +1786,7 @@ void Editor::displayMapEvents() {
|
|||
events_group = new QGraphicsItemGroup;
|
||||
scene->addItem(events_group);
|
||||
|
||||
QList<Event *> events = map->getAllEvents();
|
||||
for (Event *event : events) {
|
||||
for (const auto &event : map->getEvents()) {
|
||||
project->setEventPixmap(event);
|
||||
addMapEvent(event);
|
||||
}
|
||||
|
|
@ -2032,14 +2033,14 @@ void Editor::updateBorderVisibility() {
|
|||
// When connecting a map to itself we don't bother to re-render the map connections in real-time,
|
||||
// i.e. if the user paints a new metatile on the map this isn't immediately reflected in the connection.
|
||||
// We're rendering them now, so we take the opportunity to do a full re-render for self-connections.
|
||||
bool fullRender = (this->map && item->connection && this->map->name == item->connection->targetMapName());
|
||||
bool fullRender = (this->map && item->connection && this->map->name() == item->connection->targetMapName());
|
||||
item->render(fullRender);
|
||||
}
|
||||
}
|
||||
|
||||
void Editor::updateCustomMapHeaderValues(QTableWidget *table)
|
||||
{
|
||||
map->customHeaders = CustomAttributesTable::getAttributes(table);
|
||||
map->setCustomAttributes(CustomAttributesTable::getAttributes(table));
|
||||
map->modify();
|
||||
}
|
||||
|
||||
|
|
@ -2080,13 +2081,13 @@ void Editor::redrawObject(DraggablePixmapItem *item) {
|
|||
void Editor::updateWarpEventWarning(Event *event) {
|
||||
if (porymapConfig.warpBehaviorWarningDisabled)
|
||||
return;
|
||||
if (!project || !map || !map->layout || !event || event->getEventType() != Event::Type::Warp)
|
||||
if (!project || !map || !map->layout() || !event || event->getEventType() != Event::Type::Warp)
|
||||
return;
|
||||
Block block;
|
||||
Metatile * metatile = nullptr;
|
||||
WarpEvent * warpEvent = static_cast<WarpEvent*>(event);
|
||||
if (map->layout->getBlock(warpEvent->getX(), warpEvent->getY(), &block)) {
|
||||
metatile = Tileset::getMetatile(block.metatileId(), map->layout->tileset_primary, map->layout->tileset_secondary);
|
||||
if (map->layout()->getBlock(warpEvent->getX(), warpEvent->getY(), &block)) {
|
||||
metatile = Tileset::getMetatile(block.metatileId(), map->layout()->tileset_primary, map->layout()->tileset_secondary);
|
||||
}
|
||||
// metatile may be null if the warp is in the map border. Display the warning in this case
|
||||
bool validWarpBehavior = metatile && projectConfig.warpBehaviors.contains(metatile->behavior());
|
||||
|
|
@ -2144,10 +2145,7 @@ void Editor::selectMapEvent(DraggablePixmapItem *object, bool toggle) {
|
|||
void Editor::selectedEventIndexChanged(int index, Event::Group eventGroup) {
|
||||
int event_offs = Event::getIndexOffset(eventGroup);
|
||||
index = index - event_offs;
|
||||
Event *event = nullptr;
|
||||
if (index < this->map->events.value(eventGroup).length()) {
|
||||
event = this->map->events.value(eventGroup).at(index);
|
||||
}
|
||||
Event *event = this->map->getEvent(eventGroup, index);
|
||||
DraggablePixmapItem *selectedEvent = nullptr;
|
||||
for (QGraphicsItem *child : this->events_group->childItems()) {
|
||||
DraggablePixmapItem *item = static_cast<DraggablePixmapItem *>(child);
|
||||
|
|
@ -2189,7 +2187,7 @@ void Editor::duplicateSelectedEvents() {
|
|||
duplicate->setY(duplicate->getY() + 1);
|
||||
selectedEvents.append(duplicate);
|
||||
}
|
||||
map->editHistory.push(new EventDuplicate(this, map, selectedEvents));
|
||||
map->commit(new EventDuplicate(this, map, selectedEvents));
|
||||
}
|
||||
|
||||
DraggablePixmapItem *Editor::addNewEvent(Event::Type type) {
|
||||
|
|
@ -2209,7 +2207,7 @@ DraggablePixmapItem *Editor::addNewEvent(Event::Type type) {
|
|||
((HealLocationEvent *)event)->setIndex(project->healLocations.length());
|
||||
}
|
||||
|
||||
map->editHistory.push(new EventCreate(this, map, event));
|
||||
map->commit(new EventCreate(this, map, event));
|
||||
return event->getPixmapItem();
|
||||
}
|
||||
|
||||
|
|
@ -2217,7 +2215,7 @@ DraggablePixmapItem *Editor::addNewEvent(Event::Type type) {
|
|||
bool Editor::eventLimitReached(Event::Type event_type) {
|
||||
if (project && map) {
|
||||
if (Event::typeToGroup(event_type) == Event::Group::Object)
|
||||
return map->events.value(Event::Group::Object).length() >= project->getMaxObjectEvents();
|
||||
return map->getNumEvents(Event::Group::Object) >= project->getMaxObjectEvents();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -2246,14 +2244,12 @@ void Editor::deleteSelectedEvents() {
|
|||
// If deleting multiple events, just let editor work out next selected.
|
||||
if (numDeleted == 1) {
|
||||
Event::Group event_group = selectedEvents[0]->getEventGroup();
|
||||
int index = this->map->events.value(event_group).indexOf(selectedEvents[0]);
|
||||
if (index != this->map->events.value(event_group).size() - 1)
|
||||
int index = this->map->getIndexOfEvent(selectedEvents[0]);
|
||||
if (index != this->map->getNumEvents(event_group) - 1)
|
||||
index++;
|
||||
else
|
||||
index--;
|
||||
Event *event = nullptr;
|
||||
if (index >= 0)
|
||||
event = this->map->events.value(event_group).at(index);
|
||||
Event *event = this->map->getEvent(event_group, index);
|
||||
for (QGraphicsItem *child : this->events_group->childItems()) {
|
||||
DraggablePixmapItem *event_item = static_cast<DraggablePixmapItem *>(child);
|
||||
if (event_item->event == event) {
|
||||
|
|
@ -2262,7 +2258,7 @@ void Editor::deleteSelectedEvents() {
|
|||
}
|
||||
}
|
||||
}
|
||||
this->map->editHistory.push(new EventDelete(this, this->map, selectedEvents, nextSelectedEvent ? nextSelectedEvent->event : nullptr));
|
||||
this->map->commit(new EventDelete(this, this->map, selectedEvents, nextSelectedEvent ? nextSelectedEvent->event : nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
143
src/lib/collapsiblesection.cpp
Normal file
143
src/lib/collapsiblesection.cpp
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
Elypson/qt-collapsible-section
|
||||
(c) 2016 Michael A. Voelkel - michael.alexander.voelkel@gmail.com
|
||||
|
||||
This file is part of Elypson/qt-collapsible section.
|
||||
|
||||
Elypson/qt-collapsible-section is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Elypson/qt-collapsible-section is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Elypson/qt-collapsible-section. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
PORYMAP NOTE: Modified to support having the section expanded by default, to stop the contents
|
||||
squashing during the collapse animation, and to add some guard rails against crashes.
|
||||
*/
|
||||
|
||||
#include "collapsiblesection.h"
|
||||
CollapsibleSection::CollapsibleSection(const QString& title, const bool expanded, const int animationDuration, QWidget* parent)
|
||||
: QWidget(parent), animationDuration(animationDuration), expanded(expanded)
|
||||
{
|
||||
toggleButton = new QToolButton(this);
|
||||
headerLine = new QFrame(this);
|
||||
toggleAnimation = new QParallelAnimationGroup(this);
|
||||
contentArea = new QScrollArea(this);
|
||||
mainLayout = new QGridLayout(this);
|
||||
|
||||
toggleButton->setStyleSheet("QToolButton {border: none;}");
|
||||
toggleButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
||||
toggleButton->setText(title);
|
||||
toggleButton->setCheckable(true);
|
||||
updateToggleButton();
|
||||
|
||||
headerLine->setFrameShape(QFrame::HLine);
|
||||
headerLine->setFrameShadow(QFrame::Sunken);
|
||||
headerLine->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
|
||||
|
||||
contentArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
contentArea->setMaximumHeight(0);
|
||||
contentArea->setMinimumHeight(0);
|
||||
|
||||
sectionAnimations.insert(new QPropertyAnimation(this, "minimumHeight"));
|
||||
sectionAnimations.insert(new QPropertyAnimation(this, "maximumHeight"));
|
||||
for (const auto &anim : sectionAnimations)
|
||||
toggleAnimation->addAnimation(anim);
|
||||
contentAnimation = new QPropertyAnimation(contentArea, "maximumHeight");
|
||||
toggleAnimation->addAnimation(contentAnimation);
|
||||
|
||||
mainLayout->setVerticalSpacing(0);
|
||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
int row = 0;
|
||||
mainLayout->addWidget(toggleButton, row, 0, 1, 1, Qt::AlignLeft);
|
||||
mainLayout->addWidget(headerLine, row++, 2, 1, 1);
|
||||
mainLayout->addWidget(contentArea, row, 0, 1, 3);
|
||||
setLayout(mainLayout);
|
||||
|
||||
connect(toggleButton, &QToolButton::toggled, this, &CollapsibleSection::toggle);
|
||||
}
|
||||
|
||||
void CollapsibleSection::updateToggleButton()
|
||||
{
|
||||
toggleButton->setChecked(this->expanded);
|
||||
toggleButton->setArrowType(this->expanded ? Qt::ArrowType::DownArrow : Qt::ArrowType::RightArrow);
|
||||
}
|
||||
|
||||
void CollapsibleSection::toggle(bool expand)
|
||||
{
|
||||
if (toggleAnimation->state() != QAbstractAnimation::Stopped)
|
||||
return;
|
||||
if (this->expanded == expand)
|
||||
return;
|
||||
this->expanded = expand;
|
||||
|
||||
updateToggleButton();
|
||||
|
||||
if (expand) {
|
||||
// Opening animation. Set the contents to their maximum size immediately,
|
||||
// and they will be revealed slowly by the section animation.
|
||||
int contentHeight = getContentHeight();
|
||||
contentArea->setMinimumHeight(contentHeight);
|
||||
contentArea->setMaximumHeight(contentHeight);
|
||||
toggleAnimation->setDirection(QAbstractAnimation::Forward);
|
||||
} else {
|
||||
// Closing animation. Keep the contents at their current size, allowing
|
||||
// them to be hidden slowly by the section animation, then change their size
|
||||
// once the animation is complete so they aren't visible just below the title.
|
||||
auto ctx = new QObject();
|
||||
connect(toggleAnimation, &QAbstractAnimation::finished, ctx, [this, ctx]() {
|
||||
// This is a single-shot connection. Qt6 has built-in support for this kind of thing.
|
||||
contentArea->setMinimumHeight(0);
|
||||
contentArea->setMaximumHeight(0);
|
||||
ctx->deleteLater();
|
||||
});
|
||||
toggleAnimation->setDirection(QAbstractAnimation::Backward);
|
||||
}
|
||||
toggleAnimation->start();
|
||||
}
|
||||
|
||||
void CollapsibleSection::setContentLayout(QLayout* contentLayout)
|
||||
{
|
||||
if (contentArea->layout() == contentLayout)
|
||||
return;
|
||||
delete contentArea->layout();
|
||||
contentArea->setLayout(contentLayout);
|
||||
collapsedHeight = sizeHint().height() - contentArea->maximumHeight();
|
||||
|
||||
int contentHeight = this->expanded ? getContentHeight() : 0;
|
||||
contentArea->setMinimumHeight(contentHeight);
|
||||
contentArea->setMaximumHeight(contentHeight);
|
||||
|
||||
updateAnimationTargets();
|
||||
}
|
||||
|
||||
void CollapsibleSection::setTitle(const QString &title)
|
||||
{
|
||||
toggleButton->setText(title);
|
||||
}
|
||||
|
||||
int CollapsibleSection::getContentHeight() const
|
||||
{
|
||||
return contentArea->layout() ? contentArea->layout()->sizeHint().height() : 0;
|
||||
}
|
||||
|
||||
void CollapsibleSection::updateAnimationTargets()
|
||||
{
|
||||
const int contentHeight = getContentHeight();
|
||||
for (auto anim : sectionAnimations) {
|
||||
anim->setDuration(animationDuration);
|
||||
anim->setStartValue(collapsedHeight);
|
||||
anim->setEndValue(collapsedHeight + contentHeight);
|
||||
}
|
||||
contentAnimation->setDuration(animationDuration);
|
||||
contentAnimation->setStartValue(0);
|
||||
contentAnimation->setEndValue(contentHeight);
|
||||
}
|
||||
|
|
@ -337,9 +337,9 @@ namespace fex
|
|||
return DefineStatement(identifer, value);
|
||||
}
|
||||
|
||||
std::map<std::string, int> Parser::ReadDefines(const QString &filename, std::vector<std::string> matching)
|
||||
tsl::ordered_map<std::string, int> Parser::ReadDefines(const QString &filename, std::vector<std::string> matching)
|
||||
{
|
||||
std::map<std::string, int> out;
|
||||
tsl::ordered_map<std::string, int> out;
|
||||
|
||||
Lexer lexer;
|
||||
auto tokens = lexer.LexFile(filename);
|
||||
|
|
@ -488,12 +488,12 @@ namespace fex
|
|||
return items;
|
||||
}
|
||||
|
||||
std::map<std::string, ArrayValue> Parser::ParseTopLevelObjects(std::vector<Token> tokens)
|
||||
tsl::ordered_map<std::string, ArrayValue> Parser::ParseTopLevelObjects(std::vector<Token> tokens)
|
||||
{
|
||||
index_ = 0;
|
||||
tokens_ = std::move(tokens);
|
||||
|
||||
std::map<std::string, ArrayValue> items;
|
||||
tsl::ordered_map<std::string, ArrayValue> items;
|
||||
|
||||
while (index_ < tokens_.size())
|
||||
{
|
||||
|
|
|
|||
50
src/lib/fex/parser_util.cpp
Normal file
50
src/lib/fex/parser_util.cpp
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#include "lib/fex/parser_util.h"
|
||||
|
||||
#include <QMap>
|
||||
|
||||
#include "lib/fex/parser.h"
|
||||
|
||||
ParserUtil::ParserUtil(QString root): root_(root) {}
|
||||
|
||||
QStringList ParserUtil::ReadDefines(QString filename, QString prefix)
|
||||
{
|
||||
if (filename.isEmpty()) {
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
QString filepath = root_ + "/" + filename;
|
||||
|
||||
fex::Parser parser;
|
||||
|
||||
std::vector<std::string> match_list = { prefix.toStdString() + ".*" };
|
||||
tsl::ordered_map<std::string, int> defines = parser.ReadDefines(filepath.toStdString(), match_list);
|
||||
|
||||
QStringList out;
|
||||
for(auto const& define : defines) {
|
||||
out.append(QString::fromStdString(define.first));
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
QStringList ParserUtil::ReadDefinesValueSort(QString filename, QString prefix)
|
||||
{
|
||||
|
||||
if (filename.isEmpty()) {
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
QString filepath = root_ + "/" + filename;
|
||||
|
||||
fex::Parser parser;
|
||||
|
||||
std::vector<std::string> match_list = { prefix.toStdString() + ".*" };
|
||||
tsl::ordered_map<std::string, int> defines = parser.ReadDefines(filepath.toStdString(), match_list);
|
||||
|
||||
QMultiMap<int, QString> defines_keyed_by_value;
|
||||
for (const auto& pair : defines) {
|
||||
defines_keyed_by_value.insert(pair.second, QString::fromStdString(pair.first));
|
||||
}
|
||||
|
||||
return defines_keyed_by_value.values();
|
||||
}
|
||||
1134
src/mainwindow.cpp
1134
src/mainwindow.cpp
File diff suppressed because it is too large
Load Diff
1282
src/project.cpp
1282
src/project.cpp
File diff suppressed because it is too large
Load Diff
|
|
@ -337,7 +337,7 @@ void MainWindow::refreshAfterPaletteChange(Tileset *tileset) {
|
|||
this->editor->map_item->draw(true);
|
||||
this->editor->updateMapBorder();
|
||||
this->editor->updateMapConnections();
|
||||
this->editor->project->saveTilesetPalettes(tileset);
|
||||
tileset->savePalettes();
|
||||
}
|
||||
|
||||
void MainWindow::setTilesetPalette(Tileset *tileset, int paletteIndex, QList<QList<int>> colors) {
|
||||
|
|
@ -576,14 +576,14 @@ void MainWindow::setSecondaryTileset(QString tileset) {
|
|||
|
||||
void MainWindow::saveMetatilesByMetatileId(int metatileId) {
|
||||
Tileset * tileset = Tileset::getMetatileTileset(metatileId, this->editor->layout->tileset_primary, this->editor->layout->tileset_secondary);
|
||||
if (this->editor->project && tileset)
|
||||
this->editor->project->saveTilesetMetatiles(tileset);
|
||||
if (tileset)
|
||||
tileset->saveMetatiles();
|
||||
}
|
||||
|
||||
void MainWindow::saveMetatileAttributesByMetatileId(int metatileId) {
|
||||
Tileset * tileset = Tileset::getMetatileTileset(metatileId, this->editor->layout->tileset_primary, this->editor->layout->tileset_secondary);
|
||||
if (this->editor->project && tileset)
|
||||
this->editor->project->saveTilesetMetatileAttributes(tileset);
|
||||
if (tileset)
|
||||
tileset->saveMetatileAttributes();
|
||||
|
||||
// If the tileset editor is open it needs to be refreshed with the new changes.
|
||||
// Rather than do a full refresh (which is costly) we tell the editor it will need
|
||||
|
|
@ -814,156 +814,132 @@ QJSValue MainWindow::getTilePixels(int tileId) {
|
|||
QString MainWindow::getSong() {
|
||||
if (!this->editor || !this->editor->map)
|
||||
return QString();
|
||||
return this->editor->map->song;
|
||||
return this->editor->map->header()->song();
|
||||
}
|
||||
|
||||
void MainWindow::setSong(QString song) {
|
||||
if (!this->ui || !this->editor || !this->editor->project)
|
||||
if (!this->editor || !this->editor->map || !this->editor->project)
|
||||
return;
|
||||
if (!this->editor->project->songNames.contains(song)) {
|
||||
logError(QString("Unknown song '%1'").arg(song));
|
||||
return;
|
||||
}
|
||||
this->ui->comboBox_Song->setCurrentText(song);
|
||||
this->editor->map->header()->setSong(song);
|
||||
}
|
||||
|
||||
QString MainWindow::getLocation() {
|
||||
if (!this->editor || !this->editor->map)
|
||||
return QString();
|
||||
return this->editor->map->location;
|
||||
return this->editor->map->header()->location();
|
||||
}
|
||||
|
||||
void MainWindow::setLocation(QString location) {
|
||||
if (!this->ui || !this->editor || !this->editor->project)
|
||||
if (!this->editor || !this->editor->map || !this->editor->project)
|
||||
return;
|
||||
if (!this->editor->project->mapSectionIdNames.contains(location)) {
|
||||
logError(QString("Unknown location '%1'").arg(location));
|
||||
return;
|
||||
}
|
||||
this->ui->comboBox_Location->setCurrentText(location);
|
||||
this->editor->map->header()->setLocation(location);
|
||||
}
|
||||
|
||||
bool MainWindow::getRequiresFlash() {
|
||||
if (!this->editor || !this->editor->map)
|
||||
return false;
|
||||
return this->editor->map->requiresFlash;
|
||||
return this->editor->map->header()->requiresFlash();
|
||||
}
|
||||
|
||||
void MainWindow::setRequiresFlash(bool require) {
|
||||
if (!this->ui)
|
||||
if (!this->editor || !this->editor->map)
|
||||
return;
|
||||
this->ui->checkBox_Visibility->setChecked(require);
|
||||
this->editor->map->header()->setRequiresFlash(require);
|
||||
}
|
||||
|
||||
QString MainWindow::getWeather() {
|
||||
if (!this->editor || !this->editor->map)
|
||||
return QString();
|
||||
return this->editor->map->weather;
|
||||
return this->editor->map->header()->weather();
|
||||
}
|
||||
|
||||
void MainWindow::setWeather(QString weather) {
|
||||
if (!this->ui || !this->editor || !this->editor->project)
|
||||
if (!this->editor || !this->editor->map || !this->editor->project)
|
||||
return;
|
||||
if (!this->editor->project->weatherNames.contains(weather)) {
|
||||
logError(QString("Unknown weather '%1'").arg(weather));
|
||||
return;
|
||||
}
|
||||
this->ui->comboBox_Weather->setCurrentText(weather);
|
||||
this->editor->map->header()->setWeather(weather);
|
||||
}
|
||||
|
||||
QString MainWindow::getType() {
|
||||
if (!this->editor || !this->editor->map)
|
||||
return QString();
|
||||
return this->editor->map->type;
|
||||
return this->editor->map->header()->type();
|
||||
}
|
||||
|
||||
void MainWindow::setType(QString type) {
|
||||
if (!this->ui || !this->editor || !this->editor->project)
|
||||
if (!this->editor || !this->editor->map || !this->editor->project)
|
||||
return;
|
||||
if (!this->editor->project->mapTypes.contains(type)) {
|
||||
logError(QString("Unknown map type '%1'").arg(type));
|
||||
return;
|
||||
}
|
||||
this->ui->comboBox_Type->setCurrentText(type);
|
||||
this->editor->map->header()->setType(type);
|
||||
}
|
||||
|
||||
QString MainWindow::getBattleScene() {
|
||||
if (!this->editor || !this->editor->map)
|
||||
return QString();
|
||||
return this->editor->map->battle_scene;
|
||||
return this->editor->map->header()->battleScene();
|
||||
}
|
||||
|
||||
void MainWindow::setBattleScene(QString battleScene) {
|
||||
if (!this->ui || !this->editor || !this->editor->project)
|
||||
if (!this->editor || !this->editor->map || !this->editor->project)
|
||||
return;
|
||||
if (!this->editor->project->mapBattleScenes.contains(battleScene)) {
|
||||
logError(QString("Unknown battle scene '%1'").arg(battleScene));
|
||||
return;
|
||||
}
|
||||
this->ui->comboBox_BattleScene->setCurrentText(battleScene);
|
||||
this->editor->map->header()->setBattleScene(battleScene);
|
||||
}
|
||||
|
||||
bool MainWindow::getShowLocationName() {
|
||||
if (!this->editor || !this->editor->map)
|
||||
return false;
|
||||
return this->editor->map->show_location;
|
||||
return this->editor->map->header()->showsLocationName();
|
||||
}
|
||||
|
||||
void MainWindow::setShowLocationName(bool show) {
|
||||
if (!this->ui)
|
||||
if (!this->editor || !this->editor->map)
|
||||
return;
|
||||
this->ui->checkBox_ShowLocation->setChecked(show);
|
||||
this->editor->map->header()->setShowsLocationName(show);
|
||||
}
|
||||
|
||||
bool MainWindow::getAllowRunning() {
|
||||
if (!this->editor || !this->editor->map)
|
||||
return false;
|
||||
return this->editor->map->allowRunning;
|
||||
return this->editor->map->header()->allowsRunning();
|
||||
}
|
||||
|
||||
void MainWindow::setAllowRunning(bool allow) {
|
||||
if (!this->ui)
|
||||
if (!this->editor || !this->editor->map)
|
||||
return;
|
||||
this->ui->checkBox_AllowRunning->setChecked(allow);
|
||||
this->editor->map->header()->setAllowsRunning(allow);
|
||||
}
|
||||
|
||||
bool MainWindow::getAllowBiking() {
|
||||
if (!this->editor || !this->editor->map)
|
||||
return false;
|
||||
return this->editor->map->allowBiking;
|
||||
return this->editor->map->header()->allowsBiking();
|
||||
}
|
||||
|
||||
void MainWindow::setAllowBiking(bool allow) {
|
||||
if (!this->ui)
|
||||
if (!this->editor || !this->editor->map)
|
||||
return;
|
||||
this->ui->checkBox_AllowBiking->setChecked(allow);
|
||||
this->editor->map->header()->setAllowsBiking(allow);
|
||||
}
|
||||
|
||||
bool MainWindow::getAllowEscaping() {
|
||||
if (!this->editor || !this->editor->map)
|
||||
return false;
|
||||
return this->editor->map->allowEscaping;
|
||||
return this->editor->map->header()->allowsEscaping();
|
||||
}
|
||||
|
||||
void MainWindow::setAllowEscaping(bool allow) {
|
||||
if (!this->ui)
|
||||
if (!this->editor || !this->editor->map)
|
||||
return;
|
||||
this->ui->checkBox_AllowEscaping->setChecked(allow);
|
||||
this->editor->map->header()->setAllowsEscaping(allow);
|
||||
}
|
||||
|
||||
int MainWindow::getFloorNumber() {
|
||||
if (!this->editor || !this->editor->map)
|
||||
return 0;
|
||||
return this->editor->map->floorNumber;
|
||||
return this->editor->map->header()->floorNumber();
|
||||
}
|
||||
|
||||
void MainWindow::setFloorNumber(int floorNumber) {
|
||||
if (!this->ui)
|
||||
if (!this->editor || !this->editor->map)
|
||||
return;
|
||||
if (floorNumber < -128 || floorNumber > 127) {
|
||||
logError(QString("Invalid floor number '%1'").arg(floorNumber));
|
||||
return;
|
||||
}
|
||||
this->ui->spinBox_FloorNumber->setValue(floorNumber);
|
||||
this->editor->map->header()->setFloorNumber(floorNumber);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,10 @@
|
|||
#include "colorinputwidget.h"
|
||||
#include "ui_colorinputwidget.h"
|
||||
#include "colorpicker.h"
|
||||
#include "validator.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
class HexCodeValidator : public QValidator {
|
||||
virtual QValidator::State validate(QString &input, int &) const override {
|
||||
input = input.toUpper();
|
||||
return QValidator::Acceptable;
|
||||
}
|
||||
};
|
||||
|
||||
static inline int rgb5(int rgb) { return round(static_cast<double>(rgb * 31) / 255.0); }
|
||||
static inline int rgb8(int rgb) { return round(rgb * 255. / 31.); }
|
||||
static inline int gbaRed(int rgb) { return rgb & 0x1f; }
|
||||
|
|
@ -43,8 +37,8 @@ void ColorInputWidget::init() {
|
|||
connect(ui->spinBox_Green, QOverload<int>::of(&QSpinBox::valueChanged), this, &ColorInputWidget::setRgbFromSpinners);
|
||||
connect(ui->spinBox_Blue, QOverload<int>::of(&QSpinBox::valueChanged), this, &ColorInputWidget::setRgbFromSpinners);
|
||||
|
||||
static const HexCodeValidator hexValidator;
|
||||
ui->lineEdit_Hex->setValidator(&hexValidator);
|
||||
static const UppercaseValidator uppercaseValidator;
|
||||
ui->lineEdit_Hex->setValidator(&uppercaseValidator);
|
||||
connect(ui->lineEdit_Hex, &QLineEdit::textEdited, this, &ColorInputWidget::setRgbFromHexString);
|
||||
|
||||
// We have separate signals for when color input editing finishes.
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ QVariant ConnectionPixmapItem::itemChange(GraphicsItemChange change, const QVari
|
|||
|
||||
// This is convoluted because of how our edit history works; this would otherwise just be 'this->connection->setOffset(newOffset);'
|
||||
if (this->connection->parentMap() && newOffset != this->connection->offset())
|
||||
this->connection->parentMap()->editHistory.push(new MapConnectionMove(this->connection, newOffset, this->actionId));
|
||||
this->connection->parentMap()->commit(new MapConnectionMove(this->connection, newOffset, this->actionId));
|
||||
|
||||
return QPointF(x, y);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,24 +79,24 @@ void ConnectionsListItem::mousePressEvent(QMouseEvent *) {
|
|||
void ConnectionsListItem::on_comboBox_Direction_currentTextChanged(QString direction) {
|
||||
this->setSelected(true);
|
||||
if (this->map)
|
||||
this->map->editHistory.push(new MapConnectionChangeDirection(this->connection, direction));
|
||||
this->map->commit(new MapConnectionChangeDirection(this->connection, direction));
|
||||
}
|
||||
|
||||
void ConnectionsListItem::on_comboBox_Map_currentTextChanged(QString mapName) {
|
||||
this->setSelected(true);
|
||||
if (this->map && ui->comboBox_Map->findText(mapName) >= 0)
|
||||
this->map->editHistory.push(new MapConnectionChangeMap(this->connection, mapName));
|
||||
this->map->commit(new MapConnectionChangeMap(this->connection, mapName));
|
||||
}
|
||||
|
||||
void ConnectionsListItem::on_spinBox_Offset_valueChanged(int offset) {
|
||||
this->setSelected(true);
|
||||
if (this->map)
|
||||
this->map->editHistory.push(new MapConnectionMove(this->connection, offset, this->actionId));
|
||||
this->map->commit(new MapConnectionMove(this->connection, offset, this->actionId));
|
||||
}
|
||||
|
||||
void ConnectionsListItem::on_button_Delete_clicked() {
|
||||
if (this->map)
|
||||
this->map->editHistory.push(new MapConnectionRemove(this->map, this->connection));
|
||||
this->map->commit(new MapConnectionRemove(this->map, this->connection));
|
||||
}
|
||||
|
||||
void ConnectionsListItem::on_button_OpenMap_clicked() {
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ void CustomScriptsEditor::displayNewScript(QString filepath) {
|
|||
// Verify new script path is not already in list
|
||||
for (int i = 0; i < ui->list->count(); i++) {
|
||||
if (filepath == this->getScriptFilepath(ui->list->item(i), false)) {
|
||||
QMessageBox::information(this, "", QString("The script '%1' is already loaded").arg(filepath));
|
||||
QMessageBox::information(this, QApplication::applicationName(), QString("The script '%1' is already loaded").arg(filepath));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -219,7 +219,7 @@ void CustomScriptsEditor::openScript(QListWidgetItem * item) {
|
|||
const QString path = this->getScriptFilepath(item);
|
||||
QFileInfo fileInfo(path);
|
||||
if (!fileInfo.exists() || !fileInfo.isFile()){
|
||||
QMessageBox::warning(this, "", QString("Failed to open script '%1'").arg(path));
|
||||
QMessageBox::warning(this, QApplication::applicationName(), QString("Failed to open script '%1'").arg(path));
|
||||
return;
|
||||
}
|
||||
Editor::openInTextEditor(path);
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ void DraggablePixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *mouse) {
|
|||
} else {
|
||||
selectedEvents.append(this->event);
|
||||
}
|
||||
editor->map->editHistory.push(new EventMove(selectedEvents, moveDistance.x(), moveDistance.y(), currentActionId));
|
||||
editor->map->commit(new EventMove(selectedEvents, moveDistance.x(), moveDistance.y(), currentActionId));
|
||||
this->releaseSelectionQueued = false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ void EventFrame::connectSignals(MainWindow *) {
|
|||
connect(this->spinner_x, QOverload<int>::of(&QSpinBox::valueChanged), [this](int value) {
|
||||
int delta = value - event->getX();
|
||||
if (delta) {
|
||||
this->event->getMap()->editHistory.push(new EventMove(QList<Event *>() << this->event, delta, 0, this->spinner_x->getActionId()));
|
||||
this->event->getMap()->commit(new EventMove(QList<Event *>() << this->event, delta, 0, this->spinner_x->getActionId()));
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ void EventFrame::connectSignals(MainWindow *) {
|
|||
connect(this->spinner_y, QOverload<int>::of(&QSpinBox::valueChanged), [this](int value) {
|
||||
int delta = value - event->getY();
|
||||
if (delta) {
|
||||
this->event->getMap()->editHistory.push(new EventMove(QList<Event *>() << this->event, 0, delta, this->spinner_y->getActionId()));
|
||||
this->event->getMap()->commit(new EventMove(QList<Event *>() << this->event, 0, delta, this->spinner_y->getActionId()));
|
||||
}
|
||||
});
|
||||
connect(this->event->getPixmapItem(), &DraggablePixmapItem::yChanged, this->spinner_y, &NoScrollSpinBox::setValue);
|
||||
|
|
|
|||
226
src/ui/mapheaderform.cpp
Normal file
226
src/ui/mapheaderform.cpp
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
#include "mapheaderform.h"
|
||||
#include "ui_mapheaderform.h"
|
||||
#include "project.h"
|
||||
|
||||
MapHeaderForm::MapHeaderForm(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, ui(new Ui::MapHeaderForm)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
// This value is an s8 by default, but we don't need to unnecessarily limit users.
|
||||
ui->spinBox_FloorNumber->setMinimum(INT_MIN);
|
||||
ui->spinBox_FloorNumber->setMaximum(INT_MAX);
|
||||
|
||||
// The layout for this UI keeps fields at their size hint, which is a little short for the line edit.
|
||||
ui->lineEdit_LocationName->setMinimumWidth(ui->comboBox_Location->sizeHint().width());
|
||||
|
||||
connect(ui->comboBox_Song, &QComboBox::currentTextChanged, this, &MapHeaderForm::onSongUpdated);
|
||||
connect(ui->comboBox_Location, &QComboBox::currentTextChanged, this, &MapHeaderForm::onLocationChanged);
|
||||
connect(ui->comboBox_Weather, &QComboBox::currentTextChanged, this, &MapHeaderForm::onWeatherChanged);
|
||||
connect(ui->comboBox_Type, &QComboBox::currentTextChanged, this, &MapHeaderForm::onTypeChanged);
|
||||
connect(ui->comboBox_BattleScene, &QComboBox::currentTextChanged, this, &MapHeaderForm::onBattleSceneChanged);
|
||||
|
||||
connect(ui->checkBox_RequiresFlash, &QCheckBox::stateChanged, this, &MapHeaderForm::onRequiresFlashChanged);
|
||||
connect(ui->checkBox_ShowLocationName, &QCheckBox::stateChanged, this, &MapHeaderForm::onShowLocationNameChanged);
|
||||
connect(ui->checkBox_AllowRunning, &QCheckBox::stateChanged, this, &MapHeaderForm::onAllowRunningChanged);
|
||||
connect(ui->checkBox_AllowBiking, &QCheckBox::stateChanged, this, &MapHeaderForm::onAllowBikingChanged);
|
||||
connect(ui->checkBox_AllowEscaping, &QCheckBox::stateChanged, this, &MapHeaderForm::onAllowEscapingChanged);
|
||||
|
||||
connect(ui->spinBox_FloorNumber, QOverload<int>::of(&QSpinBox::valueChanged), this, &MapHeaderForm::onFloorNumberChanged);
|
||||
|
||||
connect(ui->lineEdit_LocationName, &QLineEdit::textChanged, this, &MapHeaderForm::onLocationNameChanged);
|
||||
}
|
||||
|
||||
MapHeaderForm::~MapHeaderForm()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MapHeaderForm::setProject(Project * project, bool allowChanges) {
|
||||
clear();
|
||||
|
||||
if (m_project) {
|
||||
m_project->disconnect(this);
|
||||
}
|
||||
m_project = project;
|
||||
m_allowProjectChanges = allowChanges;
|
||||
|
||||
if (!m_project)
|
||||
return;
|
||||
|
||||
// Populate combo boxes
|
||||
|
||||
const QSignalBlocker b_Song(ui->comboBox_Song);
|
||||
ui->comboBox_Song->clear();
|
||||
ui->comboBox_Song->addItems(m_project->songNames);
|
||||
|
||||
const QSignalBlocker b_Weather(ui->comboBox_Weather);
|
||||
ui->comboBox_Weather->clear();
|
||||
ui->comboBox_Weather->addItems(m_project->weatherNames);
|
||||
|
||||
const QSignalBlocker b_Type(ui->comboBox_Type);
|
||||
ui->comboBox_Type->clear();
|
||||
ui->comboBox_Type->addItems(m_project->mapTypes);
|
||||
|
||||
const QSignalBlocker b_BattleScene(ui->comboBox_BattleScene);
|
||||
ui->comboBox_BattleScene->clear();
|
||||
ui->comboBox_BattleScene->addItems(m_project->mapBattleScenes);
|
||||
|
||||
const QSignalBlocker b_Locations(ui->comboBox_Location);
|
||||
ui->comboBox_Location->clear();
|
||||
ui->comboBox_Location->addItems(m_project->mapSectionIdNames);
|
||||
|
||||
// Hide config-specific settings
|
||||
|
||||
bool hasFlags = projectConfig.mapAllowFlagsEnabled;
|
||||
ui->checkBox_AllowRunning->setVisible(hasFlags);
|
||||
ui->checkBox_AllowBiking->setVisible(hasFlags);
|
||||
ui->checkBox_AllowEscaping->setVisible(hasFlags);
|
||||
ui->label_AllowRunning->setVisible(hasFlags);
|
||||
ui->label_AllowBiking->setVisible(hasFlags);
|
||||
ui->label_AllowEscaping->setVisible(hasFlags);
|
||||
|
||||
bool floorNumEnabled = projectConfig.floorNumberEnabled;
|
||||
ui->spinBox_FloorNumber->setVisible(floorNumEnabled);
|
||||
ui->label_FloorNumber->setVisible(floorNumEnabled);
|
||||
|
||||
// If the project changes any of the displayed data, update it accordingly.
|
||||
connect(m_project, &Project::mapSectionIdNamesChanged, this, &MapHeaderForm::setLocations);
|
||||
connect(m_project, &Project::mapSectionDisplayNameChanged, this, &MapHeaderForm::updateLocationName);
|
||||
}
|
||||
|
||||
void MapHeaderForm::setLocations(const QStringList &locations) {
|
||||
const QSignalBlocker b(ui->comboBox_Location);
|
||||
const QString before = ui->comboBox_Location->currentText();
|
||||
ui->comboBox_Location->clear();
|
||||
ui->comboBox_Location->addItems(locations);
|
||||
ui->comboBox_Location->setCurrentText(before);
|
||||
}
|
||||
|
||||
// Assign a MapHeader that the form will keep in sync with the UI.
|
||||
void MapHeaderForm::setHeader(MapHeader *header) {
|
||||
if (m_header == header)
|
||||
return;
|
||||
|
||||
if (m_header) {
|
||||
m_header->disconnect(this);
|
||||
}
|
||||
m_header = header;
|
||||
|
||||
if (!m_header) {
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// If the MapHeader is changed externally (for example, with the scripting API) update the UI accordingly
|
||||
connect(m_header, &MapHeader::songChanged, this, &MapHeaderForm::setSong);
|
||||
connect(m_header, &MapHeader::locationChanged, this, &MapHeaderForm::setLocation);
|
||||
connect(m_header, &MapHeader::requiresFlashChanged, this, &MapHeaderForm::setRequiresFlash);
|
||||
connect(m_header, &MapHeader::weatherChanged, this, &MapHeaderForm::setWeather);
|
||||
connect(m_header, &MapHeader::typeChanged, this, &MapHeaderForm::setType);
|
||||
connect(m_header, &MapHeader::battleSceneChanged, this, &MapHeaderForm::setBattleScene);
|
||||
connect(m_header, &MapHeader::showsLocationNameChanged, this, &MapHeaderForm::setShowsLocationName);
|
||||
connect(m_header, &MapHeader::allowsRunningChanged, this, &MapHeaderForm::setAllowsRunning);
|
||||
connect(m_header, &MapHeader::allowsBikingChanged, this, &MapHeaderForm::setAllowsBiking);
|
||||
connect(m_header, &MapHeader::allowsEscapingChanged, this, &MapHeaderForm::setAllowsEscaping);
|
||||
connect(m_header, &MapHeader::floorNumberChanged, this, &MapHeaderForm::setFloorNumber);
|
||||
|
||||
// Immediately update the UI to reflect the assigned MapHeader
|
||||
setHeaderData(*m_header);
|
||||
}
|
||||
|
||||
void MapHeaderForm::clear() {
|
||||
m_header = nullptr;
|
||||
setHeaderData(MapHeader());
|
||||
}
|
||||
|
||||
void MapHeaderForm::setHeaderData(const MapHeader &header) {
|
||||
setSong(header.song());
|
||||
setLocation(header.location());
|
||||
setRequiresFlash(header.requiresFlash());
|
||||
setWeather(header.weather());
|
||||
setType(header.type());
|
||||
setBattleScene(header.battleScene());
|
||||
setShowsLocationName(header.showsLocationName());
|
||||
setAllowsRunning(header.allowsRunning());
|
||||
setAllowsBiking(header.allowsBiking());
|
||||
setAllowsEscaping(header.allowsEscaping());
|
||||
setFloorNumber(header.floorNumber());
|
||||
updateLocationName();
|
||||
}
|
||||
|
||||
MapHeader MapHeaderForm::headerData() const {
|
||||
if (m_header)
|
||||
return *m_header;
|
||||
|
||||
// Build header from UI
|
||||
MapHeader header;
|
||||
header.setSong(song());
|
||||
header.setLocation(location());
|
||||
header.setRequiresFlash(requiresFlash());
|
||||
header.setWeather(weather());
|
||||
header.setType(type());
|
||||
header.setBattleScene(battleScene());
|
||||
header.setShowsLocationName(showsLocationName());
|
||||
header.setAllowsRunning(allowsRunning());
|
||||
header.setAllowsBiking(allowsBiking());
|
||||
header.setAllowsEscaping(allowsEscaping());
|
||||
header.setFloorNumber(floorNumber());
|
||||
return header;
|
||||
}
|
||||
|
||||
void MapHeaderForm::updateLocationName() {
|
||||
setLocationName(m_project ? m_project->getMapsecDisplayName(location()) : QString());
|
||||
}
|
||||
|
||||
// Set data in UI
|
||||
void MapHeaderForm::setSong(const QString &song) { ui->comboBox_Song->setCurrentText(song); }
|
||||
void MapHeaderForm::setLocation(const QString &location) { ui->comboBox_Location->setCurrentText(location); }
|
||||
void MapHeaderForm::setLocationName(const QString &locationName) { ui->lineEdit_LocationName->setText(locationName); }
|
||||
void MapHeaderForm::setRequiresFlash(bool requiresFlash) { ui->checkBox_RequiresFlash->setChecked(requiresFlash); }
|
||||
void MapHeaderForm::setWeather(const QString &weather) { ui->comboBox_Weather->setCurrentText(weather); }
|
||||
void MapHeaderForm::setType(const QString &type) { ui->comboBox_Type->setCurrentText(type); }
|
||||
void MapHeaderForm::setBattleScene(const QString &battleScene) { ui->comboBox_BattleScene->setCurrentText(battleScene); }
|
||||
void MapHeaderForm::setShowsLocationName(bool showsLocationName) { ui->checkBox_ShowLocationName->setChecked(showsLocationName); }
|
||||
void MapHeaderForm::setAllowsRunning(bool allowsRunning) { ui->checkBox_AllowRunning->setChecked(allowsRunning); }
|
||||
void MapHeaderForm::setAllowsBiking(bool allowsBiking) { ui->checkBox_AllowBiking->setChecked(allowsBiking); }
|
||||
void MapHeaderForm::setAllowsEscaping(bool allowsEscaping) { ui->checkBox_AllowEscaping->setChecked(allowsEscaping); }
|
||||
void MapHeaderForm::setFloorNumber(int floorNumber) { ui->spinBox_FloorNumber->setValue(floorNumber); }
|
||||
|
||||
// Read data from UI
|
||||
QString MapHeaderForm::song() const { return ui->comboBox_Song->currentText(); }
|
||||
QString MapHeaderForm::location() const { return ui->comboBox_Location->currentText(); }
|
||||
QString MapHeaderForm::locationName() const { return ui->lineEdit_LocationName->text(); }
|
||||
bool MapHeaderForm::requiresFlash() const { return ui->checkBox_RequiresFlash->isChecked(); }
|
||||
QString MapHeaderForm::weather() const { return ui->comboBox_Weather->currentText(); }
|
||||
QString MapHeaderForm::type() const { return ui->comboBox_Type->currentText(); }
|
||||
QString MapHeaderForm::battleScene() const { return ui->comboBox_BattleScene->currentText(); }
|
||||
bool MapHeaderForm::showsLocationName() const { return ui->checkBox_ShowLocationName->isChecked(); }
|
||||
bool MapHeaderForm::allowsRunning() const { return ui->checkBox_AllowRunning->isChecked(); }
|
||||
bool MapHeaderForm::allowsBiking() const { return ui->checkBox_AllowBiking->isChecked(); }
|
||||
bool MapHeaderForm::allowsEscaping() const { return ui->checkBox_AllowEscaping->isChecked(); }
|
||||
int MapHeaderForm::floorNumber() const { return ui->spinBox_FloorNumber->value(); }
|
||||
|
||||
// Send changes in UI to tracked MapHeader (if there is one)
|
||||
void MapHeaderForm::onSongUpdated(const QString &song) { if (m_header) m_header->setSong(song); }
|
||||
void MapHeaderForm::onWeatherChanged(const QString &weather) { if (m_header) m_header->setWeather(weather); }
|
||||
void MapHeaderForm::onTypeChanged(const QString &type) { if (m_header) m_header->setType(type); }
|
||||
void MapHeaderForm::onBattleSceneChanged(const QString &battleScene) { if (m_header) m_header->setBattleScene(battleScene); }
|
||||
void MapHeaderForm::onRequiresFlashChanged(int selected) { if (m_header) m_header->setRequiresFlash(selected == Qt::Checked); }
|
||||
void MapHeaderForm::onShowLocationNameChanged(int selected) { if (m_header) m_header->setShowsLocationName(selected == Qt::Checked); }
|
||||
void MapHeaderForm::onAllowRunningChanged(int selected) { if (m_header) m_header->setAllowsRunning(selected == Qt::Checked); }
|
||||
void MapHeaderForm::onAllowBikingChanged(int selected) { if (m_header) m_header->setAllowsBiking(selected == Qt::Checked); }
|
||||
void MapHeaderForm::onAllowEscapingChanged(int selected) { if (m_header) m_header->setAllowsEscaping(selected == Qt::Checked); }
|
||||
void MapHeaderForm::onFloorNumberChanged(int offset) { if (m_header) m_header->setFloorNumber(offset); }
|
||||
void MapHeaderForm::onLocationChanged(const QString &location) {
|
||||
if (m_header) m_header->setLocation(location);
|
||||
updateLocationName();
|
||||
}
|
||||
void MapHeaderForm::onLocationNameChanged(const QString &locationName) {
|
||||
if (m_project && m_allowProjectChanges) {
|
||||
// The location name is actually part of the project, not the map header.
|
||||
// If the field is changed in the UI we can push these changes to the project.
|
||||
m_project->setMapsecDisplayName(location(), locationName);
|
||||
}
|
||||
}
|
||||
|
|
@ -36,25 +36,25 @@ QString getDescription(ImageExporterMode mode) {
|
|||
return "";
|
||||
}
|
||||
|
||||
MapImageExporter::MapImageExporter(QWidget *parent_, Editor *editor_, ImageExporterMode mode) :
|
||||
QDialog(parent_),
|
||||
MapImageExporter::MapImageExporter(QWidget *parent, Editor *editor, ImageExporterMode mode) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::MapImageExporter)
|
||||
{
|
||||
this->setAttribute(Qt::WA_DeleteOnClose);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
ui->setupUi(this);
|
||||
this->map = editor_->map;
|
||||
this->layout = editor_->layout;
|
||||
this->editor = editor_;
|
||||
this->mode = mode;
|
||||
this->setWindowTitle(getTitle(this->mode));
|
||||
this->ui->label_Description->setText(getDescription(this->mode));
|
||||
this->ui->groupBox_Connections->setVisible(this->mode != ImageExporterMode::Stitch);
|
||||
this->ui->groupBox_Timelapse->setVisible(this->mode == ImageExporterMode::Timelapse);
|
||||
m_map = editor->map;
|
||||
m_layout = editor->layout;
|
||||
m_editor = editor;
|
||||
m_mode = mode;
|
||||
setWindowTitle(getTitle(m_mode));
|
||||
ui->label_Description->setText(getDescription(m_mode));
|
||||
ui->groupBox_Connections->setVisible(m_mode != ImageExporterMode::Stitch);
|
||||
ui->groupBox_Timelapse->setVisible(m_mode == ImageExporterMode::Timelapse);
|
||||
|
||||
if (this->map) {
|
||||
this->ui->comboBox_MapSelection->addItems(editor->project->mapNames);
|
||||
this->ui->comboBox_MapSelection->setCurrentText(map->name);
|
||||
this->ui->comboBox_MapSelection->setEnabled(false);// TODO: allow selecting map from drop-down
|
||||
if (m_map) {
|
||||
ui->comboBox_MapSelection->addItems(editor->project->mapNames);
|
||||
ui->comboBox_MapSelection->setCurrentText(m_map->name());
|
||||
ui->comboBox_MapSelection->setEnabled(false);// TODO: allow selecting map from drop-down
|
||||
}
|
||||
|
||||
connect(ui->pushButton_Save, &QPushButton::pressed, this, &MapImageExporter::saveImage);
|
||||
|
|
@ -62,7 +62,7 @@ MapImageExporter::MapImageExporter(QWidget *parent_, Editor *editor_, ImageExpor
|
|||
}
|
||||
|
||||
MapImageExporter::~MapImageExporter() {
|
||||
delete scene;
|
||||
delete m_scene;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
|
@ -80,48 +80,49 @@ void MapImageExporter::resizeEvent(QResizeEvent *event) {
|
|||
|
||||
void MapImageExporter::saveImage() {
|
||||
// Make sure preview is up-to-date before we save.
|
||||
if (this->preview.isNull())
|
||||
if (m_preview.isNull())
|
||||
updatePreview();
|
||||
if (this->preview.isNull())
|
||||
if (m_preview.isNull())
|
||||
return;
|
||||
|
||||
QString title = getTitle(this->mode);
|
||||
const QString title = getTitle(m_mode);
|
||||
const QString itemName = m_map ? m_map->name() : m_layout->name;
|
||||
QString defaultFilename;
|
||||
switch (this->mode)
|
||||
switch (m_mode)
|
||||
{
|
||||
case ImageExporterMode::Normal:
|
||||
defaultFilename = this->map? this->map->name : this->layout->name;
|
||||
defaultFilename = itemName;
|
||||
break;
|
||||
case ImageExporterMode::Stitch:
|
||||
defaultFilename = QString("Stitch_From_%1").arg(this->map? this->map->name : this->layout->name);
|
||||
defaultFilename = QString("Stitch_From_%1").arg(itemName);
|
||||
break;
|
||||
case ImageExporterMode::Timelapse:
|
||||
defaultFilename = QString("Timelapse_%1").arg(this->map? this->map->name : this->layout->name);
|
||||
defaultFilename = QString("Timelapse_%1").arg(itemName);
|
||||
break;
|
||||
}
|
||||
|
||||
QString defaultFilepath = QString("%1/%2.%3")
|
||||
.arg(FileDialog::getDirectory())
|
||||
.arg(defaultFilename)
|
||||
.arg(this->mode == ImageExporterMode::Timelapse ? "gif" : "png");
|
||||
QString filter = this->mode == ImageExporterMode::Timelapse ? "Image Files (*.gif)" : "Image Files (*.png *.jpg *.bmp)";
|
||||
.arg(m_mode == ImageExporterMode::Timelapse ? "gif" : "png");
|
||||
QString filter = m_mode == ImageExporterMode::Timelapse ? "Image Files (*.gif)" : "Image Files (*.png *.jpg *.bmp)";
|
||||
QString filepath = FileDialog::getSaveFileName(this, title, defaultFilepath, filter);
|
||||
if (!filepath.isEmpty()) {
|
||||
switch (this->mode) {
|
||||
switch (m_mode) {
|
||||
case ImageExporterMode::Normal:
|
||||
case ImageExporterMode::Stitch:
|
||||
// Normal and Stitch modes already have the image ready to go in the preview.
|
||||
this->preview.save(filepath);
|
||||
m_preview.save(filepath);
|
||||
break;
|
||||
case ImageExporterMode::Timelapse:
|
||||
// Timelapse will play in order of layout changes then map changes (events)
|
||||
// TODO: potentially update in the future?
|
||||
QGifImage timelapseImg;
|
||||
timelapseImg.setDefaultDelay(this->settings.timelapseDelayMs);
|
||||
timelapseImg.setDefaultDelay(m_settings.timelapseDelayMs);
|
||||
timelapseImg.setDefaultTransparentColor(QColor(0, 0, 0));
|
||||
|
||||
// lambda to avoid redundancy
|
||||
auto generateTimelapseFromHistory = [this, &timelapseImg](QString progressText, QUndoStack &historyStack){
|
||||
auto generateTimelapseFromHistory = [this, &timelapseImg](QString progressText, QUndoStack *historyStack){
|
||||
QProgressDialog progress(progressText, "Cancel", 0, 1, this);
|
||||
progress.setAutoClose(true);
|
||||
progress.setWindowModality(Qt::WindowModal);
|
||||
|
|
@ -129,20 +130,20 @@ void MapImageExporter::saveImage() {
|
|||
progress.setMaximum(1);
|
||||
progress.setValue(0);
|
||||
|
||||
int maxWidth = this->layout->getWidth() * 16;
|
||||
int maxHeight = this->layout->getHeight() * 16;
|
||||
if (this->settings.showBorder) {
|
||||
int maxWidth = m_layout->getWidth() * 16;
|
||||
int maxHeight = m_layout->getHeight() * 16;
|
||||
if (m_settings.showBorder) {
|
||||
maxWidth += 2 * STITCH_MODE_BORDER_DISTANCE * 16;
|
||||
maxHeight += 2 * STITCH_MODE_BORDER_DISTANCE * 16;
|
||||
}
|
||||
// Rewind to the specified start of the map edit history.
|
||||
int i = 0;
|
||||
while (historyStack.canUndo()) {
|
||||
while (historyStack->canUndo()) {
|
||||
progress.setValue(i);
|
||||
historyStack.undo();
|
||||
int width = this->layout->getWidth() * 16;
|
||||
int height = this->layout->getHeight() * 16;
|
||||
if (this->settings.showBorder) {
|
||||
historyStack->undo();
|
||||
int width = m_layout->getWidth() * 16;
|
||||
int height = m_layout->getHeight() * 16;
|
||||
if (m_settings.showBorder) {
|
||||
width += 2 * STITCH_MODE_BORDER_DISTANCE * 16;
|
||||
height += 2 * STITCH_MODE_BORDER_DISTANCE * 16;
|
||||
}
|
||||
|
|
@ -161,19 +162,19 @@ void MapImageExporter::saveImage() {
|
|||
while (i > 0) {
|
||||
if (progress.wasCanceled()) {
|
||||
progress.close();
|
||||
while (i > 0 && historyStack.canRedo()) {
|
||||
while (i > 0 && historyStack->canRedo()) {
|
||||
i--;
|
||||
historyStack.redo();
|
||||
historyStack->redo();
|
||||
}
|
||||
return;
|
||||
}
|
||||
while (historyStack.canRedo() &&
|
||||
!historyItemAppliesToFrame(historyStack.command(historyStack.index()))) {
|
||||
while (historyStack->canRedo() &&
|
||||
!historyItemAppliesToFrame(historyStack->command(historyStack->index()))) {
|
||||
i--;
|
||||
historyStack.redo();
|
||||
historyStack->redo();
|
||||
}
|
||||
progress.setValue(progress.maximum() - i);
|
||||
QPixmap pixmap = this->getFormattedMapPixmap(this->map);
|
||||
QPixmap pixmap = getFormattedMapPixmap();
|
||||
if (pixmap.width() < maxWidth || pixmap.height() < maxHeight) {
|
||||
QPixmap pixmap2 = QPixmap(maxWidth, maxHeight);
|
||||
QPainter painter(&pixmap2);
|
||||
|
|
@ -183,34 +184,34 @@ void MapImageExporter::saveImage() {
|
|||
pixmap = pixmap2;
|
||||
}
|
||||
timelapseImg.addFrame(pixmap.toImage());
|
||||
for (int j = 0; j < this->settings.timelapseSkipAmount; j++) {
|
||||
for (int j = 0; j < m_settings.timelapseSkipAmount; j++) {
|
||||
if (i > 0) {
|
||||
i--;
|
||||
historyStack.redo();
|
||||
while (historyStack.canRedo() &&
|
||||
!historyItemAppliesToFrame(historyStack.command(historyStack.index()))) {
|
||||
historyStack->redo();
|
||||
while (historyStack->canRedo() &&
|
||||
!historyItemAppliesToFrame(historyStack->command(historyStack->index()))) {
|
||||
i--;
|
||||
historyStack.redo();
|
||||
historyStack->redo();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// The latest map state is the last animated frame.
|
||||
QPixmap pixmap = this->getFormattedMapPixmap(this->map);
|
||||
QPixmap pixmap = getFormattedMapPixmap();
|
||||
timelapseImg.addFrame(pixmap.toImage());
|
||||
progress.close();
|
||||
};
|
||||
|
||||
if (this->layout)
|
||||
generateTimelapseFromHistory("Building layout timelapse...", this->layout->editHistory);
|
||||
if (m_layout)
|
||||
generateTimelapseFromHistory("Building layout timelapse...", &m_layout->editHistory);
|
||||
|
||||
if (this->map)
|
||||
generateTimelapseFromHistory("Building map timelapse...", this->map->editHistory);
|
||||
if (m_map)
|
||||
generateTimelapseFromHistory("Building map timelapse...", m_map->editHistory());
|
||||
|
||||
timelapseImg.save(filepath);
|
||||
break;
|
||||
}
|
||||
this->close();
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -229,26 +230,26 @@ bool MapImageExporter::historyItemAppliesToFrame(const QUndoCommand *command) {
|
|||
case CommandId::ID_PaintCollision:
|
||||
case CommandId::ID_BucketFillCollision:
|
||||
case CommandId::ID_MagicFillCollision:
|
||||
return this->settings.showCollision;
|
||||
return m_settings.showCollision;
|
||||
case CommandId::ID_PaintBorder:
|
||||
return this->settings.showBorder;
|
||||
return m_settings.showBorder;
|
||||
case CommandId::ID_MapConnectionMove:
|
||||
case CommandId::ID_MapConnectionChangeDirection:
|
||||
case CommandId::ID_MapConnectionChangeMap:
|
||||
case CommandId::ID_MapConnectionAdd:
|
||||
case CommandId::ID_MapConnectionRemove:
|
||||
return this->settings.showUpConnections || this->settings.showDownConnections || this->settings.showLeftConnections || this->settings.showRightConnections;
|
||||
return m_settings.showUpConnections || m_settings.showDownConnections || m_settings.showLeftConnections || m_settings.showRightConnections;
|
||||
case CommandId::ID_EventMove:
|
||||
case CommandId::ID_EventShift:
|
||||
case CommandId::ID_EventCreate:
|
||||
case CommandId::ID_EventDelete:
|
||||
case CommandId::ID_EventDuplicate: {
|
||||
bool eventTypeIsApplicable =
|
||||
(this->settings.showObjects && (command->id() & IDMask_EventType_Object) != 0)
|
||||
|| (this->settings.showWarps && (command->id() & IDMask_EventType_Warp) != 0)
|
||||
|| (this->settings.showBGs && (command->id() & IDMask_EventType_BG) != 0)
|
||||
|| (this->settings.showTriggers && (command->id() & IDMask_EventType_Trigger) != 0)
|
||||
|| (this->settings.showHealLocations && (command->id() & IDMask_EventType_Heal) != 0);
|
||||
(m_settings.showObjects && (command->id() & IDMask_EventType_Object) != 0)
|
||||
|| (m_settings.showWarps && (command->id() & IDMask_EventType_Warp) != 0)
|
||||
|| (m_settings.showBGs && (command->id() & IDMask_EventType_BG) != 0)
|
||||
|| (m_settings.showTriggers && (command->id() & IDMask_EventType_Trigger) != 0)
|
||||
|| (m_settings.showHealLocations && (command->id() & IDMask_EventType_Heal) != 0);
|
||||
return eventTypeIsApplicable;
|
||||
}
|
||||
default:
|
||||
|
|
@ -268,7 +269,7 @@ QPixmap MapImageExporter::getStitchedImage(QProgressDialog *progress, bool inclu
|
|||
QSet<QString> visited;
|
||||
QList<StitchedMap> stitchedMaps;
|
||||
QList<StitchedMap> unvisited;
|
||||
unvisited.append(StitchedMap{0, 0, this->editor->map});
|
||||
unvisited.append(StitchedMap{0, 0, m_editor->map});
|
||||
|
||||
progress->setLabelText("Gathering stitched maps...");
|
||||
while (!unvisited.isEmpty()) {
|
||||
|
|
@ -279,9 +280,9 @@ QPixmap MapImageExporter::getStitchedImage(QProgressDialog *progress, bool inclu
|
|||
progress->setValue(visited.size());
|
||||
|
||||
StitchedMap cur = unvisited.takeFirst();
|
||||
if (visited.contains(cur.map->name))
|
||||
if (visited.contains(cur.map->name()))
|
||||
continue;
|
||||
visited.insert(cur.map->name);
|
||||
visited.insert(cur.map->name());
|
||||
stitchedMaps.append(cur);
|
||||
|
||||
for (MapConnection *connection : cur.map->getConnections()) {
|
||||
|
|
@ -361,7 +362,7 @@ QPixmap MapImageExporter::getStitchedImage(QProgressDialog *progress, bool inclu
|
|||
pixelX -= STITCH_MODE_BORDER_DISTANCE * 16;
|
||||
pixelY -= STITCH_MODE_BORDER_DISTANCE * 16;
|
||||
}
|
||||
QPixmap pixmap = this->getFormattedMapPixmap(map.map);
|
||||
QPixmap pixmap = getFormattedMapPixmap(map.map);
|
||||
painter.drawPixmap(pixelX, pixelY, pixmap);
|
||||
}
|
||||
|
||||
|
|
@ -382,7 +383,7 @@ QPixmap MapImageExporter::getStitchedImage(QProgressDialog *progress, bool inclu
|
|||
|
||||
int pixelX = (map.x - minX) * 16;
|
||||
int pixelY = (map.y - minY) * 16;
|
||||
QPixmap pixmapWithoutBorders = this->getFormattedMapPixmap(map.map, true);
|
||||
QPixmap pixmapWithoutBorders = getFormattedMapPixmap(map.map, true);
|
||||
painter.drawPixmap(pixelX, pixelY, pixmapWithoutBorders);
|
||||
}
|
||||
}
|
||||
|
|
@ -391,56 +392,50 @@ QPixmap MapImageExporter::getStitchedImage(QProgressDialog *progress, bool inclu
|
|||
}
|
||||
|
||||
void MapImageExporter::updatePreview() {
|
||||
if (this->scene) {
|
||||
delete this->scene;
|
||||
this->scene = nullptr;
|
||||
if (m_scene) {
|
||||
delete m_scene;
|
||||
m_scene = nullptr;
|
||||
}
|
||||
this->scene = new QGraphicsScene;
|
||||
m_scene = new QGraphicsScene;
|
||||
|
||||
if (this->mode == ImageExporterMode::Stitch) {
|
||||
if (m_mode == ImageExporterMode::Stitch) {
|
||||
QProgressDialog progress("Building map stitch...", "Cancel", 0, 1, this);
|
||||
progress.setAutoClose(true);
|
||||
progress.setWindowModality(Qt::WindowModal);
|
||||
progress.setModal(true);
|
||||
progress.setMinimumDuration(1000);
|
||||
this->preview = getStitchedImage(&progress, this->settings.showBorder);
|
||||
m_preview = getStitchedImage(&progress, m_settings.showBorder);
|
||||
progress.close();
|
||||
} else {
|
||||
// Timelapse mode doesn't currently have a real preview. It just displays the current map as in Normal mode.
|
||||
this->preview = getFormattedMapPixmap(this->map);
|
||||
m_preview = getFormattedMapPixmap();
|
||||
}
|
||||
this->scene->addPixmap(this->preview);
|
||||
ui->graphicsView_Preview->setScene(scene);
|
||||
m_scene->addPixmap(m_preview);
|
||||
ui->graphicsView_Preview->setScene(m_scene);
|
||||
scalePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::scalePreview() {
|
||||
if (this->scene && !this->settings.previewActualSize){
|
||||
ui->graphicsView_Preview->fitInView(this->scene->sceneRect(), Qt::KeepAspectRatioByExpanding);
|
||||
if (m_scene && !m_settings.previewActualSize){
|
||||
ui->graphicsView_Preview->fitInView(m_scene->sceneRect(), Qt::KeepAspectRatioByExpanding);
|
||||
}
|
||||
}
|
||||
|
||||
// THIS
|
||||
QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) {
|
||||
QPixmap pixmap;
|
||||
QPixmap MapImageExporter::getFormattedMapPixmap() {
|
||||
return m_map ? getFormattedMapPixmap(m_map) : getFormattedLayoutPixmap(m_layout);
|
||||
}
|
||||
|
||||
Layout *layout;
|
||||
QPixmap MapImageExporter::getFormattedLayoutPixmap(Layout *layout, bool ignoreBorder, bool ignoreGrid) {
|
||||
if (!layout)
|
||||
return QPixmap();
|
||||
|
||||
// draw background layer / base image
|
||||
if (!this->map) {
|
||||
layout = this->layout;
|
||||
layout->render(true);
|
||||
pixmap = layout->pixmap;
|
||||
} else {
|
||||
layout = map->layout;
|
||||
map->layout->render(true);
|
||||
pixmap = map->layout->pixmap;
|
||||
}
|
||||
layout->render(true);
|
||||
QPixmap pixmap = layout->pixmap;
|
||||
|
||||
if (this->settings.showCollision) {
|
||||
if (m_settings.showCollision) {
|
||||
QPainter collisionPainter(&pixmap);
|
||||
layout->renderCollision(true);
|
||||
collisionPainter.setOpacity(editor->collisionOpacity);
|
||||
collisionPainter.setOpacity(m_editor->collisionOpacity);
|
||||
collisionPainter.drawPixmap(0, 0, layout->collision_pixmap);
|
||||
collisionPainter.end();
|
||||
}
|
||||
|
|
@ -448,11 +443,11 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) {
|
|||
// draw map border
|
||||
// note: this will break when allowing map to be selected from drop down maybe
|
||||
int borderHeight = 0, borderWidth = 0;
|
||||
if (!ignoreBorder && this->settings.showBorder) {
|
||||
int borderDistance = this->mode ? STITCH_MODE_BORDER_DISTANCE : BORDER_DISTANCE;
|
||||
if (!ignoreBorder && m_settings.showBorder) {
|
||||
int borderDistance = m_mode ? STITCH_MODE_BORDER_DISTANCE : BORDER_DISTANCE;
|
||||
layout->renderBorder();
|
||||
int borderHorzDist = editor->getBorderDrawDistance(layout->getBorderWidth());
|
||||
int borderVertDist = editor->getBorderDrawDistance(layout->getBorderHeight());
|
||||
int borderHorzDist = m_editor->getBorderDrawDistance(layout->getBorderWidth());
|
||||
int borderVertDist = m_editor->getBorderDrawDistance(layout->getBorderHeight());
|
||||
borderWidth = borderDistance * 16;
|
||||
borderHeight = borderDistance * 16;
|
||||
QPixmap newPixmap = QPixmap(layout->pixmap.width() + borderWidth * 2, layout->pixmap.height() + borderHeight * 2);
|
||||
|
|
@ -467,20 +462,34 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) {
|
|||
pixmap = newPixmap;
|
||||
}
|
||||
|
||||
if (!this->map) {
|
||||
return pixmap;
|
||||
}
|
||||
// The grid should be painted last, so if this layout pixmap is being painted
|
||||
// as part of a map (which has more to paint after this) then don't paint the grid yet.
|
||||
if (!ignoreGrid)
|
||||
paintGrid(&pixmap, ignoreBorder);
|
||||
|
||||
if (!ignoreBorder && (this->settings.showUpConnections || this->settings.showDownConnections || this->settings.showLeftConnections || this->settings.showRightConnections)) {
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) {
|
||||
if (!map)
|
||||
return QPixmap();
|
||||
|
||||
QPixmap pixmap = getFormattedLayoutPixmap(map->layout(), ignoreBorder, true);
|
||||
|
||||
if (!ignoreBorder && (m_settings.showUpConnections || m_settings.showDownConnections || m_settings.showLeftConnections || m_settings.showRightConnections)) {
|
||||
// if showing connections, draw on outside of image
|
||||
QPainter connectionPainter(&pixmap);
|
||||
|
||||
int borderDistance = m_mode ? STITCH_MODE_BORDER_DISTANCE : BORDER_DISTANCE;
|
||||
int borderWidth = borderDistance * 16;
|
||||
int borderHeight = borderDistance * 16;
|
||||
// TODO: Reading the connections from the editor and not 'map' is incorrect.
|
||||
for (auto connectionItem : editor->connection_items) {
|
||||
for (auto connectionItem : m_editor->connection_items) {
|
||||
const QString direction = connectionItem->connection->direction();
|
||||
if ((this->settings.showUpConnections && direction == "up")
|
||||
|| (this->settings.showDownConnections && direction == "down")
|
||||
|| (this->settings.showLeftConnections && direction == "left")
|
||||
|| (this->settings.showRightConnections && direction == "right"))
|
||||
if ((m_settings.showUpConnections && direction == "up")
|
||||
|| (m_settings.showDownConnections && direction == "down")
|
||||
|| (m_settings.showLeftConnections && direction == "left")
|
||||
|| (m_settings.showRightConnections && direction == "right"))
|
||||
connectionPainter.drawImage(connectionItem->x() + borderWidth, connectionItem->y() + borderHeight,
|
||||
connectionItem->connection->getPixmap().toImage());
|
||||
}
|
||||
|
|
@ -488,37 +497,43 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) {
|
|||
}
|
||||
|
||||
// draw events
|
||||
if (this->settings.showObjects || this->settings.showWarps || this->settings.showBGs || this->settings.showTriggers || this->settings.showHealLocations) {
|
||||
if (m_settings.showObjects || m_settings.showWarps || m_settings.showBGs || m_settings.showTriggers || m_settings.showHealLocations) {
|
||||
QPainter eventPainter(&pixmap);
|
||||
int pixelOffset = 0;
|
||||
if (!ignoreBorder && this->settings.showBorder) {
|
||||
pixelOffset = this->mode == ImageExporterMode::Normal ? BORDER_DISTANCE * 16 : STITCH_MODE_BORDER_DISTANCE * 16;
|
||||
if (!ignoreBorder && m_settings.showBorder) {
|
||||
pixelOffset = m_mode == ImageExporterMode::Normal ? BORDER_DISTANCE * 16 : STITCH_MODE_BORDER_DISTANCE * 16;
|
||||
}
|
||||
const QList<Event *> events = map->getAllEvents();
|
||||
const QList<Event *> events = map->getEvents();
|
||||
for (const auto &event : events) {
|
||||
Event::Group group = event->getEventGroup();
|
||||
if ((this->settings.showObjects && group == Event::Group::Object)
|
||||
|| (this->settings.showWarps && group == Event::Group::Warp)
|
||||
|| (this->settings.showBGs && group == Event::Group::Bg)
|
||||
|| (this->settings.showTriggers && group == Event::Group::Coord)
|
||||
|| (this->settings.showHealLocations && group == Event::Group::Heal)) {
|
||||
editor->project->setEventPixmap(event);
|
||||
if ((m_settings.showObjects && group == Event::Group::Object)
|
||||
|| (m_settings.showWarps && group == Event::Group::Warp)
|
||||
|| (m_settings.showBGs && group == Event::Group::Bg)
|
||||
|| (m_settings.showTriggers && group == Event::Group::Coord)
|
||||
|| (m_settings.showHealLocations && group == Event::Group::Heal)) {
|
||||
m_editor->project->setEventPixmap(event);
|
||||
eventPainter.drawImage(QPoint(event->getPixelX() + pixelOffset, event->getPixelY() + pixelOffset), event->getPixmap().toImage());
|
||||
}
|
||||
}
|
||||
eventPainter.end();
|
||||
}
|
||||
paintGrid(&pixmap, ignoreBorder);
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
void MapImageExporter::paintGrid(QPixmap *pixmap, bool ignoreBorder) {
|
||||
// draw grid directly onto the pixmap
|
||||
// since the last grid lines are outside of the pixmap, add a pixel to the bottom and right
|
||||
if (this->settings.showGrid) {
|
||||
if (m_settings.showGrid) {
|
||||
bool hasBorder = !ignoreBorder && m_settings.showBorder;
|
||||
int addX = 1, addY = 1;
|
||||
if (borderHeight) addY = 0;
|
||||
if (borderWidth) addX = 0;
|
||||
if (hasBorder) addY = 0;
|
||||
if (hasBorder) addX = 0;
|
||||
|
||||
QPixmap newPixmap= QPixmap(pixmap.width() + addX, pixmap.height() + addY);
|
||||
QPixmap newPixmap= QPixmap(pixmap->width() + addX, pixmap->height() + addY);
|
||||
QPainter gridPainter(&newPixmap);
|
||||
gridPainter.drawImage(QPoint(0, 0), pixmap.toImage());
|
||||
gridPainter.drawImage(QPoint(0, 0), pixmap->toImage());
|
||||
for (int x = 0; x < newPixmap.width(); x += 16) {
|
||||
gridPainter.drawLine(x, 0, x, newPixmap.height());
|
||||
}
|
||||
|
|
@ -526,58 +541,56 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) {
|
|||
gridPainter.drawLine(0, y, newPixmap.width(), y);
|
||||
}
|
||||
gridPainter.end();
|
||||
pixmap = newPixmap;
|
||||
*pixmap = newPixmap;
|
||||
}
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
void MapImageExporter::updateShowBorderState() {
|
||||
// If any of the Connections settings are enabled then this setting is locked (it's implicitly enabled)
|
||||
bool on = (this->settings.showUpConnections || this->settings.showDownConnections || this->settings.showLeftConnections || this->settings.showRightConnections);
|
||||
bool on = (m_settings.showUpConnections || m_settings.showDownConnections || m_settings.showLeftConnections || m_settings.showRightConnections);
|
||||
const QSignalBlocker blocker(ui->checkBox_Border);
|
||||
ui->checkBox_Border->setChecked(on);
|
||||
ui->checkBox_Border->setDisabled(on);
|
||||
this->settings.showBorder = on;
|
||||
m_settings.showBorder = on;
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_Elevation_stateChanged(int state) {
|
||||
this->settings.showCollision = (state == Qt::Checked);
|
||||
m_settings.showCollision = (state == Qt::Checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_Grid_stateChanged(int state) {
|
||||
this->settings.showGrid = (state == Qt::Checked);
|
||||
m_settings.showGrid = (state == Qt::Checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_Border_stateChanged(int state) {
|
||||
this->settings.showBorder = (state == Qt::Checked);
|
||||
m_settings.showBorder = (state == Qt::Checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_Objects_stateChanged(int state) {
|
||||
this->settings.showObjects = (state == Qt::Checked);
|
||||
m_settings.showObjects = (state == Qt::Checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_Warps_stateChanged(int state) {
|
||||
this->settings.showWarps = (state == Qt::Checked);
|
||||
m_settings.showWarps = (state == Qt::Checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_BGs_stateChanged(int state) {
|
||||
this->settings.showBGs = (state == Qt::Checked);
|
||||
m_settings.showBGs = (state == Qt::Checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_Triggers_stateChanged(int state) {
|
||||
this->settings.showTriggers = (state == Qt::Checked);
|
||||
m_settings.showTriggers = (state == Qt::Checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_HealLocations_stateChanged(int state) {
|
||||
this->settings.showHealLocations = (state == Qt::Checked);
|
||||
m_settings.showHealLocations = (state == Qt::Checked);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
|
|
@ -588,51 +601,51 @@ void MapImageExporter::on_checkBox_AllEvents_stateChanged(int state) {
|
|||
const QSignalBlocker b_Objects(ui->checkBox_Objects);
|
||||
ui->checkBox_Objects->setChecked(on);
|
||||
ui->checkBox_Objects->setDisabled(on);
|
||||
this->settings.showObjects = on;
|
||||
m_settings.showObjects = on;
|
||||
|
||||
const QSignalBlocker b_Warps(ui->checkBox_Warps);
|
||||
ui->checkBox_Warps->setChecked(on);
|
||||
ui->checkBox_Warps->setDisabled(on);
|
||||
this->settings.showWarps = on;
|
||||
m_settings.showWarps = on;
|
||||
|
||||
const QSignalBlocker b_BGs(ui->checkBox_BGs);
|
||||
ui->checkBox_BGs->setChecked(on);
|
||||
ui->checkBox_BGs->setDisabled(on);
|
||||
this->settings.showBGs = on;
|
||||
m_settings.showBGs = on;
|
||||
|
||||
const QSignalBlocker b_Triggers(ui->checkBox_Triggers);
|
||||
ui->checkBox_Triggers->setChecked(on);
|
||||
ui->checkBox_Triggers->setDisabled(on);
|
||||
this->settings.showTriggers = on;
|
||||
m_settings.showTriggers = on;
|
||||
|
||||
const QSignalBlocker b_HealLocations(ui->checkBox_HealLocations);
|
||||
ui->checkBox_HealLocations->setChecked(on);
|
||||
ui->checkBox_HealLocations->setDisabled(on);
|
||||
this->settings.showHealLocations = on;
|
||||
m_settings.showHealLocations = on;
|
||||
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_ConnectionUp_stateChanged(int state) {
|
||||
this->settings.showUpConnections = (state == Qt::Checked);
|
||||
m_settings.showUpConnections = (state == Qt::Checked);
|
||||
updateShowBorderState();
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_ConnectionDown_stateChanged(int state) {
|
||||
this->settings.showDownConnections = (state == Qt::Checked);
|
||||
m_settings.showDownConnections = (state == Qt::Checked);
|
||||
updateShowBorderState();
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_ConnectionLeft_stateChanged(int state) {
|
||||
this->settings.showLeftConnections = (state == Qt::Checked);
|
||||
m_settings.showLeftConnections = (state == Qt::Checked);
|
||||
updateShowBorderState();
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_ConnectionRight_stateChanged(int state) {
|
||||
this->settings.showRightConnections = (state == Qt::Checked);
|
||||
m_settings.showRightConnections = (state == Qt::Checked);
|
||||
updateShowBorderState();
|
||||
updatePreview();
|
||||
}
|
||||
|
|
@ -644,30 +657,30 @@ void MapImageExporter::on_checkBox_AllConnections_stateChanged(int state) {
|
|||
const QSignalBlocker b_Up(ui->checkBox_ConnectionUp);
|
||||
ui->checkBox_ConnectionUp->setChecked(on);
|
||||
ui->checkBox_ConnectionUp->setDisabled(on);
|
||||
this->settings.showUpConnections = on;
|
||||
m_settings.showUpConnections = on;
|
||||
|
||||
const QSignalBlocker b_Down(ui->checkBox_ConnectionDown);
|
||||
ui->checkBox_ConnectionDown->setChecked(on);
|
||||
ui->checkBox_ConnectionDown->setDisabled(on);
|
||||
this->settings.showDownConnections = on;
|
||||
m_settings.showDownConnections = on;
|
||||
|
||||
const QSignalBlocker b_Left(ui->checkBox_ConnectionLeft);
|
||||
ui->checkBox_ConnectionLeft->setChecked(on);
|
||||
ui->checkBox_ConnectionLeft->setDisabled(on);
|
||||
this->settings.showLeftConnections = on;
|
||||
m_settings.showLeftConnections = on;
|
||||
|
||||
const QSignalBlocker b_Right(ui->checkBox_ConnectionRight);
|
||||
ui->checkBox_ConnectionRight->setChecked(on);
|
||||
ui->checkBox_ConnectionRight->setDisabled(on);
|
||||
this->settings.showRightConnections = on;
|
||||
m_settings.showRightConnections = on;
|
||||
|
||||
updateShowBorderState();
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_checkBox_ActualSize_stateChanged(int state) {
|
||||
this->settings.previewActualSize = (state == Qt::Checked);
|
||||
if (this->settings.previewActualSize) {
|
||||
m_settings.previewActualSize = (state == Qt::Checked);
|
||||
if (m_settings.previewActualSize) {
|
||||
ui->graphicsView_Preview->resetTransform();
|
||||
} else {
|
||||
scalePreview();
|
||||
|
|
@ -675,20 +688,20 @@ void MapImageExporter::on_checkBox_ActualSize_stateChanged(int state) {
|
|||
}
|
||||
|
||||
void MapImageExporter::on_pushButton_Reset_pressed() {
|
||||
this->settings = {};
|
||||
m_settings = {};
|
||||
for (auto widget : this->findChildren<QCheckBox *>()) {
|
||||
const QSignalBlocker b(widget); // Prevent calls to updatePreview
|
||||
widget->setChecked(false);
|
||||
}
|
||||
ui->spinBox_TimelapseDelay->setValue(this->settings.timelapseDelayMs);
|
||||
ui->spinBox_FrameSkip->setValue(this->settings.timelapseSkipAmount);
|
||||
ui->spinBox_TimelapseDelay->setValue(m_settings.timelapseDelayMs);
|
||||
ui->spinBox_FrameSkip->setValue(m_settings.timelapseSkipAmount);
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
void MapImageExporter::on_spinBox_TimelapseDelay_valueChanged(int delayMs) {
|
||||
this->settings.timelapseDelayMs = delayMs;
|
||||
m_settings.timelapseDelayMs = delayMs;
|
||||
}
|
||||
|
||||
void MapImageExporter::on_spinBox_FrameSkip_valueChanged(int skip) {
|
||||
this->settings.timelapseSkipAmount = skip;
|
||||
m_settings.timelapseSkipAmount = skip;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
#include "maplistmodels.h"
|
||||
#include "validator.h"
|
||||
#include "project.h"
|
||||
#include "filterchildrenproxymodel.h"
|
||||
|
||||
#include <QMouseEvent>
|
||||
#include <QLineEdit>
|
||||
|
||||
#include "project.h"
|
||||
#include "filterchildrenproxymodel.h"
|
||||
|
||||
|
||||
|
||||
void MapTree::removeSelected() {
|
||||
|
|
@ -38,8 +38,52 @@ void MapTree::keyPressEvent(QKeyEvent *event) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
MapListModel::MapListModel(Project *project, QObject *parent) : QStandardItemModel(parent) {
|
||||
this->project = project;
|
||||
this->root = invisibleRootItem();
|
||||
|
||||
this->mapGrayIcon = QIcon(QStringLiteral(":/icons/map_grayed.ico"));
|
||||
this->mapIcon = QIcon(QStringLiteral(":/icons/map.ico"));
|
||||
this->mapEditedIcon = QIcon(QStringLiteral(":/icons/map_edited.ico"));
|
||||
this->mapOpenedIcon = QIcon(QStringLiteral(":/icons/map_opened.ico"));
|
||||
|
||||
this->mapFolderIcon.addFile(QStringLiteral(":/icons/folder_closed_map.ico"), QSize(), QIcon::Normal, QIcon::Off);
|
||||
this->mapFolderIcon.addFile(QStringLiteral(":/icons/folder_map.ico"), QSize(), QIcon::Normal, QIcon::On);
|
||||
|
||||
this->emptyMapFolderIcon.addFile(QStringLiteral(":/icons/folder_closed.ico"), QSize(), QIcon::Normal, QIcon::Off);
|
||||
this->emptyMapFolderIcon.addFile(QStringLiteral(":/icons/folder.ico"), QSize(), QIcon::Normal, QIcon::On);
|
||||
}
|
||||
|
||||
QStandardItem *MapListModel::itemAt(const QModelIndex &index) const {
|
||||
if (index.isValid()) {
|
||||
QStandardItem *item = static_cast<QStandardItem*>(index.internalPointer());
|
||||
if (item)
|
||||
return item;
|
||||
}
|
||||
return this->root;
|
||||
}
|
||||
|
||||
QStandardItem *MapListModel::itemAt(const QString &itemName) const {
|
||||
QModelIndex index = this->indexOf(itemName);
|
||||
if (!index.isValid())
|
||||
return nullptr;
|
||||
return this->itemAt(index)->child(index.row(), index.column());
|
||||
}
|
||||
|
||||
QModelIndex MapListModel::indexOf(const QString &itemName) const {
|
||||
if (this->mapItems.contains(itemName))
|
||||
return this->mapItems.value(itemName)->index();
|
||||
|
||||
if (this->mapFolderItems.contains(itemName))
|
||||
return this->mapFolderItems.value(itemName)->index();
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
void MapListModel::removeItemAt(const QModelIndex &index) {
|
||||
QStandardItem *item = this->getItem(index)->child(index.row(), index.column());
|
||||
QStandardItem *item = this->itemAt(index)->child(index.row(), index.column());
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
|
|
@ -49,24 +93,106 @@ void MapListModel::removeItemAt(const QModelIndex &index) {
|
|||
} else {
|
||||
// TODO: Because there's no support for deleting maps we can only delete empty folders
|
||||
if (!item->hasChildren()) {
|
||||
this->removeItem(item);
|
||||
removeItem(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QStandardItem *MapListModel::createMapItem(const QString &mapName, QStandardItem *map) {
|
||||
if (!map) map = new QStandardItem;
|
||||
map->setText(mapName);
|
||||
map->setData(mapName, MapListUserRoles::NameRole);
|
||||
map->setData("map_name", MapListUserRoles::TypeRole);
|
||||
map->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemNeverHasChildren);
|
||||
map->setToolTip(this->project->mapNamesToMapConstants.value(mapName));
|
||||
this->mapItems.insert(mapName, map);
|
||||
return map;
|
||||
}
|
||||
|
||||
QStandardItem *MapListModel::createMapFolderItem(const QString &folderName, QStandardItem *folder) {
|
||||
if (!folder) folder = new QStandardItem;
|
||||
folder->setText(folderName);
|
||||
folder->setData(folderName, MapListUserRoles::NameRole);
|
||||
folder->setData(this->folderTypeName, MapListUserRoles::TypeRole);
|
||||
folder->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
|
||||
folder->setEditable(this->editable); // Will override flags if necessary
|
||||
this->mapFolderItems.insert(folderName, folder);
|
||||
return folder;
|
||||
}
|
||||
|
||||
QStandardItem *MapListModel::insertMapItem(const QString &mapName, const QString &folderName) {
|
||||
if (mapName.isEmpty() || mapName == this->project->getDynamicMapName()) // Disallow adding MAP_DYNAMIC to the map list.
|
||||
return nullptr;
|
||||
|
||||
QStandardItem *map = createMapItem(mapName);
|
||||
|
||||
QStandardItem *folder = this->mapFolderItems[folderName];
|
||||
if (!folder) {
|
||||
// Folder doesn't exist yet, add it.
|
||||
folder = insertMapFolderItem(folderName);
|
||||
}
|
||||
// If folder is still nullptr here it's because we failed to create it.
|
||||
if (folder) {
|
||||
folder->appendRow(map);
|
||||
}
|
||||
|
||||
if (this->sortingEnabled)
|
||||
this->sort(0, Qt::AscendingOrder);
|
||||
return map;
|
||||
}
|
||||
|
||||
QStandardItem *MapListModel::insertMapFolderItem(const QString &folderName) {
|
||||
if (folderName.isEmpty())
|
||||
return nullptr;
|
||||
|
||||
QStandardItem *item = createMapFolderItem(folderName);
|
||||
this->root->appendRow(item);
|
||||
if (this->sortingEnabled)
|
||||
this->sort(0, Qt::AscendingOrder);
|
||||
return item;
|
||||
}
|
||||
|
||||
QVariant MapListModel::data(const QModelIndex &index, int role) const {
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
int row = index.row();
|
||||
int col = index.column();
|
||||
|
||||
const QStandardItem *item = this->itemAt(index)->child(row, col);
|
||||
const QString type = item->data(MapListUserRoles::TypeRole).toString();
|
||||
const QString name = item->data(MapListUserRoles::NameRole).toString();
|
||||
|
||||
if (role == Qt::DecorationRole) {
|
||||
if (type == "map_name") {
|
||||
// Decorating map in the map list
|
||||
if (name == this->activeItemName)
|
||||
return this->mapOpenedIcon;
|
||||
|
||||
const Map* map = this->project->mapCache.value(name);
|
||||
if (!map)
|
||||
return this->mapGrayIcon;
|
||||
return map->hasUnsavedChanges() ? this->mapEditedIcon : this->mapIcon;
|
||||
} else if (type == this->folderTypeName) {
|
||||
// Decorating map folder in the map list
|
||||
return item->hasChildren() ? this->mapFolderIcon : this->emptyMapFolderIcon;
|
||||
}
|
||||
}
|
||||
return QStandardItemModel::data(index, role);
|
||||
}
|
||||
|
||||
|
||||
|
||||
QWidget *GroupNameDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const {
|
||||
QLineEdit *editor = new QLineEdit(parent);
|
||||
static const QRegularExpression expression("[A-Za-z_]+[\\w]*");
|
||||
editor->setPlaceholderText("gMapGroup_");
|
||||
editor->setValidator(new QRegularExpressionValidator(expression, parent));
|
||||
editor->setPlaceholderText(Project::getMapGroupPrefix());
|
||||
editor->setValidator(new IdentifierValidator(parent));
|
||||
editor->setFrame(false);
|
||||
return editor;
|
||||
}
|
||||
|
||||
void GroupNameDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {
|
||||
QString groupName = index.data(Qt::UserRole).toString();
|
||||
QString groupName = index.data(MapListUserRoles::NameRole).toString();
|
||||
QLineEdit *le = static_cast<QLineEdit *>(editor);
|
||||
le->setText(groupName);
|
||||
}
|
||||
|
|
@ -74,7 +200,7 @@ void GroupNameDelegate::setEditorData(QWidget *editor, const QModelIndex &index)
|
|||
void GroupNameDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
|
||||
QLineEdit *le = static_cast<QLineEdit *>(editor);
|
||||
QString groupName = le->text();
|
||||
model->setData(index, groupName, Qt::UserRole);
|
||||
model->setData(index, groupName, MapListUserRoles::NameRole);
|
||||
}
|
||||
|
||||
void GroupNameDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const {
|
||||
|
|
@ -83,11 +209,16 @@ void GroupNameDelegate::updateEditorGeometry(QWidget *editor, const QStyleOption
|
|||
|
||||
|
||||
|
||||
MapGroupModel::MapGroupModel(Project *project, QObject *parent) : MapListModel(parent) {
|
||||
this->project = project;
|
||||
this->root = this->invisibleRootItem();
|
||||
MapGroupModel::MapGroupModel(Project *project, QObject *parent) : MapListModel(project, parent) {
|
||||
this->folderTypeName = "map_group";
|
||||
this->editable = true;
|
||||
|
||||
initialize();
|
||||
for (const auto &groupName : this->project->groupNames) {
|
||||
insertMapFolderItem(groupName);
|
||||
for (const auto &mapName : this->project->groupNameToMapNames.value(groupName)) {
|
||||
insertMapItem(mapName, groupName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Qt::DropActions MapGroupModel::supportedDropActions() const {
|
||||
|
|
@ -112,7 +243,7 @@ QMimeData *MapGroupModel::mimeData(const QModelIndexList &indexes) const {
|
|||
// if dropping a selection containing a group(s) and map(s), clear all selection but first group.
|
||||
for (const QModelIndex &index : indexes) {
|
||||
if (index.isValid() && data(index, MapListUserRoles::TypeRole).toString() == "map_group") {
|
||||
QString groupName = data(index, Qt::UserRole).toString();
|
||||
QString groupName = data(index, MapListUserRoles::NameRole).toString();
|
||||
stream << groupName;
|
||||
mimeData->setData("application/porymap.mapgroupmodel.group", encodedData);
|
||||
mimeData->setData("application/porymap.mapgroupmodel.source.row", QByteArray::number(index.row()));
|
||||
|
|
@ -122,7 +253,7 @@ QMimeData *MapGroupModel::mimeData(const QModelIndexList &indexes) const {
|
|||
|
||||
for (const QModelIndex &index : indexes) {
|
||||
if (index.isValid()) {
|
||||
QString mapName = data(index, Qt::UserRole).toString();
|
||||
QString mapName = data(index, MapListUserRoles::NameRole).toString();
|
||||
stream << mapName;
|
||||
}
|
||||
}
|
||||
|
|
@ -168,12 +299,12 @@ bool MapGroupModel::dropMimeData(const QMimeData *data, Qt::DropAction action, i
|
|||
QStringList mapsToMove;
|
||||
for (int i = 0; i < this->rowCount(originIndex); ++i ) {
|
||||
children << this->index( i, 0, originIndex);
|
||||
mapsToMove << this->index( i, 0 , originIndex).data(Qt::UserRole).toString();
|
||||
mapsToMove << this->index( i, 0 , originIndex).data(MapListUserRoles::NameRole).toString();
|
||||
}
|
||||
|
||||
QModelIndex groupIndex = index(row, 0, parentIndex);
|
||||
QStandardItem *groupItem = this->itemFromIndex(groupIndex);
|
||||
createGroupItem(groupName, row, groupItem);
|
||||
createMapFolderItem(groupName, groupItem);
|
||||
|
||||
for (QString mapName : mapsToMove) {
|
||||
QStandardItem *mapItem = createMapItem(mapName);
|
||||
|
|
@ -224,177 +355,63 @@ bool MapGroupModel::dropMimeData(const QMimeData *data, Qt::DropAction action, i
|
|||
void MapGroupModel::updateProject() {
|
||||
if (!this->project) return;
|
||||
|
||||
QStringList groupNames;
|
||||
QMap<QString, int> mapGroups;
|
||||
QList<QStringList> groupedMapNames;
|
||||
// Temporary objects in case of failure, so we won't modify the project unless it succeeds.
|
||||
QStringList mapNames;
|
||||
QStringList groupNames;
|
||||
QMap<QString, QStringList> groupNameToMapNames;
|
||||
|
||||
for (int g = 0; g < this->root->rowCount(); g++) {
|
||||
QStandardItem *groupItem = this->item(g);
|
||||
QString groupName = groupItem->data(Qt::UserRole).toString();
|
||||
const QStandardItem *groupItem = this->item(g);
|
||||
QString groupName = groupItem->data(MapListUserRoles::NameRole).toString();
|
||||
groupNames.append(groupName);
|
||||
mapGroups[groupName] = g;
|
||||
QStringList mapsInGroup;
|
||||
for (int m = 0; m < groupItem->rowCount(); m++) {
|
||||
QStandardItem *mapItem = groupItem->child(m);
|
||||
const QStandardItem *mapItem = groupItem->child(m);
|
||||
if (!mapItem) {
|
||||
logError("An error occured while trying to apply updates to map group structure.");
|
||||
return;
|
||||
}
|
||||
QString mapName = mapItem->data(Qt::UserRole).toString();
|
||||
mapsInGroup.append(mapName);
|
||||
QString mapName = mapItem->data(MapListUserRoles::NameRole).toString();
|
||||
groupNameToMapNames[groupName].append(mapName);
|
||||
mapNames.append(mapName);
|
||||
}
|
||||
groupedMapNames.append(mapsInGroup);
|
||||
}
|
||||
|
||||
this->project->groupNames = groupNames;
|
||||
this->project->mapGroups = mapGroups;
|
||||
this->project->groupedMapNames = groupedMapNames;
|
||||
this->project->mapNames = mapNames;
|
||||
this->project->groupNames = groupNames;
|
||||
this->project->groupNameToMapNames = groupNameToMapNames;
|
||||
this->project->hasUnsavedDataChanges = true;
|
||||
}
|
||||
|
||||
QStandardItem *MapGroupModel::createGroupItem(QString groupName, int groupIndex, QStandardItem *group) {
|
||||
if (!group) group = new QStandardItem;
|
||||
group->setText(groupName);
|
||||
group->setData(groupName, Qt::UserRole);
|
||||
group->setData("map_group", MapListUserRoles::TypeRole);
|
||||
group->setData(groupIndex, MapListUserRoles::GroupRole);
|
||||
group->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsSelectable);
|
||||
this->groupItems.insert(groupName, group);
|
||||
return group;
|
||||
}
|
||||
|
||||
QStandardItem *MapGroupModel::createMapItem(QString mapName, QStandardItem *map) {
|
||||
if (!map) map = new QStandardItem;
|
||||
map->setData(mapName, Qt::UserRole);
|
||||
map->setData("map_name", MapListUserRoles::TypeRole);
|
||||
map->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
|
||||
this->mapItems[mapName] = map;
|
||||
return map;
|
||||
}
|
||||
|
||||
QStandardItem *MapGroupModel::insertGroupItem(QString groupName) {
|
||||
QStandardItem *group = createGroupItem(groupName, this->groupItems.size());
|
||||
this->root->appendRow(group);
|
||||
this->updateProject();
|
||||
return group;
|
||||
}
|
||||
|
||||
void MapGroupModel::removeItem(QStandardItem *item) {
|
||||
this->removeRow(item->row());
|
||||
this->updateProject();
|
||||
}
|
||||
|
||||
QStandardItem *MapGroupModel::insertMapItem(QString mapName, QString groupName) {
|
||||
QStandardItem *group = this->groupItems[groupName];
|
||||
if (!group) {
|
||||
group = insertGroupItem(groupName);
|
||||
}
|
||||
QStandardItem *map = createMapItem(mapName);
|
||||
group->appendRow(map);
|
||||
return map;
|
||||
}
|
||||
|
||||
void MapGroupModel::initialize() {
|
||||
this->groupItems.clear();
|
||||
this->mapItems.clear();
|
||||
for (int i = 0; i < this->project->groupNames.length(); i++) {
|
||||
QString group_name = this->project->groupNames.value(i);
|
||||
QStandardItem *group = createGroupItem(group_name, i);
|
||||
root->appendRow(group);
|
||||
QStringList names = this->project->groupedMapNames.value(i);
|
||||
for (int j = 0; j < names.length(); j++) {
|
||||
QString map_name = names.value(j);
|
||||
QStandardItem *map = createMapItem(map_name);
|
||||
group->appendRow(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QStandardItem *MapGroupModel::getItem(const QModelIndex &index) const {
|
||||
if (index.isValid()) {
|
||||
QStandardItem *item = static_cast<QStandardItem*>(index.internalPointer());
|
||||
if (item)
|
||||
return item;
|
||||
}
|
||||
return this->root;
|
||||
}
|
||||
|
||||
QModelIndex MapGroupModel::indexOf(QString mapName) const {
|
||||
if (this->mapItems.contains(mapName)) {
|
||||
return this->mapItems[mapName]->index();
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QVariant MapGroupModel::data(const QModelIndex &index, int role) const {
|
||||
if (!index.isValid()) return QVariant();
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
int row = index.row();
|
||||
int col = index.column();
|
||||
|
||||
if (role == Qt::DecorationRole) {
|
||||
static QIcon mapGrayIcon = QIcon(QStringLiteral(":/icons/map_grayed.ico"));
|
||||
static QIcon mapIcon = QIcon(QStringLiteral(":/icons/map.ico"));
|
||||
static QIcon mapEditedIcon = QIcon(QStringLiteral(":/icons/map_edited.ico"));
|
||||
static QIcon mapOpenedIcon = QIcon(QStringLiteral(":/icons/map_opened.ico"));
|
||||
|
||||
static QIcon mapFolderIcon;
|
||||
static QIcon folderIcon;
|
||||
static bool loaded = false;
|
||||
if (!loaded) {
|
||||
mapFolderIcon.addFile(QStringLiteral(":/icons/folder_closed_map.ico"), QSize(), QIcon::Normal, QIcon::Off);
|
||||
mapFolderIcon.addFile(QStringLiteral(":/icons/folder_map.ico"), QSize(), QIcon::Normal, QIcon::On);
|
||||
folderIcon.addFile(QStringLiteral(":/icons/folder_closed.ico"), QSize(), QIcon::Normal, QIcon::Off);
|
||||
folderIcon.addFile(QStringLiteral(":/icons/folder.ico"), QSize(), QIcon::Normal, QIcon::On);
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
QStandardItem *item = this->getItem(index)->child(row, col);
|
||||
QString type = item->data(MapListUserRoles::TypeRole).toString();
|
||||
|
||||
if (type == "map_group") {
|
||||
if (!item->hasChildren()) {
|
||||
return folderIcon;
|
||||
}
|
||||
return mapFolderIcon;
|
||||
} else if (type == "map_name") {
|
||||
QString mapName = item->data(Qt::UserRole).toString();
|
||||
if (mapName == this->openMap) {
|
||||
return mapOpenedIcon;
|
||||
}
|
||||
else if (this->project->mapCache.contains(mapName)) {
|
||||
if (this->project->mapCache.value(mapName)->hasUnsavedChanges()) {
|
||||
return mapEditedIcon;
|
||||
}
|
||||
else {
|
||||
return mapIcon;
|
||||
}
|
||||
}
|
||||
return mapGrayIcon;
|
||||
}
|
||||
}
|
||||
else if (role == Qt::DisplayRole) {
|
||||
QStandardItem *item = this->getItem(index)->child(row, col);
|
||||
QString type = item->data(MapListUserRoles::TypeRole).toString();
|
||||
const QStandardItem *item = this->itemAt(index)->child(row, col);
|
||||
const QString type = item->data(MapListUserRoles::TypeRole).toString();
|
||||
const QString name = item->data(MapListUserRoles::NameRole).toString();
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
if (type == "map_name") {
|
||||
return QString("[%1.%2] ").arg(this->getItem(index)->row()).arg(row, 2, 10, QLatin1Char('0')) + item->data(Qt::UserRole).toString();
|
||||
return QString("[%1.%2] ").arg(this->itemAt(index)->row()).arg(row, 2, 10, QLatin1Char('0')) + name;
|
||||
}
|
||||
else if (type == "map_group") {
|
||||
return item->data(Qt::UserRole).toString();
|
||||
else if (type == this->folderTypeName) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
return QStandardItemModel::data(index, role);
|
||||
return MapListModel::data(index, role);
|
||||
}
|
||||
|
||||
bool MapGroupModel::setData(const QModelIndex &index, const QVariant &value, int role) {
|
||||
if (role == Qt::UserRole && data(index, MapListUserRoles::TypeRole).toString() == "map_group") {
|
||||
// verify uniqueness of new group name
|
||||
if (this->project->groupNames.contains(value.toString())) {
|
||||
if (role == MapListUserRoles::NameRole && data(index, MapListUserRoles::TypeRole).toString() == "map_group") {
|
||||
if (!this->project->isIdentifierUnique(value.toString())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -406,287 +423,87 @@ bool MapGroupModel::setData(const QModelIndex &index, const QVariant &value, int
|
|||
|
||||
|
||||
|
||||
MapAreaModel::MapAreaModel(Project *project, QObject *parent) : MapListModel(parent) {
|
||||
this->project = project;
|
||||
this->root = this->invisibleRootItem();
|
||||
MapLocationModel::MapLocationModel(Project *project, QObject *parent) : MapListModel(project, parent) {
|
||||
this->folderTypeName = "map_section";
|
||||
|
||||
initialize();
|
||||
}
|
||||
|
||||
QStandardItem *MapAreaModel::createAreaItem(QString mapsecName) {
|
||||
QStandardItem *area = new QStandardItem;
|
||||
area->setText(mapsecName);
|
||||
area->setEditable(false);
|
||||
area->setData(mapsecName, Qt::UserRole);
|
||||
area->setData("map_section", MapListUserRoles::TypeRole);
|
||||
// group->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
|
||||
this->areaItems.insert(mapsecName, area);
|
||||
return area;
|
||||
}
|
||||
|
||||
QStandardItem *MapAreaModel::createMapItem(QString mapName, int, int) {
|
||||
QStandardItem *map = new QStandardItem;
|
||||
map->setText(mapName);
|
||||
map->setEditable(false);
|
||||
map->setData(mapName, Qt::UserRole);
|
||||
map->setData("map_name", MapListUserRoles::TypeRole);
|
||||
// map->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
|
||||
this->mapItems.insert(mapName, map);
|
||||
return map;
|
||||
}
|
||||
|
||||
QStandardItem *MapAreaModel::insertAreaItem(QString areaName) {
|
||||
this->project->addNewMapsec(areaName);
|
||||
QStandardItem *item = createAreaItem(areaName);
|
||||
this->root->appendRow(item);
|
||||
this->sort(0, Qt::AscendingOrder);
|
||||
return item;
|
||||
}
|
||||
|
||||
QStandardItem *MapAreaModel::insertMapItem(QString mapName, QString areaName, int groupIndex) {
|
||||
QStandardItem *area = this->areaItems[areaName];
|
||||
if (!area) {
|
||||
return nullptr;
|
||||
for (const auto &idName : this->project->mapSectionIdNames) {
|
||||
insertMapFolderItem(idName);
|
||||
}
|
||||
int mapIndex = area->rowCount();
|
||||
QStandardItem *map = createMapItem(mapName, groupIndex, mapIndex);
|
||||
area->appendRow(map);
|
||||
return map;
|
||||
for (const auto &mapName : this->project->mapNames) {
|
||||
insertMapItem(mapName, this->project->mapNameToMapSectionName.value(mapName));
|
||||
}
|
||||
|
||||
this->sortingEnabled = true;
|
||||
sort(0, Qt::AscendingOrder);
|
||||
}
|
||||
|
||||
void MapAreaModel::removeItem(QStandardItem *item) {
|
||||
this->project->removeMapsec(item->data(Qt::UserRole).toString());
|
||||
void MapLocationModel::removeItem(QStandardItem *item) {
|
||||
this->project->removeMapsec(item->data(MapListUserRoles::NameRole).toString());
|
||||
this->removeRow(item->row());
|
||||
}
|
||||
|
||||
void MapAreaModel::initialize() {
|
||||
this->areaItems.clear();
|
||||
this->mapItems.clear();
|
||||
|
||||
for (const auto &idName : this->project->mapSectionIdNames) {
|
||||
this->root->appendRow(createAreaItem(idName));
|
||||
}
|
||||
|
||||
for (int i = 0; i < this->project->groupNames.length(); i++) {
|
||||
QStringList names = this->project->groupedMapNames.value(i);
|
||||
for (int j = 0; j < names.length(); j++) {
|
||||
QString mapName = names.value(j);
|
||||
QStandardItem *map = createMapItem(mapName, i, j);
|
||||
QString mapsecName = this->project->readMapLocation(mapName);
|
||||
if (this->areaItems.contains(mapsecName)) {
|
||||
this->areaItems[mapsecName]->appendRow(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
this->sort(0, Qt::AscendingOrder);
|
||||
}
|
||||
|
||||
QStandardItem *MapAreaModel::getItem(const QModelIndex &index) const {
|
||||
if (index.isValid()) {
|
||||
QStandardItem *item = static_cast<QStandardItem*>(index.internalPointer());
|
||||
if (item)
|
||||
return item;
|
||||
}
|
||||
return this->root;
|
||||
}
|
||||
|
||||
QModelIndex MapAreaModel::indexOf(QString mapName) const {
|
||||
if (this->mapItems.contains(mapName)) {
|
||||
return this->mapItems[mapName]->index();
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QVariant MapAreaModel::data(const QModelIndex &index, int role) const {
|
||||
if (!index.isValid()) return QVariant();
|
||||
|
||||
int row = index.row();
|
||||
int col = index.column();
|
||||
|
||||
if (role == Qt::DecorationRole) {
|
||||
static QIcon mapGrayIcon = QIcon(QStringLiteral(":/icons/map_grayed.ico"));
|
||||
static QIcon mapIcon = QIcon(QStringLiteral(":/icons/map.ico"));
|
||||
static QIcon mapEditedIcon = QIcon(QStringLiteral(":/icons/map_edited.ico"));
|
||||
static QIcon mapOpenedIcon = QIcon(QStringLiteral(":/icons/map_opened.ico"));
|
||||
|
||||
static QIcon mapFolderIcon;
|
||||
static QIcon folderIcon;
|
||||
static bool loaded = false;
|
||||
if (!loaded) {
|
||||
mapFolderIcon.addFile(QStringLiteral(":/icons/folder_closed_map.ico"), QSize(), QIcon::Normal, QIcon::Off);
|
||||
mapFolderIcon.addFile(QStringLiteral(":/icons/folder_map.ico"), QSize(), QIcon::Normal, QIcon::On);
|
||||
folderIcon.addFile(QStringLiteral(":/icons/folder_closed.ico"), QSize(), QIcon::Normal, QIcon::Off);
|
||||
folderIcon.addFile(QStringLiteral(":/icons/folder.ico"), QSize(), QIcon::Normal, QIcon::On);
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
QStandardItem *item = this->getItem(index)->child(row, col);
|
||||
QString type = item->data(MapListUserRoles::TypeRole).toString();
|
||||
|
||||
if (type == "map_section") {
|
||||
if (item->hasChildren()) {
|
||||
return mapFolderIcon;
|
||||
}
|
||||
return folderIcon;
|
||||
} else if (type == "map_name") {
|
||||
QString mapName = item->data(Qt::UserRole).toString();
|
||||
if (mapName == this->openMap) {
|
||||
return mapOpenedIcon;
|
||||
}
|
||||
else if (this->project->mapCache.contains(mapName)) {
|
||||
if (this->project->mapCache.value(mapName)->hasUnsavedChanges()) {
|
||||
return mapEditedIcon;
|
||||
}
|
||||
else {
|
||||
return mapIcon;
|
||||
}
|
||||
}
|
||||
return mapGrayIcon;
|
||||
}
|
||||
}
|
||||
else if (role == Qt::DisplayRole) {
|
||||
QStandardItem *item = this->getItem(index)->child(row, col);
|
||||
QString type = item->data(MapListUserRoles::TypeRole).toString();
|
||||
|
||||
if (type == "map_section") {
|
||||
return item->data(Qt::UserRole).toString();
|
||||
}
|
||||
}
|
||||
|
||||
return QStandardItemModel::data(index, role);
|
||||
QStandardItem *MapLocationModel::createMapFolderItem(const QString &folderName, QStandardItem *folder) {
|
||||
folder = MapListModel::createMapFolderItem(folderName, folder);
|
||||
folder->setToolTip(this->project->getMapsecDisplayName(folderName));
|
||||
return folder;
|
||||
}
|
||||
|
||||
|
||||
|
||||
LayoutTreeModel::LayoutTreeModel(Project *project, QObject *parent) : MapListModel(parent) {
|
||||
this->project = project;
|
||||
this->root = this->invisibleRootItem();
|
||||
LayoutTreeModel::LayoutTreeModel(Project *project, QObject *parent) : MapListModel(project, parent) {
|
||||
this->folderTypeName = "map_layout";
|
||||
|
||||
initialize();
|
||||
}
|
||||
|
||||
QStandardItem *LayoutTreeModel::createLayoutItem(QString layoutId) {
|
||||
QStandardItem *layout = new QStandardItem;
|
||||
layout->setText(this->project->layoutIdsToNames[layoutId]);
|
||||
layout->setEditable(false);
|
||||
layout->setData(layoutId, Qt::UserRole);
|
||||
layout->setData("map_layout", MapListUserRoles::TypeRole);
|
||||
// // group->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
|
||||
this->layoutItems.insert(layoutId, layout);
|
||||
return layout;
|
||||
}
|
||||
|
||||
QStandardItem *LayoutTreeModel::createMapItem(QString mapName) {
|
||||
QStandardItem *map = new QStandardItem;
|
||||
map->setText(mapName);
|
||||
map->setEditable(false);
|
||||
map->setData(mapName, Qt::UserRole);
|
||||
map->setData("map_name", MapListUserRoles::TypeRole);
|
||||
map->setFlags(Qt::NoItemFlags | Qt::ItemNeverHasChildren);
|
||||
this->mapItems.insert(mapName, map);
|
||||
return map;
|
||||
}
|
||||
|
||||
QStandardItem *LayoutTreeModel::insertLayoutItem(QString layoutId) {
|
||||
QStandardItem *layoutItem = this->createLayoutItem(layoutId);
|
||||
this->root->appendRow(layoutItem);
|
||||
this->sort(0, Qt::AscendingOrder);
|
||||
return layoutItem;
|
||||
}
|
||||
|
||||
QStandardItem *LayoutTreeModel::insertMapItem(QString mapName, QString layoutId) {
|
||||
QStandardItem *layout = nullptr;
|
||||
if (this->layoutItems.contains(layoutId)) {
|
||||
layout = this->layoutItems[layoutId];
|
||||
for (const auto &layoutId : this->project->layoutIds) {
|
||||
insertMapFolderItem(layoutId);
|
||||
}
|
||||
else {
|
||||
layout = createLayoutItem(layoutId);
|
||||
this->root->appendRow(layout);
|
||||
for (const auto &mapName : this->project->mapNames) {
|
||||
insertMapItem(mapName, this->project->mapNameToLayoutId.value(mapName));
|
||||
}
|
||||
if (!layout) {
|
||||
return nullptr;
|
||||
}
|
||||
QStandardItem *map = createMapItem(mapName);
|
||||
layout->appendRow(map);
|
||||
return map;
|
||||
|
||||
this->sortingEnabled = true;
|
||||
sort(0, Qt::AscendingOrder);
|
||||
}
|
||||
|
||||
void LayoutTreeModel::removeItem(QStandardItem *) {
|
||||
// TODO: Deleting layouts not supported
|
||||
}
|
||||
|
||||
QStandardItem *LayoutTreeModel::createMapFolderItem(const QString &folderName, QStandardItem *folder) {
|
||||
folder = MapListModel::createMapFolderItem(folderName, folder);
|
||||
|
||||
void LayoutTreeModel::initialize() {
|
||||
this->layoutItems.clear();
|
||||
this->mapItems.clear();
|
||||
for (int i = 0; i < this->project->mapLayoutsTable.length(); i++) {
|
||||
QString layoutId = project->mapLayoutsTable.value(i);
|
||||
QStandardItem *layoutItem = createLayoutItem(layoutId);
|
||||
this->root->appendRow(layoutItem);
|
||||
}
|
||||
// Despite using layout IDs internally, the Layouts map list shows layouts using their file path name.
|
||||
// We could handle this with Qt::DisplayRole in LayoutTreeModel::data, but then it would be sorted using the ID instead of the name.
|
||||
const Layout* layout = this->project->mapLayouts.value(folderName);
|
||||
if (layout) folder->setText(layout->name);
|
||||
|
||||
for (auto mapList : this->project->groupedMapNames) {
|
||||
for (auto mapName : mapList) {
|
||||
QString layoutId = project->readMapLayoutId(mapName);
|
||||
QStandardItem *map = createMapItem(mapName);
|
||||
this->layoutItems[layoutId]->appendRow(map);
|
||||
}
|
||||
}
|
||||
this->sort(0, Qt::AscendingOrder);
|
||||
}
|
||||
// The layout ID will instead be shown as a tool tip.
|
||||
folder->setToolTip(folderName);
|
||||
|
||||
QStandardItem *LayoutTreeModel::getItem(const QModelIndex &index) const {
|
||||
if (index.isValid()) {
|
||||
QStandardItem *item = static_cast<QStandardItem*>(index.internalPointer());
|
||||
if (item)
|
||||
return item;
|
||||
}
|
||||
return this->root;
|
||||
}
|
||||
|
||||
QModelIndex LayoutTreeModel::indexOf(QString layoutName) const {
|
||||
if (this->layoutItems.contains(layoutName)) {
|
||||
return this->layoutItems[layoutName]->index();
|
||||
}
|
||||
return QModelIndex();
|
||||
return folder;
|
||||
}
|
||||
|
||||
QVariant LayoutTreeModel::data(const QModelIndex &index, int role) const {
|
||||
if (!index.isValid()) return QVariant();
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
int row = index.row();
|
||||
int col = index.column();
|
||||
|
||||
if (role == Qt::DecorationRole) {
|
||||
static QIcon mapGrayIcon = QIcon(QStringLiteral(":/icons/map_grayed.ico"));
|
||||
static QIcon mapIcon = QIcon(QStringLiteral(":/icons/map.ico"));
|
||||
static QIcon mapEditedIcon = QIcon(QStringLiteral(":/icons/map_edited.ico"));
|
||||
static QIcon mapOpenedIcon = QIcon(QStringLiteral(":/icons/map_opened.ico"));
|
||||
const QStandardItem *item = this->itemAt(index)->child(row, col);
|
||||
const QString type = item->data(MapListUserRoles::TypeRole).toString();
|
||||
const QString name = item->data(MapListUserRoles::NameRole).toString();
|
||||
|
||||
QStandardItem *item = this->getItem(index)->child(row, col);
|
||||
QString type = item->data(MapListUserRoles::TypeRole).toString();
|
||||
if (type == this->folderTypeName) {
|
||||
if (role == Qt::DecorationRole) {
|
||||
// Map layouts are used as folders, but we display them with the same icons as maps.
|
||||
if (name == this->activeItemName)
|
||||
return this->mapOpenedIcon;
|
||||
|
||||
if (type == "map_layout") {
|
||||
QString layoutId = item->data(Qt::UserRole).toString();
|
||||
if (layoutId == this->openLayout) {
|
||||
return mapOpenedIcon;
|
||||
}
|
||||
else if (this->project->mapLayouts.contains(layoutId)) {
|
||||
if (this->project->mapLayouts.value(layoutId)->hasUnsavedChanges()) {
|
||||
return mapEditedIcon;
|
||||
}
|
||||
else if (!this->project->mapLayouts[layoutId]->loaded) {
|
||||
return mapGrayIcon;
|
||||
}
|
||||
}
|
||||
return mapIcon;
|
||||
const Layout* layout = this->project->mapLayouts.value(name);
|
||||
if (!layout || !layout->loaded)
|
||||
return this->mapGrayIcon;
|
||||
return layout->hasUnsavedChanges() ? this->mapEditedIcon : this->mapIcon;
|
||||
}
|
||||
else if (type == "map_name") {
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
return QStandardItemModel::data(index, role);
|
||||
return MapListModel::data(index, role);
|
||||
}
|
||||
|
|
|
|||
78
src/ui/message.cpp
Normal file
78
src/ui/message.cpp
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#include "message.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
Message::Message(QMessageBox::Icon icon, const QString &text, QMessageBox::StandardButtons buttons, QWidget *parent) :
|
||||
QMessageBox(icon, QApplication::applicationName(), text, buttons, parent)
|
||||
{
|
||||
setWindowModality(Qt::WindowModal);
|
||||
}
|
||||
|
||||
ErrorMessage::ErrorMessage(const QString &message, QWidget *parent) :
|
||||
Message(QMessageBox::Critical,
|
||||
message,
|
||||
QMessageBox::Ok,
|
||||
parent)
|
||||
{
|
||||
setDefaultButton(QMessageBox::Ok);
|
||||
}
|
||||
|
||||
WarningMessage::WarningMessage(const QString &message, QWidget *parent) :
|
||||
Message(QMessageBox::Warning,
|
||||
message,
|
||||
QMessageBox::Ok,
|
||||
parent)
|
||||
{
|
||||
setDefaultButton(QMessageBox::Ok);
|
||||
}
|
||||
|
||||
InfoMessage::InfoMessage(const QString &message, QWidget *parent) :
|
||||
Message(QMessageBox::Information,
|
||||
message,
|
||||
QMessageBox::Close,
|
||||
parent)
|
||||
{
|
||||
setDefaultButton(QMessageBox::Close);
|
||||
}
|
||||
|
||||
QuestionMessage::QuestionMessage(const QString &message, QWidget *parent) :
|
||||
Message(QMessageBox::Question,
|
||||
message,
|
||||
QMessageBox::No | QMessageBox::Yes,
|
||||
parent)
|
||||
{
|
||||
setDefaultButton(QMessageBox::No);
|
||||
}
|
||||
|
||||
RecentErrorMessage::RecentErrorMessage(const QString &message, QWidget *parent) :
|
||||
ErrorMessage(message, parent)
|
||||
{
|
||||
setInformativeText(QString("Please see %1 for full error details.").arg(getLogPath()));
|
||||
setDetailedText(getMostRecentError());
|
||||
}
|
||||
|
||||
int RecentErrorMessage::show(const QString &message, QWidget *parent) {
|
||||
RecentErrorMessage msgBox(message, parent);
|
||||
return msgBox.exec();
|
||||
};
|
||||
|
||||
int ErrorMessage::show(const QString &message, QWidget *parent) {
|
||||
ErrorMessage msgBox(message, parent);
|
||||
return msgBox.exec();
|
||||
};
|
||||
|
||||
int WarningMessage::show(const QString &message, QWidget *parent) {
|
||||
WarningMessage msgBox(message, parent);
|
||||
return msgBox.exec();
|
||||
};
|
||||
|
||||
int QuestionMessage::show(const QString &message, QWidget *parent) {
|
||||
QuestionMessage msgBox(message, parent);
|
||||
return msgBox.exec();
|
||||
};
|
||||
|
||||
int InfoMessage::show(const QString &message, QWidget *parent) {
|
||||
InfoMessage msgBox(message, parent);
|
||||
return msgBox.exec();
|
||||
};
|
||||
164
src/ui/newlayoutdialog.cpp
Normal file
164
src/ui/newlayoutdialog.cpp
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
#include "newlayoutdialog.h"
|
||||
#include "maplayout.h"
|
||||
#include "ui_newlayoutdialog.h"
|
||||
#include "config.h"
|
||||
#include "validator.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QSet>
|
||||
#include <QStringList>
|
||||
|
||||
const QString lineEdit_ErrorStylesheet = "QLineEdit { background-color: rgba(255, 0, 0, 25%) }";
|
||||
|
||||
NewLayoutDialog::NewLayoutDialog(Project *project, QWidget *parent) :
|
||||
NewLayoutDialog(project, nullptr, parent)
|
||||
{}
|
||||
|
||||
NewLayoutDialog::NewLayoutDialog(Project *project, const Layout *layoutToCopy, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::NewLayoutDialog),
|
||||
layoutToCopy(layoutToCopy)
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
ui->setupUi(this);
|
||||
this->project = project;
|
||||
Layout::Settings *settings = &project->newLayoutSettings;
|
||||
|
||||
// Note: 'layoutToCopy' will have an empty name if it's an import from AdvanceMap
|
||||
if (this->layoutToCopy && !this->layoutToCopy->name.isEmpty()) {
|
||||
settings->name = project->toUniqueIdentifier(this->layoutToCopy->name);
|
||||
} else {
|
||||
settings->name = QString();
|
||||
}
|
||||
// Generate a unique Layout constant
|
||||
settings->id = project->toUniqueIdentifier(Layout::layoutConstantFromName(settings->name));
|
||||
|
||||
ui->newLayoutForm->initUi(project);
|
||||
|
||||
auto validator = new IdentifierValidator(this);
|
||||
ui->lineEdit_Name->setValidator(validator);
|
||||
ui->lineEdit_LayoutID->setValidator(validator);
|
||||
|
||||
connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &NewLayoutDialog::dialogButtonClicked);
|
||||
|
||||
refresh();
|
||||
|
||||
if (porymapConfig.newLayoutDialogGeometry.isEmpty()){
|
||||
// On first display resize to fit contents a little better
|
||||
adjustSize();
|
||||
} else {
|
||||
restoreGeometry(porymapConfig.newLayoutDialogGeometry);
|
||||
}
|
||||
}
|
||||
|
||||
NewLayoutDialog::~NewLayoutDialog()
|
||||
{
|
||||
porymapConfig.newLayoutDialogGeometry = saveGeometry();
|
||||
saveSettings();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void NewLayoutDialog::refresh() {
|
||||
const Layout::Settings *settings = &this->project->newLayoutSettings;
|
||||
|
||||
if (this->layoutToCopy) {
|
||||
// If we're importing a layout then some settings will be enforced.
|
||||
ui->newLayoutForm->setSettings(this->layoutToCopy->settings());
|
||||
ui->newLayoutForm->setDisabled(true);
|
||||
} else {
|
||||
ui->newLayoutForm->setSettings(*settings);
|
||||
ui->newLayoutForm->setDisabled(false);
|
||||
}
|
||||
|
||||
ui->lineEdit_Name->setText(settings->name);
|
||||
ui->lineEdit_LayoutID->setText(settings->id);
|
||||
}
|
||||
|
||||
void NewLayoutDialog::saveSettings() {
|
||||
Layout::Settings *settings = &this->project->newLayoutSettings;
|
||||
|
||||
*settings = ui->newLayoutForm->settings();
|
||||
settings->id = ui->lineEdit_LayoutID->text();
|
||||
settings->name = ui->lineEdit_Name->text();
|
||||
}
|
||||
|
||||
bool NewLayoutDialog::validateLayoutID(bool allowEmpty) {
|
||||
QString id = ui->lineEdit_LayoutID->text();
|
||||
|
||||
QString errorText;
|
||||
if (id.isEmpty()) {
|
||||
if (!allowEmpty) errorText = QString("%1 cannot be empty.").arg(ui->label_LayoutID->text());
|
||||
} else if (!this->project->isIdentifierUnique(id)) {
|
||||
errorText = QString("%1 '%2' is not unique.").arg(ui->label_LayoutID->text()).arg(id);
|
||||
}
|
||||
|
||||
bool isValid = errorText.isEmpty();
|
||||
ui->label_LayoutIDError->setText(errorText);
|
||||
ui->label_LayoutIDError->setVisible(!isValid);
|
||||
ui->lineEdit_LayoutID->setStyleSheet(!isValid ? lineEdit_ErrorStylesheet : "");
|
||||
return isValid;
|
||||
}
|
||||
|
||||
void NewLayoutDialog::on_lineEdit_LayoutID_textChanged(const QString &) {
|
||||
validateLayoutID(true);
|
||||
}
|
||||
|
||||
bool NewLayoutDialog::validateName(bool allowEmpty) {
|
||||
QString name = ui->lineEdit_Name->text();
|
||||
|
||||
QString errorText;
|
||||
if (name.isEmpty()) {
|
||||
if (!allowEmpty) errorText = QString("%1 cannot be empty.").arg(ui->label_Name->text());
|
||||
} else if (!this->project->isIdentifierUnique(name)) {
|
||||
errorText = QString("%1 '%2' is not unique.").arg(ui->label_Name->text()).arg(name);
|
||||
}
|
||||
|
||||
bool isValid = errorText.isEmpty();
|
||||
ui->label_NameError->setText(errorText);
|
||||
ui->label_NameError->setVisible(!isValid);
|
||||
ui->lineEdit_Name->setStyleSheet(!isValid ? lineEdit_ErrorStylesheet : "");
|
||||
return isValid;
|
||||
}
|
||||
|
||||
void NewLayoutDialog::on_lineEdit_Name_textChanged(const QString &text) {
|
||||
validateName(true);
|
||||
|
||||
// Changing the layout name updates the layout ID field to match.
|
||||
ui->lineEdit_LayoutID->setText(Layout::layoutConstantFromName(text));
|
||||
}
|
||||
|
||||
void NewLayoutDialog::dialogButtonClicked(QAbstractButton *button) {
|
||||
auto role = ui->buttonBox->buttonRole(button);
|
||||
if (role == QDialogButtonBox::RejectRole){
|
||||
reject();
|
||||
} else if (role == QDialogButtonBox::ResetRole) {
|
||||
this->project->initNewLayoutSettings();
|
||||
refresh();
|
||||
} else if (role == QDialogButtonBox::AcceptRole) {
|
||||
accept();
|
||||
}
|
||||
}
|
||||
|
||||
void NewLayoutDialog::accept() {
|
||||
// Make sure to call each validation function so that all errors are shown at once.
|
||||
bool success = true;
|
||||
if (!ui->newLayoutForm->validate()) success = false;
|
||||
if (!validateLayoutID()) success = false;
|
||||
if (!validateName()) success = false;
|
||||
if (!success)
|
||||
return;
|
||||
|
||||
// Update settings from UI
|
||||
saveSettings();
|
||||
|
||||
Layout *layout = this->project->createNewLayout(this->project->newLayoutSettings, this->layoutToCopy);
|
||||
if (!layout) {
|
||||
ui->label_GenericError->setText(QString("Failed to create layout. See %1 for details.").arg(getLogPath()));
|
||||
ui->label_GenericError->setVisible(true);
|
||||
return;
|
||||
}
|
||||
ui->label_GenericError->setVisible(false);
|
||||
|
||||
emit applied(layout->id);
|
||||
QDialog::accept();
|
||||
}
|
||||
144
src/ui/newlayoutform.cpp
Normal file
144
src/ui/newlayoutform.cpp
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
#include "newlayoutform.h"
|
||||
#include "ui_newlayoutform.h"
|
||||
#include "project.h"
|
||||
|
||||
const QString lineEdit_ErrorStylesheet = "QLineEdit { background-color: rgba(255, 0, 0, 25%) }";
|
||||
|
||||
NewLayoutForm::NewLayoutForm(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, ui(new Ui::NewLayoutForm)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->groupBox_BorderDimensions->setVisible(projectConfig.useCustomBorderSize);
|
||||
|
||||
ui->spinBox_BorderWidth->setMaximum(MAX_BORDER_WIDTH);
|
||||
ui->spinBox_BorderHeight->setMaximum(MAX_BORDER_HEIGHT);
|
||||
|
||||
connect(ui->spinBox_MapWidth, QOverload<int>::of(&QSpinBox::valueChanged), [=](int){ validateMapDimensions(); });
|
||||
connect(ui->spinBox_MapHeight, QOverload<int>::of(&QSpinBox::valueChanged), [=](int){ validateMapDimensions(); });
|
||||
|
||||
connect(ui->comboBox_PrimaryTileset->lineEdit(), &QLineEdit::editingFinished, [this]{ validatePrimaryTileset(true); });
|
||||
connect(ui->comboBox_SecondaryTileset->lineEdit(), &QLineEdit::editingFinished, [this]{ validateSecondaryTileset(true); });
|
||||
}
|
||||
|
||||
NewLayoutForm::~NewLayoutForm()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void NewLayoutForm::initUi(Project *project) {
|
||||
m_project = project;
|
||||
|
||||
ui->comboBox_PrimaryTileset->clear();
|
||||
ui->comboBox_SecondaryTileset->clear();
|
||||
|
||||
if (m_project) {
|
||||
ui->comboBox_PrimaryTileset->addItems(m_project->primaryTilesetLabels);
|
||||
ui->comboBox_SecondaryTileset->addItems(m_project->secondaryTilesetLabels);
|
||||
|
||||
ui->spinBox_MapWidth->setMaximum(m_project->getMaxMapWidth());
|
||||
ui->spinBox_MapHeight->setMaximum(m_project->getMaxMapHeight());
|
||||
}
|
||||
}
|
||||
|
||||
void NewLayoutForm::setDisabled(bool disabled) {
|
||||
ui->groupBox_MapDimensions->setDisabled(disabled);
|
||||
ui->groupBox_BorderDimensions->setDisabled(disabled);
|
||||
ui->groupBox_Tilesets->setDisabled(disabled);
|
||||
}
|
||||
|
||||
void NewLayoutForm::setSettings(const Layout::Settings &settings) {
|
||||
ui->spinBox_MapWidth->setValue(settings.width);
|
||||
ui->spinBox_MapHeight->setValue(settings.height);
|
||||
ui->spinBox_BorderWidth->setValue(settings.borderWidth);
|
||||
ui->spinBox_BorderHeight->setValue(settings.borderHeight);
|
||||
ui->comboBox_PrimaryTileset->setTextItem(settings.primaryTilesetLabel);
|
||||
ui->comboBox_SecondaryTileset->setTextItem(settings.secondaryTilesetLabel);
|
||||
}
|
||||
|
||||
Layout::Settings NewLayoutForm::settings() const {
|
||||
Layout::Settings settings;
|
||||
settings.width = ui->spinBox_MapWidth->value();
|
||||
settings.height = ui->spinBox_MapHeight->value();
|
||||
if (ui->groupBox_BorderDimensions->isVisible()) {
|
||||
settings.borderWidth = ui->spinBox_BorderWidth->value();
|
||||
settings.borderHeight = ui->spinBox_BorderHeight->value();
|
||||
} else {
|
||||
settings.borderWidth = DEFAULT_BORDER_WIDTH;
|
||||
settings.borderHeight = DEFAULT_BORDER_HEIGHT;
|
||||
}
|
||||
settings.primaryTilesetLabel = ui->comboBox_PrimaryTileset->currentText();
|
||||
settings.secondaryTilesetLabel = ui->comboBox_SecondaryTileset->currentText();
|
||||
return settings;
|
||||
}
|
||||
|
||||
bool NewLayoutForm::validate() {
|
||||
// Make sure to call each validation function so that all errors are shown at once.
|
||||
bool valid = true;
|
||||
if (!validateMapDimensions()) valid = false;
|
||||
if (!validatePrimaryTileset()) valid = false;
|
||||
if (!validateSecondaryTileset()) valid = false;
|
||||
return valid;
|
||||
}
|
||||
|
||||
bool NewLayoutForm::validateMapDimensions() {
|
||||
int size = m_project->getMapDataSize(ui->spinBox_MapWidth->value(), ui->spinBox_MapHeight->value());
|
||||
int maxSize = m_project->getMaxMapDataSize();
|
||||
|
||||
// TODO: Get from project
|
||||
const int additionalWidth = 15;
|
||||
const int additionalHeight = 14;
|
||||
|
||||
QString errorText;
|
||||
if (size > maxSize) {
|
||||
errorText = QString("The specified width and height are too large.\n"
|
||||
"The maximum map width and height is the following: (width + %1) * (height + %2) <= %3\n"
|
||||
"The specified map width and height was: (%4 + %1) * (%5 + %2) = %6")
|
||||
.arg(additionalWidth)
|
||||
.arg(additionalHeight)
|
||||
.arg(maxSize)
|
||||
.arg(ui->spinBox_MapWidth->value())
|
||||
.arg(ui->spinBox_MapHeight->value())
|
||||
.arg(size);
|
||||
}
|
||||
|
||||
bool isValid = errorText.isEmpty();
|
||||
ui->label_MapDimensionsError->setText(errorText);
|
||||
ui->label_MapDimensionsError->setVisible(!isValid);
|
||||
return isValid;
|
||||
}
|
||||
|
||||
bool NewLayoutForm::validatePrimaryTileset(bool allowEmpty) {
|
||||
const QString name = ui->comboBox_PrimaryTileset->currentText();
|
||||
|
||||
QString errorText;
|
||||
if (name.isEmpty()) {
|
||||
if (!allowEmpty) errorText = QString("The Primary Tileset cannot be empty.");
|
||||
} else if (ui->comboBox_PrimaryTileset->findText(name) < 0) {
|
||||
errorText = QString("The Primary Tileset '%1' does not exist.").arg(ui->label_PrimaryTileset->text()).arg(name);
|
||||
}
|
||||
|
||||
bool isValid = errorText.isEmpty();
|
||||
ui->label_PrimaryTilesetError->setText(errorText);
|
||||
ui->label_PrimaryTilesetError->setVisible(!isValid);
|
||||
ui->comboBox_PrimaryTileset->lineEdit()->setStyleSheet(!isValid ? lineEdit_ErrorStylesheet : "");
|
||||
return isValid;
|
||||
}
|
||||
|
||||
bool NewLayoutForm::validateSecondaryTileset(bool allowEmpty) {
|
||||
const QString name = ui->comboBox_SecondaryTileset->currentText();
|
||||
|
||||
QString errorText;
|
||||
if (name.isEmpty()) {
|
||||
if (!allowEmpty) errorText = QString("The Secondary Tileset cannot be empty.");
|
||||
} else if (ui->comboBox_SecondaryTileset->findText(name) < 0) {
|
||||
errorText = QString("The Secondary Tileset '%1' does not exist.").arg(name);
|
||||
}
|
||||
|
||||
bool isValid = errorText.isEmpty();
|
||||
ui->label_SecondaryTilesetError->setText(errorText);
|
||||
ui->label_SecondaryTilesetError->setVisible(!isValid);
|
||||
ui->comboBox_SecondaryTileset->lineEdit()->setStyleSheet(!isValid ? lineEdit_ErrorStylesheet : "");
|
||||
return isValid;
|
||||
}
|
||||
79
src/ui/newlocationdialog.cpp
Normal file
79
src/ui/newlocationdialog.cpp
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
#include "newlocationdialog.h"
|
||||
#include "ui_newlocationdialog.h"
|
||||
#include "project.h"
|
||||
#include "validator.h"
|
||||
|
||||
const QString lineEdit_ErrorStylesheet = "QLineEdit { background-color: rgba(255, 0, 0, 25%) }";
|
||||
|
||||
NewLocationDialog::NewLocationDialog(Project* project, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::NewLocationDialog),
|
||||
namePrefix(projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix))
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
ui->setupUi(this);
|
||||
this->project = project;
|
||||
|
||||
ui->lineEdit_IdName->setValidator(new IdentifierValidator(namePrefix, this));
|
||||
ui->lineEdit_IdName->setText(namePrefix);
|
||||
|
||||
connect(ui->lineEdit_IdName, &QLineEdit::textChanged, this, &NewLocationDialog::onIdNameChanged);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &NewLocationDialog::dialogButtonClicked);
|
||||
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
NewLocationDialog::~NewLocationDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void NewLocationDialog::onIdNameChanged(const QString &idName) {
|
||||
validateIdName(true);
|
||||
|
||||
// Extract a presumed display name from the ID name
|
||||
QString displayName = idName;
|
||||
if (displayName.startsWith(namePrefix))
|
||||
displayName.remove(0, namePrefix.length());
|
||||
displayName.replace("_", " ");
|
||||
ui->lineEdit_DisplayName->setText(displayName);
|
||||
}
|
||||
|
||||
bool NewLocationDialog::validateIdName(bool allowEmpty) {
|
||||
const QString name = ui->lineEdit_IdName->text();
|
||||
|
||||
QString errorText;
|
||||
if (name.isEmpty() || name == namePrefix) {
|
||||
if (!allowEmpty) errorText = QString("%1 cannot be empty.").arg(ui->label_IdName->text());
|
||||
} else if (!this->project->isIdentifierUnique(name)) {
|
||||
errorText = QString("%1 '%2' is not unique.").arg(ui->label_IdName->text()).arg(name);
|
||||
}
|
||||
|
||||
bool isValid = errorText.isEmpty();
|
||||
ui->label_IdNameError->setText(errorText);
|
||||
ui->label_IdNameError->setVisible(!isValid);
|
||||
ui->lineEdit_IdName->setStyleSheet(!isValid ? lineEdit_ErrorStylesheet : "");
|
||||
return isValid;
|
||||
}
|
||||
|
||||
void NewLocationDialog::dialogButtonClicked(QAbstractButton *button) {
|
||||
auto role = ui->buttonBox->buttonRole(button);
|
||||
if (role == QDialogButtonBox::RejectRole){
|
||||
reject();
|
||||
} else if (role == QDialogButtonBox::AcceptRole) {
|
||||
accept();
|
||||
}
|
||||
}
|
||||
|
||||
void NewLocationDialog::accept() {
|
||||
if (!validateIdName())
|
||||
return;
|
||||
|
||||
const QString idName = ui->lineEdit_IdName->text();
|
||||
const QString displayName = ui->lineEdit_DisplayName->text();
|
||||
|
||||
this->project->addNewMapsec(idName);
|
||||
this->project->setMapsecDisplayName(idName, displayName);
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ NewMapConnectionDialog::NewMapConnectionDialog(QWidget *parent, Map* map, const
|
|||
QString defaultMapName;
|
||||
if (mapNames.isEmpty()) {
|
||||
defaultMapName = QString();
|
||||
} else if (mapNames.first() == map->name && mapNames.length() > 1) {
|
||||
} else if (mapNames.first() == map->name() && mapNames.length() > 1) {
|
||||
// Prefer not to connect the map to itself
|
||||
defaultMapName = mapNames.at(1);
|
||||
} else {
|
||||
|
|
|
|||
268
src/ui/newmapdialog.cpp
Normal file
268
src/ui/newmapdialog.cpp
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
#include "newmapdialog.h"
|
||||
#include "maplayout.h"
|
||||
#include "mainwindow.h"
|
||||
#include "ui_newmapdialog.h"
|
||||
#include "config.h"
|
||||
#include "validator.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QSet>
|
||||
#include <QStringList>
|
||||
|
||||
const QString lineEdit_ErrorStylesheet = "QLineEdit { background-color: rgba(255, 0, 0, 25%) }";
|
||||
|
||||
NewMapDialog::NewMapDialog(Project *project, QWidget *parent) :
|
||||
NewMapDialog(project, nullptr, parent)
|
||||
{}
|
||||
|
||||
NewMapDialog::NewMapDialog(Project *project, const Map *mapToCopy, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::NewMapDialog),
|
||||
mapToCopy(mapToCopy)
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
ui->setupUi(this);
|
||||
this->project = project;
|
||||
Project::NewMapSettings *settings = &project->newMapSettings;
|
||||
|
||||
if (this->mapToCopy) {
|
||||
// Copy settings from the map we're duplicating
|
||||
if (this->mapToCopy->layout()){
|
||||
settings->layout = this->mapToCopy->layout()->settings();
|
||||
}
|
||||
settings->header = *this->mapToCopy->header();
|
||||
settings->group = project->mapNameToMapGroup(this->mapToCopy->name());
|
||||
settings->name = project->toUniqueIdentifier(this->mapToCopy->name());
|
||||
|
||||
} else {
|
||||
// Clear the previously-used map name. The rest of the settings are preserved between sessions.
|
||||
settings->name = QString();
|
||||
}
|
||||
// Generate a unique Layout constant
|
||||
settings->layout.id = project->toUniqueIdentifier(Layout::layoutConstantFromName(settings->name));
|
||||
|
||||
ui->newLayoutForm->initUi(project);
|
||||
ui->comboBox_Group->addItems(project->groupNames);
|
||||
ui->comboBox_LayoutID->addItems(project->layoutIds);
|
||||
|
||||
auto validator = new IdentifierValidator(this);
|
||||
ui->lineEdit_Name->setValidator(validator);
|
||||
ui->comboBox_Group->setValidator(validator);
|
||||
ui->comboBox_LayoutID->setValidator(validator);
|
||||
|
||||
// Create a collapsible section that has all the map header data.
|
||||
this->headerForm = new MapHeaderForm();
|
||||
this->headerForm->setProject(project, false);
|
||||
auto sectionLayout = new QVBoxLayout();
|
||||
sectionLayout->addWidget(this->headerForm);
|
||||
|
||||
this->headerSection = new CollapsibleSection("Header Data", porymapConfig.newMapHeaderSectionExpanded, 150, this);
|
||||
this->headerSection->setContentLayout(sectionLayout);
|
||||
ui->layout_HeaderData->addWidget(this->headerSection);
|
||||
|
||||
connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &NewMapDialog::dialogButtonClicked);
|
||||
|
||||
refresh();
|
||||
restoreGeometry(porymapConfig.newMapDialogGeometry);
|
||||
}
|
||||
|
||||
// Adding new map to an existing map list folder. Initialize settings accordingly.
|
||||
// Even if we initialize settings like this we'll allow users to change them afterwards,
|
||||
// because nothing is expecting them to stay at these values (with exception to layouts).
|
||||
NewMapDialog::NewMapDialog(Project *project, int mapListTab, const QString &mapListItem, QWidget *parent) :
|
||||
NewMapDialog(project, parent)
|
||||
{
|
||||
switch (mapListTab)
|
||||
{
|
||||
case MapListTab::Groups:
|
||||
ui->comboBox_Group->setTextItem(mapListItem);
|
||||
break;
|
||||
case MapListTab::Locations:
|
||||
this->headerForm->setLocation(mapListItem);
|
||||
break;
|
||||
case MapListTab::Layouts:
|
||||
// We specifically lock the layout ID because otherwise the setting would be overwritten when
|
||||
// the user changes the map name (which will normally automatically update the layout ID to match).
|
||||
// For the Group/Location settings above we don't care if the user changes them afterwards.
|
||||
ui->comboBox_LayoutID->setTextItem(mapListItem);
|
||||
ui->comboBox_LayoutID->setDisabled(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NewMapDialog::~NewMapDialog()
|
||||
{
|
||||
porymapConfig.newMapDialogGeometry = saveGeometry();
|
||||
saveSettings();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
// Reload the UI from the last-saved settings.
|
||||
void NewMapDialog::refresh() {
|
||||
const Project::NewMapSettings *settings = &this->project->newMapSettings;
|
||||
|
||||
ui->lineEdit_Name->setText(settings->name);
|
||||
ui->comboBox_Group->setTextItem(settings->group);
|
||||
|
||||
// If the layout combo box is disabled, it's because we're enforcing the setting. Leave it unchanged.
|
||||
if (ui->comboBox_LayoutID->isEnabled())
|
||||
ui->comboBox_LayoutID->setTextItem(settings->layout.id);
|
||||
|
||||
ui->newLayoutForm->setSettings(settings->layout);
|
||||
ui->checkBox_CanFlyTo->setChecked(settings->canFlyTo);
|
||||
this->headerForm->setHeaderData(settings->header);
|
||||
}
|
||||
|
||||
void NewMapDialog::saveSettings() {
|
||||
Project::NewMapSettings *settings = &this->project->newMapSettings;
|
||||
|
||||
settings->name = ui->lineEdit_Name->text();
|
||||
settings->group = ui->comboBox_Group->currentText();
|
||||
settings->layout = ui->newLayoutForm->settings();
|
||||
settings->layout.id = ui->comboBox_LayoutID->currentText();
|
||||
settings->canFlyTo = ui->checkBox_CanFlyTo->isChecked();
|
||||
settings->header = this->headerForm->headerData();
|
||||
|
||||
// This dialog doesn't give users the option to give new layouts a name, we generate one using the map name.
|
||||
// We instead add a "_Layout" suffix to differentiate the layout name from the map name.
|
||||
// (an older iteration of this dialog gave users an option to name new layouts, but it's extra clutter for
|
||||
// something the majority of users creating a map won't need. If they want to give a specific name to a layout
|
||||
// they can create the layout first, then create a new map that uses that layout.)
|
||||
const Layout *layout = this->project->mapLayouts.value(settings->layout.id);
|
||||
if (!layout) {
|
||||
const QString newLayoutName = settings->name + QStringLiteral("_Layout");
|
||||
settings->layout.name = this->project->toUniqueIdentifier(newLayoutName);
|
||||
} else {
|
||||
// Pre-existing layout. The layout name won't be read, but we'll make sure it's correct anyway.
|
||||
settings->layout.name = layout->name;
|
||||
}
|
||||
|
||||
// Folders for new layouts created for new maps use the map name, rather than the layout name
|
||||
// (i.e., if you create "MyMap", you'll get a 'data/layouts/MyMap/', rather than 'data/layouts/MyMap_Layout/').
|
||||
// There's no real reason for this, aside from maintaining consistency with the default layout folder names that do this.
|
||||
settings->layout.folderName = settings->name;
|
||||
|
||||
porymapConfig.newMapHeaderSectionExpanded = this->headerSection->isExpanded();
|
||||
}
|
||||
|
||||
bool NewMapDialog::validateName(bool allowEmpty) {
|
||||
QString name = ui->lineEdit_Name->text();
|
||||
|
||||
QString errorText;
|
||||
if (name.isEmpty()) {
|
||||
if (!allowEmpty) errorText = QString("%1 cannot be empty.").arg(ui->label_Name->text());
|
||||
} else if (!this->project->isIdentifierUnique(name)) {
|
||||
errorText = QString("%1 '%2' is not unique.").arg(ui->label_Name->text()).arg(name);
|
||||
}
|
||||
|
||||
bool isValid = errorText.isEmpty();
|
||||
ui->label_NameError->setText(errorText);
|
||||
ui->label_NameError->setVisible(!isValid);
|
||||
ui->lineEdit_Name->setStyleSheet(!isValid ? lineEdit_ErrorStylesheet : "");
|
||||
return isValid;
|
||||
}
|
||||
|
||||
void NewMapDialog::on_lineEdit_Name_textChanged(const QString &text) {
|
||||
validateName(true);
|
||||
|
||||
// Changing the map name updates the layout ID field to match.
|
||||
if (ui->comboBox_LayoutID->isEnabled()) {
|
||||
ui->comboBox_LayoutID->setCurrentText(Layout::layoutConstantFromName(text));
|
||||
}
|
||||
}
|
||||
|
||||
bool NewMapDialog::validateGroup(bool allowEmpty) {
|
||||
QString groupName = ui->comboBox_Group->currentText();
|
||||
|
||||
QString errorText;
|
||||
if (groupName.isEmpty()) {
|
||||
if (!allowEmpty) errorText = QString("%1 cannot be empty.").arg(ui->label_Group->text());
|
||||
} else if (!this->project->groupNames.contains(groupName) && !this->project->isIdentifierUnique(groupName)) {
|
||||
errorText = QString("%1 must either be the name of an existing map group, or a unique identifier for a new map group.").arg(ui->label_Group->text());
|
||||
}
|
||||
|
||||
bool isValid = errorText.isEmpty();
|
||||
ui->label_GroupError->setText(errorText);
|
||||
ui->label_GroupError->setVisible(!isValid);
|
||||
ui->comboBox_Group->lineEdit()->setStyleSheet(!isValid ? lineEdit_ErrorStylesheet : "");
|
||||
return isValid;
|
||||
}
|
||||
|
||||
void NewMapDialog::on_comboBox_Group_currentTextChanged(const QString &) {
|
||||
validateGroup(true);
|
||||
}
|
||||
|
||||
bool NewMapDialog::validateLayoutID(bool allowEmpty) {
|
||||
QString layoutId = ui->comboBox_LayoutID->currentText();
|
||||
|
||||
QString errorText;
|
||||
if (layoutId.isEmpty()) {
|
||||
if (!allowEmpty) errorText = QString("%1 cannot be empty.").arg(ui->label_LayoutID->text());
|
||||
} else if (!this->project->layoutIds.contains(layoutId) && !this->project->isIdentifierUnique(layoutId)) {
|
||||
errorText = QString("%1 must either be the ID for an existing layout, or a unique identifier for a new layout.").arg(ui->label_LayoutID->text());
|
||||
}
|
||||
|
||||
bool isValid = errorText.isEmpty();
|
||||
ui->label_LayoutIDError->setText(errorText);
|
||||
ui->label_LayoutIDError->setVisible(!isValid);
|
||||
ui->comboBox_LayoutID->lineEdit()->setStyleSheet(!isValid ? lineEdit_ErrorStylesheet : "");
|
||||
return isValid;
|
||||
}
|
||||
|
||||
void NewMapDialog::on_comboBox_LayoutID_currentTextChanged(const QString &text) {
|
||||
validateLayoutID(true);
|
||||
|
||||
// Changing the layout ID to an existing layout updates the layout settings to match.
|
||||
const Layout *layout = this->project->mapLayouts.value(text);
|
||||
if (!layout && this->mapToCopy) {
|
||||
// When duplicating a map, if a new layout ID is specified the settings will be updated
|
||||
// to match the layout of the map we're duplicating.
|
||||
layout = this->mapToCopy->layout();
|
||||
}
|
||||
|
||||
if (layout) {
|
||||
ui->newLayoutForm->setSettings(layout->settings());
|
||||
ui->newLayoutForm->setDisabled(true);
|
||||
} else {
|
||||
ui->newLayoutForm->setDisabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void NewMapDialog::dialogButtonClicked(QAbstractButton *button) {
|
||||
auto role = ui->buttonBox->buttonRole(button);
|
||||
if (role == QDialogButtonBox::RejectRole){
|
||||
reject();
|
||||
} else if (role == QDialogButtonBox::ResetRole) {
|
||||
this->project->initNewMapSettings();
|
||||
refresh();
|
||||
} else if (role == QDialogButtonBox::AcceptRole) {
|
||||
accept();
|
||||
}
|
||||
}
|
||||
|
||||
void NewMapDialog::accept() {
|
||||
// Make sure to call each validation function so that all errors are shown at once.
|
||||
bool success = true;
|
||||
if (!ui->newLayoutForm->validate()) success = false;
|
||||
if (!validateName()) success = false;
|
||||
if (!validateGroup()) success = false;
|
||||
if (!validateLayoutID()) success = false;
|
||||
if (!success)
|
||||
return;
|
||||
|
||||
// Update settings from UI
|
||||
saveSettings();
|
||||
|
||||
Map *map = this->project->createNewMap(this->project->newMapSettings, this->mapToCopy);
|
||||
if (!map) {
|
||||
ui->label_GenericError->setText(QString("Failed to create map. See %1 for details.").arg(getLogPath()));
|
||||
ui->label_GenericError->setVisible(true);
|
||||
return;
|
||||
}
|
||||
ui->label_GenericError->setVisible(false);
|
||||
|
||||
// If the location name field was changed, update the project for that too.
|
||||
this->project->setMapsecDisplayName(this->headerForm->location(), this->headerForm->locationName());
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
67
src/ui/newmapgroupdialog.cpp
Normal file
67
src/ui/newmapgroupdialog.cpp
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
#include "newmapgroupdialog.h"
|
||||
#include "ui_newmapgroupdialog.h"
|
||||
#include "project.h"
|
||||
#include "validator.h"
|
||||
|
||||
const QString lineEdit_ErrorStylesheet = "QLineEdit { background-color: rgba(255, 0, 0, 25%) }";
|
||||
|
||||
NewMapGroupDialog::NewMapGroupDialog(Project* project, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::NewMapGroupDialog)
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
ui->setupUi(this);
|
||||
this->project = project;
|
||||
|
||||
ui->lineEdit_Name->setValidator(new IdentifierValidator(this));
|
||||
ui->lineEdit_Name->setText(Project::getMapGroupPrefix());
|
||||
|
||||
connect(ui->lineEdit_Name, &QLineEdit::textChanged, this, &NewMapGroupDialog::onNameChanged);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &NewMapGroupDialog::dialogButtonClicked);
|
||||
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
NewMapGroupDialog::~NewMapGroupDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void NewMapGroupDialog::onNameChanged(const QString &) {
|
||||
validateName(true);
|
||||
}
|
||||
|
||||
bool NewMapGroupDialog::validateName(bool allowEmpty) {
|
||||
const QString name = ui->lineEdit_Name->text();
|
||||
|
||||
QString errorText;
|
||||
if (name.isEmpty()) {
|
||||
if (!allowEmpty) errorText = QString("%1 cannot be empty.").arg(ui->label_Name->text());
|
||||
} else if (!this->project->isIdentifierUnique(name)) {
|
||||
errorText = QString("%1 '%2' is not unique.").arg(ui->label_Name->text()).arg(name);
|
||||
}
|
||||
|
||||
bool isValid = errorText.isEmpty();
|
||||
ui->label_NameError->setText(errorText);
|
||||
ui->label_NameError->setVisible(!isValid);
|
||||
ui->lineEdit_Name->setStyleSheet(!isValid ? lineEdit_ErrorStylesheet : "");
|
||||
return isValid;
|
||||
}
|
||||
|
||||
void NewMapGroupDialog::dialogButtonClicked(QAbstractButton *button) {
|
||||
auto role = ui->buttonBox->buttonRole(button);
|
||||
if (role == QDialogButtonBox::RejectRole){
|
||||
reject();
|
||||
} else if (role == QDialogButtonBox::AcceptRole) {
|
||||
accept();
|
||||
}
|
||||
}
|
||||
|
||||
void NewMapGroupDialog::accept() {
|
||||
if (!validateName())
|
||||
return;
|
||||
|
||||
this->project->addNewMapGroup(ui->lineEdit_Name->text());
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
|
@ -1,361 +0,0 @@
|
|||
#include "newmappopup.h"
|
||||
#include "maplayout.h"
|
||||
#include "mainwindow.h"
|
||||
#include "ui_newmappopup.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QSet>
|
||||
#include <QStringList>
|
||||
|
||||
// TODO: Convert to modal dialog (among other things, this means we wouldn't need to worry about changes to the map list while this is open)
|
||||
|
||||
struct NewMapPopup::Settings NewMapPopup::settings = {};
|
||||
|
||||
NewMapPopup::NewMapPopup(QWidget *parent, Project *project) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::NewMapPopup)
|
||||
{
|
||||
this->setAttribute(Qt::WA_DeleteOnClose);
|
||||
ui->setupUi(this);
|
||||
this->project = project;
|
||||
this->existingLayout = false;
|
||||
this->importedMap = false;
|
||||
}
|
||||
|
||||
NewMapPopup::~NewMapPopup()
|
||||
{
|
||||
saveSettings();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void NewMapPopup::initUi() {
|
||||
// Populate combo boxes
|
||||
ui->comboBox_NewMap_Primary_Tileset->addItems(project->primaryTilesetLabels);
|
||||
ui->comboBox_NewMap_Secondary_Tileset->addItems(project->secondaryTilesetLabels);
|
||||
ui->comboBox_NewMap_Group->addItems(project->groupNames);
|
||||
ui->comboBox_NewMap_Song->addItems(project->songNames);
|
||||
ui->comboBox_NewMap_Type->addItems(project->mapTypes);
|
||||
ui->comboBox_NewMap_Location->addItems(project->mapSectionIdNames);
|
||||
|
||||
const QSignalBlocker b(ui->comboBox_Layout);
|
||||
ui->comboBox_Layout->addItems(project->mapLayoutsTable);
|
||||
this->layoutId = project->mapLayoutsTable.first();
|
||||
|
||||
// Set spin box limits
|
||||
ui->spinBox_NewMap_Width->setMinimum(1);
|
||||
ui->spinBox_NewMap_Height->setMinimum(1);
|
||||
ui->spinBox_NewMap_Width->setMaximum(project->getMaxMapWidth());
|
||||
ui->spinBox_NewMap_Height->setMaximum(project->getMaxMapHeight());
|
||||
ui->spinBox_NewMap_BorderWidth->setMinimum(1);
|
||||
ui->spinBox_NewMap_BorderHeight->setMinimum(1);
|
||||
ui->spinBox_NewMap_BorderWidth->setMaximum(MAX_BORDER_WIDTH);
|
||||
ui->spinBox_NewMap_BorderHeight->setMaximum(MAX_BORDER_HEIGHT);
|
||||
ui->spinBox_NewMap_Floor_Number->setMinimum(-128);
|
||||
ui->spinBox_NewMap_Floor_Number->setMaximum(127);
|
||||
|
||||
// Hide config specific ui elements
|
||||
bool hasFlags = projectConfig.mapAllowFlagsEnabled;
|
||||
ui->checkBox_NewMap_Allow_Running->setVisible(hasFlags);
|
||||
ui->checkBox_NewMap_Allow_Biking->setVisible(hasFlags);
|
||||
ui->checkBox_NewMap_Allow_Escape_Rope->setVisible(hasFlags);
|
||||
ui->label_NewMap_Allow_Running->setVisible(hasFlags);
|
||||
ui->label_NewMap_Allow_Biking->setVisible(hasFlags);
|
||||
ui->label_NewMap_Allow_Escape_Rope->setVisible(hasFlags);
|
||||
|
||||
bool hasCustomBorders = projectConfig.useCustomBorderSize;
|
||||
ui->spinBox_NewMap_BorderWidth->setVisible(hasCustomBorders);
|
||||
ui->spinBox_NewMap_BorderHeight->setVisible(hasCustomBorders);
|
||||
ui->label_NewMap_BorderWidth->setVisible(hasCustomBorders);
|
||||
ui->label_NewMap_BorderHeight->setVisible(hasCustomBorders);
|
||||
|
||||
bool hasFloorNumber = projectConfig.floorNumberEnabled;
|
||||
ui->spinBox_NewMap_Floor_Number->setVisible(hasFloorNumber);
|
||||
ui->label_NewMap_Floor_Number->setVisible(hasFloorNumber);
|
||||
|
||||
this->updateGeometry();
|
||||
}
|
||||
|
||||
void NewMapPopup::init() {
|
||||
// Restore previous settings
|
||||
ui->lineEdit_NewMap_Name->setText(project->getNewMapName());
|
||||
ui->comboBox_NewMap_Group->setTextItem(settings.group);
|
||||
ui->spinBox_NewMap_Width->setValue(settings.width);
|
||||
ui->spinBox_NewMap_Height->setValue(settings.height);
|
||||
ui->spinBox_NewMap_BorderWidth->setValue(settings.borderWidth);
|
||||
ui->spinBox_NewMap_BorderHeight->setValue(settings.borderHeight);
|
||||
ui->comboBox_NewMap_Primary_Tileset->setTextItem(settings.primaryTilesetLabel);
|
||||
ui->comboBox_NewMap_Secondary_Tileset->setTextItem(settings.secondaryTilesetLabel);
|
||||
ui->comboBox_NewMap_Type->setTextItem(settings.type);
|
||||
ui->comboBox_NewMap_Location->setTextItem(settings.location);
|
||||
ui->comboBox_NewMap_Song->setTextItem(settings.song);
|
||||
ui->checkBox_NewMap_Flyable->setChecked(settings.canFlyTo);
|
||||
ui->checkBox_NewMap_Show_Location->setChecked(settings.showLocationName);
|
||||
ui->checkBox_NewMap_Allow_Running->setChecked(settings.allowRunning);
|
||||
ui->checkBox_NewMap_Allow_Biking->setChecked(settings.allowBiking);
|
||||
ui->checkBox_NewMap_Allow_Escape_Rope->setChecked(settings.allowEscaping);
|
||||
ui->spinBox_NewMap_Floor_Number->setValue(settings.floorNumber);
|
||||
|
||||
// Connect signals
|
||||
connect(ui->spinBox_NewMap_Width, QOverload<int>::of(&QSpinBox::valueChanged), [=](int){checkNewMapDimensions();});
|
||||
connect(ui->spinBox_NewMap_Height, QOverload<int>::of(&QSpinBox::valueChanged), [=](int){checkNewMapDimensions();});
|
||||
|
||||
ui->frame_NewMap_Options->setEnabled(true);
|
||||
}
|
||||
|
||||
// Creating new map by right-clicking in the map list
|
||||
void NewMapPopup::init(int tabIndex, QString fieldName) {
|
||||
initUi();
|
||||
switch (tabIndex)
|
||||
{
|
||||
case MapListTab::Groups:
|
||||
settings.group = fieldName;
|
||||
break;
|
||||
case MapListTab::Areas:
|
||||
settings.location = fieldName;
|
||||
break;
|
||||
case MapListTab::Layouts:
|
||||
this->ui->checkBox_UseExistingLayout->setCheckState(Qt::Checked);
|
||||
useLayout(fieldName);
|
||||
break;
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
// Creating new map from AdvanceMap import
|
||||
void NewMapPopup::init(Layout *mapLayout) {
|
||||
initUi();
|
||||
this->importedMap = true;
|
||||
useLayoutSettings(mapLayout);
|
||||
|
||||
this->map = new Map();
|
||||
this->map->layout = new Layout();
|
||||
this->map->layout->blockdata = mapLayout->blockdata;
|
||||
|
||||
if (!mapLayout->border.isEmpty()) {
|
||||
this->map->layout->border = mapLayout->border;
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
bool NewMapPopup::checkNewMapDimensions() {
|
||||
int numMetatiles = project->getMapDataSize(ui->spinBox_NewMap_Width->value(), ui->spinBox_NewMap_Height->value());
|
||||
int maxMetatiles = project->getMaxMapDataSize();
|
||||
|
||||
if (numMetatiles > maxMetatiles) {
|
||||
ui->frame_NewMap_Warning->setVisible(true);
|
||||
QString errorText = QString("Error: The specified width and height are too large.\n"
|
||||
"The maximum map width and height is the following: (width + 15) * (height + 14) <= %1\n"
|
||||
"The specified map width and height was: (%2 + 15) * (%3 + 14) = %4")
|
||||
.arg(maxMetatiles)
|
||||
.arg(ui->spinBox_NewMap_Width->value())
|
||||
.arg(ui->spinBox_NewMap_Height->value())
|
||||
.arg(numMetatiles);
|
||||
ui->label_NewMap_WarningMessage->setText(errorText);
|
||||
ui->label_NewMap_WarningMessage->setWordWrap(true);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
ui->frame_NewMap_Warning->setVisible(false);
|
||||
ui->label_NewMap_WarningMessage->clear();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool NewMapPopup::checkNewMapGroup() {
|
||||
group = project->groupNames.indexOf(this->ui->comboBox_NewMap_Group->currentText());
|
||||
|
||||
if (group < 0) {
|
||||
ui->frame_NewMap_Warning->setVisible(true);
|
||||
QString errorText = QString("Error: The specified map group '%1' does not exist.")
|
||||
.arg(ui->comboBox_NewMap_Group->currentText());
|
||||
ui->label_NewMap_WarningMessage->setText(errorText);
|
||||
ui->label_NewMap_WarningMessage->setWordWrap(true);
|
||||
return false;
|
||||
} else {
|
||||
ui->frame_NewMap_Warning->setVisible(false);
|
||||
ui->label_NewMap_WarningMessage->clear();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void NewMapPopup::setDefaultSettings(Project *project) {
|
||||
settings.group = project->groupNames.at(0);
|
||||
settings.width = project->getDefaultMapSize();
|
||||
settings.height = project->getDefaultMapSize();
|
||||
settings.borderWidth = DEFAULT_BORDER_WIDTH;
|
||||
settings.borderHeight = DEFAULT_BORDER_HEIGHT;
|
||||
settings.primaryTilesetLabel = project->getDefaultPrimaryTilesetLabel();
|
||||
settings.secondaryTilesetLabel = project->getDefaultSecondaryTilesetLabel();
|
||||
settings.type = project->mapTypes.value(0, "0");
|
||||
settings.location = project->mapSectionIdNames.value(0, "0");
|
||||
settings.song = project->defaultSong;
|
||||
settings.canFlyTo = false;
|
||||
settings.showLocationName = true;
|
||||
settings.allowRunning = false;
|
||||
settings.allowBiking = false;
|
||||
settings.allowEscaping = false;
|
||||
settings.floorNumber = 0;
|
||||
}
|
||||
|
||||
void NewMapPopup::saveSettings() {
|
||||
settings.group = ui->comboBox_NewMap_Group->currentText();
|
||||
settings.width = ui->spinBox_NewMap_Width->value();
|
||||
settings.height = ui->spinBox_NewMap_Height->value();
|
||||
settings.borderWidth = ui->spinBox_NewMap_BorderWidth->value();
|
||||
settings.borderHeight = ui->spinBox_NewMap_BorderHeight->value();
|
||||
settings.primaryTilesetLabel = ui->comboBox_NewMap_Primary_Tileset->currentText();
|
||||
settings.secondaryTilesetLabel = ui->comboBox_NewMap_Secondary_Tileset->currentText();
|
||||
settings.type = ui->comboBox_NewMap_Type->currentText();
|
||||
settings.location = ui->comboBox_NewMap_Location->currentText();
|
||||
settings.song = ui->comboBox_NewMap_Song->currentText();
|
||||
settings.canFlyTo = ui->checkBox_NewMap_Flyable->isChecked();
|
||||
settings.showLocationName = ui->checkBox_NewMap_Show_Location->isChecked();
|
||||
settings.allowRunning = ui->checkBox_NewMap_Allow_Running->isChecked();
|
||||
settings.allowBiking = ui->checkBox_NewMap_Allow_Biking->isChecked();
|
||||
settings.allowEscaping = ui->checkBox_NewMap_Allow_Escape_Rope->isChecked();
|
||||
settings.floorNumber = ui->spinBox_NewMap_Floor_Number->value();
|
||||
}
|
||||
|
||||
void NewMapPopup::useLayoutSettings(Layout *layout) {
|
||||
if (!layout) return;
|
||||
|
||||
settings.width = layout->width;
|
||||
ui->spinBox_NewMap_Width->setValue(layout->width);
|
||||
|
||||
settings.height = layout->height;
|
||||
ui->spinBox_NewMap_Height->setValue(layout->height);
|
||||
|
||||
settings.borderWidth = layout->border_width;
|
||||
ui->spinBox_NewMap_BorderWidth->setValue(layout->border_width);
|
||||
|
||||
settings.borderHeight = layout->border_height;
|
||||
ui->spinBox_NewMap_BorderWidth->setValue(layout->border_height);
|
||||
|
||||
settings.primaryTilesetLabel = layout->tileset_primary_label;
|
||||
ui->comboBox_NewMap_Primary_Tileset->setCurrentIndex(ui->comboBox_NewMap_Primary_Tileset->findText(layout->tileset_primary_label));
|
||||
|
||||
settings.secondaryTilesetLabel = layout->tileset_secondary_label;
|
||||
ui->comboBox_NewMap_Secondary_Tileset->setCurrentIndex(ui->comboBox_NewMap_Secondary_Tileset->findText(layout->tileset_secondary_label));
|
||||
}
|
||||
|
||||
void NewMapPopup::useLayout(QString layoutId) {
|
||||
this->existingLayout = true;
|
||||
this->layoutId = layoutId;
|
||||
|
||||
this->ui->comboBox_Layout->setCurrentIndex(this->ui->comboBox_Layout->findText(layoutId));
|
||||
|
||||
useLayoutSettings(project->mapLayouts.value(this->layoutId));
|
||||
}
|
||||
|
||||
void NewMapPopup::on_checkBox_UseExistingLayout_stateChanged(int state) {
|
||||
bool layoutEditsEnabled = (state == Qt::Unchecked);
|
||||
|
||||
this->ui->comboBox_Layout->setEnabled(!layoutEditsEnabled);
|
||||
|
||||
this->ui->spinBox_NewMap_Width->setEnabled(layoutEditsEnabled);
|
||||
this->ui->spinBox_NewMap_Height->setEnabled(layoutEditsEnabled);
|
||||
this->ui->spinBox_NewMap_BorderWidth->setEnabled(layoutEditsEnabled);
|
||||
this->ui->spinBox_NewMap_BorderWidth->setEnabled(layoutEditsEnabled);
|
||||
this->ui->comboBox_NewMap_Primary_Tileset->setEnabled(layoutEditsEnabled);
|
||||
this->ui->comboBox_NewMap_Secondary_Tileset->setEnabled(layoutEditsEnabled);
|
||||
|
||||
if (!layoutEditsEnabled) {
|
||||
useLayout(this->layoutId);//this->ui->comboBox_Layout->currentText());
|
||||
} else {
|
||||
this->existingLayout = false;
|
||||
}
|
||||
}
|
||||
|
||||
void NewMapPopup::on_comboBox_Layout_currentTextChanged(const QString &text) {
|
||||
if (this->project->mapLayoutsTable.contains(text)) {
|
||||
useLayout(text);
|
||||
}
|
||||
}
|
||||
|
||||
void NewMapPopup::on_lineEdit_NewMap_Name_textChanged(const QString &text) {
|
||||
if (project->mapNames.contains(text)) {
|
||||
this->ui->lineEdit_NewMap_Name->setStyleSheet("QLineEdit { background-color: rgba(255, 0, 0, 25%) }");
|
||||
} else {
|
||||
this->ui->lineEdit_NewMap_Name->setStyleSheet("");
|
||||
}
|
||||
}
|
||||
|
||||
void NewMapPopup::on_pushButton_NewMap_Accept_clicked() {
|
||||
if (!checkNewMapDimensions() || !checkNewMapGroup()) {
|
||||
// ignore when map dimensions or map group are invalid
|
||||
return;
|
||||
}
|
||||
Map *newMap = new Map;
|
||||
Layout *layout;
|
||||
|
||||
// If map name is not unique, use default value. Also use only valid characters.
|
||||
// After stripping invalid characters, strip any leading digits.
|
||||
static const QRegularExpression re_invalidChars("[^a-zA-Z0-9_]+");
|
||||
QString newMapName = this->ui->lineEdit_NewMap_Name->text().remove(re_invalidChars);
|
||||
static const QRegularExpression re_NaN("^[0-9]*");
|
||||
newMapName.remove(re_NaN);
|
||||
if (project->mapNames.contains(newMapName) || newMapName.isEmpty()) {
|
||||
newMapName = project->getNewMapName();
|
||||
}
|
||||
|
||||
newMap->name = newMapName;
|
||||
newMap->type = this->ui->comboBox_NewMap_Type->currentText();
|
||||
newMap->location = this->ui->comboBox_NewMap_Location->currentText();
|
||||
newMap->song = this->ui->comboBox_NewMap_Song->currentText();
|
||||
newMap->requiresFlash = false;
|
||||
newMap->weather = this->project->weatherNames.value(0, "0");
|
||||
newMap->show_location = this->ui->checkBox_NewMap_Show_Location->isChecked();
|
||||
newMap->battle_scene = this->project->mapBattleScenes.value(0, "0");
|
||||
|
||||
if (this->existingLayout) {
|
||||
layout = this->project->mapLayouts.value(this->layoutId);
|
||||
newMap->needsLayoutDir = false;
|
||||
} else {
|
||||
layout = new Layout;
|
||||
layout->id = Layout::layoutConstantFromName(newMapName);
|
||||
layout->name = QString("%1_Layout").arg(newMap->name);
|
||||
layout->width = this->ui->spinBox_NewMap_Width->value();
|
||||
layout->height = this->ui->spinBox_NewMap_Height->value();
|
||||
if (projectConfig.useCustomBorderSize) {
|
||||
layout->border_width = this->ui->spinBox_NewMap_BorderWidth->value();
|
||||
layout->border_height = this->ui->spinBox_NewMap_BorderHeight->value();
|
||||
} else {
|
||||
layout->border_width = DEFAULT_BORDER_WIDTH;
|
||||
layout->border_height = DEFAULT_BORDER_HEIGHT;
|
||||
}
|
||||
layout->tileset_primary_label = this->ui->comboBox_NewMap_Primary_Tileset->currentText();
|
||||
layout->tileset_secondary_label = this->ui->comboBox_NewMap_Secondary_Tileset->currentText();
|
||||
QString basePath = projectConfig.getFilePath(ProjectFilePath::data_layouts_folders);
|
||||
layout->border_path = QString("%1%2/border.bin").arg(basePath, newMapName);
|
||||
layout->blockdata_path = QString("%1%2/map.bin").arg(basePath, newMapName);
|
||||
}
|
||||
|
||||
if (this->importedMap) {
|
||||
layout->blockdata = map->layout->blockdata;
|
||||
if (!map->layout->border.isEmpty())
|
||||
layout->border = map->layout->border;
|
||||
}
|
||||
|
||||
if (this->ui->checkBox_NewMap_Flyable->isChecked()) {
|
||||
newMap->needsHealLocation = true;
|
||||
}
|
||||
|
||||
if (projectConfig.mapAllowFlagsEnabled) {
|
||||
newMap->allowRunning = this->ui->checkBox_NewMap_Allow_Running->isChecked();
|
||||
newMap->allowBiking = this->ui->checkBox_NewMap_Allow_Biking->isChecked();
|
||||
newMap->allowEscaping = this->ui->checkBox_NewMap_Allow_Escape_Rope->isChecked();
|
||||
}
|
||||
if (projectConfig.floorNumberEnabled) {
|
||||
newMap->floorNumber = this->ui->spinBox_NewMap_Floor_Number->value();
|
||||
}
|
||||
|
||||
newMap->layout = layout;
|
||||
newMap->layoutId = layout->id;
|
||||
if (this->existingLayout) {
|
||||
project->loadMapLayout(newMap);
|
||||
}
|
||||
map = newMap;
|
||||
emit applied();
|
||||
this->close();
|
||||
}
|
||||
|
|
@ -1,49 +1,80 @@
|
|||
#include "newtilesetdialog.h"
|
||||
#include "ui_newtilesetdialog.h"
|
||||
#include "project.h"
|
||||
#include "imageexport.h"
|
||||
#include "validator.h"
|
||||
|
||||
const QString lineEdit_ErrorStylesheet = "QLineEdit { background-color: rgba(255, 0, 0, 25%) }";
|
||||
|
||||
NewTilesetDialog::NewTilesetDialog(Project* project, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::NewTilesetDialog)
|
||||
ui(new Ui::NewTilesetDialog),
|
||||
symbolPrefix(projectConfig.getIdentifier(ProjectIdentifier::symbol_tilesets_prefix))
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
ui->setupUi(this);
|
||||
this->setFixedSize(this->width(), this->height());
|
||||
this->project = project;
|
||||
//only allow characters valid for a symbol
|
||||
static const QRegularExpression expression("[_A-Za-z0-9]+$");
|
||||
QRegularExpressionValidator *validator = new QRegularExpressionValidator(expression);
|
||||
this->ui->nameLineEdit->setValidator(validator);
|
||||
|
||||
bool checkerboard = porymapConfig.tilesetCheckerboardFill;
|
||||
this->ui->fillCheckBox->setChecked(checkerboard);
|
||||
this->checkerboardFill = checkerboard;
|
||||
ui->checkBox_CheckerboardFill->setChecked(porymapConfig.tilesetCheckerboardFill);
|
||||
ui->comboBox_Type->setMinimumContentsLength(12 + this->symbolPrefix.length());
|
||||
ui->lineEdit_Name->setValidator(new IdentifierValidator(this->symbolPrefix, this));
|
||||
ui->lineEdit_Name->setText(this->symbolPrefix);
|
||||
|
||||
connect(this->ui->nameLineEdit, &QLineEdit::textChanged, this, &NewTilesetDialog::NameOrSecondaryChanged);
|
||||
connect(this->ui->typeComboBox, &QComboBox::currentTextChanged, this, &NewTilesetDialog::SecondaryChanged);
|
||||
connect(this->ui->fillCheckBox, &QCheckBox::stateChanged, this, &NewTilesetDialog::FillChanged);
|
||||
//connect(this->ui->toolButton, &QToolButton::clicked, this, &NewTilesetDialog::ChangeFilePath);
|
||||
this->SecondaryChanged();
|
||||
connect(ui->lineEdit_Name, &QLineEdit::textChanged, this, &NewTilesetDialog::onNameChanged);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::clicked, this, &NewTilesetDialog::dialogButtonClicked);
|
||||
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
NewTilesetDialog::~NewTilesetDialog()
|
||||
{
|
||||
porymapConfig.tilesetCheckerboardFill = ui->checkBox_CheckerboardFill->isChecked();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void NewTilesetDialog::SecondaryChanged(){
|
||||
this->isSecondary = (this->ui->typeComboBox->currentIndex() == 1);
|
||||
NameOrSecondaryChanged();
|
||||
void NewTilesetDialog::onNameChanged(const QString &) {
|
||||
validateName(true);
|
||||
}
|
||||
|
||||
void NewTilesetDialog::NameOrSecondaryChanged() {
|
||||
this->friendlyName = this->ui->nameLineEdit->text();
|
||||
this->fullSymbolName = projectConfig.getIdentifier(ProjectIdentifier::symbol_tilesets_prefix) + this->friendlyName;
|
||||
this->ui->symbolNameLineEdit->setText(this->fullSymbolName);
|
||||
this->path = Tileset::getExpectedDir(this->fullSymbolName, this->isSecondary);
|
||||
this->ui->pathLineEdit->setText(this->path);
|
||||
bool NewTilesetDialog::validateName(bool allowEmpty) {
|
||||
const QString name = ui->lineEdit_Name->text();
|
||||
|
||||
QString errorText;
|
||||
if (name.isEmpty() || name == symbolPrefix) {
|
||||
if (!allowEmpty) errorText = QString("%1 cannot be empty.").arg(ui->label_Name->text());
|
||||
} else if (!this->project->isIdentifierUnique(name)) {
|
||||
errorText = QString("%1 '%2' is not unique.").arg(ui->label_Name->text()).arg(name);
|
||||
}
|
||||
|
||||
bool isValid = errorText.isEmpty();
|
||||
ui->label_NameError->setText(errorText);
|
||||
ui->label_NameError->setVisible(!isValid);
|
||||
ui->lineEdit_Name->setStyleSheet(!isValid ? lineEdit_ErrorStylesheet : "");
|
||||
return isValid;
|
||||
}
|
||||
|
||||
void NewTilesetDialog::FillChanged() {
|
||||
this->checkerboardFill = this->ui->fillCheckBox->isChecked();
|
||||
porymapConfig.tilesetCheckerboardFill = this->checkerboardFill;
|
||||
void NewTilesetDialog::dialogButtonClicked(QAbstractButton *button) {
|
||||
auto role = ui->buttonBox->buttonRole(button);
|
||||
if (role == QDialogButtonBox::RejectRole){
|
||||
reject();
|
||||
} else if (role == QDialogButtonBox::AcceptRole) {
|
||||
accept();
|
||||
}
|
||||
}
|
||||
|
||||
void NewTilesetDialog::accept() {
|
||||
if (!validateName())
|
||||
return;
|
||||
|
||||
bool secondary = ui->comboBox_Type->currentIndex() == 1;
|
||||
Tileset *tileset = this->project->createNewTileset(ui->lineEdit_Name->text(), secondary, ui->checkBox_CheckerboardFill->isChecked());
|
||||
if (!tileset) {
|
||||
ui->label_GenericError->setText(QString("Failed to create tileset. See %1 for details.").arg(getLogPath()));
|
||||
ui->label_GenericError->setVisible(true);
|
||||
return;
|
||||
}
|
||||
ui->label_GenericError->setVisible(false);
|
||||
|
||||
QDialog::accept();
|
||||
emit applied(tileset);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ bool Prefab::tryImportDefaultPrefabs(QWidget * parent, BaseGameVersion version,
|
|||
// into their project.
|
||||
QMessageBox::StandardButton prompt =
|
||||
QMessageBox::question(parent,
|
||||
"Import Default Prefabs",
|
||||
QApplication::applicationName(),
|
||||
QString("Would you like to import the default prefabs for %1? %2.")
|
||||
.arg(projectConfig.getBaseGameVersionString(version))
|
||||
.arg(fileWarning),
|
||||
|
|
|
|||
|
|
@ -116,11 +116,6 @@ void ProjectSettingsEditor::initUi() {
|
|||
ui->lineEdit_BorderMetatiles->setValidator(validator_HexList);
|
||||
this->setBorderMetatilesUi(projectConfig.useCustomBorderSize);
|
||||
|
||||
// Validate that the text added to the warp behavior list could be a valid define
|
||||
// (we don't care whether it actually is a metatile behavior define)
|
||||
static const QRegularExpression expression_Word("^[A-Za-z0-9_]*$");
|
||||
QRegularExpressionValidator *validator_Word = new QRegularExpressionValidator(expression_Word);
|
||||
ui->comboBox_WarpBehaviors->setValidator(validator_Word);
|
||||
ui->textEdit_WarpBehaviors->setTextColor(Qt::gray);
|
||||
|
||||
// Set spin box limits
|
||||
|
|
@ -298,7 +293,7 @@ QStringList ProjectSettingsEditor::getWarpBehaviorsList() {
|
|||
|
||||
void ProjectSettingsEditor::setWarpBehaviorsList(QStringList list) {
|
||||
list.removeDuplicates();
|
||||
list.sort();
|
||||
Project::numericalModeSort(list);
|
||||
ui->textEdit_WarpBehaviors->setText(list.join("\n"));
|
||||
}
|
||||
|
||||
|
|
@ -400,7 +395,7 @@ QString ProjectSettingsEditor::chooseProjectFile(const QString &defaultFilepath)
|
|||
if (!path.startsWith(this->baseDir)){
|
||||
// Most of Porymap's file-parsing code for project files will assume that filepaths
|
||||
// are relative to the root project folder, so we enforce that here.
|
||||
QMessageBox::warning(this, "Failed to set custom filepath",
|
||||
QMessageBox::warning(this, QApplication::applicationName(),
|
||||
QString("Custom filepaths must be inside the root project folder '%1'").arg(this->baseDir));
|
||||
return QString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ RegionMapEditor::RegionMapEditor(QWidget *parent, Project *project) :
|
|||
this->setAttribute(Qt::WA_DeleteOnClose);
|
||||
this->ui->setupUi(this);
|
||||
this->project = project;
|
||||
connect(this->project, &Project::mapSectionIdNamesChanged, this, &RegionMapEditor::setLocations);
|
||||
this->configFilepath = QString("%1/%2").arg(this->project->root).arg(projectConfig.getFilePath(ProjectFilePath::json_region_porymap_cfg));
|
||||
this->initShortcuts();
|
||||
this->restoreWindowState();
|
||||
|
|
@ -651,10 +652,9 @@ void RegionMapEditor::displayRegionMapLayout() {
|
|||
void RegionMapEditor::displayRegionMapLayoutOptions() {
|
||||
if (!this->region_map->layoutEnabled()) return;
|
||||
|
||||
this->ui->comboBox_RM_ConnectedMap->blockSignals(true);
|
||||
const QSignalBlocker b(ui->comboBox_RM_ConnectedMap);
|
||||
this->ui->comboBox_RM_ConnectedMap->clear();
|
||||
this->ui->comboBox_RM_ConnectedMap->addItems(this->project->mapSectionIdNames);
|
||||
this->ui->comboBox_RM_ConnectedMap->blockSignals(false);
|
||||
|
||||
this->ui->frame_RM_Options->setEnabled(true);
|
||||
|
||||
|
|
@ -662,22 +662,19 @@ void RegionMapEditor::displayRegionMapLayoutOptions() {
|
|||
}
|
||||
|
||||
void RegionMapEditor::updateRegionMapLayoutOptions(int index) {
|
||||
this->ui->comboBox_RM_ConnectedMap->blockSignals(true);
|
||||
const QSignalBlocker b_ConnectedMap(ui->comboBox_RM_ConnectedMap);
|
||||
this->ui->comboBox_RM_ConnectedMap->setCurrentText(this->region_map->squareMapSection(index));
|
||||
this->ui->comboBox_RM_ConnectedMap->blockSignals(false);
|
||||
|
||||
this->ui->pushButton_RM_Options_delete->setEnabled(this->region_map->squareHasMap(index));
|
||||
|
||||
this->ui->spinBox_RM_LayoutWidth->blockSignals(true);
|
||||
this->ui->spinBox_RM_LayoutHeight->blockSignals(true);
|
||||
const QSignalBlocker b_LayoutWidth(ui->spinBox_RM_LayoutWidth);
|
||||
const QSignalBlocker b_LayoutHeight(ui->spinBox_RM_LayoutHeight);
|
||||
this->ui->spinBox_RM_LayoutWidth->setMinimum(1);
|
||||
this->ui->spinBox_RM_LayoutWidth->setMaximum(this->region_map->tilemapWidth() - this->region_map->padLeft());
|
||||
this->ui->spinBox_RM_LayoutHeight->setMinimum(1);
|
||||
this->ui->spinBox_RM_LayoutHeight->setMaximum(this->region_map->tilemapHeight() - this->region_map->padTop());
|
||||
this->ui->spinBox_RM_LayoutWidth->setValue(this->region_map->layoutWidth());
|
||||
this->ui->spinBox_RM_LayoutHeight->setValue(this->region_map->layoutHeight());
|
||||
this->ui->spinBox_RM_LayoutWidth->blockSignals(false);
|
||||
this->ui->spinBox_RM_LayoutHeight->blockSignals(false);
|
||||
}
|
||||
|
||||
void RegionMapEditor::displayRegionMapEntriesImage() {
|
||||
|
|
@ -732,8 +729,12 @@ void RegionMapEditor::displayRegionMapEntryOptions() {
|
|||
void RegionMapEditor::updateRegionMapEntryOptions(QString section) {
|
||||
if (!this->region_map->layoutEnabled()) return;
|
||||
|
||||
const QSignalBlocker b_X(this->ui->spinBox_RM_Entry_x);
|
||||
const QSignalBlocker b_Y(this->ui->spinBox_RM_Entry_y);
|
||||
const QSignalBlocker b_W(this->ui->spinBox_RM_Entry_width);
|
||||
const QSignalBlocker b_H(this->ui->spinBox_RM_Entry_height);
|
||||
|
||||
bool enabled = (section != this->region_map->default_map_section) && this->region_map_entries.contains(section);
|
||||
this->ui->lineEdit_RM_MapName->setEnabled(enabled);
|
||||
this->ui->spinBox_RM_Entry_x->setEnabled(enabled);
|
||||
this->ui->spinBox_RM_Entry_y->setEnabled(enabled);
|
||||
this->ui->spinBox_RM_Entry_width->setEnabled(enabled);
|
||||
|
|
@ -741,56 +742,31 @@ void RegionMapEditor::updateRegionMapEntryOptions(QString section) {
|
|||
this->ui->pushButton_entryActivate->setEnabled(section != this->region_map->default_map_section);
|
||||
this->ui->pushButton_entryActivate->setText(enabled ? "Remove" : "Add");
|
||||
|
||||
this->ui->lineEdit_RM_MapName->blockSignals(true);
|
||||
this->ui->spinBox_RM_Entry_x->blockSignals(true);
|
||||
this->ui->spinBox_RM_Entry_y->blockSignals(true);
|
||||
this->ui->spinBox_RM_Entry_width->blockSignals(true);
|
||||
this->ui->spinBox_RM_Entry_height->blockSignals(true);
|
||||
|
||||
this->ui->comboBox_RM_Entry_MapSection->setCurrentText(section);
|
||||
this->activeEntry = section;
|
||||
this->region_map_entries_item->currentSection = section;
|
||||
MapSectionEntry entry = enabled ? this->region_map_entries[section] : MapSectionEntry();
|
||||
this->ui->lineEdit_RM_MapName->setText(entry.name);
|
||||
this->ui->spinBox_RM_Entry_x->setValue(entry.x);
|
||||
this->ui->spinBox_RM_Entry_y->setValue(entry.y);
|
||||
this->ui->spinBox_RM_Entry_width->setValue(entry.width);
|
||||
this->ui->spinBox_RM_Entry_height->setValue(entry.height);
|
||||
|
||||
this->ui->lineEdit_RM_MapName->blockSignals(false);
|
||||
this->ui->spinBox_RM_Entry_x->blockSignals(false);
|
||||
this->ui->spinBox_RM_Entry_y->blockSignals(false);
|
||||
this->ui->spinBox_RM_Entry_width->blockSignals(false);
|
||||
this->ui->spinBox_RM_Entry_height->blockSignals(false);
|
||||
}
|
||||
|
||||
void RegionMapEditor::on_pushButton_entryActivate_clicked() {
|
||||
QString section = this->ui->comboBox_RM_Entry_MapSection->currentText();
|
||||
if (section == this->region_map->default_map_section) return;
|
||||
|
||||
MapSectionEntry oldEntry = this->region_map->getEntry(section);
|
||||
if (this->region_map_entries.contains(section)) {
|
||||
// disable
|
||||
MapSectionEntry oldEntry = this->region_map->getEntry(section);
|
||||
this->region_map->removeEntry(section);
|
||||
MapSectionEntry newEntry = this->region_map->getEntry(section);
|
||||
RemoveEntry *commit = new RemoveEntry(this->region_map, section, oldEntry, newEntry);
|
||||
this->region_map->editHistory.push(commit);
|
||||
updateRegionMapEntryOptions(section);
|
||||
|
||||
this->ui->pushButton_entryActivate->setText("Add");
|
||||
this->region_map->editHistory.push(new RemoveEntry(this->region_map, section, oldEntry, MapSectionEntry()));
|
||||
} else {
|
||||
// enable
|
||||
MapSectionEntry oldEntry = this->region_map->getEntry(section);
|
||||
MapSectionEntry entry = MapSectionEntry();
|
||||
entry.valid = true;
|
||||
this->region_map->setEntry(section, entry);
|
||||
MapSectionEntry newEntry = this->region_map->getEntry(section);
|
||||
AddEntry *commit = new AddEntry(this->region_map, section, oldEntry, newEntry);
|
||||
this->region_map->editHistory.push(commit);
|
||||
updateRegionMapEntryOptions(section);
|
||||
|
||||
this->ui->pushButton_entryActivate->setText("Remove");
|
||||
MapSectionEntry newEntry = MapSectionEntry();
|
||||
newEntry.valid = true;
|
||||
this->region_map->editHistory.push(new AddEntry(this->region_map, section, oldEntry, newEntry));
|
||||
}
|
||||
updateRegionMapEntryOptions(section);
|
||||
}
|
||||
|
||||
void RegionMapEditor::displayRegionMapTileSelector() {
|
||||
|
|
@ -936,7 +912,7 @@ void RegionMapEditor::on_tabWidget_Region_Map_currentChanged(int index) {
|
|||
break;
|
||||
case 2:
|
||||
this->ui->verticalSlider_Zoom_Image_Tiles->setVisible(false);
|
||||
on_comboBox_RM_Entry_MapSection_textActivated(ui->comboBox_RM_Entry_MapSection->currentText());
|
||||
on_comboBox_RM_Entry_MapSection_currentTextChanged(ui->comboBox_RM_Entry_MapSection->currentText());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -947,7 +923,7 @@ void RegionMapEditor::on_comboBox_RM_ConnectedMap_textActivated(const QString &m
|
|||
onRegionMapLayoutSelectedTileChanged(this->currIndex);// re-draw layout image
|
||||
}
|
||||
|
||||
void RegionMapEditor::on_comboBox_RM_Entry_MapSection_textActivated(const QString &text) {
|
||||
void RegionMapEditor::on_comboBox_RM_Entry_MapSection_currentTextChanged(const QString &text) {
|
||||
this->activeEntry = text;
|
||||
this->region_map_entries_item->currentSection = text;
|
||||
updateRegionMapEntryOptions(text);
|
||||
|
|
@ -1050,15 +1026,6 @@ void RegionMapEditor::on_spinBox_RM_LayoutHeight_valueChanged(int value) {
|
|||
}
|
||||
}
|
||||
|
||||
void RegionMapEditor::on_lineEdit_RM_MapName_textEdited(const QString &text) {
|
||||
if (!this->region_map_entries.contains(activeEntry)) return;
|
||||
MapSectionEntry oldEntry = this->region_map_entries[activeEntry];
|
||||
this->region_map_entries[activeEntry].name = text;
|
||||
MapSectionEntry newEntry = this->region_map_entries[activeEntry];
|
||||
EditEntry *commit = new EditEntry(this->region_map, activeEntry, oldEntry, newEntry);
|
||||
this->region_map->editHistory.push(commit);
|
||||
}
|
||||
|
||||
void RegionMapEditor::on_pushButton_RM_Options_delete_clicked() {
|
||||
int index = this->region_map->tilemapToLayoutIndex(this->currIndex);
|
||||
QList<LayoutSquare> oldLayout = this->region_map->getLayout(this->region_map->getLayer());
|
||||
|
|
@ -1151,7 +1118,7 @@ void RegionMapEditor::on_action_Swap_triggered() {
|
|||
connect(&buttonBox, &QDialogButtonBox::accepted, [&popup, &oldSecBox, &newSecBox, &beforeSection, &afterSection](){
|
||||
beforeSection = oldSecBox->currentText();
|
||||
afterSection = newSecBox->currentText();
|
||||
if (!beforeSection.isEmpty() && !afterSection.isEmpty()) {
|
||||
if (!beforeSection.isEmpty() && !afterSection.isEmpty() && beforeSection != afterSection) {
|
||||
popup.accept();
|
||||
}
|
||||
});
|
||||
|
|
@ -1190,7 +1157,7 @@ void RegionMapEditor::on_action_Replace_triggered() {
|
|||
connect(&buttonBox, &QDialogButtonBox::accepted, [&popup, &oldSecBox, &newSecBox, &beforeSection, &afterSection](){
|
||||
beforeSection = oldSecBox->currentText();
|
||||
afterSection = newSecBox->currentText();
|
||||
if (!beforeSection.isEmpty() && !afterSection.isEmpty()) {
|
||||
if (!beforeSection.isEmpty() && !afterSection.isEmpty() && beforeSection != afterSection) {
|
||||
popup.accept();
|
||||
}
|
||||
});
|
||||
|
|
@ -1269,7 +1236,7 @@ void RegionMapEditor::closeEvent(QCloseEvent *event)
|
|||
if (this->modified()) {
|
||||
QMessageBox::StandardButton result = QMessageBox::question(
|
||||
this,
|
||||
"porymap",
|
||||
QApplication::applicationName(),
|
||||
"The region map has been modified, save changes?",
|
||||
QMessageBox::No | QMessageBox::Yes | QMessageBox::Cancel,
|
||||
QMessageBox::Yes);
|
||||
|
|
@ -1323,3 +1290,18 @@ void RegionMapEditor::on_verticalSlider_Zoom_Image_Tiles_valueChanged(int val) {
|
|||
ui->graphicsView_RegionMap_Tiles->setTransform(transform);
|
||||
ui->graphicsView_RegionMap_Tiles->setFixedSize(width + 2, height + 2);
|
||||
}
|
||||
|
||||
// Repopulate the combo boxes that display MAPSEC names.
|
||||
void RegionMapEditor::setLocations(const QStringList &locations) {
|
||||
const QSignalBlocker b_ConnectedMap(ui->comboBox_RM_ConnectedMap);
|
||||
auto before = ui->comboBox_RM_ConnectedMap->currentText();
|
||||
ui->comboBox_RM_ConnectedMap->clear();
|
||||
ui->comboBox_RM_ConnectedMap->addItems(locations);
|
||||
ui->comboBox_RM_ConnectedMap->setCurrentText(before);
|
||||
|
||||
const QSignalBlocker b_MapSection(ui->comboBox_RM_Entry_MapSection);
|
||||
before = ui->comboBox_RM_Entry_MapSection->currentText();
|
||||
ui->comboBox_RM_Entry_MapSection->clear();
|
||||
ui->comboBox_RM_Entry_MapSection->addItems(locations);
|
||||
ui->comboBox_RM_Entry_MapSection->setCurrentText(before);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ void RegionMapEntriesPixmapItem::draw() {
|
|||
|
||||
int entry_x, entry_y, entry_w, entry_h;
|
||||
|
||||
if (!entry.valid || entry.name == region_map->default_map_section) {
|
||||
if (!entry.valid || currentSection == region_map->default_map_section) {
|
||||
entry_x = entry_y = 0;
|
||||
entry_w = entry_h = 1;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -158,7 +158,7 @@ void ShortcutsEditor::promptUserOnDuplicateFound(MultiKeyEdit *sender, MultiKeyE
|
|||
.arg(duplicateKeySequence.toString()).arg(siblingLabel);
|
||||
|
||||
const auto result = QMessageBox::question(
|
||||
this, "porymap", message, QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||
this, QApplication::applicationName(), message, QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||
|
||||
if (result == QMessageBox::Yes)
|
||||
removeKeySequence(duplicateKeySequence, sibling);
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@
|
|||
#include "ui_tileseteditor.h"
|
||||
#include "log.h"
|
||||
#include "imageproviders.h"
|
||||
#include "metatileparser.h"
|
||||
#include "advancemapparser.h"
|
||||
#include "paletteutil.h"
|
||||
#include "imageexport.h"
|
||||
#include "config.h"
|
||||
#include "shortcut.h"
|
||||
#include "filedialog.h"
|
||||
#include "validator.h"
|
||||
#include <QMessageBox>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QCloseEvent>
|
||||
|
|
@ -20,9 +21,33 @@ TilesetEditor::TilesetEditor(Project *project, Layout *layout, QWidget *parent)
|
|||
layout(layout),
|
||||
hasUnsavedChanges(false)
|
||||
{
|
||||
this->setAttribute(Qt::WA_DeleteOnClose);
|
||||
this->setTilesets(this->layout->tileset_primary_label, this->layout->tileset_secondary_label);
|
||||
this->initUi();
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
setTilesets(this->layout->tileset_primary_label, this->layout->tileset_secondary_label);
|
||||
ui->setupUi(this);
|
||||
|
||||
this->tileXFlip = ui->checkBox_xFlip->isChecked();
|
||||
this->tileYFlip = ui->checkBox_yFlip->isChecked();
|
||||
this->paletteId = ui->spinBox_paletteSelector->value();
|
||||
|
||||
// TODO: The dividing line at the moment is only accurate if the number of primary metatiles is divisible by 8.
|
||||
// If it's not, the secondary metatiles will wrap above the line. This has other problems (like skewing
|
||||
// metatile groups the user may have designed) so this should be fixed by filling the primary metatiles
|
||||
// image with invalid magenta metatiles until it's divisible by 8. Then the line can be re-enabled as-is.
|
||||
ui->actionShow_Tileset_Divider->setChecked(/*porymapConfig.showTilesetEditorDivider*/false);
|
||||
ui->actionShow_Tileset_Divider->setVisible(false);
|
||||
|
||||
ui->spinBox_paletteSelector->setMinimum(0);
|
||||
ui->spinBox_paletteSelector->setMaximum(Project::getNumPalettesTotal() - 1);
|
||||
ui->lineEdit_metatileLabel->setValidator(new IdentifierValidator(this));
|
||||
|
||||
setAttributesUi();
|
||||
initMetatileSelector();
|
||||
initMetatileLayersItem();
|
||||
initTileSelector();
|
||||
initSelectedTileItem();
|
||||
initShortcuts();
|
||||
this->metatileSelector->select(0);
|
||||
restoreWindowState();
|
||||
}
|
||||
|
||||
TilesetEditor::~TilesetEditor()
|
||||
|
|
@ -57,7 +82,7 @@ void TilesetEditor::updateTilesets(QString primaryTilesetLabel, QString secondar
|
|||
if (this->hasUnsavedChanges) {
|
||||
QMessageBox::StandardButton result = QMessageBox::question(
|
||||
this,
|
||||
"porymap",
|
||||
QApplication::applicationName(),
|
||||
"Tileset has been modified, save changes?",
|
||||
QMessageBox::No | QMessageBox::Yes,
|
||||
QMessageBox::Yes);
|
||||
|
|
@ -92,33 +117,6 @@ void TilesetEditor::setTilesets(QString primaryTilesetLabel, QString secondaryTi
|
|||
this->initMetatileHistory();
|
||||
}
|
||||
|
||||
void TilesetEditor::initUi() {
|
||||
ui->setupUi(this);
|
||||
this->tileXFlip = ui->checkBox_xFlip->isChecked();
|
||||
this->tileYFlip = ui->checkBox_yFlip->isChecked();
|
||||
this->paletteId = ui->spinBox_paletteSelector->value();
|
||||
this->ui->spinBox_paletteSelector->setMinimum(0);
|
||||
this->ui->spinBox_paletteSelector->setMaximum(Project::getNumPalettesTotal() - 1);
|
||||
|
||||
// TODO: The dividing line at the moment is only accurate if the number of primary metatiles is divisible by 8.
|
||||
// If it's not, the secondary metatiles will wrap above the line. This has other problems (like skewing
|
||||
// metatile groups the user may have designed) so this should be fixed by filling the primary metatiles
|
||||
// image with invalid magenta metatiles until it's divisible by 8. Then the line can be re-enabled as-is.
|
||||
this->ui->actionShow_Tileset_Divider->setChecked(/*porymapConfig.showTilesetEditorDivider*/false);
|
||||
this->ui->actionShow_Tileset_Divider->setVisible(false);
|
||||
|
||||
this->setAttributesUi();
|
||||
this->setMetatileLabelValidator();
|
||||
|
||||
this->initMetatileSelector();
|
||||
this->initMetatileLayersItem();
|
||||
this->initTileSelector();
|
||||
this->initSelectedTileItem();
|
||||
this->initShortcuts();
|
||||
this->metatileSelector->select(0);
|
||||
this->restoreWindowState();
|
||||
}
|
||||
|
||||
void TilesetEditor::setAttributesUi() {
|
||||
// Behavior
|
||||
if (projectConfig.metatileBehaviorMask) {
|
||||
|
|
@ -178,13 +176,6 @@ void TilesetEditor::setAttributesUi() {
|
|||
this->ui->frame_Properties->adjustSize();
|
||||
}
|
||||
|
||||
void TilesetEditor::setMetatileLabelValidator() {
|
||||
//only allow characters valid for a symbol
|
||||
static const QRegularExpression expression("[_A-Za-z0-9]*$");
|
||||
QRegularExpressionValidator *validator = new QRegularExpressionValidator(expression);
|
||||
this->ui->lineEdit_metatileLabel->setValidator(validator);
|
||||
}
|
||||
|
||||
void TilesetEditor::initMetatileSelector()
|
||||
{
|
||||
this->metatileSelector = new TilesetEditorMetatileSelector(this->primaryTileset, this->secondaryTileset, this->layout);
|
||||
|
|
@ -726,22 +717,9 @@ void TilesetEditor::importTilesetTiles(Tileset *tileset, bool primary) {
|
|||
image = image.convertToFormat(QImage::Format::Format_Indexed8, colorTable);
|
||||
}
|
||||
|
||||
// Validate image is properly indexed to 16 colors.
|
||||
int colorCount = image.colorCount();
|
||||
if (colorCount > 16) {
|
||||
flattenTo4bppImage(&image);
|
||||
} else if (colorCount < 16) {
|
||||
QVector<QRgb> colorTable = image.colorTable();
|
||||
for (int i = colorTable.length(); i < 16; i++) {
|
||||
colorTable.append(Qt::black);
|
||||
}
|
||||
image.setColorTable(colorTable);
|
||||
}
|
||||
|
||||
this->project->loadTilesetTiles(tileset, image);
|
||||
tileset->loadTilesImage(&image);
|
||||
this->refresh();
|
||||
this->hasUnsavedChanges = true;
|
||||
tileset->hasUnsavedTilesImage = true;
|
||||
}
|
||||
|
||||
void TilesetEditor::closeEvent(QCloseEvent *event)
|
||||
|
|
@ -749,7 +727,7 @@ void TilesetEditor::closeEvent(QCloseEvent *event)
|
|||
if (this->hasUnsavedChanges) {
|
||||
QMessageBox::StandardButton result = QMessageBox::question(
|
||||
this,
|
||||
"porymap",
|
||||
QApplication::applicationName(),
|
||||
"Tileset has been modified, save changes?",
|
||||
QMessageBox::No | QMessageBox::Yes | QMessageBox::Cancel,
|
||||
QMessageBox::Yes);
|
||||
|
|
@ -988,7 +966,7 @@ void TilesetEditor::importTilesetMetatiles(Tileset *tileset, bool primary)
|
|||
}
|
||||
|
||||
bool error = false;
|
||||
QList<Metatile*> metatiles = MetatileParser::parse(filepath, &error, primary);
|
||||
QList<Metatile*> metatiles = AdvanceMapParser::parseMetatiles(filepath, &error, primary);
|
||||
if (error) {
|
||||
QMessageBox msgBox(this);
|
||||
msgBox.setText("Failed to import metatiles from Advance Map 1.92 .bvd file.");
|
||||
|
|
@ -997,6 +975,7 @@ void TilesetEditor::importTilesetMetatiles(Tileset *tileset, bool primary)
|
|||
msgBox.setDefaultButton(QMessageBox::Ok);
|
||||
msgBox.setIcon(QMessageBox::Icon::Critical);
|
||||
msgBox.exec();
|
||||
qDeleteAll(metatiles);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -465,7 +465,7 @@ void WildMonChart::showHelpDialog() {
|
|||
informativeText = levelTabInfo;
|
||||
}
|
||||
|
||||
QMessageBox msgBox(QMessageBox::Information, "porymap", text, QMessageBox::Close, this);
|
||||
QMessageBox msgBox(QMessageBox::Information, QApplication::applicationName(), text, QMessageBox::Close, this);
|
||||
msgBox.setTextFormat(Qt::RichText);
|
||||
msgBox.setInformativeText(informativeText);
|
||||
msgBox.exec();
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user