Update Collision tab UI

This commit is contained in:
GriffinR 2023-12-07 13:45:08 -05:00
parent d5210cf230
commit 4f0e8716f2
15 changed files with 263 additions and 99 deletions

View file

@ -1144,7 +1144,14 @@
<property name="bottomMargin"> <property name="bottomMargin">
<number>3</number> <number>3</number>
</property> </property>
<item row="0" column="0"> <item row="3" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Opacity</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="3">
<widget class="QScrollArea" name="scrollArea_1"> <widget class="QScrollArea" name="scrollArea_1">
<property name="widgetResizable"> <property name="widgetResizable">
<bool>true</bool> <bool>true</bool>
@ -1154,8 +1161,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>428</width> <width>427</width>
<height>696</height> <height>512</height>
</rect> </rect>
</property> </property>
<layout class="QGridLayout" name="gridLayout_7"> <layout class="QGridLayout" name="gridLayout_7">
@ -1174,29 +1181,6 @@
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
</property> </property>
<item row="0" column="1">
<widget class="QLabel" name="label">
<property name="text">
<string>Opacity</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSlider" name="horizontalSlider_CollisionTransparency">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="0"> <item row="2" column="0">
<spacer name="horizontalSpacer_18"> <spacer name="horizontalSpacer_18">
<property name="orientation"> <property name="orientation">
@ -1224,6 +1208,12 @@
<height>512</height> <height>512</height>
</size> </size>
</property> </property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
</widget> </widget>
</item> </item>
<item row="2" column="2"> <item row="2" column="2">
@ -1256,6 +1246,83 @@
</widget> </widget>
</widget> </widget>
</item> </item>
<item row="6" column="0" colspan="3">
<widget class="QSlider" name="horizontalSlider_CollisionZoom">
<property name="minimum">
<number>10</number>
</property>
<property name="maximum">
<number>90</number>
</property>
<property name="value">
<number>30</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="4" column="0" colspan="3">
<widget class="QSlider" name="horizontalSlider_CollisionTransparency">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>50</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="0" colspan="3">
<widget class="QFrame" name="frame_5">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout" name="gridLayout_8">
<item row="0" column="1">
<widget class="QSpinBox" name="spinBox_SelectedElevation"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string>Collision</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="spinBox_SelectedCollision"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
<string>Elevation</string>
</property>
</widget>
</item>
<item row="0" column="2">
<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>
</layout>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tab_prefabs"> <widget class="QWidget" name="tab_prefabs">
@ -1314,8 +1381,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>398</width> <width>382</width>
<height>631</height> <height>611</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_14"> <layout class="QVBoxLayout" name="verticalLayout_14">
@ -1615,8 +1682,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>434</width> <width>100</width>
<height>581</height> <height>16</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -1709,8 +1776,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>434</width> <width>100</width>
<height>581</height> <height>16</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -1803,8 +1870,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>434</width> <width>100</width>
<height>581</height> <height>16</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -1903,8 +1970,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>434</width> <width>100</width>
<height>581</height> <height>16</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -1997,8 +2064,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>434</width> <width>100</width>
<height>581</height> <height>16</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -2051,8 +2118,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>434</width> <width>100</width>
<height>625</height> <height>30</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -2388,7 +2455,7 @@
<string>Custom fields will be added to the map.json file for the current map.</string> <string>Custom fields will be added to the map.json file for the current map.</string>
</property> </property>
<attribute name="horizontalHeaderVisible"> <attribute name="horizontalHeaderVisible">
<bool>true</bool> <bool>false</bool>
</attribute> </attribute>
<attribute name="horizontalHeaderCascadingSectionResizes"> <attribute name="horizontalHeaderCascadingSectionResizes">
<bool>false</bool> <bool>false</bool>

View file

@ -56,6 +56,7 @@ public:
this->mapSortOrder = MapSortOrder::Group; this->mapSortOrder = MapSortOrder::Group;
this->prettyCursors = true; this->prettyCursors = true;
this->collisionOpacity = 50; this->collisionOpacity = 50;
this->collisionZoom = 30;
this->metatilesZoom = 30; this->metatilesZoom = 30;
this->showPlayerView = false; this->showPlayerView = false;
this->showCursorTile = true; this->showCursorTile = true;
@ -78,6 +79,7 @@ public:
void setProjectSettingsEditorGeometry(QByteArray, QByteArray); void setProjectSettingsEditorGeometry(QByteArray, QByteArray);
void setCustomScriptsEditorGeometry(QByteArray, QByteArray); void setCustomScriptsEditorGeometry(QByteArray, QByteArray);
void setCollisionOpacity(int opacity); void setCollisionOpacity(int opacity);
void setCollisionZoom(int zoom);
void setMetatilesZoom(int zoom); void setMetatilesZoom(int zoom);
void setShowPlayerView(bool enabled); void setShowPlayerView(bool enabled);
void setShowCursorTile(bool enabled); void setShowCursorTile(bool enabled);
@ -100,6 +102,7 @@ public:
QMap<QString, QByteArray> getProjectSettingsEditorGeometry(); QMap<QString, QByteArray> getProjectSettingsEditorGeometry();
QMap<QString, QByteArray> getCustomScriptsEditorGeometry(); QMap<QString, QByteArray> getCustomScriptsEditorGeometry();
int getCollisionOpacity(); int getCollisionOpacity();
int getCollisionZoom();
int getMetatilesZoom(); int getMetatilesZoom();
bool getShowPlayerView(); bool getShowPlayerView();
bool getShowCursorTile(); bool getShowCursorTile();
@ -140,6 +143,7 @@ private:
QByteArray customScriptsEditorGeometry; QByteArray customScriptsEditorGeometry;
QByteArray customScriptsEditorState; QByteArray customScriptsEditorState;
int collisionOpacity; int collisionOpacity;
int collisionZoom;
int metatilesZoom; int metatilesZoom;
bool showPlayerView; bool showPlayerView;
bool showCursorTile; bool showCursorTile;

View file

@ -152,7 +152,7 @@ public:
void scaleMapView(int); void scaleMapView(int);
static void openInTextEditor(const QString &path, int lineNum = 0); static void openInTextEditor(const QString &path, int lineNum = 0);
bool eventLimitReached(Event::Type type); bool eventLimitReached(Event::Type type);
static void setCollisionGraphics(); void setCollisionGraphics();
public slots: public slots:
void openMapScripts() const; void openMapScripts() const;
@ -163,6 +163,10 @@ public slots:
void selectedEventIndexChanged(int index, Event::Group eventGroup); void selectedEventIndexChanged(int index, Event::Group eventGroup);
private: private:
const QImage defaultCollisionImgSheet = QImage(":/images/collisions.png");
const QImage collisionPlaceholder = QImage(":/images/collisions_unknown.png");
QPixmap collisionSheetPixmap;
void setConnectionItemsVisible(bool); void setConnectionItemsVisible(bool);
void setBorderItemsVisible(bool, qreal = 1); void setBorderItemsVisible(bool, qreal = 1);
void setConnectionEditControlValues(MapConnection*); void setConnectionEditControlValues(MapConnection*);
@ -181,6 +185,7 @@ private:
void updateEncounterFields(EncounterFields newFields); void updateEncounterFields(EncounterFields newFields);
QString getMovementPermissionText(uint16_t collision, uint16_t elevation); QString getMovementPermissionText(uint16_t collision, uint16_t elevation);
QString getMetatileDisplayMessage(uint16_t metatileId); QString getMetatileDisplayMessage(uint16_t metatileId);
void setCollisionTabSpinBoxes(uint16_t collision, uint16_t elevation);
static bool startDetachedProcess(const QString &command, static bool startDetachedProcess(const QString &command,
const QString &workingDirectory = QString(), const QString &workingDirectory = QString(),
qint64 *pid = nullptr); qint64 *pid = nullptr);

View file

@ -276,11 +276,13 @@ private slots:
void on_pushButton_DeleteCustomHeaderField_clicked(); void on_pushButton_DeleteCustomHeaderField_clicked();
void on_tableWidget_CustomHeaderFields_cellChanged(int row, int column); void on_tableWidget_CustomHeaderFields_cellChanged(int row, int column);
void on_horizontalSlider_MetatileZoom_valueChanged(int value); void on_horizontalSlider_MetatileZoom_valueChanged(int value);
void on_horizontalSlider_CollisionZoom_valueChanged(int value);
void on_pushButton_NewWildMonGroup_clicked(); void on_pushButton_NewWildMonGroup_clicked();
void on_pushButton_DeleteWildMonGroup_clicked(); void on_pushButton_DeleteWildMonGroup_clicked();
void on_pushButton_ConfigureEncountersJSON_clicked(); void on_pushButton_ConfigureEncountersJSON_clicked();
void on_pushButton_CreatePrefab_clicked(); void on_pushButton_CreatePrefab_clicked();
void on_spinBox_SelectedElevation_valueChanged(int elevation);
void on_spinBox_SelectedCollision_valueChanged(int collision);
void on_actionRegion_Map_Editor_triggered(); void on_actionRegion_Map_Editor_triggered();
void on_actionPreferences_triggered(); void on_actionPreferences_triggered();
void togglePreferenceSpecificUi(); void togglePreferenceSpecificUi();
@ -370,7 +372,7 @@ private:
void initMapSortOrder(); void initMapSortOrder();
void initShortcuts(); void initShortcuts();
void initExtraShortcuts(); void initExtraShortcuts();
void setProjectSpecificUIVisibility(); void setProjectSpecificUI();
void setWildEncountersUIEnabled(bool enabled); void setWildEncountersUIEnabled(bool enabled);
void loadUserSettings(); void loadUserSettings();
void applyMapListFilter(QString filterText); void applyMapListFilter(QString filterText);

View file

@ -230,6 +230,8 @@ public:
static bool mapDimensionsValid(int width, int height); static bool mapDimensionsValid(int width, int height);
bool calculateDefaultMapSize(); bool calculateDefaultMapSize();
static int getMaxObjectEvents(); static int getMaxObjectEvents();
static int getMaxCollision();
static int getMaxElevation();
private: private:
void updateMapLayout(Map*); void updateMapLayout(Map*);
@ -253,6 +255,8 @@ private:
static int max_map_data_size; static int max_map_data_size;
static int default_map_size; static int default_map_size;
static int max_object_events; static int max_object_events;
static int max_collision;
static int max_elevation;
QStringListModel eventScriptLabelModel; QStringListModel eventScriptLabelModel;
QCompleter eventScriptLabelCompleter; QCompleter eventScriptLabelCompleter;

View file

@ -1,8 +1,9 @@
#ifndef COLLISIONPIXMAPITEM_H #ifndef COLLISIONPIXMAPITEM_H
#define COLLISIONPIXMAPITEM_H #define COLLISIONPIXMAPITEM_H
#include <QSpinBox>
#include "metatileselector.h" #include "metatileselector.h"
#include "movementpermissionsselector.h"
#include "mappixmapitem.h" #include "mappixmapitem.h"
#include "map.h" #include "map.h"
#include "settings.h" #include "settings.h"
@ -10,13 +11,15 @@
class CollisionPixmapItem : public MapPixmapItem { class CollisionPixmapItem : public MapPixmapItem {
Q_OBJECT Q_OBJECT
public: public:
CollisionPixmapItem(Map *map, MovementPermissionsSelector *movementPermissionsSelector, MetatileSelector *metatileSelector, Settings *settings, qreal *opacity) CollisionPixmapItem(Map *map, QSpinBox * selectedCollision, QSpinBox * selectedElevation, MetatileSelector *metatileSelector, Settings *settings, qreal *opacity)
: MapPixmapItem(map, metatileSelector, settings){ : MapPixmapItem(map, metatileSelector, settings){
this->movementPermissionsSelector = movementPermissionsSelector; this->selectedCollision = selectedCollision;
this->selectedElevation = selectedElevation;
this->opacity = opacity; this->opacity = opacity;
map->setCollisionItem(this); map->setCollisionItem(this);
} }
MovementPermissionsSelector *movementPermissionsSelector; QSpinBox * selectedCollision;
QSpinBox * selectedElevation;
qreal *opacity; qreal *opacity;
void updateMovementPermissionSelection(QGraphicsSceneMouseEvent *event); void updateMovementPermissionSelection(QGraphicsSceneMouseEvent *event);
virtual void paint(QGraphicsSceneMouseEvent*); virtual void paint(QGraphicsSceneMouseEvent*);
@ -28,6 +31,7 @@ public:
private: private:
unsigned actionId_ = 0; unsigned actionId_ = 0;
QPoint previousPos; QPoint previousPos;
void updateSelection(QPoint pos);
signals: signals:
void mouseEvent(QGraphicsSceneMouseEvent *, CollisionPixmapItem *); void mouseEvent(QGraphicsSceneMouseEvent *, CollisionPixmapItem *);

View file

@ -6,15 +6,19 @@
class MovementPermissionsSelector: public SelectablePixmapItem { class MovementPermissionsSelector: public SelectablePixmapItem {
Q_OBJECT Q_OBJECT
public: public:
MovementPermissionsSelector(int cellWidth, int cellHeight, QPixmap basePixmap) : MovementPermissionsSelector(QPixmap basePixmap)
SelectablePixmapItem(cellWidth, cellHeight, 1, 1), : SelectablePixmapItem(MovementPermissionsSelector::CellWidth, MovementPermissionsSelector::CellHeight, 1, 1) {
basePixmap(basePixmap) { this->basePixmap = basePixmap;
setAcceptHoverEvents(true); setAcceptHoverEvents(true);
} }
void draw(); void draw();
uint16_t getSelectedCollision(); uint16_t getSelectedCollision();
uint16_t getSelectedElevation(); uint16_t getSelectedElevation();
void select(uint16_t collision, uint16_t elevation); void select(uint16_t collision, uint16_t elevation);
void setBasePixmap(QPixmap pixmap);
static const int CellWidth;
static const int CellHeight;
protected: protected:
void hoverMoveEvent(QGraphicsSceneHoverEvent*); void hoverMoveEvent(QGraphicsSceneHoverEvent*);
@ -22,7 +26,7 @@ protected:
private: private:
void setSelectedMovementPermissions(QPointF); void setSelectedMovementPermissions(QPointF);
const QPixmap basePixmap; QPixmap basePixmap;
signals: signals:
void hoveredMovementPermissionChanged(uint16_t, uint16_t); void hoveredMovementPermissionChanged(uint16_t, uint16_t);

View file

@ -35,6 +35,9 @@ protected:
void mouseMoveEvent(QGraphicsSceneMouseEvent*); void mouseMoveEvent(QGraphicsSceneMouseEvent*);
void mouseReleaseEvent(QGraphicsSceneMouseEvent*); void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
virtual void drawSelection(); virtual void drawSelection();
signals:
void selectionChanged(int, int, int, int);
}; };
#endif // SELECTABLEPIXMAPITEM_H #endif // SELECTABLEPIXMAPITEM_H

View file

@ -244,6 +244,8 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) {
this->customScriptsEditorState = bytesFromString(value); this->customScriptsEditorState = bytesFromString(value);
} else if (key == "metatiles_zoom") { } else if (key == "metatiles_zoom") {
this->metatilesZoom = getConfigInteger(key, value, 10, 100, 30); this->metatilesZoom = getConfigInteger(key, value, 10, 100, 30);
} else if (key == "collision_zoom") {
this->collisionZoom = getConfigInteger(key, value, 10, 100, 30);
} else if (key == "show_player_view") { } else if (key == "show_player_view") {
this->showPlayerView = getConfigBool(key, value); this->showPlayerView = getConfigBool(key, value);
} else if (key == "show_cursor_tile") { } else if (key == "show_cursor_tile") {
@ -293,7 +295,8 @@ QMap<QString, QString> PorymapConfig::getKeyValueMap() {
map.insert("custom_scripts_editor_geometry", stringFromByteArray(this->customScriptsEditorGeometry)); map.insert("custom_scripts_editor_geometry", stringFromByteArray(this->customScriptsEditorGeometry));
map.insert("custom_scripts_editor_state", stringFromByteArray(this->customScriptsEditorState)); map.insert("custom_scripts_editor_state", stringFromByteArray(this->customScriptsEditorState));
map.insert("collision_opacity", QString("%1").arg(this->collisionOpacity)); map.insert("collision_opacity", QString("%1").arg(this->collisionOpacity));
map.insert("metatiles_zoom", QString("%1").arg(this->metatilesZoom)); map.insert("collision_zoom", QString::number(this->collisionZoom));
map.insert("metatiles_zoom", QString::number(this->metatilesZoom));
map.insert("show_player_view", this->showPlayerView ? "1" : "0"); map.insert("show_player_view", this->showPlayerView ? "1" : "0");
map.insert("show_cursor_tile", this->showCursorTile ? "1" : "0"); map.insert("show_cursor_tile", this->showCursorTile ? "1" : "0");
map.insert("show_border", this->showBorder ? "1" : "0"); map.insert("show_border", this->showBorder ? "1" : "0");
@ -399,6 +402,11 @@ void PorymapConfig::setCollisionOpacity(int opacity) {
// don't auto-save here because this can be called very frequently. // don't auto-save here because this can be called very frequently.
} }
void PorymapConfig::setCollisionZoom(int zoom) {
this->collisionZoom = zoom;
// don't auto-save here because this can be called very frequently.
}
void PorymapConfig::setMetatilesZoom(int zoom) { void PorymapConfig::setMetatilesZoom(int zoom) {
this->metatilesZoom = zoom; this->metatilesZoom = zoom;
// don't auto-save here because this can be called very frequently. // don't auto-save here because this can be called very frequently.
@ -519,6 +527,10 @@ int PorymapConfig::getCollisionOpacity() {
return this->collisionOpacity; return this->collisionOpacity;
} }
int PorymapConfig::getCollisionZoom() {
return this->collisionZoom;
}
int PorymapConfig::getMetatilesZoom() { int PorymapConfig::getMetatilesZoom() {
return this->metatilesZoom; return this->metatilesZoom;
} }

View file

@ -20,8 +20,6 @@
#include <math.h> #include <math.h>
static bool selectNewEvents = false; static bool selectNewEvents = false;
static const QPixmap *collisionSheetPixmap = nullptr;
static const int movementPermissionsSelectorCellSize = 32;
// 2D array mapping collision+elevation combos to an icon. // 2D array mapping collision+elevation combos to an icon.
QList<QList<const QImage*>> Editor::collisionIcons; QList<QList<const QImage*>> Editor::collisionIcons;
@ -54,6 +52,8 @@ Editor::~Editor()
delete this->playerViewRect; delete this->playerViewRect;
delete this->cursorMapTileRect; delete this->cursorMapTileRect;
delete this->map_ruler; delete this->map_ruler;
for (auto sublist : collisionIcons)
qDeleteAll(sublist);
closeProject(); closeProject();
} }
@ -1430,7 +1430,7 @@ void Editor::displayMapMovementPermissions() {
scene->removeItem(collision_item); scene->removeItem(collision_item);
delete collision_item; delete collision_item;
} }
collision_item = new CollisionPixmapItem(map, this->movement_permissions_selector_item, collision_item = new CollisionPixmapItem(map, ui->spinBox_SelectedCollision, ui->spinBox_SelectedElevation,
this->metatile_selector_item, this->settings, &this->collisionOpacity); this->metatile_selector_item, this->settings, &this->collisionOpacity);
connect(collision_item, &CollisionPixmapItem::mouseEvent, this, &Editor::mouseEvent_collision); connect(collision_item, &CollisionPixmapItem::mouseEvent, this, &Editor::mouseEvent_collision);
connect(collision_item, &CollisionPixmapItem::hoveredMapMovementPermissionChanged, connect(collision_item, &CollisionPixmapItem::hoveredMapMovementPermissionChanged,
@ -1489,13 +1489,14 @@ void Editor::displayMovementPermissionSelector() {
scene_collision_metatiles = new QGraphicsScene; scene_collision_metatiles = new QGraphicsScene;
if (!movement_permissions_selector_item) { if (!movement_permissions_selector_item) {
movement_permissions_selector_item = new MovementPermissionsSelector(movementPermissionsSelectorCellSize, movement_permissions_selector_item = new MovementPermissionsSelector(this->collisionSheetPixmap);
movementPermissionsSelectorCellSize,
collisionSheetPixmap ? *collisionSheetPixmap : QPixmap());
connect(movement_permissions_selector_item, &MovementPermissionsSelector::hoveredMovementPermissionChanged, connect(movement_permissions_selector_item, &MovementPermissionsSelector::hoveredMovementPermissionChanged,
this, &Editor::onHoveredMovementPermissionChanged); this, &Editor::onHoveredMovementPermissionChanged);
connect(movement_permissions_selector_item, &MovementPermissionsSelector::hoveredMovementPermissionCleared, connect(movement_permissions_selector_item, &MovementPermissionsSelector::hoveredMovementPermissionCleared,
this, &Editor::onHoveredMovementPermissionCleared); this, &Editor::onHoveredMovementPermissionCleared);
connect(movement_permissions_selector_item, &SelectablePixmapItem::selectionChanged, [this](int x, int y, int, int) {
this->setCollisionTabSpinBoxes(x, y);
});
movement_permissions_selector_item->select(0, projectConfig.getNewMapElevation()); // TODO: New map collision config? movement_permissions_selector_item->select(0, projectConfig.getNewMapElevation()); // TODO: New map collision config?
} }
@ -2235,13 +2236,16 @@ void Editor::objectsView_onMousePress(QMouseEvent *event) {
selectingEvent = false; selectingEvent = false;
} }
// TODO: Show elevation & collision spinners on collision tab void Editor::setCollisionTabSpinBoxes(uint16_t collision, uint16_t elevation) {
// TODO: Hide selection rect for elevation/collision combos not shown on the image const QSignalBlocker blocker1(ui->spinBox_SelectedCollision);
// TODO: Zoom slider const QSignalBlocker blocker2(ui->spinBox_SelectedElevation);
ui->spinBox_SelectedCollision->setValue(collision);
ui->spinBox_SelectedElevation->setValue(elevation);
}
// TODO: Bug--Images with transparency allow users to paint metatiles on the Collision tab // TODO: Bug--Images with transparency allow users to paint metatiles on the Collision tab
// Custom collision graphics may be provided by the user. // Custom collision graphics may be provided by the user.
void Editor::setCollisionGraphics() { void Editor::setCollisionGraphics() {
static const QImage defaultCollisionImgSheet = QImage(":/images/collisions.png");
QString customPath = projectConfig.getCollisionSheetPath(); QString customPath = projectConfig.getCollisionSheetPath();
QImage imgSheet; QImage imgSheet;
@ -2255,11 +2259,11 @@ void Editor::setCollisionGraphics() {
if (imgSheet.isNull()) { if (imgSheet.isNull()) {
// Custom collision image failed to load, use default // Custom collision image failed to load, use default
logWarn(QString("Failed to load custom collision image '%1', using default.").arg(customPath)); logWarn(QString("Failed to load custom collision image '%1', using default.").arg(customPath));
imgSheet = defaultCollisionImgSheet; imgSheet = this->defaultCollisionImgSheet;
} }
} else { } else {
// No custom collision image specified, use the default. // No custom collision image specified, use the default.
imgSheet = defaultCollisionImgSheet; imgSheet = this->defaultCollisionImgSheet;
} }
// Like the vanilla collision image, users are not required to provide an image that gives an icon for every elevation/collision combination. // Like the vanilla collision image, users are not required to provide an image that gives an icon for every elevation/collision combination.
@ -2267,42 +2271,37 @@ void Editor::setCollisionGraphics() {
const int imgColumns = projectConfig.getCollisionSheetWidth(); const int imgColumns = projectConfig.getCollisionSheetWidth();
const int imgRows = projectConfig.getCollisionSheetHeight(); const int imgRows = projectConfig.getCollisionSheetHeight();
// Create a pixmap for the selector on the Collision tab // Create a pixmap for the selector on the Collision tab. If a project was previously opened we'll also need to refresh the selector.
delete collisionSheetPixmap; this->collisionSheetPixmap = QPixmap::fromImage(imgSheet).scaled(MovementPermissionsSelector::CellWidth * imgColumns,
collisionSheetPixmap = new QPixmap(QPixmap::fromImage(imgSheet) MovementPermissionsSelector::CellHeight * imgRows);
.scaled(movementPermissionsSelectorCellSize * imgColumns, if (this->movement_permissions_selector_item)
movementPermissionsSelectorCellSize * imgRows)); this->movement_permissions_selector_item->setBasePixmap(this->collisionSheetPixmap);
for (auto sublist : collisionIcons) for (auto sublist : collisionIcons)
qDeleteAll(sublist); qDeleteAll(sublist);
collisionIcons.clear(); collisionIcons.clear();
// Chop up the collision image sheet into separate icon images to be displayed on the map. // Use the image sheet to create an icon for each collision/elevation combination.
// Any icons for elevation/collision combinations that aren't provided by the image sheet are also created now. // Any icons for combinations that aren't provided by the image sheet are also created now using default graphics.
const int w = 16; const int w = 16, h = 16;
const int h = 16;
const int numCollisions = 4; // TODO: Read value from elsewhere
const int numElevations = 16; // TODO: Read value from elsewhere
imgSheet = imgSheet.scaled(w * imgColumns, h * imgRows); imgSheet = imgSheet.scaled(w * imgColumns, h * imgRows);
for (int collision = 0; collision < numCollisions; collision++) { for (int collision = 0; collision <= Project::getMaxCollision(); collision++) {
// If (collision >= imgColumns) here, it's a valid collision value, but it is not represented with an icon on the image sheet. // If (collision >= imgColumns) here, it's a valid collision value, but it is not represented with an icon on the image sheet.
// In this case we just use the rightmost collision icon. This is mostly to support the vanilla case, where technically 0-3 // In this case we just use the rightmost collision icon. This is mostly to support the vanilla case, where technically 0-3
// are valid collision values, but 1-3 have the same meaning, so the vanilla collision selector image only has 2 columns. // are valid collision values, but 1-3 have the same meaning, so the vanilla collision selector image only has 2 columns.
int x = ((collision < imgColumns) ? collision : imgColumns) * w; int x = ((collision < imgColumns) ? collision : (imgColumns - 1)) * w;
QList<const QImage*> sublist; QList<const QImage*> sublist;
for (int elevation = 0; elevation < numElevations; elevation++) { for (int elevation = 0; elevation <= Project::getMaxElevation(); elevation++) {
if (elevation < imgRows) { if (elevation < imgRows) {
// This elevation has an icon on the image sheet, add it to the list // This elevation has an icon on the image sheet, add it to the list
int y = elevation * h; int y = elevation * h;
sublist.append(new QImage(imgSheet.copy(x, y, w, h))); sublist.append(new QImage(imgSheet.copy(x, y, w, h)));
} else { } else {
// This is a valid elevation value, but it has no icon on the image sheet. // This is a valid elevation value, but it has no icon on the image sheet.
// Give it a placeholder "?" icon (white if passable, red otherwise) // Give it a placeholder "?" icon (red if impassable, white otherwise)
static const QImage placeholder = QImage(":/images/collisions_unknown.png"); sublist.append(new QImage(this->collisionPlaceholder.copy(x != 0 ? w : 0, 0, w, h)));
static const QImage * placeholder_White = new QImage(placeholder.copy(0, 0, w, h));
static const QImage * placeholder_Red = new QImage(placeholder.copy(w, 0, w, h));
sublist.append(x == 0 ? placeholder_White : placeholder_Red);
} }
} }
collisionIcons.append(sublist); collisionIcons.append(sublist);

View file

@ -372,7 +372,8 @@ void MainWindow::setWildEncountersUIEnabled(bool enabled) {
ui->mainTabBar->setTabEnabled(4, enabled); ui->mainTabBar->setTabEnabled(4, enabled);
} }
void MainWindow::setProjectSpecificUIVisibility() // Update the UI using information we've read from the user's project config file.
void MainWindow::setProjectSpecificUI()
{ {
this->setWildEncountersUIEnabled(userConfig.getEncounterJsonActive()); this->setWildEncountersUIEnabled(userConfig.getEncounterJsonActive());
@ -393,7 +394,9 @@ void MainWindow::setProjectSpecificUIVisibility()
ui->label_FloorNumber->setVisible(floorNumEnabled); ui->label_FloorNumber->setVisible(floorNumEnabled);
Event::setIcons(); Event::setIcons();
Editor::setCollisionGraphics(); editor->setCollisionGraphics();
ui->spinBox_SelectedElevation->setMaximum(Project::getMaxElevation());
ui->spinBox_SelectedCollision->setMaximum(Project::getMaxCollision());
} }
void MainWindow::mapSortOrder_changed(QAction *action) void MainWindow::mapSortOrder_changed(QAction *action)
@ -455,6 +458,9 @@ void MainWindow::loadUserSettings() {
ui->horizontalSlider_MetatileZoom->blockSignals(true); ui->horizontalSlider_MetatileZoom->blockSignals(true);
ui->horizontalSlider_MetatileZoom->setValue(porymapConfig.getMetatilesZoom()); ui->horizontalSlider_MetatileZoom->setValue(porymapConfig.getMetatilesZoom());
ui->horizontalSlider_MetatileZoom->blockSignals(false); ui->horizontalSlider_MetatileZoom->blockSignals(false);
ui->horizontalSlider_CollisionZoom->blockSignals(true);
ui->horizontalSlider_CollisionZoom->setValue(porymapConfig.getCollisionZoom());
ui->horizontalSlider_CollisionZoom->blockSignals(false);
setTheme(porymapConfig.getTheme()); setTheme(porymapConfig.getTheme());
} }
@ -514,7 +520,7 @@ bool MainWindow::openProject(QString dir) {
projectConfig.load(); projectConfig.load();
this->closeSupplementaryWindows(); this->closeSupplementaryWindows();
this->setProjectSpecificUIVisibility(); this->setProjectSpecificUI();
this->newMapDefaultsSet = false; this->newMapDefaultsSet = false;
Scripting::init(this); Scripting::init(this);
@ -718,6 +724,7 @@ void MainWindow::refreshMapScene()
ui->graphicsView_Collision->setFixedSize(editor->movement_permissions_selector_item->pixmap().width() + 2, editor->movement_permissions_selector_item->pixmap().height() + 2); ui->graphicsView_Collision->setFixedSize(editor->movement_permissions_selector_item->pixmap().width() + 2, editor->movement_permissions_selector_item->pixmap().height() + 2);
on_horizontalSlider_MetatileZoom_valueChanged(ui->horizontalSlider_MetatileZoom->value()); on_horizontalSlider_MetatileZoom_valueChanged(ui->horizontalSlider_MetatileZoom->value());
on_horizontalSlider_CollisionZoom_valueChanged(ui->horizontalSlider_CollisionZoom->value());
} }
void MainWindow::openWarpMap(QString map_name, int event_id, Event::Group event_group) { void MainWindow::openWarpMap(QString map_name, int event_id, Event::Group event_group) {
@ -2797,6 +2804,33 @@ void MainWindow::on_horizontalSlider_MetatileZoom_valueChanged(int value) {
redrawMetatileSelection(); redrawMetatileSelection();
} }
void MainWindow::on_horizontalSlider_CollisionZoom_valueChanged(int value) {
porymapConfig.setCollisionZoom(value);
double scale = pow(3.0, static_cast<double>(value - 30) / 30.0);
QTransform transform;
transform.scale(scale, scale);
QSize size(editor->movement_permissions_selector_item->pixmap().width(),
editor->movement_permissions_selector_item->pixmap().height());
size *= scale;
ui->graphicsView_Collision->setResizeAnchor(QGraphicsView::NoAnchor);
ui->graphicsView_Collision->setTransform(transform);
ui->graphicsView_Collision->setFixedSize(size.width() + 2, size.height() + 2);
}
void MainWindow::on_spinBox_SelectedCollision_valueChanged(int collision) {
if (!this->editor || !this->editor->movement_permissions_selector_item)
return;
this->editor->movement_permissions_selector_item->select(collision, ui->spinBox_SelectedElevation->value());
}
void MainWindow::on_spinBox_SelectedElevation_valueChanged(int elevation) {
if (!this->editor || !this->editor->movement_permissions_selector_item)
return;
this->editor->movement_permissions_selector_item->select(ui->spinBox_SelectedCollision->value(), elevation);
}
void MainWindow::on_actionRegion_Map_Editor_triggered() { void MainWindow::on_actionRegion_Map_Editor_triggered() {
if (!this->regionMapEditor) { if (!this->regionMapEditor) {
if (!initRegionMapEditor()) { if (!initRegionMapEditor()) {

View file

@ -35,6 +35,10 @@ int Project::max_map_data_size = 10240; // 0x2800
int Project::default_map_size = 20; int Project::default_map_size = 20;
int Project::max_object_events = 64; int Project::max_object_events = 64;
// TODO: Replace once Block layout can be edited
int Project::max_collision = 3;
int Project::max_elevation = 15;
Project::Project(QWidget *parent) : Project::Project(QWidget *parent) :
QObject(parent), QObject(parent),
eventScriptLabelModel(this), eventScriptLabelModel(this),
@ -2579,6 +2583,16 @@ int Project::getMaxObjectEvents()
return Project::max_object_events; return Project::max_object_events;
} }
int Project::getMaxCollision()
{
return Project::max_collision;
}
int Project::getMaxElevation()
{
return Project::max_elevation;
}
void Project::setImportExportPath(QString filename) void Project::setImportExportPath(QString filename)
{ {
this->importExportPath = QFileInfo(filename).absolutePath(); this->importExportPath = QFileInfo(filename).absolutePath();

View file

@ -75,8 +75,8 @@ void CollisionPixmapItem::paint(QGraphicsSceneMouseEvent *event) {
Block block; Block block;
if (map->getBlock(pos.x(), pos.y(), &block)) { if (map->getBlock(pos.x(), pos.y(), &block)) {
block.collision = this->movementPermissionsSelector->getSelectedCollision(); block.collision = this->selectedCollision->value();
block.elevation = this->movementPermissionsSelector->getSelectedElevation(); block.elevation = this->selectedElevation->value();
map->setBlock(pos.x(), pos.y(), block, true); map->setBlock(pos.x(), pos.y(), block, true);
} }
@ -93,8 +93,8 @@ void CollisionPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) {
Blockdata oldCollision = map->layout->blockdata; Blockdata oldCollision = map->layout->blockdata;
QPoint pos = Metatile::coordFromPixmapCoord(event->pos()); QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
uint16_t collision = this->movementPermissionsSelector->getSelectedCollision(); uint16_t collision = this->selectedCollision->value();
uint16_t elevation = this->movementPermissionsSelector->getSelectedElevation(); uint16_t elevation = this->selectedElevation->value();
map->floodFillCollisionElevation(pos.x(), pos.y(), collision, elevation); map->floodFillCollisionElevation(pos.x(), pos.y(), collision, elevation);
if (map->layout->blockdata != oldCollision) { if (map->layout->blockdata != oldCollision) {
@ -109,8 +109,8 @@ void CollisionPixmapItem::magicFill(QGraphicsSceneMouseEvent *event) {
} else if (map) { } else if (map) {
Blockdata oldCollision = map->layout->blockdata; Blockdata oldCollision = map->layout->blockdata;
QPoint pos = Metatile::coordFromPixmapCoord(event->pos()); QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
uint16_t collision = this->movementPermissionsSelector->getSelectedCollision(); uint16_t collision = this->selectedCollision->value();
uint16_t elevation = this->movementPermissionsSelector->getSelectedElevation(); uint16_t elevation = this->selectedElevation->value();
map->magicFillCollisionElevation(pos.x(), pos.y(), collision, elevation); map->magicFillCollisionElevation(pos.x(), pos.y(), collision, elevation);
if (map->layout->blockdata != oldCollision) { if (map->layout->blockdata != oldCollision) {
@ -121,10 +121,7 @@ void CollisionPixmapItem::magicFill(QGraphicsSceneMouseEvent *event) {
void CollisionPixmapItem::pick(QGraphicsSceneMouseEvent *event) { void CollisionPixmapItem::pick(QGraphicsSceneMouseEvent *event) {
QPoint pos = Metatile::coordFromPixmapCoord(event->pos()); QPoint pos = Metatile::coordFromPixmapCoord(event->pos());
Block block; this->updateSelection(pos);
if (map->getBlock(pos.x(), pos.y(), &block)) {
this->movementPermissionsSelector->select(block.collision, block.elevation);
}
} }
void CollisionPixmapItem::updateMovementPermissionSelection(QGraphicsSceneMouseEvent *event) { void CollisionPixmapItem::updateMovementPermissionSelection(QGraphicsSceneMouseEvent *event) {
@ -135,9 +132,14 @@ void CollisionPixmapItem::updateMovementPermissionSelection(QGraphicsSceneMouseE
if (pos.x() >= map->getWidth()) pos.setX(map->getWidth() - 1); if (pos.x() >= map->getWidth()) pos.setX(map->getWidth() - 1);
if (pos.y() < 0) pos.setY(0); if (pos.y() < 0) pos.setY(0);
if (pos.y() >= map->getHeight()) pos.setY(map->getHeight() - 1); if (pos.y() >= map->getHeight()) pos.setY(map->getHeight() - 1);
this->updateSelection(pos);
}
void CollisionPixmapItem::updateSelection(QPoint pos) {
Block block; Block block;
if (map->getBlock(pos.x(), pos.y(), &block)) { if (map->getBlock(pos.x(), pos.y(), &block)) {
this->movementPermissionsSelector->select(block.collision, block.elevation); const QSignalBlocker blocker(this->selectedCollision); // We only need a signal for changing one of them, not both
this->selectedCollision->setValue(block.collision);
this->selectedElevation->setValue(block.elevation);
} }
} }

View file

@ -1,11 +1,19 @@
#include "movementpermissionsselector.h" #include "movementpermissionsselector.h"
#include <QPainter> #include <QPainter>
const int MovementPermissionsSelector::CellWidth = 32;
const int MovementPermissionsSelector::CellHeight = 32;
void MovementPermissionsSelector::draw() { void MovementPermissionsSelector::draw() {
this->setPixmap(this->basePixmap); this->setPixmap(this->basePixmap);
this->drawSelection(); this->drawSelection();
} }
void MovementPermissionsSelector::setBasePixmap(QPixmap pixmap) {
this->basePixmap = pixmap;
this->draw();
}
uint16_t MovementPermissionsSelector::getSelectedCollision() { uint16_t MovementPermissionsSelector::getSelectedCollision() {
return static_cast<uint16_t>(this->selectionInitialX); return static_cast<uint16_t>(this->selectionInitialX);
} }
@ -15,7 +23,7 @@ uint16_t MovementPermissionsSelector::getSelectedElevation() {
} }
void MovementPermissionsSelector::select(uint16_t collision, uint16_t elevation) { void MovementPermissionsSelector::select(uint16_t collision, uint16_t elevation) {
SelectablePixmapItem::select(collision != 0, elevation, 0, 0); SelectablePixmapItem::select(collision, elevation, 0, 0);
} }
void MovementPermissionsSelector::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { void MovementPermissionsSelector::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {

View file

@ -22,6 +22,7 @@ void SelectablePixmapItem::select(int x, int y, int width, int height)
this->selectionOffsetX = qMax(0, qMin(width, this->maxSelectionWidth)); this->selectionOffsetX = qMax(0, qMin(width, this->maxSelectionWidth));
this->selectionOffsetY = qMax(0, qMin(height, this->maxSelectionHeight)); this->selectionOffsetY = qMax(0, qMin(height, this->maxSelectionHeight));
this->draw(); this->draw();
emit this->selectionChanged(x, y, width, height);
} }
void SelectablePixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) void SelectablePixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
@ -76,6 +77,7 @@ void SelectablePixmapItem::updateSelection(int x, int y)
} }
this->draw(); this->draw();
emit this->selectionChanged(x, y, width, height);
} }
QPoint SelectablePixmapItem::getCellPos(QPointF pos) QPoint SelectablePixmapItem::getCellPos(QPointF pos)