Merge pull request from garakmon/slam

Separate Layouts and Maps
This commit is contained in:
t 2024-11-11 11:10:00 -05:00 committed by GitHub
commit c9695521c7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
85 changed files with 4750 additions and 2592 deletions
docsrc/manual
forms
include
porymap.pro
resources
src

View file

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

File diff suppressed because it is too large Load diff

175
forms/maplisttoolbar.ui Normal file
View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -10,6 +10,7 @@
#include <QCheckBox>
#include <QCursor>
#include <QUndoGroup>
#include <QPointer>
#include "mapconnection.h"
#include "metatileselector.h"
@ -21,7 +22,7 @@
#include "divingmappixmapitem.h"
#include "currentselectedmetatilespixmapitem.h"
#include "collisionpixmapitem.h"
#include "mappixmapitem.h"
#include "layoutpixmapitem.h"
#include "settings.h"
#include "gridsettings.h"
#include "movablerect.h"
@ -46,18 +47,33 @@ public:
public:
Ui::MainWindow* ui;
QObject *parent = nullptr;
QPointer<Project> project = nullptr;
Map *map = nullptr;
QPointer<Map> map = nullptr;
QPointer<Layout> layout = nullptr;
QUndoGroup editGroup; // Manages the undo history for each map
Settings *settings;
GridSettings gridSettings;
void setProject(Project * project);
void saveProject();
void save();
void closeProject();
bool setMap(QString map_name);
void saveProject();
void saveUiFields();
void saveEncounterTabData();
void closeProject();
bool setMap(QString map_name);
bool setLayout(QString layoutName);
void unsetMap();
Tileset *getCurrentMapPrimaryTileset();
bool displayMap();
bool displayLayout();
void displayMetatileSelector();
void displayMapMetatiles();
void displayMapMovementPermissions();
@ -75,56 +91,54 @@ public:
void updateMapBorder();
void updateMapConnections();
void setEditingMap();
void setEditingCollision();
void setEditingObjects();
void setEditingConnections();
void setMapEditingButtonsEnabled(bool enabled);
void setConnectionsVisibility(bool visible);
void updateDivingMapsVisibility();
void renderDivingConnections();
void addConnection(MapConnection* connection);
void removeConnection(MapConnection* connection);
void removeSelectedConnection();
void addNewWildMonGroup(QWidget *window);
void deleteWildMonGroup();
void configureEncounterJSON(QWidget *);
EncounterTableModel* getCurrentWildMonTable();
void updateDiveMap(QString mapName);
void updateEmergeMap(QString mapName);
void setSelectedConnection(MapConnection *connection);
void updatePrimaryTileset(QString tilesetLabel, bool forceLoad = false);
void updateSecondaryTileset(QString tilesetLabel, bool forceLoad = false);
void toggleBorderVisibility(bool visible, bool enableScriptCallback = true);
void updateCustomMapHeaderValues(QTableWidget *);
void configureEncounterJSON(QWidget *);
Tileset *getCurrentMapPrimaryTileset();
DraggablePixmapItem *addMapEvent(Event *event);
bool eventLimitReached(Map *, Event::Type);
void selectMapEvent(DraggablePixmapItem *object, bool toggle = false);
DraggablePixmapItem *addNewEvent(Event::Type type);
void updateSelectedEvents();
void duplicateSelectedEvents();
void redrawObject(DraggablePixmapItem *item);
QList<DraggablePixmapItem *> getObjects();
void updateCursorRectPos(int x, int y);
void setCursorRectVisible(bool visible);
void updateWarpEventWarning(Event *event);
void updateWarpEventWarnings();
bool eventLimitReached(Map *, Event::Type);
QPointer<QGraphicsScene> scene = nullptr;
QGraphicsPixmapItem *current_view = nullptr;
QPointer<MapPixmapItem> map_item = nullptr;
QPointer<LayoutPixmapItem> map_item = nullptr;
QList<QPointer<ConnectionPixmapItem>> connection_items;
QMap<QString, QPointer<DivingMapPixmapItem>> diving_map_items;
QGraphicsPathItem *connection_mask = nullptr;
QPointer<CollisionPixmapItem> collision_item = nullptr;
QGraphicsItemGroup *events_group = nullptr;
QList<QGraphicsPixmapItem*> borderItems;
QGraphicsItemGroup *mapGrid = nullptr;
MapRuler *map_ruler = nullptr;
MovableRect *playerViewRect = nullptr;
CursorTileRect *cursorMapTileRect = nullptr;
MapRuler *map_ruler = nullptr;
QPointer<QGraphicsScene> scene_metatiles = nullptr;
QPointer<QGraphicsScene> scene_current_metatile_selection = nullptr;
@ -140,8 +154,27 @@ public:
QPointer<ConnectionPixmapItem> selected_connection_item = nullptr;
QPointer<MapConnection> connection_to_select = nullptr;
QString map_edit_mode = "paint";
QString obj_edit_mode = "select";
enum class EditAction { None, Paint, Select, Fill, Shift, Pick, Move };
EditAction mapEditAction = EditAction::Paint;
EditAction objectEditAction = EditAction::Select;
enum class EditMode { None, Disabled, Metatiles, Collision, Header, Events, Connections, Encounters };
EditMode editMode = EditMode::None;
void setEditMode(EditMode mode) { this->editMode = mode; }
EditMode getEditMode() { return this->editMode; }
bool getEditingLayout();
void setEditorView();
void setEditingMetatiles();
void setEditingCollision();
void setEditingHeader();
void setEditingObjects();
void setEditingConnections();
void setEditingEncounters();
void setMapEditingButtonsEnabled(bool enabled);
int scaleIndex = 2;
qreal collisionOpacity = 0.5;
@ -151,10 +184,9 @@ public:
int getBorderDrawDistance(int dimension);
QUndoGroup editGroup; // Manages the undo history for each map
bool selectingEvent = false;
void deleteSelectedEvents();
void shouldReselectEvents();
void scaleMapView(int);
static void openInTextEditor(const QString &path, int lineNum = 0);
@ -206,11 +238,11 @@ private:
qint64 *pid = nullptr);
private slots:
void onMapStartPaint(QGraphicsSceneMouseEvent *event, MapPixmapItem *item);
void onMapEndPaint(QGraphicsSceneMouseEvent *event, MapPixmapItem *item);
void onMapStartPaint(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *item);
void onMapEndPaint(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *item);
void setSmartPathCursorMode(QGraphicsSceneMouseEvent *event);
void setStraightPathCursorMode(QGraphicsSceneMouseEvent *event);
void mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item);
void mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *item);
void mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item);
void setSelectedConnectionItem(ConnectionPixmapItem *connectionItem);
void onHoveredMovementPermissionChanged(uint16_t, uint16_t);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

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

View file

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

View file

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

View file

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

View file

@ -45,6 +45,7 @@ public:
private:
Ui::MapImageExporter *ui;
Layout *layout = nullptr;
Map *map = nullptr;
Editor *editor = nullptr;
QGraphicsScene *scene = nullptr;

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -72,14 +72,16 @@ SOURCES += src/core/block.cpp \
src/ui/cursortilerect.cpp \
src/ui/customattributestable.cpp \
src/ui/eventframes.cpp \
src/ui/eventfilters.cpp \
src/ui/filterchildrenproxymodel.cpp \
src/ui/maplistmodels.cpp \
src/ui/maplisttoolbar.cpp \
src/ui/graphicsview.cpp \
src/ui/imageproviders.cpp \
src/ui/mappixmapitem.cpp \
src/ui/layoutpixmapitem.cpp \
src/ui/prefabcreationdialog.cpp \
src/ui/regionmappixmapitem.cpp \
src/ui/citymappixmapitem.cpp \
src/ui/mapsceneeventfilter.cpp \
src/ui/metatilelayersitem.cpp \
src/ui/metatileselector.cpp \
src/ui/movablerect.cpp \
@ -170,16 +172,18 @@ HEADERS += include/core/block.h \
include/ui/cursortilerect.h \
include/ui/customattributestable.h \
include/ui/eventframes.h \
include/ui/eventfilters.h \
include/ui/filterchildrenproxymodel.h \
include/ui/maplistmodels.h \
include/ui/maplisttoolbar.h \
include/ui/graphicsview.h \
include/ui/imageproviders.h \
include/ui/mappixmapitem.h \
include/ui/layoutpixmapitem.h \
include/ui/mapview.h \
include/ui/prefabcreationdialog.h \
include/ui/regionmappixmapitem.h \
include/ui/citymappixmapitem.h \
include/ui/colorinputwidget.h \
include/ui/mapsceneeventfilter.h \
include/ui/metatilelayersitem.h \
include/ui/metatileselector.h \
include/ui/movablerect.h \
@ -227,6 +231,7 @@ FORMS += forms/mainwindow.ui \
forms/colorinputwidget.ui \
forms/connectionslistitem.ui \
forms/gridsettingsdialog.ui \
forms/maplisttoolbar.ui \
forms/newmapconnectiondialog.ui \
forms/prefabcreationdialog.ui \
forms/prefabframe.ui \

Binary file not shown.

Before

(image error) Size: 1.1 KiB

After

(image error) Size: 1.1 KiB

Binary file not shown.

Before

(image error) Size: 318 B

After

(image error) Size: 1.8 KiB

Binary file not shown.

After

(image error) Size: 1.1 KiB

Binary file not shown.

Before

(image error) Size: 318 B

After

(image error) Size: 2.1 KiB

BIN
resources/icons/folder_add.ico Executable file

Binary file not shown.

After

(image error) Size: 1.5 KiB

Binary file not shown.

Before

(image error) Size: 1.1 KiB

After

(image error) Size: 5.4 KiB

Binary file not shown.

After

(image error) Size: 4.2 KiB

Binary file not shown.

After

(image error) Size: 4.2 KiB

Binary file not shown.

After

(image error) Size: 4.3 KiB

Binary file not shown.

After

(image error) Size: 1.1 KiB

BIN
resources/icons/minimap.ico Normal file

Binary file not shown.

After

(image error) Size: 1.4 KiB

Binary file not shown.

After

(image error) Size: 4.2 KiB

View file

@ -10,18 +10,24 @@
<file>icons/file_put.ico</file>
<file>icons/fill_color_cursor.ico</file>
<file>icons/fill_color.ico</file>
<file>icons/folder_add.ico</file>
<file>icons/folder_closed_map.ico</file>
<file>icons/folder_closed.ico</file>
<file>icons/folder_eye_closed.ico</file>
<file>icons/folder_eye_open.ico</file>
<file>icons/folder_map_edited.ico</file>
<file>icons/folder_map_opened.ico</file>
<file>icons/folder_map.ico</file>
<file>icons/folder.ico</file>
<file>icons/lock_edit.ico</file>
<file>icons/unlock_edit.ico</file>
<file>icons/help.ico</file>
<file>icons/link_broken.ico</file>
<file>icons/link.ico</file>
<file>icons/map_edited.ico</file>
<file>icons/map_opened.ico</file>
<file>icons/map.ico</file>
<file>icons/map_grayed.ico</file>
<file>icons/move.ico</file>
<file>icons/pencil_cursor.ico</file>
<file>icons/pencil.ico</file>
@ -37,7 +43,10 @@
<file>icons/sort_map.ico</file>
<file>icons/sort_number.ico</file>
<file>icons/tall_grass.ico</file>
<file>icons/minimap.ico</file>
<file>icons/viewsprites.ico</file>
<file>icons/application_form_edit.ico</file>
<file>icons/connections.ico</file>
<file>icons/ui/dark_checkbox_checked_disabled.png</file>
<file>icons/ui/dark_checkbox_checked_disabled@2x.png</file>
<file>icons/ui/dark_checkbox_checked.png</file>

View file

@ -110,7 +110,6 @@ const QMap<ProjectIdentifier, QPair<QString, QString>> ProjectConfig::defaultIde
{ProjectIdentifier::define_map_empty, {"define_map_empty", "UNDEFINED"}},
{ProjectIdentifier::define_map_section_prefix, {"define_map_section_prefix", "MAPSEC_"}},
{ProjectIdentifier::define_map_section_empty, {"define_map_section_empty", "NONE"}},
{ProjectIdentifier::define_map_section_count, {"define_map_section_count", "COUNT"}},
{ProjectIdentifier::define_species_prefix, {"define_species_prefix", "SPECIES_"}},
// Regex
{ProjectIdentifier::regex_behaviors, {"regex_behaviors", "\\bMB_"}},
@ -167,7 +166,6 @@ const QMap<ProjectFilePath, QPair<QString, QString>> ProjectConfig::defaultPaths
{ProjectFilePath::constants_obj_event_movement, { "constants_obj_event_movement", "include/constants/event_object_movement.h"}},
{ProjectFilePath::constants_obj_events, { "constants_obj_events", "include/constants/event_objects.h"}},
{ProjectFilePath::constants_event_bg, { "constants_event_bg", "include/constants/event_bg.h"}},
{ProjectFilePath::constants_region_map_sections, { "constants_region_map_sections", "include/constants/region_map_sections.h"}},
{ProjectFilePath::constants_metatile_labels, { "constants_metatile_labels", "include/constants/metatile_labels.h"}},
{ProjectFilePath::constants_metatile_behaviors, { "constants_metatile_behaviors", "include/constants/metatile_behaviors.h"}},
{ProjectFilePath::constants_species, { "constants_species", "include/constants/species.h"}},
@ -278,18 +276,6 @@ uint32_t KeyValueConfigBase::getConfigUint32(QString key, QString value, uint32_
return qMin(max, qMax(min, result));
}
const QMap<MapSortOrder, QString> mapSortOrderMap = {
{MapSortOrder::Group, "group"},
{MapSortOrder::Layout, "layout"},
{MapSortOrder::Area, "area"},
};
const QMap<QString, MapSortOrder> mapSortOrderReverseMap = {
{"group", MapSortOrder::Group},
{"layout", MapSortOrder::Layout},
{"area", MapSortOrder::Area},
};
PorymapConfig porymapConfig;
QString PorymapConfig::getConfigFilepath() {
@ -314,14 +300,8 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) {
this->reopenOnLaunch = getConfigBool(key, value);
} else if (key == "pretty_cursors") {
this->prettyCursors = getConfigBool(key, value);
} else if (key == "map_sort_order") {
QString sortOrder = value.toLower();
if (mapSortOrderReverseMap.contains(sortOrder)) {
this->mapSortOrder = mapSortOrderReverseMap.value(sortOrder);
} else {
this->mapSortOrder = MapSortOrder::Group;
logWarn(QString("Invalid config value for map_sort_order: '%1'. Must be 'group', 'area', or 'layout'.").arg(value));
}
} else if (key == "map_list_tab") {
this->mapListTab = getConfigInteger(key, value, 0, 2, 0);
} else if (key == "main_window_geometry") {
this->mainWindowGeometry = bytesFromString(value);
} else if (key == "main_window_state") {
@ -438,7 +418,7 @@ QMap<QString, QString> PorymapConfig::getKeyValueMap() {
map.insert("project_manually_closed", this->projectManuallyClosed ? "1" : "0");
map.insert("reopen_on_launch", this->reopenOnLaunch ? "1" : "0");
map.insert("pretty_cursors", this->prettyCursors ? "1" : "0");
map.insert("map_sort_order", mapSortOrderMap.value(this->mapSortOrder));
map.insert("map_list_tab", QString::number(this->mapListTab));
map.insert("main_window_geometry", stringFromByteArray(this->mainWindowGeometry));
map.insert("main_window_state", stringFromByteArray(this->mainWindowState));
map.insert("map_splitter_state", stringFromByteArray(this->mapSplitterState));
@ -740,8 +720,8 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
} else if (key == "enable_map_allow_flags") {
this->mapAllowFlagsEnabled = getConfigBool(key, value);
#ifdef CONFIG_BACKWARDS_COMPATABILITY
} else if (key == "recent_map") {
userConfig.recentMap = value;
} else if (key == "recent_map_or_layout") {
userConfig.recentMapOrLayout = value;
} else if (key == "use_encounter_json") {
userConfig.useEncounterJson = getConfigBool(key, value);
} else if (key == "custom_scripts") {
@ -1035,8 +1015,8 @@ QString UserConfig::getConfigFilepath() {
}
void UserConfig::parseConfigKeyValue(QString key, QString value) {
if (key == "recent_map") {
this->recentMap = value;
if (key == "recent_map_or_layout") {
this->recentMapOrLayout = value;
} else if (key == "use_encounter_json") {
this->useEncounterJson = getConfigBool(key, value);
} else if (key == "custom_scripts") {
@ -1052,7 +1032,7 @@ void UserConfig::setUnreadKeys() {
QMap<QString, QString> UserConfig::getKeyValueMap() {
QMap<QString, QString> map;
map.insert("recent_map", this->recentMap);
map.insert("recent_map_or_layout", this->recentMapOrLayout);
map.insert("use_encounter_json", QString::number(this->useEncounterJson));
map.insert("custom_scripts", this->outputCustomScripts());
return map;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -4,7 +4,7 @@
#include "log.h"
#include "connectionslistitem.h"
#include "currentselectedmetatilespixmapitem.h"
#include "mapsceneeventfilter.h"
#include "eventfilters.h"
#include "metatile.h"
#include "montabwidget.h"
#include "editcommands.h"
@ -75,10 +75,14 @@ void Editor::saveProject() {
}
void Editor::save() {
if (project && map) {
if (this->project && this->map) {
saveUiFields();
project->saveMap(map);
project->saveAllDataStructures();
this->project->saveMap(this->map);
this->project->saveAllDataStructures();
}
else if (this->project && this->layout) {
this->project->saveLayout(this->layout);
this->project->saveAllDataStructures();
}
}
@ -102,66 +106,103 @@ void Editor::closeProject() {
delete this->project;
}
void Editor::setEditingMap() {
current_view = map_item;
if (map_item) {
map_item->paintingMode = MapPixmapItem::PaintMode::Metatiles;
map_item->draw();
map_item->setVisible(true);
}
if (collision_item) {
collision_item->setVisible(false);
}
if (events_group) {
events_group->setVisible(false);
bool Editor::getEditingLayout() {
return this->editMode == EditMode::Metatiles || this->editMode == EditMode::Collision;
}
void Editor::setEditorView() {
// based on editMode
if (!map_item || !collision_item) return;
if (!this->layout) return;
map_item->setVisible(true); // is map item ever not visible
collision_item->setVisible(false);
switch (this->editMode) {
case EditMode::Metatiles:
case EditMode::Connections:
case EditMode::Events:
current_view = map_item;
break;
case EditMode::Collision:
current_view = collision_item;
break;
default:
current_view = nullptr;
return;
}
map_item->draw();
collision_item->draw();
current_view->setVisible(true);
updateBorderVisibility();
this->cursorMapTileRect->stopSingleTileMode();
this->cursorMapTileRect->setSingleTileMode();
this->cursorMapTileRect->setActive(true);
setMapEditingButtonsEnabled(true);
switch (this->editMode) {
case EditMode::Metatiles:
case EditMode::Collision:
map_item->setEditsEnabled(true);
this->editGroup.setActiveStack(&this->layout->editHistory);
break;
case EditMode::Connections:
this->cursorMapTileRect->setActive(false);
map_item->setEditsEnabled(false);
case EditMode::Events:
if (this->map) {
this->editGroup.setActiveStack(&this->map->editHistory);
}
break;
case EditMode::Header:
case EditMode::Encounters:
default:
this->editGroup.setActiveStack(nullptr);
break;
}
if (this->events_group) {
this->events_group->setVisible(this->editMode == EditMode::Events);
}
setMapEditingButtonsEnabled(this->editMode != EditMode::Events);
}
void Editor::setEditingMetatiles() {
this->editMode = EditMode::Metatiles;
setEditorView();
}
void Editor::setEditingCollision() {
current_view = collision_item;
if (collision_item) {
collision_item->draw();
collision_item->setVisible(true);
}
if (map_item) {
map_item->paintingMode = MapPixmapItem::PaintMode::Metatiles;
map_item->draw();
map_item->setVisible(true);
}
if (events_group) {
events_group->setVisible(false);
}
updateBorderVisibility();
this->cursorMapTileRect->setSingleTileMode();
this->cursorMapTileRect->setActive(true);
this->editMode = EditMode::Collision;
setMapEditingButtonsEnabled(true);
setEditorView();
}
void Editor::setEditingHeader() {
this->editMode = EditMode::Header;
setEditorView();
}
void Editor::setEditingObjects() {
current_view = map_item;
if (events_group) {
events_group->setVisible(true);
}
if (map_item) {
map_item->paintingMode = MapPixmapItem::PaintMode::EventObjects;
map_item->draw();
map_item->setVisible(true);
}
if (collision_item) {
collision_item->setVisible(false);
}
updateBorderVisibility();
this->cursorMapTileRect->setSingleTileMode();
this->cursorMapTileRect->setActive(false);
updateWarpEventWarnings();
this->editMode = EditMode::Events;
setMapEditingButtonsEnabled(false);
setEditorView();
updateWarpEventWarnings();
}
void Editor::setEditingConnections() {
this->editMode = EditMode::Connections;
setEditorView();
}
void Editor::setEditingEncounters() {
this->editMode = EditMode::Encounters;
setEditorView();
}
void Editor::setMapEditingButtonsEnabled(bool enabled) {
@ -170,7 +211,7 @@ void Editor::setMapEditingButtonsEnabled(bool enabled) {
this->ui->pushButton_ChangeDimensions->setEnabled(enabled);
// If the fill button is pressed, unpress it and select the pointer.
if (!enabled && (this->ui->toolButton_Fill->isChecked() || this->ui->toolButton_Dropper->isChecked())) {
this->map_edit_mode = "select";
this->mapEditAction = EditAction::Select;
this->settings->mapCursor = QCursor();
this->cursorMapTileRect->setSingleTileMode();
this->ui->toolButton_Fill->setChecked(false);
@ -180,24 +221,6 @@ void Editor::setMapEditingButtonsEnabled(bool enabled) {
this->ui->checkBox_smartPaths->setEnabled(enabled);
}
void Editor::setEditingConnections() {
current_view = map_item;
if (map_item) {
map_item->paintingMode = MapPixmapItem::PaintMode::Disabled;
map_item->draw();
map_item->setVisible(true);
}
if (collision_item) {
collision_item->setVisible(false);
}
if (events_group) {
events_group->setVisible(false);
}
updateBorderVisibility();
this->cursorMapTileRect->setSingleTileMode();
this->cursorMapTileRect->setActive(false);
}
void Editor::clearWildMonTables() {
QStackedWidget *stack = ui->stackedWidget_WildMons;
const QSignalBlocker blocker(stack);
@ -788,6 +811,9 @@ void Editor::displayConnection(MapConnection *connection) {
connect(listItem, &ConnectionsListItem::openMapClicked, this, &Editor::openConnectedMap);
connect(pixmapItem, &ConnectionPixmapItem::connectionItemDoubleClicked, this, &Editor::openConnectedMap);
// Pressing the delete key on a selected connection's pixmap deletes it
connect(pixmapItem, &ConnectionPixmapItem::deleteRequested, this, &Editor::removeConnection);
// Sync the selection highlight between the list UI and the pixmap
connect(pixmapItem, &ConnectionPixmapItem::selectionChanged, [=](bool selected) {
listItem->setSelected(selected);
@ -846,11 +872,6 @@ void Editor::removeConnection(MapConnection *connection) {
this->map->editHistory.push(new MapConnectionRemove(this->map, connection));
}
void Editor::removeSelectedConnection() {
if (selected_connection_item)
removeConnection(selected_connection_item->connection);
}
void Editor::removeConnectionPixmap(MapConnection *connection) {
if (!connection)
return;
@ -1059,8 +1080,8 @@ void Editor::onHoveredMovementPermissionCleared() {
}
QString Editor::getMetatileDisplayMessage(uint16_t metatileId) {
Metatile *metatile = Tileset::getMetatile(metatileId, map->layout->tileset_primary, map->layout->tileset_secondary);
QString label = Tileset::getMetatileLabel(metatileId, map->layout->tileset_primary, map->layout->tileset_secondary);
Metatile *metatile = Tileset::getMetatile(metatileId, this->layout->tileset_primary, this->layout->tileset_secondary);
QString label = Tileset::getMetatileLabel(metatileId, this->layout->tileset_primary, this->layout->tileset_secondary);
QString message = QString("Metatile: %1").arg(Metatile::getMetatileIdString(metatileId));
if (label.size())
message += QString(" \"%1\"").arg(label);
@ -1146,46 +1167,46 @@ void Editor::setCursorRectVisible(bool visible) {
void Editor::onHoveredMapMetatileChanged(const QPoint &pos) {
int x = pos.x();
int y = pos.y();
if (!map->isWithinBounds(x, y))
if (!layout->isWithinBounds(x, y))
return;
this->updateCursorRectPos(x, y);
if (map_item->paintingMode == MapPixmapItem::PaintMode::Metatiles) {
int blockIndex = y * map->getWidth() + x;
int metatileId = map->layout->blockdata.at(blockIndex).metatileId();
if (this->getEditingLayout()) {
int blockIndex = y * layout->getWidth() + x;
int metatileId = layout->blockdata.at(blockIndex).metatileId();
this->ui->statusBar->showMessage(QString("X: %1, Y: %2, %3, Scale = %4x")
.arg(x)
.arg(y)
.arg(getMetatileDisplayMessage(metatileId))
.arg(QString::number(zoomLevels[this->scaleIndex], 'g', 2)));
}
else if (map_item->paintingMode == MapPixmapItem::PaintMode::EventObjects) {
else if (this->editMode == EditMode::Events) {
this->ui->statusBar->showMessage(QString("X: %1, Y: %2, Scale = %3x")
.arg(x)
.arg(y)
.arg(QString::number(zoomLevels[this->scaleIndex], 'g', 2)));
}
Scripting::cb_BlockHoverChanged(x, y);
}
void Editor::onHoveredMapMetatileCleared() {
this->setCursorRectVisible(false);
if (map_item->paintingMode == MapPixmapItem::PaintMode::Metatiles
|| map_item->paintingMode == MapPixmapItem::PaintMode::EventObjects) {
if (!map_item->getEditsEnabled()) {
this->ui->statusBar->clearMessage();
}
Scripting::cb_BlockHoverCleared();
}
void Editor::onHoveredMapMovementPermissionChanged(int x, int y) {
if (!map->isWithinBounds(x, y))
if (!layout->isWithinBounds(x, y))
return;
this->updateCursorRectPos(x, y);
if (map_item->paintingMode == MapPixmapItem::PaintMode::Metatiles) {
int blockIndex = y * map->getWidth() + x;
uint16_t collision = map->layout->blockdata.at(blockIndex).collision();
uint16_t elevation = map->layout->blockdata.at(blockIndex).elevation();
if (this->getEditingLayout()) {
int blockIndex = y * layout->getWidth() + x;
uint16_t collision = layout->blockdata.at(blockIndex).collision();
uint16_t elevation = layout->blockdata.at(blockIndex).elevation();
QString message = QString("X: %1, Y: %2, %3")
.arg(x)
.arg(y)
@ -1197,7 +1218,7 @@ void Editor::onHoveredMapMovementPermissionChanged(int x, int y) {
void Editor::onHoveredMapMovementPermissionCleared() {
this->setCursorRectVisible(false);
if (map_item->paintingMode == MapPixmapItem::PaintMode::Metatiles) {
if (this->getEditingLayout()) {
this->ui->statusBar->clearMessage();
}
Scripting::cb_BlockHoverCleared();
@ -1219,11 +1240,7 @@ QString Editor::getMovementPermissionText(uint16_t collision, uint16_t elevation
return message;
}
bool Editor::setMap(QString map_name) {
if (map_name.isEmpty()) {
return false;
}
void Editor::unsetMap() {
// disconnect previous map's signals so they are not firing
// multiple times if set again in the future
if (map) {
@ -1232,47 +1249,90 @@ bool Editor::setMap(QString map_name) {
for (auto connection : map->getConnections())
disconnectMapConnection(connection);
}
clearMapConnections();
if (project) {
Map *loadedMap = project->loadMap(map_name);
if (!loadedMap) {
return false;
}
this->map = nullptr;
}
map = loadedMap;
editGroup.addStack(&map->editHistory);
editGroup.setActiveStack(&map->editHistory);
selected_events->clear();
if (!displayMap()) {
return false;
}
map_ruler->setMapDimensions(QSize(map->getWidth(), map->getHeight()));
connect(map, &Map::mapDimensionsChanged, map_ruler, &MapRuler::setMapDimensions);
connect(map, &Map::openScriptRequested, this, &Editor::openScript);
connect(map, &Map::connectionAdded, this, &Editor::displayConnection);
connect(map, &Map::connectionRemoved, this, &Editor::removeConnectionPixmap);
updateSelectedEvents();
bool Editor::setMap(QString map_name) {
if (!project || map_name.isEmpty()) {
return false;
}
unsetMap();
Map *loadedMap = project->loadMap(map_name);
if (!loadedMap) {
return false;
}
this->map = loadedMap;
setLayout(map->layout->id);
editGroup.addStack(&map->editHistory);
editGroup.setActiveStack(&map->editHistory);
selected_events->clear();
if (!displayMap()) {
return false;
}
displayWildMonTables();
connect(map, &Map::openScriptRequested, this, &Editor::openScript);
connect(map, &Map::connectionAdded, this, &Editor::displayConnection);
connect(map, &Map::connectionRemoved, this, &Editor::removeConnectionPixmap);
updateSelectedEvents();
return true;
}
void Editor::onMapStartPaint(QGraphicsSceneMouseEvent *event, MapPixmapItem *item) {
if (item->paintingMode != MapPixmapItem::PaintMode::Metatiles) {
bool Editor::setLayout(QString layoutId) {
if (!project || layoutId.isEmpty()) {
return false;
}
this->layout = this->project->loadLayout(layoutId);
if (!displayLayout()) {
return false;
}
editGroup.addStack(&layout->editHistory);
map_ruler->setMapDimensions(QSize(this->layout->getWidth(), this->layout->getHeight()));
connect(this->layout, &Layout::layoutDimensionsChanged, map_ruler, &MapRuler::setMapDimensions);
ui->comboBox_PrimaryTileset->blockSignals(true);
ui->comboBox_SecondaryTileset->blockSignals(true);
ui->comboBox_PrimaryTileset->setCurrentText(this->layout->tileset_primary_label);
ui->comboBox_SecondaryTileset->setCurrentText(this->layout->tileset_secondary_label);
ui->comboBox_PrimaryTileset->blockSignals(false);
ui->comboBox_SecondaryTileset->blockSignals(false);
const QSignalBlocker b0(this->ui->comboBox_LayoutSelector);
int index = this->ui->comboBox_LayoutSelector->findText(layoutId);
if (index < 0) index = 0;
this->ui->comboBox_LayoutSelector->setCurrentIndex(index);
return true;
}
void Editor::onMapStartPaint(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *) {
if (!this->getEditingLayout()) {
return;
}
QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
if (event->buttons() & Qt::RightButton && (map_edit_mode == "paint" || map_edit_mode == "fill")) {
if (event->buttons() & Qt::RightButton && (mapEditAction == EditAction::Paint || mapEditAction == EditAction::Fill)) {
this->cursorMapTileRect->initRightClickSelectionAnchor(pos.x(), pos.y());
} else {
this->cursorMapTileRect->initAnchor(pos.x(), pos.y());
}
}
void Editor::onMapEndPaint(QGraphicsSceneMouseEvent *, MapPixmapItem *item) {
if (!(item->paintingMode == MapPixmapItem::PaintMode::Metatiles)) {
void Editor::onMapEndPaint(QGraphicsSceneMouseEvent *, LayoutPixmapItem *) {
if (!this->getEditingLayout()) {
return;
}
this->cursorMapTileRect->stopRightClickSelectionAnchor();
@ -1305,16 +1365,16 @@ void Editor::setStraightPathCursorMode(QGraphicsSceneMouseEvent *event) {
}
}
void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item) {
void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *item) {
// TODO: add event tab object painting tool buttons stuff here
if (item->paintingMode == MapPixmapItem::PaintMode::Disabled) {
if (!item->getEditsEnabled()) {
return;
}
QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
if (item->paintingMode == MapPixmapItem::PaintMode::Metatiles) {
if (map_edit_mode == "paint") {
if (this->getEditingLayout()) {
if (mapEditAction == EditAction::Paint) {
if (event->buttons() & Qt::RightButton) {
item->updateMetatileSelection(event);
} else if (event->buttons() & Qt::MiddleButton) {
@ -1336,9 +1396,9 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item
}
item->paint(event);
}
} else if (map_edit_mode == "select") {
} else if (mapEditAction == EditAction::Select) {
item->select(event);
} else if (map_edit_mode == "fill") {
} else if (mapEditAction == EditAction::Fill) {
if (event->buttons() & Qt::RightButton) {
item->updateMetatileSelection(event);
} else if (event->modifiers() & Qt::ControlModifier) {
@ -1346,13 +1406,13 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item
} else {
item->floodFill(event);
}
} else if (map_edit_mode == "pick") {
} else if (mapEditAction == EditAction::Pick) {
if (event->buttons() & Qt::RightButton) {
item->updateMetatileSelection(event);
} else {
item->pick(event);
}
} else if (map_edit_mode == "shift") {
} else if (mapEditAction == EditAction::Shift) {
this->setStraightPathCursorMode(event);
if (this->cursorMapTileRect->getStraightPathMode()) {
item->lockNondominantAxis(event);
@ -1360,11 +1420,11 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item
}
item->shift(event);
}
} else if (item->paintingMode == MapPixmapItem::PaintMode::EventObjects) {
if (obj_edit_mode == "paint" && event->type() == QEvent::GraphicsSceneMousePress) {
} else if (this->editMode == EditMode::Events) {
if (objectEditAction == EditAction::Paint && event->type() == QEvent::GraphicsSceneMousePress) {
// Right-clicking while in paint mode will change mode to select.
if (event->buttons() & Qt::RightButton) {
this->obj_edit_mode = "select";
this->objectEditAction = EditAction::Select;
this->settings->mapCursor = QCursor();
this->cursorMapTileRect->setSingleTileMode();
this->ui->toolButton_Paint->setChecked(false);
@ -1386,9 +1446,9 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item
}
}
}
} else if (obj_edit_mode == "select") {
} else if (objectEditAction == EditAction::Select) {
// do nothing here, at least for now
} else if (obj_edit_mode == "shift" && item->map) {
} else if (objectEditAction == EditAction::Shift) {
static QPoint selection_origin;
static unsigned actionId = 0;
@ -1404,8 +1464,8 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item
QList<Event *> selectedEvents;
for (DraggablePixmapItem *item : getObjects()) {
selectedEvents.append(item->event);
for (DraggablePixmapItem *pixmapItem : getObjects()) {
selectedEvents.append(pixmapItem->event);
}
selection_origin = QPoint(pos.x(), pos.y());
@ -1418,13 +1478,13 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item
}
void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item) {
if (item->paintingMode != MapPixmapItem::PaintMode::Metatiles) {
if (!item->getEditsEnabled()) {
return;
}
QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
if (map_edit_mode == "paint") {
if (mapEditAction == EditAction::Paint) {
if (event->buttons() & Qt::RightButton) {
item->updateMovementPermissionSelection(event);
} else if (event->buttons() & Qt::MiddleButton) {
@ -1441,9 +1501,9 @@ void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixm
}
item->paint(event);
}
} else if (map_edit_mode == "select") {
} else if (mapEditAction == EditAction::Select) {
item->select(event);
} else if (map_edit_mode == "fill") {
} else if (mapEditAction == EditAction::Fill) {
if (event->buttons() & Qt::RightButton) {
item->pick(event);
} else if (event->modifiers() & Qt::ControlModifier) {
@ -1451,9 +1511,9 @@ void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixm
} else {
item->floodFill(event);
}
} else if (map_edit_mode == "pick") {
} else if (mapEditAction == EditAction::Pick) {
item->pick(event);
} else if (map_edit_mode == "shift") {
} else if (mapEditAction == EditAction::Shift) {
this->setStraightPathCursorMode(event);
if (this->cursorMapTileRect->getStraightPathMode()) {
item->lockNondominantAxis(event);
@ -1490,6 +1550,23 @@ void Editor::clearMap() {
}
bool Editor::displayMap() {
if (!this->map)
return false;
displayMapEvents();
displayMapConnections();
maskNonVisibleConnectionTiles();
if (events_group) {
events_group->setVisible(false);
}
return true;
}
bool Editor::displayLayout() {
if (!this->layout)
return false;
if (!scene) {
scene = new QGraphicsScene;
MapSceneEventFilter *filter = new MapSceneEventFilter(scene);
@ -1498,18 +1575,15 @@ bool Editor::displayMap() {
scene->installEventFilter(this->map_ruler);
}
clearConnectionMask();
displayMetatileSelector();
displayMovementPermissionSelector();
displayMapMetatiles();
displayMovementPermissionSelector();
displayMapMovementPermissions();
displayBorderMetatiles();
displayCurrentMetatilesSelection();
displayMapEvents();
displayMapConnections();
displayMapBorder();
displayMapGrid();
displayWildMonTables();
maskNonVisibleConnectionTiles();
this->map_ruler->setZValue(1000);
scene->addItem(this->map_ruler);
@ -1520,9 +1594,7 @@ bool Editor::displayMap() {
if (collision_item) {
collision_item->setVisible(false);
}
if (events_group) {
events_group->setVisible(false);
}
return true;
}
@ -1538,7 +1610,7 @@ void Editor::displayMetatileSelector() {
scene_metatiles = new QGraphicsScene;
if (!metatile_selector_item) {
metatile_selector_item = new MetatileSelector(8, map);
metatile_selector_item = new MetatileSelector(8, this->layout);
connect(metatile_selector_item, &MetatileSelector::hoveredMetatileSelectionChanged,
this, &Editor::onHoveredMetatileSelectionChanged);
connect(metatile_selector_item, &MetatileSelector::hoveredMetatileSelectionCleared,
@ -1547,14 +1619,14 @@ void Editor::displayMetatileSelector() {
this, &Editor::onSelectedMetatilesChanged);
metatile_selector_item->select(0);
} else {
metatile_selector_item->setMap(map);
metatile_selector_item->setLayout(this->layout);
if (metatile_selector_item->primaryTileset
&& metatile_selector_item->primaryTileset != map->layout->tileset_primary)
emit tilesetUpdated(map->layout->tileset_primary->name);
&& metatile_selector_item->primaryTileset != this->layout->tileset_primary)
emit tilesetUpdated(this->layout->tileset_primary->name);
if (metatile_selector_item->secondaryTileset
&& metatile_selector_item->secondaryTileset != map->layout->tileset_secondary)
emit tilesetUpdated(map->layout->tileset_secondary->name);
metatile_selector_item->setTilesets(map->layout->tileset_primary, map->layout->tileset_secondary);
&& metatile_selector_item->secondaryTileset != this->layout->tileset_secondary)
emit tilesetUpdated(this->layout->tileset_secondary->name);
metatile_selector_item->setTilesets(this->layout->tileset_primary, this->layout->tileset_secondary);
}
scene_metatiles->addItem(metatile_selector_item);
@ -1571,12 +1643,12 @@ void Editor::clearMapMetatiles() {
void Editor::displayMapMetatiles() {
clearMapMetatiles();
map_item = new MapPixmapItem(map, this->metatile_selector_item, this->settings);
connect(map_item, &MapPixmapItem::mouseEvent, this, &Editor::mouseEvent_map);
connect(map_item, &MapPixmapItem::startPaint, this, &Editor::onMapStartPaint);
connect(map_item, &MapPixmapItem::endPaint, this, &Editor::onMapEndPaint);
connect(map_item, &MapPixmapItem::hoveredMapMetatileChanged, this, &Editor::onHoveredMapMetatileChanged);
connect(map_item, &MapPixmapItem::hoveredMapMetatileCleared, this, &Editor::onHoveredMapMetatileCleared);
map_item = new LayoutPixmapItem(this->layout, this->metatile_selector_item, this->settings);
connect(map_item, &LayoutPixmapItem::mouseEvent, this, &Editor::mouseEvent_map);
connect(map_item, &LayoutPixmapItem::startPaint, this, &Editor::onMapStartPaint);
connect(map_item, &LayoutPixmapItem::endPaint, this, &Editor::onMapEndPaint);
connect(map_item, &LayoutPixmapItem::hoveredMapMetatileChanged, this, &Editor::onHoveredMapMetatileChanged);
connect(map_item, &LayoutPixmapItem::hoveredMapMetatileCleared, this, &Editor::onHoveredMapMetatileCleared);
map_item->draw(true);
scene->addItem(map_item);
@ -1601,7 +1673,7 @@ void Editor::clearMapMovementPermissions() {
void Editor::displayMapMovementPermissions() {
clearMapMovementPermissions();
collision_item = new CollisionPixmapItem(map, ui->spinBox_SelectedCollision, ui->spinBox_SelectedElevation,
collision_item = new CollisionPixmapItem(this->layout, ui->spinBox_SelectedCollision, ui->spinBox_SelectedElevation,
this->metatile_selector_item, this->settings, &this->collisionOpacity);
connect(collision_item, &CollisionPixmapItem::mouseEvent, this, &Editor::mouseEvent_collision);
connect(collision_item, &CollisionPixmapItem::hoveredMapMovementPermissionChanged,
@ -1625,7 +1697,7 @@ void Editor::displayBorderMetatiles() {
clearBorderMetatiles();
scene_selected_border_metatiles = new QGraphicsScene;
selected_border_metatiles_item = new BorderMetatilesPixmapItem(map, this->metatile_selector_item);
selected_border_metatiles_item = new BorderMetatilesPixmapItem(this->layout, this->metatile_selector_item);
selected_border_metatiles_item->draw();
scene_selected_border_metatiles->addItem(selected_border_metatiles_item);
@ -1650,14 +1722,14 @@ void Editor::displayCurrentMetatilesSelection() {
clearCurrentMetatilesSelection();
scene_current_metatile_selection = new QGraphicsScene;
current_metatile_selection_item = new CurrentSelectedMetatilesPixmapItem(map, this->metatile_selector_item);
current_metatile_selection_item = new CurrentSelectedMetatilesPixmapItem(this->layout, this->metatile_selector_item);
current_metatile_selection_item->draw();
scene_current_metatile_selection->addItem(current_metatile_selection_item);
}
void Editor::redrawCurrentMetatilesSelection() {
if (current_metatile_selection_item) {
current_metatile_selection_item->setMap(map);
current_metatile_selection_item->setLayout(this->layout);
current_metatile_selection_item->draw();
emit currentMetatilesSelectionChanged();
}
@ -1783,8 +1855,8 @@ void Editor::maskNonVisibleConnectionTiles() {
mask.addRect(
-BORDER_DISTANCE * 16,
-BORDER_DISTANCE * 16,
(map->getWidth() + BORDER_DISTANCE * 2) * 16,
(map->getHeight() + BORDER_DISTANCE * 2) * 16
(layout->getWidth() + BORDER_DISTANCE * 2) * 16,
(layout->getHeight() + BORDER_DISTANCE * 2) * 16
);
// Mask the tiles with the current theme's background color.
@ -1807,13 +1879,13 @@ void Editor::clearMapBorder() {
void Editor::displayMapBorder() {
clearMapBorder();
int borderWidth = map->getBorderWidth();
int borderHeight = map->getBorderHeight();
int borderWidth = this->layout->getBorderWidth();
int borderHeight = this->layout->getBorderHeight();
int borderHorzDist = getBorderDrawDistance(borderWidth);
int borderVertDist = getBorderDrawDistance(borderHeight);
QPixmap pixmap = map->renderBorder();
for (int y = -borderVertDist; y < map->getHeight() + borderVertDist; y += borderHeight)
for (int x = -borderHorzDist; x < map->getWidth() + borderHorzDist; x += borderWidth) {
QPixmap pixmap = this->layout->renderBorder();
for (int y = -borderVertDist; y < this->layout->getHeight() + borderVertDist; y += borderHeight)
for (int x = -borderHorzDist; x < this->layout->getWidth() + borderHorzDist; x += borderWidth) {
QGraphicsPixmapItem *item = new QGraphicsPixmapItem(pixmap);
item->setX(x * 16);
item->setY(y * 16);
@ -1824,7 +1896,7 @@ void Editor::displayMapBorder() {
}
void Editor::updateMapBorder() {
QPixmap pixmap = this->map->renderBorder(true);
QPixmap pixmap = this->layout->renderBorder(true);
for (auto item : this->borderItems) {
item->setPixmap(pixmap);
}
@ -1875,8 +1947,8 @@ void Editor::displayMapGrid() {
// elements of the scripting API, so they're painted manually in MapView::drawForeground.
this->mapGrid = new QGraphicsItemGroup();
const int pixelMapWidth = map->getWidth() * 16;
const int pixelMapHeight = map->getHeight() * 16;
const int pixelMapWidth = this->layout->getWidth() * 16;
const int pixelMapHeight = this->layout->getHeight() * 16;
// The grid can be moved with a user-specified x/y offset. The grid's dash patterns will only wrap in full pattern increments,
// so we draw an additional row/column outside the map that can be revealed as the offset changes.
@ -1913,21 +1985,21 @@ void Editor::updateMapGrid() {
void Editor::updatePrimaryTileset(QString tilesetLabel, bool forceLoad)
{
if (map->layout->tileset_primary_label != tilesetLabel || forceLoad)
if (this->layout->tileset_primary_label != tilesetLabel || forceLoad)
{
map->layout->tileset_primary_label = tilesetLabel;
map->layout->tileset_primary = project->getTileset(tilesetLabel, forceLoad);
map->clearBorderCache();
this->layout->tileset_primary_label = tilesetLabel;
this->layout->tileset_primary = project->getTileset(tilesetLabel, forceLoad);
layout->clearBorderCache();
}
}
void Editor::updateSecondaryTileset(QString tilesetLabel, bool forceLoad)
{
if (map->layout->tileset_secondary_label != tilesetLabel || forceLoad)
if (this->layout->tileset_secondary_label != tilesetLabel || forceLoad)
{
map->layout->tileset_secondary_label = tilesetLabel;
map->layout->tileset_secondary = project->getTileset(tilesetLabel, forceLoad);
map->clearBorderCache();
this->layout->tileset_secondary_label = tilesetLabel;
this->layout->tileset_secondary = project->getTileset(tilesetLabel, forceLoad);
layout->clearBorderCache();
}
}
@ -1973,7 +2045,7 @@ void Editor::updateCustomMapHeaderValues(QTableWidget *table)
Tileset* Editor::getCurrentMapPrimaryTileset()
{
QString tilesetLabel = map->layout->tileset_primary_label;
QString tilesetLabel = this->layout->tileset_primary_label;
return project->getTileset(tilesetLabel);
}
@ -2008,12 +2080,12 @@ void Editor::redrawObject(DraggablePixmapItem *item) {
void Editor::updateWarpEventWarning(Event *event) {
if (porymapConfig.warpBehaviorWarningDisabled)
return;
if (!project || !map || !event || event->getEventType() != Event::Type::Warp)
if (!project || !map || !map->layout || !event || event->getEventType() != Event::Type::Warp)
return;
Block block;
Metatile * metatile = nullptr;
WarpEvent * warpEvent = static_cast<WarpEvent*>(event);
if (map->getBlock(warpEvent->getX(), warpEvent->getY(), &block)) {
if (map->layout->getBlock(warpEvent->getX(), warpEvent->getY(), &block)) {
metatile = Tileset::getMetatile(block.metatileId(), map->layout->tileset_primary, map->layout->tileset_secondary);
}
// metatile may be null if the warp is in the map border. Display the warning in this case
@ -2093,7 +2165,7 @@ void Editor::selectedEventIndexChanged(int index, Event::Group eventGroup) {
}
void Editor::duplicateSelectedEvents() {
if (!selected_events || !selected_events->length() || !map || !current_view || map_item->paintingMode != MapPixmapItem::PaintMode::EventObjects)
if (!selected_events || !selected_events->length() || !map || !current_view || this->getEditingLayout())
return;
QList<Event *> selectedEvents;
@ -2150,6 +2222,50 @@ bool Editor::eventLimitReached(Event::Type event_type) {
return false;
}
void Editor::deleteSelectedEvents() {
if (!this->selected_events || this->selected_events->length() == 0 || !this->map || this->editMode != EditMode::Events)
return;
DraggablePixmapItem *nextSelectedEvent = nullptr;
QList<Event *> selectedEvents;
int numDeleted = 0;
for (DraggablePixmapItem *item : *this->selected_events) {
Event::Group event_group = item->event->getEventGroup();
if (event_group != Event::Group::Heal) {
numDeleted++;
item->event->setPixmapItem(item);
selectedEvents.append(item->event);
}
else { // don't allow deletion of heal locations
logWarn(QString("Cannot delete event of type '%1'").arg(Event::eventTypeToString(item->event->getEventType())));
}
}
if (numDeleted) {
// Get the index for the event that should be selected after this event has been deleted.
// Select event at next smallest index when deleting a single event.
// If deleting multiple events, just let editor work out next selected.
if (numDeleted == 1) {
Event::Group event_group = selectedEvents[0]->getEventGroup();
int index = this->map->events.value(event_group).indexOf(selectedEvents[0]);
if (index != this->map->events.value(event_group).size() - 1)
index++;
else
index--;
Event *event = nullptr;
if (index >= 0)
event = this->map->events.value(event_group).at(index);
for (QGraphicsItem *child : this->events_group->childItems()) {
DraggablePixmapItem *event_item = static_cast<DraggablePixmapItem *>(child);
if (event_item->event == event) {
nextSelectedEvent = event_item;
break;
}
}
}
this->map->editHistory.push(new EventDelete(this, this->map, selectedEvents, nextSelectedEvent ? nextSelectedEvent->event : nullptr));
}
}
void Editor::openMapScripts() const {
openInTextEditor(map->getScriptsFilePath());
}
@ -2232,11 +2348,11 @@ bool Editor::startDetachedProcess(const QString &command, const QString &working
// is clicking on the background instead of an event.
void Editor::objectsView_onMousePress(QMouseEvent *event) {
// make sure we are in object editing mode
if (map_item && map_item->paintingMode != MapPixmapItem::PaintMode::EventObjects) {
if (map_item && this->editMode != EditMode::Events) {
return;
}
if (this->obj_edit_mode == "paint" && event->buttons() & Qt::RightButton) {
this->obj_edit_mode = "select";
if (this->objectEditAction == EditAction::Paint && event->buttons() & Qt::RightButton) {
this->objectEditAction = EditAction::Select;
this->settings->mapCursor = QCursor();
this->cursorMapTileRect->setSingleTileMode();
this->ui->toolButton_Paint->setChecked(false);

File diff suppressed because it is too large Load diff

View file

@ -35,10 +35,10 @@ int Project::max_map_data_size = 10240; // 0x2800
int Project::default_map_size = 20;
int Project::max_object_events = 64;
Project::Project(QWidget *parent) :
Project::Project(QObject *parent) :
QObject(parent)
{
initSignals();
QObject::connect(&this->fileWatcher, &QFileSystemWatcher::fileChanged, this, &Project::fileChanged);
}
Project::~Project()
@ -49,45 +49,6 @@ Project::~Project()
clearEventGraphics();
}
void Project::initSignals() {
// detect changes to specific filepaths being monitored
QObject::connect(&fileWatcher, &QFileSystemWatcher::fileChanged, [this](QString changed){
if (!porymapConfig.monitorFiles) return;
if (modifiedFileTimestamps.contains(changed)) {
if (QDateTime::currentMSecsSinceEpoch() < modifiedFileTimestamps[changed]) {
return;
}
modifiedFileTimestamps.remove(changed);
}
static bool showing = false;
if (showing) return;
QMessageBox notice(this->parentWidget());
notice.setText("File Changed");
notice.setInformativeText(QString("The file %1 has changed on disk. Would you like to reload the project?")
.arg(changed.remove(this->root + "/")));
notice.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
notice.setDefaultButton(QMessageBox::No);
notice.setIcon(QMessageBox::Question);
QCheckBox showAgainCheck("Do not ask again.");
notice.setCheckBox(&showAgainCheck);
showing = true;
int choice = notice.exec();
if (choice == QMessageBox::Yes) {
emit reloadProject();
} else if (choice == QMessageBox::No) {
if (showAgainCheck.isChecked()) {
porymapConfig.monitorFiles = false;
emit uncheckMonitorFilesAction();
}
}
showing = false;
});
}
void Project::set_root(QString dir) {
this->root = dir;
FileDialog::setDirectory(dir);
@ -163,7 +124,6 @@ void Project::clearMapCache() {
delete map;
}
mapCache.clear();
emit mapCacheCleared();
}
void Project::clearTilesetCache() {
@ -429,15 +389,87 @@ QString Project::readMapLocation(QString map_name) {
return ParseUtil::jsonToQString(mapObj["region_map_section"]);
}
bool Project::loadLayout(MapLayout *layout) {
// Force these to run even if one fails
bool loadedTilesets = loadLayoutTilesets(layout);
bool loadedBlockdata = loadBlockdata(layout);
bool loadedBorder = loadLayoutBorder(layout);
Layout *Project::createNewLayout(Layout::SimpleSettings &layoutSettings) {
QString basePath = projectConfig.getFilePath(ProjectFilePath::data_layouts_folders);
Layout *layout;
return loadedTilesets
&& loadedBlockdata
&& loadedBorder;
// Handle the case where we are copying from an existing layout first.
if (!layoutSettings.from_id.isEmpty()) {
// load from layout
loadLayout(mapLayouts[layoutSettings.from_id]);
layout = mapLayouts[layoutSettings.from_id]->copy();
layout->name = layoutSettings.name;
layout->id = layoutSettings.id;
layout->border_path = QString("%1%2/border.bin").arg(basePath, layoutSettings.name);
layout->blockdata_path = QString("%1%2/map.bin").arg(basePath, layoutSettings.name);
}
else {
layout = new Layout;
layout->name = layoutSettings.name;
layout->id = layoutSettings.id;
layout->width = layoutSettings.width;
layout->height = layoutSettings.height;
layout->border_width = DEFAULT_BORDER_WIDTH;
layout->border_height = DEFAULT_BORDER_HEIGHT;
layout->tileset_primary_label = layoutSettings.tileset_primary_label;
layout->tileset_secondary_label = layoutSettings.tileset_secondary_label;
layout->border_path = QString("%1%2/border.bin").arg(basePath, layoutSettings.name);
layout->blockdata_path = QString("%1%2/map.bin").arg(basePath, layoutSettings.name);
setNewLayoutBlockdata(layout);
setNewLayoutBorder(layout);
}
// Create a new directory for the layout
QString newLayoutDir = QString(root + "/%1%2").arg(projectConfig.getFilePath(ProjectFilePath::data_layouts_folders), layout->name);
if (!QDir::root().mkdir(newLayoutDir)) {
logError(QString("Error: failed to create directory for new layout: '%1'").arg(newLayoutDir));
delete layout;
return nullptr;
}
mapLayouts.insert(layout->id, layout);
mapLayoutsMaster.insert(layout->id, layout->copy());
mapLayoutsTable.append(layout->id);
mapLayoutsTableMaster.append(layout->id);
layoutIdsToNames.insert(layout->id, layout->name);
saveLayout(layout);
this->loadLayout(layout);
return layout;
}
bool Project::loadLayout(Layout *layout) {
if (!layout->loaded) {
// Force these to run even if one fails
bool loadedTilesets = loadLayoutTilesets(layout);
bool loadedBlockdata = loadBlockdata(layout);
bool loadedBorder = loadLayoutBorder(layout);
if (loadedTilesets && loadedBlockdata && loadedBorder) {
layout->loaded = true;
return true;
} else {
return false;
}
}
return true;
}
Layout *Project::loadLayout(QString layoutId) {
if (mapLayouts.contains(layoutId)) {
Layout *layout = mapLayouts[layoutId];
if (loadLayout(layout)) {
return layout;
}
}
logError(QString("Error: Failed to load layout '%1'").arg(layoutId));
return nullptr;
}
bool Project::loadMapLayout(Map* map) {
@ -462,7 +494,10 @@ bool Project::loadMapLayout(Map* map) {
void Project::clearMapLayouts() {
qDeleteAll(mapLayouts);
mapLayouts.clear();
qDeleteAll(mapLayoutsMaster);
mapLayoutsMaster.clear();
mapLayoutsTable.clear();
layoutIdsToNames.clear();
}
bool Project::readMapLayouts() {
@ -510,7 +545,7 @@ bool Project::readMapLayouts() {
logError(QString("Layout %1 is missing field(s) in %2.").arg(i).arg(layoutsFilepath));
return false;
}
MapLayout *layout = new MapLayout();
Layout *layout = new Layout();
layout->id = ParseUtil::jsonToQString(layoutObj["id"]);
if (layout->id.isEmpty()) {
logError(QString("Missing 'id' value on layout %1 in %2").arg(i).arg(layoutsFilepath));
@ -586,14 +621,12 @@ bool Project::readMapLayouts() {
return false;
}
mapLayouts.insert(layout->id, layout);
mapLayoutsMaster.insert(layout->id, layout->copy());
mapLayoutsTable.append(layout->id);
mapLayoutsTableMaster.append(layout->id);
layoutIdsToNames.insert(layout->id, layout->name);
}
// Deep copy
mapLayoutsMaster = mapLayouts;
mapLayoutsMaster.detach();
mapLayoutsTableMaster = mapLayoutsTable;
mapLayoutsTableMaster.detach();
return true;
}
@ -610,7 +643,7 @@ void Project::saveMapLayouts() {
OrderedJson::array layoutsArr;
for (QString layoutId : mapLayoutsTableMaster) {
MapLayout *layout = mapLayouts.value(layoutId);
Layout *layout = mapLayoutsMaster.value(layoutId);
OrderedJson::object layoutObj;
layoutObj["id"] = layout->id;
layoutObj["name"] = layout->name;
@ -675,6 +708,47 @@ void Project::saveMapGroups() {
mapGroupsFile.close();
}
void Project::saveRegionMapSections() {
const QString filepath = QString("%1/%2").arg(this->root).arg(projectConfig.getFilePath(ProjectFilePath::json_region_map_entries));
QFile file(filepath);
if (!file.open(QIODevice::WriteOnly)) {
logError(QString("Could not open '%1' for writing").arg(filepath));
return;
}
const QString emptyMapsecName = getEmptyMapsecName();
OrderedJson::array mapSectionArray;
for (const auto &idName : this->mapSectionIdNames) {
// The 'empty' map section (MAPSEC_NONE) isn't normally present in the region map sections data file.
// We append this name to mapSectionIdNames ourselves if it isn't present, in which case we don't want to output data for it here.
if (!this->saveEmptyMapsec && idName == emptyMapsecName)
continue;
OrderedJson::object mapSectionObj;
mapSectionObj["id"] = idName;
if (this->regionMapEntries.contains(idName)) {
MapSectionEntry entry = this->regionMapEntries.value(idName);
mapSectionObj["name"] = entry.name;
mapSectionObj["x"] = entry.x;
mapSectionObj["y"] = entry.y;
mapSectionObj["width"] = entry.width;
mapSectionObj["height"] = entry.height;
}
mapSectionArray.append(mapSectionObj);
}
OrderedJson::object object;
object["map_sections"] = mapSectionArray;
ignoreWatchedFileTemporarily(filepath);
OrderedJson json(object);
OrderedJsonDoc jsonDoc(&json);
jsonDoc.dump(&file);
file.close();
}
void Project::saveWildMonData() {
if (!this->wildEncountersLoaded) return;
@ -1062,7 +1136,7 @@ void Project::saveTilesetPalettes(Tileset *tileset) {
}
}
bool Project::loadLayoutTilesets(MapLayout *layout) {
bool Project::loadLayoutTilesets(Layout *layout) {
layout->tileset_primary = getTileset(layout->tileset_primary_label);
if (!layout->tileset_primary) {
QString defaultTileset = this->getDefaultPrimaryTilesetLabel();
@ -1130,11 +1204,11 @@ Tileset* Project::loadTileset(QString label, Tileset *tileset) {
return tileset;
}
bool Project::loadBlockdata(MapLayout *layout) {
bool Project::loadBlockdata(Layout *layout) {
QString path = QString("%1/%2").arg(root).arg(layout->blockdata_path);
layout->blockdata = readBlockdata(path);
layout->lastCommitBlocks.blocks = layout->blockdata;
layout->lastCommitBlocks.mapDimensions = QSize(layout->getWidth(), layout->getHeight());
layout->lastCommitBlocks.layoutDimensions = QSize(layout->getWidth(), layout->getHeight());
if (layout->blockdata.count() != layout->getWidth() * layout->getHeight()) {
logWarn(QString("Layout blockdata length %1 does not match dimensions %2x%3 (should be %4). Resizing blockdata.")
@ -1147,19 +1221,19 @@ bool Project::loadBlockdata(MapLayout *layout) {
return true;
}
void Project::setNewMapBlockdata(Map *map) {
map->layout->blockdata.clear();
int width = map->getWidth();
int height = map->getHeight();
void Project::setNewLayoutBlockdata(Layout *layout) {
layout->blockdata.clear();
int width = layout->getWidth();
int height = layout->getHeight();
Block block(projectConfig.defaultMetatileId, projectConfig.defaultCollision, projectConfig.defaultElevation);
for (int i = 0; i < width * height; i++) {
map->layout->blockdata.append(block);
layout->blockdata.append(block);
}
map->layout->lastCommitBlocks.blocks = map->layout->blockdata;
map->layout->lastCommitBlocks.mapDimensions = QSize(width, height);
layout->lastCommitBlocks.blocks = layout->blockdata;
layout->lastCommitBlocks.layoutDimensions = QSize(width, height);
}
bool Project::loadLayoutBorder(MapLayout *layout) {
bool Project::loadLayoutBorder(Layout *layout) {
QString path = QString("%1/%2").arg(root).arg(layout->border_path);
layout->border = readBlockdata(path);
layout->lastCommitBlocks.border = layout->border;
@ -1175,36 +1249,36 @@ bool Project::loadLayoutBorder(MapLayout *layout) {
return true;
}
void Project::setNewMapBorder(Map *map) {
map->layout->border.clear();
int width = map->getBorderWidth();
int height = map->getBorderHeight();
void Project::setNewLayoutBorder(Layout *layout) {
layout->border.clear();
int width = layout->getBorderWidth();
int height = layout->getBorderHeight();
if (projectConfig.newMapBorderMetatileIds.length() != width * height) {
// Border size doesn't match the number of default border metatiles.
// Fill the border with empty metatiles.
for (int i = 0; i < width * height; i++) {
map->layout->border.append(0);
layout->border.append(0);
}
} else {
// Fill the border with the default metatiles from the config.
for (int i = 0; i < width * height; i++) {
map->layout->border.append(projectConfig.newMapBorderMetatileIds.at(i));
layout->border.append(projectConfig.newMapBorderMetatileIds.at(i));
}
}
map->layout->lastCommitBlocks.border = map->layout->border;
map->layout->lastCommitBlocks.borderDimensions = QSize(width, height);
layout->lastCommitBlocks.border = layout->border;
layout->lastCommitBlocks.borderDimensions = QSize(width, height);
}
void Project::saveLayoutBorder(Map *map) {
QString path = QString("%1/%2").arg(root).arg(map->layout->border_path);
writeBlockdata(path, map->layout->border);
void Project::saveLayoutBorder(Layout *layout) {
QString path = QString("%1/%2").arg(root).arg(layout->border_path);
writeBlockdata(path, layout->border);
}
void Project::saveLayoutBlockdata(Map* map) {
QString path = QString("%1/%2").arg(root).arg(map->layout->blockdata_path);
writeBlockdata(path, map->layout->blockdata);
void Project::saveLayoutBlockdata(Layout *layout) {
QString path = QString("%1/%2").arg(root).arg(layout->blockdata_path);
writeBlockdata(path, layout->blockdata);
}
void Project::writeBlockdata(QString path, const Blockdata &blockdata) {
@ -1359,36 +1433,46 @@ void Project::saveMap(Map *map) {
jsonDoc.dump(&mapFile);
mapFile.close();
saveLayoutBorder(map);
saveLayoutBlockdata(map);
saveLayout(map->layout);
saveHealLocations(map);
// Update global data structures with current map data.
updateMapLayout(map);
map->isPersistedToFile = true;
map->hasUnsavedDataChanges = false;
map->editHistory.setClean();
}
void Project::updateMapLayout(Map* map) {
if (!mapLayoutsTableMaster.contains(map->layoutId)) {
mapLayoutsTableMaster.append(map->layoutId);
void Project::saveLayout(Layout *layout) {
//
saveLayoutBorder(layout);
saveLayoutBlockdata(layout);
// Update global data structures with current map data.
updateLayout(layout);
layout->editHistory.setClean();
}
void Project::updateLayout(Layout *layout) {
if (!mapLayoutsTableMaster.contains(layout->id)) {
mapLayoutsTableMaster.append(layout->id);
}
// Deep copy
MapLayout *layout = mapLayouts.value(map->layoutId);
MapLayout *newLayout = new MapLayout();
*newLayout = *layout;
mapLayoutsMaster.insert(map->layoutId, newLayout);
if (mapLayoutsMaster.contains(layout->id)) {
mapLayoutsMaster[layout->id]->copyFrom(layout);
}
else {
mapLayoutsMaster.insert(layout->id, layout->copy());
}
}
void Project::saveAllDataStructures() {
saveMapLayouts();
saveMapGroups();
saveRegionMapSections();
saveMapConstantsHeader();
saveWildMonData();
saveConfig();
this->hasUnsavedDataChanges = false;
}
void Project::saveConfig() {
@ -1872,11 +1956,12 @@ Map* Project::addNewMapToGroup(QString mapName, int groupNum, Map *newMap, bool
if (!existingLayout) {
this->mapLayouts.insert(newMap->layoutId, newMap->layout);
this->mapLayoutsTable.append(newMap->layoutId);
this->layoutIdsToNames.insert(newMap->layout->id, newMap->layout->name);
if (!importedMap) {
setNewMapBlockdata(newMap);
setNewLayoutBlockdata(newMap->layout);
}
if (newMap->layout->border.isEmpty()) {
setNewMapBorder(newMap);
setNewLayoutBorder(newMap->layout);
}
}
@ -2166,24 +2251,99 @@ bool Project::readFieldmapMasks() {
}
bool Project::readRegionMapSections() {
this->mapSectionNameToValue.clear();
this->mapSectionValueToName.clear();
this->mapSectionIdNames.clear();
this->regionMapEntries.clear();
this->saveEmptyMapsec = false;
const QString defaultName = getEmptyMapsecName();
const QString requiredPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix);
const QStringList regexList = {QString("\\b%1").arg(projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix))};
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_region_map_sections);
fileWatcher.addPath(root + "/" + filename);
this->mapSectionNameToValue = parser.readCDefinesByRegex(filename, regexList);
if (this->mapSectionNameToValue.isEmpty()) {
logError(QString("Failed to read region map sections from %1.").arg(filename));
QJsonDocument doc;
const QString filepath = QString("%1/%2").arg(this->root).arg(projectConfig.getFilePath(ProjectFilePath::json_region_map_entries));
if (!parser.tryParseJsonFile(&doc, filepath)) {
logError(QString("Failed to read region map sections from '%1'").arg(filepath));
return false;
}
fileWatcher.addPath(filepath);
for (QString defineName : this->mapSectionNameToValue.keys()) {
this->mapSectionValueToName.insert(this->mapSectionNameToValue[defineName], defineName);
QJsonArray mapSections = doc.object()["map_sections"].toArray();
for (int i = 0; i < mapSections.size(); i++) {
QJsonObject mapSectionObj = mapSections.at(i).toObject();
// For each map section, "id" is the only required field. This is the field we use to display the location names in various drop-downs.
const QString idField = "id";
if (!mapSectionObj.contains(idField)) {
logWarn(QString("Ignoring data for map section %1. Missing required field \"%2\"").arg(i).arg(idField));
continue;
}
const QString idName = ParseUtil::jsonToQString(mapSectionObj[idField]);
if (!idName.startsWith(requiredPrefix)) {
logWarn(QString("Ignoring data for map section '%1'. IDs must start with the prefix '%2'").arg(idName).arg(requiredPrefix));
continue;
}
this->mapSectionIdNames.append(idName);
if (idName == defaultName) {
// If the user has data for the 'empty' MAPSEC we need to know to output it later,
// because we will otherwise add a dummy entry for this value.
this->saveEmptyMapsec = true;
}
// Map sections may have additional data indicating their position on the region map.
// If they have this data, we can add them to the region map entry list.
bool hasRegionMapData = true;
static const QSet<QString> regionMapFieldNames = { "name", "x", "y", "width", "height" };
for (auto fieldName : regionMapFieldNames) {
if (!mapSectionObj.contains(fieldName)) {
hasRegionMapData = false;
break;
}
}
if (!hasRegionMapData)
continue;
MapSectionEntry entry;
entry.name = ParseUtil::jsonToQString(mapSectionObj["name"]);
entry.x = ParseUtil::jsonToInt(mapSectionObj["x"]);
entry.y = ParseUtil::jsonToInt(mapSectionObj["y"]);
entry.width = ParseUtil::jsonToInt(mapSectionObj["width"]);
entry.height = ParseUtil::jsonToInt(mapSectionObj["height"]);
entry.valid = true;
this->regionMapEntries[idName] = entry;
}
// Make sure the default name is present in the list.
if (!this->mapSectionIdNames.contains(defaultName)) {
this->mapSectionIdNames.append(defaultName);
}
return true;
}
QString Project::getEmptyMapsecName() {
return projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix) + projectConfig.getIdentifier(ProjectIdentifier::define_map_section_empty);
}
// This function assumes a valid and unique name
void Project::addNewMapsec(const QString &name) {
if (!this->mapSectionIdNames.isEmpty() && this->mapSectionIdNames.last() == getEmptyMapsecName()) {
// If the default map section name (MAPSEC_NONE) is last in the list we'll keep it last in the list.
this->mapSectionIdNames.insert(this->mapSectionIdNames.length() - 1, name);
} else {
this->mapSectionIdNames.append(name);
}
this->hasUnsavedDataChanges = true;
emit mapSectionIdNamesChanged();
}
void Project::removeMapsec(const QString &name) {
if (!this->mapSectionIdNames.contains(name) || name == getEmptyMapsecName())
return;
this->mapSectionIdNames.removeOne(name);
this->hasUnsavedDataChanges = true;
emit mapSectionIdNamesChanged();
}
// Read the constants to preserve any "unused" heal locations when writing the file later
bool Project::readHealLocationConstants() {
this->healLocationNameToValue.clear();
@ -2866,3 +3026,23 @@ void Project::applyParsedLimits() {
projectConfig.collisionSheetHeight = qMin(projectConfig.collisionSheetHeight, Block::getMaxElevation() + 1);
projectConfig.collisionSheetWidth = qMin(projectConfig.collisionSheetWidth, Block::getMaxCollision() + 1);
}
bool Project::hasUnsavedChanges() {
if (this->hasUnsavedDataChanges)
return true;
// Check layouts for unsaved changes
for (auto i = this->mapLayouts.constBegin(); i != this->mapLayouts.constEnd(); i++) {
auto layout = i.value();
if (layout && layout->hasUnsavedChanges())
return true;
}
// Check loaded maps for unsaved changes
for (auto i = this->mapCache.constBegin(); i != this->mapCache.constEnd(); i++) {
auto map = i.value();
if (map && map->hasUnsavedChanges())
return true;
}
return false;
}

View file

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

View file

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

View file

@ -201,13 +201,13 @@ QList<QString> ScriptUtility::getCustomScripts() {
}
QList<int> ScriptUtility::getMetatileLayerOrder() {
if (!window || !window->editor || !window->editor->map)
if (!window || !window->editor || !window->editor->layout)
return QList<int>();
return window->editor->map->metatileLayerOrder;
return window->editor->layout->metatileLayerOrder;
}
void ScriptUtility::setMetatileLayerOrder(QList<int> order) {
if (!window || !window->editor || !window->editor->map)
if (!window || !window->editor || !window->editor->layout)
return;
const int numLayers = 3;
@ -226,20 +226,20 @@ void ScriptUtility::setMetatileLayerOrder(QList<int> order) {
}
if (invalid) return;
window->editor->map->metatileLayerOrder = order;
window->editor->layout->metatileLayerOrder = order;
window->refreshAfterPalettePreviewChange();
}
QList<float> ScriptUtility::getMetatileLayerOpacity() {
if (!window || !window->editor || !window->editor->map)
if (!window || !window->editor || !window->editor->layout)
return QList<float>();
return window->editor->map->metatileLayerOpacity;
return window->editor->layout->metatileLayerOpacity;
}
void ScriptUtility::setMetatileLayerOpacity(QList<float> order) {
if (!window || !window->editor || !window->editor->map)
if (!window || !window->editor || !window->editor->layout)
return;
window->editor->map->metatileLayerOpacity = order;
window->editor->layout->metatileLayerOpacity = order;
window->refreshAfterPalettePreviewChange();
}
@ -282,7 +282,7 @@ QList<QString> ScriptUtility::getSongNames() {
QList<QString> ScriptUtility::getLocationNames() {
if (!window || !window->editor || !window->editor->project)
return QList<QString>();
return window->editor->project->mapSectionNameToValue.keys();
return window->editor->project->mapSectionIdNames;
}
QList<QString> ScriptUtility::getWeatherNames() {

View file

@ -7,30 +7,30 @@
void BorderMetatilesPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
MetatileSelection selection = this->metatileSelector->getMetatileSelection();
QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
int width = map->getBorderWidth();
int height = map->getBorderHeight();
int width = layout->getBorderWidth();
int height = layout->getBorderHeight();
Blockdata oldBorder = map->layout->border;
Blockdata oldBorder = layout->border;
for (int i = 0; i < selection.dimensions.x() && (i + pos.x()) < width; i++) {
for (int j = 0; j < selection.dimensions.y() && (j + pos.y()) < height; j++) {
MetatileSelectionItem item = selection.metatileItems.at(j * selection.dimensions.x() + i);
map->setBorderMetatileId(pos.x() + i, pos.y() + j, item.metatileId, true);
layout->setBorderMetatileId(pos.x() + i, pos.y() + j, item.metatileId, true);
}
}
if (map->layout->border != oldBorder) {
map->editHistory.push(new PaintBorder(map, oldBorder, map->layout->border, 0));
if (layout->border != oldBorder) {
layout->editHistory.push(new PaintBorder(layout, oldBorder, layout->border, 0));
}
emit borderMetatilesChanged();
}
void BorderMetatilesPixmapItem::draw() {
map->setBorderItem(this);
layout->setBorderItem(this);
int width = map->getBorderWidth();
int height = map->getBorderHeight();
int width = layout->getBorderWidth();
int height = layout->getBorderHeight();
QImage image(16 * width, 16 * height, QImage::Format_RGBA8888);
QPainter painter(&image);
@ -39,11 +39,11 @@ void BorderMetatilesPixmapItem::draw() {
int x = i * 16;
int y = j * 16;
QImage metatile_image = getMetatileImage(
map->getBorderMetatileId(i, j),
map->layout->tileset_primary,
map->layout->tileset_secondary,
map->metatileLayerOrder,
map->metatileLayerOpacity);
layout->getBorderMetatileId(i, j),
layout->tileset_primary,
layout->tileset_secondary,
layout->metatileLayerOrder,
layout->metatileLayerOpacity);
QPoint metatile_origin = QPoint(x, y);
painter.drawImage(metatile_origin, metatile_image);
}
@ -57,7 +57,7 @@ void BorderMetatilesPixmapItem::draw() {
void BorderMetatilesPixmapItem::hoverUpdate(const QPointF &pixmapPos) {
QPoint pos = Metatile::coordFromPixmapCoord(pixmapPos);
uint16_t metatileId = this->map->getBorderMetatileId(pos.x(), pos.y());
uint16_t metatileId = this->layout->getBorderMetatileId(pos.x(), pos.y());
emit this->hoveredBorderMetatileSelectionChanged(metatileId);
}

View file

@ -8,7 +8,7 @@ void CollisionPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
this->previousPos = pos;
emit this->hoveredMapMovementPermissionChanged(pos.x(), pos.y());
}
if (this->settings->betterCursors && this->paintingMode == MapPixmapItem::PaintMode::Metatiles) {
if (this->settings->betterCursors && this->getEditsEnabled()) {
setCursor(this->settings->mapCursor);
}
}
@ -21,7 +21,7 @@ void CollisionPixmapItem::hoverEnterEvent(QGraphicsSceneHoverEvent * event) {
void CollisionPixmapItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *) {
emit this->hoveredMapMovementPermissionCleared();
if (this->settings->betterCursors && this->paintingMode == MapPixmapItem::PaintMode::Metatiles){
if (this->settings->betterCursors && this->getEditsEnabled()){
unsetCursor();
}
this->has_mouse = false;
@ -49,9 +49,9 @@ void CollisionPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
}
void CollisionPixmapItem::draw(bool ignoreCache) {
if (map) {
map->setCollisionItem(this);
setPixmap(map->renderCollision(ignoreCache));
if (this->layout) {
this->layout->setCollisionItem(this);
setPixmap(this->layout->renderCollision(ignoreCache));
setOpacity(*this->opacity);
}
}
@ -59,8 +59,8 @@ void CollisionPixmapItem::draw(bool ignoreCache) {
void CollisionPixmapItem::paint(QGraphicsSceneMouseEvent *event) {
if (event->type() == QEvent::GraphicsSceneMouseRelease) {
actionId_++;
} else if (map) {
Blockdata oldCollision = map->layout->blockdata;
} else if (this->layout) {
Blockdata oldCollision = this->layout->blockdata;
QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
@ -70,18 +70,18 @@ void CollisionPixmapItem::paint(QGraphicsSceneMouseEvent *event) {
pos = this->adjustCoords(pos);
} else {
this->prevStraightPathState = false;
this->lockedAxis = MapPixmapItem::Axis::None;
this->lockedAxis = LayoutPixmapItem::Axis::None;
}
Block block;
if (map->getBlock(pos.x(), pos.y(), &block)) {
if (this->layout->getBlock(pos.x(), pos.y(), &block)) {
block.setCollision(this->selectedCollision->value());
block.setElevation(this->selectedElevation->value());
map->setBlock(pos.x(), pos.y(), block, true);
this->layout->setBlock(pos.x(), pos.y(), block, true);
}
if (map->layout->blockdata != oldCollision) {
map->editHistory.push(new PaintCollision(map, oldCollision, map->layout->blockdata, actionId_));
if (this->layout->blockdata != oldCollision) {
this->layout->editHistory.push(new PaintCollision(this->layout, oldCollision, this->layout->blockdata, actionId_));
}
}
}
@ -89,16 +89,16 @@ void CollisionPixmapItem::paint(QGraphicsSceneMouseEvent *event) {
void CollisionPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) {
if (event->type() == QEvent::GraphicsSceneMouseRelease) {
this->actionId_++;
} else if (map) {
Blockdata oldCollision = map->layout->blockdata;
} else if (this->layout) {
Blockdata oldCollision = this->layout->blockdata;
QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
uint16_t collision = this->selectedCollision->value();
uint16_t elevation = this->selectedElevation->value();
map->floodFillCollisionElevation(pos.x(), pos.y(), collision, elevation);
this->layout->floodFillCollisionElevation(pos.x(), pos.y(), collision, elevation);
if (map->layout->blockdata != oldCollision) {
map->editHistory.push(new BucketFillCollision(map, oldCollision, map->layout->blockdata));
if (this->layout->blockdata != oldCollision) {
this->layout->editHistory.push(new BucketFillCollision(this->layout, oldCollision, this->layout->blockdata));
}
}
}
@ -106,15 +106,15 @@ void CollisionPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) {
void CollisionPixmapItem::magicFill(QGraphicsSceneMouseEvent *event) {
if (event->type() == QEvent::GraphicsSceneMouseRelease) {
this->actionId_++;
} else if (map) {
Blockdata oldCollision = map->layout->blockdata;
} else if (this->layout) {
Blockdata oldCollision = this->layout->blockdata;
QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
uint16_t collision = this->selectedCollision->value();
uint16_t elevation = this->selectedElevation->value();
map->magicFillCollisionElevation(pos.x(), pos.y(), collision, elevation);
this->layout->magicFillCollisionElevation(pos.x(), pos.y(), collision, elevation);
if (map->layout->blockdata != oldCollision) {
map->editHistory.push(new MagicFillCollision(map, oldCollision, map->layout->blockdata));
if (this->layout->blockdata != oldCollision) {
this->layout->editHistory.push(new MagicFillCollision(this->layout, oldCollision, this->layout->blockdata));
}
}
}
@ -129,15 +129,15 @@ void CollisionPixmapItem::updateMovementPermissionSelection(QGraphicsSceneMouseE
// Snap point to within map bounds.
if (pos.x() < 0) pos.setX(0);
if (pos.x() >= map->getWidth()) pos.setX(map->getWidth() - 1);
if (pos.x() >= this->layout->getWidth()) pos.setX(this->layout->getWidth() - 1);
if (pos.y() < 0) pos.setY(0);
if (pos.y() >= map->getHeight()) pos.setY(map->getHeight() - 1);
if (pos.y() >= this->layout->getHeight()) pos.setY(this->layout->getHeight() - 1);
this->updateSelection(pos);
}
void CollisionPixmapItem::updateSelection(QPoint pos) {
Block block;
if (map->getBlock(pos.x(), pos.y(), &block)) {
if (this->layout->getBlock(pos.x(), pos.y(), &block)) {
this->selectedCollision->setValue(block.collision());
this->selectedElevation->setValue(block.elevation());
}

View file

@ -9,6 +9,7 @@ ConnectionPixmapItem::ConnectionPixmapItem(MapConnection* connection, int x, int
connection(connection)
{
this->setEditable(true);
setFlag(ItemIsFocusable, true);
this->basePixmap = pixmap();
this->setOrigin(x, y);
}
@ -110,17 +111,20 @@ bool ConnectionPixmapItem::getEditable() {
}
void ConnectionPixmapItem::setSelected(bool selected) {
if (selected && !hasFocus()) {
setFocus(Qt::OtherFocusReason);
}
if (this->selected == selected)
return;
this->selected = selected;
this->render();
emit selectionChanged(selected);
}
void ConnectionPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *) {
if (!this->getEditable())
return;
this->setSelected(true);
setFocus(Qt::MouseFocusReason);
}
void ConnectionPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
@ -131,3 +135,18 @@ void ConnectionPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
void ConnectionPixmapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) {
emit connectionItemDoubleClicked(this->connection);
}
void ConnectionPixmapItem::keyPressEvent(QKeyEvent* event) {
if (event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace) {
emit deleteRequested(this->connection);
} else {
QGraphicsPixmapItem::keyPressEvent(event);
}
}
void ConnectionPixmapItem::focusInEvent(QFocusEvent* event) {
if (!this->getEditable())
return;
this->setSelected(true);
QGraphicsPixmapItem::focusInEvent(event);
}

View file

@ -10,6 +10,7 @@ ConnectionsListItem::ConnectionsListItem(QWidget *parent, MapConnection * connec
ui(new Ui::ConnectionsListItem)
{
ui->setupUi(this);
setFocusPolicy(Qt::StrongFocus);
const QSignalBlocker blocker1(ui->comboBox_Direction);
const QSignalBlocker blocker2(ui->comboBox_Map);
@ -101,3 +102,16 @@ void ConnectionsListItem::on_button_Delete_clicked() {
void ConnectionsListItem::on_button_OpenMap_clicked() {
emit openMapClicked(this->connection);
}
void ConnectionsListItem::focusInEvent(QFocusEvent* event) {
this->setSelected(true);
QFrame::focusInEvent(event);
}
void ConnectionsListItem::keyPressEvent(QKeyEvent* event) {
if (event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace) {
on_button_Delete_clicked();
} else {
QFrame::keyPressEvent(event);
}
}

View file

@ -2,7 +2,7 @@
#include "imageproviders.h"
#include <QPainter>
QPixmap drawMetatileSelection(MetatileSelection selection, Map *map) {
QPixmap drawMetatileSelection(MetatileSelection selection, Layout *layout) {
int width = selection.dimensions.x() * 16;
int height = selection.dimensions.y() * 16;
QImage image(width, height, QImage::Format_RGBA8888);
@ -19,10 +19,10 @@ QPixmap drawMetatileSelection(MetatileSelection selection, Map *map) {
if (item.enabled) {
QImage metatile_image = getMetatileImage(
item.metatileId,
map->layout->tileset_primary,
map->layout->tileset_secondary,
map->metatileLayerOrder,
map->metatileLayerOpacity);
layout->tileset_primary,
layout->tileset_secondary,
layout->metatileLayerOrder,
layout->metatileLayerOpacity);
painter.drawImage(metatile_origin, metatile_image);
}
}
@ -34,5 +34,5 @@ QPixmap drawMetatileSelection(MetatileSelection selection, Map *map) {
void CurrentSelectedMetatilesPixmapItem::draw() {
MetatileSelection selection = metatileSelector->getMetatileSelection();
setPixmap(drawMetatileSelection(selection, this->map));
setPixmap(drawMetatileSelection(selection, this->layout));
}

26
src/ui/eventfilters.cpp Normal file
View file

@ -0,0 +1,26 @@
#include "eventfilters.h"
#include <QGraphicsSceneWheelEvent>
bool WheelFilter::eventFilter(QObject *, QEvent *event) {
if (event->type() == QEvent::Wheel) {
return true;
}
return false;
}
bool MapSceneEventFilter::eventFilter(QObject*, QEvent *event) {
if (event->type() == QEvent::GraphicsSceneWheel) {
QGraphicsSceneWheelEvent *wheelEvent = static_cast<QGraphicsSceneWheelEvent *>(event);
if (wheelEvent->modifiers() & Qt::ControlModifier) {
emit wheelZoom(wheelEvent->delta() > 0 ? 1 : -1);
event->accept();
return true;
}
}
return false;
}

View file

@ -8,6 +8,15 @@ FilterChildrenProxyModel::FilterChildrenProxyModel(QObject *parent) :
bool FilterChildrenProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
if (this->hideEmpty && source_parent.row() < 0) // want to hide children
{
QModelIndex source_index = sourceModel()->index(source_row, this->filterKeyColumn(), source_parent) ;
if(source_index.isValid())
{
if (!sourceModel()->hasChildren(source_index))
return false;
}
}
// custom behaviour :
if(filterRegularExpression().pattern().isEmpty() == false)
{

View file

@ -24,6 +24,14 @@ void GraphicsView::moveEvent(QMoveEvent *event) {
label_MapRulerStatus->move(mapToGlobal(QPoint(6, 6)));
}
void MapView::keyPressEvent(QKeyEvent *event) {
if (editor && (event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace)) {
editor->deleteSelectedEvents();
} else {
QGraphicsView::keyPressEvent(event);
}
}
void MapView::drawForeground(QPainter *painter, const QRectF&) {
for (auto i = this->overlayMap.constBegin(); i != this->overlayMap.constEnd(); i++) {
i.value()->renderItems(painter);

View file

@ -1,4 +1,4 @@
#include "mappixmapitem.h"
#include "layoutpixmapitem.h"
#include "metatile.h"
#include "log.h"
#include "scripting.h"
@ -7,8 +7,8 @@
#define SWAP(a, b) do { if (a != b) { a ^= b; b ^= a; a ^= b; } } while (0)
void MapPixmapItem::paint(QGraphicsSceneMouseEvent *event) {
if (map) {
void LayoutPixmapItem::paint(QGraphicsSceneMouseEvent *event) {
if (layout) {
if (event->type() == QEvent::GraphicsSceneMouseRelease) {
actionId_++;
} else {
@ -20,7 +20,7 @@ void MapPixmapItem::paint(QGraphicsSceneMouseEvent *event) {
pos = this->adjustCoords(pos);
} else {
this->prevStraightPathState = false;
this->lockedAxis = MapPixmapItem::Axis::None;
this->lockedAxis = LayoutPixmapItem::Axis::None;
}
// Paint onto the map.
@ -43,8 +43,8 @@ void MapPixmapItem::paint(QGraphicsSceneMouseEvent *event) {
}
}
void MapPixmapItem::shift(QGraphicsSceneMouseEvent *event) {
if (map) {
void LayoutPixmapItem::shift(QGraphicsSceneMouseEvent *event) {
if (layout) {
if (event->type() == QEvent::GraphicsSceneMouseRelease) {
actionId_++;
} else {
@ -56,7 +56,7 @@ void MapPixmapItem::shift(QGraphicsSceneMouseEvent *event) {
pos = this->adjustCoords(pos);
} else {
this->prevStraightPathState = false;
this->lockedAxis = MapPixmapItem::Axis::None;
this->lockedAxis = LayoutPixmapItem::Axis::None;
}
if (event->type() == QEvent::GraphicsSceneMousePress) {
@ -76,32 +76,32 @@ void MapPixmapItem::shift(QGraphicsSceneMouseEvent *event) {
}
}
void MapPixmapItem::shift(int xDelta, int yDelta, bool fromScriptCall) {
Blockdata oldMetatiles = map->layout->blockdata;
void LayoutPixmapItem::shift(int xDelta, int yDelta, bool fromScriptCall) {
Blockdata oldMetatiles = this->layout->blockdata;
for (int i = 0; i < map->getWidth(); i++)
for (int j = 0; j < map->getHeight(); j++) {
for (int i = 0; i < this->layout->getWidth(); i++)
for (int j = 0; j < this->layout->getHeight(); j++) {
int destX = i + xDelta;
int destY = j + yDelta;
if (destX < 0)
do { destX += map->getWidth(); } while (destX < 0);
do { destX += this->layout->getWidth(); } while (destX < 0);
if (destY < 0)
do { destY += map->getHeight(); } while (destY < 0);
destX %= map->getWidth();
destY %= map->getHeight();
do { destY += this->layout->getHeight(); } while (destY < 0);
destX %= this->layout->getWidth();
destY %= this->layout->getHeight();
int blockIndex = j * map->getWidth() + i;
int blockIndex = j * this->layout->getWidth() + i;
Block srcBlock = oldMetatiles.at(blockIndex);
map->setBlock(destX, destY, srcBlock);
this->layout->setBlock(destX, destY, srcBlock);
}
if (!fromScriptCall && map->layout->blockdata != oldMetatiles) {
map->editHistory.push(new ShiftMetatiles(map, oldMetatiles, map->layout->blockdata, actionId_));
if (!fromScriptCall && this->layout->blockdata != oldMetatiles) {
this->layout->editHistory.push(new ShiftMetatiles(this->layout, oldMetatiles, this->layout->blockdata, actionId_));
Scripting::cb_MapShifted(xDelta, yDelta);
}
}
void MapPixmapItem::paintNormal(int x, int y, bool fromScriptCall) {
void LayoutPixmapItem::paintNormal(int x, int y, bool fromScriptCall) {
MetatileSelection selection = this->metatileSelector->getMetatileSelection();
int initialX = fromScriptCall ? x : this->paint_tile_initial_x;
int initialY = fromScriptCall ? y : this->paint_tile_initial_y;
@ -117,14 +117,14 @@ void MapPixmapItem::paintNormal(int x, int y, bool fromScriptCall) {
y = initialY + (yDiff / selection.dimensions.y()) * selection.dimensions.y();
// for edit history
Blockdata oldMetatiles = !fromScriptCall ? map->layout->blockdata : Blockdata();
Blockdata oldMetatiles = !fromScriptCall ? this->layout->blockdata : Blockdata();
for (int i = 0; i < selection.dimensions.x() && i + x < map->getWidth(); i++)
for (int j = 0; j < selection.dimensions.y() && j + y < map->getHeight(); j++) {
for (int i = 0; i < selection.dimensions.x() && i + x < this->layout->getWidth(); i++)
for (int j = 0; j < selection.dimensions.y() && j + y < this->layout->getHeight(); j++) {
int actualX = i + x;
int actualY = j + y;
Block block;
if (map->getBlock(actualX, actualY, &block)) {
if (this->layout->getBlock(actualX, actualY, &block)) {
int index = j * selection.dimensions.x() + i;
MetatileSelectionItem item = selection.metatileItems.at(index);
if (!item.enabled)
@ -135,19 +135,19 @@ void MapPixmapItem::paintNormal(int x, int y, bool fromScriptCall) {
block.setCollision(collisionItem.collision);
block.setElevation(collisionItem.elevation);
}
map->setBlock(actualX, actualY, block, !fromScriptCall);
this->layout->setBlock(actualX, actualY, block, !fromScriptCall);
}
}
if (!fromScriptCall && map->layout->blockdata != oldMetatiles) {
map->editHistory.push(new PaintMetatile(map, oldMetatiles, map->layout->blockdata, actionId_));
if (!fromScriptCall && this->layout->blockdata != oldMetatiles) {
this->layout->editHistory.push(new PaintMetatile(this->layout, oldMetatiles, this->layout->blockdata, actionId_));
}
}
// These are tile offsets from the top-left tile in the 3x3 smart path selection.
// Each entry is for one possibility from the marching squares value for a tile.
// (Marching Squares: https://en.wikipedia.org/wiki/Marching_squares)
QList<int> MapPixmapItem::smartPathTable = QList<int>({
QList<int> LayoutPixmapItem::smartPathTable = QList<int>({
4, // 0000
4, // 0001
4, // 0010
@ -189,7 +189,7 @@ bool isValidSmartPathSelection(MetatileSelection selection) {
return true;
}
void MapPixmapItem::paintSmartPath(int x, int y, bool fromScriptCall) {
void LayoutPixmapItem::paintSmartPath(int x, int y, bool fromScriptCall) {
MetatileSelection selection = this->metatileSelector->getMetatileSelection();
if (!isValidSmartPathSelection(selection))
return;
@ -206,30 +206,30 @@ void MapPixmapItem::paintSmartPath(int x, int y, bool fromScriptCall) {
}
// for edit history
Blockdata oldMetatiles = !fromScriptCall ? map->layout->blockdata : Blockdata();
Blockdata oldMetatiles = !fromScriptCall ? this->layout->blockdata : Blockdata();
// Fill the region with the open tile.
for (int i = 0; i <= 1; i++)
for (int j = 0; j <= 1; j++) {
if (!map->isWithinBounds(x + i, y + j))
if (!this->layout->isWithinBounds(x + i, y + j))
continue;
int actualX = i + x;
int actualY = j + y;
Block block;
if (map->getBlock(actualX, actualY, &block)) {
if (this->layout->getBlock(actualX, actualY, &block)) {
block.setMetatileId(openMetatileId);
if (setCollisions) {
block.setCollision(openCollision);
block.setElevation(openElevation);
}
map->setBlock(actualX, actualY, block, !fromScriptCall);
this->layout->setBlock(actualX, actualY, block, !fromScriptCall);
}
}
// Go back and resolve the edge tiles
for (int i = -1; i <= 2; i++)
for (int j = -1; j <= 2; j++) {
if (!map->isWithinBounds(x + i, y + j))
if (!this->layout->isWithinBounds(x + i, y + j))
continue;
// Ignore the corners, which can't possible be affected by the smart path.
if ((i == -1 && j == -1) || (i == 2 && j == -1) ||
@ -240,7 +240,7 @@ void MapPixmapItem::paintSmartPath(int x, int y, bool fromScriptCall) {
int actualX = i + x;
int actualY = j + y;
Block block;
if (!map->getBlock(actualX, actualY, &block) || !isSmartPathTile(selection.metatileItems, block.metatileId())) {
if (!this->layout->getBlock(actualX, actualY, &block) || !isSmartPathTile(selection.metatileItems, block.metatileId())) {
continue;
}
@ -251,13 +251,13 @@ void MapPixmapItem::paintSmartPath(int x, int y, bool fromScriptCall) {
Block left;
// Get marching squares value, to determine which tile to use.
if (map->getBlock(actualX, actualY - 1, &top) && isSmartPathTile(selection.metatileItems, top.metatileId()))
if (this->layout->getBlock(actualX, actualY - 1, &top) && isSmartPathTile(selection.metatileItems, top.metatileId()))
id += 1;
if (map->getBlock(actualX + 1, actualY, &right) && isSmartPathTile(selection.metatileItems, right.metatileId()))
if (this->layout->getBlock(actualX + 1, actualY, &right) && isSmartPathTile(selection.metatileItems, right.metatileId()))
id += 2;
if (map->getBlock(actualX, actualY + 1, &bottom) && isSmartPathTile(selection.metatileItems, bottom.metatileId()))
if (this->layout->getBlock(actualX, actualY + 1, &bottom) && isSmartPathTile(selection.metatileItems, bottom.metatileId()))
id += 4;
if (map->getBlock(actualX - 1, actualY, &left) && isSmartPathTile(selection.metatileItems, left.metatileId()))
if (this->layout->getBlock(actualX - 1, actualY, &left) && isSmartPathTile(selection.metatileItems, left.metatileId()))
id += 8;
block.setMetatileId(selection.metatileItems.at(smartPathTable[id]).metatileId);
@ -266,19 +266,19 @@ void MapPixmapItem::paintSmartPath(int x, int y, bool fromScriptCall) {
block.setCollision(collisionItem.collision);
block.setElevation(collisionItem.elevation);
}
map->setBlock(actualX, actualY, block, !fromScriptCall);
this->layout->setBlock(actualX, actualY, block, !fromScriptCall);
}
if (!fromScriptCall && map->layout->blockdata != oldMetatiles) {
map->editHistory.push(new PaintMetatile(map, oldMetatiles, map->layout->blockdata, actionId_));
if (!fromScriptCall && this->layout->blockdata != oldMetatiles) {
this->layout->editHistory.push(new PaintMetatile(this->layout, oldMetatiles, this->layout->blockdata, actionId_));
}
}
void MapPixmapItem::lockNondominantAxis(QGraphicsSceneMouseEvent *event) {
void LayoutPixmapItem::lockNondominantAxis(QGraphicsSceneMouseEvent *event) {
/* Return if an axis is already locked, or if the mouse has been released. The mouse release check is necessary
* because MapPixmapItem::mouseReleaseEvent seems to get called before this function, which would unlock the axis
* because LayoutPixmapItem::mouseReleaseEvent seems to get called before this function, which would unlock the axis
* and then get immediately re-locked here until the next ctrl-click. */
if (this->lockedAxis != MapPixmapItem::Axis::None || event->type() == QEvent::GraphicsSceneMouseRelease)
if (this->lockedAxis != LayoutPixmapItem::Axis::None || event->type() == QEvent::GraphicsSceneMouseRelease)
return;
QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
@ -293,31 +293,31 @@ void MapPixmapItem::lockNondominantAxis(QGraphicsSceneMouseEvent *event) {
int yDiff = pos.y() - this->straight_path_initial_y;
if (xDiff || yDiff) {
if (abs(xDiff) < abs(yDiff)) {
this->lockedAxis = MapPixmapItem::Axis::X;
this->lockedAxis = LayoutPixmapItem::Axis::X;
} else {
this->lockedAxis = MapPixmapItem::Axis::Y;
this->lockedAxis = LayoutPixmapItem::Axis::Y;
}
}
}
// Adjust the cooresponding coordinate when it is locked
QPoint MapPixmapItem::adjustCoords(QPoint pos) {
if (this->lockedAxis == MapPixmapItem::Axis::X) {
QPoint LayoutPixmapItem::adjustCoords(QPoint pos) {
if (this->lockedAxis == LayoutPixmapItem::Axis::X) {
pos.setX(this->straight_path_initial_x);
} else if (this->lockedAxis == MapPixmapItem::Axis::Y) {
} else if (this->lockedAxis == LayoutPixmapItem::Axis::Y) {
pos.setY(this->straight_path_initial_y);
}
return pos;
}
void MapPixmapItem::updateMetatileSelection(QGraphicsSceneMouseEvent *event) {
void LayoutPixmapItem::updateMetatileSelection(QGraphicsSceneMouseEvent *event) {
QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
// Snap point to within map bounds.
// Snap point to within layout bounds.
if (pos.x() < 0) pos.setX(0);
if (pos.x() >= map->getWidth()) pos.setX(map->getWidth() - 1);
if (pos.x() >= this->layout->getWidth()) pos.setX(this->layout->getWidth() - 1);
if (pos.y() < 0) pos.setY(0);
if (pos.y() >= map->getHeight()) pos.setY(map->getHeight() - 1);
if (pos.y() >= this->layout->getHeight()) pos.setY(this->layout->getHeight() - 1);
// Update/apply copied metatiles.
if (event->type() == QEvent::GraphicsSceneMousePress) {
@ -325,7 +325,7 @@ void MapPixmapItem::updateMetatileSelection(QGraphicsSceneMouseEvent *event) {
selection.clear();
selection.append(QPoint(pos.x(), pos.y()));
Block block;
if (map->getBlock(pos.x(), pos.y(), &block)) {
if (this->layout->getBlock(pos.x(), pos.y(), &block)) {
this->metatileSelector->selectFromMap(block.metatileId(), block.collision(), block.elevation());
}
} else if (event->type() == QEvent::GraphicsSceneMouseMove) {
@ -348,11 +348,11 @@ void MapPixmapItem::updateMetatileSelection(QGraphicsSceneMouseEvent *event) {
int x = point.x();
int y = point.y();
Block block;
if (map->getBlock(x, y, &block)) {
if (this->layout->getBlock(x, y, &block)) {
metatiles.append(block.metatileId());
}
int blockIndex = y * map->getWidth() + x;
block = map->layout->blockdata.at(blockIndex);
int blockIndex = y * this->layout->getWidth() + x;
block = this->layout->blockdata.at(blockIndex);
auto collision = block.collision();
auto elevation = block.elevation();
collisions.append(QPair<uint16_t, uint16_t>(collision, elevation));
@ -362,8 +362,8 @@ void MapPixmapItem::updateMetatileSelection(QGraphicsSceneMouseEvent *event) {
}
}
void MapPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) {
if (map) {
void LayoutPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) {
if (this->layout) {
if (event->type() == QEvent::GraphicsSceneMouseRelease) {
actionId_++;
} else {
@ -371,7 +371,7 @@ void MapPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) {
Block block;
MetatileSelection selection = this->metatileSelector->getMetatileSelection();
int metatileId = selection.metatileItems.first().metatileId;
if (selection.metatileItems.count() > 1 || (map->getBlock(pos.x(), pos.y(), &block) && block.metatileId() != metatileId)) {
if (selection.metatileItems.count() > 1 || (this->layout->getBlock(pos.x(), pos.y(), &block) && block.metatileId() != metatileId)) {
bool smartPathsEnabled = event->modifiers() & Qt::ShiftModifier;
if ((this->settings->smartPathsEnabled || smartPathsEnabled) && selection.dimensions.x() == 3 && selection.dimensions.y() == 3)
this->floodFillSmartPath(pos.x(), pos.y());
@ -382,8 +382,8 @@ void MapPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) {
}
}
void MapPixmapItem::magicFill(QGraphicsSceneMouseEvent *event) {
if (map) {
void LayoutPixmapItem::magicFill(QGraphicsSceneMouseEvent *event) {
if (this->layout) {
if (event->type() == QEvent::GraphicsSceneMouseRelease) {
actionId_++;
} else {
@ -393,18 +393,18 @@ void MapPixmapItem::magicFill(QGraphicsSceneMouseEvent *event) {
}
}
void MapPixmapItem::magicFill(int x, int y, uint16_t metatileId, bool fromScriptCall) {
void LayoutPixmapItem::magicFill(int x, int y, uint16_t metatileId, bool fromScriptCall) {
QPoint selectionDimensions(1, 1);
QList<MetatileSelectionItem> selectedMetatiles = QList<MetatileSelectionItem>({MetatileSelectionItem{ true, metatileId }});
this->magicFill(x, y, selectionDimensions, selectedMetatiles, QList<CollisionSelectionItem>(), fromScriptCall);
}
void MapPixmapItem::magicFill(int x, int y, bool fromScriptCall) {
void LayoutPixmapItem::magicFill(int x, int y, bool fromScriptCall) {
MetatileSelection selection = this->metatileSelector->getMetatileSelection();
this->magicFill(x, y, selection.dimensions, selection.metatileItems, selection.collisionItems, fromScriptCall);
}
void MapPixmapItem::magicFill(
void LayoutPixmapItem::magicFill(
int initialX,
int initialY,
QPoint selectionDimensions,
@ -412,18 +412,18 @@ void MapPixmapItem::magicFill(
QList<CollisionSelectionItem> selectedCollisions,
bool fromScriptCall) {
Block block;
if (map->getBlock(initialX, initialY, &block)) {
if (this->layout->getBlock(initialX, initialY, &block)) {
if (selectedMetatiles.length() == 1 && selectedMetatiles.at(0).metatileId == block.metatileId()) {
return;
}
Blockdata oldMetatiles = !fromScriptCall ? map->layout->blockdata : Blockdata();
Blockdata oldMetatiles = !fromScriptCall ? this->layout->blockdata : Blockdata();
bool setCollisions = selectedCollisions.length() == selectedMetatiles.length();
uint16_t metatileId = block.metatileId();
for (int y = 0; y < map->getHeight(); y++) {
for (int x = 0; x < map->getWidth(); x++) {
if (map->getBlock(x, y, &block) && block.metatileId() == metatileId) {
for (int y = 0; y < this->layout->getHeight(); y++) {
for (int x = 0; x < this->layout->getWidth(); x++) {
if (this->layout->getBlock(x, y, &block) && block.metatileId() == metatileId) {
int xDiff = x - initialX;
int yDiff = y - initialY;
int i = xDiff % selectionDimensions.x();
@ -438,30 +438,30 @@ void MapPixmapItem::magicFill(
block.setCollision(item.collision);
block.setElevation(item.elevation);
}
map->setBlock(x, y, block, !fromScriptCall);
this->layout->setBlock(x, y, block, !fromScriptCall);
}
}
}
}
if (!fromScriptCall && map->layout->blockdata != oldMetatiles) {
map->editHistory.push(new MagicFillMetatile(map, oldMetatiles, map->layout->blockdata, actionId_));
if (!fromScriptCall && this->layout->blockdata != oldMetatiles) {
this->layout->editHistory.push(new MagicFillMetatile(this->layout, oldMetatiles, this->layout->blockdata, actionId_));
}
}
}
void MapPixmapItem::floodFill(int initialX, int initialY, bool fromScriptCall) {
void LayoutPixmapItem::floodFill(int initialX, int initialY, bool fromScriptCall) {
MetatileSelection selection = this->metatileSelector->getMetatileSelection();
this->floodFill(initialX, initialY, selection.dimensions, selection.metatileItems, selection.collisionItems, fromScriptCall);
}
void MapPixmapItem::floodFill(int initialX, int initialY, uint16_t metatileId, bool fromScriptCall) {
void LayoutPixmapItem::floodFill(int initialX, int initialY, uint16_t metatileId, bool fromScriptCall) {
QPoint selectionDimensions(1, 1);
QList<MetatileSelectionItem> selectedMetatiles = QList<MetatileSelectionItem>({MetatileSelectionItem{true, metatileId}});
this->floodFill(initialX, initialY, selectionDimensions, selectedMetatiles, QList<CollisionSelectionItem>(), fromScriptCall);
}
void MapPixmapItem::floodFill(
void LayoutPixmapItem::floodFill(
int initialX,
int initialY,
QPoint selectionDimensions,
@ -469,7 +469,7 @@ void MapPixmapItem::floodFill(
QList<CollisionSelectionItem> selectedCollisions,
bool fromScriptCall) {
bool setCollisions = selectedCollisions.length() == selectedMetatiles.length();
Blockdata oldMetatiles = !fromScriptCall ? map->layout->blockdata : Blockdata();
Blockdata oldMetatiles = !fromScriptCall ? this->layout->blockdata : Blockdata();
QSet<int> visited;
QList<QPoint> todo;
@ -479,11 +479,11 @@ void MapPixmapItem::floodFill(
int x = point.x();
int y = point.y();
Block block;
if (!map->getBlock(x, y, &block)) {
if (!this->layout->getBlock(x, y, &block)) {
continue;
}
visited.insert(x + y * map->getWidth());
visited.insert(x + y * this->layout->getWidth());
int xDiff = x - initialX;
int yDiff = y - initialY;
int i = xDiff % selectionDimensions.x();
@ -500,32 +500,32 @@ void MapPixmapItem::floodFill(
block.setCollision(item.collision);
block.setElevation(item.elevation);
}
map->setBlock(x, y, block, !fromScriptCall);
this->layout->setBlock(x, y, block, !fromScriptCall);
}
if (!visited.contains(x + 1 + y * map->getWidth()) && map->getBlock(x + 1, y, &block) && block.metatileId() == old_metatileId) {
if (!visited.contains(x + 1 + y * this->layout->getWidth()) && this->layout->getBlock(x + 1, y, &block) && block.metatileId() == old_metatileId) {
todo.append(QPoint(x + 1, y));
visited.insert(x + 1 + y * map->getWidth());
visited.insert(x + 1 + y * this->layout->getWidth());
}
if (!visited.contains(x - 1 + y * map->getWidth()) && map->getBlock(x - 1, y, &block) && block.metatileId() == old_metatileId) {
if (!visited.contains(x - 1 + y * this->layout->getWidth()) && this->layout->getBlock(x - 1, y, &block) && block.metatileId() == old_metatileId) {
todo.append(QPoint(x - 1, y));
visited.insert(x - 1 + y * map->getWidth());
visited.insert(x - 1 + y * this->layout->getWidth());
}
if (!visited.contains(x + (y + 1) * map->getWidth()) && map->getBlock(x, y + 1, &block) && block.metatileId() == old_metatileId) {
if (!visited.contains(x + (y + 1) * this->layout->getWidth()) && this->layout->getBlock(x, y + 1, &block) && block.metatileId() == old_metatileId) {
todo.append(QPoint(x, y + 1));
visited.insert(x + (y + 1) * map->getWidth());
visited.insert(x + (y + 1) * this->layout->getWidth());
}
if (!visited.contains(x + (y - 1) * map->getWidth()) && map->getBlock(x, y - 1, &block) && block.metatileId() == old_metatileId) {
if (!visited.contains(x + (y - 1) * this->layout->getWidth()) && this->layout->getBlock(x, y - 1, &block) && block.metatileId() == old_metatileId) {
todo.append(QPoint(x, y - 1));
visited.insert(x + (y - 1) * map->getWidth());
visited.insert(x + (y - 1) * this->layout->getWidth());
}
}
if (!fromScriptCall && map->layout->blockdata != oldMetatiles) {
map->editHistory.push(new BucketFillMetatile(map, oldMetatiles, map->layout->blockdata, actionId_));
if (!fromScriptCall && this->layout->blockdata != oldMetatiles) {
this->layout->editHistory.push(new BucketFillMetatile(this->layout, oldMetatiles, this->layout->blockdata, actionId_));
}
}
void MapPixmapItem::floodFillSmartPath(int initialX, int initialY, bool fromScriptCall) {
void LayoutPixmapItem::floodFillSmartPath(int initialX, int initialY, bool fromScriptCall) {
MetatileSelection selection = this->metatileSelector->getMetatileSelection();
if (!isValidSmartPathSelection(selection))
return;
@ -542,7 +542,7 @@ void MapPixmapItem::floodFillSmartPath(int initialX, int initialY, bool fromScri
setCollisions = true;
}
Blockdata oldMetatiles = !fromScriptCall ? map->layout->blockdata : Blockdata();
Blockdata oldMetatiles = !fromScriptCall ? this->layout->blockdata : Blockdata();
// Flood fill the region with the open tile.
QList<QPoint> todo;
@ -552,7 +552,7 @@ void MapPixmapItem::floodFillSmartPath(int initialX, int initialY, bool fromScri
int x = point.x();
int y = point.y();
Block block;
if (!map->getBlock(x, y, &block)) {
if (!this->layout->getBlock(x, y, &block)) {
continue;
}
@ -566,17 +566,17 @@ void MapPixmapItem::floodFillSmartPath(int initialX, int initialY, bool fromScri
block.setCollision(openCollision);
block.setElevation(openElevation);
}
map->setBlock(x, y, block, !fromScriptCall);
if (map->getBlock(x + 1, y, &block) && block.metatileId() == old_metatileId) {
this->layout->setBlock(x, y, block, !fromScriptCall);
if (this->layout->getBlock(x + 1, y, &block) && block.metatileId() == old_metatileId) {
todo.append(QPoint(x + 1, y));
}
if (map->getBlock(x - 1, y, &block) && block.metatileId() == old_metatileId) {
if (this->layout->getBlock(x - 1, y, &block) && block.metatileId() == old_metatileId) {
todo.append(QPoint(x - 1, y));
}
if (map->getBlock(x, y + 1, &block) && block.metatileId() == old_metatileId) {
if (this->layout->getBlock(x, y + 1, &block) && block.metatileId() == old_metatileId) {
todo.append(QPoint(x, y + 1));
}
if (map->getBlock(x, y - 1, &block) && block.metatileId() == old_metatileId) {
if (this->layout->getBlock(x, y - 1, &block) && block.metatileId() == old_metatileId) {
todo.append(QPoint(x, y - 1));
}
}
@ -590,11 +590,11 @@ void MapPixmapItem::floodFillSmartPath(int initialX, int initialY, bool fromScri
int x = point.x();
int y = point.y();
Block block;
if (!map->getBlock(x, y, &block)) {
if (!this->layout->getBlock(x, y, &block)) {
continue;
}
visited.insert(x + y * map->getWidth());
visited.insert(x + y * this->layout->getWidth());
int id = 0;
Block top;
Block right;
@ -602,13 +602,13 @@ void MapPixmapItem::floodFillSmartPath(int initialX, int initialY, bool fromScri
Block left;
// Get marching squares value, to determine which tile to use.
if (map->getBlock(x, y - 1, &top) && isSmartPathTile(selection.metatileItems, top.metatileId()))
if (this->layout->getBlock(x, y - 1, &top) && isSmartPathTile(selection.metatileItems, top.metatileId()))
id += 1;
if (map->getBlock(x + 1, y, &right) && isSmartPathTile(selection.metatileItems, right.metatileId()))
if (this->layout->getBlock(x + 1, y, &right) && isSmartPathTile(selection.metatileItems, right.metatileId()))
id += 2;
if (map->getBlock(x, y + 1, &bottom) && isSmartPathTile(selection.metatileItems, bottom.metatileId()))
if (this->layout->getBlock(x, y + 1, &bottom) && isSmartPathTile(selection.metatileItems, bottom.metatileId()))
id += 4;
if (map->getBlock(x - 1, y, &left) && isSmartPathTile(selection.metatileItems, left.metatileId()))
if (this->layout->getBlock(x - 1, y, &left) && isSmartPathTile(selection.metatileItems, left.metatileId()))
id += 8;
block.setMetatileId(selection.metatileItems.at(smartPathTable[id]).metatileId);
@ -617,41 +617,41 @@ void MapPixmapItem::floodFillSmartPath(int initialX, int initialY, bool fromScri
block.setCollision(item.collision);
block.setElevation(item.elevation);
}
map->setBlock(x, y, block, !fromScriptCall);
this->layout->setBlock(x, y, block, !fromScriptCall);
// Visit neighbors if they are smart-path tiles, and don't revisit any.
if (!visited.contains(x + 1 + y * map->getWidth()) && map->getBlock(x + 1, y, &block) && isSmartPathTile(selection.metatileItems, block.metatileId())) {
if (!visited.contains(x + 1 + y * this->layout->getWidth()) && this->layout->getBlock(x + 1, y, &block) && isSmartPathTile(selection.metatileItems, block.metatileId())) {
todo.append(QPoint(x + 1, y));
visited.insert(x + 1 + y * map->getWidth());
visited.insert(x + 1 + y * this->layout->getWidth());
}
if (!visited.contains(x - 1 + y * map->getWidth()) && map->getBlock(x - 1, y, &block) && isSmartPathTile(selection.metatileItems, block.metatileId())) {
if (!visited.contains(x - 1 + y * this->layout->getWidth()) && this->layout->getBlock(x - 1, y, &block) && isSmartPathTile(selection.metatileItems, block.metatileId())) {
todo.append(QPoint(x - 1, y));
visited.insert(x - 1 + y * map->getWidth());
visited.insert(x - 1 + y * this->layout->getWidth());
}
if (!visited.contains(x + (y + 1) * map->getWidth()) && map->getBlock(x, y + 1, &block) && isSmartPathTile(selection.metatileItems, block.metatileId())) {
if (!visited.contains(x + (y + 1) * this->layout->getWidth()) && this->layout->getBlock(x, y + 1, &block) && isSmartPathTile(selection.metatileItems, block.metatileId())) {
todo.append(QPoint(x, y + 1));
visited.insert(x + (y + 1) * map->getWidth());
visited.insert(x + (y + 1) * this->layout->getWidth());
}
if (!visited.contains(x + (y - 1) * map->getWidth()) && map->getBlock(x, y - 1, &block) && isSmartPathTile(selection.metatileItems, block.metatileId())) {
if (!visited.contains(x + (y - 1) * this->layout->getWidth()) && this->layout->getBlock(x, y - 1, &block) && isSmartPathTile(selection.metatileItems, block.metatileId())) {
todo.append(QPoint(x, y - 1));
visited.insert(x + (y - 1) * map->getWidth());
visited.insert(x + (y - 1) * this->layout->getWidth());
}
}
if (!fromScriptCall && map->layout->blockdata != oldMetatiles) {
map->editHistory.push(new BucketFillMetatile(map, oldMetatiles, map->layout->blockdata, actionId_));
if (!fromScriptCall && this->layout->blockdata != oldMetatiles) {
this->layout->editHistory.push(new BucketFillMetatile(this->layout, oldMetatiles, this->layout->blockdata, actionId_));
}
}
void MapPixmapItem::pick(QGraphicsSceneMouseEvent *event) {
void LayoutPixmapItem::pick(QGraphicsSceneMouseEvent *event) {
QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
Block block;
if (map->getBlock(pos.x(), pos.y(), &block)) {
if (this->layout->getBlock(pos.x(), pos.y(), &block)) {
this->metatileSelector->selectFromMap(block.metatileId(), block.collision(), block.elevation());
}
}
void MapPixmapItem::select(QGraphicsSceneMouseEvent *event) {
void LayoutPixmapItem::select(QGraphicsSceneMouseEvent *event) {
QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
if (event->type() == QEvent::GraphicsSceneMousePress) {
selection_origin = QPoint(pos.x(), pos.y());
@ -681,43 +681,47 @@ void MapPixmapItem::select(QGraphicsSceneMouseEvent *event) {
}
}
void MapPixmapItem::draw(bool ignoreCache) {
if (map) {
map->setMapItem(this);
setPixmap(map->render(ignoreCache));
void LayoutPixmapItem::draw(bool ignoreCache) {
if (this->layout) {
layout->setLayoutItem(this);
setPixmap(this->layout->render(ignoreCache));
}
}
void MapPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
void LayoutPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
if (pos != this->metatilePos) {
this->metatilePos = pos;
emit this->hoveredMapMetatileChanged(pos);
}
if (this->settings->betterCursors && this->paintingMode != MapPixmapItem::PaintMode::Disabled) {
if (this->settings->betterCursors && this->editsEnabled) {
setCursor(this->settings->mapCursor);
}
}
void MapPixmapItem::hoverEnterEvent(QGraphicsSceneHoverEvent * event) {
void LayoutPixmapItem::hoverEnterEvent(QGraphicsSceneHoverEvent * event) {
this->has_mouse = true;
QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
emit this->hoveredMapMetatileChanged(pos);
}
void MapPixmapItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *) {
void LayoutPixmapItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *) {
emit this->hoveredMapMetatileCleared();
if (this->settings->betterCursors && this->paintingMode != MapPixmapItem::PaintMode::Disabled) {
if (this->settings->betterCursors && this->editsEnabled) {
unsetCursor();
}
this->has_mouse = false;
}
void MapPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
void LayoutPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
this->paint_tile_initial_x = this->straight_path_initial_x = pos.x();
this->paint_tile_initial_y = this->straight_path_initial_y = pos.y();
emit startPaint(event, this);
emit mouseEvent(event, this);
}
void MapPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
void LayoutPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
if (pos != this->metatilePos) {
this->metatilePos = pos;
@ -725,8 +729,9 @@ void MapPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
}
emit mouseEvent(event, this);
}
void MapPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
this->lockedAxis = MapPixmapItem::Axis::None;
void LayoutPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
this->lockedAxis = LayoutPixmapItem::Axis::None;
emit endPaint(event, this);
emit mouseEvent(event, this);
}

View file

@ -43,6 +43,7 @@ MapImageExporter::MapImageExporter(QWidget *parent_, Editor *editor_, ImageExpor
this->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));
@ -50,9 +51,11 @@ MapImageExporter::MapImageExporter(QWidget *parent_, Editor *editor_, ImageExpor
this->ui->groupBox_Connections->setVisible(this->mode != ImageExporterMode::Stitch);
this->ui->groupBox_Timelapse->setVisible(this->mode == ImageExporterMode::Timelapse);
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 (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
}
connect(ui->pushButton_Save, &QPushButton::pressed, this, &MapImageExporter::saveImage);
connect(ui->pushButton_Cancel, &QPushButton::pressed, this, &MapImageExporter::close);
@ -87,13 +90,13 @@ void MapImageExporter::saveImage() {
switch (this->mode)
{
case ImageExporterMode::Normal:
defaultFilename = map->name;
defaultFilename = this->map? this->map->name : this->layout->name;
break;
case ImageExporterMode::Stitch:
defaultFilename = QString("Stitch_From_%1").arg(map->name);
defaultFilename = QString("Stitch_From_%1").arg(this->map? this->map->name : this->layout->name);
break;
case ImageExporterMode::Timelapse:
defaultFilename = QString("Timelapse_%1").arg(map->name);
defaultFilename = QString("Timelapse_%1").arg(this->map? this->map->name : this->layout->name);
break;
}
@ -111,86 +114,100 @@ void MapImageExporter::saveImage() {
this->preview.save(filepath);
break;
case ImageExporterMode::Timelapse:
QProgressDialog progress("Building map timelapse...", "Cancel", 0, 1, this);
progress.setAutoClose(true);
progress.setWindowModality(Qt::WindowModal);
progress.setModal(true);
progress.setMaximum(1);
progress.setValue(0);
int maxWidth = this->map->getWidth() * 16;
int maxHeight = this->map->getHeight() * 16;
if (this->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 (this->map->editHistory.canUndo()) {
progress.setValue(i);
this->map->editHistory.undo();
int width = this->map->getWidth() * 16;
int height = this->map->getHeight() * 16;
if (this->settings.showBorder) {
width += 2 * STITCH_MODE_BORDER_DISTANCE * 16;
height += 2 * STITCH_MODE_BORDER_DISTANCE * 16;
}
if (width > maxWidth) {
maxWidth = width;
}
if (height > maxHeight) {
maxHeight = height;
}
i++;
}
QGifImage timelapseImg(QSize(maxWidth, maxHeight));
// 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.setDefaultTransparentColor(QColor(0, 0, 0));
// Draw each frame, skpping the specified number of map edits in
// the undo history.
progress.setMaximum(i);
while (i > 0) {
if (progress.wasCanceled()) {
progress.close();
while (i > 0 && this->map->editHistory.canRedo()) {
i--;
this->map->editHistory.redo();
// lambda to avoid redundancy
auto generateTimelapseFromHistory = [this, &timelapseImg](QString progressText, QUndoStack &historyStack){
QProgressDialog progress(progressText, "Cancel", 0, 1, this);
progress.setAutoClose(true);
progress.setWindowModality(Qt::WindowModal);
progress.setModal(true);
progress.setMaximum(1);
progress.setValue(0);
int maxWidth = this->layout->getWidth() * 16;
int maxHeight = this->layout->getHeight() * 16;
if (this->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()) {
progress.setValue(i);
historyStack.undo();
int width = this->layout->getWidth() * 16;
int height = this->layout->getHeight() * 16;
if (this->settings.showBorder) {
width += 2 * STITCH_MODE_BORDER_DISTANCE * 16;
height += 2 * STITCH_MODE_BORDER_DISTANCE * 16;
}
return;
if (width > maxWidth) {
maxWidth = width;
}
if (height > maxHeight) {
maxHeight = height;
}
i++;
}
while (this->map->editHistory.canRedo() &&
!historyItemAppliesToFrame(this->map->editHistory.command(this->map->editHistory.index()))) {
i--;
this->map->editHistory.redo();
}
progress.setValue(progress.maximum() - i);
QPixmap pixmap = this->getFormattedMapPixmap(this->map);
if (pixmap.width() < maxWidth || pixmap.height() < maxHeight) {
QPixmap pixmap2 = QPixmap(maxWidth, maxHeight);
QPainter painter(&pixmap2);
pixmap2.fill(QColor(0, 0, 0));
painter.drawPixmap(0, 0, pixmap.width(), pixmap.height(), pixmap);
painter.end();
pixmap = pixmap2;
}
timelapseImg.addFrame(pixmap.toImage());
for (int j = 0; j < this->settings.timelapseSkipAmount; j++) {
if (i > 0) {
i--;
this->map->editHistory.redo();
while (this->map->editHistory.canRedo() &&
!historyItemAppliesToFrame(this->map->editHistory.command(this->map->editHistory.index()))) {
// Draw each frame, skpping the specified number of map edits in
// the undo history.
progress.setMaximum(i);
while (i > 0) {
if (progress.wasCanceled()) {
progress.close();
while (i > 0 && historyStack.canRedo()) {
i--;
this->map->editHistory.redo();
historyStack.redo();
}
return;
}
while (historyStack.canRedo() &&
!historyItemAppliesToFrame(historyStack.command(historyStack.index()))) {
i--;
historyStack.redo();
}
progress.setValue(progress.maximum() - i);
QPixmap pixmap = this->getFormattedMapPixmap(this->map);
if (pixmap.width() < maxWidth || pixmap.height() < maxHeight) {
QPixmap pixmap2 = QPixmap(maxWidth, maxHeight);
QPainter painter(&pixmap2);
pixmap2.fill(QColor(0, 0, 0));
painter.drawPixmap(0, 0, pixmap.width(), pixmap.height(), pixmap);
painter.end();
pixmap = pixmap2;
}
timelapseImg.addFrame(pixmap.toImage());
for (int j = 0; j < this->settings.timelapseSkipAmount; j++) {
if (i > 0) {
i--;
historyStack.redo();
while (historyStack.canRedo() &&
!historyItemAppliesToFrame(historyStack.command(historyStack.index()))) {
i--;
historyStack.redo();
}
}
}
}
}
// The latest map state is the last animated frame.
QPixmap pixmap = this->getFormattedMapPixmap(this->map);
timelapseImg.addFrame(pixmap.toImage());
// The latest map state is the last animated frame.
QPixmap pixmap = this->getFormattedMapPixmap(this->map);
timelapseImg.addFrame(pixmap.toImage());
progress.close();
};
if (this->layout)
generateTimelapseFromHistory("Building layout timelapse...", this->layout->editHistory);
if (this->map)
generateTimelapseFromHistory("Building map timelapse...", this->map->editHistory);
timelapseImg.save(filepath);
progress.close();
break;
}
this->close();
@ -206,8 +223,8 @@ bool MapImageExporter::historyItemAppliesToFrame(const QUndoCommand *command) {
case CommandId::ID_BucketFillMetatile:
case CommandId::ID_MagicFillMetatile:
case CommandId::ID_ShiftMetatiles:
case CommandId::ID_ResizeMap:
case CommandId::ID_ScriptEditMap:
case CommandId::ID_ResizeLayout:
case CommandId::ID_ScriptEditLayout:
return true;
case CommandId::ID_PaintCollision:
case CommandId::ID_BucketFillCollision:
@ -403,18 +420,28 @@ void MapImageExporter::scalePreview() {
}
}
// THIS
QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) {
QPixmap pixmap;
Layout *layout;
// draw background layer / base image
map->render(true);
pixmap = map->pixmap;
if (!this->map) {
layout = this->layout;
layout->render(true);
pixmap = layout->pixmap;
} else {
layout = map->layout;
map->layout->render(true);
pixmap = map->layout->pixmap;
}
if (this->settings.showCollision) {
QPainter collisionPainter(&pixmap);
map->renderCollision(true);
layout->renderCollision(true);
collisionPainter.setOpacity(editor->collisionOpacity);
collisionPainter.drawPixmap(0, 0, map->collision_pixmap);
collisionPainter.drawPixmap(0, 0, layout->collision_pixmap);
collisionPainter.end();
}
@ -423,16 +450,16 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) {
int borderHeight = 0, borderWidth = 0;
if (!ignoreBorder && this->settings.showBorder) {
int borderDistance = this->mode ? STITCH_MODE_BORDER_DISTANCE : BORDER_DISTANCE;
map->renderBorder();
int borderHorzDist = editor->getBorderDrawDistance(map->getBorderWidth());
int borderVertDist = editor->getBorderDrawDistance(map->getBorderHeight());
layout->renderBorder();
int borderHorzDist = editor->getBorderDrawDistance(layout->getBorderWidth());
int borderVertDist = editor->getBorderDrawDistance(layout->getBorderHeight());
borderWidth = borderDistance * 16;
borderHeight = borderDistance * 16;
QPixmap newPixmap = QPixmap(map->pixmap.width() + borderWidth * 2, map->pixmap.height() + borderHeight * 2);
QPixmap newPixmap = QPixmap(layout->pixmap.width() + borderWidth * 2, layout->pixmap.height() + borderHeight * 2);
QPainter borderPainter(&newPixmap);
for (int y = borderDistance - borderVertDist; y < map->getHeight() + borderVertDist * 2; y += map->getBorderHeight()) {
for (int x = borderDistance - borderHorzDist; x < map->getWidth() + borderHorzDist * 2; x += map->getBorderWidth()) {
borderPainter.drawPixmap(x * 16, y * 16, map->layout->border_pixmap);
for (int y = borderDistance - borderVertDist; y < layout->getHeight() + borderVertDist * 2; y += layout->getBorderHeight()) {
for (int x = borderDistance - borderHorzDist; x < layout->getWidth() + borderHorzDist * 2; x += layout->getBorderWidth()) {
borderPainter.drawPixmap(x * 16, y * 16, layout->border_pixmap);
}
}
borderPainter.drawImage(borderWidth, borderHeight, pixmap.toImage());
@ -440,6 +467,10 @@ QPixmap MapImageExporter::getFormattedMapPixmap(Map *map, bool ignoreBorder) {
pixmap = newPixmap;
}
if (!this->map) {
return pixmap;
}
if (!ignoreBorder && (this->settings.showUpConnections || this->settings.showDownConnections || this->settings.showLeftConnections || this->settings.showRightConnections)) {
// if showing connections, draw on outside of image
QPainter connectionPainter(&pixmap);

692
src/ui/maplistmodels.cpp Normal file
View file

@ -0,0 +1,692 @@
#include "maplistmodels.h"
#include <QMouseEvent>
#include <QLineEdit>
#include "project.h"
#include "filterchildrenproxymodel.h"
void MapTree::removeSelected() {
while (!this->selectedIndexes().isEmpty()) {
QModelIndex i = this->selectedIndexes().takeLast();
this->model()->removeRow(i.row(), i.parent());
}
}
void MapTree::keyPressEvent(QKeyEvent *event) {
if (event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace) {
// Delete selected items in the tree
auto selectionModel = this->selectionModel();
if (!selectionModel->hasSelection())
return;
auto model = static_cast<FilterChildrenProxyModel*>(this->model());
auto sourceModel = static_cast<MapListModel*>(model->sourceModel());
QModelIndexList selectedIndexes = selectionModel->selectedRows();
QList<QPersistentModelIndex> persistentIndexes;
for (const auto &index : selectedIndexes) {
persistentIndexes.append(model->mapToSource(index));
}
for (const auto &index : persistentIndexes) {
sourceModel->removeItemAt(index);
}
} else {
QWidget::keyPressEvent(event);
}
}
void MapListModel::removeItemAt(const QModelIndex &index) {
QStandardItem *item = this->getItem(index)->child(index.row(), index.column());
if (!item)
return;
const QString type = item->data(MapListUserRoles::TypeRole).toString();
if (type == "map_name") {
// TODO: No support for deleting maps
} else {
// TODO: Because there's no support for deleting maps we can only delete empty folders
if (!item->hasChildren()) {
this->removeItem(item);
}
}
}
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->setFrame(false);
return editor;
}
void GroupNameDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {
QString groupName = index.data(Qt::UserRole).toString();
QLineEdit *le = static_cast<QLineEdit *>(editor);
le->setText(groupName);
}
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);
}
void GroupNameDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const {
editor->setGeometry(option.rect);
}
MapGroupModel::MapGroupModel(Project *project, QObject *parent) : MapListModel(parent) {
this->project = project;
this->root = this->invisibleRootItem();
initialize();
}
Qt::DropActions MapGroupModel::supportedDropActions() const {
return Qt::MoveAction;
}
QStringList MapGroupModel::mimeTypes() const {
QStringList types;
types << "application/porymap.mapgroupmodel.map"
<< "application/porymap.mapgroupmodel.group"
<< "application/porymap.mapgroupmodel.source.row"
<< "application/porymap.mapgroupmodel.source.column";
return types;
}
QMimeData *MapGroupModel::mimeData(const QModelIndexList &indexes) const {
QMimeData *mimeData = QStandardItemModel::mimeData(indexes);
QByteArray encodedData;
QDataStream stream(&encodedData, QIODevice::WriteOnly);
// 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();
stream << groupName;
mimeData->setData("application/porymap.mapgroupmodel.group", encodedData);
mimeData->setData("application/porymap.mapgroupmodel.source.row", QByteArray::number(index.row()));
return mimeData;
}
}
for (const QModelIndex &index : indexes) {
if (index.isValid()) {
QString mapName = data(index, Qt::UserRole).toString();
stream << mapName;
}
}
mimeData->setData("application/porymap.mapgroupmodel.map", encodedData);
return mimeData;
}
bool MapGroupModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int, const QModelIndex &parentIndex) {
if (action == Qt::IgnoreAction)
return true;
if (!parentIndex.isValid() && !data->hasFormat("application/porymap.mapgroupmodel.group"))
return false;
int firstRow = 0;
if (row != -1) {
firstRow = row;
}
else if (parentIndex.isValid()) {
firstRow = rowCount(parentIndex);
}
if (data->hasFormat("application/porymap.mapgroupmodel.group")) {
if (parentIndex.row() != -1 || parentIndex.column() != -1) {
return false;
}
QByteArray encodedData = data->data("application/porymap.mapgroupmodel.group");
QDataStream stream(&encodedData, QIODevice::ReadOnly);
QString groupName;
while (!stream.atEnd()) {
stream >> groupName;
}
this->insertRow(row, parentIndex);
// copy children to new node
int sourceRow = data->data("application/porymap.mapgroupmodel.source.row").toInt();
QModelIndex originIndex = this->index(sourceRow, 0);
QModelIndexList children;
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();
}
QModelIndex groupIndex = index(row, 0, parentIndex);
QStandardItem *groupItem = this->itemFromIndex(groupIndex);
createGroupItem(groupName, row, groupItem);
for (QString mapName : mapsToMove) {
QStandardItem *mapItem = createMapItem(mapName);
groupItem->appendRow(mapItem);
}
}
else if (data->hasFormat("application/porymap.mapgroupmodel.map")) {
QByteArray encodedData = data->data("application/porymap.mapgroupmodel.map");
QDataStream stream(&encodedData, QIODevice::ReadOnly);
QStringList droppedMaps;
int rowCount = 0;
while (!stream.atEnd()) {
QString mapName;
stream >> mapName;
droppedMaps << mapName;
rowCount++;
}
QStandardItem *groupItem = this->itemFromIndex(parentIndex);
if (groupItem->hasChildren()) {
this->insertRows(firstRow, rowCount, parentIndex);
for (QString mapName : droppedMaps) {
QModelIndex mapIndex = index(firstRow, 0, parentIndex);
QStandardItem *mapItem = this->itemFromIndex(mapIndex);
createMapItem(mapName, mapItem);
firstRow++;
}
}
// for whatever reason insertRows doesn't work as I expected with childless items
// so just append all the new maps instead
else {
for (QString mapName : droppedMaps) {
QStandardItem *mapItem = createMapItem(mapName);
groupItem->appendRow(mapItem);
firstRow++;
}
}
}
emit dragMoveCompleted();
updateProject();
return true;
}
void MapGroupModel::updateProject() {
if (!this->project) return;
QStringList groupNames;
QMap<QString, int> mapGroups;
QList<QStringList> groupedMapNames;
QStringList mapNames;
for (int g = 0; g < this->root->rowCount(); g++) {
QStandardItem *groupItem = this->item(g);
QString groupName = groupItem->data(Qt::UserRole).toString();
groupNames.append(groupName);
mapGroups[groupName] = g;
QStringList mapsInGroup;
for (int m = 0; m < groupItem->rowCount(); m++) {
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);
mapNames.append(mapName);
}
groupedMapNames.append(mapsInGroup);
}
this->project->groupNames = groupNames;
this->project->mapGroups = mapGroups;
this->project->groupedMapNames = groupedMapNames;
this->project->mapNames = mapNames;
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();
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();
if (type == "map_name") {
return QString("[%1.%2] ").arg(this->getItem(index)->row()).arg(row, 2, 10, QLatin1Char('0')) + item->data(Qt::UserRole).toString();
}
else if (type == "map_group") {
return item->data(Qt::UserRole).toString();
}
}
return QStandardItemModel::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())) {
return false;
}
}
if (QStandardItemModel::setData(index, value, role)) {
this->updateProject();
}
return true;
}
MapAreaModel::MapAreaModel(Project *project, QObject *parent) : MapListModel(parent) {
this->project = project;
this->root = this->invisibleRootItem();
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;
}
int mapIndex = area->rowCount();
QStandardItem *map = createMapItem(mapName, groupIndex, mapIndex);
area->appendRow(map);
return map;
}
void MapAreaModel::removeItem(QStandardItem *item) {
this->project->removeMapsec(item->data(Qt::UserRole).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);
}
LayoutTreeModel::LayoutTreeModel(Project *project, QObject *parent) : MapListModel(parent) {
this->project = project;
this->root = this->invisibleRootItem();
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];
}
else {
layout = createLayoutItem(layoutId);
this->root->appendRow(layout);
}
if (!layout) {
return nullptr;
}
QStandardItem *map = createMapItem(mapName);
layout->appendRow(map);
return map;
}
void LayoutTreeModel::removeItem(QStandardItem *) {
// TODO: Deleting layouts not supported
}
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);
}
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);
}
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();
}
QVariant LayoutTreeModel::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"));
QStandardItem *item = this->getItem(index)->child(row, col);
QString type = item->data(MapListUserRoles::TypeRole).toString();
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;
}
else if (type == "map_name") {
return QVariant();
}
return QVariant();
}
return QStandardItemModel::data(index, role);
}

141
src/ui/maplisttoolbar.cpp Normal file
View file

@ -0,0 +1,141 @@
#include "maplisttoolbar.h"
#include "ui_maplisttoolbar.h"
#include "editor.h"
#include <QToolTip>
/*
TODO: The button states for each tool bar (just the two toggleable buttons, hide empty folders and allow editing)
should be saved in the config. This will be cleaner/easier once the config is JSON, so holding off on that for now.
*/
MapListToolBar::MapListToolBar(QWidget *parent)
: QFrame(parent)
, ui(new Ui::MapListToolBar)
{
ui->setupUi(this);
ui->button_ToggleEmptyFolders->setChecked(!m_emptyFoldersVisible);
ui->button_ToggleEdit->setChecked(m_editsAllowed);
connect(ui->button_AddFolder, &QAbstractButton::clicked, this, &MapListToolBar::addFolderClicked); // TODO: Tool tip
connect(ui->button_ExpandAll, &QAbstractButton::clicked, this, &MapListToolBar::expandList);
connect(ui->button_CollapseAll, &QAbstractButton::clicked, this, &MapListToolBar::collapseList);
connect(ui->button_ToggleEdit, &QAbstractButton::clicked, this, &MapListToolBar::toggleEditsAllowed);
connect(ui->lineEdit_filterBox, &QLineEdit::textChanged, this, &MapListToolBar::applyFilter);
connect(ui->button_ToggleEmptyFolders, &QAbstractButton::clicked, [this] {
toggleEmptyFolders();
// Display message to let user know what just happened (if there are no empty folders visible it's not obvious).
const QString message = QString("%1 empty folders!").arg(m_emptyFoldersVisible ? "Showing" : "Hiding");
QToolTip::showText(ui->button_ToggleEmptyFolders->mapToGlobal(QPoint(0, 0)), message);
});
}
MapListToolBar::~MapListToolBar()
{
delete ui;
}
void MapListToolBar::setList(MapTree *list) {
m_list = list;
// Sync list with current settings
setEditsAllowed(m_editsAllowed);
setEmptyFoldersVisible(m_emptyFoldersVisible);
}
void MapListToolBar::setEditsAllowedButtonVisible(bool visible) {
ui->button_ToggleEdit->setVisible(visible);
}
void MapListToolBar::toggleEditsAllowed() {
if (m_list) {
m_list->clearSelection();
}
setEditsAllowed(!m_editsAllowed);
}
void MapListToolBar::setEditsAllowed(bool allowed) {
m_editsAllowed = allowed;
const QSignalBlocker b(ui->button_ToggleEdit);
ui->button_ToggleEdit->setChecked(allowed);
if (!m_list)
return;
if (allowed) {
m_list->setSelectionMode(QAbstractItemView::ExtendedSelection);
m_list->setDragEnabled(true);
m_list->setAcceptDrops(true);
m_list->setDropIndicatorShown(true);
m_list->setDragDropMode(QAbstractItemView::InternalMove);
m_list->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed);
} else {
m_list->setSelectionMode(QAbstractItemView::NoSelection);
m_list->setDragEnabled(false);
m_list->setAcceptDrops(false);
m_list->setDropIndicatorShown(false);
m_list->setDragDropMode(QAbstractItemView::NoDragDrop);
m_list->setEditTriggers(QAbstractItemView::NoEditTriggers);
}
}
void MapListToolBar::toggleEmptyFolders() {
setEmptyFoldersVisible(!m_emptyFoldersVisible);
}
void MapListToolBar::setEmptyFoldersVisible(bool visible) {
m_emptyFoldersVisible = visible;
if (m_list) {
auto model = static_cast<FilterChildrenProxyModel*>(m_list->model());
if (model) {
model->setHideEmpty(!visible);
model->setFilterRegularExpression(ui->lineEdit_filterBox->text());
}
}
// Update tool tip to reflect what will happen if the button is pressed.
const QString toolTip = QString("%1 empty folders in the list.").arg(visible ? "Hide" : "Show");
ui->button_ToggleEmptyFolders->setToolTip(toolTip);
const QSignalBlocker b(ui->button_ToggleEmptyFolders);
ui->button_ToggleEmptyFolders->setChecked(!visible);
}
void MapListToolBar::expandList() {
if (m_list)
m_list->expandToDepth(0);
}
void MapListToolBar::collapseList() {
if (m_list) {
m_list->collapseAll();
}
}
void MapListToolBar::applyFilter(const QString &filterText) {
if (m_filterLocked)
return;
const QSignalBlocker b(ui->lineEdit_filterBox);
ui->lineEdit_filterBox->setText(filterText);
if (m_list) {
auto model = static_cast<FilterChildrenProxyModel*>(m_list->model());
if (model) model->setFilterRegularExpression(QRegularExpression(filterText, QRegularExpression::CaseInsensitiveOption));
if (filterText.isEmpty()) {
m_list->collapseAll();
emit filterCleared(m_list);
} else {
m_list->expandToDepth(0);
}
}
}
void MapListToolBar::clearFilter() {
applyFilter("");
}

View file

@ -1,23 +0,0 @@
#include "mapsceneeventfilter.h"
#include <QEvent>
#include <QGraphicsSceneWheelEvent>
MapSceneEventFilter::MapSceneEventFilter(QObject *parent) : QObject(parent)
{
}
bool MapSceneEventFilter::eventFilter(QObject*, QEvent *event)
{
if (event->type() == QEvent::GraphicsSceneWheel)
{
QGraphicsSceneWheelEvent *wheelEvent = static_cast<QGraphicsSceneWheelEvent *>(event);
if (wheelEvent->modifiers() & Qt::ControlModifier)
{
emit wheelZoom(wheelEvent->delta() > 0 ? 1 : -1);
event->accept();
return true;
}
}
return false;
}

View file

@ -28,7 +28,7 @@ void MetatileSelector::draw() {
if (i >= primaryLength) {
tile += Project::getNumMetatilesPrimary() - primaryLength;
}
QImage metatile_image = getMetatileImage(tile, this->primaryTileset, this->secondaryTileset, map->metatileLayerOrder, map->metatileLayerOpacity);
QImage metatile_image = getMetatileImage(tile, this->primaryTileset, this->secondaryTileset, layout->metatileLayerOrder, layout->metatileLayerOpacity);
int map_y = i / this->numMetatilesWide;
int map_x = i % this->numMetatilesWide;
QPoint metatile_origin = QPoint(map_x * 16, map_y * 16);
@ -226,6 +226,6 @@ QPoint MetatileSelector::getMetatileIdCoordsOnWidget(uint16_t metatileId) {
return pos;
}
void MetatileSelector::setMap(Map *map) {
this->map = map;
void MetatileSelector::setLayout(Layout *layout) {
this->layout = layout;
}

View file

@ -3,6 +3,7 @@
#include "editor.h"
#include "encountertablemodel.h"
#include "encountertabledelegates.h"
#include "eventfilters.h"
@ -11,20 +12,13 @@ static WildMonInfo encounterClipboard;
MonTabWidget::MonTabWidget(Editor *editor, QWidget *parent) : QTabWidget(parent) {
this->editor = editor;
populate();
this->tabBar()->installEventFilter(this);
this->tabBar()->installEventFilter(new WheelFilter(this));
}
MonTabWidget::~MonTabWidget() {
}
bool MonTabWidget::eventFilter(QObject *, QEvent *event) {
if (event->type() == QEvent::Wheel) {
return true;
}
return false;
}
void MonTabWidget::populate() {
EncounterFields fields = editor->project->wildMonFields;
activeTabs.resize(fields.size());

View file

@ -8,6 +8,8 @@
#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) :
@ -27,14 +29,18 @@ NewMapPopup::~NewMapPopup()
delete ui;
}
void NewMapPopup::init() {
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->mapSectionNameToValue.keys());
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);
@ -67,6 +73,10 @@ void NewMapPopup::init() {
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);
@ -94,29 +104,32 @@ void NewMapPopup::init() {
}
// Creating new map by right-clicking in the map list
void NewMapPopup::init(MapSortOrder type, QVariant data) {
switch (type)
void NewMapPopup::init(int tabIndex, QString fieldName) {
initUi();
switch (tabIndex)
{
case MapSortOrder::Group:
settings.group = project->groupNames.at(data.toInt());
case MapListTab::Groups:
settings.group = fieldName;
break;
case MapSortOrder::Area:
settings.location = data.toString();
case MapListTab::Areas:
settings.location = fieldName;
break;
case MapSortOrder::Layout:
useLayout(data.toString());
case MapListTab::Layouts:
this->ui->checkBox_UseExistingLayout->setCheckState(Qt::Checked);
useLayout(fieldName);
break;
}
init();
}
// Creating new map from AdvanceMap import
void NewMapPopup::init(MapLayout *mapLayout) {
void NewMapPopup::init(Layout *mapLayout) {
initUi();
this->importedMap = true;
useLayoutSettings(mapLayout);
this->map = new Map();
this->map->layout = new MapLayout();
this->map->layout = new Layout();
this->map->layout->blockdata = mapLayout->blockdata;
if (!mapLayout->border.isEmpty()) {
@ -175,7 +188,7 @@ void NewMapPopup::setDefaultSettings(Project *project) {
settings.primaryTilesetLabel = project->getDefaultPrimaryTilesetLabel();
settings.secondaryTilesetLabel = project->getDefaultSecondaryTilesetLabel();
settings.type = project->mapTypes.value(0, "0");
settings.location = project->mapSectionNameToValue.keys().value(0, "0");
settings.location = project->mapSectionIdNames.value(0, "0");
settings.song = project->defaultSong;
settings.canFlyTo = false;
settings.showLocationName = true;
@ -204,28 +217,60 @@ void NewMapPopup::saveSettings() {
settings.floorNumber = ui->spinBox_NewMap_Floor_Number->value();
}
void NewMapPopup::useLayoutSettings(MapLayout *layout) {
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;
useLayoutSettings(project->mapLayouts.value(this->layoutId));
// Dimensions and tilesets can't be changed for new maps using an existing layout
ui->spinBox_NewMap_Width->setDisabled(true);
ui->spinBox_NewMap_Height->setDisabled(true);
ui->spinBox_NewMap_BorderWidth->setDisabled(true);
ui->spinBox_NewMap_BorderHeight->setDisabled(true);
ui->comboBox_NewMap_Primary_Tileset->setDisabled(true);
ui->comboBox_NewMap_Secondary_Tileset->setDisabled(true);
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) {
@ -242,7 +287,7 @@ void NewMapPopup::on_pushButton_NewMap_Accept_clicked() {
return;
}
Map *newMap = new Map;
MapLayout *layout;
Layout *layout;
// If map name is not unique, use default value. Also use only valid characters.
// After stripping invalid characters, strip any leading digits.
@ -267,8 +312,8 @@ void NewMapPopup::on_pushButton_NewMap_Accept_clicked() {
layout = this->project->mapLayouts.value(this->layoutId);
newMap->needsLayoutDir = false;
} else {
layout = new MapLayout;
layout->id = MapLayout::layoutConstantFromName(newMapName);
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();

View file

@ -158,32 +158,32 @@ QList<PrefabItem> Prefab::getPrefabsForTilesets(QString primaryTileset, QString
return filteredPrefabs;
}
void Prefab::initPrefabUI(MetatileSelector *selector, QWidget *prefabWidget, QLabel *emptyPrefabLabel, Map *map) {
void Prefab::initPrefabUI(MetatileSelector *selector, QWidget *prefabWidget, QLabel *emptyPrefabLabel, Layout *layout) {
this->selector = selector;
this->prefabWidget = prefabWidget;
this->emptyPrefabLabel = emptyPrefabLabel;
this->loadPrefabs();
this->updatePrefabUi(map);
this->updatePrefabUi(layout);
}
// This function recreates the UI state for the prefab tab.
// We completely delete all the prefab widgets, and recreate new widgets
// from the relevant list of prefab items.
// This is not very efficient, but it gets the job done.
void Prefab::updatePrefabUi(Map *map) {
void Prefab::updatePrefabUi(Layout *layout) {
if (!this->selector)
return;
// Cleanup the PrefabFrame to have a clean slate.
auto layout = this->prefabWidget->layout();
while (layout && layout->count() > 1) {
auto child = layout->takeAt(1);
auto uiLayout = this->prefabWidget->layout();
while (uiLayout && uiLayout->count() > 1) {
auto child = uiLayout->takeAt(1);
if (child->widget()) {
delete child->widget();
}
delete child;
}
QList<PrefabItem> prefabs = this->getPrefabsForTilesets(map->layout->tileset_primary_label, map->layout->tileset_secondary_label);
QList<PrefabItem> prefabs = this->getPrefabsForTilesets(layout->tileset_primary_label, layout->tileset_secondary_label);
if (prefabs.isEmpty()) {
emptyPrefabLabel->setVisible(true);
return;
@ -202,7 +202,7 @@ void Prefab::updatePrefabUi(Map *map) {
frame->ui->label_Name->setText(item.name);
auto scene = new QGraphicsScene;
scene->addPixmap(drawMetatileSelection(item.selection, map));
scene->addPixmap(drawMetatileSelection(item.selection, layout));
scene->setSceneRect(scene->itemsBoundingRect());
frame->ui->graphicsView_Prefab->setScene(scene);
frame->ui->graphicsView_Prefab->setFixedSize(scene->itemsBoundingRect().width() + 2,
@ -216,7 +216,7 @@ void Prefab::updatePrefabUi(Map *map) {
});
// Clicking the delete button removes it from the list of known prefabs and updates the UI.
QObject::connect(frame->ui->pushButton_DeleteItem, &QPushButton::clicked, [this, item, map](){
QObject::connect(frame->ui->pushButton_DeleteItem, &QPushButton::clicked, [this, item, layout](){
for (int i = 0; i < this->items.size(); i++) {
if (this->items[i].id == item.id) {
QMessageBox msgBox;
@ -234,7 +234,7 @@ void Prefab::updatePrefabUi(Map *map) {
if (msgBox.clickedButton() == deleteButton) {
this->items.removeAt(i);
this->savePrefabs();
this->updatePrefabUi(map);
this->updatePrefabUi(layout);
}
break;
}
@ -246,7 +246,7 @@ void Prefab::updatePrefabUi(Map *map) {
prefabWidget->layout()->addItem(verticalSpacer);
}
void Prefab::addPrefab(MetatileSelection selection, Map *map, QString name) {
void Prefab::addPrefab(MetatileSelection selection, Layout *layout, QString name) {
// First, determine which tilesets are actually used in this new prefab,
// based on the metatile ids.
bool usesPrimaryTileset = false;
@ -264,12 +264,12 @@ void Prefab::addPrefab(MetatileSelection selection, Map *map, QString name) {
this->items.append(PrefabItem{
QUuid::createUuid(),
name,
usesPrimaryTileset ? map->layout->tileset_primary_label : "",
usesSecondaryTileset ? map->layout->tileset_secondary_label: "",
usesPrimaryTileset ? layout->tileset_primary_label : "",
usesSecondaryTileset ? layout->tileset_secondary_label: "",
selection
});
this->savePrefabs();
this->updatePrefabUi(map);
this->updatePrefabUi(layout);
}
bool Prefab::tryImportDefaultPrefabs(QWidget * parent, BaseGameVersion version, QString filepath) {

View file

@ -6,16 +6,16 @@
#include <QObject>
PrefabCreationDialog::PrefabCreationDialog(QWidget *parent, MetatileSelector *metatileSelector, Map *map) :
PrefabCreationDialog::PrefabCreationDialog(QWidget *parent, MetatileSelector *metatileSelector, Layout *layout) :
QDialog(parent),
ui(new Ui::PrefabCreationDialog)
{
ui->setupUi(this);
this->map = map;
this->layout = layout;
this->selection = metatileSelector->getMetatileSelection();
QGraphicsScene *scene = new QGraphicsScene;
QGraphicsPixmapItem *pixmapItem = scene->addPixmap(drawMetatileSelection(this->selection, map));
QGraphicsPixmapItem *pixmapItem = scene->addPixmap(drawMetatileSelection(this->selection, layout));
scene->setSceneRect(scene->itemsBoundingRect());
this->ui->graphicsView_Prefab->setScene(scene);
this->ui->graphicsView_Prefab->setFixedSize(scene->itemsBoundingRect().width() + 2,
@ -35,7 +35,7 @@ PrefabCreationDialog::PrefabCreationDialog(QWidget *parent, MetatileSelector *me
if (this->selection.hasCollision) {
this->selection.collisionItems[index].enabled = toggledState;
}
pixmapItem->setPixmap(drawMetatileSelection(this->selection, map));
pixmapItem->setPixmap(drawMetatileSelection(this->selection, layout));
});
}
@ -45,5 +45,5 @@ PrefabCreationDialog::~PrefabCreationDialog()
}
void PrefabCreationDialog::savePrefab() {
prefab.addPrefab(this->selection, this->map, this->ui->lineEdit_PrefabName->text());
prefab.addPrefab(this->selection, this->layout, this->ui->lineEdit_PrefabName->text());
}

View file

@ -29,7 +29,6 @@ RegionMapEditor::RegionMapEditor(QWidget *parent, Project *project) :
this->ui->setupUi(this);
this->project = project;
this->configFilepath = QString("%1/%2").arg(this->project->root).arg(projectConfig.getFilePath(ProjectFilePath::json_region_porymap_cfg));
this->mapSectionFilepath = QString("%1/%2").arg(this->project->root).arg(projectConfig.getFilePath(ProjectFilePath::json_region_map_entries));
this->initShortcuts();
this->restoreWindowState();
}
@ -110,67 +109,13 @@ void RegionMapEditor::applyUserShortcuts() {
}
bool RegionMapEditor::loadRegionMapEntries() {
this->region_map_entries.clear();
ParseUtil parser;
QJsonDocument sectionsDoc;
if (!parser.tryParseJsonFile(&sectionsDoc, this->mapSectionFilepath)) {
logError(QString("Failed to read map data from %1").arg(this->mapSectionFilepath));
return false;
}
// for some unknown reason, the OrderedJson class would not parse this properly
// perhaps updating nlohmann/json here would fix it, but that also requires using C++17
QJsonObject object = sectionsDoc.object();
for (auto entryRef : object["map_sections"].toArray()) {
QJsonObject entryObject = entryRef.toObject();
QString entryMapSection = ParseUtil::jsonToQString(entryObject["map_section"]);
MapSectionEntry entry;
entry.name = ParseUtil::jsonToQString(entryObject["name"]);
entry.x = ParseUtil::jsonToInt(entryObject["x"]);
entry.y = ParseUtil::jsonToInt(entryObject["y"]);
entry.width = ParseUtil::jsonToInt(entryObject["width"]);
entry.height = ParseUtil::jsonToInt(entryObject["height"]);
entry.valid = true;
this->region_map_entries[entryMapSection] = entry;
}
this->region_map_entries = this->project->regionMapEntries;
return true;
}
bool RegionMapEditor::saveRegionMapEntries() {
QFile sectionsFile(this->mapSectionFilepath);
if (!sectionsFile.open(QIODevice::WriteOnly)) {
logError(QString("Could not open %1 for writing").arg(this->mapSectionFilepath));
return false;
}
OrderedJson::object object;
OrderedJson::array mapSectionArray;
for (auto pair : this->region_map_entries) {
QString section = pair.first;
MapSectionEntry entry = pair.second;
OrderedJson::object entryObject;
entryObject["map_section"] = section;
entryObject["name"] = entry.name;
entryObject["x"] = entry.x;
entryObject["y"] = entry.y;
entryObject["width"] = entry.width;
entryObject["height"] = entry.height;
mapSectionArray.append(entryObject);
}
object["map_sections"] = mapSectionArray;
OrderedJson sectionsJson(object);
OrderedJsonDoc jsonDoc(&sectionsJson);
jsonDoc.dump(&sectionsFile);
sectionsFile.close();
this->project->regionMapEntries = this->region_map_entries;
this->project->saveRegionMapSections();
return true;
}
@ -708,7 +653,7 @@ void RegionMapEditor::displayRegionMapLayoutOptions() {
this->ui->comboBox_RM_ConnectedMap->blockSignals(true);
this->ui->comboBox_RM_ConnectedMap->clear();
this->ui->comboBox_RM_ConnectedMap->addItems(this->project->mapSectionValueToName.values());
this->ui->comboBox_RM_ConnectedMap->addItems(this->project->mapSectionIdNames);
this->ui->comboBox_RM_ConnectedMap->blockSignals(false);
this->ui->frame_RM_Options->setEnabled(true);
@ -775,7 +720,7 @@ void RegionMapEditor::displayRegionMapEntryOptions() {
if (!this->region_map->layoutEnabled()) return;
this->ui->comboBox_RM_Entry_MapSection->clear();
this->ui->comboBox_RM_Entry_MapSection->addItems(this->project->mapSectionValueToName.values());
this->ui->comboBox_RM_Entry_MapSection->addItems(this->project->mapSectionIdNames);
this->ui->spinBox_RM_Entry_x->setMaximum(128);
this->ui->spinBox_RM_Entry_y->setMaximum(128);
this->ui->spinBox_RM_Entry_width->setMinimum(1);
@ -787,17 +732,13 @@ void RegionMapEditor::displayRegionMapEntryOptions() {
void RegionMapEditor::updateRegionMapEntryOptions(QString section) {
if (!this->region_map->layoutEnabled()) return;
bool isSpecialSection = (section == this->region_map->default_map_section
|| section == this->region_map->count_map_section);
bool enabled = (!isSpecialSection && this->region_map_entries.contains(section));
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);
this->ui->spinBox_RM_Entry_height->setEnabled(enabled);
this->ui->pushButton_entryActivate->setEnabled(!isSpecialSection);
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);
@ -902,14 +843,8 @@ void RegionMapEditor::onRegionMapEntryDragged(int new_x, int new_y) {
}
void RegionMapEditor::onRegionMapLayoutSelectedTileChanged(int index) {
QString message = QString();
this->currIndex = index;
this->region_map_layout_item->highlightedTile = index;
if (this->region_map->squareHasMap(index)) {
message = QString("\t %1").arg(this->project->mapSecToMapHoverName.value(
this->region_map->squareMapSection(index))).remove("{NAME_END}");
}
this->ui->statusbar->showMessage(message);
updateRegionMapLayoutOptions(index);
this->region_map_layout_item->draw();
@ -922,8 +857,7 @@ void RegionMapEditor::onRegionMapLayoutHoveredTileChanged(int index) {
if (x >= 0 && y >= 0) {
message = QString("(%1, %2)").arg(x).arg(y);
if (this->region_map->squareHasMap(index)) {
message += QString("\t %1").arg(this->project->mapSecToMapHoverName.value(
this->region_map->squareMapSection(index))).remove("{NAME_END}");
message += QString("\t %1").arg(this->region_map->squareMapSection(index));
}
}
this->ui->statusbar->showMessage(message);
@ -1094,7 +1028,7 @@ void RegionMapEditor::on_spinBox_RM_LayoutWidth_valueChanged(int value) {
int newHeight = this->region_map->layoutHeight();
QMap<QString, QList<LayoutSquare>> newLayouts = this->region_map->getAllLayouts();
ResizeLayout *commit = new ResizeLayout(this->region_map, oldWidth, oldHeight, newWidth, newHeight, oldLayouts, newLayouts);
ResizeRMLayout *commit = new ResizeRMLayout(this->region_map, oldWidth, oldHeight, newWidth, newHeight, oldLayouts, newLayouts);
this->region_map->editHistory.push(commit);
}
}
@ -1111,7 +1045,7 @@ void RegionMapEditor::on_spinBox_RM_LayoutHeight_valueChanged(int value) {
int newHeight = this->region_map->layoutHeight();
QMap<QString, QList<LayoutSquare>> newLayouts = this->region_map->getAllLayouts();
ResizeLayout *commit = new ResizeLayout(this->region_map, oldWidth, oldHeight, newWidth, newHeight, oldLayouts, newLayouts);
ResizeRMLayout *commit = new ResizeRMLayout(this->region_map, oldWidth, oldHeight, newWidth, newHeight, oldLayouts, newLayouts);
this->region_map->editHistory.push(commit);
}
}
@ -1203,10 +1137,10 @@ void RegionMapEditor::on_action_Swap_triggered() {
QFormLayout form(&popup);
QComboBox *oldSecBox = new QComboBox();
oldSecBox->addItems(this->project->mapSectionValueToName.values());
oldSecBox->addItems(this->project->mapSectionIdNames);
form.addRow(new QLabel("Map Section 1:"), oldSecBox);
QComboBox *newSecBox = new QComboBox();
newSecBox->addItems(this->project->mapSectionValueToName.values());
newSecBox->addItems(this->project->mapSectionIdNames);
form.addRow(new QLabel("Map Section 2:"), newSecBox);
QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &popup);
@ -1242,10 +1176,10 @@ void RegionMapEditor::on_action_Replace_triggered() {
QFormLayout form(&popup);
QComboBox *oldSecBox = new QComboBox();
oldSecBox->addItems(this->project->mapSectionValueToName.values());
oldSecBox->addItems(this->project->mapSectionIdNames);
form.addRow(new QLabel("Old Map Section:"), oldSecBox);
QComboBox *newSecBox = new QComboBox();
newSecBox->addItems(this->project->mapSectionValueToName.values());
newSecBox->addItems(this->project->mapSectionIdNames);
form.addRow(new QLabel("New Map Section:"), newSecBox);
QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &popup);

View file

@ -13,15 +13,15 @@
#include <QCloseEvent>
#include <QImageReader>
TilesetEditor::TilesetEditor(Project *project, Map *map, QWidget *parent) :
TilesetEditor::TilesetEditor(Project *project, Layout *layout, QWidget *parent) :
QMainWindow(parent),
ui(new Ui::TilesetEditor),
project(project),
map(map),
layout(layout),
hasUnsavedChanges(false)
{
this->setAttribute(Qt::WA_DeleteOnClose);
this->setTilesets(this->map->layout->tileset_primary_label, this->map->layout->tileset_secondary_label);
this->setTilesets(this->layout->tileset_primary_label, this->layout->tileset_secondary_label);
this->initUi();
}
@ -43,14 +43,14 @@ TilesetEditor::~TilesetEditor()
this->metatileHistory.clear();
}
void TilesetEditor::update(Map *map, QString primaryTilesetLabel, QString secondaryTilesetLabel) {
this->updateMap(map);
void TilesetEditor::update(Layout *layout, QString primaryTilesetLabel, QString secondaryTilesetLabel) {
this->updateLayout(layout);
this->updateTilesets(primaryTilesetLabel, secondaryTilesetLabel);
}
void TilesetEditor::updateMap(Map *map) {
this->map = map;
this->metatileSelector->map = map;
void TilesetEditor::updateLayout(Layout *layout) {
this->layout = layout;
this->metatileSelector->layout = layout;
}
void TilesetEditor::updateTilesets(QString primaryTilesetLabel, QString secondaryTilesetLabel) {
@ -180,7 +180,7 @@ void TilesetEditor::setMetatileLabelValidator() {
void TilesetEditor::initMetatileSelector()
{
this->metatileSelector = new TilesetEditorMetatileSelector(this->primaryTileset, this->secondaryTileset, this->map);
this->metatileSelector = new TilesetEditorMetatileSelector(this->primaryTileset, this->secondaryTileset, this->layout);
connect(this->metatileSelector, &TilesetEditorMetatileSelector::hoveredMetatileChanged,
this, &TilesetEditor::onHoveredMetatileChanged);
connect(this->metatileSelector, &TilesetEditorMetatileSelector::hoveredMetatileCleared,
@ -387,7 +387,7 @@ void TilesetEditor::onSelectedMetatileChanged(uint16_t metatileId) {
// The Tileset Editor (if open) needs to reflect these changes when the metatile is next displayed.
if (this->metatileReloadQueue.contains(metatileId)) {
this->metatileReloadQueue.remove(metatileId);
Metatile *updatedMetatile = Tileset::getMetatile(metatileId, this->map->layout->tileset_primary, this->map->layout->tileset_secondary);
Metatile *updatedMetatile = Tileset::getMetatile(metatileId, this->layout->tileset_primary, this->layout->tileset_secondary);
if (updatedMetatile) *this->metatile = *updatedMetatile;
}

View file

@ -3,11 +3,11 @@
#include "project.h"
#include <QPainter>
TilesetEditorMetatileSelector::TilesetEditorMetatileSelector(Tileset *primaryTileset, Tileset *secondaryTileset, Map *map)
TilesetEditorMetatileSelector::TilesetEditorMetatileSelector(Tileset *primaryTileset, Tileset *secondaryTileset, Layout *layout)
: SelectablePixmapItem(32, 32, 1, 1) {
this->setTilesets(primaryTileset, secondaryTileset, false);
this->numMetatilesWide = 8;
this->map = map;
this->layout = layout;
setAcceptHoverEvents(true);
this->usedMetatiles.resize(Project::getNumMetatilesTotal());
}
@ -54,8 +54,8 @@ QImage TilesetEditorMetatileSelector::buildImage(int metatileIdStart, int numMet
metatileId,
this->primaryTileset,
this->secondaryTileset,
map->metatileLayerOrder,
map->metatileLayerOpacity,
this->layout->metatileLayerOrder,
this->layout->metatileLayerOpacity,
true)
.scaled(32, 32);
int map_y = i / this->numMetatilesWide;