Merge branch 'master' into refactor

This commit is contained in:
Diegoisawesome 2018-09-27 13:27:57 -05:00
commit 02fd5bbea6
14 changed files with 967 additions and 32 deletions

440
editor.h Executable file
View file

@ -0,0 +1,440 @@
#ifndef EDITOR_H
#define EDITOR_H
#include <QGraphicsScene>
#include <QGraphicsItemGroup>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsItemAnimation>
#include <QComboBox>
#include <QCheckBox>
#include <QCursor>
#include "project.h"
#include "ui_mainwindow.h"
class DraggablePixmapItem;
class MapPixmapItem;
class CollisionPixmapItem;
class ConnectionPixmapItem;
class MetatilesPixmapItem;
class BorderMetatilesPixmapItem;
class CurrentSelectedMetatilesPixmapItem;
class MovementPermissionsPixmapItem;
#define SWAP(a, b) do { if (a != b) { a ^= b; b ^= a; a ^= b; } } while (0)
class Editor : public QObject
{
Q_OBJECT
public:
Editor(Ui::MainWindow* ui);
public:
Ui::MainWindow* ui;
QObject *parent = nullptr;
Project *project = nullptr;
Map *map = nullptr;
void saveProject();
void save();
void undo();
void redo();
void setMap(QString map_name);
void updateCurrentMetatilesSelection();
void displayMap();
void displayMetatiles();
void displayBorderMetatiles();
void displayCurrentMetatilesSelection();
void redrawCurrentMetatilesSelection();
void displayCollisionMetatiles();
void displayElevationMetatiles();
void displayMapEvents();
void displayMapConnections();
void displayMapBorder();
void displayMapGrid();
void setEditingMap();
void setEditingCollision();
void setEditingObjects();
void setEditingConnections();
void setCurrentConnectionDirection(QString curDirection);
void updateCurrentConnectionDirection(QString curDirection);
void setConnectionsVisibility(bool visible);
void updateConnectionOffset(int offset);
void setConnectionMap(QString mapName);
void addNewConnection();
void removeCurrentConnection();
void updateDiveMap(QString mapName);
void updateEmergeMap(QString mapName);
void setSelectedConnectionFromMap(QString mapName);
void updatePrimaryTileset(QString tilesetLabel);
void updateSecondaryTileset(QString tilesetLabel);
void toggleBorderVisibility(bool visible);
DraggablePixmapItem *addMapEvent(Event *event);
void selectMapEvent(DraggablePixmapItem *object);
void selectMapEvent(DraggablePixmapItem *object, bool toggle);
DraggablePixmapItem *addNewEvent(QString event_type);
Event* createNewEvent(QString event_type);
void deleteEvent(Event *);
void updateSelectedEvents();
void redrawObject(DraggablePixmapItem *item);
QList<DraggablePixmapItem *> *getObjects();
QGraphicsScene *scene = nullptr;
QGraphicsPixmapItem *current_view = nullptr;
MapPixmapItem *map_item = nullptr;
ConnectionPixmapItem* selected_connection_item = nullptr;
QList<QGraphicsPixmapItem*> connection_items;
QList<ConnectionPixmapItem*> connection_edit_items;
CollisionPixmapItem *collision_item = nullptr;
QGraphicsItemGroup *events_group = nullptr;
QList<QGraphicsPixmapItem*> borderItems;
QList<QGraphicsLineItem*> gridLines;
QGraphicsScene *scene_metatiles = nullptr;
QGraphicsScene *scene_current_metatile_selection = nullptr;
QGraphicsScene *scene_selected_border_metatiles = nullptr;
QGraphicsScene *scene_collision_metatiles = nullptr;
QGraphicsScene *scene_elevation_metatiles = nullptr;
MetatilesPixmapItem *metatiles_item = nullptr;
BorderMetatilesPixmapItem *selected_border_metatiles_item = nullptr;
CurrentSelectedMetatilesPixmapItem *scene_current_metatile_selection_item = nullptr;
MovementPermissionsPixmapItem *collision_metatiles_item = nullptr;
QList<DraggablePixmapItem*> *events = nullptr;
QList<DraggablePixmapItem*> *selected_events = nullptr;
bool lastSelectedMetatilesFromMap = false;
int copiedMetatileSelectionWidth = 0;
int copiedMetatileSelectionHeight = 0;
QList<uint16_t> *copiedMetatileSelection = new QList<uint16_t>;
int scale_exp = 0;
double scale_base = sqrt(2); // adjust scale factor with this
QString map_edit_mode;
QString prev_edit_mode;
QCursor cursor;
void objectsView_onMousePress(QMouseEvent *event);
void objectsView_onMouseMove(QMouseEvent *event);
void objectsView_onMouseRelease(QMouseEvent *event);
private:
void setConnectionItemsVisible(bool);
void setBorderItemsVisible(bool, qreal = 1);
void setConnectionEditControlValues(Connection*);
void setConnectionEditControlsEnabled(bool);
void createConnectionItem(Connection* connection, bool hide);
void populateConnectionMapPickers();
void setDiveEmergeControls();
void updateDiveEmergeMap(QString mapName, QString direction);
void onConnectionOffsetChanged(int newOffset);
void removeMirroredConnection(Connection*);
void updateMirroredConnectionOffset(Connection*);
void updateMirroredConnectionDirection(Connection*, QString);
void updateMirroredConnectionMap(Connection*, QString);
void updateMirroredConnection(Connection*, QString, QString, bool isDelete = false);
Event* createNewObjectEvent();
Event* createNewWarpEvent();
Event* createNewHealLocationEvent();
Event* createNewCoordScriptEvent();
Event* createNewCoordWeatherEvent();
Event* createNewSignEvent();
Event* createNewHiddenItemEvent();
Event* createNewSecretBaseEvent();
private slots:
void mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item);
void mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item);
void onConnectionMoved(Connection*);
void onConnectionItemSelected(ConnectionPixmapItem* connectionItem);
void onConnectionItemDoubleClicked(ConnectionPixmapItem* connectionItem);
void onConnectionDirectionChanged(QString newDirection);
void onBorderMetatilesChanged();
signals:
void objectsChanged();
void selectedObjectsChanged();
void loadMapRequested(QString, QString);
void tilesetChanged(QString);
void warpEventDoubleClicked(QString mapName, QString warpNum);
void currentMetatilesSelectionChanged();
};
class DraggablePixmapItem : public QObject, public QGraphicsPixmapItem {
Q_OBJECT
public:
DraggablePixmapItem(QPixmap pixmap): QGraphicsPixmapItem(pixmap) {
}
Editor *editor = nullptr;
Event *event = nullptr;
QGraphicsItemAnimation *pos_anim = nullptr;
DraggablePixmapItem(Event *event_, Editor *editor_) : QGraphicsPixmapItem(event_->pixmap) {
event = event_;
editor = editor_;
updatePosition();
}
bool active;
int last_x;
int last_y;
void updatePosition() {
int x = event->getPixelX();
int y = event->getPixelY();
setX(x);
setY(y);
setZValue(event->y());
}
void move(int x, int y);
void emitPositionChanged() {
emit xChanged(event->x());
emit yChanged(event->y());
emit elevationChanged(event->elevation());
}
void updatePixmap() {
QList<Event*> objects;
objects.append(event);
event->pixmap = QPixmap();
editor->project->loadEventPixmaps(objects);
this->updatePosition();
editor->redrawObject(this);
emit spriteChanged(event->pixmap);
}
void bind(QComboBox *combo, QString key) {
connect(combo, static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
this, [this, key](QString value){
this->event->put(key, value);
});
connect(this, &DraggablePixmapItem::onPropertyChanged,
this, [combo, key](QString key2, QString value){
if (key2 == key) {
combo->addItem(value);
combo->setCurrentText(value);
}
});
}
signals:
void positionChanged(Event *event);
void xChanged(int);
void yChanged(int);
void elevationChanged(int);
void spriteChanged(QPixmap pixmap);
void onPropertyChanged(QString key, QString value);
public slots:
void set_x(const QString &text) {
event->put("x", text);
updatePosition();
}
void set_y(const QString &text) {
event->put("y", text);
updatePosition();
}
void set_elevation(const QString &text) {
event->put("elevation", text);
updatePosition();
}
void set_sprite(const QString &text) {
event->put("sprite", text);
updatePixmap();
}
void set_script(const QString &text) {
event->put("script_label", text);
}
protected:
void mousePressEvent(QGraphicsSceneMouseEvent*);
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*);
};
class EventGroup : public QGraphicsItemGroup {
};
class MapPixmapItem : public QObject, public QGraphicsPixmapItem {
Q_OBJECT
public:
MapPixmapItem(QPixmap pixmap): QGraphicsPixmapItem(pixmap) {
}
Map *map = nullptr;
Editor *editor = nullptr;
MapPixmapItem(Map *map_, Editor *editor_) {
map = map_;
editor = editor_;
setAcceptHoverEvents(true);
}
bool active;
bool right_click;
QPoint selection_origin;
QList<QPoint> selection;
virtual void paint(QGraphicsSceneMouseEvent*);
virtual void floodFill(QGraphicsSceneMouseEvent*);
void _floodFill(int x, int y);
void _floodFillSmartPath(int initialX, int initialY);
virtual void pick(QGraphicsSceneMouseEvent*);
virtual void select(QGraphicsSceneMouseEvent*);
virtual void shift(QGraphicsSceneMouseEvent*);
virtual void draw(bool ignoreCache = false);
void updateMetatileSelection(QGraphicsSceneMouseEvent *event);
private:
void updateCurHoveredTile(QPointF pos);
void paintNormal(int x, int y);
void paintSmartPath(int x, int y);
static QList<int> smartPathTable;
signals:
void mouseEvent(QGraphicsSceneMouseEvent *, MapPixmapItem *);
protected:
void hoverMoveEvent(QGraphicsSceneHoverEvent*);
void hoverLeaveEvent(QGraphicsSceneHoverEvent*);
void mousePressEvent(QGraphicsSceneMouseEvent*);
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
};
class CollisionPixmapItem : public MapPixmapItem {
Q_OBJECT
public:
CollisionPixmapItem(QPixmap pixmap): MapPixmapItem(pixmap) {
}
CollisionPixmapItem(Map *map_, Editor *editor_): MapPixmapItem(map_, editor_) {
}
void updateMovementPermissionSelection(QGraphicsSceneMouseEvent *event);
virtual void paint(QGraphicsSceneMouseEvent*);
virtual void floodFill(QGraphicsSceneMouseEvent*);
virtual void pick(QGraphicsSceneMouseEvent*);
virtual void draw(bool ignoreCache = false);
signals:
void mouseEvent(QGraphicsSceneMouseEvent *, CollisionPixmapItem *);
protected:
void mousePressEvent(QGraphicsSceneMouseEvent*);
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
};
class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem {
Q_OBJECT
public:
ConnectionPixmapItem(QPixmap pixmap, Connection* connection, int x, int y, int baseMapWidth, int baseMapHeight): QGraphicsPixmapItem(pixmap) {
this->basePixmap = pixmap;
this->connection = connection;
setFlag(ItemIsMovable);
setFlag(ItemSendsGeometryChanges);
this->initialX = x;
this->initialY = y;
this->initialOffset = connection->offset.toInt();
this->baseMapWidth = baseMapWidth;
this->baseMapHeight = baseMapHeight;
}
void render(qreal opacity = 1) {
QPixmap newPixmap = basePixmap.copy(0, 0, basePixmap.width(), basePixmap.height());
if (opacity < 1) {
QPainter painter(&newPixmap);
int alpha = static_cast<int>(255 * (1 - opacity));
painter.fillRect(0, 0, newPixmap.width(), newPixmap.height(), QColor(0, 0, 0, alpha));
painter.end();
}
this->setPixmap(newPixmap);
}
int getMinOffset();
int getMaxOffset();
QPixmap basePixmap;
Connection* connection;
int initialX;
int initialY;
int initialOffset;
int baseMapWidth;
int baseMapHeight;
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value);
void mousePressEvent(QGraphicsSceneMouseEvent*);
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*);
signals:
void connectionItemSelected(ConnectionPixmapItem* connectionItem);
void connectionItemDoubleClicked(ConnectionPixmapItem* connectionItem);
void connectionMoved(Connection*);
};
class MetatilesPixmapItem : public QObject, public QGraphicsPixmapItem {
Q_OBJECT
public:
MetatilesPixmapItem(Map *map_) {
map = map_;
setAcceptHoverEvents(true);
connect(map, SIGNAL(paintTileChanged()), this, SLOT(paintTileChanged()));
}
Map* map = nullptr;
virtual void draw();
private:
void updateSelection(QPointF pos);
protected:
virtual void updateCurHoveredMetatile(QPointF pos);
private slots:
void paintTileChanged();
protected:
void hoverMoveEvent(QGraphicsSceneHoverEvent*);
void hoverLeaveEvent(QGraphicsSceneHoverEvent*);
void mousePressEvent(QGraphicsSceneMouseEvent*);
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
};
class BorderMetatilesPixmapItem : public QObject, public QGraphicsPixmapItem {
Q_OBJECT
public:
BorderMetatilesPixmapItem(Map *map_) {
map = map_;
setAcceptHoverEvents(true);
}
Map* map = nullptr;
virtual void draw();
signals:
void borderMetatilesChanged();
protected:
void mousePressEvent(QGraphicsSceneMouseEvent*);
};
class CurrentSelectedMetatilesPixmapItem : public QObject, public QGraphicsPixmapItem {
Q_OBJECT
public:
CurrentSelectedMetatilesPixmapItem(Map *map_) {
map = map_;
}
Map* map = nullptr;
virtual void draw();
};
class MovementPermissionsPixmapItem : public MetatilesPixmapItem {
Q_OBJECT
public:
MovementPermissionsPixmapItem(Map *map_): MetatilesPixmapItem(map_) {
connect(map, SIGNAL(paintCollisionChanged(Map*)), this, SLOT(paintCollisionChanged(Map *)));
}
virtual void pick(uint16_t collision, uint16_t elevation) {
map->paint_collision = collision;
map->paint_elevation = elevation;
draw();
}
virtual void draw() {
setPixmap(map->renderCollisionMetatiles());
}
protected:
void mousePressEvent(QGraphicsSceneMouseEvent*);
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
virtual void updateCurHoveredMetatile(QPointF pos);
private slots:
void paintCollisionChanged(Map *) {
draw();
}
};
#endif // EDITOR_H

234
map.h Executable file
View file

@ -0,0 +1,234 @@
#ifndef MAP_H
#define MAP_H
#include "tileset.h"
#include "blockdata.h"
#include "event.h"
#include <QPixmap>
#include <QObject>
#include <QDebug>
#include <QGraphicsPixmapItem>
#include <math.h>
class HistoryItem {
public:
Blockdata *metatiles;
int layoutWidth;
int layoutHeight;
HistoryItem(Blockdata *metatiles_, int layoutWidth_, int layoutHeight_) {
this->metatiles = metatiles_;
this->layoutWidth = layoutWidth_;
this->layoutHeight = layoutHeight_;
}
~HistoryItem() {
if (metatiles) delete metatiles;
}
};
template <typename T>
class History {
public:
History() {
}
T back() {
if (head > 0) {
return history.at(--head);
}
return NULL;
}
T next() {
if (head + 1 < history.length()) {
return history.at(++head);
}
return NULL;
}
void push(T commit) {
while (head + 1 < history.length()) {
HistoryItem *item = history.last();
history.removeLast();
delete item;
}
if (saved > head) {
saved = -1;
}
history.append(commit);
head++;
}
T current() {
if (head < 0 || history.length() == 0) {
return NULL;
}
return history.at(head);
}
void save() {
saved = head;
}
bool isSaved() {
return saved == head;
}
private:
QList<T> history;
int head = -1;
int saved = -1;
};
class Connection {
public:
Connection() {
}
public:
QString direction;
QString offset;
QString map_name;
};
class MapLayout {
public:
MapLayout() {}
int index;
QString name;
QString label;
QString width;
QString height;
QString border_label;
QString border_path;
QString blockdata_label;
QString blockdata_path;
QString tileset_primary_label;
QString tileset_secondary_label;
Tileset *tileset_primary = nullptr;
Tileset *tileset_secondary = nullptr;
Blockdata* blockdata = nullptr;
QImage border_image;
QPixmap border_pixmap;
Blockdata *border = nullptr;
Blockdata *cached_blockdata = nullptr;
Blockdata *cached_collision = nullptr;
Blockdata *cached_border = nullptr;
bool has_unsaved_changes = false;
public:
static QString getNameFromLabel(QString label) {
// ASSUMPTION: strip off "_Layout" from layout label. Directories in 'data/layouts/' must be well-formed.
return label.replace(label.lastIndexOf("_Layout"), label.length(), "");
}
};
class Map : public QObject
{
Q_OBJECT
public:
explicit Map(QObject *parent = nullptr);
public:
QString name;
QString constantName;
QString group_num;
QString layout_label;
QString events_label;
QString scripts_label;
QString connections_label;
QString song;
QString layout_id;
QString location;
QString requiresFlash;
QString isFlyable; // TODO: implement this
QString weather;
QString type;
QString unknown;
QString show_location;
QString battle_scene;
MapLayout *layout;
bool isPersistedToFile = true;
public:
void setName(QString mapName);
static QString mapConstantFromName(QString mapName);
static QString objectEventsLabelFromName(QString mapName);
static QString warpEventsLabelFromName(QString mapName);
static QString coordEventsLabelFromName(QString mapName);
static QString bgEventsLabelFromName(QString mapName);
int getWidth();
int getHeight();
uint16_t getSelectedBlockIndex(int);
int getDisplayedBlockIndex(int);
QPixmap render(bool ignoreCache);
QPixmap renderMetatiles();
QPixmap renderCollision(bool ignoreCache);
QImage collision_image;
QPixmap collision_pixmap;
QImage getCollisionMetatileImage(Block);
QImage getCollisionMetatileImage(int, int);
QPixmap renderCollisionMetatiles();
void drawSelection(int i, int w, int selectionWidth, int selectionHeight, QPainter *painter, int gridWidth);
bool blockChanged(int, Blockdata*);
void cacheBlockdata();
void cacheCollision();
QImage image;
QPixmap pixmap;
QList<QImage> metatile_images;
bool smart_paths_enabled = false;
int paint_metatile_initial_x;
int paint_metatile_initial_y;
int paint_tile_index;
int paint_tile_width = 1;
int paint_tile_height = 1;
int paint_tile_initial_x;
int paint_tile_initial_y;
int selected_metatiles_width;
int selected_metatiles_height;
QList<uint16_t> *selected_metatiles = nullptr;
uint16_t paint_collision;
uint16_t paint_elevation;
Block *getBlock(int x, int y);
void setBlock(int x, int y, Block block);
void _setBlock(int x, int y, Block block);
void floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation);
void _floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation);
History<HistoryItem*> history;
void undo();
void redo();
void commit();
QList<Event*> getAllEvents();
void removeEvent(Event *event);
void addEvent(Event *event);
QMap<QString, QList<Event*>> events;
QList<Connection*> connections;
QPixmap renderConnection(Connection);
void setNewDimensionsBlockdata(int newWidth, int newHeight);
void setDimensions(int newWidth, int newHeight, bool setNewBlockData = true);
QPixmap renderBorder();
void cacheBorder();
bool hasUnsavedChanges();
void hoveredTileChanged(int x, int y, int block);
void clearHoveredTile();
void hoveredMetatileChanged(int block);
void clearHoveredMetatile();
void hoveredMovementPermissionTileChanged(int collision, int elevation);
void clearHoveredMovementPermissionTile();
void setSelectedMetatilesFromTilePicker();
signals:
void paintTileChanged();
void paintCollisionChanged(Map *map);
void mapChanged(Map *map);
void mapNeedsRedrawing();
void statusBarMessage(QString);
public slots:
};
#endif // MAP_H

58
porymap.pro Executable file
View file

@ -0,0 +1,58 @@
#-------------------------------------------------
#
# Project created by QtCreator 2016-08-31T15:19:13
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = porymap
TEMPLATE = app
RC_ICONS = resources/icons/porymap-icon-1.ico
ICON = resources/icons/porymap-icon-1.ico
SOURCES += main.cpp\
mainwindow.cpp \
project.cpp \
map.cpp \
blockdata.cpp \
block.cpp \
tileset.cpp \
tile.cpp \
event.cpp \
editor.cpp \
objectpropertiesframe.cpp \
graphicsview.cpp \
parseutil.cpp \
neweventtoolbutton.cpp \
noscrollcombobox.cpp \
noscrollspinbox.cpp \
heallocation.cpp \
mapsceneeventfilter.cpp
HEADERS += mainwindow.h \
project.h \
map.h \
blockdata.h \
block.h \
tileset.h \
tile.h \
event.h \
editor.h \
objectpropertiesframe.h \
graphicsview.h \
parseutil.h \
neweventtoolbutton.h \
noscrollcombobox.h \
noscrollspinbox.h \
heallocation.h \
mapsceneeventfilter.h
FORMS += mainwindow.ui \
objectpropertiesframe.ui
RESOURCES += \
resources/images.qrc

View file

@ -40,8 +40,6 @@ public:
QString show_location;
QString battle_scene;
MapLayout *layout;
int scale_exp = 0;
double scale_base = sqrt(2); // adjust scale factor with this
bool isPersistedToFile = true;
QImage collision_image;
QPixmap collision_pixmap;

View file

@ -3,6 +3,7 @@
#include "imageproviders.h"
#include "mapconnection.h"
#include "currentselectedmetatilespixmapitem.h"
#include "mapsceneeventfilter.h"
#include <QCheckBox>
#include <QPainter>
#include <QMouseEvent>
@ -348,7 +349,7 @@ void Editor::onHoveredMapMetatileChanged(int x, int y) {
.arg(x)
.arg(y)
.arg(QString("%1").arg(tile, 3, 16, QChar('0')).toUpper())
.arg(QString::number(pow(map->scale_base, map->scale_exp))));
.arg(QString::number(pow(scale_base, scale_exp))));
}
}
@ -461,8 +462,12 @@ void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixm
}
void Editor::displayMap() {
if (!scene)
if (!scene) {
scene = new QGraphicsScene;
MapSceneEventFilter *filter = new MapSceneEventFilter();
scene->installEventFilter(filter);
connect(filter, &MapSceneEventFilter::wheelZoom, this, &Editor::wheelZoom);
}
if (map_item && scene) {
scene->removeItem(map_item);

View file

@ -110,6 +110,9 @@ public:
QString map_edit_mode;
QString prev_edit_mode;
int scale_exp = 0;
double scale_base = sqrt(2); // adjust scale factor with this
void objectsView_onMousePress(QMouseEvent *event);
void objectsView_onMouseMove(QMouseEvent *event);
void objectsView_onMouseRelease(QMouseEvent *event);
@ -164,6 +167,7 @@ signals:
void tilesetChanged(QString);
void warpEventDoubleClicked(QString mapName, QString warpNum);
void currentMetatilesSelectionChanged();
void wheelZoom(int delta);
};

View file

@ -32,6 +32,7 @@ MainWindow::MainWindow(QWidget *parent) :
{
QCoreApplication::setOrganizationName("pret");
QCoreApplication::setApplicationName("porymap");
QApplication::setApplicationDisplayName("porymap");
QApplication::setWindowIcon(QIcon(":/icons/porymap-icon-1.ico"));
ui->setupUi(this);
@ -50,6 +51,8 @@ MainWindow::~MainWindow()
void MainWindow::initExtraShortcuts() {
new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Z), this, SLOT(redo()));
new QShortcut(QKeySequence("Ctrl+0"), this, SLOT(resetMapViewScale()));
ui->actionZoom_In->setShortcuts({QKeySequence("Ctrl++"), QKeySequence("Ctrl+=")});
}
void MainWindow::initExtraSignals() {
@ -64,6 +67,7 @@ void MainWindow::initEditor() {
connect(this->editor, SIGNAL(tilesetChanged(QString)), this, SLOT(onTilesetChanged(QString)));
connect(this->editor, SIGNAL(warpEventDoubleClicked(QString,QString)), this, SLOT(openWarpMap(QString,QString)));
connect(this->editor, SIGNAL(currentMetatilesSelectionChanged()), this, SLOT(currentMetatilesSelectionChanged()));
connect(this->editor, &Editor::wheelZoom, this, &MainWindow::scaleMapView);
this->loadUserSettings();
}
@ -103,12 +107,12 @@ void MainWindow::openProject(QString dir) {
if (!already_open) {
editor->project = new Project;
editor->project->root = dir;
setWindowTitle(editor->project->getProjectTitle() + " - porymap");
setWindowTitle(editor->project->getProjectTitle());
loadDataStructures();
populateMapList();
setMap(getDefaultMap());
} else {
setWindowTitle(editor->project->getProjectTitle() + " - porymap");
setWindowTitle(editor->project->getProjectTitle());
loadDataStructures();
populateMapList();
}
@ -180,7 +184,7 @@ void MainWindow::setMap(QString map_name) {
redrawMapScene();
displayMapProperties();
setWindowTitle(map_name + " - " + editor->project->getProjectTitle() + " - porymap");
setWindowTitle(map_name + " - " + editor->project->getProjectTitle());
connect(editor->map, SIGNAL(mapChanged(Map*)), this, SLOT(onMapChanged(Map *)));
connect(editor->map, SIGNAL(mapNeedsRedrawing()), this, SLOT(onMapNeedsRedrawing()));
@ -194,18 +198,24 @@ void MainWindow::redrawMapScene()
editor->displayMap();
on_tabWidget_currentChanged(ui->tabWidget->currentIndex());
double base = editor->scale_base;
double exp = editor->scale_exp;
int width = static_cast<int>(ceil((editor->scene->width()) * pow(base,exp))) + 2;
int height = static_cast<int>(ceil((editor->scene->height()) * pow(base,exp))) + 2;
ui->graphicsView_Map->setScene(editor->scene);
ui->graphicsView_Map->setSceneRect(editor->scene->sceneRect());
ui->graphicsView_Map->setFixedSize(static_cast<int>(editor->scene->width()) + 2, static_cast<int>(editor->scene->height()) + 2);
ui->graphicsView_Map->setFixedSize(width, height);
ui->graphicsView_Objects_Map->setScene(editor->scene);
ui->graphicsView_Objects_Map->setSceneRect(editor->scene->sceneRect());
ui->graphicsView_Objects_Map->setFixedSize(static_cast<int>(editor->scene->width()) + 2, static_cast<int>(editor->scene->height()) + 2);
ui->graphicsView_Objects_Map->setFixedSize(width, height);
ui->graphicsView_Objects_Map->editor = editor;
ui->graphicsView_Connections->setScene(editor->scene);
ui->graphicsView_Connections->setSceneRect(editor->scene->sceneRect());
ui->graphicsView_Connections->setFixedSize(static_cast<int>(editor->scene->width()) + 2, static_cast<int>(editor->scene->height()) + 2);
ui->graphicsView_Connections->setFixedSize(width, height);
ui->graphicsView_Metatiles->setScene(editor->scene_metatiles);
//ui->graphicsView_Metatiles->setSceneRect(editor->scene_metatiles->sceneRect());
@ -520,7 +530,7 @@ void MainWindow::currentMetatilesSelectionChanged()
void MainWindow::on_mapList_activated(const QModelIndex &index)
{
QVariant data = index.data(Qt::UserRole);
if (!data.isNull()) {
if (index.data(MapListUserRoles::TypeRole) == "map_name" && !data.isNull()) {
setMap(data.toString());
}
}
@ -665,19 +675,33 @@ void MainWindow::on_actionMap_Shift_triggered()
}
void MainWindow::scaleMapView(int s) {
editor->map->scale_exp += s;
if ((editor->scale_exp + s) <= 5 && (editor->scale_exp + s) >= -2) // sane limits
{
if (s == 0)
{
s = -editor->scale_exp;
}
double base = editor->map->scale_base;
double exp = editor->map->scale_exp;
double sfactor = pow(base,s);
editor->scale_exp += s;
ui->graphicsView_Map->scale(sfactor,sfactor);
ui->graphicsView_Objects_Map->scale(sfactor,sfactor);
double base = editor->scale_base;
double exp = editor->scale_exp;
double sfactor = pow(base,s);
int width = static_cast<int>((editor->scene->width() + 2) * pow(base,exp));
int height = static_cast<int>((editor->scene->height() + 2) * pow(base,exp));
ui->graphicsView_Map->setFixedSize(width, height);
ui->graphicsView_Objects_Map->setFixedSize(width, height);
ui->graphicsView_Map->scale(sfactor,sfactor);
ui->graphicsView_Objects_Map->scale(sfactor,sfactor);
ui->graphicsView_Connections->scale(sfactor,sfactor);
int width = static_cast<int>(ceil((editor->scene->width()) * pow(base,exp))) + 2;
int height = static_cast<int>(ceil((editor->scene->height()) * pow(base,exp))) + 2;
ui->graphicsView_Map->setFixedSize(width, height);
ui->graphicsView_Objects_Map->setFixedSize(width, height);
ui->graphicsView_Connections->setFixedSize(width, height);
}
}
void MainWindow::resetMapViewScale() {
scaleMapView(0);
}
void MainWindow::addNewEvent(QString event_type)

View file

@ -25,6 +25,9 @@ public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
public slots:
void scaleMapView(int);
private slots:
void on_action_Open_Project_triggered();
void on_mapList_activated(const QModelIndex &index);
@ -118,6 +121,8 @@ private slots:
void on_checkBox_ToggleBorder_stateChanged(int arg1);
void resetMapViewScale();
private:
Ui::MainWindow *ui;
QStandardItemModel *mapListModel;
@ -141,7 +146,6 @@ private:
void displayMapProperties();
void checkToolButtons();
void scaleMapView(int);
void initExtraShortcuts();
void initExtraSignals();
void initEditor();

View file

@ -2195,7 +2195,7 @@
<string>Zoom In</string>
</property>
<property name="shortcut">
<string>+</string>
<string>Ctrl++</string>
</property>
</action>
<action name="actionZoom_Out">
@ -2203,7 +2203,7 @@
<string>Zoom Out</string>
</property>
<property name="shortcut">
<string>-</string>
<string>Ctrl+-</string>
</property>
</action>
<action name="actionBetter_Cursors">

View file

@ -43,7 +43,8 @@ SOURCES += core/block.cpp \
main.cpp \
mainwindow.cpp \
project.cpp \
settings.cpp
settings.cpp \
ui/mapsceneeventfilter.cpp
HEADERS += core/block.h \
core/blockdata.h \
@ -75,7 +76,8 @@ HEADERS += core/block.h \
editor.h \
mainwindow.h \
project.h \
settings.h
settings.h \
ui/mapsceneeventfilter.h
FORMS += mainwindow.ui \
eventpropertiesframe.ui

View file

@ -38,7 +38,11 @@ QImage getMetatileImage(int tile, Tileset *primaryTileset, Tileset *secondaryTil
if (tile_image.isNull()) {
// Some metatiles specify tiles that are outside the valid range.
// These are treated as completely transparent, so they can be skipped without
// being drawn.
// being drawn unless they're on the bottom layer, in which case we need
// a placeholder because garbage will be drawn otherwise.
if (layer == 0) {
metatile_painter.fillRect(x * 8, y * 8, 8, 8, palettes.value(0).value(0));
}
continue;
}

View file

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

View file

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

120
tileset.cpp Executable file
View file

@ -0,0 +1,120 @@
#include "tileset.h"
#include "project.h"
#include <QPainter>
#include <QImage>
#include <QDebug>
Tileset::Tileset()
{
}
Metatile::Metatile()
{
tiles = new QList<Tile>;
}
QImage Metatile::getMetatileImage(int tile, Tileset *primaryTileset, Tileset *secondaryTileset) {
QImage metatile_image(16, 16, QImage::Format_RGBA8888);
Metatile* metatile = Metatile::getMetatile(tile, primaryTileset, secondaryTileset);
if (!metatile || !metatile->tiles) {
metatile_image.fill(0xffffffff);
return metatile_image;
}
Tileset* blockTileset = Metatile::getBlockTileset(tile, primaryTileset, secondaryTileset);
if (!blockTileset) {
metatile_image.fill(0xffffffff);
return metatile_image;
}
QList<QList<QRgb>> palettes = Metatile::getBlockPalettes(primaryTileset, secondaryTileset);
QPainter metatile_painter(&metatile_image);
for (int layer = 0; layer < 2; layer++)
for (int y = 0; y < 2; y++)
for (int x = 0; x < 2; x++) {
Tile tile_ = metatile->tiles->value((y * 2) + x + (layer * 4));
QImage tile_image = Metatile::getMetatileTile(tile_.tile, primaryTileset, secondaryTileset);
if (tile_image.isNull()) {
// Some metatiles specify tiles that are outside the valid range.
// These are treated as completely transparent, so they can be skipped without
// being drawn unless they're on the bottom layer, in which case we need
// a placeholder.
if (layer == 0) {
metatile_painter.fillRect(x * 8, y * 8, 8, 8, palettes.value(0).value(0));
}
continue;
}
// Colorize the metatile tiles with its palette.
if (tile_.palette < palettes.length()) {
QList<QRgb> palette = palettes.value(tile_.palette);
for (int j = 0; j < palette.length(); j++) {
tile_image.setColor(j, palette.value(j));
}
} else {
qDebug() << "Tile is referring to invalid palette number: " << tile_.palette;
}
// The top layer of the metatile has its first color displayed at transparent.
if (layer > 0) {
QColor color(tile_image.color(0));
color.setAlpha(0);
tile_image.setColor(0, color.rgba());
}
QPoint origin = QPoint(x*8, y*8);
metatile_painter.drawImage(origin, tile_image.mirrored(tile_.xflip == 1, tile_.yflip == 1));
}
metatile_painter.end();
return metatile_image;
}
Metatile* Metatile::getMetatile(int index, Tileset *primaryTileset, Tileset *secondaryTileset) {
Tileset *tileset = Metatile::getBlockTileset(index, primaryTileset, secondaryTileset);
int local_index = Metatile::getBlockIndex(index);
if (!tileset || !tileset->metatiles) {
return nullptr;
}
Metatile *metatile = tileset->metatiles->value(local_index, nullptr);
return metatile;
}
QImage Metatile::getMetatileTile(int tile, Tileset *primaryTileset, Tileset *secondaryTileset) {
Tileset *tileset = Metatile::getBlockTileset(tile, primaryTileset, secondaryTileset);
int local_index = Metatile::getBlockIndex(tile);
if (!tileset || !tileset->tiles) {
return QImage();
}
return tileset->tiles->value(local_index, QImage());
}
Tileset* Metatile::getBlockTileset(int metatile_index, Tileset *primaryTileset, Tileset *secondaryTileset) {
if (metatile_index < Project::getNumMetatilesPrimary()) {
return primaryTileset;
} else {
return secondaryTileset;
}
}
int Metatile::getBlockIndex(int index) {
if (index < Project::getNumMetatilesPrimary()) {
return index;
} else {
return index - Project::getNumMetatilesPrimary();
}
}
QList<QList<QRgb>> Metatile::getBlockPalettes(Tileset *primaryTileset, Tileset *secondaryTileset) {
QList<QList<QRgb>> palettes;
for (int i = 0; i < Project::getNumPalettesPrimary(); i++) {
palettes.append(primaryTileset->palettes->at(i));
}
for (int i = Project::getNumPalettesPrimary(); i < Project::getNumPalettesTotal(); i++) {
palettes.append(secondaryTileset->palettes->at(i));
}
return palettes;
}