Jelajahi Sumber

Merge pull request #3032 from Nordsoft91/editor-improvements-1.4

Random dwellings can be connected to town types
Nordsoft91 2 tahun lalu
induk
melakukan
3f3c079c0e

+ 2 - 0
mapeditor/CMakeLists.txt

@@ -34,6 +34,7 @@ set(editor_SRCS
 		inspector/rewardswidget.cpp
 		inspector/questwidget.cpp
 		inspector/heroskillswidget.cpp
+		inspector/PickObjectDelegate.cpp
 		resourceExtractor/ResourceConverter.cpp
 )
 
@@ -72,6 +73,7 @@ set(editor_HEADERS
 		inspector/rewardswidget.h
 		inspector/questwidget.h
 		inspector/heroskillswidget.h
+		inspector/PickObjectDelegate.h
 		resourceExtractor/ResourceConverter.h
 )
 

+ 59 - 0
mapeditor/inspector/PickObjectDelegate.cpp

@@ -0,0 +1,59 @@
+/*
+ * PickObjectDelegate.cpp, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+#include "StdInc.h"
+#include "PickObjectDelegate.h"
+
+#include "../mapcontroller.h"
+#include "../../lib/mapObjects/CGObjectInstance.h"
+
+PickObjectDelegate::PickObjectDelegate(MapController & c): controller(c)
+{
+	filter = [](const CGObjectInstance *)
+	{
+		return true;
+	};
+}
+
+PickObjectDelegate::PickObjectDelegate(MapController & c, std::function<bool(const CGObjectInstance *)> f): controller(c), filter(f)
+{
+	
+}
+
+void PickObjectDelegate::onObjectPicked(const CGObjectInstance * o)
+{
+	for(int lvl : {0, 1})
+	{
+		auto & l = controller.scene(lvl)->objectPickerView;
+		l.clear();
+		l.update();
+		QObject::disconnect(&l, &ObjectPickerLayer::selectionMade, this, &PickObjectDelegate::onObjectPicked);
+	}
+	
+	QMap<int, QVariant> data;
+	data[Qt::DisplayRole] = QVariant("None");
+	data[Qt::UserRole] = QVariant::fromValue(data_cast(o));
+	if(o)
+		data[Qt::DisplayRole] = QVariant(QString::fromStdString(o->instanceName));
+	const_cast<QAbstractItemModel*>(modelIndex.model())->setItemData(modelIndex, data);
+}
+
+QWidget * PickObjectDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+	for(int lvl : {0, 1})
+	{
+		auto & l = controller.scene(lvl)->objectPickerView;
+		l.highlight(filter);
+		l.update();
+		QObject::connect(&l, &ObjectPickerLayer::selectionMade, this, &PickObjectDelegate::onObjectPicked);
+	}
+	
+	modelIndex = index;
+	return nullptr;
+}

+ 45 - 0
mapeditor/inspector/PickObjectDelegate.h

@@ -0,0 +1,45 @@
+/*
+ * PickObjectDelegate.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+#pragma once
+
+#include <QItemDelegate>
+
+class MapController;
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+class CGObjectInstance;
+
+VCMI_LIB_NAMESPACE_END
+
+class PickObjectDelegate : public QItemDelegate
+{
+	Q_OBJECT
+public:
+	PickObjectDelegate(MapController &);
+	PickObjectDelegate(MapController &, std::function<bool(const CGObjectInstance *)>);
+	
+	template<class T>
+	static bool typedFilter(const CGObjectInstance * o)
+	{
+		return dynamic_cast<const T*>(o) != nullptr;
+	}
+
+	QWidget * createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const override;
+	
+public slots:
+	void onObjectPicked(const CGObjectInstance *);
+	
+private:
+	MapController & controller;
+	std::function<bool(const CGObjectInstance *)> filter;
+	mutable QModelIndex modelIndex;
+};

+ 35 - 18
mapeditor/inspector/inspector.cpp

@@ -26,6 +26,8 @@
 #include "rewardswidget.h"
 #include "questwidget.h"
 #include "heroskillswidget.h"
+#include "PickObjectDelegate.h"
+#include "../mapcontroller.h"
 
 static QList<std::pair<QString, QVariant>> MissionIdentifiers
 {
@@ -239,6 +241,12 @@ void Inspector::updateProperties(CGDwelling * o)
 	if(!o) return;
 	
 	addProperty("Owner", o->tempOwner, false);
+	
+	if(dynamic_cast<CCreGenAsCastleInfo*>(o->info))
+	{
+		auto * delegate = new PickObjectDelegate(controller, PickObjectDelegate::typedFilter<CGTownInstance>);
+		addProperty("Same as town", PropertyEditorPlaceholder(), delegate, false);
+	}
 }
 
 void Inspector::updateProperties(CGLighthouse * o)
@@ -288,7 +296,7 @@ void Inspector::updateProperties(CGHeroInstance * o)
 		auto * delegate = new InspectorDelegate;
 		for(int i = 0; i < VLC->heroh->objects.size(); ++i)
 		{
-			if(map->allowedHeroes.at(i))
+			if(controller.map()->allowedHeroes.at(i))
 			{
 				if(o->ID == Obj::PRISON || (o->type && VLC->heroh->objects[i]->heroClass->getIndex() == o->type->heroClass->getIndex()))
 				{
@@ -325,7 +333,7 @@ void Inspector::updateProperties(CGArtifact * o)
 			auto * delegate = new InspectorDelegate;
 			for(auto spell : VLC->spellh->objects)
 			{
-				if(map->allowedSpells.at(spell->id))
+				if(controller.map()->allowedSpells.at(spell->id))
 					delegate->options.push_back({QObject::tr(spell->getNameTranslated().c_str()), QVariant::fromValue(int(spell->getId()))});
 			}
 			addProperty("Spell", VLC->spellh->getById(spellId)->getNameTranslated(), delegate, false);
@@ -379,7 +387,7 @@ void Inspector::updateProperties(CRewardableObject * o)
 {
 	if(!o) return;
 		
-	auto * delegate = new RewardsDelegate(*map, *o);
+	auto * delegate = new RewardsDelegate(*controller.map(), *o);
 	addProperty("Reward", PropertyEditorPlaceholder(), delegate, false);
 }
 
@@ -415,7 +423,7 @@ void Inspector::updateProperties(CGSeerHut * o)
 	addProperty("Completed text", o->quest->completedText, new MessageDelegate, false);
 	
 	{ //Quest
-		auto * delegate = new QuestDelegate(*map, *o);
+		auto * delegate = new QuestDelegate(*controller.map(), *o);
 		addProperty("Quest", PropertyEditorPlaceholder(), delegate, false);
 	}
 }
@@ -441,8 +449,8 @@ void Inspector::updateProperties()
 	
 	auto * delegate = new InspectorDelegate();
 	delegate->options.push_back({QObject::tr("neutral"), QVariant::fromValue(PlayerColor::NEUTRAL.getNum())});
-	for(int p = 0; p < map->players.size(); ++p)
-		if(map->players[p].canAnyonePlay())
+	for(int p = 0; p < controller.map()->players.size(); ++p)
+		if(controller.map()->players[p].canAnyonePlay())
 			delegate->options.push_back({QString::fromStdString(GameConstants::PLAYER_COLOR_NAMES[p]), QVariant::fromValue(PlayerColor(p).getNum())});
 	addProperty("Owner", obj->tempOwner, delegate, true);
 	
@@ -530,7 +538,7 @@ void Inspector::setProperty(CGPandoraBox * o, const QString & key, const QVarian
 	if(!o) return;
 	
 	if(key == "Message")
-		o->message = MetaString::createFromTextID(mapRegisterLocalizedString("map", *map, TextIdentifier("guards", o->instanceName, "message"), value.toString().toStdString()));
+		o->message = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller.map(), TextIdentifier("guards", o->instanceName, "message"), value.toString().toStdString()));
 }
 
 void Inspector::setProperty(CGEvent * o, const QString & key, const QVariant & value)
@@ -552,7 +560,7 @@ void Inspector::setProperty(CGTownInstance * o, const QString & key, const QVari
 	if(!o) return;
 	
 	if(key == "Town name")
-		o->setNameTextId(mapRegisterLocalizedString("map", *map, TextIdentifier("town", o->instanceName, "name"), value.toString().toStdString()));
+		o->setNameTextId(mapRegisterLocalizedString("map", *controller.map(), TextIdentifier("town", o->instanceName, "name"), value.toString().toStdString()));
 }
 
 void Inspector::setProperty(CGSignBottle * o, const QString & key, const QVariant & value)
@@ -560,7 +568,7 @@ void Inspector::setProperty(CGSignBottle * o, const QString & key, const QVarian
 	if(!o) return;
 	
 	if(key == "Message")
-		o->message = MetaString::createFromTextID(mapRegisterLocalizedString("map", *map, TextIdentifier("sign", o->instanceName, "message"), value.toString().toStdString()));
+		o->message = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller.map(), TextIdentifier("sign", o->instanceName, "message"), value.toString().toStdString()));
 }
 
 void Inspector::setProperty(CGMine * o, const QString & key, const QVariant & value)
@@ -576,7 +584,7 @@ void Inspector::setProperty(CGArtifact * o, const QString & key, const QVariant
 	if(!o) return;
 	
 	if(key == "Message")
-		o->message = MetaString::createFromTextID(mapRegisterLocalizedString("map", *map, TextIdentifier("guards", o->instanceName, "message"), value.toString().toStdString()));
+		o->message = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller.map(), TextIdentifier("guards", o->instanceName, "message"), value.toString().toStdString()));
 	
 	if(o->storedArtifact && key == "Spell")
 	{
@@ -587,6 +595,16 @@ void Inspector::setProperty(CGArtifact * o, const QString & key, const QVariant
 void Inspector::setProperty(CGDwelling * o, const QString & key, const QVariant & value)
 {
 	if(!o) return;
+	
+	if(key == "Same as town")
+	{
+		if(auto * info = dynamic_cast<CCreGenAsCastleInfo*>(o->info))
+		{
+			info->instanceId = "";
+			if(CGTownInstance * town = data_cast<CGTownInstance>(value.toLongLong()))
+				info->instanceId = town->instanceName;
+		}
+	}
 }
 
 void Inspector::setProperty(CGGarrison * o, const QString & key, const QVariant & value)
@@ -605,10 +623,10 @@ void Inspector::setProperty(CGHeroInstance * o, const QString & key, const QVari
 		o->gender = EHeroGender(value.toInt());
 	
 	if(key == "Name")
-		o->nameCustomTextId = mapRegisterLocalizedString("map", *map, TextIdentifier("hero", o->instanceName, "name"), value.toString().toStdString());
+		o->nameCustomTextId = mapRegisterLocalizedString("map", *controller.map(), TextIdentifier("hero", o->instanceName, "name"), value.toString().toStdString());
 	
 	if(key == "Biography")
-		o->biographyCustomTextId = mapRegisterLocalizedString("map", *map, TextIdentifier("hero", o->instanceName, "biography"), value.toString().toStdString());
+		o->biographyCustomTextId = mapRegisterLocalizedString("map", *controller.map(), TextIdentifier("hero", o->instanceName, "biography"), value.toString().toStdString());
 	
 	if(key == "Experience")
 		o->exp = value.toString().toInt();
@@ -644,7 +662,7 @@ void Inspector::setProperty(CGCreature * o, const QString & key, const QVariant
 	if(!o) return;
 	
 	if(key == "Message")
-		o->message = MetaString::createFromTextID(mapRegisterLocalizedString("map", *map, TextIdentifier("monster", o->instanceName, "message"), value.toString().toStdString()));
+		o->message = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller.map(), TextIdentifier("monster", o->instanceName, "message"), value.toString().toStdString()));
 	if(key == "Character")
 		o->character = CGCreature::Character(value.toInt());
 	if(key == "Never flees")
@@ -662,11 +680,11 @@ void Inspector::setProperty(CGSeerHut * o, const QString & key, const QVariant &
 	if(key == "Mission type")
 		o->quest->missionType = CQuest::Emission(value.toInt());
 	if(key == "First visit text")
-		o->quest->firstVisitText = MetaString::createFromTextID(mapRegisterLocalizedString("map", *map, TextIdentifier("quest", o->instanceName, "firstVisit"), value.toString().toStdString()));
+		o->quest->firstVisitText = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller.map(), TextIdentifier("quest", o->instanceName, "firstVisit"), value.toString().toStdString()));
 	if(key == "Next visit text")
-		o->quest->nextVisitText = MetaString::createFromTextID(mapRegisterLocalizedString("map", *map, TextIdentifier("quest", o->instanceName, "nextVisit"), value.toString().toStdString()));
+		o->quest->nextVisitText = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller.map(), TextIdentifier("quest", o->instanceName, "nextVisit"), value.toString().toStdString()));
 	if(key == "Completed text")
-		o->quest->completedText = MetaString::createFromTextID(mapRegisterLocalizedString("map", *map, TextIdentifier("quest", o->instanceName, "completed"), value.toString().toStdString()));
+		o->quest->completedText = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller.map(), TextIdentifier("quest", o->instanceName, "completed"), value.toString().toStdString()));
 }
 
 
@@ -799,7 +817,7 @@ QTableWidgetItem * Inspector::addProperty(CQuest::Emission value)
 
 //========================================================================
 
-Inspector::Inspector(CMap * m, CGObjectInstance * o, QTableWidget * t): obj(o), table(t), map(m)
+Inspector::Inspector(MapController & c, CGObjectInstance * o, QTableWidget * t): obj(o), table(t), controller(c)
 {
 }
 
@@ -845,4 +863,3 @@ void InspectorDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
 		QStyledItemDelegate::setModelData(editor, model, index);
 	}
 }
-

+ 3 - 5
mapeditor/inspector/inspector.h

@@ -32,6 +32,7 @@ void setProperty(x*, const QString &, const QVariant &);
 #define SET_PROPERTIES(x) setProperty(dynamic_cast<x*>(obj), key, value)
 
 
+class MapController;
 class Initializer
 {
 public:
@@ -101,7 +102,7 @@ protected:
 //===============END OF DECLARATION=======================================
 	
 public:
-	Inspector(CMap *, CGObjectInstance *, QTableWidget *);
+	Inspector(MapController &, CGObjectInstance *, QTableWidget *);
 
 	void setProperty(const QString & key, const QTableWidgetItem * item);
 	
@@ -154,12 +155,10 @@ protected:
 	QTableWidget * table;
 	CGObjectInstance * obj;
 	QMap<QString, QTableWidgetItem*> keyItems;
-	CMap * map;
+	MapController & controller;
 };
 
 
-
-
 class InspectorDelegate : public QStyledItemDelegate
 {
 	Q_OBJECT
@@ -172,4 +171,3 @@ public:
 	
 	QList<std::pair<QString, QVariant>> options;
 };
-

+ 9 - 7
mapeditor/mainwindow.cpp

@@ -213,6 +213,7 @@ MainWindow::MainWindow(QWidget* parent) :
 	ui->mapView->setController(&controller);
 	ui->mapView->setOptimizationFlags(QGraphicsView::DontSavePainterState | QGraphicsView::DontAdjustForAntialiasing);
 	connect(ui->mapView, &MapView::openObjectProperties, this, &MainWindow::loadInspector);
+	connect(ui->mapView, &MapView::currentCoordinates, this, &MainWindow::currentCoordinatesChanged);
 	
 	ui->minimapView->setScene(controller.miniScene(0));
 	ui->minimapView->setController(&controller);
@@ -296,12 +297,11 @@ void MainWindow::initializeMap(bool isNew)
 	ui->minimapView->setScene(controller.miniScene(mapLevel));
 	ui->minimapView->dimensions();
 	
-	setStatusMessage(QString("Scene objects: %1").arg(ui->mapView->scene()->items().size()));
-
 	//enable settings
 	ui->actionMapSettings->setEnabled(true);
 	ui->actionPlayers_settings->setEnabled(true);
 	ui->actionTranslations->setEnabled(true);
+	ui->actionLevel->setEnabled(controller.map()->twoLevel);
 	
 	//set minimal players count
 	if(isNew)
@@ -459,6 +459,11 @@ void MainWindow::on_actionSave_triggered()
 		saveMap();
 }
 
+void MainWindow::currentCoordinatesChanged(int x, int y)
+{
+	setStatusMessage(QString("x: %1   y: %2").arg(x).arg(y));
+}
+
 void MainWindow::terrainButtonClicked(TerrainId terrain)
 {
 	controller.commitTerrainChange(mapLevel, terrain);
@@ -993,7 +998,7 @@ void MainWindow::loadInspector(CGObjectInstance * obj, bool switchTab)
 {
 	if(switchTab)
 		ui->tabWidget->setCurrentIndex(1);
-	Inspector inspector(controller.map(), obj, ui->inspectorWidget);
+	Inspector inspector(controller, obj, ui->inspectorWidget);
 	inspector.updateProperties();
 }
 
@@ -1017,7 +1022,7 @@ void MainWindow::on_inspectorWidget_itemChanged(QTableWidgetItem *item)
 	auto param = tableWidget->item(r, c - 1)->text();
 
 	//set parameter
-	Inspector inspector(controller.map(), obj, tableWidget);
+	Inspector inspector(controller, obj, tableWidget);
 	inspector.setProperty(param, item);
 	controller.commitObjectChange(mapLevel);
 }
@@ -1103,9 +1108,6 @@ void MainWindow::onSelectionMade(int level, bool anythingSelected)
 {
 	if (level == mapLevel)
 	{
-		auto info = QString::asprintf("Selection on layer %d: %s", level, anythingSelected ? "true" : "false");
-		setStatusMessage(info);
-
 		ui->actionErase->setEnabled(anythingSelected);
 		ui->toolErase->setEnabled(anythingSelected);
 	}

+ 1 - 0
mapeditor/mainwindow.h

@@ -82,6 +82,7 @@ private slots:
 
 	void terrainButtonClicked(TerrainId terrain);
 	void roadOrRiverButtonClicked(ui8 type, bool isRoad);
+	void currentCoordinatesChanged(int x, int y);
 
 	void on_toolErase_clicked();
 

+ 1 - 2
mapeditor/mapview.cpp

@@ -98,8 +98,7 @@ void MapView::mouseMoveEvent(QMouseEvent *mouseEvent)
 
 	tilePrev = tile;
 
-	//TODO: cast parent->parent to MainWindow in order to show coordinates or another way to do it?
-	//main->setStatusMessage(QString("x: %1 y: %2").arg(tile.x, tile.y));
+	emit currentCoordinates(tile.x, tile.y);
 
 	switch(selectionTool)
 	{

+ 1 - 0
mapeditor/mapview.h

@@ -111,6 +111,7 @@ public slots:
 	
 signals:
 	void openObjectProperties(CGObjectInstance *, bool switchTab);
+	void currentCoordinates(int, int);
 	//void viewportChanged(const QRectF & rect);
 
 protected: