commit
e91df38714
33 changed files with 3257 additions and 49 deletions
10
.gitignore
vendored
10
.gitignore
vendored
|
@ -2,12 +2,14 @@ porymap.pro.user
|
||||||
*.autosave
|
*.autosave
|
||||||
*.stash
|
*.stash
|
||||||
*.o
|
*.o
|
||||||
moc_*
|
|
||||||
qrc_*
|
|
||||||
porymap.app*
|
porymap.app*
|
||||||
porymap
|
porymap
|
||||||
|
porymap.cfg
|
||||||
|
porymap.log
|
||||||
Makefile
|
Makefile
|
||||||
|
|
||||||
# Generated UI header
|
# Qt generated files
|
||||||
ui_*.h
|
ui_*.h
|
||||||
|
moc_*.h
|
||||||
|
moc_*.cpp
|
||||||
|
qrc_*.cpp
|
||||||
|
|
|
@ -2750,6 +2750,7 @@
|
||||||
<addaction name="action_NewMap"/>
|
<addaction name="action_NewMap"/>
|
||||||
<addaction name="actionNew_Tileset"/>
|
<addaction name="actionNew_Tileset"/>
|
||||||
<addaction name="actionTileset_Editor"/>
|
<addaction name="actionTileset_Editor"/>
|
||||||
|
<addaction name="actionRegion_Map_Editor"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuHelp">
|
<widget class="QMenu" name="menuHelp">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
@ -2977,6 +2978,11 @@
|
||||||
<string>Cursor Tile Outline</string>
|
<string>Cursor Tile Outline</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionRegion_Map_Editor">
|
||||||
|
<property name="text">
|
||||||
|
<string>Region Map Editor</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
<action name="actionNew_Tileset">
|
<action name="actionNew_Tileset">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>New Tileset...</string>
|
<string>New Tileset...</string>
|
||||||
|
|
1148
forms/regionmapeditor.ui
Normal file
1148
forms/regionmapeditor.ui
Normal file
File diff suppressed because it is too large
Load diff
|
@ -4,6 +4,7 @@
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QByteArrayList>
|
#include <QByteArrayList>
|
||||||
|
#include <QSize>
|
||||||
|
|
||||||
enum MapSortOrder {
|
enum MapSortOrder {
|
||||||
Group = 0,
|
Group = 0,
|
||||||
|
@ -36,6 +37,7 @@ public:
|
||||||
this->metatilesZoom = 30;
|
this->metatilesZoom = 30;
|
||||||
this->showPlayerView = false;
|
this->showPlayerView = false;
|
||||||
this->showCursorTile = true;
|
this->showCursorTile = true;
|
||||||
|
this->regionMapDimensions = QSize(32, 20);
|
||||||
}
|
}
|
||||||
void setRecentProject(QString project);
|
void setRecentProject(QString project);
|
||||||
void setRecentMap(QString map);
|
void setRecentMap(QString map);
|
||||||
|
@ -46,6 +48,7 @@ public:
|
||||||
void setMetatilesZoom(int zoom);
|
void setMetatilesZoom(int zoom);
|
||||||
void setShowPlayerView(bool enabled);
|
void setShowPlayerView(bool enabled);
|
||||||
void setShowCursorTile(bool enabled);
|
void setShowCursorTile(bool enabled);
|
||||||
|
void setRegionMapDimensions(int width, int height);
|
||||||
QString getRecentProject();
|
QString getRecentProject();
|
||||||
QString getRecentMap();
|
QString getRecentMap();
|
||||||
MapSortOrder getMapSortOrder();
|
MapSortOrder getMapSortOrder();
|
||||||
|
@ -55,6 +58,7 @@ public:
|
||||||
int getMetatilesZoom();
|
int getMetatilesZoom();
|
||||||
bool getShowPlayerView();
|
bool getShowPlayerView();
|
||||||
bool getShowCursorTile();
|
bool getShowCursorTile();
|
||||||
|
QSize getRegionMapDimensions();
|
||||||
protected:
|
protected:
|
||||||
QString getConfigFilepath();
|
QString getConfigFilepath();
|
||||||
void parseConfigKeyValue(QString key, QString value);
|
void parseConfigKeyValue(QString key, QString value);
|
||||||
|
@ -76,6 +80,7 @@ private:
|
||||||
int metatilesZoom;
|
int metatilesZoom;
|
||||||
bool showPlayerView;
|
bool showPlayerView;
|
||||||
bool showCursorTile;
|
bool showCursorTile;
|
||||||
|
QSize regionMapDimensions;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern PorymapConfig porymapConfig;
|
extern PorymapConfig porymapConfig;
|
||||||
|
|
|
@ -12,4 +12,21 @@ public:
|
||||||
~HistoryItem();
|
~HistoryItem();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum RegionMapEditorBox {
|
||||||
|
BackgroundImage = 1,
|
||||||
|
CityMapImage = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
class RegionMapHistoryItem {
|
||||||
|
public:
|
||||||
|
int which;
|
||||||
|
int mapWidth = 0;
|
||||||
|
int mapHeight = 0;
|
||||||
|
QVector<uint8_t> tiles;
|
||||||
|
QString cityMap;
|
||||||
|
RegionMapHistoryItem(int type, QVector<uint8_t> tiles, QString cityMap);
|
||||||
|
RegionMapHistoryItem(int type, QVector<uint8_t> tiles, int width, int height);
|
||||||
|
~RegionMapHistoryItem();
|
||||||
|
};
|
||||||
|
|
||||||
#endif // HISTORYITEM_H
|
#endif // HISTORYITEM_H
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define MAPCONNECTION_H
|
#define MAPCONNECTION_H
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
class MapConnection {
|
class MapConnection {
|
||||||
public:
|
public:
|
||||||
|
@ -10,4 +11,12 @@ public:
|
||||||
QString map_name;
|
QString map_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline bool operator==(const MapConnection &c1, const MapConnection &c2) {
|
||||||
|
return c1.map_name == c2.map_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint qHash(const MapConnection &key) {
|
||||||
|
return qHash(key.map_name);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // MAPCONNECTION_H
|
#endif // MAPCONNECTION_H
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
#ifndef PALETTEPARSER_H
|
#ifndef PALETTEUTIL_H
|
||||||
#define PALETTEPARSER_H
|
#define PALETTEUTIL_H
|
||||||
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QRgb>
|
#include <QRgb>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
class PaletteParser
|
class PaletteUtil
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PaletteParser();
|
PaletteUtil();
|
||||||
QList<QRgb> parse(QString filepath, bool *error);
|
QList<QRgb> parse(QString filepath, bool *error);
|
||||||
|
void writeJASC(QString filepath, QVector<QRgb> colors, int offset, int nColors);
|
||||||
private:
|
private:
|
||||||
QList<QRgb> parsePal(QString filepath, bool *error);
|
QList<QRgb> parsePal(QString filepath, bool *error);
|
||||||
QList<QRgb> parseJASC(QString filepath, bool *error);
|
QList<QRgb> parseJASC(QString filepath, bool *error);
|
||||||
|
@ -20,4 +21,4 @@ private:
|
||||||
int clampColorValue(int value);
|
int clampColorValue(int value);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PALETTEPARSER_H
|
#endif // PALETTEUTIL_H
|
113
include/core/regionmap.h
Normal file
113
include/core/regionmap.h
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
#ifndef REGIONMAP_H
|
||||||
|
#define REGIONMAP_H
|
||||||
|
|
||||||
|
#include "map.h"
|
||||||
|
#include "project.h"
|
||||||
|
#include "tilemaptileselector.h"
|
||||||
|
#include "history.h"
|
||||||
|
#include "historyitem.h"
|
||||||
|
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QString>
|
||||||
|
#include <QVector>
|
||||||
|
#include <QList>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QGraphicsScene>
|
||||||
|
#include <QGraphicsView>
|
||||||
|
|
||||||
|
struct RegionMapEntry
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
QString name;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RegionMapSquare
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int x = -1;
|
||||||
|
int y = -1;
|
||||||
|
uint8_t tile_img_id = 0x00;
|
||||||
|
uint8_t secid = 0x00;
|
||||||
|
bool has_map = false;
|
||||||
|
bool has_city_map = false;
|
||||||
|
bool duplicated = false;
|
||||||
|
QString map_name;
|
||||||
|
QString mapsec;
|
||||||
|
QString city_map_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RegionMap : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
RegionMap() = default;
|
||||||
|
|
||||||
|
~RegionMap() {};
|
||||||
|
|
||||||
|
Project *project = nullptr;
|
||||||
|
|
||||||
|
QVector<RegionMapSquare> map_squares;
|
||||||
|
History<RegionMapHistoryItem*> history;
|
||||||
|
|
||||||
|
const int padLeft = 1;
|
||||||
|
const int padRight = 3;
|
||||||
|
const int padTop = 2;
|
||||||
|
const int padBottom = 3;
|
||||||
|
|
||||||
|
void init(Project*);
|
||||||
|
|
||||||
|
void readBkgImgBin();
|
||||||
|
void readLayout();
|
||||||
|
|
||||||
|
void save();
|
||||||
|
void saveTileImages();
|
||||||
|
void saveBkgImgBin();
|
||||||
|
void saveLayout();
|
||||||
|
void saveOptions(int id, QString sec, QString name, int x, int y);
|
||||||
|
|
||||||
|
void resize(int width, int height);
|
||||||
|
void resetSquare(int index);
|
||||||
|
void clearLayout();
|
||||||
|
void clearImage();
|
||||||
|
void replaceSectionId(unsigned oldId, unsigned newId);
|
||||||
|
|
||||||
|
int width();
|
||||||
|
int height();
|
||||||
|
QSize imgSize();
|
||||||
|
unsigned getTileId(int x, int y);
|
||||||
|
int getMapSquareIndex(int x, int y);
|
||||||
|
QString pngPath();
|
||||||
|
void setTemporaryPngPath(QString);
|
||||||
|
QString cityTilesPath();
|
||||||
|
void setTemporaryCityTilesPath(QString);
|
||||||
|
|
||||||
|
QVector<uint8_t> getTiles();
|
||||||
|
void setTiles(QVector<uint8_t> tileIds);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int layout_width_;
|
||||||
|
int layout_height_;
|
||||||
|
int img_width_;
|
||||||
|
int img_height_;
|
||||||
|
|
||||||
|
QString region_map_png_path;
|
||||||
|
QString region_map_bin_path;
|
||||||
|
QString region_map_entries_path;
|
||||||
|
QString region_map_layout_bin_path;
|
||||||
|
QString city_map_tiles_path;
|
||||||
|
|
||||||
|
QMap<QString, QString> sMapNamesMap;
|
||||||
|
QMap<QString, struct RegionMapEntry> mapSecToMapEntry;
|
||||||
|
QVector<QString> sMapNames;
|
||||||
|
|
||||||
|
int img_index_(int x, int y);
|
||||||
|
int layout_index_(int x, int y);
|
||||||
|
|
||||||
|
QString fix_case(QString);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // REGIONMAP_H
|
|
@ -116,7 +116,7 @@ public:
|
||||||
|
|
||||||
QString map_edit_mode;
|
QString map_edit_mode;
|
||||||
QString prev_edit_mode;
|
QString prev_edit_mode;
|
||||||
|
|
||||||
int scale_exp = 0;
|
int scale_exp = 0;
|
||||||
double scale_base = sqrt(2); // adjust scale factor with this
|
double scale_base = sqrt(2); // adjust scale factor with this
|
||||||
qreal collisionOpacity = 0.5;
|
qreal collisionOpacity = 0.5;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
#include "tileseteditor.h"
|
#include "tileseteditor.h"
|
||||||
|
#include "regionmapeditor.h"
|
||||||
#include "filterchildrenproxymodel.h"
|
#include "filterchildrenproxymodel.h"
|
||||||
#include "newmappopup.h"
|
#include "newmappopup.h"
|
||||||
#include "newtilesetdialog.h"
|
#include "newtilesetdialog.h"
|
||||||
|
@ -162,9 +163,12 @@ private slots:
|
||||||
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_actionRegion_Map_Editor_triggered();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MainWindow *ui;
|
Ui::MainWindow *ui;
|
||||||
TilesetEditor *tilesetEditor = nullptr;
|
TilesetEditor *tilesetEditor = nullptr;
|
||||||
|
RegionMapEditor *regionMapEditor = nullptr;
|
||||||
FilterChildrenProxyModel *mapListProxyModel;
|
FilterChildrenProxyModel *mapListProxyModel;
|
||||||
NewMapPopup *newmapprompt = nullptr;
|
NewMapPopup *newmapprompt = nullptr;
|
||||||
QStandardItemModel *mapListModel;
|
QStandardItemModel *mapListModel;
|
||||||
|
|
|
@ -30,7 +30,9 @@ public:
|
||||||
QString layoutsLabel;
|
QString layoutsLabel;
|
||||||
QMap<QString, MapLayout*> mapLayouts;
|
QMap<QString, MapLayout*> mapLayouts;
|
||||||
QMap<QString, MapLayout*> mapLayoutsMaster;
|
QMap<QString, MapLayout*> mapLayoutsMaster;
|
||||||
QStringList *regionMapSections = nullptr;
|
QMap<QString, QString> *mapSecToMapHoverName;
|
||||||
|
QMap<QString, int> mapSectionNameToValue;
|
||||||
|
QMap<int, QString> mapSectionValueToName;
|
||||||
QStringList *itemNames = nullptr;
|
QStringList *itemNames = nullptr;
|
||||||
QStringList *flagNames = nullptr;
|
QStringList *flagNames = nullptr;
|
||||||
QStringList *varNames = nullptr;
|
QStringList *varNames = nullptr;
|
||||||
|
|
52
include/ui/citymappixmapitem.h
Normal file
52
include/ui/citymappixmapitem.h
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef CITYMAPPIXMAPITEM_H
|
||||||
|
#define CITYMAPPIXMAPITEM_H
|
||||||
|
|
||||||
|
#include "tilemaptileselector.h"
|
||||||
|
|
||||||
|
#include <QGraphicsPixmapItem>
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
|
class CityMapPixmapItem : public QObject, public QGraphicsPixmapItem {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
CityMapPixmapItem(QString fname, TilemapTileSelector *tile_selector) {
|
||||||
|
this->file = fname;
|
||||||
|
this->tile_selector = tile_selector;
|
||||||
|
setAcceptHoverEvents(true);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
TilemapTileSelector *tile_selector;
|
||||||
|
|
||||||
|
QString file;
|
||||||
|
|
||||||
|
QByteArray data;
|
||||||
|
|
||||||
|
void init();
|
||||||
|
void save();
|
||||||
|
void create(QString);
|
||||||
|
virtual void paint(QGraphicsSceneMouseEvent*);
|
||||||
|
virtual void draw();
|
||||||
|
int getIndexAt(int, int);
|
||||||
|
int width();
|
||||||
|
int height();
|
||||||
|
|
||||||
|
QVector<uint8_t> getTiles();
|
||||||
|
void setTiles(QVector<uint8_t>);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int width_;
|
||||||
|
int height_;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void mouseEvent(QGraphicsSceneMouseEvent *, CityMapPixmapItem *);
|
||||||
|
void hoveredRegionMapTileChanged(int x, int y);
|
||||||
|
void hoveredRegionMapTileCleared();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||||
|
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
|
||||||
|
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CITYMAPPIXMAPITEM_H
|
118
include/ui/regionmapeditor.h
Normal file
118
include/ui/regionmapeditor.h
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
#ifndef REGIONMAPEDITOR_H
|
||||||
|
#define REGIONMAPEDITOR_H
|
||||||
|
|
||||||
|
#include "regionmappixmapitem.h"
|
||||||
|
#include "citymappixmapitem.h"
|
||||||
|
#include "regionmaplayoutpixmapitem.h"
|
||||||
|
#include "regionmap.h"
|
||||||
|
#include "history.h"
|
||||||
|
#include "historyitem.h"
|
||||||
|
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QGraphicsSceneMouseEvent>
|
||||||
|
#include <QCloseEvent>
|
||||||
|
#include <QResizeEvent>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class RegionMapEditor;
|
||||||
|
}
|
||||||
|
|
||||||
|
class RegionMapEditor : public QMainWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RegionMapEditor(QWidget *parent = 0, Project *pro = nullptr);
|
||||||
|
~RegionMapEditor();
|
||||||
|
|
||||||
|
RegionMap *region_map;
|
||||||
|
|
||||||
|
void loadRegionMapData();
|
||||||
|
void loadCityMaps();
|
||||||
|
void setCurrentSquareOptions();
|
||||||
|
|
||||||
|
void onRegionMapTileSelectorSelectedTileChanged(unsigned id);
|
||||||
|
void onCityMapTileSelectorSelectedTileChanged(unsigned id);
|
||||||
|
void onRegionMapTileSelectorHoveredTileChanged(unsigned id);
|
||||||
|
void onRegionMapTileSelectorHoveredTileCleared();
|
||||||
|
|
||||||
|
void onRegionMapLayoutSelectedTileChanged(int index);
|
||||||
|
void onRegionMapLayoutHoveredTileChanged(int index);
|
||||||
|
void onRegionMapLayoutHoveredTileCleared();
|
||||||
|
|
||||||
|
void undo();
|
||||||
|
void redo();
|
||||||
|
|
||||||
|
void resize(int width, int height);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::RegionMapEditor *ui;
|
||||||
|
Project *project;
|
||||||
|
|
||||||
|
History<RegionMapHistoryItem*> history;
|
||||||
|
|
||||||
|
int currIndex;
|
||||||
|
unsigned selectedCityTile;
|
||||||
|
unsigned selectedImageTile;
|
||||||
|
|
||||||
|
bool hasUnsavedChanges = false;
|
||||||
|
bool cityMapFirstDraw = true;
|
||||||
|
bool regionMapFirstDraw = true;
|
||||||
|
|
||||||
|
double scaleUpFactor = 2.0;
|
||||||
|
double initialScale = 30.0;
|
||||||
|
|
||||||
|
QGraphicsScene *scene_region_map_image = nullptr;
|
||||||
|
QGraphicsScene *scene_city_map_image = nullptr;
|
||||||
|
QGraphicsScene *scene_region_map_layout = nullptr;
|
||||||
|
QGraphicsScene *scene_region_map_tiles = nullptr;
|
||||||
|
QGraphicsScene *scene_city_map_tiles = nullptr;
|
||||||
|
|
||||||
|
TilemapTileSelector *mapsquare_selector_item = nullptr;
|
||||||
|
TilemapTileSelector *city_map_selector_item = nullptr;
|
||||||
|
|
||||||
|
RegionMapLayoutPixmapItem *region_map_layout_item = nullptr;
|
||||||
|
RegionMapPixmapItem *region_map_item = nullptr;
|
||||||
|
CityMapPixmapItem *city_map_item = nullptr;
|
||||||
|
|
||||||
|
void displayRegionMap();
|
||||||
|
void displayRegionMapImage();
|
||||||
|
void displayRegionMapLayout();
|
||||||
|
void displayRegionMapLayoutOptions();
|
||||||
|
void updateRegionMapLayoutOptions(int index);
|
||||||
|
void displayRegionMapTileSelector();
|
||||||
|
void displayCityMapTileSelector();
|
||||||
|
void displayCityMap(QString name);
|
||||||
|
void importTileImage(bool city = false);//QString path);// what is this path tho?
|
||||||
|
|
||||||
|
bool createCityMap(QString name);
|
||||||
|
|
||||||
|
void closeEvent(QCloseEvent* event);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_action_RegionMap_Save_triggered();
|
||||||
|
void on_action_RegionMap_Undo_triggered();
|
||||||
|
void on_action_RegionMap_Redo_triggered();
|
||||||
|
void on_action_RegionMap_Resize_triggered();
|
||||||
|
void on_action_RegionMap_ClearImage_triggered();
|
||||||
|
void on_action_RegionMap_ClearLayout_triggered();
|
||||||
|
void on_action_Swap_triggered();
|
||||||
|
void on_action_Import_RegionMap_ImageTiles_triggered();
|
||||||
|
void on_action_Import_CityMap_ImageTiles_triggered();
|
||||||
|
void on_tabWidget_Region_Map_currentChanged(int);
|
||||||
|
void on_pushButton_RM_Options_delete_clicked();
|
||||||
|
void on_comboBox_RM_ConnectedMap_activated(const QString &text);
|
||||||
|
void on_pushButton_CityMap_add_clicked();
|
||||||
|
void on_verticalSlider_Zoom_Map_Image_valueChanged(int);
|
||||||
|
void on_verticalSlider_Zoom_Image_Tiles_valueChanged(int);
|
||||||
|
void on_verticalSlider_Zoom_City_Map_valueChanged(int);
|
||||||
|
void on_verticalSlider_Zoom_City_Tiles_valueChanged(int);
|
||||||
|
void on_comboBox_CityMap_picker_currentTextChanged(const QString &text);
|
||||||
|
void on_lineEdit_RM_MapName_textEdited(const QString &text);
|
||||||
|
void onHoveredRegionMapTileChanged(int x, int y);
|
||||||
|
void onHoveredRegionMapTileCleared();
|
||||||
|
void mouseEvent_region_map(QGraphicsSceneMouseEvent *event, RegionMapPixmapItem *item);
|
||||||
|
void mouseEvent_city_map(QGraphicsSceneMouseEvent *event, CityMapPixmapItem *item);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // REGIONMAPEDITOR_H
|
41
include/ui/regionmaplayoutpixmapitem.h
Normal file
41
include/ui/regionmaplayoutpixmapitem.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef REGIONMAPLAYOUTPIXMAPITEM_H
|
||||||
|
#define REGIONMAPLAYOUTPIXMAPITEM_H
|
||||||
|
|
||||||
|
#include "tilemaptileselector.h"
|
||||||
|
#include "regionmap.h"
|
||||||
|
|
||||||
|
class RegionMapLayoutPixmapItem : public SelectablePixmapItem {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
RegionMapLayoutPixmapItem(RegionMap *rmap, TilemapTileSelector *ts) : SelectablePixmapItem(8, 8, 1, 1) {
|
||||||
|
this->region_map = rmap;
|
||||||
|
this->tile_selector = ts;
|
||||||
|
setAcceptHoverEvents(true);
|
||||||
|
}
|
||||||
|
RegionMap *region_map;
|
||||||
|
TilemapTileSelector *tile_selector;
|
||||||
|
int selectedTile;
|
||||||
|
int highlightedTile;
|
||||||
|
void draw();
|
||||||
|
void select(int, int);
|
||||||
|
void select(int);
|
||||||
|
void highlight(int, int, int);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateSelectedTile();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void mouseEvent(QGraphicsSceneMouseEvent *, RegionMapLayoutPixmapItem *);
|
||||||
|
void hoveredTileChanged(int);
|
||||||
|
void hoveredTileCleared();
|
||||||
|
void selectedTileChanged(int);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void hoverMoveEvent(QGraphicsSceneHoverEvent*);
|
||||||
|
void hoverLeaveEvent(QGraphicsSceneHoverEvent*);
|
||||||
|
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||||
|
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
|
||||||
|
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // REGIONMAPLAYOUTPIXMAPITEM_H
|
36
include/ui/regionmappixmapitem.h
Normal file
36
include/ui/regionmappixmapitem.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef REGIONMAPPIXMAPITEM_H
|
||||||
|
#define REGIONMAPPIXMAPITEM_H
|
||||||
|
|
||||||
|
#include "regionmap.h"
|
||||||
|
#include "tilemaptileselector.h"
|
||||||
|
#include <QGraphicsPixmapItem>
|
||||||
|
|
||||||
|
class RegionMapPixmapItem : public QObject, public QGraphicsPixmapItem {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
RegionMapPixmapItem(RegionMap *rmap, TilemapTileSelector *tile_selector) {
|
||||||
|
this->region_map = rmap;
|
||||||
|
this->tile_selector = tile_selector;
|
||||||
|
setAcceptHoverEvents(true);
|
||||||
|
}
|
||||||
|
RegionMap *region_map;
|
||||||
|
TilemapTileSelector *tile_selector;
|
||||||
|
|
||||||
|
virtual void paint(QGraphicsSceneMouseEvent*);
|
||||||
|
virtual void select(QGraphicsSceneMouseEvent*);
|
||||||
|
virtual void draw();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void mouseEvent(QGraphicsSceneMouseEvent *, RegionMapPixmapItem *);
|
||||||
|
void hoveredRegionMapTileChanged(int x, int y);
|
||||||
|
void hoveredRegionMapTileCleared();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void hoverMoveEvent(QGraphicsSceneHoverEvent*);
|
||||||
|
void hoverLeaveEvent(QGraphicsSceneHoverEvent*);
|
||||||
|
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||||
|
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
|
||||||
|
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // REGIONMAPPIXMAPITEM_H
|
48
include/ui/tilemaptileselector.h
Normal file
48
include/ui/tilemaptileselector.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#ifndef TILEMAPTILESELECTOR_H
|
||||||
|
#define TILEMAPTILESELECTOR_H
|
||||||
|
|
||||||
|
#include "selectablepixmapitem.h"
|
||||||
|
|
||||||
|
class TilemapTileSelector: public SelectablePixmapItem {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
TilemapTileSelector(QPixmap pixmap_): SelectablePixmapItem(8, 8, 1, 1) {
|
||||||
|
this->tilemap = pixmap_;
|
||||||
|
this->setPixmap(this->tilemap);
|
||||||
|
this->numTilesWide = tilemap.width() / 8;
|
||||||
|
this->selectedTile = 0x00;
|
||||||
|
setAcceptHoverEvents(true);
|
||||||
|
}
|
||||||
|
void draw();
|
||||||
|
void select(unsigned tileId);
|
||||||
|
unsigned getSelectedTile();
|
||||||
|
|
||||||
|
int pixelWidth;
|
||||||
|
int pixelHeight;
|
||||||
|
|
||||||
|
unsigned selectedTile = 0;
|
||||||
|
|
||||||
|
QPixmap tilemap;
|
||||||
|
QImage tileImg(unsigned tileId);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||||
|
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
|
||||||
|
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
|
||||||
|
void hoverMoveEvent(QGraphicsSceneHoverEvent*);
|
||||||
|
void hoverLeaveEvent(QGraphicsSceneHoverEvent*);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int numTilesWide;
|
||||||
|
int numTiles;
|
||||||
|
void updateSelectedTile();
|
||||||
|
unsigned getTileId(int x, int y);
|
||||||
|
QPoint getTileIdCoords(unsigned);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void hoveredTileChanged(unsigned);
|
||||||
|
void hoveredTileCleared();
|
||||||
|
void selectedTileChanged(unsigned);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TILEMAPTILESELECTOR_H
|
19
porymap.pro
19
porymap.pro
|
@ -24,15 +24,17 @@ SOURCES += src/core/block.cpp \
|
||||||
src/core/maplayout.cpp \
|
src/core/maplayout.cpp \
|
||||||
src/core/metatile.cpp \
|
src/core/metatile.cpp \
|
||||||
src/core/metatileparser.cpp \
|
src/core/metatileparser.cpp \
|
||||||
src/core/paletteparser.cpp \
|
src/core/paletteutil.cpp \
|
||||||
src/core/parseutil.cpp \
|
src/core/parseutil.cpp \
|
||||||
src/core/tile.cpp \
|
src/core/tile.cpp \
|
||||||
src/core/tileset.cpp \
|
src/core/tileset.cpp \
|
||||||
|
src/core/regionmap.cpp \
|
||||||
src/ui/aboutporymap.cpp \
|
src/ui/aboutporymap.cpp \
|
||||||
src/ui/bordermetatilespixmapitem.cpp \
|
src/ui/bordermetatilespixmapitem.cpp \
|
||||||
src/ui/collisionpixmapitem.cpp \
|
src/ui/collisionpixmapitem.cpp \
|
||||||
src/ui/connectionpixmapitem.cpp \
|
src/ui/connectionpixmapitem.cpp \
|
||||||
src/ui/currentselectedmetatilespixmapitem.cpp \
|
src/ui/currentselectedmetatilespixmapitem.cpp \
|
||||||
|
src/ui/regionmaplayoutpixmapitem.cpp \
|
||||||
src/ui/cursortilerect.cpp \
|
src/ui/cursortilerect.cpp \
|
||||||
src/ui/customattributestable.cpp \
|
src/ui/customattributestable.cpp \
|
||||||
src/ui/eventpropertiesframe.cpp \
|
src/ui/eventpropertiesframe.cpp \
|
||||||
|
@ -40,6 +42,8 @@ SOURCES += src/core/block.cpp \
|
||||||
src/ui/graphicsview.cpp \
|
src/ui/graphicsview.cpp \
|
||||||
src/ui/imageproviders.cpp \
|
src/ui/imageproviders.cpp \
|
||||||
src/ui/mappixmapitem.cpp \
|
src/ui/mappixmapitem.cpp \
|
||||||
|
src/ui/regionmappixmapitem.cpp \
|
||||||
|
src/ui/citymappixmapitem.cpp \
|
||||||
src/ui/mapsceneeventfilter.cpp \
|
src/ui/mapsceneeventfilter.cpp \
|
||||||
src/ui/metatilelayersitem.cpp \
|
src/ui/metatilelayersitem.cpp \
|
||||||
src/ui/metatileselector.cpp \
|
src/ui/metatileselector.cpp \
|
||||||
|
@ -53,6 +57,8 @@ SOURCES += src/core/block.cpp \
|
||||||
src/ui/tileseteditor.cpp \
|
src/ui/tileseteditor.cpp \
|
||||||
src/ui/tileseteditormetatileselector.cpp \
|
src/ui/tileseteditormetatileselector.cpp \
|
||||||
src/ui/tileseteditortileselector.cpp \
|
src/ui/tileseteditortileselector.cpp \
|
||||||
|
src/ui/tilemaptileselector.cpp \
|
||||||
|
src/ui/regionmapeditor.cpp \
|
||||||
src/ui/newmappopup.cpp \
|
src/ui/newmappopup.cpp \
|
||||||
src/config.cpp \
|
src/config.cpp \
|
||||||
src/editor.cpp \
|
src/editor.cpp \
|
||||||
|
@ -75,15 +81,17 @@ HEADERS += include/core/block.h \
|
||||||
include/core/maplayout.h \
|
include/core/maplayout.h \
|
||||||
include/core/metatile.h \
|
include/core/metatile.h \
|
||||||
include/core/metatileparser.h \
|
include/core/metatileparser.h \
|
||||||
include/core/paletteparser.h \
|
include/core/paletteutil.h \
|
||||||
include/core/parseutil.h \
|
include/core/parseutil.h \
|
||||||
include/core/tile.h \
|
include/core/tile.h \
|
||||||
include/core/tileset.h \
|
include/core/tileset.h \
|
||||||
include/ui/aboutporymap.h \
|
include/core/regionmap.h \
|
||||||
|
include/ui/aboutporymap.h \
|
||||||
include/ui/bordermetatilespixmapitem.h \
|
include/ui/bordermetatilespixmapitem.h \
|
||||||
include/ui/collisionpixmapitem.h \
|
include/ui/collisionpixmapitem.h \
|
||||||
include/ui/connectionpixmapitem.h \
|
include/ui/connectionpixmapitem.h \
|
||||||
include/ui/currentselectedmetatilespixmapitem.h \
|
include/ui/currentselectedmetatilespixmapitem.h \
|
||||||
|
include/ui/regionmaplayoutpixmapitem.h \
|
||||||
include/ui/cursortilerect.h \
|
include/ui/cursortilerect.h \
|
||||||
include/ui/customattributestable.h \
|
include/ui/customattributestable.h \
|
||||||
include/ui/eventpropertiesframe.h \
|
include/ui/eventpropertiesframe.h \
|
||||||
|
@ -91,6 +99,8 @@ HEADERS += include/core/block.h \
|
||||||
include/ui/graphicsview.h \
|
include/ui/graphicsview.h \
|
||||||
include/ui/imageproviders.h \
|
include/ui/imageproviders.h \
|
||||||
include/ui/mappixmapitem.h \
|
include/ui/mappixmapitem.h \
|
||||||
|
include/ui/regionmappixmapitem.h \
|
||||||
|
include/ui/citymappixmapitem.h \
|
||||||
include/ui/mapsceneeventfilter.h \
|
include/ui/mapsceneeventfilter.h \
|
||||||
include/ui/metatilelayersitem.h \
|
include/ui/metatilelayersitem.h \
|
||||||
include/ui/metatileselector.h \
|
include/ui/metatileselector.h \
|
||||||
|
@ -104,6 +114,8 @@ HEADERS += include/core/block.h \
|
||||||
include/ui/tileseteditor.h \
|
include/ui/tileseteditor.h \
|
||||||
include/ui/tileseteditormetatileselector.h \
|
include/ui/tileseteditormetatileselector.h \
|
||||||
include/ui/tileseteditortileselector.h \
|
include/ui/tileseteditortileselector.h \
|
||||||
|
include/ui/tilemaptileselector.h \
|
||||||
|
include/ui/regionmapeditor.h \
|
||||||
include/ui/newmappopup.h \
|
include/ui/newmappopup.h \
|
||||||
include/config.h \
|
include/config.h \
|
||||||
include/editor.h \
|
include/editor.h \
|
||||||
|
@ -117,6 +129,7 @@ FORMS += forms/mainwindow.ui \
|
||||||
forms/eventpropertiesframe.ui \
|
forms/eventpropertiesframe.ui \
|
||||||
forms/tileseteditor.ui \
|
forms/tileseteditor.ui \
|
||||||
forms/paletteeditor.ui \
|
forms/paletteeditor.ui \
|
||||||
|
forms/regionmapeditor.ui \
|
||||||
forms/newmappopup.ui \
|
forms/newmappopup.ui \
|
||||||
forms/aboutporymap.ui \
|
forms/aboutporymap.ui \
|
||||||
forms/newtilesetdialog.ui
|
forms/newtilesetdialog.ui
|
||||||
|
|
|
@ -156,6 +156,17 @@ void PorymapConfig::parseConfigKeyValue(QString key, QString value) {
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
logWarn(QString("Invalid config value for show_cursor_tile: '%1'. Must be 0 or 1.").arg(value));
|
logWarn(QString("Invalid config value for show_cursor_tile: '%1'. Must be 0 or 1.").arg(value));
|
||||||
}
|
}
|
||||||
|
} else if (key == "region_map_dimensions") {
|
||||||
|
bool ok1, ok2;
|
||||||
|
QStringList dims = value.split("x");
|
||||||
|
int w = dims[0].toInt(&ok1);
|
||||||
|
int h = dims[1].toInt(&ok2);
|
||||||
|
if (!ok1 || !ok2) {
|
||||||
|
logWarn("Cannot parse region map dimensions. Using default values instead.");
|
||||||
|
this->regionMapDimensions = QSize(32, 20);
|
||||||
|
} else {
|
||||||
|
this->regionMapDimensions = QSize(w, h);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
|
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
|
||||||
}
|
}
|
||||||
|
@ -176,6 +187,8 @@ QMap<QString, QString> PorymapConfig::getKeyValueMap() {
|
||||||
map.insert("metatiles_zoom", QString("%1").arg(this->metatilesZoom));
|
map.insert("metatiles_zoom", QString("%1").arg(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("region_map_dimensions", QString("%1x%2").arg(this->regionMapDimensions.width())
|
||||||
|
.arg(this->regionMapDimensions.height()));
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,6 +259,10 @@ void PorymapConfig::setShowCursorTile(bool enabled) {
|
||||||
this->save();
|
this->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PorymapConfig::setRegionMapDimensions(int width, int height) {
|
||||||
|
this->regionMapDimensions = QSize(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
QString PorymapConfig::getRecentProject() {
|
QString PorymapConfig::getRecentProject() {
|
||||||
return this->recentProject;
|
return this->recentProject;
|
||||||
}
|
}
|
||||||
|
@ -290,6 +307,10 @@ bool PorymapConfig::getShowCursorTile() {
|
||||||
return this->showCursorTile;
|
return this->showCursorTile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSize PorymapConfig::getRegionMapDimensions() {
|
||||||
|
return this->regionMapDimensions;
|
||||||
|
}
|
||||||
|
|
||||||
const QMap<BaseGameVersion, QString> baseGameVersionMap = {
|
const QMap<BaseGameVersion, QString> baseGameVersionMap = {
|
||||||
{BaseGameVersion::pokeruby, "pokeruby"},
|
{BaseGameVersion::pokeruby, "pokeruby"},
|
||||||
{BaseGameVersion::pokeemerald, "pokeemerald"},
|
{BaseGameVersion::pokeemerald, "pokeemerald"},
|
||||||
|
|
|
@ -9,3 +9,18 @@ HistoryItem::HistoryItem(Blockdata *metatiles, int layoutWidth, int layoutHeight
|
||||||
HistoryItem::~HistoryItem() {
|
HistoryItem::~HistoryItem() {
|
||||||
if (this->metatiles) delete this->metatiles;
|
if (this->metatiles) delete this->metatiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RegionMapHistoryItem::RegionMapHistoryItem(int which, QVector<uint8_t> tiles, QString cityMap) {
|
||||||
|
this->which = which;
|
||||||
|
this->tiles = tiles;
|
||||||
|
this->cityMap = cityMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegionMapHistoryItem::RegionMapHistoryItem(int which, QVector<uint8_t> tiles, int width, int height) {
|
||||||
|
this->which = which;
|
||||||
|
this->tiles = tiles;
|
||||||
|
this->mapWidth = width;
|
||||||
|
this->mapHeight = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegionMapHistoryItem::~RegionMapHistoryItem() {}
|
||||||
|
|
|
@ -341,7 +341,6 @@ void Map::_floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Map::undo() {
|
void Map::undo() {
|
||||||
HistoryItem *commit = metatileHistory.back();
|
HistoryItem *commit = metatileHistory.back();
|
||||||
if (!commit)
|
if (!commit)
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
#include "paletteparser.h"
|
#include "paletteutil.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
|
|
||||||
PaletteParser::PaletteParser()
|
PaletteUtil::PaletteUtil()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QRgb> PaletteParser::parse(QString filepath, bool *error) {
|
QList<QRgb> PaletteUtil::parse(QString filepath, bool *error) {
|
||||||
QFileInfo info(filepath);
|
QFileInfo info(filepath);
|
||||||
QString extension = info.completeSuffix();
|
QString extension = info.completeSuffix();
|
||||||
if (extension.isNull()) {
|
if (extension.isNull()) {
|
||||||
|
@ -34,7 +34,7 @@ QList<QRgb> PaletteParser::parse(QString filepath, bool *error) {
|
||||||
return QList<QRgb>();
|
return QList<QRgb>();
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QRgb> PaletteParser::parsePal(QString filepath, bool *error) {
|
QList<QRgb> PaletteUtil::parsePal(QString filepath, bool *error) {
|
||||||
QFile file(filepath);
|
QFile file(filepath);
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
*error = true;
|
*error = true;
|
||||||
|
@ -53,7 +53,7 @@ QList<QRgb> PaletteParser::parsePal(QString filepath, bool *error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QRgb> PaletteParser::parseJASC(QString filepath, bool *error) {
|
QList<QRgb> PaletteUtil::parseJASC(QString filepath, bool *error) {
|
||||||
QFile file(filepath);
|
QFile file(filepath);
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
*error = true;
|
*error = true;
|
||||||
|
@ -120,7 +120,7 @@ QList<QRgb> PaletteParser::parseJASC(QString filepath, bool *error) {
|
||||||
return palette;
|
return palette;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QRgb> PaletteParser::parseAdvanceMapPal(QString filepath, bool *error) {
|
QList<QRgb> PaletteUtil::parseAdvanceMapPal(QString filepath, bool *error) {
|
||||||
QFile file(filepath);
|
QFile file(filepath);
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
*error = true;
|
*error = true;
|
||||||
|
@ -152,7 +152,7 @@ QList<QRgb> PaletteParser::parseAdvanceMapPal(QString filepath, bool *error) {
|
||||||
return palette;
|
return palette;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QRgb> PaletteParser::parseAdobeColorTable(QString filepath, bool *error) {
|
QList<QRgb> PaletteUtil::parseAdobeColorTable(QString filepath, bool *error) {
|
||||||
QFile file(filepath);
|
QFile file(filepath);
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
*error = true;
|
*error = true;
|
||||||
|
@ -184,7 +184,7 @@ QList<QRgb> PaletteParser::parseAdobeColorTable(QString filepath, bool *error) {
|
||||||
return palette;
|
return palette;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QRgb> PaletteParser::parseTileLayerPro(QString filepath, bool *error) {
|
QList<QRgb> PaletteUtil::parseTileLayerPro(QString filepath, bool *error) {
|
||||||
QFile file(filepath);
|
QFile file(filepath);
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
*error = true;
|
*error = true;
|
||||||
|
@ -222,7 +222,7 @@ QList<QRgb> PaletteParser::parseTileLayerPro(QString filepath, bool *error) {
|
||||||
return palette;
|
return palette;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QRgb> PaletteParser::parseAdvancePaletteEditor(QString filepath, bool *error) {
|
QList<QRgb> PaletteUtil::parseAdvancePaletteEditor(QString filepath, bool *error) {
|
||||||
QFile file(filepath);
|
QFile file(filepath);
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
*error = true;
|
*error = true;
|
||||||
|
@ -267,7 +267,35 @@ QList<QRgb> PaletteParser::parseAdvancePaletteEditor(QString filepath, bool *err
|
||||||
return palette;
|
return palette;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PaletteParser::clampColorValue(int value) {
|
void PaletteUtil::writeJASC(QString filepath, QVector<QRgb> palette, int offset, int nColors) {
|
||||||
|
if (!nColors) {
|
||||||
|
logWarn(QString("Cannot save a palette with no colors."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (offset > palette.size() || offset + nColors > palette.size()) {
|
||||||
|
logWarn("Palette offset out of range for color table.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString text = "JASC-PAL\r\n0100\r\n";
|
||||||
|
text += QString::number(nColors) + "\r\n";
|
||||||
|
|
||||||
|
for (int i = offset; i < offset + nColors; i++) {
|
||||||
|
QRgb color = palette.at(i);
|
||||||
|
text += QString::number(qRed(color)) + " "
|
||||||
|
+ QString::number(qGreen(color)) + " "
|
||||||
|
+ QString::number(qBlue(color)) + "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile file(filepath);
|
||||||
|
if (file.open(QIODevice::WriteOnly)) {
|
||||||
|
file.write(text.toUtf8());
|
||||||
|
} else {
|
||||||
|
logWarn(QString("Could not write to file '%1': ").arg(filepath) + file.errorString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int PaletteUtil::clampColorValue(int value) {
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
value = 0;
|
value = 0;
|
||||||
}
|
}
|
361
src/core/regionmap.cpp
Normal file
361
src/core/regionmap.cpp
Normal file
|
@ -0,0 +1,361 @@
|
||||||
|
#include "regionmap.h"
|
||||||
|
#include "paletteutil.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QImage>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
void RegionMap::init(Project *pro) {
|
||||||
|
QString path = pro->root;
|
||||||
|
this->project = pro;
|
||||||
|
|
||||||
|
QSize dimensions = porymapConfig.getRegionMapDimensions();
|
||||||
|
img_width_ = dimensions.width();
|
||||||
|
img_height_ = dimensions.height();
|
||||||
|
|
||||||
|
layout_width_ = img_width_ - this->padLeft - this->padRight;
|
||||||
|
layout_height_ = img_height_ - this->padTop - this->padBottom;
|
||||||
|
|
||||||
|
region_map_bin_path = path + "/graphics/pokenav/region_map_map.bin";
|
||||||
|
region_map_png_path = path + "/graphics/pokenav/region_map.png";
|
||||||
|
region_map_entries_path = path + "/src/data/region_map/region_map_entries.h";
|
||||||
|
region_map_layout_bin_path = path + "/graphics/pokenav/region_map_section_layout.bin";
|
||||||
|
city_map_tiles_path = path + "/graphics/pokenav/zoom_tiles.png";
|
||||||
|
|
||||||
|
readBkgImgBin();
|
||||||
|
readLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMap::save() {
|
||||||
|
logInfo("Saving region map data.");
|
||||||
|
saveTileImages();
|
||||||
|
saveBkgImgBin();
|
||||||
|
saveLayout();
|
||||||
|
porymapConfig.setRegionMapDimensions(this->img_width_, this->img_height_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMap::saveTileImages() {
|
||||||
|
QFile backgroundTileFile(pngPath());
|
||||||
|
if (backgroundTileFile.open(QIODevice::ReadOnly)) {
|
||||||
|
QByteArray imageData = backgroundTileFile.readAll();
|
||||||
|
QImage pngImage = QImage::fromData(imageData);
|
||||||
|
this->region_map_png_path = project->root + "/graphics/pokenav/region_map.png";
|
||||||
|
pngImage.save(pngPath());
|
||||||
|
|
||||||
|
PaletteUtil parser;
|
||||||
|
parser.writeJASC(project->root + "/graphics/pokenav/region_map.pal", pngImage.colorTable(), 0x70, 0x20);
|
||||||
|
}
|
||||||
|
QFile cityTileFile(cityTilesPath());
|
||||||
|
if (cityTileFile.open(QIODevice::ReadOnly)) {
|
||||||
|
QByteArray imageData = cityTileFile.readAll();
|
||||||
|
QImage cityTilesImage = QImage::fromData(imageData);
|
||||||
|
this->city_map_tiles_path = project->root + "/graphics/pokenav/zoom_tiles.png";
|
||||||
|
cityTilesImage.save(cityTilesPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMap::readBkgImgBin() {
|
||||||
|
QFile binFile(region_map_bin_path);
|
||||||
|
if (!binFile.open(QIODevice::ReadOnly)) return;
|
||||||
|
|
||||||
|
QByteArray mapBinData = binFile.readAll();
|
||||||
|
binFile.close();
|
||||||
|
|
||||||
|
if (mapBinData.size() < img_height_ * img_width_) {
|
||||||
|
logError(QString("The region map tilemap at %1 is too small.").arg(region_map_bin_path));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int m = 0; m < img_height_; m++) {
|
||||||
|
for (int n = 0; n < img_width_; n++) {
|
||||||
|
RegionMapSquare square;
|
||||||
|
square.tile_img_id = mapBinData.at(n + m * img_width_ * 2);
|
||||||
|
map_squares.append(square);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMap::saveBkgImgBin() {
|
||||||
|
QByteArray data(pow(img_width_ * 2, 2),0);
|
||||||
|
|
||||||
|
for (int m = 0; m < img_height_; m++) {
|
||||||
|
for (int n = 0; n < img_width_; n++) {
|
||||||
|
data[n + m * img_width_ * 2] = map_squares[n + m * img_width_].tile_img_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile file(region_map_bin_path);
|
||||||
|
if (!file.open(QIODevice::WriteOnly)) return;
|
||||||
|
file.write(data);
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMap::readLayout() {
|
||||||
|
QFile file(region_map_entries_path);
|
||||||
|
if (!file.open(QIODevice::ReadOnly)) return;
|
||||||
|
|
||||||
|
QString line;
|
||||||
|
|
||||||
|
QMap<QString, QString> *qmap = new QMap<QString, QString>;
|
||||||
|
|
||||||
|
QTextStream in(&file);
|
||||||
|
in.setCodec("UTF-8");
|
||||||
|
while (!in.atEnd()) {
|
||||||
|
line = in.readLine();
|
||||||
|
if (line.startsWith("static const u8")) {
|
||||||
|
QRegularExpression reBefore("sMapName_(.*)\\[");
|
||||||
|
QRegularExpression reAfter("_\\(\"(.*)\"");
|
||||||
|
QString const_name = reBefore.match(line).captured(1);
|
||||||
|
QString full_name = reAfter.match(line).captured(1);
|
||||||
|
sMapNames.append(const_name);
|
||||||
|
sMapNamesMap.insert(const_name, full_name);
|
||||||
|
} else if (line.contains("MAPSEC")) {
|
||||||
|
QRegularExpression reBefore("\\[(.*)\\]");
|
||||||
|
QRegularExpression reAfter("{(.*)}");
|
||||||
|
QStringList entry = reAfter.match(line).captured(1).remove(" ").split(",");
|
||||||
|
QString mapsec = reBefore.match(line).captured(1);
|
||||||
|
QString insertion = entry[4].remove("sMapName_");
|
||||||
|
qmap->insert(mapsec, sMapNamesMap.value(insertion));
|
||||||
|
mapSecToMapEntry[mapsec] = {
|
||||||
|
// x y width height name
|
||||||
|
entry[0].toInt(), entry[1].toInt(), entry[2].toInt(), entry[3].toInt(), insertion
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
project->mapSecToMapHoverName = qmap;
|
||||||
|
|
||||||
|
QFile binFile(region_map_layout_bin_path);
|
||||||
|
if (!binFile.open(QIODevice::ReadOnly)) return;
|
||||||
|
QByteArray mapBinData = binFile.readAll();
|
||||||
|
binFile.close();
|
||||||
|
|
||||||
|
for (int y = 0; y < layout_height_; y++) {
|
||||||
|
for (int x = 0; x < layout_width_; x++) {
|
||||||
|
int i = img_index_(x,y);
|
||||||
|
uint8_t id = static_cast<uint8_t>(mapBinData.at(layout_index_(x,y)));
|
||||||
|
map_squares[i].secid = id;
|
||||||
|
QString secname = project->mapSectionValueToName.value(id);
|
||||||
|
if (secname != "MAPSEC_NONE") map_squares[i].has_map = true;
|
||||||
|
map_squares[i].mapsec = secname;
|
||||||
|
map_squares[i].map_name = sMapNamesMap.value(mapSecToMapEntry.value(secname).name);
|
||||||
|
map_squares[i].x = x;
|
||||||
|
map_squares[i].y = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMap::saveLayout() {
|
||||||
|
QString entries_text;
|
||||||
|
QString layout_text;
|
||||||
|
|
||||||
|
entries_text += "#ifndef GUARD_DATA_REGION_MAP_REGION_MAP_ENTRIES_H\n";
|
||||||
|
entries_text += "#define GUARD_DATA_REGION_MAP_REGION_MAP_ENTRIES_H\n\n";
|
||||||
|
|
||||||
|
for (auto sName : sMapNames) {
|
||||||
|
entries_text += "static const u8 sMapName_" + sName + "[] = _(\"" + sMapNamesMap.value(sName) + "\");\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
entries_text += "\nconst struct RegionMapLocation gRegionMapEntries[] = {\n";
|
||||||
|
|
||||||
|
for (auto sec : project->mapSectionNameToValue.keys()) {
|
||||||
|
if (!mapSecToMapEntry.contains(sec)) continue;
|
||||||
|
struct RegionMapEntry entry = mapSecToMapEntry.value(sec);
|
||||||
|
entries_text += " [" + sec + "] = {" + QString::number(entry.x) + ", " + QString::number(entry.y) + ", "
|
||||||
|
+ QString::number(entry.width) + ", " + QString::number(entry.height) + ", sMapName_" + entry.name + "},\n";
|
||||||
|
}
|
||||||
|
entries_text += "};\n\n#endif // GUARD_DATA_REGION_MAP_REGION_MAP_ENTRIES_H\n";
|
||||||
|
|
||||||
|
project->saveTextFile(region_map_entries_path, entries_text);
|
||||||
|
|
||||||
|
QByteArray data;
|
||||||
|
for (int m = 0; m < layout_height_; m++) {
|
||||||
|
for (int n = 0; n < layout_width_; n++) {
|
||||||
|
int i = img_index_(n,m);
|
||||||
|
data.append(map_squares[i].secid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QFile bfile(region_map_layout_bin_path);
|
||||||
|
if (!bfile.open(QIODevice::WriteOnly)) return;
|
||||||
|
bfile.write(data);
|
||||||
|
bfile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMap::saveOptions(int id, QString sec, QString name, int x, int y) {
|
||||||
|
resetSquare(id);
|
||||||
|
int index = getMapSquareIndex(x + this->padLeft, y + this->padTop);
|
||||||
|
if (!sec.isEmpty()) {
|
||||||
|
// Validate the input section name.
|
||||||
|
if (!project->mapSectionNameToValue.contains(sec)) {
|
||||||
|
sec = "MAPSEC_NONE";
|
||||||
|
name = QString();
|
||||||
|
}
|
||||||
|
this->map_squares[index].has_map = sec == "MAPSEC_NONE" ? false : true;
|
||||||
|
this->map_squares[index].secid = static_cast<uint8_t>(project->mapSectionNameToValue.value(sec));
|
||||||
|
this->map_squares[index].mapsec = sec;
|
||||||
|
if (!name.isEmpty()) {
|
||||||
|
this->map_squares[index].map_name = name;
|
||||||
|
this->project->mapSecToMapHoverName->insert(sec, name);
|
||||||
|
QString sName = fix_case(sec);
|
||||||
|
sMapNamesMap.insert(sName, name);
|
||||||
|
if (!mapSecToMapEntry.keys().contains(sec)) {
|
||||||
|
sMapNames.append(sName);
|
||||||
|
struct RegionMapEntry entry = {x, y, 1, 1, sName};
|
||||||
|
mapSecToMapEntry.insert(sec, entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->map_squares[index].x = x;
|
||||||
|
this->map_squares[index].y = y;
|
||||||
|
this->map_squares[index].duplicated = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMap::resetSquare(int index) {
|
||||||
|
this->map_squares[index].mapsec = "MAPSEC_NONE";
|
||||||
|
this->map_squares[index].map_name = QString();
|
||||||
|
this->map_squares[index].has_map = false;
|
||||||
|
this->map_squares[index].secid = static_cast<uint8_t>(project->mapSectionNameToValue.value("MAPSEC_NONE"));
|
||||||
|
this->map_squares[index].has_city_map = false;
|
||||||
|
this->map_squares[index].city_map_name = QString();
|
||||||
|
this->map_squares[index].duplicated = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMap::clearLayout() {
|
||||||
|
for (int i = 0; i < map_squares.size(); i++)
|
||||||
|
resetSquare(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMap::clearImage() {
|
||||||
|
for (int i = 0; i < map_squares.size(); i++)
|
||||||
|
this->map_squares[i].tile_img_id = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMap::replaceSectionId(unsigned oldId, unsigned newId) {
|
||||||
|
for (auto &square : map_squares) {
|
||||||
|
if (square.secid == oldId) {
|
||||||
|
square.has_map = false;
|
||||||
|
square.secid = newId;
|
||||||
|
QString secname = project->mapSectionValueToName.value(newId);
|
||||||
|
if (secname != "MAPSEC_NONE") square.has_map = true;
|
||||||
|
square.mapsec = secname;
|
||||||
|
square.map_name = sMapNamesMap.value(mapSecToMapEntry.value(secname).name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMap::resize(int newWidth, int newHeight) {
|
||||||
|
QVector<RegionMapSquare> new_squares;
|
||||||
|
|
||||||
|
for (int y = 0; y < newHeight; y++) {
|
||||||
|
for (int x = 0; x < newWidth; x++) {
|
||||||
|
RegionMapSquare square;
|
||||||
|
if (x < img_width_ && y < img_height_) {
|
||||||
|
square = map_squares[getMapSquareIndex(x, y)];
|
||||||
|
} else if (x < newWidth - this->padRight && y < newHeight - this->padBottom) {
|
||||||
|
square.tile_img_id = 0;
|
||||||
|
square.x = x;
|
||||||
|
square.y = y;
|
||||||
|
square.mapsec = "MAPSEC_NONE";
|
||||||
|
} else {
|
||||||
|
square.tile_img_id = 0;
|
||||||
|
}
|
||||||
|
new_squares.append(square);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->map_squares = new_squares;
|
||||||
|
this->img_width_ = newWidth;
|
||||||
|
this->img_height_ = newHeight;
|
||||||
|
this->layout_width_ = newWidth - this->padLeft - this->padRight;
|
||||||
|
this->layout_height_ = newHeight - this->padTop - this->padBottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<uint8_t> RegionMap::getTiles() {
|
||||||
|
QVector<uint8_t> tileIds;
|
||||||
|
for (auto square : map_squares) {
|
||||||
|
tileIds.append(square.tile_img_id);
|
||||||
|
}
|
||||||
|
return tileIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMap::setTiles(QVector<uint8_t> tileIds) {
|
||||||
|
if (tileIds.size() != map_squares.size()) return;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (uint8_t tileId : tileIds) {
|
||||||
|
map_squares[i].tile_img_id = tileId;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Layout coords to image index.
|
||||||
|
int RegionMap::img_index_(int x, int y) {
|
||||||
|
return ((x + this->padLeft) + (y + this->padTop) * img_width_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Layout coords to layout index.
|
||||||
|
int RegionMap::layout_index_(int x, int y) {
|
||||||
|
return (x + y * layout_width_);
|
||||||
|
}
|
||||||
|
|
||||||
|
int RegionMap::width() {
|
||||||
|
return this->img_width_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RegionMap::height() {
|
||||||
|
return this->img_height_;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize RegionMap::imgSize() {
|
||||||
|
return QSize(img_width_ * 8, img_height_ * 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned RegionMap::getTileId(int x, int y) {
|
||||||
|
return map_squares.at(x + y * img_width_).tile_img_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString RegionMap::pngPath() {
|
||||||
|
return this->region_map_png_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMap::setTemporaryPngPath(QString path) {
|
||||||
|
this->region_map_png_path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString RegionMap::cityTilesPath() {
|
||||||
|
return this->city_map_tiles_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMap::setTemporaryCityTilesPath(QString path) {
|
||||||
|
this->city_map_tiles_path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// From x, y of image.
|
||||||
|
int RegionMap::getMapSquareIndex(int x, int y) {
|
||||||
|
int index = (x + y * img_width_);
|
||||||
|
return index < map_squares.length() ? index : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For turning a MAPSEC_NAME into a unique identifier sMapName-style variable.
|
||||||
|
// CAPS_WITH_UNDERSCORE to CamelCase
|
||||||
|
QString RegionMap::fix_case(QString caps) {
|
||||||
|
bool big = true;
|
||||||
|
QString camel;
|
||||||
|
|
||||||
|
for (auto ch : caps.remove(QRegularExpression("({.*})")).remove("MAPSEC")) {
|
||||||
|
if (ch == '_' || ch == ' ') {
|
||||||
|
big = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (big) {
|
||||||
|
camel += ch.toUpper();
|
||||||
|
big = false;
|
||||||
|
}
|
||||||
|
else camel += ch.toLower();
|
||||||
|
}
|
||||||
|
return camel;
|
||||||
|
}
|
|
@ -8,6 +8,7 @@
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
|
#include <QDir>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
static bool selectingEvent = false;
|
static bool selectingEvent = false;
|
||||||
|
@ -1283,6 +1284,5 @@ void Editor::objectsView_onMousePress(QMouseEvent *event) {
|
||||||
selected_events->append(first);
|
selected_events->append(first);
|
||||||
updateSelectedEvents();
|
updateSelectedEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
selectingEvent = false;
|
selectingEvent = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -465,7 +465,7 @@ void MainWindow::displayMapProperties() {
|
||||||
ui->comboBox_Song->addItems(songs);
|
ui->comboBox_Song->addItems(songs);
|
||||||
ui->comboBox_Song->setCurrentText(map->song);
|
ui->comboBox_Song->setCurrentText(map->song);
|
||||||
|
|
||||||
ui->comboBox_Location->addItems(*project->regionMapSections);
|
ui->comboBox_Location->addItems(project->mapSectionValueToName.values());
|
||||||
ui->comboBox_Location->setCurrentText(map->location);
|
ui->comboBox_Location->setCurrentText(map->location);
|
||||||
|
|
||||||
QMap<QString, QStringList> tilesets = project->getTilesetLabels();
|
QMap<QString, QStringList> tilesets = project->getTilesetLabels();
|
||||||
|
@ -658,8 +658,8 @@ void MainWindow::sortMapList() {
|
||||||
case MapSortOrder::Area:
|
case MapSortOrder::Area:
|
||||||
{
|
{
|
||||||
QMap<QString, int> mapsecToGroupNum;
|
QMap<QString, int> mapsecToGroupNum;
|
||||||
for (int i = 0; i < project->regionMapSections->length(); i++) {
|
for (int i = 0; i < project->mapSectionNameToValue.size(); i++) {
|
||||||
QString mapsec_name = project->regionMapSections->value(i);
|
QString mapsec_name = project->mapSectionValueToName.value(i);
|
||||||
QStandardItem *mapsec = new QStandardItem;
|
QStandardItem *mapsec = new QStandardItem;
|
||||||
mapsec->setText(mapsec_name);
|
mapsec->setText(mapsec_name);
|
||||||
mapsec->setIcon(folderIcon);
|
mapsec->setIcon(folderIcon);
|
||||||
|
@ -2123,6 +2123,24 @@ void MainWindow::on_horizontalSlider_MetatileZoom_valueChanged(int value) {
|
||||||
currentMetatilesSelectionChanged();
|
currentMetatilesSelectionChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionRegion_Map_Editor_triggered() {
|
||||||
|
if (!this->regionMapEditor) {
|
||||||
|
this->regionMapEditor = new RegionMapEditor(this, this->editor->project);
|
||||||
|
this->regionMapEditor->loadRegionMapData();
|
||||||
|
this->regionMapEditor->loadCityMaps();
|
||||||
|
connect(this->regionMapEditor, &QObject::destroyed, [=](QObject *) { this->regionMapEditor = nullptr; });
|
||||||
|
this->regionMapEditor->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->regionMapEditor->isVisible()) {
|
||||||
|
this->regionMapEditor->show();
|
||||||
|
} else if (this->regionMapEditor->isMinimized()) {
|
||||||
|
this->regionMapEditor->showNormal();
|
||||||
|
} else {
|
||||||
|
this->regionMapEditor->activateWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::closeEvent(QCloseEvent *event) {
|
void MainWindow::closeEvent(QCloseEvent *event) {
|
||||||
porymapConfig.setGeometry(
|
porymapConfig.setGeometry(
|
||||||
this->saveGeometry(),
|
this->saveGeometry(),
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "historyitem.h"
|
#include "historyitem.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "parseutil.h"
|
#include "parseutil.h"
|
||||||
|
#include "paletteutil.h"
|
||||||
#include "tile.h"
|
#include "tile.h"
|
||||||
#include "tileset.h"
|
#include "tileset.h"
|
||||||
|
|
||||||
|
@ -30,7 +31,6 @@ Project::Project()
|
||||||
groupNames = new QStringList;
|
groupNames = new QStringList;
|
||||||
map_groups = new QMap<QString, int>;
|
map_groups = new QMap<QString, int>;
|
||||||
mapNames = new QStringList;
|
mapNames = new QStringList;
|
||||||
regionMapSections = new QStringList;
|
|
||||||
itemNames = new QStringList;
|
itemNames = new QStringList;
|
||||||
flagNames = new QStringList;
|
flagNames = new QStringList;
|
||||||
varNames = new QStringList;
|
varNames = new QStringList;
|
||||||
|
@ -720,20 +720,10 @@ void Project::saveTilesetTilesImage(Tileset *tileset) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Project::saveTilesetPalettes(Tileset *tileset, bool primary) {
|
void Project::saveTilesetPalettes(Tileset *tileset, bool primary) {
|
||||||
|
PaletteUtil parser;
|
||||||
for (int i = 0; i < Project::getNumPalettesTotal(); i++) {
|
for (int i = 0; i < Project::getNumPalettesTotal(); i++) {
|
||||||
QString filepath = tileset->palettePaths.at(i);
|
QString filepath = tileset->palettePaths.at(i);
|
||||||
QString content = "JASC-PAL\r\n";
|
parser.writeJASC(filepath, tileset->palettes->at(i).toVector(), 0, 16);
|
||||||
content += "0100\r\n";
|
|
||||||
content += "16\r\n";
|
|
||||||
for (int j = 0; j < 16; j++) {
|
|
||||||
QRgb color = tileset->palettes->at(i).at(j);
|
|
||||||
content += QString("%1 %2 %3\r\n")
|
|
||||||
.arg(qRed(color))
|
|
||||||
.arg(qGreen(color))
|
|
||||||
.arg(qBlue(color));
|
|
||||||
}
|
|
||||||
|
|
||||||
saveTextFile(filepath, content);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1507,8 +1497,18 @@ void Project::readTilesetProperties() {
|
||||||
|
|
||||||
void Project::readRegionMapSections() {
|
void Project::readRegionMapSections() {
|
||||||
QString filepath = root + "/include/constants/region_map_sections.h";
|
QString filepath = root + "/include/constants/region_map_sections.h";
|
||||||
QStringList prefixes = (QStringList() << "MAPSEC_");
|
this->mapSectionNameToValue.clear();
|
||||||
readCDefinesSorted(filepath, prefixes, regionMapSections);
|
this->mapSectionValueToName.clear();
|
||||||
|
QString text = readTextFile(filepath);
|
||||||
|
if (!text.isNull()) {
|
||||||
|
QStringList prefixes = (QStringList() << "MAPSEC_");
|
||||||
|
this->mapSectionNameToValue = readCDefines(text, prefixes);
|
||||||
|
for (QString defineName : this->mapSectionNameToValue.keys()) {
|
||||||
|
this->mapSectionValueToName.insert(this->mapSectionNameToValue[defineName], defineName);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logError(QString("Failed to read C defines file: '%1'").arg(filepath));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Project::readItemNames() {
|
void Project::readItemNames() {
|
||||||
|
|
111
src/ui/citymappixmapitem.cpp
Normal file
111
src/ui/citymappixmapitem.cpp
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
#include "citymappixmapitem.h"
|
||||||
|
#include "imageproviders.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
void CityMapPixmapItem::init() {
|
||||||
|
width_ = 10;
|
||||||
|
height_ = 10;
|
||||||
|
|
||||||
|
QFile binFile(file);
|
||||||
|
if (!binFile.open(QIODevice::ReadOnly)) return;
|
||||||
|
|
||||||
|
data = binFile.readAll();
|
||||||
|
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokeruby) {
|
||||||
|
for (int i = 0; i < data.size(); i++)
|
||||||
|
data[i] = data[i] ^ 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
binFile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CityMapPixmapItem::draw() {
|
||||||
|
QImage image(width_ * 8, height_ * 8, QImage::Format_RGBA8888);
|
||||||
|
|
||||||
|
QPainter painter(&image);
|
||||||
|
for (int i = 0; i < data.size() / 2; i++) {
|
||||||
|
QImage img = this->tile_selector->tileImg(data[i * 2]);// need to skip every other tile
|
||||||
|
int x = i % width_;
|
||||||
|
int y = i / width_;
|
||||||
|
QPoint pos = QPoint(x * 8, y * 8);
|
||||||
|
painter.drawImage(pos, img);
|
||||||
|
}
|
||||||
|
painter.end();
|
||||||
|
|
||||||
|
this->setPixmap(QPixmap::fromImage(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CityMapPixmapItem::save() {
|
||||||
|
QFile binFile(file);
|
||||||
|
if (!binFile.open(QIODevice::WriteOnly)) {
|
||||||
|
logError(QString("Cannot save city map tilemap to %1.").arg(file));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokeruby) {
|
||||||
|
for (int i = 0; i < data.size(); i++)
|
||||||
|
data[i] = data[i] ^ 0x80;
|
||||||
|
}
|
||||||
|
binFile.write(data);
|
||||||
|
binFile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CityMapPixmapItem::paint(QGraphicsSceneMouseEvent *event) {
|
||||||
|
QPointF pos = event->pos();
|
||||||
|
int x = static_cast<int>(pos.x()) / 8;
|
||||||
|
int y = static_cast<int>(pos.y()) / 8;
|
||||||
|
int index = getIndexAt(x, y);
|
||||||
|
data[index] = static_cast<uint8_t>(this->tile_selector->selectedTile);
|
||||||
|
|
||||||
|
draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CityMapPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||||
|
emit mouseEvent(event, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CityMapPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
|
||||||
|
QPointF pos = event->pos();
|
||||||
|
int x = static_cast<int>(pos.x()) / 8;
|
||||||
|
int y = static_cast<int>(pos.y()) / 8;
|
||||||
|
if (x < width_ && x >= 0
|
||||||
|
&& y < height_ && y >= 0) {
|
||||||
|
emit this->hoveredRegionMapTileChanged(x, y);
|
||||||
|
emit mouseEvent(event, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CityMapPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
|
||||||
|
emit mouseEvent(event, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<uint8_t> CityMapPixmapItem::getTiles() {
|
||||||
|
QVector<uint8_t> tiles;
|
||||||
|
for (auto tile : data) {
|
||||||
|
tiles.append(tile);
|
||||||
|
}
|
||||||
|
return tiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CityMapPixmapItem::setTiles(QVector<uint8_t> tiles) {
|
||||||
|
QByteArray newData;
|
||||||
|
for (auto tile : tiles) {
|
||||||
|
newData.append(tile);
|
||||||
|
}
|
||||||
|
this->data = newData;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CityMapPixmapItem::getIndexAt(int x, int y) {
|
||||||
|
return 2 * (x + y * this->width_);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CityMapPixmapItem::width() {
|
||||||
|
return this->width_;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CityMapPixmapItem::height() {
|
||||||
|
return this->height_;
|
||||||
|
}
|
|
@ -70,7 +70,7 @@ void NewMapPopup::setDefaultValues(int groupNum, QString mapSec) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->comboBox_NewMap_Type->addItems(*project->mapTypes);
|
ui->comboBox_NewMap_Type->addItems(*project->mapTypes);
|
||||||
ui->comboBox_NewMap_Location->addItems(*project->regionMapSections);
|
ui->comboBox_NewMap_Location->addItems(project->mapSectionValueToName.values());
|
||||||
if (!mapSec.isEmpty()) ui->comboBox_NewMap_Location->setCurrentText(mapSec);
|
if (!mapSec.isEmpty()) ui->comboBox_NewMap_Location->setCurrentText(mapSec);
|
||||||
|
|
||||||
ui->frame_NewMap_Options->setEnabled(true);
|
ui->frame_NewMap_Options->setEnabled(true);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#include "paletteeditor.h"
|
#include "paletteeditor.h"
|
||||||
#include "ui_paletteeditor.h"
|
#include "ui_paletteeditor.h"
|
||||||
#include "paletteparser.h"
|
#include "paletteutil.h"
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
@ -268,7 +268,7 @@ void PaletteEditor::on_actionImport_Palette_triggered()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PaletteParser parser;
|
PaletteUtil parser;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
QList<QRgb> palette = parser.parse(filepath, &error);
|
QList<QRgb> palette = parser.parse(filepath, &error);
|
||||||
if (error) {
|
if (error) {
|
||||||
|
|
807
src/ui/regionmapeditor.cpp
Normal file
807
src/ui/regionmapeditor.cpp
Normal file
|
@ -0,0 +1,807 @@
|
||||||
|
#include "regionmapeditor.h"
|
||||||
|
#include "ui_regionmapeditor.h"
|
||||||
|
#include "imageexport.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QDialogButtonBox>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QFormLayout>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QColor>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
RegionMapEditor::RegionMapEditor(QWidget *parent, Project *project_) :
|
||||||
|
QMainWindow(parent),
|
||||||
|
ui(new Ui::RegionMapEditor)
|
||||||
|
{
|
||||||
|
this->ui->setupUi(this);
|
||||||
|
this->project = project_;
|
||||||
|
this->region_map = new RegionMap;
|
||||||
|
this->ui->action_RegionMap_Resize->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
RegionMapEditor::~RegionMapEditor()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
delete region_map;
|
||||||
|
delete region_map_item;
|
||||||
|
delete mapsquare_selector_item;
|
||||||
|
delete region_map_layout_item;
|
||||||
|
delete scene_region_map_image;
|
||||||
|
delete city_map_selector_item;
|
||||||
|
delete city_map_item;
|
||||||
|
delete scene_city_map_tiles;
|
||||||
|
delete scene_city_map_image;
|
||||||
|
delete scene_region_map_layout;
|
||||||
|
delete scene_region_map_tiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::on_action_RegionMap_Save_triggered() {
|
||||||
|
setCurrentSquareOptions();
|
||||||
|
if (project && region_map) {
|
||||||
|
this->region_map->save();
|
||||||
|
this->city_map_item->save();
|
||||||
|
this->currIndex = this->region_map_layout_item->highlightedTile;
|
||||||
|
this->region_map_layout_item->highlightedTile = -1;
|
||||||
|
displayRegionMap();
|
||||||
|
}
|
||||||
|
this->hasUnsavedChanges = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::setCurrentSquareOptions() {
|
||||||
|
if (project && region_map) {
|
||||||
|
this->region_map->saveOptions(
|
||||||
|
this->currIndex,
|
||||||
|
this->ui->comboBox_RM_ConnectedMap->currentText(),
|
||||||
|
this->ui->lineEdit_RM_MapName->text(),
|
||||||
|
this->region_map->map_squares[this->currIndex].x,
|
||||||
|
this->region_map->map_squares[this->currIndex].y
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::loadRegionMapData() {
|
||||||
|
this->region_map->init(project);
|
||||||
|
this->currIndex = this->region_map->width() * this->region_map->padTop + this->region_map->padLeft;
|
||||||
|
displayRegionMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::loadCityMaps() {
|
||||||
|
QDir directory(project->root + "/graphics/pokenav/city_maps");
|
||||||
|
QStringList files = directory.entryList(QStringList() << "*.bin", QDir::Files);
|
||||||
|
QStringList without_bin;
|
||||||
|
for (QString file : files) {
|
||||||
|
without_bin.append(file.remove(".bin"));
|
||||||
|
}
|
||||||
|
this->ui->comboBox_CityMap_picker->addItems(without_bin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::displayRegionMap() {
|
||||||
|
displayRegionMapTileSelector();
|
||||||
|
displayCityMapTileSelector();
|
||||||
|
displayRegionMapImage();
|
||||||
|
displayRegionMapLayout();
|
||||||
|
displayRegionMapLayoutOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::displayRegionMapImage() {
|
||||||
|
if (!scene_region_map_image) {
|
||||||
|
this->scene_region_map_image = new QGraphicsScene;
|
||||||
|
}
|
||||||
|
if (region_map_item && scene_region_map_image) {
|
||||||
|
scene_region_map_image->removeItem(region_map_item);
|
||||||
|
delete region_map_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->region_map_item = new RegionMapPixmapItem(this->region_map, this->mapsquare_selector_item);
|
||||||
|
this->region_map_item->draw();
|
||||||
|
|
||||||
|
connect(this->region_map_item, &RegionMapPixmapItem::mouseEvent,
|
||||||
|
this, &RegionMapEditor::mouseEvent_region_map);
|
||||||
|
connect(this->region_map_item, &RegionMapPixmapItem::hoveredRegionMapTileChanged,
|
||||||
|
this, &RegionMapEditor::onHoveredRegionMapTileChanged);
|
||||||
|
connect(this->region_map_item, &RegionMapPixmapItem::hoveredRegionMapTileCleared,
|
||||||
|
this, &RegionMapEditor::onHoveredRegionMapTileCleared);
|
||||||
|
|
||||||
|
this->scene_region_map_image->addItem(this->region_map_item);
|
||||||
|
this->scene_region_map_image->setSceneRect(this->scene_region_map_image->itemsBoundingRect());
|
||||||
|
|
||||||
|
this->ui->graphicsView_Region_Map_BkgImg->setScene(this->scene_region_map_image);
|
||||||
|
|
||||||
|
if (regionMapFirstDraw) {
|
||||||
|
on_verticalSlider_Zoom_Map_Image_valueChanged(initialScale);
|
||||||
|
RegionMapHistoryItem *commit = new RegionMapHistoryItem(
|
||||||
|
RegionMapEditorBox::BackgroundImage, this->region_map->getTiles(), this->region_map->width(), this->region_map->height()
|
||||||
|
);
|
||||||
|
history.push(commit);
|
||||||
|
regionMapFirstDraw = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::displayRegionMapLayout() {
|
||||||
|
if (!scene_region_map_layout) {
|
||||||
|
this->scene_region_map_layout = new QGraphicsScene;
|
||||||
|
}
|
||||||
|
if (region_map_layout_item && scene_region_map_layout) {
|
||||||
|
this->scene_region_map_layout->removeItem(region_map_layout_item);
|
||||||
|
delete region_map_layout_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->region_map_layout_item = new RegionMapLayoutPixmapItem(this->region_map, this->mapsquare_selector_item);
|
||||||
|
|
||||||
|
connect(this->region_map_layout_item, &RegionMapLayoutPixmapItem::selectedTileChanged,
|
||||||
|
this, &RegionMapEditor::onRegionMapLayoutSelectedTileChanged);
|
||||||
|
connect(this->region_map_layout_item, &RegionMapLayoutPixmapItem::hoveredTileChanged,
|
||||||
|
this, &RegionMapEditor::onRegionMapLayoutHoveredTileChanged);
|
||||||
|
connect(this->region_map_layout_item, &RegionMapLayoutPixmapItem::hoveredTileCleared,
|
||||||
|
this, &RegionMapEditor::onRegionMapLayoutHoveredTileCleared);
|
||||||
|
|
||||||
|
this->region_map_layout_item->draw();
|
||||||
|
this->region_map_layout_item->select(this->currIndex);
|
||||||
|
|
||||||
|
this->scene_region_map_layout->addItem(region_map_layout_item);
|
||||||
|
this->scene_region_map_layout->setSceneRect(this->scene_region_map_layout->itemsBoundingRect());
|
||||||
|
|
||||||
|
this->ui->graphicsView_Region_Map_Layout->setScene(this->scene_region_map_layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::displayRegionMapLayoutOptions() {
|
||||||
|
this->ui->comboBox_RM_ConnectedMap->clear();
|
||||||
|
this->ui->comboBox_RM_ConnectedMap->addItems(this->project->mapSectionValueToName.values());
|
||||||
|
|
||||||
|
this->ui->frame_RM_Options->setEnabled(true);
|
||||||
|
|
||||||
|
updateRegionMapLayoutOptions(this->currIndex);
|
||||||
|
|
||||||
|
// TODO: implement when the code is decompiled
|
||||||
|
this->ui->label_RM_CityMap->setVisible(false);
|
||||||
|
this->ui->comboBox_RM_CityMap->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::updateRegionMapLayoutOptions(int index) {
|
||||||
|
this->ui->comboBox_RM_ConnectedMap->blockSignals(true);
|
||||||
|
this->ui->lineEdit_RM_MapName->setText(this->project->mapSecToMapHoverName->value(this->region_map->map_squares[index].mapsec));
|
||||||
|
this->ui->comboBox_RM_ConnectedMap->setCurrentText(this->region_map->map_squares[index].mapsec);
|
||||||
|
this->ui->comboBox_RM_ConnectedMap->blockSignals(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::displayRegionMapTileSelector() {
|
||||||
|
if (!scene_region_map_tiles) {
|
||||||
|
this->scene_region_map_tiles = new QGraphicsScene;
|
||||||
|
}
|
||||||
|
if (mapsquare_selector_item && scene_region_map_tiles) {
|
||||||
|
this->scene_region_map_tiles->removeItem(mapsquare_selector_item);
|
||||||
|
delete mapsquare_selector_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->mapsquare_selector_item = new TilemapTileSelector(QPixmap(this->region_map->pngPath()));
|
||||||
|
this->mapsquare_selector_item->draw();
|
||||||
|
|
||||||
|
this->scene_region_map_tiles->addItem(this->mapsquare_selector_item);
|
||||||
|
|
||||||
|
connect(this->mapsquare_selector_item, &TilemapTileSelector::selectedTileChanged,
|
||||||
|
this, &RegionMapEditor::onRegionMapTileSelectorSelectedTileChanged);
|
||||||
|
connect(this->mapsquare_selector_item, &TilemapTileSelector::hoveredTileChanged,
|
||||||
|
this, &RegionMapEditor::onRegionMapTileSelectorHoveredTileChanged);
|
||||||
|
connect(this->mapsquare_selector_item, &TilemapTileSelector::hoveredTileCleared,
|
||||||
|
this, &RegionMapEditor::onRegionMapTileSelectorHoveredTileCleared);
|
||||||
|
|
||||||
|
this->ui->graphicsView_RegionMap_Tiles->setScene(this->scene_region_map_tiles);
|
||||||
|
on_verticalSlider_Zoom_Image_Tiles_valueChanged(initialScale);
|
||||||
|
|
||||||
|
this->mapsquare_selector_item->select(this->selectedImageTile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::displayCityMapTileSelector() {
|
||||||
|
if (!scene_city_map_tiles) {
|
||||||
|
this->scene_city_map_tiles = new QGraphicsScene;
|
||||||
|
}
|
||||||
|
if (city_map_selector_item && scene_city_map_tiles) {
|
||||||
|
scene_city_map_tiles->removeItem(city_map_selector_item);
|
||||||
|
delete city_map_selector_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->city_map_selector_item = new TilemapTileSelector(QPixmap(this->region_map->cityTilesPath()));
|
||||||
|
this->city_map_selector_item->draw();
|
||||||
|
|
||||||
|
this->scene_city_map_tiles->addItem(this->city_map_selector_item);
|
||||||
|
|
||||||
|
connect(this->city_map_selector_item, &TilemapTileSelector::selectedTileChanged,
|
||||||
|
this, &RegionMapEditor::onCityMapTileSelectorSelectedTileChanged);
|
||||||
|
|
||||||
|
this->ui->graphicsView_City_Map_Tiles->setScene(this->scene_city_map_tiles);
|
||||||
|
on_verticalSlider_Zoom_City_Tiles_valueChanged(initialScale);
|
||||||
|
|
||||||
|
this->city_map_selector_item->select(this->selectedCityTile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::displayCityMap(QString f) {
|
||||||
|
QString file = this->project->root + "/graphics/pokenav/city_maps/" + f + ".bin";
|
||||||
|
|
||||||
|
if (!scene_city_map_image) {
|
||||||
|
scene_city_map_image = new QGraphicsScene;
|
||||||
|
}
|
||||||
|
if (city_map_item && scene_city_map_image) {
|
||||||
|
scene_city_map_image->removeItem(city_map_item);
|
||||||
|
delete city_map_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
city_map_item = new CityMapPixmapItem(file, this->city_map_selector_item);
|
||||||
|
city_map_item->draw();
|
||||||
|
|
||||||
|
connect(this->city_map_item, &CityMapPixmapItem::mouseEvent,
|
||||||
|
this, &RegionMapEditor::mouseEvent_city_map);
|
||||||
|
|
||||||
|
scene_city_map_image->addItem(city_map_item);
|
||||||
|
scene_city_map_image->setSceneRect(this->scene_city_map_image->sceneRect());
|
||||||
|
|
||||||
|
this->ui->graphicsView_City_Map->setScene(scene_city_map_image);
|
||||||
|
on_verticalSlider_Zoom_City_Map_valueChanged(initialScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RegionMapEditor::createCityMap(QString name) {
|
||||||
|
bool errored = false;
|
||||||
|
|
||||||
|
QString file = this->project->root + "/graphics/pokenav/city_maps/" + name + ".bin";
|
||||||
|
|
||||||
|
uint8_t filler = 0x30;
|
||||||
|
uint8_t border = 0x7;
|
||||||
|
uint8_t blank = 0x1;
|
||||||
|
QByteArray new_data(400, filler);
|
||||||
|
for (int i = 0; i < new_data.size(); i++) {
|
||||||
|
if (i % 2) continue;
|
||||||
|
int x = i % 20;
|
||||||
|
int y = i / 20;
|
||||||
|
if (y <= 1 || y >= 8 || x <= 3 || x >= 16)
|
||||||
|
new_data[i] = border;
|
||||||
|
else
|
||||||
|
new_data[i] = blank;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile binFile(file);
|
||||||
|
if (!binFile.open(QIODevice::WriteOnly)) errored = true;
|
||||||
|
binFile.write(new_data);
|
||||||
|
binFile.close();
|
||||||
|
|
||||||
|
loadCityMaps();
|
||||||
|
this->ui->comboBox_CityMap_picker->setCurrentText(name);
|
||||||
|
|
||||||
|
return !errored;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::onRegionMapTileSelectorSelectedTileChanged(unsigned id) {
|
||||||
|
this->selectedImageTile = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::onCityMapTileSelectorSelectedTileChanged(unsigned id) {
|
||||||
|
this->selectedCityTile = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::onRegionMapTileSelectorHoveredTileChanged(unsigned tileId) {
|
||||||
|
QString message = QString("Tile: 0x") + QString("%1").arg(tileId, 4, 16, QChar('0')).toUpper();
|
||||||
|
this->ui->statusbar->showMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::onRegionMapTileSelectorHoveredTileCleared() {
|
||||||
|
this->ui->statusbar->clearMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::onRegionMapLayoutSelectedTileChanged(int index) {
|
||||||
|
setCurrentSquareOptions();
|
||||||
|
QString message = QString();
|
||||||
|
this->currIndex = index;
|
||||||
|
this->region_map_layout_item->highlightedTile = index;
|
||||||
|
if (this->region_map->map_squares[index].has_map) {
|
||||||
|
message = QString("\t %1").arg(this->project->mapSecToMapHoverName->value(
|
||||||
|
this->region_map->map_squares[index].mapsec)).remove("{NAME_END}");
|
||||||
|
}
|
||||||
|
this->ui->statusbar->showMessage(message);
|
||||||
|
|
||||||
|
updateRegionMapLayoutOptions(index);
|
||||||
|
this->region_map_layout_item->draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::onRegionMapLayoutHoveredTileChanged(int index) {
|
||||||
|
QString message = QString();
|
||||||
|
int x = this->region_map->map_squares[index].x;
|
||||||
|
int y = this->region_map->map_squares[index].y;
|
||||||
|
if (x >= 0 && y >= 0) {
|
||||||
|
message = QString("(%1, %2)").arg(x).arg(y);
|
||||||
|
if (this->region_map->map_squares[index].has_map) {
|
||||||
|
message += QString("\t %1").arg(this->project->mapSecToMapHoverName->value(
|
||||||
|
this->region_map->map_squares[index].mapsec)).remove("{NAME_END}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->ui->statusbar->showMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::onRegionMapLayoutHoveredTileCleared() {
|
||||||
|
this->ui->statusbar->clearMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::onHoveredRegionMapTileChanged(int x, int y) {
|
||||||
|
QString message = QString("x: %1, y: %2 Tile: 0x").arg(x).arg(y)
|
||||||
|
+ QString("%1").arg(this->region_map->getTileId(x, y), 4, 16, QChar('0')).toUpper();
|
||||||
|
this->ui->statusbar->showMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::onHoveredRegionMapTileCleared() {
|
||||||
|
this->ui->statusbar->clearMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::mouseEvent_region_map(QGraphicsSceneMouseEvent *event, RegionMapPixmapItem *item) {
|
||||||
|
QPointF pos = event->pos();
|
||||||
|
int x = static_cast<int>(pos.x()) / 8;
|
||||||
|
int y = static_cast<int>(pos.y()) / 8;
|
||||||
|
int index = this->region_map->getMapSquareIndex(x, y);
|
||||||
|
if (index > this->region_map->map_squares.size() - 1) return;
|
||||||
|
|
||||||
|
if (event->buttons() & Qt::RightButton) {
|
||||||
|
item->select(event);
|
||||||
|
//} else if (event->buttons() & Qt::MiddleButton) {// TODO
|
||||||
|
} else {
|
||||||
|
if (event->type() == QEvent::GraphicsSceneMouseRelease) {
|
||||||
|
RegionMapHistoryItem *current = history.current();
|
||||||
|
bool addToHistory = !(current && current->tiles == this->region_map->getTiles());
|
||||||
|
if (addToHistory) {
|
||||||
|
RegionMapHistoryItem *commit = new RegionMapHistoryItem(
|
||||||
|
RegionMapEditorBox::BackgroundImage, this->region_map->getTiles(), this->region_map->width(), this->region_map->height()
|
||||||
|
);
|
||||||
|
history.push(commit);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
item->paint(event);
|
||||||
|
this->region_map_layout_item->draw();
|
||||||
|
this->hasUnsavedChanges = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::mouseEvent_city_map(QGraphicsSceneMouseEvent *event, CityMapPixmapItem *item) {
|
||||||
|
QPointF pos = event->pos();
|
||||||
|
int x = static_cast<int>(pos.x()) / 8;
|
||||||
|
int y = static_cast<int>(pos.y()) / 8;
|
||||||
|
int index = this->city_map_item->getIndexAt(x, y);
|
||||||
|
|
||||||
|
if (cityMapFirstDraw) {
|
||||||
|
RegionMapHistoryItem *commit = new RegionMapHistoryItem(
|
||||||
|
RegionMapEditorBox::CityMapImage, this->city_map_item->getTiles(), this->city_map_item->file
|
||||||
|
);
|
||||||
|
history.push(commit);
|
||||||
|
cityMapFirstDraw = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event->buttons() & Qt::RightButton) {// TODO
|
||||||
|
//} else if (event->buttons() & Qt::MiddleButton) {// TODO
|
||||||
|
} else {
|
||||||
|
if (event->type() == QEvent::GraphicsSceneMouseRelease) {
|
||||||
|
RegionMapHistoryItem *current = history.current();
|
||||||
|
bool addToHistory = !(current && current->tiles == this->city_map_item->getTiles());
|
||||||
|
if (addToHistory) {
|
||||||
|
RegionMapHistoryItem *commit = new RegionMapHistoryItem(
|
||||||
|
RegionMapEditorBox::CityMapImage, this->city_map_item->getTiles(), this->city_map_item->file
|
||||||
|
);
|
||||||
|
history.push(commit);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
item->paint(event);
|
||||||
|
this->hasUnsavedChanges = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::on_tabWidget_Region_Map_currentChanged(int index) {
|
||||||
|
this->ui->stackedWidget_RM_Options->setCurrentIndex(index);
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
this->ui->verticalSlider_Zoom_Image_Tiles->setVisible(true);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
this->ui->verticalSlider_Zoom_Image_Tiles->setVisible(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::on_comboBox_RM_ConnectedMap_activated(const QString &mapsec) {
|
||||||
|
this->ui->lineEdit_RM_MapName->setText(this->project->mapSecToMapHoverName->value(mapsec));
|
||||||
|
this->hasUnsavedChanges = true;// sometimes this is called for unknown reasons
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::on_lineEdit_RM_MapName_textEdited(const QString &text) {
|
||||||
|
this->hasUnsavedChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::on_pushButton_RM_Options_delete_clicked() {
|
||||||
|
this->region_map->resetSquare(this->region_map_layout_item->selectedTile);
|
||||||
|
updateRegionMapLayoutOptions(this->region_map_layout_item->selectedTile);
|
||||||
|
this->region_map_layout_item->draw();
|
||||||
|
this->region_map_layout_item->select(this->region_map_layout_item->selectedTile);
|
||||||
|
this->hasUnsavedChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::on_pushButton_CityMap_add_clicked() {
|
||||||
|
QDialog popup(this, Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
|
||||||
|
popup.setWindowTitle("New City Map");
|
||||||
|
popup.setWindowModality(Qt::NonModal);
|
||||||
|
|
||||||
|
QFormLayout form(&popup);
|
||||||
|
|
||||||
|
QLineEdit *input = new QLineEdit();
|
||||||
|
form.addRow(new QLabel("Name:"), input);
|
||||||
|
|
||||||
|
QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &popup);
|
||||||
|
|
||||||
|
QString name;
|
||||||
|
|
||||||
|
form.addRow(&buttonBox);
|
||||||
|
connect(&buttonBox, SIGNAL(rejected()), &popup, SLOT(reject()));
|
||||||
|
connect(&buttonBox, &QDialogButtonBox::accepted, [&popup, &input, &name](){
|
||||||
|
name = input->text().remove(QRegularExpression("[^a-zA-Z0-9_]+"));
|
||||||
|
if (!name.isEmpty())
|
||||||
|
popup.accept();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (popup.exec() == QDialog::Accepted) {
|
||||||
|
createCityMap(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->hasUnsavedChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::on_action_RegionMap_Resize_triggered() {
|
||||||
|
QDialog popup(this, Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
|
||||||
|
popup.setWindowTitle("New Region Map Dimensions");
|
||||||
|
popup.setWindowModality(Qt::NonModal);
|
||||||
|
|
||||||
|
QFormLayout form(&popup);
|
||||||
|
|
||||||
|
QSpinBox *widthSpinBox = new QSpinBox();
|
||||||
|
QSpinBox *heightSpinBox = new QSpinBox();
|
||||||
|
widthSpinBox->setMinimum(32);
|
||||||
|
heightSpinBox->setMinimum(20);
|
||||||
|
widthSpinBox->setMaximum(60);// TODO: find real limits
|
||||||
|
heightSpinBox->setMaximum(40);
|
||||||
|
widthSpinBox->setValue(this->region_map->width());
|
||||||
|
heightSpinBox->setValue(this->region_map->height());
|
||||||
|
form.addRow(new QLabel("Width"), widthSpinBox);
|
||||||
|
form.addRow(new QLabel("Height"), heightSpinBox);
|
||||||
|
|
||||||
|
QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &popup);
|
||||||
|
|
||||||
|
form.addRow(&buttonBox);
|
||||||
|
connect(&buttonBox, SIGNAL(rejected()), &popup, SLOT(reject()));
|
||||||
|
connect(&buttonBox, SIGNAL(accepted()), &popup, SLOT(accept()));
|
||||||
|
|
||||||
|
if (popup.exec() == QDialog::Accepted) {
|
||||||
|
resize(widthSpinBox->value(), heightSpinBox->value());
|
||||||
|
RegionMapHistoryItem *commit = new RegionMapHistoryItem(
|
||||||
|
RegionMapEditorBox::BackgroundImage, this->region_map->getTiles(), widthSpinBox->value(), heightSpinBox->value()
|
||||||
|
);
|
||||||
|
history.push(commit);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->hasUnsavedChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::on_action_RegionMap_Undo_triggered() {
|
||||||
|
undo();
|
||||||
|
this->hasUnsavedChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::undo() {
|
||||||
|
RegionMapHistoryItem *commit = history.back();
|
||||||
|
if (!commit) return;
|
||||||
|
|
||||||
|
switch (commit->which)
|
||||||
|
{
|
||||||
|
case RegionMapEditorBox::BackgroundImage:
|
||||||
|
if (commit->mapWidth != this->region_map->width() || commit->mapHeight != this->region_map->height())
|
||||||
|
this->resize(commit->mapWidth, commit->mapHeight);
|
||||||
|
this->region_map->setTiles(commit->tiles);
|
||||||
|
this->region_map_item->draw();
|
||||||
|
this->region_map_layout_item->draw();
|
||||||
|
break;
|
||||||
|
case RegionMapEditorBox::CityMapImage:
|
||||||
|
if (commit->cityMap == this->city_map_item->file)
|
||||||
|
this->city_map_item->setTiles(commit->tiles);
|
||||||
|
this->city_map_item->draw();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::on_action_RegionMap_Redo_triggered() {
|
||||||
|
redo();
|
||||||
|
this->hasUnsavedChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::redo() {
|
||||||
|
RegionMapHistoryItem *commit = history.next();
|
||||||
|
if (!commit) return;
|
||||||
|
|
||||||
|
switch (commit->which)
|
||||||
|
{
|
||||||
|
case RegionMapEditorBox::BackgroundImage:
|
||||||
|
if (commit->mapWidth != this->region_map->width() || commit->mapHeight != this->region_map->height())
|
||||||
|
this->resize(commit->mapWidth, commit->mapHeight);
|
||||||
|
this->region_map->setTiles(commit->tiles);
|
||||||
|
this->region_map_item->draw();
|
||||||
|
this->region_map_layout_item->draw();
|
||||||
|
break;
|
||||||
|
case RegionMapEditorBox::CityMapImage:
|
||||||
|
this->city_map_item->setTiles(commit->tiles);
|
||||||
|
this->city_map_item->draw();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::resize(int w, int h) {
|
||||||
|
this->region_map->resize(w, h);
|
||||||
|
this->currIndex = this->region_map->padLeft * w + this->region_map->padTop;
|
||||||
|
displayRegionMapImage();
|
||||||
|
displayRegionMapLayout();
|
||||||
|
displayRegionMapLayoutOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::on_action_Swap_triggered() {
|
||||||
|
QDialog popup(this, Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
|
||||||
|
popup.setWindowTitle("New City Map");
|
||||||
|
popup.setWindowModality(Qt::NonModal);
|
||||||
|
|
||||||
|
QFormLayout form(&popup);
|
||||||
|
|
||||||
|
QComboBox *oldSecBox = new QComboBox();
|
||||||
|
oldSecBox->addItems(this->project->mapSectionValueToName.values());
|
||||||
|
form.addRow(new QLabel("Old Map Section:"), oldSecBox);
|
||||||
|
QComboBox *newSecBox = new QComboBox();
|
||||||
|
newSecBox->addItems(this->project->mapSectionValueToName.values());
|
||||||
|
form.addRow(new QLabel("New Map Section:"), newSecBox);
|
||||||
|
|
||||||
|
QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &popup);
|
||||||
|
form.addRow(&buttonBox);
|
||||||
|
|
||||||
|
QString beforeSection, afterSection;
|
||||||
|
uint8_t oldId, newId;
|
||||||
|
connect(&buttonBox, SIGNAL(rejected()), &popup, SLOT(reject()));
|
||||||
|
connect(&buttonBox, &QDialogButtonBox::accepted, [this, &popup, &oldSecBox, &newSecBox,
|
||||||
|
&beforeSection, &afterSection, &oldId, &newId](){
|
||||||
|
beforeSection = oldSecBox->currentText();
|
||||||
|
afterSection = newSecBox->currentText();
|
||||||
|
if (!beforeSection.isEmpty() && !afterSection.isEmpty()) {
|
||||||
|
oldId = static_cast<uint8_t>(this->project->mapSectionNameToValue.value(beforeSection));
|
||||||
|
newId = static_cast<uint8_t>(this->project->mapSectionNameToValue.value(afterSection));
|
||||||
|
popup.accept();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (popup.exec() == QDialog::Accepted) {
|
||||||
|
this->region_map->replaceSectionId(oldId, newId);
|
||||||
|
this->region_map_layout_item->draw();
|
||||||
|
this->region_map_layout_item->select(this->region_map_layout_item->selectedTile);
|
||||||
|
this->hasUnsavedChanges = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::on_action_RegionMap_ClearImage_triggered() {
|
||||||
|
this->region_map->clearImage();
|
||||||
|
RegionMapHistoryItem *commit = new RegionMapHistoryItem(
|
||||||
|
RegionMapEditorBox::BackgroundImage, this->region_map->getTiles(), this->region_map->width(), this->region_map->height()
|
||||||
|
);
|
||||||
|
history.push(commit);
|
||||||
|
|
||||||
|
displayRegionMapImage();
|
||||||
|
displayRegionMapLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::on_action_RegionMap_ClearLayout_triggered() {
|
||||||
|
QMessageBox::StandardButton result = QMessageBox::question(
|
||||||
|
this,
|
||||||
|
"WARNING",
|
||||||
|
"This action will reset the entire map layout to MAPSEC_NONE, continue?",
|
||||||
|
QMessageBox::Yes | QMessageBox::Cancel,
|
||||||
|
QMessageBox::Yes
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result == QMessageBox::Yes) {
|
||||||
|
this->region_map->clearLayout();
|
||||||
|
displayRegionMapLayout();
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::on_action_Import_RegionMap_ImageTiles_triggered() {
|
||||||
|
importTileImage(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::on_action_Import_CityMap_ImageTiles_triggered() {
|
||||||
|
importTileImage(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::importTileImage(bool city) {
|
||||||
|
QString descriptor = city ? "City Map" : "Region Map";
|
||||||
|
|
||||||
|
QString infilepath = QFileDialog::getOpenFileName(this, QString("Import %1 Tiles Image").arg(descriptor),
|
||||||
|
this->project->root, "Image Files (*.png *.bmp *.jpg *.dib)");
|
||||||
|
if (infilepath.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logInfo(QString("Importing %1 Tiles from '%2'").arg(descriptor).arg(infilepath));
|
||||||
|
|
||||||
|
// Read image data from buffer so that the built-in QImage doesn't try to detect file format
|
||||||
|
// purely from the extension name.
|
||||||
|
QFile file(infilepath);
|
||||||
|
QImage image;
|
||||||
|
if (file.open(QIODevice::ReadOnly)) {
|
||||||
|
QByteArray imageData = file.readAll();
|
||||||
|
image = QImage::fromData(imageData);
|
||||||
|
} else {
|
||||||
|
QString errorMessage = QString("Failed to open image file: '%1'").arg(infilepath);
|
||||||
|
logError(errorMessage);
|
||||||
|
QMessageBox msgBox(this);
|
||||||
|
msgBox.setText("Failed to import tiles.");
|
||||||
|
msgBox.setInformativeText(errorMessage);
|
||||||
|
msgBox.setDefaultButton(QMessageBox::Ok);
|
||||||
|
msgBox.setIcon(QMessageBox::Icon::Critical);
|
||||||
|
msgBox.exec();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (image.width() == 0 || image.height() == 0 || image.width() % 8 != 0 || image.height() % 8 != 0) {
|
||||||
|
QString errorMessage = QString("The image dimensions (%1 x %2) are invalid. Width and height must be multiples of 8 pixels.")
|
||||||
|
.arg(image.width())
|
||||||
|
.arg(image.height());
|
||||||
|
logError(errorMessage);
|
||||||
|
QMessageBox msgBox(this);
|
||||||
|
msgBox.setText("Failed to import tiles.");
|
||||||
|
msgBox.setInformativeText(errorMessage);
|
||||||
|
msgBox.setDefaultButton(QMessageBox::Ok);
|
||||||
|
msgBox.setIcon(QMessageBox::Icon::Critical);
|
||||||
|
msgBox.exec();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate total number of tiles in image.
|
||||||
|
int numTilesWide = image.width() / 8;
|
||||||
|
int numTilesHigh = image.height() / 8;
|
||||||
|
int totalTiles = numTilesHigh * numTilesWide;
|
||||||
|
int maxAllowedTiles = 0x100;
|
||||||
|
if (totalTiles > maxAllowedTiles) {
|
||||||
|
QString errorMessage = QString("The total number of tiles in the provided image (%1) is greater than the allowed number (%2).")
|
||||||
|
.arg(maxAllowedTiles)
|
||||||
|
.arg(totalTiles);
|
||||||
|
logError(errorMessage);
|
||||||
|
QMessageBox msgBox(this);
|
||||||
|
msgBox.setText("Failed to import tiles.");
|
||||||
|
msgBox.setInformativeText(errorMessage);
|
||||||
|
msgBox.setDefaultButton(QMessageBox::Ok);
|
||||||
|
msgBox.setIcon(QMessageBox::Icon::Critical);
|
||||||
|
msgBox.exec();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the image's palette.
|
||||||
|
QString palMessage = QString();
|
||||||
|
bool palError = false;
|
||||||
|
if (image.colorCount() == 0) {
|
||||||
|
palMessage = QString("The provided image is not indexed.");
|
||||||
|
palError = true;
|
||||||
|
} else if (!city && image.colorCount() != 256) {
|
||||||
|
palMessage = QString("The provided image has a palette with %1 colors. You must provide an indexed imaged with a 256 color palette.").arg(image.colorCount());
|
||||||
|
palError = true;
|
||||||
|
} else if (city && image.colorCount() != 16) {
|
||||||
|
palMessage = QString("The provided image has a palette with %1 colors. You must provide an indexed imaged with a 16 color palette.").arg(image.colorCount());
|
||||||
|
palError = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (palError) {
|
||||||
|
logError(palMessage);
|
||||||
|
QMessageBox msgBox(this);
|
||||||
|
msgBox.setText("Failed to import tiles.");
|
||||||
|
msgBox.setInformativeText(palMessage);
|
||||||
|
msgBox.setDefaultButton(QMessageBox::Ok);
|
||||||
|
msgBox.setIcon(QMessageBox::Icon::Critical);
|
||||||
|
msgBox.exec();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the image from the correct path.
|
||||||
|
if (city) {
|
||||||
|
this->region_map->setTemporaryCityTilesPath(infilepath);
|
||||||
|
} else {
|
||||||
|
this->region_map->setTemporaryPngPath(infilepath);
|
||||||
|
}
|
||||||
|
this->hasUnsavedChanges = true;
|
||||||
|
|
||||||
|
// Redload and redraw images.
|
||||||
|
displayRegionMap();
|
||||||
|
displayCityMap(this->ui->comboBox_CityMap_picker->currentText());
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::on_comboBox_CityMap_picker_currentTextChanged(const QString &file) {
|
||||||
|
this->displayCityMap(file);
|
||||||
|
this->cityMapFirstDraw = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::closeEvent(QCloseEvent *event)
|
||||||
|
{
|
||||||
|
if (this->hasUnsavedChanges) {
|
||||||
|
QMessageBox::StandardButton result = QMessageBox::question(
|
||||||
|
this,
|
||||||
|
"porymap",
|
||||||
|
"The region map has been modified, save changes?",
|
||||||
|
QMessageBox::No | QMessageBox::Yes | QMessageBox::Cancel,
|
||||||
|
QMessageBox::Yes);
|
||||||
|
|
||||||
|
if (result == QMessageBox::Yes) {
|
||||||
|
this->on_action_RegionMap_Save_triggered();
|
||||||
|
event->accept();
|
||||||
|
} else if (result == QMessageBox::No) {
|
||||||
|
event->accept();
|
||||||
|
} else if (result == QMessageBox::Cancel) {
|
||||||
|
event->ignore();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
event->accept();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::on_verticalSlider_Zoom_Map_Image_valueChanged(int val) {
|
||||||
|
double scale = pow(scaleUpFactor, static_cast<double>(val - initialScale) / initialScale);
|
||||||
|
|
||||||
|
QMatrix matrix;
|
||||||
|
matrix.scale(scale, scale);
|
||||||
|
int width = ceil(static_cast<double>(this->region_map->imgSize().width()) * scale);
|
||||||
|
int height = ceil(static_cast<double>(this->region_map->imgSize().height()) * scale);
|
||||||
|
|
||||||
|
ui->graphicsView_Region_Map_BkgImg->setResizeAnchor(QGraphicsView::NoAnchor);
|
||||||
|
ui->graphicsView_Region_Map_BkgImg->setMatrix(matrix);
|
||||||
|
ui->graphicsView_Region_Map_BkgImg->setFixedSize(width + 2, height + 2);
|
||||||
|
ui->graphicsView_Region_Map_Layout->setResizeAnchor(QGraphicsView::NoAnchor);
|
||||||
|
ui->graphicsView_Region_Map_Layout->setMatrix(matrix);
|
||||||
|
ui->graphicsView_Region_Map_Layout->setFixedSize(width + 2, height + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::on_verticalSlider_Zoom_Image_Tiles_valueChanged(int val) {
|
||||||
|
double scale = pow(scaleUpFactor, static_cast<double>(val - initialScale) / initialScale);
|
||||||
|
|
||||||
|
QMatrix matrix;
|
||||||
|
matrix.scale(scale, scale);
|
||||||
|
int width = ceil(static_cast<double>(this->mapsquare_selector_item->pixelWidth) * scale);
|
||||||
|
int height = ceil(static_cast<double>(this->mapsquare_selector_item->pixelHeight) * scale);
|
||||||
|
|
||||||
|
ui->graphicsView_RegionMap_Tiles->setResizeAnchor(QGraphicsView::NoAnchor);
|
||||||
|
ui->graphicsView_RegionMap_Tiles->setMatrix(matrix);
|
||||||
|
ui->graphicsView_RegionMap_Tiles->setFixedSize(width + 2, height + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::on_verticalSlider_Zoom_City_Map_valueChanged(int val) {
|
||||||
|
double scale = pow(scaleUpFactor, static_cast<double>(val - initialScale) / initialScale);
|
||||||
|
|
||||||
|
QMatrix matrix;
|
||||||
|
matrix.scale(scale, scale);
|
||||||
|
int width = ceil(static_cast<double>(8 * city_map_item->width()) * scale);
|
||||||
|
int height = ceil(static_cast<double>(8 * city_map_item->height()) * scale);
|
||||||
|
|
||||||
|
ui->graphicsView_City_Map->setResizeAnchor(QGraphicsView::NoAnchor);
|
||||||
|
ui->graphicsView_City_Map->setMatrix(matrix);
|
||||||
|
ui->graphicsView_City_Map->setFixedSize(width + 2, height + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapEditor::on_verticalSlider_Zoom_City_Tiles_valueChanged(int val) {
|
||||||
|
double scale = pow(scaleUpFactor, static_cast<double>(val - initialScale) / initialScale);
|
||||||
|
|
||||||
|
QMatrix matrix;
|
||||||
|
matrix.scale(scale, scale);
|
||||||
|
int width = ceil(static_cast<double>(this->city_map_selector_item->pixelWidth) * scale);
|
||||||
|
int height = ceil(static_cast<double>(this->city_map_selector_item->pixelHeight) * scale);
|
||||||
|
|
||||||
|
ui->graphicsView_City_Map_Tiles->setResizeAnchor(QGraphicsView::NoAnchor);
|
||||||
|
ui->graphicsView_City_Map_Tiles->setMatrix(matrix);
|
||||||
|
ui->graphicsView_City_Map_Tiles->setFixedSize(width + 2, height + 2);
|
||||||
|
}
|
90
src/ui/regionmaplayoutpixmapitem.cpp
Normal file
90
src/ui/regionmaplayoutpixmapitem.cpp
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
#include "regionmaplayoutpixmapitem.h"
|
||||||
|
|
||||||
|
void RegionMapLayoutPixmapItem::draw() {
|
||||||
|
if (!region_map) return;
|
||||||
|
|
||||||
|
QImage image(region_map->width() * 8, region_map->height() * 8, QImage::Format_RGBA8888);
|
||||||
|
|
||||||
|
QPainter painter(&image);
|
||||||
|
for (int i = 0; i < region_map->map_squares.size(); i++) {
|
||||||
|
QImage bottom_img = this->tile_selector->tileImg(region_map->map_squares[i].tile_img_id);
|
||||||
|
QImage top_img(8, 8, QImage::Format_RGBA8888);
|
||||||
|
if (region_map->map_squares[i].has_map) {
|
||||||
|
top_img.fill(Qt::gray);
|
||||||
|
} else {
|
||||||
|
top_img.fill(Qt::black);
|
||||||
|
}
|
||||||
|
int x = i % region_map->width();
|
||||||
|
int y = i / region_map->width();
|
||||||
|
QPoint pos = QPoint(x * 8, y * 8);
|
||||||
|
painter.setOpacity(1);
|
||||||
|
painter.drawImage(pos, bottom_img);
|
||||||
|
painter.save();
|
||||||
|
painter.setOpacity(0.55);
|
||||||
|
painter.drawImage(pos, top_img);
|
||||||
|
painter.restore();
|
||||||
|
}
|
||||||
|
painter.end();
|
||||||
|
|
||||||
|
this->setPixmap(QPixmap::fromImage(image));
|
||||||
|
this->drawSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapLayoutPixmapItem::select(int x, int y) {
|
||||||
|
int index = this->region_map->getMapSquareIndex(x, y);
|
||||||
|
SelectablePixmapItem::select(x, y, 0, 0);
|
||||||
|
this->selectedTile = index;
|
||||||
|
this->updateSelectedTile();
|
||||||
|
|
||||||
|
emit selectedTileChanged(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapLayoutPixmapItem::select(int index) {
|
||||||
|
int x = index % this->region_map->width();
|
||||||
|
int y = index / this->region_map->width();
|
||||||
|
SelectablePixmapItem::select(x, y, 0, 0);
|
||||||
|
this->selectedTile = index;
|
||||||
|
this->updateSelectedTile();
|
||||||
|
|
||||||
|
emit selectedTileChanged(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapLayoutPixmapItem::highlight(int x, int y, int red) {
|
||||||
|
this->highlightedTile = red;
|
||||||
|
SelectablePixmapItem::select(x + this->region_map->padLeft, y + this->region_map->padTop, 0, 0);
|
||||||
|
draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapLayoutPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||||
|
QPoint pos = this->getCellPos(event->pos());
|
||||||
|
int index = this->region_map->getMapSquareIndex(pos.x(), pos.y());
|
||||||
|
if (this->region_map->map_squares[index].x >= 0
|
||||||
|
&& this->region_map->map_squares[index].y >= 0) {
|
||||||
|
SelectablePixmapItem::mousePressEvent(event);
|
||||||
|
this->updateSelectedTile();
|
||||||
|
emit selectedTileChanged(this->selectedTile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapLayoutPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
|
||||||
|
mousePressEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapLayoutPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {}
|
||||||
|
|
||||||
|
void RegionMapLayoutPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
|
||||||
|
QPoint pos = this->getCellPos(event->pos());
|
||||||
|
int tileId = this->region_map->getMapSquareIndex(pos.x(), pos.y());
|
||||||
|
emit this->hoveredTileChanged(tileId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapLayoutPixmapItem::hoverLeaveEvent(QGraphicsSceneHoverEvent* event) {
|
||||||
|
emit this->hoveredTileCleared();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapLayoutPixmapItem::updateSelectedTile() {
|
||||||
|
QPoint origin = this->getSelectionStart();
|
||||||
|
this->selectedTile = this->region_map->getMapSquareIndex(origin.x(), origin.y());
|
||||||
|
this->highlightedTile = -1;
|
||||||
|
draw();
|
||||||
|
}
|
66
src/ui/regionmappixmapitem.cpp
Normal file
66
src/ui/regionmappixmapitem.cpp
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
#include "regionmappixmapitem.h"
|
||||||
|
|
||||||
|
void RegionMapPixmapItem::draw() {
|
||||||
|
if (!region_map) return;
|
||||||
|
|
||||||
|
QImage image(region_map->width() * 8, region_map->height() * 8, QImage::Format_RGBA8888);
|
||||||
|
|
||||||
|
QPainter painter(&image);
|
||||||
|
for (int i = 0; i < region_map->map_squares.size(); i++) {
|
||||||
|
QImage img = this->tile_selector->tileImg(region_map->map_squares[i].tile_img_id);
|
||||||
|
int x = i % region_map->width();
|
||||||
|
int y = i / region_map->width();
|
||||||
|
QPoint pos = QPoint(x * 8, y * 8);
|
||||||
|
painter.drawImage(pos, img);
|
||||||
|
}
|
||||||
|
painter.end();
|
||||||
|
|
||||||
|
this->setPixmap(QPixmap::fromImage(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapPixmapItem::paint(QGraphicsSceneMouseEvent *event) {
|
||||||
|
if (region_map) {
|
||||||
|
QPointF pos = event->pos();
|
||||||
|
int x = static_cast<int>(pos.x()) / 8;
|
||||||
|
int y = static_cast<int>(pos.y()) / 8;
|
||||||
|
int index = x + y * region_map->width();
|
||||||
|
this->region_map->map_squares[index].tile_img_id = this->tile_selector->selectedTile;
|
||||||
|
draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapPixmapItem::select(QGraphicsSceneMouseEvent *event) {
|
||||||
|
QPointF pos = event->pos();
|
||||||
|
int x = static_cast<int>(pos.x()) / 8;
|
||||||
|
int y = static_cast<int>(pos.y()) / 8;
|
||||||
|
this->tile_selector->select(this->region_map->getTileId(x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
|
||||||
|
int x = static_cast<int>(event->pos().x()) / 8;
|
||||||
|
int y = static_cast<int>(event->pos().y()) / 8;
|
||||||
|
emit this->hoveredRegionMapTileChanged(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapPixmapItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *) {
|
||||||
|
emit this->hoveredRegionMapTileCleared();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||||
|
emit mouseEvent(event, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
|
||||||
|
QPointF pos = event->pos();
|
||||||
|
int x = static_cast<int>(pos.x()) / 8;
|
||||||
|
int y = static_cast<int>(pos.y()) / 8;
|
||||||
|
if (x < this->region_map->width() && x >= 0
|
||||||
|
&& y < this->region_map->height() && y >= 0) {
|
||||||
|
emit this->hoveredRegionMapTileChanged(x, y);
|
||||||
|
emit mouseEvent(event, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegionMapPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
|
||||||
|
emit mouseEvent(event, this);
|
||||||
|
}
|
77
src/ui/tilemaptileselector.cpp
Normal file
77
src/ui/tilemaptileselector.cpp
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
#include "tilemaptileselector.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
void TilemapTileSelector::draw() {
|
||||||
|
size_t width_ = this->tilemap.width();
|
||||||
|
this->pixelWidth = width_;
|
||||||
|
size_t height_ = this->tilemap.height();
|
||||||
|
this->pixelHeight = height_;
|
||||||
|
size_t ntiles_ = (width_/8) * (height_/8);
|
||||||
|
|
||||||
|
this->numTilesWide = width_ / 8;
|
||||||
|
this->numTiles = ntiles_;
|
||||||
|
|
||||||
|
this->setPixmap(tilemap);
|
||||||
|
this->drawSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TilemapTileSelector::select(unsigned tileId) {
|
||||||
|
QPoint coords = this->getTileIdCoords(tileId);
|
||||||
|
SelectablePixmapItem::select(coords.x(), coords.y(), 0, 0);
|
||||||
|
this->selectedTile = tileId;
|
||||||
|
emit selectedTileChanged(tileId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TilemapTileSelector::updateSelectedTile() {
|
||||||
|
QPoint origin = this->getSelectionStart();
|
||||||
|
this->selectedTile = this->getTileId(origin.x(), origin.y());
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned TilemapTileSelector::getSelectedTile() {
|
||||||
|
return this->selectedTile;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned TilemapTileSelector::getTileId(int x, int y) {
|
||||||
|
int index = y * this->numTilesWide + x;
|
||||||
|
return index < this->numTiles ? index : this->numTiles % index;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPoint TilemapTileSelector::getTileIdCoords(unsigned tileId) {
|
||||||
|
int index = tileId < this->numTiles ? tileId : this->numTiles % tileId;
|
||||||
|
return QPoint(index % this->numTilesWide, index / this->numTilesWide);
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage TilemapTileSelector::tileImg(unsigned tileId) {
|
||||||
|
QPoint pos = getTileIdCoords(tileId);
|
||||||
|
return this->tilemap.copy(pos.x() * 8, pos.y() * 8, 8, 8).toImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TilemapTileSelector::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||||
|
SelectablePixmapItem::mousePressEvent(event);
|
||||||
|
this->updateSelectedTile();
|
||||||
|
emit selectedTileChanged(this->selectedTile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TilemapTileSelector::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
|
||||||
|
SelectablePixmapItem::mouseMoveEvent(event);
|
||||||
|
this->updateSelectedTile();
|
||||||
|
emit hoveredTileChanged(this->selectedTile);
|
||||||
|
emit selectedTileChanged(this->selectedTile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TilemapTileSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
|
||||||
|
SelectablePixmapItem::mouseReleaseEvent(event);
|
||||||
|
this->updateSelectedTile();
|
||||||
|
emit selectedTileChanged(this->selectedTile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TilemapTileSelector::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
|
||||||
|
QPoint pos = this->getCellPos(event->pos());
|
||||||
|
unsigned tileId = this->getTileId(pos.x(), pos.y());
|
||||||
|
emit this->hoveredTileChanged(tileId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TilemapTileSelector::hoverLeaveEvent(QGraphicsSceneHoverEvent* event) {
|
||||||
|
emit this->hoveredTileCleared();
|
||||||
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "imageproviders.h"
|
#include "imageproviders.h"
|
||||||
#include "metatileparser.h"
|
#include "metatileparser.h"
|
||||||
#include "paletteparser.h"
|
#include "paletteutil.h"
|
||||||
#include "imageexport.h"
|
#include "imageexport.h"
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
@ -410,7 +410,7 @@ void TilesetEditor::importTilesetTiles(Tileset *tileset, bool primary) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PaletteParser parser;
|
PaletteUtil parser;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
QList<QRgb> palette = parser.parse(filepath, &error);
|
QList<QRgb> palette = parser.parse(filepath, &error);
|
||||||
if (error) {
|
if (error) {
|
||||||
|
|
Loading…
Reference in a new issue