mirror of
https://github.com/huderlem/porymap.git
synced 2026-07-02 00:02:04 -05:00
Add event group limit
This commit is contained in:
parent
7fc985fc1d
commit
ac8db41299
|
|
@ -1341,6 +1341,29 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_MaxEvents" native="true">
|
||||
<layout class="QFormLayout" name="formLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_MaxEvents">
|
||||
<property name="text">
|
||||
<string>Maximum Events per Event group</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="NoScrollSpinBox" name="spinBox_MaxEvents">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Maps cannot have more than this number of events in each event group. Object events are additionally limited by 'define_obj_event_count' on the Identifiers tab.</p></body></html></string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_Events">
|
||||
<property name="title">
|
||||
|
|
|
|||
|
|
@ -319,6 +319,7 @@ public:
|
|||
this->unusedTileNormal = 0x3014;
|
||||
this->unusedTileCovered = 0x0000;
|
||||
this->unusedTileSplit = 0x0000;
|
||||
this->maxEventsPerGroup = 255;
|
||||
this->identifiers.clear();
|
||||
this->readKeys.clear();
|
||||
}
|
||||
|
|
@ -388,6 +389,7 @@ public:
|
|||
int collisionSheetWidth;
|
||||
int collisionSheetHeight;
|
||||
QList<uint32_t> warpBehaviors;
|
||||
int maxEventsPerGroup;
|
||||
|
||||
protected:
|
||||
virtual QString getConfigFilepath() override;
|
||||
|
|
|
|||
|
|
@ -110,9 +110,9 @@ public:
|
|||
|
||||
DraggablePixmapItem *addEventPixmapItem(Event *event);
|
||||
void removeEventPixmapItem(Event *event);
|
||||
bool eventLimitReached(Map *, Event::Type);
|
||||
bool canAddEvents(const QList<Event*> &events);
|
||||
void selectMapEvent(DraggablePixmapItem *item, bool toggle = false);
|
||||
DraggablePixmapItem *addNewEvent(Event::Type type);
|
||||
Event *addNewEvent(Event::Type type);
|
||||
void updateSelectedEvents();
|
||||
void duplicateSelectedEvents();
|
||||
void redrawAllEvents();
|
||||
|
|
@ -185,7 +185,6 @@ public:
|
|||
void shouldReselectEvents();
|
||||
void scaleMapView(int);
|
||||
static void openInTextEditor(const QString &path, int lineNum = 0);
|
||||
bool eventLimitReached(Event::Type type);
|
||||
void setCollisionGraphics();
|
||||
|
||||
public slots:
|
||||
|
|
|
|||
|
|
@ -218,7 +218,6 @@ private slots:
|
|||
void on_actionMove_triggered();
|
||||
void on_actionMap_Shift_triggered();
|
||||
|
||||
void addNewEvent(Event::Type type);
|
||||
void tryAddEventTab(QWidget * tab);
|
||||
void displayEventTabs();
|
||||
void updateSelectedEvents();
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ public:
|
|||
static int getMapDataSize(int width, int height);
|
||||
static bool mapDimensionsValid(int width, int height);
|
||||
bool calculateDefaultMapSize();
|
||||
static int getMaxObjectEvents();
|
||||
int getMaxEvents(Event::Group group);
|
||||
static QString getEmptyMapsecName();
|
||||
static QString getMapGroupPrefix();
|
||||
|
||||
|
|
@ -263,6 +263,8 @@ private:
|
|||
void ignoreWatchedFileTemporarily(QString filepath);
|
||||
void recordFileChange(const QString &filepath);
|
||||
|
||||
int maxEventsPerGroup;
|
||||
int maxObjectEvents;
|
||||
static int num_tiles_primary;
|
||||
static int num_tiles_total;
|
||||
static int num_metatiles_primary;
|
||||
|
|
@ -270,7 +272,6 @@ private:
|
|||
static int num_pals_total;
|
||||
static int max_map_data_size;
|
||||
static int default_map_dimension;
|
||||
static int max_object_events;
|
||||
|
||||
signals:
|
||||
void fileChanged(const QString &filepath);
|
||||
|
|
|
|||
|
|
@ -803,6 +803,8 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
|
|||
const QStringList behaviorList = value.split(",", Qt::SkipEmptyParts);
|
||||
for (auto s : behaviorList)
|
||||
this->warpBehaviors.append(getConfigUint32(key, s));
|
||||
} else if (key == "max_events_per_group") {
|
||||
this->maxEventsPerGroup = getConfigInteger(key, value, 1, INT_MAX, 255);
|
||||
} else {
|
||||
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
|
||||
}
|
||||
|
|
@ -898,6 +900,7 @@ QMap<QString, QString> ProjectConfig::getKeyValueMap() {
|
|||
for (const auto &value : this->warpBehaviors)
|
||||
warpBehaviorStrs.append("0x" + QString("%1").arg(value, 2, 16, QChar('0')).toUpper());
|
||||
map.insert("warp_behaviors", warpBehaviorStrs.join(","));
|
||||
map.insert("max_events_per_group", QString::number(this->maxEventsPerGroup));
|
||||
|
||||
return map;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1330,17 +1330,13 @@ void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, LayoutPixmapItem *i
|
|||
} else {
|
||||
// Left-clicking while in paint mode will add a new event of the
|
||||
// type of the first currently selected events.
|
||||
// Disallow adding heal locations, deleting them is not possible yet
|
||||
Event::Type eventType = Event::Type::Object;
|
||||
if (this->selected_events->size() > 0)
|
||||
eventType = this->selected_events->first()->event->getEventType();
|
||||
|
||||
DraggablePixmapItem *newEvent = addNewEvent(eventType);
|
||||
if (newEvent) {
|
||||
newEvent->move(pos.x(), pos.y());
|
||||
emit eventsChanged();
|
||||
selectMapEvent(newEvent);
|
||||
}
|
||||
Event* event = addNewEvent(eventType);
|
||||
if (event && event->getPixmapItem())
|
||||
event->getPixmapItem()->moveTo(pos);
|
||||
}
|
||||
} else if (eventEditAction == EditAction::Select) {
|
||||
// do nothing here, at least for now
|
||||
|
|
@ -2083,47 +2079,66 @@ void Editor::selectedEventIndexChanged(int index, Event::Group eventGroup) {
|
|||
}
|
||||
}
|
||||
|
||||
void Editor::duplicateSelectedEvents() {
|
||||
if (!selected_events || !selected_events->length() || !map || !current_view || this->getEditingLayout())
|
||||
return;
|
||||
bool Editor::canAddEvents(const QList<Event*> &events) {
|
||||
if (!this->project || !this->map)
|
||||
return false;
|
||||
|
||||
QList<Event *> selectedEvents;
|
||||
for (int i = 0; i < selected_events->length(); i++) {
|
||||
Event *original = selected_events->at(i)->event;
|
||||
Event::Type eventType = original->getEventType();
|
||||
if (eventLimitReached(eventType)) {
|
||||
logWarn(QString("Skipping duplication, the map limit for events of type '%1' has been reached.").arg(Event::typeToString(eventType)));
|
||||
continue;
|
||||
QMap<Event::Group, int> newEventCounts;
|
||||
for (const auto &event : events) {
|
||||
Event::Group group = event->getEventGroup();
|
||||
int maxEvents = this->project->getMaxEvents(group);
|
||||
if (this->map->getNumEvents(group) + newEventCounts[group]++ >= maxEvents) {
|
||||
return false;
|
||||
}
|
||||
Event *duplicate = original->duplicate();
|
||||
duplicate->setX(duplicate->getX() + 1);
|
||||
duplicate->setY(duplicate->getY() + 1);
|
||||
selectedEvents.append(duplicate);
|
||||
}
|
||||
map->commit(new EventDuplicate(this, map, selectedEvents));
|
||||
return true;
|
||||
}
|
||||
|
||||
DraggablePixmapItem *Editor::addNewEvent(Event::Type type) {
|
||||
if (!project || !map || eventLimitReached(type))
|
||||
void Editor::duplicateSelectedEvents() {
|
||||
if (!selected_events || !selected_events->length() || !project || !map || !current_view || this->getEditingLayout())
|
||||
return;
|
||||
|
||||
QList<Event *> duplicatedEvents;
|
||||
for (int i = 0; i < selected_events->length(); i++) {
|
||||
duplicatedEvents.append(selected_events->at(i)->event->duplicate());
|
||||
}
|
||||
if (!canAddEvents(duplicatedEvents)) {
|
||||
WarningMessage::show(QStringLiteral("Unable to duplicate, the maximum number of events would be exceeded."), ui->graphicsView_Map);
|
||||
qDeleteAll(duplicatedEvents);
|
||||
return;
|
||||
}
|
||||
this->map->commit(new EventDuplicate(this, this->map, duplicatedEvents));
|
||||
}
|
||||
|
||||
Event *Editor::addNewEvent(Event::Type type) {
|
||||
if (!this->project || !this->map)
|
||||
return nullptr;
|
||||
|
||||
Event::Group group = Event::typeToGroup(type);
|
||||
int maxEvents = this->project->getMaxEvents(group);
|
||||
if (this->map->getNumEvents(group) >= maxEvents) {
|
||||
WarningMessage::show(QString("The maximum number of %1 events (%2) has been reached.").arg(Event::groupToString(group)).arg(maxEvents), ui->graphicsView_Map);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Event *event = Event::create(type);
|
||||
if (!event)
|
||||
return nullptr;
|
||||
|
||||
event->setMap(this->map);
|
||||
event->setDefaultValues(this->project);
|
||||
map->commit(new EventCreate(this, map, event));
|
||||
return event->getPixmapItem();
|
||||
}
|
||||
|
||||
// Currently only object events have an explicit limit
|
||||
bool Editor::eventLimitReached(Event::Type event_type) {
|
||||
if (project && map) {
|
||||
if (Event::typeToGroup(event_type) == Event::Group::Object)
|
||||
return map->getNumEvents(Event::Group::Object) >= project->getMaxObjectEvents();
|
||||
// This will add the event to the map, create the event pixmap item, and select the event.
|
||||
this->map->commit(new EventCreate(this, this->map, event));
|
||||
|
||||
auto pixmapItem = event->getPixmapItem();
|
||||
if (pixmapItem) {
|
||||
auto halfSize = ui->graphicsView_Map->size() / 2;
|
||||
auto centerPos = ui->graphicsView_Map->mapToScene(halfSize.width(), halfSize.height());
|
||||
pixmapItem->moveTo(Metatile::coordFromPixmapCoord(centerPos));
|
||||
}
|
||||
return false;
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
void Editor::deleteSelectedEvents() {
|
||||
|
|
|
|||
|
|
@ -264,8 +264,6 @@ void MainWindow::initCustomUI() {
|
|||
}
|
||||
|
||||
void MainWindow::initExtraSignals() {
|
||||
// other signals
|
||||
connect(ui->newEventToolButton, &NewEventToolButton::newEventAdded, this, &MainWindow::addNewEvent);
|
||||
connect(ui->tabWidget_EventType, &QTabWidget::currentChanged, this, &MainWindow::eventTabChanged);
|
||||
|
||||
// Change pages on wild encounter groups
|
||||
|
|
@ -343,6 +341,7 @@ void MainWindow::initEditor() {
|
|||
connect(this->editor, &Editor::wildMonTableEdited, [this] { this->markMapEdited(); });
|
||||
connect(this->editor, &Editor::mapRulerStatusChanged, this, &MainWindow::onMapRulerStatusChanged);
|
||||
connect(this->editor, &Editor::tilesetUpdated, this, &Scripting::cb_TilesetUpdated);
|
||||
connect(ui->newEventToolButton, &NewEventToolButton::newEventAdded, this->editor, &Editor::addNewEvent);
|
||||
connect(ui->toolButton_deleteEvent, &QAbstractButton::clicked, this->editor, &Editor::deleteSelectedEvents);
|
||||
|
||||
this->loadUserSettings();
|
||||
|
|
@ -1304,7 +1303,7 @@ void MainWindow::onNewMapCreated(Map *newMap, const QString &groupName) {
|
|||
logInfo(QString("Created a new map named %1.").arg(newMap->name()));
|
||||
|
||||
if (newMap->needsHealLocation()) {
|
||||
addNewEvent(Event::Type::HealLocation);
|
||||
this->editor->addNewEvent(Event::Type::HealLocation);
|
||||
}
|
||||
|
||||
// TODO: Creating a new map shouldn't be automatically saved.
|
||||
|
|
@ -1750,14 +1749,7 @@ void MainWindow::paste() {
|
|||
QJsonArray events = pasteObject["events"].toArray();
|
||||
for (QJsonValue event : events) {
|
||||
// paste the event to the map
|
||||
const QString typeString = event["event_type"].toString();
|
||||
Event::Type type = Event::typeFromString(typeString);
|
||||
|
||||
if (this->editor->eventLimitReached(type)) {
|
||||
logWarn(QString("Cannot paste event, the limit for type '%1' has been reached.").arg(typeString));
|
||||
continue;
|
||||
}
|
||||
|
||||
Event::Type type = Event::typeFromString(event["event_type"].toString());
|
||||
Event *pasteEvent = Event::create(type);
|
||||
if (!pasteEvent)
|
||||
continue;
|
||||
|
|
@ -1766,12 +1758,16 @@ void MainWindow::paste() {
|
|||
pasteEvent->setMap(this->editor->map);
|
||||
newEvents.append(pasteEvent);
|
||||
}
|
||||
if (newEvents.empty())
|
||||
return;
|
||||
|
||||
if (!newEvents.empty()) {
|
||||
editor->map->commit(new EventPaste(this->editor, editor->map, newEvents));
|
||||
updateEvents();
|
||||
if (!this->editor->canAddEvents(newEvents)) {
|
||||
WarningMessage::show(QStringLiteral("Unable to paste, the maximum number of events would be exceeded."), this);
|
||||
qDeleteAll(newEvents);
|
||||
return;
|
||||
}
|
||||
|
||||
this->editor->map->commit(new EventPaste(this->editor, this->editor->map, newEvents));
|
||||
updateEvents();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1983,29 +1979,6 @@ void MainWindow::resetMapViewScale() {
|
|||
editor->scaleMapView(0);
|
||||
}
|
||||
|
||||
void MainWindow::addNewEvent(Event::Type type) {
|
||||
if (editor && editor->project) {
|
||||
DraggablePixmapItem *item = editor->addNewEvent(type);
|
||||
if (item) {
|
||||
auto halfSize = ui->graphicsView_Map->size() / 2;
|
||||
auto centerPos = ui->graphicsView_Map->mapToScene(halfSize.width(), halfSize.height());
|
||||
item->moveTo(Metatile::coordFromPixmapCoord(centerPos));
|
||||
updateEvents();
|
||||
editor->selectMapEvent(item);
|
||||
} else {
|
||||
WarningMessage msgBox(QStringLiteral("Failed to add new event."), this);
|
||||
if (Event::typeToGroup(type) == Event::Group::Object) {
|
||||
msgBox.setInformativeText(QString("The limit for object events (%1) has been reached.\n\n"
|
||||
"This limit can be adjusted with %2 in '%3'.")
|
||||
.arg(editor->project->getMaxObjectEvents())
|
||||
.arg(projectConfig.getIdentifier(ProjectIdentifier::define_obj_event_count))
|
||||
.arg(projectConfig.getFilePath(ProjectFilePath::constants_global)));
|
||||
}
|
||||
msgBox.exec();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::tryAddEventTab(QWidget * tab) {
|
||||
auto group = getEventGroupFromTabWidget(tab);
|
||||
if (editor->map->getNumEvents(group))
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ int Project::num_pals_primary = 6;
|
|||
int Project::num_pals_total = 13;
|
||||
int Project::max_map_data_size = 10240; // 0x2800
|
||||
int Project::default_map_dimension = 20;
|
||||
int Project::max_object_events = 64;
|
||||
|
||||
Project::Project(QObject *parent) :
|
||||
QObject(parent)
|
||||
|
|
@ -2578,21 +2577,22 @@ bool Project::readMiscellaneousConstants() {
|
|||
fileWatcher.addPath(root + "/" + filename);
|
||||
QMap<QString, int> defines = parser.readCDefinesByName(filename, {maxObjectEventsName});
|
||||
|
||||
this->maxObjectEvents = 64; // Default value
|
||||
auto it = defines.find(maxObjectEventsName);
|
||||
if (it != defines.end()) {
|
||||
if (it.value() > 0) {
|
||||
Project::max_object_events = it.value();
|
||||
this->maxObjectEvents = it.value();
|
||||
} else {
|
||||
logWarn(QString("Value for '%1' is %2, must be greater than 0. Using default (%3) instead.")
|
||||
.arg(maxObjectEventsName)
|
||||
.arg(it.value())
|
||||
.arg(Project::max_object_events));
|
||||
.arg(this->maxObjectEvents));
|
||||
}
|
||||
}
|
||||
else {
|
||||
logWarn(QString("Value for '%1' not found. Using default (%2) instead.")
|
||||
.arg(maxObjectEventsName)
|
||||
.arg(Project::max_object_events));
|
||||
.arg(this->maxObjectEvents));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -2943,9 +2943,14 @@ bool Project::calculateDefaultMapSize(){
|
|||
return true;
|
||||
}
|
||||
|
||||
int Project::getMaxObjectEvents()
|
||||
{
|
||||
return Project::max_object_events;
|
||||
// Object events have their own limit specified by ProjectIdentifier::define_obj_event_count.
|
||||
// The default value for this is 64. All events (object events included) are also limited by
|
||||
// the data types of the event counters in the project. This would normally be u8, so the limit is 255.
|
||||
// We let the users tell us this limit in case they change these data types.
|
||||
int Project::getMaxEvents(Event::Group group) {
|
||||
if (group == Event::Group::Object)
|
||||
return qMin(this->maxObjectEvents, projectConfig.maxEventsPerGroup);
|
||||
return projectConfig.maxEventsPerGroup;
|
||||
}
|
||||
|
||||
QString Project::getEmptyMapDefineName() {
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ void ProjectSettingsEditor::initUi() {
|
|||
ui->spinBox_UnusedTileNormal->setMaximum(Tile::maxValue);
|
||||
ui->spinBox_UnusedTileCovered->setMaximum(Tile::maxValue);
|
||||
ui->spinBox_UnusedTileSplit->setMaximum(Tile::maxValue);
|
||||
ui->spinBox_MaxEvents->setMaximum(INT_MAX);
|
||||
|
||||
// The values for some of the settings we provide in this window can be determined using constants in the user's projects.
|
||||
// If the user has these constants we disable these settings in the UI -- they can modify them using their constants.
|
||||
|
|
@ -464,6 +465,7 @@ void ProjectSettingsEditor::refresh() {
|
|||
ui->spinBox_UnusedTileNormal->setValue(projectConfig.unusedTileNormal);
|
||||
ui->spinBox_UnusedTileCovered->setValue(projectConfig.unusedTileCovered);
|
||||
ui->spinBox_UnusedTileSplit->setValue(projectConfig.unusedTileSplit);
|
||||
ui->spinBox_MaxEvents->setValue(projectConfig.maxEventsPerGroup);
|
||||
|
||||
// Set (and sync) border metatile IDs
|
||||
this->setBorderMetatileIds(false, projectConfig.newMapBorderMetatileIds);
|
||||
|
|
@ -538,6 +540,7 @@ void ProjectSettingsEditor::save() {
|
|||
projectConfig.unusedTileNormal = ui->spinBox_UnusedTileNormal->value();
|
||||
projectConfig.unusedTileCovered = ui->spinBox_UnusedTileCovered->value();
|
||||
projectConfig.unusedTileSplit = ui->spinBox_UnusedTileSplit->value();
|
||||
projectConfig.maxEventsPerGroup = ui->spinBox_MaxEvents->value();
|
||||
|
||||
// Save line edit settings
|
||||
projectConfig.prefabFilepath = ui->lineEdit_PrefabsPath->text();
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user