1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-03-17 20:58:07 +02:00

Object picker implemented

This commit is contained in:
nordsoft 2023-09-11 18:01:53 +02:00
parent 082e1194ff
commit 19407954ed
8 changed files with 359 additions and 132 deletions

View File

@ -30,9 +30,9 @@ public:
virtual void initialize(const CMap & map) = 0;
virtual void update(CMap & map) = 0;
std::string getTownName(const CMap & map, int objectIdx);
std::string getHeroName(const CMap & map, int objectIdx);
std::string getMonsterName(const CMap & map, int objectIdx);
static std::string getTownName(const CMap & map, int objectIdx);
static std::string getHeroName(const CMap & map, int objectIdx);
static std::string getMonsterName(const CMap & map, int objectIdx);
static JsonNode conditionToJson(const EventCondition & event);

View File

@ -198,6 +198,9 @@ void MapView::mousePressEvent(QMouseEvent *event)
auto * sc = static_cast<MapScene*>(scene());
if(!sc || !controller->map())
return;
if(sc->objectPickerView.isVisible())
return;
mouseStart = mapToScene(event->pos());
tileStart = tilePrev = int3(mouseStart.x() / 32, mouseStart.y() / 32, sc->level);
@ -338,6 +341,22 @@ void MapView::mouseReleaseEvent(QMouseEvent *event)
if(rubberBand)
rubberBand->hide();
if(sc->objectPickerView.isVisible())
{
if(event->button() == Qt::RightButton)
sc->objectPickerView.discard();
if(event->button() == Qt::LeftButton)
{
mouseStart = mapToScene(event->pos());
tileStart = tilePrev = int3(mouseStart.x() / 32, mouseStart.y() / 32, sc->level);
if(auto * pickedObject = sc->selectionObjectsView.selectObjectAt(tileStart.x, tileStart.y))
sc->objectPickerView.select(pickedObject);
}
return;
}
switch(selectionTool)
{
@ -547,6 +566,7 @@ MapScene::MapScene(int lvl):
terrainView(this),
objectsView(this),
selectionObjectsView(this),
objectPickerView(this),
isTerrainSelected(false),
isObjectSelected(false)
{
@ -562,6 +582,7 @@ std::list<AbstractLayer *> MapScene::getAbstractLayers()
&objectsView,
&gridView,
&passabilityView,
&objectPickerView,
&selectionTerrainView,
&selectionObjectsView
};
@ -575,6 +596,7 @@ void MapScene::updateViews()
objectsView.show(true);
selectionTerrainView.show(true);
selectionObjectsView.show(true);
objectPickerView.show(true);
}
void MapScene::terrainSelected(bool anythingSelected)

View File

@ -66,6 +66,7 @@ public:
TerrainLayer terrainView;
ObjectsLayer objectsView;
SelectionObjectsLayer selectionObjectsView;
ObjectPickerLayer objectPickerView;
signals:
void selected(bool anything);

View File

@ -11,6 +11,7 @@
#include "StdInc.h"
#include "playerparams.h"
#include "ui_playerparams.h"
#include "mapsettings/abstractsettings.h"
#include "../lib/CTownHandler.h"
#include "../lib/constants/StringConstants.h"
@ -87,7 +88,8 @@ PlayerParams::PlayerParams(MapController & ctrl, int playerId, QWidget *parent)
{
if(playerInfo.hasMainTown && playerInfo.posOfMainTown == town->pos)
foundMainTown = townIndex;
const auto name = ctown->faction ? town->getObjectName() : town->getNameTranslated() + ", (random)";
const auto name = AbstractSettings::getTownName(*controller.map(), i);
ui->mainTown->addItem(tr(name.c_str()), QVariant::fromValue(i));
++townIndex;
}
@ -186,3 +188,49 @@ void PlayerParams::on_playerColorCombo_activated(int index)
}
}
void PlayerParams::on_townSelect_clicked()
{
auto pred = [this](const CGObjectInstance * obj) -> bool
{
if(auto town = dynamic_cast<const CGTownInstance*>(obj))
return town->getOwner().getNum() == playerColor;
return false;
};
std::vector<std::reference_wrapper<ObjectPickerLayer>> pickers;
pickers.emplace_back(controller.scene(0)->objectPickerView);
if(controller.map()->twoLevel)
pickers.emplace_back(controller.scene(1)->objectPickerView);
for(auto l : pickers)
{
l.get().highlight(pred);
l.get().update();
QObject::connect(&l.get(), &ObjectPickerLayer::selectionMade, this, &PlayerParams::onTownPicked);
}
dynamic_cast<QWidget*>(parent()->parent()->parent()->parent())->hide();
}
void PlayerParams::onTownPicked(const CGObjectInstance * obj)
{
dynamic_cast<QWidget*>(parent()->parent()->parent()->parent())->show();
std::vector<std::reference_wrapper<ObjectPickerLayer>> pickers;
pickers.emplace_back(controller.scene(0)->objectPickerView);
if(controller.map()->twoLevel)
pickers.emplace_back(controller.scene(1)->objectPickerView);
for(auto l : pickers)
{
l.get().clear();
l.get().update();
QObject::disconnect(&l.get(), &ObjectPickerLayer::selectionMade, this, &PlayerParams::onTownPicked);
}
if(!obj) //discarded
return;
}

View File

@ -28,6 +28,8 @@ public:
PlayerInfo playerInfo;
int playerColor;
void onTownPicked(const CGObjectInstance *);
private slots:
void on_radioHuman_toggled(bool checked);
@ -46,6 +48,8 @@ private slots:
void on_playerColorCombo_activated(int index);
void on_townSelect_clicked();
private:
Ui::PlayerParams *ui;

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>505</width>
<width>614</width>
<height>160</height>
</rect>
</property>
@ -25,7 +25,7 @@
<property name="windowTitle">
<string/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
@ -49,136 +49,180 @@
<property name="title">
<string/>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="4" column="0">
<widget class="QComboBox" name="teamId">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QRadioButton" name="radioCpu">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>CPU only</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioHuman">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Human/CPU</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Team</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="teamId">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="generateHero">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Generate hero at main</string>
</property>
</widget>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Color</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="playerColorCombo">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Main town</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<item>
<widget class="QComboBox" name="mainTown">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>(default)</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QToolButton" name="townSelect">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="generateHero">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Generate hero at main</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="2">
<widget class="QCheckBox" name="randomFaction">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Random faction</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Team</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QRadioButton" name="radioCpu">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>CPU only</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="radioHuman">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Human/CPU</string>
</property>
</widget>
</item>
<item row="0" column="2" rowspan="4">
<widget class="QListWidget" name="allowedFactions">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="mainTown">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="leftMargin">
<number>0</number>
</property>
<item>
<property name="text">
<string>(default)</string>
</property>
<widget class="QListWidget" name="allowedFactions">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
</widget>
</item>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Main town</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="playerColorCombo">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label">
<property name="text">
<string>Color</string>
</property>
</widget>
<item>
<widget class="QCheckBox" name="randomFaction">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Random faction</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>

View File

@ -112,6 +112,83 @@ void PassabilityLayer::update()
redraw();
}
ObjectPickerLayer::ObjectPickerLayer(MapSceneBase * s): AbstractLayer(s)
{
}
void ObjectPickerLayer::highlight(std::function<bool(const CGObjectInstance *)> predicate)
{
if(!map)
return;
for(int j = 0; j < map->height; ++j)
{
for(int i = 0; i < map->width; ++i)
{
auto tl = map->getTile(int3(i, j, scene->level));
auto * obj = tl.topVisitableObj();
if(!obj && !tl.blockingObjects.empty())
obj = tl.blockingObjects.front();
if(obj && predicate(obj))
possibleObjects.insert(obj);
}
}
isActive = true;
}
bool ObjectPickerLayer::isVisible() const
{
return isShown && isActive;
}
void ObjectPickerLayer::clear()
{
possibleObjects.clear();
isActive = false;
}
void ObjectPickerLayer::update()
{
if(!map)
return;
pixmap.reset(new QPixmap(map->width * 32, map->height * 32));
pixmap->fill(Qt::transparent);
if(isActive)
pixmap->fill(QColor(255, 255, 255, 128));
QPainter painter(pixmap.get());
painter.setCompositionMode(QPainter::CompositionMode_Source);
for(auto * obj : possibleObjects)
{
if(obj->pos.z != scene->level)
continue;
for(auto & pos : obj->getBlockedPos())
painter.fillRect(pos.x * 32, pos.y * 32, 32, 32, QColor(255, 211, 0, 64));
}
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
redraw();
}
void ObjectPickerLayer::select(const CGObjectInstance * obj)
{
if(obj && possibleObjects.count(obj))
{
clear();
emit selectionMade(obj);
}
}
void ObjectPickerLayer::discard()
{
clear();
emit selectionMade(nullptr);
}
SelectionTerrainLayer::SelectionTerrainLayer(MapSceneBase * s): AbstractLayer(s)
{
}

View File

@ -116,7 +116,7 @@ public:
void update() override;
void draw(bool onlyDirty = true); //TODO: implement dirty
void draw(bool onlyDirty = true);
void setDirty(int x, int y);
void setDirty(const CGObjectInstance * object);
@ -127,6 +127,37 @@ private:
};
class ObjectPickerLayer: public AbstractLayer
{
Q_OBJECT
public:
ObjectPickerLayer(MapSceneBase * s);
void update() override;
bool isVisible() const;
template<class T>
void highlight()
{
highlight([](const CGObjectInstance * o){ return dynamic_cast<T*>(o); });
}
void highlight(std::function<bool(const CGObjectInstance *)> predicate);
void clear();
void select(const CGObjectInstance *);
void discard();
signals:
void selectionMade(const CGObjectInstance *);
private:
bool isActive = false;
std::set<const CGObjectInstance *> possibleObjects;
};
class SelectionObjectsLayer: public AbstractLayer
{
Q_OBJECT