1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Merge remote-tracking branch 'origin/cpp-map-editor' into gui-ux-improvements

# Conflicts:
#	mapeditor/mainwindow.h
#	mapeditor/mainwindow.ui
#	mapeditor/windownewmap.cpp
This commit is contained in:
Tomasz Zielinski 2022-09-11 08:10:16 +02:00
commit 816d4b3081
45 changed files with 1637 additions and 328 deletions

View File

@ -324,6 +324,11 @@ CStackWindow::ButtonsSection::ButtonsSection(CStackWindow * owner, int yOffset)
upgradeBtn->addOverlay(std::make_shared<CAnimImage>("CPRSMALL", VLC->creh->objects[upgradeInfo.info.newID[buttonIndex]]->iconIndex));
if(buttonsToCreate == 1) // single upgrade avaialbe
{
upgradeBtn->assignedKeys.insert(SDLK_u);
}
upgrade[buttonIndex] = upgradeBtn;
}
}

12
config/creatures/conflux.json Normal file → Executable file
View File

@ -31,6 +31,12 @@
"type" : "MORE_DAMAGE_FROM_SPELL",
"subtype" : "spell.chainLightning",
"val" : 100
},
"armageddonVulnerablity" :
{
"type" : "MORE_DAMAGE_FROM_SPELL",
"subtype" : "spell.armageddon",
"val" : 100
}
},
"upgrades": ["stormElemental"],
@ -523,6 +529,12 @@
"type" : "MORE_DAMAGE_FROM_SPELL",
"subtype" : "spell.chainLightning",
"val" : 100
},
"armageddonVulnerablity" :
{
"type" : "MORE_DAMAGE_FROM_SPELL",
"subtype" : "spell.armageddon",
"val" : 100
}
},
"graphics" :

2
config/creatures/inferno.json Normal file → Executable file
View File

@ -315,7 +315,7 @@
"fireShield" :
{
"type" : "FIRE_SHIELD",
"val" : 30
"val" : 20
}
},
"graphics" :

7
config/heroes/conflux.json Normal file → Executable file
View File

@ -46,8 +46,9 @@
]
},
"bonuses" : {
"health" : {
"type" : "STACK_HEALTH",
"damage" : {
"type" : "CREATURE_DAMAGE",
"subtype" : 0,
"val" : 5
},
"attack" : {
@ -173,7 +174,7 @@
]
},
"bonuses" : {
"health" : {
"damage" : {
"type" : "CREATURE_DAMAGE",
"subtype" : 0,
"val" : 5

View File

@ -648,7 +648,7 @@
<item row="17" column="7">
<widget class="QPushButton" name="updatesButton">
<property name="text">
<string>Updates</string>
<string>Check for updates</string>
</property>
</widget>
</item>

View File

@ -257,7 +257,7 @@ void CCreature::addBonus(int val, Bonus::BonusType type, int subtype)
if(existing.empty())
{
auto added = std::make_shared<Bonus>(Bonus::PERMANENT, type, Bonus::CREATURE_ABILITY, val, getIndex(), subtype, Bonus::BASE_NUMBER);
auto added = std::make_shared<Bonus>(Bonus::PERMANENT, type, Bonus::CREATURE_ABILITY, val, getIndex(), subtype, Bonus::ADDITIVE_VALUE);
addNewBonus(added);
}
else
@ -611,9 +611,6 @@ CCreature * CCreatureHandler::loadFromJson(const std::string & scope, const Json
if(!node["shots"].isNull())
cre->addBonus(node["shots"].Integer(), Bonus::SHOTS);
if(!node["spellPoints"].isNull())
cre->addBonus(node["spellPoints"].Integer(), Bonus::CASTS);
loadStackExperience(cre, node["stackExperience"]);
loadJsonAnimation(cre, node["graphics"]);
loadCreatureJson(cre, node);

View File

@ -620,10 +620,11 @@ void LayerTransitionRule::process(
destination.blocked = true;
}
}
else if(source.node->accessible != CGPathNode::ACCESSIBLE && destination.node->accessible != CGPathNode::ACCESSIBLE)
else if(destination.node->accessible != CGPathNode::ACCESSIBLE)
{
/// Hero that fly can only land on accessible tiles
destination.blocked = true;
if(!destination.isGuardianTile && destination.nodeObject)
destination.blocked = true;
}
break;

View File

@ -957,7 +957,10 @@ void CBonusSystemNode::getAllBonusesRec(BonusList &out) const
auto updated = b->updater
? getUpdatedBonus(b, b->updater)
: b;
out.push_back(updated);
//do not add bonus with same pointer
if(!vstd::contains(out, updated))
out.push_back(updated);
}
}

View File

@ -165,3 +165,17 @@ void CFilesystemList::addLoader(ISimpleResourceLoader * loader, bool writeable)
if (writeable)
writeableLoaders.insert(loader);
}
bool CFilesystemList::removeLoader(ISimpleResourceLoader * loader)
{
for(auto loaderIterator = loaders.begin(); loaderIterator != loaders.end(); ++loaderIterator)
{
if(loaderIterator->get() == loader)
{
loaders.erase(loaderIterator);
writeableLoaders.erase(loader);
return true;
}
}
return false;
}

View File

@ -84,4 +84,14 @@ public:
* @param writeable - resource shall be treated as writeable
*/
void addLoader(ISimpleResourceLoader * loader, bool writeable);
/**
* Removes loader from the loader list
* Take care about memory deallocation
*
* @param loader The simple resource loader object to remove
*
* @return if loader was successfully removed
*/
bool removeLoader(ISimpleResourceLoader * loader);
};

View File

@ -225,6 +225,21 @@ void CResourceHandler::addFilesystem(const std::string & parent, const std::stri
knownLoaders[identifier] = loader;
}
bool CResourceHandler::removeFilesystem(const std::string & parent, const std::string & identifier)
{
if(knownLoaders.count(identifier) == 0)
return false;
if(knownLoaders.count(parent) == 0)
return false;
auto list = dynamic_cast<CFilesystemList *>(knownLoaders.at(parent));
assert(list);
list->removeLoader(knownLoaders[identifier]);
knownLoaders.erase(identifier);
return true;
}
ISimpleResourceLoader * CResourceHandler::createFileSystem(const std::string & prefix, const JsonNode &fsConfig)
{
CFilesystemGenerator generator(prefix);

View File

@ -87,6 +87,14 @@ public:
* @param loader resource loader to add
*/
static void addFilesystem(const std::string & parent, const std::string & identifier, ISimpleResourceLoader * loader);
/**
* @brief removeFilesystem removes reviously added filesyste, from global resouce holder
* @param parent parent loader containing filesystem
* @param identifier name of this loader
* @return if filesystem was successfully removed
*/
static bool removeFilesystem(const std::string & parent, const std::string & identifier);
/**
* @brief createModFileSystem - creates filesystem out of config file

View File

@ -15,13 +15,17 @@ set(editor_SRCS
mapview.cpp
radiopushbutton.cpp
objectbrowser.cpp
inspector.cpp
mapsettings.cpp
playersettings.cpp
playerparams.cpp
scenelayer.cpp
mapcontroller.cpp
validator.cpp
inspector/inspector.cpp
inspector/townbulidingswidget.cpp
inspector/armywidget.cpp
inspector/messagewidget.cpp
inspector/rewardswidget.cpp
)
set(editor_HEADERS
@ -40,13 +44,17 @@ set(editor_HEADERS
mapview.h
radiopushbutton.h
objectbrowser.h
inspector.h
mapsettings.h
playersettings.h
playerparams.h
scenelayer.h
mapcontroller.h
validator.h
inspector/inspector.h
inspector/townbulidingswidget.h
inspector/armywidget.h
inspector/messagewidget.h
inspector/rewardswidget.h
)
set(editor_FORMS
@ -57,9 +65,13 @@ set(editor_FORMS
playersettings.ui
playerparams.ui
validator.ui
inspector/townbulidingswidget.ui
inspector/armywidget.ui
inspector/messagewidget.ui
inspector/rewardswidget.ui
)
assign_source_group(${editor_SRCS} ${editor_HEADERS} VCMI_launcher.rc)
assign_source_group(${editor_SRCS} ${editor_HEADERS} mapeditor.rc)
# Tell CMake to run moc when necessary:
set(CMAKE_AUTOMOC ON)
@ -79,7 +91,7 @@ else()
endif()
if(WIN32)
set(editor_ICON VCMI_launcher.rc)
set(editor_ICON mapeditor.rc)
endif()
add_executable(vcmieditor WIN32 ${editor_SRCS} ${editor_HEADERS} ${editor_UI_HEADERS} ${editor_ICON})

View File

@ -1,110 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="VCMI_launcher" />
<Option pch_mode="0" />
<Option compiler="gcc" />
<Build>
<Target title="Debug Win32">
<Option output="../VCMI_launcher" prefix_auto="1" extension_auto="1" />
<Option working_dir="../" />
<Option object_output="../obj/Launcher/Debug" />
<Option type="0" />
<Option compiler="gcc" />
<Compiler>
<Add option="-g" />
<Add option="-Og" />
</Compiler>
</Target>
<Target title="Release Win32">
<Option output="../VCMI_launcher" prefix_auto="1" extension_auto="1" />
<Option working_dir="../" />
<Option object_output="../obj/Launcher/Release" />
<Option type="0" />
<Option compiler="gcc" />
<Compiler>
<Add option="-O3" />
<Add option="-flto" />
</Compiler>
<Linker>
<Add option="-s" />
<Add option="-flto" />
</Linker>
</Target>
</Build>
<Compiler>
<Add option="-Wextra" />
<Add option="-Wall" />
<Add option="-std=gnu++11" />
<Add option="-isystem $(#boost.include)" />
<Add option="-DBOOST_SYSTEM_NO_DEPRECATED" />
<Add option="-D_WIN32" />
<Add directory="." />
<Add directory="$(#qt.include)" />
<Add directory="$(#qt.include)/QtGui" />
<Add directory="$(#qt.include)/QtCore" />
<Add directory="$(#qt.include)/QtWidgets" />
</Compiler>
<Linker>
<Add option="-lVCMI_lib" />
<Add option="-lQt5Core" />
<Add option="-lQt5Gui" />
<Add option="-lQt5Widgets" />
<Add option="-lQt5Network" />
<Add option="-lboost_filesystem$(#boost.libsuffix)" />
<Add option="-lboost_system$(#boost.libsuffix)" />
<Add directory="../" />
<Add directory="$(#qt.lib)" />
<Add directory="$(#boost.lib)" />
</Linker>
<Unit filename="StdInc.cpp">
<Option compile="0" />
<Option link="0" />
</Unit>
<Unit filename="StdInc.h">
<Option compile="1" />
<Option weight="0" />
</Unit>
<Unit filename="VCMI_launcher.rc">
<Option compilerVar="WINDRES" />
</Unit>
<Unit filename="jsonutils.cpp" />
<Unit filename="jsonutils.h" />
<Unit filename="launcherdirs.cpp" />
<Unit filename="launcherdirs.h" />
<Unit filename="main.cpp" />
<Unit filename="mainwindow_moc.cpp" />
<Unit filename="mainwindow_moc.h" />
<Unit filename="mainwindow_moc.ui" />
<Unit filename="modManager/cdownloadmanager_moc.cpp" />
<Unit filename="modManager/cdownloadmanager_moc.h" />
<Unit filename="modManager/cmodlist.cpp" />
<Unit filename="modManager/cmodlist.h" />
<Unit filename="modManager/cmodlistmodel_moc.cpp" />
<Unit filename="modManager/cmodlistmodel_moc.h" />
<Unit filename="modManager/cmodlistview_moc.cpp" />
<Unit filename="modManager/cmodlistview_moc.h" />
<Unit filename="modManager/cmodlistview_moc.ui" />
<Unit filename="modManager/cmodmanager.cpp" />
<Unit filename="modManager/cmodmanager.h" />
<Unit filename="modManager/imageviewer_moc.cpp" />
<Unit filename="modManager/imageviewer_moc.h" />
<Unit filename="modManager/imageviewer_moc.ui" />
<Unit filename="modManager/qrc_cdownloadmanager_moc.cpp" />
<Unit filename="modManager/qrc_cmodlistmodel_moc.cpp" />
<Unit filename="modManager/qrc_cmodlistview_moc.cpp" />
<Unit filename="modManager/qrc_imageviewer_moc.cpp" />
<Unit filename="qrc_mainwindow_moc.cpp" />
<Unit filename="settingsView/csettingsview_moc.cpp" />
<Unit filename="settingsView/csettingsview_moc.h" />
<Unit filename="settingsView/csettingsview_moc.ui" />
<Unit filename="settingsView/qrc_csettingsview_moc.cpp" />
<Extensions>
<code_completion />
<envvars />
<debugger />
<lib_finder disable_auto="1" />
</Extensions>
</Project>
</CodeBlocks_project_file>

Binary file not shown.

Before

(image error) Size: 31 KiB

View File

@ -1 +0,0 @@
IDI_ICON1 ICON "VCMI_launcher.ico"

View File

@ -0,0 +1,142 @@
#include "armywidget.h"
#include "ui_armywidget.h"
#include "CCreatureHandler.h"
ArmyWidget::ArmyWidget(CArmedInstance & a, QWidget *parent) :
QDialog(parent),
army(a),
ui(new Ui::ArmyWidget)
{
ui->setupUi(this);
uiCounts[0] = ui->count0; uiSlots[0] = ui->slot0;
uiCounts[1] = ui->count1; uiSlots[1] = ui->slot1;
uiCounts[2] = ui->count2; uiSlots[2] = ui->slot2;
uiCounts[3] = ui->count3; uiSlots[3] = ui->slot3;
uiCounts[4] = ui->count4; uiSlots[4] = ui->slot4;
uiCounts[5] = ui->count5; uiSlots[5] = ui->slot5;
uiCounts[6] = ui->count6; uiSlots[6] = ui->slot6;
for(int i = 0; i < TOTAL_SLOTS; ++i)
{
uiCounts[i]->setInputMask("d0000");
uiCounts[i]->setText("1");
uiSlots[i]->addItem("");
uiSlots[i]->setItemData(0, -1);
for(int c = 0; c < VLC->creh->objects.size(); ++c)
{
auto creature = VLC->creh->objects[c];
uiSlots[i]->insertItem(c + 1, tr(creature->getPluralName().c_str()));
uiSlots[i]->setItemData(c + 1, creature->getId().getNum());
}
}
ui->formationTight->setChecked(true);
}
int ArmyWidget::searchItemIndex(int slotId, CreatureID creId) const
{
for(int i = 0; i < uiSlots[slotId]->count(); ++i)
{
if(creId.getNum() == uiSlots[slotId]->itemData(i).toInt())
return i;
}
return 0;
}
void ArmyWidget::obtainData()
{
for(int i = 0; i < TOTAL_SLOTS; ++i)
{
if(army.hasStackAtSlot(SlotID(i)))
{
auto * creature = army.getCreature(SlotID(i));
uiSlots[i]->setCurrentIndex(searchItemIndex(i, creature->getId()));
uiCounts[i]->setText(QString::number(army.getStackCount(SlotID(i))));
}
}
if(army.formation)
ui->formationTight->setChecked(true);
else
ui->formationWide->setChecked(true);
}
bool ArmyWidget::commitChanges()
{
bool isArmed = false;
for(int i = 0; i < TOTAL_SLOTS; ++i)
{
CreatureID creId(uiSlots[i]->itemData(uiSlots[i]->currentIndex()).toInt());
if(creId == -1)
{
if(army.hasStackAtSlot(SlotID(i)))
army.eraseStack(SlotID(i));
}
else
{
isArmed = true;
int amount = uiCounts[i]->text().toInt();
if(amount)
{
army.setCreature(SlotID(i), creId, amount);
}
else
{
if(army.hasStackAtSlot(SlotID(i)))
army.eraseStack(SlotID(i));
army.putStack(SlotID(i), new CStackInstance(creId, amount, false));
}
}
}
army.setFormation(ui->formationTight->isChecked());
return isArmed;
}
ArmyWidget::~ArmyWidget()
{
delete ui;
}
ArmyDelegate::ArmyDelegate(CArmedInstance & t): army(t), QStyledItemDelegate()
{
}
QWidget * ArmyDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return new ArmyWidget(army, parent);
}
void ArmyDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
if(auto * ed = qobject_cast<ArmyWidget *>(editor))
{
ed->obtainData();
}
else
{
QStyledItemDelegate::setEditorData(editor, index);
}
}
void ArmyDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
if(auto * ed = qobject_cast<ArmyWidget *>(editor))
{
auto isArmed = ed->commitChanges();
model->setData(index, "dummy");
if(isArmed)
model->setData(index, "HAS ARMY");
else
model->setData(index, "");
}
else
{
QStyledItemDelegate::setModelData(editor, model, index);
}
}

View File

@ -0,0 +1,49 @@
#ifndef ARMYWIDGET_H
#define ARMYWIDGET_H
#include <QDialog>
#include "../lib/mapObjects/CArmedInstance.h"
const int TOTAL_SLOTS = 7;
namespace Ui {
class ArmyWidget;
}
class ArmyWidget : public QDialog
{
Q_OBJECT
public:
explicit ArmyWidget(CArmedInstance &, QWidget *parent = nullptr);
~ArmyWidget();
void obtainData();
bool commitChanges();
private:
int searchItemIndex(int slotId, CreatureID creId) const;
Ui::ArmyWidget *ui;
CArmedInstance & army;
std::array<QLineEdit*, TOTAL_SLOTS> uiCounts;
std::array<QComboBox*, TOTAL_SLOTS> uiSlots;
};
class ArmyDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
using QStyledItemDelegate::QStyledItemDelegate;
ArmyDelegate(CArmedInstance &);
QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
private:
CArmedInstance & army;
};
#endif // ARMYWIDGET_H

View File

@ -0,0 +1,277 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ArmyWidget</class>
<widget class="QDialog" name="ArmyWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>318</width>
<height>314</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>318</width>
<height>314</height>
</size>
</property>
<property name="windowTitle">
<string>Army settings</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="6" column="0">
<widget class="QComboBox" name="slot6">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QComboBox" name="slot3">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QComboBox" name="slot2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="count6">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="count2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="count1">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="count5">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QRadioButton" name="formationWide">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Wide formation</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="count3">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QComboBox" name="slot1">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QComboBox" name="slot0">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QComboBox" name="slot4">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="count4">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QComboBox" name="slot5">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="count0">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QRadioButton" name="formationTight">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Tight formation</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -6,8 +6,12 @@
#include "../lib/mapObjects/CObjectClassesHandler.h"
#include "../lib/mapping/CMap.h"
#include "townbulidingswidget.h"
#include "armywidget.h"
#include "messagewidget.h"
//===============IMPLEMENT OBJECT INITIALIZATION FUNCTIONS================
Initializer::Initializer(CMap * m, CGObjectInstance * o) : map(m)
Initializer::Initializer(CMap * m, CGObjectInstance * o, const PlayerColor & pl) : map(m), defaultPlayer(pl)
{
///IMPORTANT! initialize order should be from base objects to derived objects
INIT_OBJ_TYPE(CGResource);
@ -20,6 +24,8 @@ Initializer::Initializer(CMap * m, CGObjectInstance * o) : map(m)
INIT_OBJ_TYPE(CGTownInstance);
INIT_OBJ_TYPE(CGCreature);
INIT_OBJ_TYPE(CGHeroInstance);
INIT_OBJ_TYPE(CGSignBottle);
INIT_OBJ_TYPE(CGLighthouse);
}
bool stringToBool(const QString & s)
@ -35,39 +41,61 @@ void Initializer::initialize(CArmedInstance * o)
if(!o) return;
}
void Initializer::initialize(CGSignBottle * o)
{
if(!o) return;
}
void Initializer::initialize(CGCreature * o)
{
if(!o) return;
o->character = CGCreature::Character::HOSTILE;
o->putStack(SlotID(0), new CStackInstance(CreatureID(o->subID), 0, false));
}
void Initializer::initialize(CGDwelling * o)
{
if(!o) return;
o->tempOwner = PlayerColor::NEUTRAL;
o->tempOwner = defaultPlayer;
switch(o->ID)
{
case Obj::RANDOM_DWELLING:
case Obj::RANDOM_DWELLING_LVL:
case Obj::RANDOM_DWELLING_FACTION:
o->initRandomObjectInfo();
}
}
void Initializer::initialize(CGGarrison * o)
{
if(!o) return;
o->tempOwner = PlayerColor::NEUTRAL;
o->tempOwner = defaultPlayer;
o->removableUnits = true;
}
void Initializer::initialize(CGShipyard * o)
{
if(!o) return;
o->tempOwner = PlayerColor::NEUTRAL;
o->tempOwner = defaultPlayer;
}
void Initializer::initialize(CGLighthouse * o)
{
if(!o) return;
o->tempOwner = defaultPlayer;
}
void Initializer::initialize(CGHeroInstance * o)
{
if(!o) return;
o->tempOwner = PlayerColor::NEUTRAL;
o->tempOwner = defaultPlayer;
}
void Initializer::initialize(CGTownInstance * o)
@ -113,7 +141,7 @@ void Initializer::initialize(CGMine * o)
{
if(!o) return;
o->tempOwner = PlayerColor::NEUTRAL;
o->tempOwner = defaultPlayer;
o->producedResource = Res::ERes(o->subID);
o->producedQuantity = o->defaultResProduction();
}
@ -130,13 +158,8 @@ void Inspector::updateProperties(CArmedInstance * o)
{
if(!o) return;
auto * delegate = new InspectorDelegate();
delegate->options << "NEUTRAL";
for(int p = 0; p < map->players.size(); ++p)
if(map->players[p].canAnyonePlay())
delegate->options << QString("PLAYER %1").arg(p);
addProperty("Owner", o->tempOwner, delegate, true);
auto * delegate = new ArmyDelegate(*o);
addProperty("Army", PropertyEditorPlaceholder(), delegate, false);
}
void Inspector::updateProperties(CGDwelling * o)
@ -146,11 +169,19 @@ void Inspector::updateProperties(CGDwelling * o)
addProperty("Owner", o->tempOwner, false);
}
void Inspector::updateProperties(CGLighthouse * o)
{
if(!o) return;
addProperty("Owner", o->tempOwner, false);
}
void Inspector::updateProperties(CGGarrison * o)
{
if(!o) return;
addProperty("Owner", o->tempOwner, false);
addProperty("Removable units", o->removableUnits, InspectorDelegate::boolDelegate(), false);
}
void Inspector::updateProperties(CGShipyard * o)
@ -172,6 +203,9 @@ void Inspector::updateProperties(CGTownInstance * o)
if(!o) return;
addProperty("Town name", o->name, false);
auto * delegate = new TownBuildingsDelegate(*o);
addProperty("Buildings", PropertyEditorPlaceholder(), delegate, false);
}
void Inspector::updateProperties(CGArtifact * o)
@ -190,7 +224,7 @@ void Inspector::updateProperties(CGArtifact * o)
for(auto spell : VLC->spellh->objects)
{
//if(map->isAllowedSpell(spell->id))
delegate->options << QString::fromStdString(spell->name);
delegate->options << QObject::tr(spell->name.c_str());
}
addProperty("Spell", VLC->spellh->objects[spellId]->name, delegate, false);
}
@ -214,6 +248,13 @@ void Inspector::updateProperties(CGResource * o)
addProperty("Message", o->message, false);
}
void Inspector::updateProperties(CGSignBottle * o)
{
if(!o) return;
addProperty("Message", o->message, new MessageDelegate, false);
}
void Inspector::updateProperties(CGCreature * o)
{
if(!o) return;
@ -227,6 +268,8 @@ void Inspector::updateProperties(CGCreature * o)
addProperty("Never flees", o->neverFlees, InspectorDelegate::boolDelegate(), false);
addProperty("Not growing", o->notGrowingTeam, InspectorDelegate::boolDelegate(), false);
addProperty("Artifact reward", o->gainedArtifact); //TODO: implement in setProperty
addProperty("Army", PropertyEditorPlaceholder(), true);
addProperty("Amount", o->stacks[SlotID(0)]->count, false);
//addProperty("Resources reward", o->resources); //TODO: implement in setProperty
}
@ -246,6 +289,13 @@ void Inspector::updateProperties()
auto factory = VLC->objtypeh->getHandlerFor(obj->ID, obj->subID);
addProperty("IsStatic", factory->isStaticObject());
auto * delegate = new InspectorDelegate();
delegate->options << "NEUTRAL";
for(int p = 0; p < map->players.size(); ++p)
if(map->players[p].canAnyonePlay())
delegate->options << QString("PLAYER %1").arg(p);
addProperty("Owner", obj->tempOwner, delegate, true);
UPDATE_OBJ_PROPERTIES(CArmedInstance);
UPDATE_OBJ_PROPERTIES(CGResource);
UPDATE_OBJ_PROPERTIES(CGArtifact);
@ -256,6 +306,8 @@ void Inspector::updateProperties()
UPDATE_OBJ_PROPERTIES(CGTownInstance);
UPDATE_OBJ_PROPERTIES(CGCreature);
UPDATE_OBJ_PROPERTIES(CGHeroInstance);
UPDATE_OBJ_PROPERTIES(CGSignBottle);
UPDATE_OBJ_PROPERTIES(CGLighthouse);
table->show();
}
@ -286,6 +338,8 @@ void Inspector::setProperty(const QString & key, const QVariant & value)
SET_PROPERTIES(CGCreature);
SET_PROPERTIES(CGHeroInstance);
SET_PROPERTIES(CGShipyard);
SET_PROPERTIES(CGSignBottle);
SET_PROPERTIES(CGLighthouse);
}
void Inspector::setProperty(CArmedInstance * object, const QString & key, const QVariant & value)
@ -293,6 +347,11 @@ void Inspector::setProperty(CArmedInstance * object, const QString & key, const
if(!object) return;
}
void Inspector::setProperty(CGLighthouse * object, const QString & key, const QVariant & value)
{
if(!object) return;
}
void Inspector::setProperty(CGTownInstance * object, const QString & key, const QVariant & value)
{
if(!object) return;
@ -301,6 +360,14 @@ void Inspector::setProperty(CGTownInstance * object, const QString & key, const
object->name = value.toString().toStdString();
}
void Inspector::setProperty(CGSignBottle * object, const QString & key, const QVariant & value)
{
if(!object) return;
if(key == "Message")
object->message = value.toString().toStdString();
}
void Inspector::setProperty(CGMine * object, const QString & key, const QVariant & value)
{
if(!object) return;
@ -337,6 +404,9 @@ void Inspector::setProperty(CGDwelling * object, const QString & key, const QVar
void Inspector::setProperty(CGGarrison * object, const QString & key, const QVariant & value)
{
if(!object) return;
if(key == "Removable units")
object->removableUnits = stringToBool(value.toString());
}
void Inspector::setProperty(CGHeroInstance * object, const QString & key, const QVariant & value)
@ -381,6 +451,8 @@ void Inspector::setProperty(CGCreature * object, const QString & key, const QVar
object->neverFlees = stringToBool(value.toString());
if(key == "Not growing")
object->notGrowingTeam = stringToBool(value.toString());
if(key == "Amount")
object->stacks[SlotID(0)]->count = value.toString().toInt();
}
@ -393,6 +465,13 @@ QTableWidgetItem * Inspector::addProperty(CGObjectInstance * value)
return new QTableWidgetItem(QString::number(reinterpret_cast<NumericPointer>(value)));
}
QTableWidgetItem * Inspector::addProperty(Inspector::PropertyEditorPlaceholder value)
{
auto item = new QTableWidgetItem("");
item->setData(Qt::UserRole, QString("PropertyEditor"));
return item;
}
QTableWidgetItem * Inspector::addProperty(unsigned int value)
{
return new QTableWidgetItem(QString::number(value));
@ -509,16 +588,6 @@ InspectorDelegate * InspectorDelegate::boolDelegate()
QWidget * InspectorDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return new QComboBox(parent);
//return QStyledItemDelegate::createEditor(parent, option, index);
//connect(editor, SIGNAL(activated(int)), this, SLOT(commitAndCloseEditor(int)));
}
void InspectorDelegate::commitAndCloseEditor(int id)
{
//QComboBox *editor = qobject_cast<QComboBox *>(sender());
//emit commitData(editor);
//emit closeEditor(editor);
}
void InspectorDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
@ -546,3 +615,4 @@ void InspectorDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
QStyledItemDelegate::setModelData(editor, model, index);
}
}

View File

@ -33,17 +33,22 @@ public:
DECLARE_OBJ_TYPE(CGGarrison);
DECLARE_OBJ_TYPE(CGHeroInstance);
DECLARE_OBJ_TYPE(CGCreature);
DECLARE_OBJ_TYPE(CGSignBottle);
DECLARE_OBJ_TYPE(CGLighthouse);
Initializer(CMap *, CGObjectInstance *);
Initializer(CMap *, CGObjectInstance *, const PlayerColor &);
private:
CMap * map;
PlayerColor defaultPlayer;
};
class Inspector
{
protected:
struct PropertyEditorPlaceholder {};
//===============DECLARE PROPERTIES SETUP=================================
DECLARE_OBJ_PROPERTY_METHODS(CArmedInstance);
DECLARE_OBJ_PROPERTY_METHODS(CGTownInstance);
@ -55,6 +60,8 @@ protected:
DECLARE_OBJ_PROPERTY_METHODS(CGGarrison);
DECLARE_OBJ_PROPERTY_METHODS(CGHeroInstance);
DECLARE_OBJ_PROPERTY_METHODS(CGCreature);
DECLARE_OBJ_PROPERTY_METHODS(CGSignBottle);
DECLARE_OBJ_PROPERTY_METHODS(CGLighthouse);
//===============DECLARE PROPERTY VALUE TYPE==============================
QTableWidgetItem * addProperty(unsigned int value);
@ -67,8 +74,10 @@ protected:
QTableWidgetItem * addProperty(bool value);
QTableWidgetItem * addProperty(CGObjectInstance * value);
QTableWidgetItem * addProperty(CGCreature::Character value);
QTableWidgetItem * addProperty(PropertyEditorPlaceholder value);
//===============END OF DECLARATION=======================================
public:
Inspector(CMap *, CGObjectInstance *, QTableWidget *);
@ -138,10 +147,6 @@ public:
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
QStringList options;
private slots:
void commitAndCloseEditor(int);
};
#endif // INSPECTOR_H

View File

@ -0,0 +1,53 @@
#include "messagewidget.h"
#include "ui_messagewidget.h"
MessageWidget::MessageWidget(QWidget *parent) :
QDialog(parent),
ui(new Ui::MessageWidget)
{
ui->setupUi(this);
}
MessageWidget::~MessageWidget()
{
delete ui;
}
void MessageWidget::setMessage(const QString & m)
{
ui->messageEdit->setPlainText(m);
}
QString MessageWidget::getMessage() const
{
return ui->messageEdit->toPlainText();
}
QWidget * MessageDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return new MessageWidget(parent);
}
void MessageDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
if(auto *ed = qobject_cast<MessageWidget *>(editor))
{
ed->setMessage(index.data().toString());
}
else
{
QStyledItemDelegate::setEditorData(editor, index);
}
}
void MessageDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
if(auto *ed = qobject_cast<MessageWidget *>(editor))
{
model->setData(index, ed->getMessage());
}
else
{
QStyledItemDelegate::setModelData(editor, model, index);
}
}

View File

@ -0,0 +1,37 @@
#ifndef MESSAGEWIDGET_H
#define MESSAGEWIDGET_H
#include <QDialog>
namespace Ui {
class MessageWidget;
}
class MessageWidget : public QDialog
{
Q_OBJECT
public:
explicit MessageWidget(QWidget *parent = nullptr);
~MessageWidget();
void setMessage(const QString &);
QString getMessage() const;
private:
Ui::MessageWidget *ui;
};
class MessageDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
using QStyledItemDelegate::QStyledItemDelegate;
QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
};
#endif // MESSAGEWIDGET_H

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MessageWidget</class>
<widget class="QDialog" name="MessageWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>306</width>
<height>201</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>306</width>
<height>201</height>
</size>
</property>
<property name="windowTitle">
<string>Message</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QPlainTextEdit" name="messageEdit"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,14 @@
#include "rewardswidget.h"
#include "ui_rewardswidget.h"
RewardsWidget::RewardsWidget(QWidget *parent) :
QDialog(parent),
ui(new Ui::RewardsWidget)
{
ui->setupUi(this);
}
RewardsWidget::~RewardsWidget()
{
delete ui;
}

View File

@ -0,0 +1,22 @@
#ifndef REWARDSWIDGET_H
#define REWARDSWIDGET_H
#include <QDialog>
namespace Ui {
class RewardsWidget;
}
class RewardsWidget : public QDialog
{
Q_OBJECT
public:
explicit RewardsWidget(QWidget *parent = nullptr);
~RewardsWidget();
private:
Ui::RewardsWidget *ui;
};
#endif // REWARDSWIDGET_H

View File

@ -0,0 +1,18 @@
<ui version="4.0">
<class>RewardsWidget</class>
<widget class="QDialog" name="RewardsWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,243 @@
#include "townbulidingswidget.h"
#include "ui_townbulidingswidget.h"
#include "../lib/CModHandler.h"
#include "../lib/CGeneralTextHandler.h"
std::string defaultBuildingIdConversion(BuildingID bId)
{
switch(bId)
{
case BuildingID::DEFAULT: return "DEFAULT";
case BuildingID::MAGES_GUILD_1: return "MAGES_GUILD_1";
case BuildingID::MAGES_GUILD_2: return "MAGES_GUILD_2";
case BuildingID::MAGES_GUILD_3: return "MAGES_GUILD_3";
case BuildingID::MAGES_GUILD_4: return "MAGES_GUILD_4";
case BuildingID::MAGES_GUILD_5: return "MAGES_GUILD_5";
case BuildingID::TAVERN: return "TAVERN";
case BuildingID::SHIPYARD: return "SHIPYARD";
case BuildingID::FORT: return "FORT";
case BuildingID::CITADEL: return "CITADEL";
case BuildingID::CASTLE: return "CASTLE";
case BuildingID::VILLAGE_HALL: return "VILLAGE_HALL";
case BuildingID::TOWN_HALL: return "TOWN_HALL";
case BuildingID::CITY_HALL: return "CITY_HALL";
case BuildingID::CAPITOL: return "CAPITOL";
case BuildingID::MARKETPLACE: return "MARKETPLACE";
case BuildingID::RESOURCE_SILO: return "RESOURCE_SILO";
case BuildingID::BLACKSMITH: return "BLACKSMITH";
case BuildingID::SPECIAL_1: return "SPECIAL_1";
case BuildingID::SPECIAL_2: return "SPECIAL_2";
case BuildingID::SPECIAL_3: return "SPECIAL_3";
case BuildingID::SPECIAL_4: return "SPECIAL_4";
case BuildingID::HORDE_1: return "HORDE_1";
case BuildingID::HORDE_1_UPGR: return "HORDE_1_UPGR";
case BuildingID::HORDE_2: return "HORDE_2";
case BuildingID::HORDE_2_UPGR: return "HORDE_2_UPGR";
case BuildingID::SHIP: return "SHIP";
case BuildingID::GRAIL: return "GRAIL";
case BuildingID::EXTRA_TOWN_HALL: return "EXTRA_TOWN_HALL";
case BuildingID::EXTRA_CITY_HALL: return "EXTRA_CITY_HALL";
case BuildingID::EXTRA_CAPITOL: return "EXTRA_CAPITOL";
case BuildingID::DWELL_LVL_1: return "DWELL_LVL_1";
case BuildingID::DWELL_LVL_2: return "DWELL_LVL_2";
case BuildingID::DWELL_LVL_3: return "DWELL_LVL_3";
case BuildingID::DWELL_LVL_4: return "DWELL_LVL_4";
case BuildingID::DWELL_LVL_5: return "DWELL_LVL_5";
case BuildingID::DWELL_LVL_6: return "DWELL_LVL_6";
case BuildingID::DWELL_LVL_7: return "DWELL_LVL_7";
case BuildingID::DWELL_LVL_1_UP: return "DWELL_LVL_1_UP";
case BuildingID::DWELL_LVL_2_UP: return "DWELL_LVL_2_UP";
case BuildingID::DWELL_LVL_3_UP: return "DWELL_LVL_3_UP";
case BuildingID::DWELL_LVL_4_UP: return "DWELL_LVL_4_UP";
case BuildingID::DWELL_LVL_5_UP: return "DWELL_LVL_5_UP";
case BuildingID::DWELL_LVL_6_UP: return "DWELL_LVL_6_UP";
case BuildingID::DWELL_LVL_7_UP: return "DWELL_LVL_7_UP";
default:
return "UNKNOWN";
}
}
TownBulidingsWidget::TownBulidingsWidget(CGTownInstance & t, QWidget *parent) :
town(t),
QDialog(parent),
ui(new Ui::TownBulidingsWidget)
{
ui->setupUi(this);
ui->treeView->setModel(&model);
//ui->treeView->setColumnCount(3);
model.setHorizontalHeaderLabels(QStringList() << QStringLiteral("Type") << QStringLiteral("Enabled") << QStringLiteral("Built"));
//setAttribute(Qt::WA_DeleteOnClose);
}
TownBulidingsWidget::~TownBulidingsWidget()
{
delete ui;
}
QStandardItem * TownBulidingsWidget::addBuilding(const CTown & ctown, int bId, std::set<si32> & remaining)
{
BuildingID buildingId(bId);
const CBuilding * building = ctown.buildings.at(buildingId);
if(!building)
{
remaining.erase(bId);
return nullptr;
}
QString name = tr(building->Name().c_str());
if(name.isEmpty())
name = QString::fromStdString(defaultBuildingIdConversion(buildingId));
QList<QStandardItem *> checks;
checks << new QStandardItem(name);
checks.back()->setData(bId, Qt::UserRole);
checks << new QStandardItem;
checks.back()->setCheckable(true);
checks.back()->setCheckState(town.forbiddenBuildings.count(buildingId) ? Qt::Unchecked : Qt::Checked);
checks.back()->setData(bId, Qt::UserRole);
checks << new QStandardItem;
checks.back()->setCheckable(true);
checks.back()->setCheckState(town.builtBuildings.count(buildingId) ? Qt::Checked : Qt::Unchecked);
checks.back()->setData(bId, Qt::UserRole);
if(building->getBase() == buildingId)
{
model.appendRow(checks);
}
else
{
QStandardItem * parent = nullptr;
std::vector<QModelIndex> stack;
stack.push_back(QModelIndex());
while(!parent && !stack.empty())
{
auto pindex = stack.back();
stack.pop_back();
for(int i = 0; i < model.rowCount(pindex); ++i)
{
QModelIndex index = model.index(i, 0, pindex);
if(building->upgrade == model.itemFromIndex(index)->data(Qt::UserRole).toInt())
{
parent = model.itemFromIndex(index);
break;
}
if(model.hasChildren(index))
stack.push_back(index);
}
}
if(!parent)
parent = addBuilding(ctown, building->upgrade.getNum(), remaining);
if(!parent)
{
remaining.erase(bId);
return nullptr;
}
parent->appendRow(checks);
}
remaining.erase(bId);
return checks.front();
}
void TownBulidingsWidget::addBuildings(const CTown & ctown)
{
auto buildings = ctown.getAllBuildings();
while(!buildings.empty())
{
addBuilding(ctown, *buildings.begin(), buildings);
}
ui->treeView->resizeColumnToContents(0);
ui->treeView->resizeColumnToContents(1);
ui->treeView->resizeColumnToContents(2);
}
std::set<BuildingID> TownBulidingsWidget::getForbiddenBuildings()
{
std::set<BuildingID> result;
for(int i = 0; i < model.rowCount(); ++i)
{
if(auto * item = model.item(i, 1))
if(item->checkState() == Qt::Unchecked)
result.emplace(item->data(Qt::UserRole).toInt());
}
return result;
}
std::set<BuildingID> TownBulidingsWidget::getBuiltBuildings()
{
std::set<BuildingID> result;
for(int i = 0; i < model.rowCount(); ++i)
{
if(auto * item = model.item(i, 2))
if(item->checkState() == Qt::Checked)
result.emplace(item->data(Qt::UserRole).toInt());
}
return result;
}
void TownBulidingsWidget::on_treeView_expanded(const QModelIndex &index)
{
ui->treeView->resizeColumnToContents(0);
}
void TownBulidingsWidget::on_treeView_collapsed(const QModelIndex &index)
{
ui->treeView->resizeColumnToContents(0);
}
TownBuildingsDelegate::TownBuildingsDelegate(CGTownInstance & t): town(t), QStyledItemDelegate()
{
}
QWidget * TownBuildingsDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return new TownBulidingsWidget(town, parent);
}
void TownBuildingsDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
if(auto * ed = qobject_cast<TownBulidingsWidget *>(editor))
{
auto * ctown = town.town;
if(!ctown)
ctown = VLC->townh->randomTown;
if(!ctown)
throw std::runtime_error("No Town defined for type selected");
ed->addBuildings(*ctown);
}
else
{
QStyledItemDelegate::setEditorData(editor, index);
}
}
void TownBuildingsDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
if(auto * ed = qobject_cast<TownBulidingsWidget *>(editor))
{
town.forbiddenBuildings = ed->getForbiddenBuildings();
town.builtBuildings = ed->getBuiltBuildings();
auto data = model->itemData(index);
model->setData(index, "dummy");
model->setItemData(index, data); //dummy change to trigger signal
}
else
{
QStyledItemDelegate::setModelData(editor, model, index);
}
}

View File

@ -0,0 +1,53 @@
#ifndef TOWNBULIDINGSWIDGET_H
#define TOWNBULIDINGSWIDGET_H
#include <QDialog>
#include "../lib/mapObjects/CGTownInstance.h"
namespace Ui {
class TownBulidingsWidget;
}
class TownBulidingsWidget : public QDialog
{
Q_OBJECT
QStandardItem * addBuilding(const CTown & ctown, int bId, std::set<si32> & remaining);
public:
explicit TownBulidingsWidget(CGTownInstance &, QWidget *parent = nullptr);
~TownBulidingsWidget();
void addBuildings(const CTown & ctown);
std::set<BuildingID> getForbiddenBuildings();
std::set<BuildingID> getBuiltBuildings();
private slots:
void on_treeView_expanded(const QModelIndex &index);
void on_treeView_collapsed(const QModelIndex &index);
private:
Ui::TownBulidingsWidget *ui;
CGTownInstance & town;
mutable QStandardItemModel model;
};
class TownBuildingsDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
using QStyledItemDelegate::QStyledItemDelegate;
TownBuildingsDelegate(CGTownInstance &);
QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
private:
CGTownInstance & town;
//std::set<BuildingID>
};
#endif // TOWNBULIDINGSWIDGET_H

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TownBulidingsWidget</class>
<widget class="QDialog" name="TownBulidingsWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>480</width>
<height>280</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>480</width>
<height>280</height>
</size>
</property>
<property name="windowTitle">
<string>Buildings</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QTreeView" name="treeView">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<attribute name="headerCascadingSectionResizes">
<bool>true</bool>
</attribute>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -18,6 +18,7 @@
#include "../lib/mapping/CMapEditManager.h"
#include "../lib/Terrain.h"
#include "../lib/mapObjects/CObjectClassesHandler.h"
#include "../lib/filesystem/CFilesystemLoader.h"
#include "CGameInfo.h"
@ -25,7 +26,7 @@
#include "graphics.h"
#include "windownewmap.h"
#include "objectbrowser.h"
#include "inspector.h"
#include "inspector/inspector.h"
#include "mapsettings.h"
#include "playersettings.h"
#include "validator.h"
@ -161,7 +162,14 @@ MainWindow::MainWindow(QWidget *parent) :
loadObjectsTree();
ui->tabWidget->setCurrentIndex(0);
for(int i = 0; i < 8; ++i)
{
connect(getActionPlayer(PlayerColor(i)), &QAction::toggled, this, [&, i](){switchDefaultPlayer(PlayerColor(i));});
}
connect(getActionPlayer(PlayerColor::NEUTRAL), &QAction::toggled, this, [&](){switchDefaultPlayer(PlayerColor::NEUTRAL);});
onPlayersChanged();
show();
}
@ -171,6 +179,27 @@ MainWindow::~MainWindow()
delete ui;
}
bool MainWindow::getAnswerAboutUnsavedChanges()
{
if(unsaved)
{
auto sure = QMessageBox::question(this, "Confirmation", "Unsaved changes will be lost, are you sure?");
if(sure == QMessageBox::No)
{
return false;
}
}
return true;
}
void MainWindow::closeEvent(QCloseEvent *event)
{
if(getAnswerAboutUnsavedChanges())
QMainWindow::closeEvent(event);
else
event->ignore();
}
void MainWindow::setStatusMessage(const QString & status)
{
statusBar()->showMessage(status);
@ -205,10 +234,15 @@ void MainWindow::initializeMap(bool isNew)
//enable settings
ui->actionMapSettings->setEnabled(true);
ui->actionPlayers_settings->setEnabled(true);
onPlayersChanged();
}
void MainWindow::on_actionOpen_triggered()
{
if(!getAnswerAboutUnsavedChanges())
return;
auto filenameSelect = QFileDialog::getOpenFileName(this, tr("Open Image"), QString::fromStdString(VCMIDirs::get().userCachePath().make_preferred().string()), tr("Homm3 Files (*.vmap *.h3m)"));
if(filenameSelect.isNull())
@ -217,14 +251,16 @@ void MainWindow::on_actionOpen_triggered()
QFileInfo fi(filenameSelect);
std::string fname = fi.fileName().toStdString();
std::string fdir = fi.dir().path().toStdString();
ResourceID resId("MAPS/" + fname, EResType::MAP);
//ResourceID resId("MAPS/SomeMap.vmap", EResType::MAP);
if(!CResourceHandler::get()->existsResource(resId))
{
QMessageBox::information(this, "Failed to open map", "Only map folder is supported");
return;
}
ResourceID resId("MAPEDITOR/" + fname, EResType::MAP);
//addFilesystem takes care about memory deallocation if case of failure, no memory leak here
auto * mapEditorFilesystem = new CFilesystemLoader("MAPEDITOR/", fdir, 0);
CResourceHandler::removeFilesystem("local", "mapEditor");
CResourceHandler::addFilesystem("local", "mapEditor", mapEditorFilesystem);
if(!CResourceHandler::get("mapEditor")->existsResource(resId))
QMessageBox::warning(this, "Failed to open map", "Cannot open map from this folder");
CMapService mapService;
try
@ -299,7 +335,8 @@ void MainWindow::on_actionSave_as_triggered()
void MainWindow::on_actionNew_triggered()
{
new WindowNewMap(this);
if(getAnswerAboutUnsavedChanges())
new WindowNewMap(this);
}
void MainWindow::on_actionSave_triggered()
@ -333,11 +370,11 @@ void MainWindow::addGroupIntoCatalog(const std::string & groupName, bool staticO
if(catalog.count(ID))
continue;
addGroupIntoCatalog(groupName, staticOnly, ID);
addGroupIntoCatalog(groupName, true, staticOnly, ID);
}
}
void MainWindow::addGroupIntoCatalog(const std::string & groupName, bool staticOnly, int ID)
void MainWindow::addGroupIntoCatalog(const std::string & groupName, bool useCustomName, bool staticOnly, int ID)
{
QStandardItem * itemGroup = nullptr;
auto itms = objectsModel.findItems(QString::fromStdString(groupName));
@ -352,7 +389,6 @@ void MainWindow::addGroupIntoCatalog(const std::string & groupName, bool staticO
}
auto knownSubObjects = VLC->objtypeh->knownSubObjects(ID);
bool singleSubObject = knownSubObjects.size() == 1;
for(auto secondaryID : knownSubObjects)
{
auto factory = VLC->objtypeh->getHandlerFor(ID, secondaryID);
@ -361,7 +397,12 @@ void MainWindow::addGroupIntoCatalog(const std::string & groupName, bool staticO
if(staticOnly && !factory->isStaticObject())
continue;
auto * itemType = new QStandardItem(QString::fromStdString(factory->subTypeName));
auto subGroupName = QString::fromStdString(factory->subTypeName);
auto customName = factory->getCustomName();
if(customName)
subGroupName = tr(customName->c_str());
auto * itemType = new QStandardItem(subGroupName);
for(int templateId = 0; templateId < templates.size(); ++templateId)
{
auto templ = templates[templateId];
@ -391,15 +432,23 @@ void MainWindow::addGroupIntoCatalog(const std::string & groupName, bool staticO
{"animationEditor", QString::fromStdString(templ.editorAnimationFile)},
{"animation", QString::fromStdString(templ.animationFile)},
{"preview", jsonFromPixmap(preview)}};
//create object to extract name
std::unique_ptr<CGObjectInstance> temporaryObj(factory->create(templ));
QString translated = useCustomName ? tr(temporaryObj->getObjectName().c_str()) : subGroupName;
//do not have extra level
if(singleTemplate)
{
if(useCustomName)
itemType->setText(translated);
itemType->setIcon(QIcon(preview));
itemType->setData(data);
}
else
{
if(useCustomName)
itemType->setText(translated);
auto * item = new QStandardItem(QIcon(preview), QString::fromStdString(templ.stringID));
item->setData(data);
itemType->appendRow(item);
@ -412,6 +461,8 @@ void MainWindow::addGroupIntoCatalog(const std::string & groupName, bool staticO
void MainWindow::loadObjectsTree()
{
try
{
ui->terrainFilterCombo->addItem("");
//adding terrains
for(auto & terrain : Terrain::Manager::terrains())
@ -443,146 +494,153 @@ void MainWindow::loadObjectsTree()
//adding objects
addGroupIntoCatalog("TOWNS", false, Obj::TOWN);
addGroupIntoCatalog("TOWNS", false, Obj::RANDOM_TOWN);
addGroupIntoCatalog("TOWNS", false, Obj::SHIPYARD);
addGroupIntoCatalog("TOWNS", false, Obj::GARRISON);
addGroupIntoCatalog("TOWNS", false, Obj::GARRISON2);
addGroupIntoCatalog("MISC", false, Obj::ALTAR_OF_SACRIFICE);
addGroupIntoCatalog("MISC", false, Obj::ARENA);
addGroupIntoCatalog("MISC", false, Obj::BLACK_MARKET);
addGroupIntoCatalog("MISC", false, Obj::BORDERGUARD);
addGroupIntoCatalog("MISC", false, Obj::KEYMASTER);
addGroupIntoCatalog("MISC", false, Obj::BUOY);
addGroupIntoCatalog("MISC", false, Obj::CAMPFIRE);
addGroupIntoCatalog("MISC", false, Obj::CARTOGRAPHER);
addGroupIntoCatalog("MISC", false, Obj::SWAN_POND);
addGroupIntoCatalog("MISC", false, Obj::COVER_OF_DARKNESS);
addGroupIntoCatalog("MISC", false, Obj::CORPSE);
addGroupIntoCatalog("MISC", false, Obj::MARLETTO_TOWER);
addGroupIntoCatalog("MISC", false, Obj::DERELICT_SHIP);
addGroupIntoCatalog("MISC", false, Obj::FAERIE_RING);
addGroupIntoCatalog("MISC", false, Obj::FLOTSAM);
addGroupIntoCatalog("MISC", false, Obj::FOUNTAIN_OF_FORTUNE);
addGroupIntoCatalog("MISC", false, Obj::FOUNTAIN_OF_YOUTH);
addGroupIntoCatalog("MISC", false, Obj::GARDEN_OF_REVELATION);
addGroupIntoCatalog("MISC", false, Obj::HILL_FORT);
addGroupIntoCatalog("MISC", false, Obj::IDOL_OF_FORTUNE);
addGroupIntoCatalog("MISC", false, Obj::LIBRARY_OF_ENLIGHTENMENT);
addGroupIntoCatalog("MISC", false, Obj::LIGHTHOUSE);
addGroupIntoCatalog("MISC", false, Obj::SCHOOL_OF_MAGIC);
addGroupIntoCatalog("MISC", false, Obj::MAGIC_SPRING);
addGroupIntoCatalog("MISC", false, Obj::MAGIC_WELL);
addGroupIntoCatalog("MISC", false, Obj::MERCENARY_CAMP);
addGroupIntoCatalog("MISC", false, Obj::MERMAID);
addGroupIntoCatalog("MISC", false, Obj::MYSTICAL_GARDEN);
addGroupIntoCatalog("MISC", false, Obj::OASIS);
addGroupIntoCatalog("MISC", false, Obj::OBELISK);
addGroupIntoCatalog("MISC", false, Obj::REDWOOD_OBSERVATORY);
addGroupIntoCatalog("MISC", false, Obj::OCEAN_BOTTLE);
addGroupIntoCatalog("MISC", false, Obj::PILLAR_OF_FIRE);
addGroupIntoCatalog("MISC", false, Obj::STAR_AXIS);
addGroupIntoCatalog("MISC", false, Obj::RALLY_FLAG);
addGroupIntoCatalog("MISC", false, Obj::LEAN_TO);
addGroupIntoCatalog("MISC", false, Obj::WATERING_HOLE);
addGroupIntoCatalog("PRISON", false, Obj::PRISON);
addGroupIntoCatalog("ARTIFACTS", false, Obj::ARTIFACT);
addGroupIntoCatalog("ARTIFACTS", false, Obj::RANDOM_ART);
addGroupIntoCatalog("ARTIFACTS", false, Obj::RANDOM_TREASURE_ART);
addGroupIntoCatalog("ARTIFACTS", false, Obj::RANDOM_MINOR_ART);
addGroupIntoCatalog("ARTIFACTS", false, Obj::RANDOM_MAJOR_ART);
addGroupIntoCatalog("ARTIFACTS", false, Obj::RANDOM_RELIC_ART);
addGroupIntoCatalog("RESOURCES", false, Obj::PANDORAS_BOX);
addGroupIntoCatalog("RESOURCES", false, Obj::RANDOM_RESOURCE);
addGroupIntoCatalog("RESOURCES", false, Obj::RESOURCE);
addGroupIntoCatalog("RESOURCES", false, Obj::SEA_CHEST);
addGroupIntoCatalog("RESOURCES", false, Obj::TREASURE_CHEST);
addGroupIntoCatalog("RESOURCES", false, Obj::SPELL_SCROLL);
addGroupIntoCatalog("BANKS", false, Obj::CREATURE_BANK);
addGroupIntoCatalog("BANKS", false, Obj::DRAGON_UTOPIA);
addGroupIntoCatalog("DWELLINGS", false, Obj::CREATURE_GENERATOR1);
addGroupIntoCatalog("DWELLINGS", false, Obj::CREATURE_GENERATOR2);
addGroupIntoCatalog("DWELLINGS", false, Obj::CREATURE_GENERATOR3);
addGroupIntoCatalog("DWELLINGS", false, Obj::CREATURE_GENERATOR4);
addGroupIntoCatalog("DWELLINGS", false, Obj::RANDOM_DWELLING);
addGroupIntoCatalog("DWELLINGS", false, Obj::RANDOM_DWELLING_LVL);
addGroupIntoCatalog("DWELLINGS", false, Obj::RANDOM_DWELLING_FACTION);
addGroupIntoCatalog("GROUNDS", false, Obj::CURSED_GROUND1);
addGroupIntoCatalog("GROUNDS", false, Obj::MAGIC_PLAINS1);
addGroupIntoCatalog("GROUNDS", false, Obj::CLOVER_FIELD);
addGroupIntoCatalog("GROUNDS", false, Obj::CURSED_GROUND2);
addGroupIntoCatalog("GROUNDS", false, Obj::EVIL_FOG);
addGroupIntoCatalog("GROUNDS", false, Obj::FAVORABLE_WINDS);
addGroupIntoCatalog("GROUNDS", false, Obj::FIERY_FIELDS);
addGroupIntoCatalog("GROUNDS", false, Obj::HOLY_GROUNDS);
addGroupIntoCatalog("GROUNDS", false, Obj::LUCID_POOLS);
addGroupIntoCatalog("GROUNDS", false, Obj::MAGIC_CLOUDS);
addGroupIntoCatalog("GROUNDS", false, Obj::MAGIC_PLAINS2);
addGroupIntoCatalog("GROUNDS", false, Obj::ROCKLANDS);
addGroupIntoCatalog("TELEPORTS", false, Obj::MONOLITH_ONE_WAY_ENTRANCE);
addGroupIntoCatalog("TELEPORTS", false, Obj::MONOLITH_ONE_WAY_EXIT);
addGroupIntoCatalog("TELEPORTS", false, Obj::MONOLITH_TWO_WAY);
addGroupIntoCatalog("TELEPORTS", false, Obj::SUBTERRANEAN_GATE);
addGroupIntoCatalog("TELEPORTS", false, Obj::WHIRLPOOL);
addGroupIntoCatalog("MINES", false, Obj::MINE);
addGroupIntoCatalog("MINES", false, Obj::ABANDONED_MINE);
addGroupIntoCatalog("MINES", false, Obj::WINDMILL);
addGroupIntoCatalog("MINES", false, Obj::WATER_WHEEL);
addGroupIntoCatalog("TRIGGERS", false, Obj::EVENT);
addGroupIntoCatalog("TRIGGERS", false, Obj::GRAIL);
addGroupIntoCatalog("TRIGGERS", false, Obj::SIGN);
addGroupIntoCatalog("MONSTERS", false, Obj::MONSTER);
addGroupIntoCatalog("MONSTERS", false, Obj::RANDOM_MONSTER);
addGroupIntoCatalog("MONSTERS", false, Obj::RANDOM_MONSTER_L1);
addGroupIntoCatalog("MONSTERS", false, Obj::RANDOM_MONSTER_L2);
addGroupIntoCatalog("MONSTERS", false, Obj::RANDOM_MONSTER_L3);
addGroupIntoCatalog("MONSTERS", false, Obj::RANDOM_MONSTER_L4);
addGroupIntoCatalog("MONSTERS", false, Obj::RANDOM_MONSTER_L5);
addGroupIntoCatalog("MONSTERS", false, Obj::RANDOM_MONSTER_L6);
addGroupIntoCatalog("MONSTERS", false, Obj::RANDOM_MONSTER_L7);
addGroupIntoCatalog("QUESTS", false, Obj::SEER_HUT);
addGroupIntoCatalog("QUESTS", false, Obj::BORDER_GATE);
addGroupIntoCatalog("QUESTS", false, Obj::QUEST_GUARD);
addGroupIntoCatalog("QUESTS", false, Obj::HUT_OF_MAGI);
addGroupIntoCatalog("QUESTS", false, Obj::EYE_OF_MAGI);
addGroupIntoCatalog("TOWNS", false, false, Obj::TOWN);
addGroupIntoCatalog("TOWNS", false, false, Obj::RANDOM_TOWN);
addGroupIntoCatalog("TOWNS", true, false, Obj::SHIPYARD);
addGroupIntoCatalog("TOWNS", true, false, Obj::GARRISON);
addGroupIntoCatalog("TOWNS", true, false, Obj::GARRISON2);
addGroupIntoCatalog("MISC", true, false, Obj::ALTAR_OF_SACRIFICE);
addGroupIntoCatalog("MISC", true, false, Obj::ARENA);
addGroupIntoCatalog("MISC", true, false, Obj::BLACK_MARKET);
addGroupIntoCatalog("MISC", true, false, Obj::BUOY);
addGroupIntoCatalog("MISC", true, false, Obj::CARTOGRAPHER);
addGroupIntoCatalog("MISC", true, false, Obj::SWAN_POND);
addGroupIntoCatalog("MISC", true, false, Obj::COVER_OF_DARKNESS);
addGroupIntoCatalog("MISC", true, false, Obj::CORPSE);
addGroupIntoCatalog("MISC", true, false, Obj::FAERIE_RING);
addGroupIntoCatalog("MISC", true, false, Obj::FOUNTAIN_OF_FORTUNE);
addGroupIntoCatalog("MISC", true, false, Obj::FOUNTAIN_OF_YOUTH);
addGroupIntoCatalog("MISC", true, false, Obj::GARDEN_OF_REVELATION);
addGroupIntoCatalog("MISC", true, false, Obj::HILL_FORT);
addGroupIntoCatalog("MISC", true, false, Obj::IDOL_OF_FORTUNE);
addGroupIntoCatalog("MISC", true, false, Obj::LIBRARY_OF_ENLIGHTENMENT);
addGroupIntoCatalog("MISC", true, false, Obj::LIGHTHOUSE);
addGroupIntoCatalog("MISC", true, false, Obj::SCHOOL_OF_MAGIC);
addGroupIntoCatalog("MISC", true, false, Obj::MAGIC_SPRING);
addGroupIntoCatalog("MISC", true, false, Obj::MAGIC_WELL);
addGroupIntoCatalog("MISC", true, false, Obj::MERCENARY_CAMP);
addGroupIntoCatalog("MISC", true, false, Obj::MERMAID);
addGroupIntoCatalog("MISC", true, false, Obj::MYSTICAL_GARDEN);
addGroupIntoCatalog("MISC", true, false, Obj::OASIS);
addGroupIntoCatalog("MISC", true, false, Obj::LEAN_TO);
addGroupIntoCatalog("MISC", true, false, Obj::OBELISK);
addGroupIntoCatalog("MISC", true, false, Obj::REDWOOD_OBSERVATORY);
addGroupIntoCatalog("MISC", true, false, Obj::PILLAR_OF_FIRE);
addGroupIntoCatalog("MISC", true, false, Obj::STAR_AXIS);
addGroupIntoCatalog("MISC", true, false, Obj::RALLY_FLAG);
addGroupIntoCatalog("MISC", true, false, Obj::WATERING_HOLE);
addGroupIntoCatalog("MISC", true, false, Obj::SCHOLAR);
addGroupIntoCatalog("MISC", true, false, Obj::SHRINE_OF_MAGIC_INCANTATION);
addGroupIntoCatalog("MISC", true, false, Obj::SHRINE_OF_MAGIC_GESTURE);
addGroupIntoCatalog("MISC", true, false, Obj::SHRINE_OF_MAGIC_THOUGHT);
addGroupIntoCatalog("MISC", true, false, Obj::SIRENS);
addGroupIntoCatalog("MISC", true, false, Obj::STABLES);
addGroupIntoCatalog("MISC", true, false, Obj::TAVERN);
addGroupIntoCatalog("MISC", true, false, Obj::TEMPLE);
addGroupIntoCatalog("MISC", true, false, Obj::DEN_OF_THIEVES);
addGroupIntoCatalog("MISC", true, false, Obj::TRADING_POST);
addGroupIntoCatalog("MISC", true, false, Obj::TRADING_POST_SNOW);
addGroupIntoCatalog("MISC", true, false, Obj::LEARNING_STONE);
addGroupIntoCatalog("MISC", true, false, Obj::TREE_OF_KNOWLEDGE);
addGroupIntoCatalog("MISC", true, false, Obj::UNIVERSITY);
addGroupIntoCatalog("MISC", true, false, Obj::WAGON);
addGroupIntoCatalog("MISC", true, false, Obj::SCHOOL_OF_WAR);
addGroupIntoCatalog("MISC", true, false, Obj::WAR_MACHINE_FACTORY);
addGroupIntoCatalog("MISC", true, false, Obj::WARRIORS_TOMB);
addGroupIntoCatalog("MISC", true, false, Obj::WITCH_HUT);
addGroupIntoCatalog("MISC", true, false, Obj::FREELANCERS_GUILD);
addGroupIntoCatalog("MISC", true, false, Obj::SANCTUARY);
addGroupIntoCatalog("MISC", true, false, Obj::MARLETTO_TOWER);
//addGroupIntoCatalog("PRISON", true, false, Obj::PRISON);
addGroupIntoCatalog("ARTIFACTS", true, false, Obj::ARTIFACT);
addGroupIntoCatalog("ARTIFACTS", false, false, Obj::RANDOM_ART);
addGroupIntoCatalog("ARTIFACTS", false, false, Obj::RANDOM_TREASURE_ART);
addGroupIntoCatalog("ARTIFACTS", false, false, Obj::RANDOM_MINOR_ART);
addGroupIntoCatalog("ARTIFACTS", false, false, Obj::RANDOM_MAJOR_ART);
addGroupIntoCatalog("ARTIFACTS", false, false, Obj::RANDOM_RELIC_ART);
addGroupIntoCatalog("ARTIFACTS", true, false, Obj::SPELL_SCROLL);
//addGroupIntoCatalog("RESOURCES", true, false, Obj::PANDORAS_BOX);
addGroupIntoCatalog("RESOURCES", true, false, Obj::RANDOM_RESOURCE);
addGroupIntoCatalog("RESOURCES", false, false, Obj::RESOURCE);
addGroupIntoCatalog("RESOURCES", true, false, Obj::SEA_CHEST);
addGroupIntoCatalog("RESOURCES", true, false, Obj::TREASURE_CHEST);
addGroupIntoCatalog("RESOURCES", true, false, Obj::CAMPFIRE);
addGroupIntoCatalog("RESOURCES", true, false, Obj::SHIPWRECK_SURVIVOR);
addGroupIntoCatalog("RESOURCES", true, false, Obj::FLOTSAM);
addGroupIntoCatalog("BANKS", true, false, Obj::CREATURE_BANK);
addGroupIntoCatalog("BANKS", true, false, Obj::DRAGON_UTOPIA);
addGroupIntoCatalog("BANKS", true, false, Obj::CRYPT);
addGroupIntoCatalog("BANKS", true, false, Obj::DERELICT_SHIP);
addGroupIntoCatalog("BANKS", true, false, Obj::PYRAMID);
addGroupIntoCatalog("BANKS", true, false, Obj::SHIPWRECK);
addGroupIntoCatalog("DWELLINGS", true, false, Obj::CREATURE_GENERATOR1);
addGroupIntoCatalog("DWELLINGS", true, false, Obj::CREATURE_GENERATOR2);
addGroupIntoCatalog("DWELLINGS", true, false, Obj::CREATURE_GENERATOR3);
addGroupIntoCatalog("DWELLINGS", true, false, Obj::CREATURE_GENERATOR4);
addGroupIntoCatalog("DWELLINGS", true, false, Obj::REFUGEE_CAMP);
addGroupIntoCatalog("DWELLINGS", false, false, Obj::RANDOM_DWELLING);
addGroupIntoCatalog("DWELLINGS", false, false, Obj::RANDOM_DWELLING_LVL);
addGroupIntoCatalog("DWELLINGS", false, false, Obj::RANDOM_DWELLING_FACTION);
addGroupIntoCatalog("GROUNDS", true, false, Obj::CURSED_GROUND1);
addGroupIntoCatalog("GROUNDS", true, false, Obj::MAGIC_PLAINS1);
addGroupIntoCatalog("GROUNDS", true, false, Obj::CLOVER_FIELD);
addGroupIntoCatalog("GROUNDS", true, false, Obj::CURSED_GROUND2);
addGroupIntoCatalog("GROUNDS", true, false, Obj::EVIL_FOG);
addGroupIntoCatalog("GROUNDS", true, false, Obj::FAVORABLE_WINDS);
addGroupIntoCatalog("GROUNDS", true, false, Obj::FIERY_FIELDS);
addGroupIntoCatalog("GROUNDS", true, false, Obj::HOLY_GROUNDS);
addGroupIntoCatalog("GROUNDS", true, false, Obj::LUCID_POOLS);
addGroupIntoCatalog("GROUNDS", true, false, Obj::MAGIC_CLOUDS);
addGroupIntoCatalog("GROUNDS", true, false, Obj::MAGIC_PLAINS2);
addGroupIntoCatalog("GROUNDS", true, false, Obj::ROCKLANDS);
addGroupIntoCatalog("GROUNDS", true, false, Obj::HOLE);
addGroupIntoCatalog("TELEPORTS", true, false, Obj::MONOLITH_ONE_WAY_ENTRANCE);
addGroupIntoCatalog("TELEPORTS", true, false, Obj::MONOLITH_ONE_WAY_EXIT);
addGroupIntoCatalog("TELEPORTS", true, false, Obj::MONOLITH_TWO_WAY);
addGroupIntoCatalog("TELEPORTS", true, false, Obj::SUBTERRANEAN_GATE);
addGroupIntoCatalog("TELEPORTS", true, false, Obj::WHIRLPOOL);
addGroupIntoCatalog("MINES", true, false, Obj::MINE);
addGroupIntoCatalog("MINES", false, false, Obj::ABANDONED_MINE);
addGroupIntoCatalog("MINES", true, false, Obj::WINDMILL);
addGroupIntoCatalog("MINES", true, false, Obj::WATER_WHEEL);
//addGroupIntoCatalog("TRIGGERS", true, false, Obj::EVENT);
addGroupIntoCatalog("TRIGGERS", true, false, Obj::GRAIL);
addGroupIntoCatalog("TRIGGERS", true, false, Obj::SIGN);
addGroupIntoCatalog("TRIGGERS", true, false, Obj::OCEAN_BOTTLE);
addGroupIntoCatalog("MONSTERS", false, false, Obj::MONSTER);
addGroupIntoCatalog("MONSTERS", true, false, Obj::RANDOM_MONSTER);
addGroupIntoCatalog("MONSTERS", true, false, Obj::RANDOM_MONSTER_L1);
addGroupIntoCatalog("MONSTERS", true, false, Obj::RANDOM_MONSTER_L2);
addGroupIntoCatalog("MONSTERS", true, false, Obj::RANDOM_MONSTER_L3);
addGroupIntoCatalog("MONSTERS", true, false, Obj::RANDOM_MONSTER_L4);
addGroupIntoCatalog("MONSTERS", true, false, Obj::RANDOM_MONSTER_L5);
addGroupIntoCatalog("MONSTERS", true, false, Obj::RANDOM_MONSTER_L6);
addGroupIntoCatalog("MONSTERS", true, false, Obj::RANDOM_MONSTER_L7);
//addGroupIntoCatalog("QUESTS", true, false, Obj::SEER_HUT);
addGroupIntoCatalog("QUESTS", true, false, Obj::BORDER_GATE);
//addGroupIntoCatalog("QUESTS", true, false, Obj::QUEST_GUARD);
addGroupIntoCatalog("QUESTS", true, false, Obj::HUT_OF_MAGI);
addGroupIntoCatalog("QUESTS", true, false, Obj::EYE_OF_MAGI);
addGroupIntoCatalog("QUESTS", true, false, Obj::BORDERGUARD);
addGroupIntoCatalog("QUESTS", true, false, Obj::KEYMASTER);
addGroupIntoCatalog("OBSTACLES", true);
addGroupIntoCatalog("OTHER", false);
//addGroupIntoCatalog("OTHER", false);
/*
HERO = 34,
LEAN_TO = 39,
PYRAMID = 63,//subtype 0
WOG_OBJECT = 63,//subtype > 0
RANDOM_HERO = 70,
REFUGEE_CAMP = 78,
SANCTUARY = 80,
SCHOLAR = 81,
CRYPT = 84,
SHIPWRECK = 85,
SHIPWRECK_SURVIVOR = 86,
SHRINE_OF_MAGIC_INCANTATION = 88,
SHRINE_OF_MAGIC_GESTURE = 89,
SHRINE_OF_MAGIC_THOUGHT = 90,
SIRENS = 92,
STABLES = 94,
TAVERN = 95,
TEMPLE = 96,
DEN_OF_THIEVES = 97,
TRADING_POST = 99,
LEARNING_STONE = 100,
TREE_OF_KNOWLEDGE = 102,
UNIVERSITY = 104,
WAGON = 105,
WAR_MACHINE_FACTORY = 106,
SCHOOL_OF_WAR = 107,
WARRIORS_TOMB = 108,
WITCH_HUT = 113,
HOLE = 124,
FREELANCERS_GUILD = 213,
HERO_PLACEHOLDER = 214,
TRADING_POST_SNOW = 221,
*/
}
catch(const std::exception & e)
{
QMessageBox::critical(this, "Mods loading problem", "Critical error during Mods loading. Disable some mods and restart.");
}
}
void MainWindow::on_actionLevel_triggered()
@ -864,8 +922,60 @@ void MainWindow::on_actionPlayers_settings_triggered()
auto settingsDialog = new PlayerSettings(controller, this);
settingsDialog->setWindowModality(Qt::WindowModal);
settingsDialog->setModal(true);
connect(settingsDialog, &QDialog::finished, this, &MainWindow::onPlayersChanged);
}
QAction * MainWindow::getActionPlayer(const PlayerColor & player)
{
if(player.getNum() == 0) return ui->actionPlayer_1;
if(player.getNum() == 1) return ui->actionPlayer_2;
if(player.getNum() == 2) return ui->actionPlayer_3;
if(player.getNum() == 3) return ui->actionPlayer_4;
if(player.getNum() == 4) return ui->actionPlayer_5;
if(player.getNum() == 5) return ui->actionPlayer_6;
if(player.getNum() == 6) return ui->actionPlayer_7;
if(player.getNum() == 7) return ui->actionPlayer_8;
return ui->actionNeutral;
}
void MainWindow::switchDefaultPlayer(const PlayerColor & player)
{
if(controller.defaultPlayer == player)
return;
ui->actionNeutral->blockSignals(true);
ui->actionNeutral->setChecked(PlayerColor::NEUTRAL == player);
ui->actionNeutral->blockSignals(false);
for(int i = 0; i < 8; ++i)
{
getActionPlayer(PlayerColor(i))->blockSignals(true);
getActionPlayer(PlayerColor(i))->setChecked(PlayerColor(i) == player);
getActionPlayer(PlayerColor(i))->blockSignals(false);
}
controller.defaultPlayer = player;
}
void MainWindow::onPlayersChanged()
{
if(controller.map())
{
getActionPlayer(PlayerColor::NEUTRAL)->setEnabled(true);
for(int i = 0; i < controller.map()->players.size(); ++i)
getActionPlayer(PlayerColor(i))->setEnabled(controller.map()->players.at(i).canAnyonePlay());
if(!getActionPlayer(controller.defaultPlayer)->isEnabled() || controller.defaultPlayer == PlayerColor::NEUTRAL)
switchDefaultPlayer(PlayerColor::NEUTRAL);
}
else
{
for(int i = 0; i < PlayerColor::PLAYER_LIMIT.getNum(); ++i)
getActionPlayer(PlayerColor(i))->setEnabled(false);
getActionPlayer(PlayerColor::NEUTRAL)->setEnabled(false);
}
}
void MainWindow::enableUndo(bool enable)
{
ui->actionUndo->setEnabled(enable);

View File

@ -96,6 +96,8 @@ private slots:
void on_actionUpdate_appearance_triggered();
void on_actionRecreate_obstacles_triggered();
void switchDefaultPlayer(const PlayerColor &);
public slots:
@ -105,15 +107,23 @@ public slots:
void enableUndo(bool enable);
void enableRedo(bool enable);
void onSelectionMade(int level, bool anythingSelected);
void onPlayersChanged();
void displayStatus(const QString& message, int timeout = 2000);
private:
void preparePreview(const QModelIndex &index, bool createNew);
void addGroupIntoCatalog(const std::string & groupName, bool staticOnly);
void addGroupIntoCatalog(const std::string & groupName, bool staticOnly, int ID);
void addGroupIntoCatalog(const std::string & groupName, bool useCustomName, bool staticOnly, int ID);
QAction * getActionPlayer(const PlayerColor &);
void changeBrushState(int idx);
void setTitle();
void closeEvent(QCloseEvent *event) override;
bool getAnswerAboutUnsavedChanges();
void loadUserSettings();
void saveUserSettings();

View File

@ -51,7 +51,7 @@
<x>0</x>
<y>0</y>
<width>1024</width>
<height>18</height>
<height>17</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
@ -88,6 +88,16 @@
<addaction name="actionLevel"/>
<addaction name="actionGrid"/>
<addaction name="actionPass"/>
<addaction name="separator"/>
<addaction name="actionNeutral"/>
<addaction name="actionPlayer_1"/>
<addaction name="actionPlayer_2"/>
<addaction name="actionPlayer_3"/>
<addaction name="actionPlayer_4"/>
<addaction name="actionPlayer_5"/>
<addaction name="actionPlayer_6"/>
<addaction name="actionPlayer_7"/>
<addaction name="actionPlayer_8"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuEdit"/>
@ -295,6 +305,9 @@
<property name="mouseTracking">
<bool>false</bool>
</property>
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
@ -672,7 +685,7 @@
<x>0</x>
<y>0</y>
<width>128</width>
<height>344</height>
<height>320</height>
</rect>
</property>
<property name="sizePolicy">
@ -715,7 +728,7 @@
<x>0</x>
<y>0</y>
<width>128</width>
<height>344</height>
<height>320</height>
</rect>
</property>
<property name="sizePolicy">
@ -734,7 +747,7 @@
<x>0</x>
<y>0</y>
<width>128</width>
<height>344</height>
<height>320</height>
</rect>
</property>
<property name="sizePolicy">
@ -796,6 +809,9 @@
<property name="text">
<string>Save as</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+S</string>
</property>
</action>
<action name="actionLevel">
<property name="text">
@ -920,7 +936,7 @@
<string>Erase</string>
</property>
<property name="shortcut">
<string>Del</string>
<string>Backspace, Del</string>
</property>
</action>
<action name="actionNeutral">
@ -930,6 +946,9 @@
<property name="text">
<string>Neutral</string>
</property>
<property name="shortcut">
<string>Ctrl+0</string>
</property>
</action>
<action name="actionValidate">
<property name="text">
@ -952,6 +971,94 @@
<string>Recreate obstacles</string>
</property>
</action>
<action name="actionPlayer_1">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Player 1</string>
</property>
<property name="shortcut">
<string>Ctrl+1</string>
</property>
</action>
<action name="actionPlayer_2">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Player 2</string>
</property>
<property name="shortcut">
<string>Ctrl+2</string>
</property>
</action>
<action name="actionPlayer_3">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Player 3</string>
</property>
<property name="shortcut">
<string>Ctrl+3</string>
</property>
</action>
<action name="actionPlayer_4">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Player 4</string>
</property>
<property name="shortcut">
<string>Ctrl+4</string>
</property>
</action>
<action name="actionPlayer_5">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Player 5</string>
</property>
<property name="shortcut">
<string>Ctrl+5</string>
</property>
</action>
<action name="actionPlayer_6">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Player 6</string>
</property>
<property name="shortcut">
<string>Ctrl+6</string>
</property>
</action>
<action name="actionPlayer_7">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Player 7</string>
</property>
<property name="shortcut">
<string>Ctrl+7</string>
</property>
</action>
<action name="actionPlayer_8">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Player 8</string>
</property>
<property name="shortcut">
<string>Ctrl+8</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

View File

@ -13,7 +13,7 @@
#include "scenelayer.h"
#include "maphandler.h"
#include "mainwindow.h"
#include "inspector.h"
#include "inspector/inspector.h"
MapController::MapController(MainWindow * m): main(m)
@ -195,6 +195,7 @@ void MapController::commitObjectErase(int level)
_scenes[level]->selectionObjectsView.clear();
_scenes[level]->objectsView.draw();
_scenes[level]->selectionObjectsView.draw();
_scenes[level]->passabilityView.update();
_miniscenes[level]->updateViews();
main->mapChanged();
@ -318,7 +319,30 @@ void MapController::commitObjectCreate(int level)
auto * newObj = _scenes[level]->selectionObjectsView.newObject;
if(!newObj)
return;
Initializer init(map(), newObj);
//need this because of possible limits
auto rmgInfo = VLC->objtypeh->getHandlerFor(newObj->ID, newObj->subID)->getRMGInfo();
//find all objects of such type
int objCounter = 0;
for(auto o : _map->objects)
{
if(o->ID == newObj->ID && o->subID == newObj->subID)
{
++objCounter;
}
}
if((rmgInfo.mapLimit && objCounter >= rmgInfo.mapLimit)
|| (newObj->ID == Obj::GRAIL && objCounter >= 1)) //special case for grail
{
auto typeName = QString::fromStdString(newObj->typeName);
auto subTypeName = QString::fromStdString(newObj->subTypeName);
main->setStatusMessage(QString("Reached map limit for object %1 - %2").arg(typeName, subTypeName));
return; //maplimit reached
}
Initializer init(map(), newObj, defaultPlayer);
_map->getEditManager()->insertObject(newObj);
_mapHandler->invalidate(newObj);

View File

@ -45,6 +45,8 @@ public:
void undo();
void redo();
PlayerColor defaultPlayer;
private:
std::unique_ptr<CMap> _map;
std::unique_ptr<MapHandler> _mapHandler;

BIN
mapeditor/mapeditor.ico Normal file

Binary file not shown.

After

(image error) Size: 79 KiB

1
mapeditor/mapeditor.rc Normal file
View File

@ -0,0 +1 @@
IDI_ICON1 ICON "mapeditor.ico"

View File

@ -372,13 +372,8 @@ QRgb MapHandler::getTileColor(int x, int y, int z)
// if object at tile is owned - it will be colored as its owner
for(auto & object : getObjects(x, y, z))
{
//heroes will be blitted later
switch (object.obj->ID)
{
case Obj::HERO:
case Obj::PRISON:
continue;
}
if(!object.obj->getBlockedPos().count(int3(x, y, z)))
continue;
PlayerColor player = object.obj->getOwner();
if(player == PlayerColor::NEUTRAL)

View File

@ -11,8 +11,8 @@ MapSettings::MapSettings(MapController & ctrl, QWidget *parent) :
assert(controller.map());
ui->mapNameEdit->setText(QString::fromStdString(controller.map()->name));
ui->mapDescriptionEdit->setPlainText(QString::fromStdString(controller.map()->description));
ui->mapNameEdit->setText(tr(controller.map()->name.c_str()));
ui->mapDescriptionEdit->setPlainText(tr(controller.map()->description.c_str()));
show();

View File

@ -70,7 +70,7 @@ void MapView::mouseMoveEvent(QMouseEvent *mouseEvent)
this->update();
auto * sc = static_cast<MapScene*>(scene());
if(!sc)
if(!sc || !controller->map())
return;
auto pos = mapToScene(mouseEvent->pos()); //TODO: do we need to check size?
@ -176,7 +176,7 @@ void MapView::mousePressEvent(QMouseEvent *event)
this->update();
auto * sc = static_cast<MapScene*>(scene());
if(!sc)
if(!sc || !controller->map())
return;
mouseStart = mapToScene(event->pos());
@ -265,11 +265,18 @@ void MapView::mousePressEvent(QMouseEvent *event)
{
if(sc->selectionObjectsView.isSelected(obj))
{
sc->selectionObjectsView.selectionMode = 2;
if(qApp->keyboardModifiers() & Qt::ControlModifier)
{
sc->selectionObjectsView.deselectObject(obj);
sc->selectionObjectsView.selectionMode = 1;
}
else
sc->selectionObjectsView.selectionMode = 2;
}
else
{
sc->selectionObjectsView.clear();
if(!(qApp->keyboardModifiers() & Qt::ControlModifier))
sc->selectionObjectsView.clear();
sc->selectionObjectsView.selectionMode = 2;
sc->selectionObjectsView.selectObject(obj);
}
@ -294,7 +301,7 @@ void MapView::mouseReleaseEvent(QMouseEvent *event)
this->update();
auto * sc = static_cast<MapScene*>(scene());
if(!sc || !controller)
if(!sc || !controller->map())
return;
switch(selectionTool)

View File

@ -43,14 +43,23 @@ PlayerParams::PlayerParams(MapController & ctrl, int playerId, QWidget *parent)
//load towns
int foundMainTown = -1;
for(int i = 0; i < controller.map()->towns.size(); ++i)
for(int i = 0, townIndex = 0; i < controller.map()->objects.size(); ++i)
{
auto town = controller.map()->towns[i];
if(town && town->town && town->town->faction && town->getOwner().getNum() == playerColor)
if(auto town = dynamic_cast<CGTownInstance*>(controller.map()->objects[i].get()))
{
if(playerInfo.hasMainTown && playerInfo.posOfMainTown == town->pos)
foundMainTown = i;
ui->mainTown->addItem(QString::fromStdString(town->getObjectName()), QVariant::fromValue(i));
auto * ctown = town->town;
if(!ctown)
ctown = VLC->townh->randomTown;
if(ctown && town->getOwner().getNum() == playerColor)
{
if(playerInfo.hasMainTown && playerInfo.posOfMainTown == town->pos)
foundMainTown = townIndex;
auto name = town->name + ", (random)";
if(ctown->faction)
name = town->getObjectName();
ui->mainTown->addItem(tr(name.c_str()), QVariant::fromValue(i));
++townIndex;
}
}
}
@ -60,7 +69,9 @@ PlayerParams::PlayerParams(MapController & ctrl, int playerId, QWidget *parent)
}
else
{
ui->generateHero->setEnabled(false);
playerInfo.hasMainTown = false;
playerInfo.generateHeroAtMainTown = false;
playerInfo.posOfMainTown = int3(-1, -1, -1);
}
@ -112,12 +123,15 @@ void PlayerParams::on_mainTown_activated(int index)
{
if(index == 0) //default
{
ui->generateHero->setEnabled(false);
ui->generateHero->setChecked(false);
playerInfo.hasMainTown = false;
playerInfo.posOfMainTown = int3(-1, -1, -1);
}
else
{
auto town = controller.map()->towns.at(ui->mainTown->currentData().toInt());
ui->generateHero->setEnabled(true);
auto town = controller.map()->objects.at(ui->mainTown->currentData().toInt());
playerInfo.hasMainTown = true;
playerInfo.posOfMainTown = town->pos;
}

View File

@ -27,6 +27,8 @@ PlayerSettings::PlayerSettings(MapController & ctrl, QWidget *parent) :
ui->playersCount->setCurrentText("");
else
ui->playersCount->setCurrentIndex(players - 2);
setAttribute(Qt::WA_DeleteOnClose);
}
PlayerSettings::~PlayerSettings()

View File

@ -2,7 +2,7 @@
#include "scenelayer.h"
#include "mainwindow.h"
#include "../lib/mapping/CMapEditManager.h"
#include "inspector.h"
#include "inspector/inspector.h"
#include "mapview.h"
#include "mapcontroller.h"

View File

@ -10,6 +10,8 @@ Validator::Validator(const CMap * map, QWidget *parent) :
ui->setupUi(this);
show();
setAttribute(Qt::WA_DeleteOnClose);
std::array<QString, 2> icons{"mapeditor/icons/mod-update.png", "mapeditor/icons/mod-delete.png"};

View File

@ -24,6 +24,9 @@ WindowNewMap::WindowNewMap(QWidget *parent) :
loadUserSettings();
ui->widthTxt->setInputMask("d00");
ui->heightTxt->setInputMask("d00");
//setup initial parameters - can depend on loaded settings
mapGenOptions.setWidth(ui->widthTxt->text().toInt());
mapGenOptions.setHeight(ui->heightTxt->text().toInt());