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:
garak
2022-03-01 15:32:44 -05:00
committed by garakmon
parent c1e3415417
commit 1334369906
24 changed files with 3468 additions and 1976 deletions

View File

@@ -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

View File

@@ -9,6 +9,7 @@
#include "wildmoninfo.h"
#include "parseutil.h"
#include "orderedjson.h"
#include "regionmap.h"
#include <QStringList>
#include <QList>

View File

@@ -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);

View 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

View File

@@ -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*);