mirror of
https://github.com/huderlem/porymap.git
synced 2026-10-02 12:56:38 -05:00
begin overhaul of region map editor
- use a configurator to give users more options - support firered (tilemaps, layout layers) - add support for 4bpp and 8bpp tilemaps - use new region map entries json format - temporarily disabled city tilemap editor code
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
#define REGIONMAP_H
|
||||
|
||||
#include "map.h"
|
||||
#include "project.h"
|
||||
#include "tilemaptileselector.h"
|
||||
#include "history.h"
|
||||
|
||||
@@ -15,6 +14,11 @@
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsView>
|
||||
|
||||
#include <memory>
|
||||
using std::shared_ptr;
|
||||
|
||||
class Project;
|
||||
|
||||
enum RegionMapEditorBox {
|
||||
BackgroundImage = 1,
|
||||
CityMapImage = 2,
|
||||
@@ -41,71 +45,44 @@ public:
|
||||
~RegionMapHistoryItem() {}
|
||||
};
|
||||
|
||||
class RegionMapEntry
|
||||
struct LayoutSquare
|
||||
{
|
||||
public:
|
||||
RegionMapEntry()=default;
|
||||
RegionMapEntry(int x_, int y_, int width_, int height_, QString name_) {
|
||||
this-> x = x_;
|
||||
this-> y = y_;
|
||||
this-> width = width_;
|
||||
this-> height = height_;
|
||||
this-> name = name_;
|
||||
}
|
||||
QString map_section;
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
QString name;
|
||||
|
||||
void setX(int);
|
||||
void setY(int);
|
||||
void setWidth(int);
|
||||
void setHeight(int);
|
||||
bool has_map = false;
|
||||
};
|
||||
|
||||
class RegionMapSquare
|
||||
struct MapSectionEntry
|
||||
{
|
||||
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;
|
||||
QString name = "";
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int width = 1;
|
||||
int height = 1;
|
||||
bool valid = false;
|
||||
};
|
||||
|
||||
class RegionMap
|
||||
{
|
||||
public:
|
||||
RegionMap() = default;
|
||||
RegionMap() = delete;
|
||||
RegionMap(Project *);
|
||||
|
||||
Project *project = nullptr;
|
||||
|
||||
QVector<RegionMapSquare> map_squares;
|
||||
History<RegionMapHistoryItem*> history;
|
||||
History<RegionMapHistoryItem*> history; // TODO
|
||||
|
||||
QMap<QString, QString> sMapNamesMap;
|
||||
QMap<QString, RegionMapEntry> mapSecToMapEntry;
|
||||
QVector<QString> sMapNames;
|
||||
bool loadMapData(poryjson::Json);
|
||||
bool loadTilemap(poryjson::Json);
|
||||
bool loadLayout(poryjson::Json);
|
||||
bool loadEntries();
|
||||
|
||||
const int padLeft = 1;
|
||||
const int padRight = 3;
|
||||
const int padTop = 2;
|
||||
const int padBottom = 3;
|
||||
|
||||
bool init(Project*);
|
||||
|
||||
bool readBkgImgBin();
|
||||
bool readLayout();
|
||||
void setEntries(tsl::ordered_map<QString, MapSectionEntry> *entries) { this->region_map_entries = entries; }
|
||||
MapSectionEntry getEntry(QString section);
|
||||
|
||||
void save();
|
||||
void saveTileImages();
|
||||
void saveBkgImgBin();
|
||||
void saveTilemap();
|
||||
void saveLayout();
|
||||
void saveOptions(int id, QString sec, QString name, int x, int y);
|
||||
|
||||
@@ -115,38 +92,115 @@ public:
|
||||
void clearImage();
|
||||
void replaceSectionId(unsigned oldId, unsigned newId);
|
||||
|
||||
int width();
|
||||
int height();
|
||||
QSize imgSize();
|
||||
unsigned getTileId(int index);
|
||||
shared_ptr<TilemapTile> getTile(int index);
|
||||
unsigned getTileId(int x, int y);
|
||||
shared_ptr<TilemapTile> getTile(int x, int y);
|
||||
bool squareHasMap(int index);
|
||||
QString squareMapSection(int index);
|
||||
int squareX(int index);
|
||||
int squareY(int index);
|
||||
bool squareInLayout(int x, int y);
|
||||
int firstLayoutIndex() { return this->offset_left + this->offset_top * this->tilemap_width; }
|
||||
|
||||
void setTileId(int index, unsigned id);
|
||||
void setTile(int index, TilemapTile &tile);
|
||||
void setTileData(int index, unsigned id, bool hFlip, bool vFlip, int palette);
|
||||
int getMapSquareIndex(int x, int y);
|
||||
|
||||
QString palPath();
|
||||
QString pngPath();
|
||||
void setTemporaryPngPath(QString);
|
||||
QString cityTilesPath();
|
||||
void setTemporaryCityTilesPath(QString);
|
||||
QString entriesPath() { return this->entries_path; }
|
||||
|
||||
QVector<uint8_t> getTiles();
|
||||
void setTiles(QVector<uint8_t> tileIds);
|
||||
|
||||
QStringList getLayers() { return this->layout_layers; }
|
||||
void setLayer(QString layer) { this->current_layer = layer; }
|
||||
QString getLayer() { return this->current_layer; }
|
||||
|
||||
QString fixCase(QString);
|
||||
|
||||
private:
|
||||
int layout_width_;
|
||||
int layout_height_;
|
||||
int img_width_;
|
||||
int img_height_;
|
||||
int padLeft() { return this->offset_left; }
|
||||
int padTop() { return this->offset_top; }
|
||||
int padRight() { return this->tilemap_width - this->layout_width - this->offset_left; }
|
||||
int padBottom() { return this->tilemap_height - this->layout_height - this->offset_top; }
|
||||
|
||||
QString region_map_png_path;
|
||||
QString region_map_bin_path;
|
||||
QString region_map_entries_path;
|
||||
QString region_map_layout_bin_path;
|
||||
int tilemapWidth() { return this->tilemap_width; }
|
||||
int tilemapHeight() { return this->tilemap_height; }
|
||||
int tilemapSize() { return this->tilemap_width * this->tilemap_height; }
|
||||
int tilemapBytes();
|
||||
|
||||
int tilemapToLayoutIndex(int index);
|
||||
|
||||
TilemapFormat tilemapFormat() { return this->tilemap_format; }
|
||||
|
||||
int pixelWidth() { return this->tilemap_width * 8; }
|
||||
int pixelHeight() { return this->tilemap_height * 8; }
|
||||
|
||||
QString fullPath(QString local);
|
||||
|
||||
private:
|
||||
|
||||
tsl::ordered_map<QString, MapSectionEntry> *region_map_entries = nullptr;
|
||||
|
||||
QString alias;
|
||||
|
||||
int tilemap_width;
|
||||
int tilemap_height;
|
||||
|
||||
// default is 32x20 (or 30x20 / screen size??)
|
||||
int region_width;
|
||||
int region_height;
|
||||
|
||||
// default is 28x15
|
||||
int layout_width;
|
||||
int layout_height;
|
||||
|
||||
int offset_left;
|
||||
int offset_top;
|
||||
//int ;
|
||||
//int img_height_;
|
||||
|
||||
TilemapFormat tilemap_format;
|
||||
|
||||
enum class LayoutFormat { None, Binary, CArray };
|
||||
LayoutFormat layout_format;
|
||||
|
||||
QString tileset_path;
|
||||
QString tilemap_path;
|
||||
QString palette_path = "";
|
||||
|
||||
QString entries_path;
|
||||
QString layout_path;
|
||||
|
||||
// TODO: default values?
|
||||
QString layout_array_label;
|
||||
bool layout_uses_layers = false;
|
||||
//QList<QString> layout_layers;
|
||||
|
||||
//QList<RegionMapSquare> map_squares;
|
||||
QList<shared_ptr<TilemapTile>> tilemap;
|
||||
|
||||
// what about separate array for layout
|
||||
// and a pointer to an entries / map sections object (from project? or editor?)
|
||||
QStringList layout_layers;
|
||||
QString current_layer;
|
||||
|
||||
// TODO: qstring, or {section name, x, y, section_id, has_map}
|
||||
QMap<QString, QList<LayoutSquare>> layouts; // key: layer, value: layout list
|
||||
|
||||
// TODO
|
||||
QString city_map_tiles_path;
|
||||
|
||||
// todo: no???? why would i be doing this it's pointless
|
||||
// let the user figure this shit out
|
||||
bool region_map_png_needs_saving = false;
|
||||
bool city_map_png_needs_saving = false;
|
||||
|
||||
int img_index_(int x, int y);
|
||||
int layout_index_(int x, int y);
|
||||
int get_tilemap_index(int x, int y);
|
||||
int get_layout_index(int x, int y);
|
||||
};
|
||||
|
||||
#endif // REGIONMAP_H
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "wildmoninfo.h"
|
||||
#include "parseutil.h"
|
||||
#include "orderedjson.h"
|
||||
#include "regionmap.h"
|
||||
|
||||
#include <QStringList>
|
||||
#include <QList>
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "regionmaplayoutpixmapitem.h"
|
||||
#include "regionmapentriespixmapitem.h"
|
||||
#include "regionmap.h"
|
||||
#include "orderedjson.h"
|
||||
#include "project.h"
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
@@ -24,9 +26,10 @@ public:
|
||||
explicit RegionMapEditor(QWidget *parent = 0, Project *pro = nullptr);
|
||||
~RegionMapEditor();
|
||||
|
||||
RegionMap *region_map;
|
||||
RegionMap *region_map = nullptr;
|
||||
tsl::ordered_map<QString, RegionMap *> region_maps;
|
||||
|
||||
bool loadRegionMapData();
|
||||
bool load();
|
||||
bool loadCityMaps();
|
||||
void setCurrentSquareOptions();
|
||||
|
||||
@@ -56,9 +59,11 @@ private:
|
||||
Ui::RegionMapEditor *ui;
|
||||
Project *project;
|
||||
|
||||
poryjson::Json rmConfigJson;
|
||||
|
||||
History<RegionMapHistoryItem*> history;
|
||||
|
||||
int currIndex;
|
||||
int currIndex = 0;
|
||||
unsigned selectedCityTile;
|
||||
unsigned selectedImageTile;
|
||||
QString activeEntry;
|
||||
@@ -86,6 +91,17 @@ private:
|
||||
RegionMapPixmapItem *region_map_item = nullptr;
|
||||
CityMapPixmapItem *city_map_item = nullptr;
|
||||
|
||||
bool loadRegionMapEntries();
|
||||
bool saveRegionMapEntries();
|
||||
tsl::ordered_map<QString, MapSectionEntry> region_map_entries;
|
||||
|
||||
void buildConfigDialog();
|
||||
poryjson::Json configRegionMapDialog();
|
||||
void buildUpdateConfigDialog();
|
||||
poryjson::Json buildDefaultJson();
|
||||
poryjson::Json getJsonFromAlias(QString alias);
|
||||
bool loadRegionMapData();
|
||||
|
||||
void initShortcuts();
|
||||
void displayRegionMap();
|
||||
void displayRegionMapImage();
|
||||
@@ -94,11 +110,11 @@ private:
|
||||
void displayRegionMapLayoutOptions();
|
||||
void updateRegionMapLayoutOptions(int index);
|
||||
void displayRegionMapTileSelector();
|
||||
void updateLayerDisplayed();
|
||||
void displayCityMapTileSelector();
|
||||
void displayCityMap(QString name);
|
||||
void displayRegionMapEntryOptions();
|
||||
void updateRegionMapEntryOptions(QString);
|
||||
void importTileImage(bool city = false);
|
||||
|
||||
bool createCityMap(QString name);
|
||||
bool tryInsertNewMapEntry(QString);
|
||||
@@ -114,21 +130,22 @@ private slots:
|
||||
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_textActivated(const QString &);
|
||||
void on_comboBox_RM_Entry_MapSection_textActivated(const QString &);
|
||||
void on_comboBox_regionSelector_textActivated(const QString &);
|
||||
void on_comboBox_layoutLayer_textActivated(const QString &);
|
||||
void on_spinBox_RM_Entry_x_valueChanged(int);
|
||||
void on_spinBox_RM_Entry_y_valueChanged(int);
|
||||
void on_spinBox_RM_Entry_width_valueChanged(int);
|
||||
void on_spinBox_RM_Entry_height_valueChanged(int);
|
||||
void on_spinBox_tilePalette_valueChanged(int);
|
||||
void on_checkBox_tileHFlip_stateChanged(int);
|
||||
void on_checkBox_tileVFlip_stateChanged(int);
|
||||
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 &);
|
||||
void on_lineEdit_RM_MapName_textEdited(const QString &);
|
||||
void onHoveredRegionMapTileChanged(int x, int y);
|
||||
|
||||
47
include/ui/regionmappropertiesdialog.h
Normal file
47
include/ui/regionmappropertiesdialog.h
Normal file
@@ -0,0 +1,47 @@
|
||||
#ifndef REGIONMAPPROPERTIESDIALOG_H
|
||||
#define REGIONMAPPROPERTIESDIALOG_H
|
||||
|
||||
#include "orderedjson.h"
|
||||
|
||||
#include <QDialog>
|
||||
#include <QFileDialog>
|
||||
|
||||
class Project;
|
||||
|
||||
namespace Ui {
|
||||
class RegionMapPropertiesDialog;
|
||||
}
|
||||
|
||||
class RegionMapPropertiesDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RegionMapPropertiesDialog(QWidget *parent = nullptr);
|
||||
~RegionMapPropertiesDialog();
|
||||
|
||||
void setProject(Project *project) { this->project = project; }
|
||||
|
||||
void setProperties(poryjson::Json object);
|
||||
poryjson::Json saveToJson();
|
||||
|
||||
virtual void accept() override;
|
||||
|
||||
private:
|
||||
Ui::RegionMapPropertiesDialog *ui;
|
||||
Project *project = nullptr;
|
||||
|
||||
void hideMessages();
|
||||
|
||||
QString browse(QString filter, QFileDialog::FileMode mode);
|
||||
|
||||
private slots:
|
||||
void on_browse_tilesetImagePath_clicked();
|
||||
void on_browse_tilemapBinPath_clicked();
|
||||
void on_browse_tilemapPalettePath_clicked();
|
||||
void on_browse_layoutPath_clicked();
|
||||
|
||||
//void on_buttonBox_accepted();
|
||||
};
|
||||
|
||||
#endif // REGIONMAPPROPERTIESDIALOG_H
|
||||
@@ -1,29 +1,146 @@
|
||||
#pragma once
|
||||
#ifndef TILEMAPTILESELECTOR_H
|
||||
#define TILEMAPTILESELECTOR_H
|
||||
|
||||
#include "selectablepixmapitem.h"
|
||||
#include "paletteutil.h"
|
||||
|
||||
#include <memory>
|
||||
using std::shared_ptr;
|
||||
|
||||
enum class TilemapFormat { Plain, BPP_4, BPP_8 };
|
||||
|
||||
class TilemapTile {
|
||||
unsigned raw_ = 0;
|
||||
unsigned id_ = 0;
|
||||
bool hFlip_ = false;
|
||||
bool vFlip_ = false;
|
||||
int palette_ = 0;
|
||||
|
||||
protected:
|
||||
TilemapTile(unsigned raw, unsigned id, bool hFlip, bool vFlip, int palette) : raw_(raw), id_(id), hFlip_(hFlip), vFlip_(vFlip), palette_(palette) {}
|
||||
virtual ~TilemapTile() {}
|
||||
|
||||
public:
|
||||
TilemapTile()=default;
|
||||
|
||||
TilemapTile(TilemapTile &other) {
|
||||
this->raw_ = other.raw();
|
||||
this->id_ = other.id();
|
||||
this->hFlip_ = other.hFlip();
|
||||
this->vFlip_ = other.vFlip();
|
||||
this->palette_ = other.palette();
|
||||
}
|
||||
|
||||
TilemapTile &operator=(const TilemapTile &other) {
|
||||
this->raw_ = other.raw();
|
||||
this->id_ = other.id();
|
||||
this->hFlip_ = other.hFlip();
|
||||
this->vFlip_ = other.vFlip();
|
||||
this->palette_ = other.palette();
|
||||
return *this;
|
||||
}
|
||||
|
||||
virtual void copy(TilemapTile &other) {
|
||||
this->raw_ = other.raw();
|
||||
this->id_ = other.id();
|
||||
this->hFlip_ = other.hFlip();
|
||||
this->vFlip_ = other.vFlip();
|
||||
this->palette_ = other.palette();
|
||||
}
|
||||
|
||||
virtual unsigned raw() const { return this->raw_; }
|
||||
virtual unsigned id() const { return this->id_; }
|
||||
virtual bool hFlip() const { return this->hFlip_; }
|
||||
virtual bool vFlip() const { return this->vFlip_; }
|
||||
virtual int palette() const { return this->palette_; }
|
||||
|
||||
virtual void setId(unsigned id) { this->id_ = id; }
|
||||
virtual void setHFlip(bool hFlip) { this->hFlip_ = hFlip; }
|
||||
virtual void setVFlip(bool vFlip) { this->vFlip_ = vFlip; }
|
||||
virtual void setPalette(int palette) { this->palette_ = palette; }
|
||||
|
||||
virtual QString info() {
|
||||
return QString("Tile: 0x") + QString("%1 ").arg(this->id(), 4, 16, QChar('0')).toUpper();
|
||||
}
|
||||
};
|
||||
|
||||
class PlainTile : public TilemapTile {
|
||||
public:
|
||||
PlainTile(unsigned raw) : TilemapTile(raw, raw, false, false, 0) {}
|
||||
|
||||
~PlainTile() {}
|
||||
};
|
||||
|
||||
class BPP4Tile : public TilemapTile {
|
||||
public:
|
||||
BPP4Tile(unsigned raw) : TilemapTile(
|
||||
raw,
|
||||
raw & 0x3ff, // tileId
|
||||
!!(raw & 0x0400), // hFlip
|
||||
!!(raw & 0x0800), // vFlip
|
||||
(raw & 0xf000) >> 12 // palette
|
||||
) {}
|
||||
|
||||
~BPP4Tile() {}
|
||||
|
||||
virtual QString info() override {
|
||||
return TilemapTile::info() + QString("hFlip: %1 vFlip: %2 palette: %3").arg(this->hFlip()).arg(this->vFlip()).arg(this->palette());
|
||||
}
|
||||
};
|
||||
|
||||
class BPP8Tile : public TilemapTile {
|
||||
public:
|
||||
BPP8Tile(unsigned raw) : TilemapTile(
|
||||
raw,
|
||||
raw & 0x3ff, // tileId
|
||||
!!(raw & 0x0400), // hFlip
|
||||
!!(raw & 0x0800), // vFlip
|
||||
0 // palette
|
||||
) {}
|
||||
|
||||
~BPP8Tile() {}
|
||||
|
||||
virtual QString info() override {
|
||||
return TilemapTile::info() + QString("hFlip: %1 vFlip: %2").arg(this->hFlip()).arg(this->vFlip());
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
TilemapTileSelector(QString tilesetFilepath, TilemapFormat format, QString palFilepath): SelectablePixmapItem(8, 8, 1, 1) {
|
||||
this->tileset = QImage(tilesetFilepath);
|
||||
this->format = format;
|
||||
bool err;
|
||||
this->palette = PaletteUtil::parse(palFilepath, &err);
|
||||
this->setPixmap(QPixmap::fromImage(this->tileset));
|
||||
this->numTilesWide = this->tileset.width() / 8;
|
||||
this->selectedTile = 0x00;
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
void draw();
|
||||
void select(unsigned tileId);
|
||||
unsigned getSelectedTile();
|
||||
void setPalette();
|
||||
|
||||
int pixelWidth;
|
||||
int pixelHeight;
|
||||
|
||||
void select(unsigned tileId);
|
||||
unsigned selectedTile = 0;
|
||||
|
||||
QPixmap tilemap;
|
||||
QImage tileImg(unsigned tileId);
|
||||
void selectVFlip(bool hFlip) { this->tile_hFlip = hFlip; }
|
||||
bool tile_hFlip = false;
|
||||
|
||||
void selectHFlip(bool vFlip) { this->tile_vFlip = vFlip; }
|
||||
bool tile_vFlip = false;
|
||||
|
||||
void selectPalette(int palette) { this->tile_palette = palette; }
|
||||
int tile_palette = 0;
|
||||
|
||||
QImage tileset;
|
||||
TilemapFormat format = TilemapFormat::Plain;
|
||||
QList<QRgb> palette;
|
||||
QImage tileImg(shared_ptr<TilemapTile> tile);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
|
||||
Reference in New Issue
Block a user