implement ui
This commit is contained in:
287
src/ui/SelectedBuildingPanel.cpp
Normal file
287
src/ui/SelectedBuildingPanel.cpp
Normal file
@@ -0,0 +1,287 @@
|
||||
#include "SelectedBuildingPanel.h"
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "Building.h"
|
||||
#include "BuildingType.h"
|
||||
#include "Simulation.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
QString buildingTypeName(BuildingType type)
|
||||
{
|
||||
const std::string id = buildingTypeId(type);
|
||||
QString result;
|
||||
bool nextUpper = true;
|
||||
for (char c : id)
|
||||
{
|
||||
if (c == '_')
|
||||
{
|
||||
result += ' ';
|
||||
nextUpper = true;
|
||||
}
|
||||
else if (nextUpper)
|
||||
{
|
||||
result += static_cast<char>(std::toupper(static_cast<unsigned char>(c)));
|
||||
nextUpper = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
result += c;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool isProductionBuilding(BuildingType type)
|
||||
{
|
||||
return type == BuildingType::Miner
|
||||
|| type == BuildingType::Smelter
|
||||
|| type == BuildingType::Assembler
|
||||
|| type == BuildingType::ReprocessingPlant
|
||||
|| type == BuildingType::Shipyard;
|
||||
}
|
||||
|
||||
bool isBeltLike(BuildingType type)
|
||||
{
|
||||
return type == BuildingType::Belt || type == BuildingType::Splitter;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
SelectedBuildingPanel::SelectedBuildingPanel(Simulation* sim,
|
||||
const GameConfig* config,
|
||||
QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_sim(sim)
|
||||
, m_config(config)
|
||||
, m_singleId(kInvalidEntityId)
|
||||
{
|
||||
m_layout = new QVBoxLayout(this);
|
||||
m_layout->setContentsMargins(8, 8, 8, 8);
|
||||
m_layout->setSpacing(4);
|
||||
m_layout->setAlignment(Qt::AlignTop);
|
||||
|
||||
m_titleLabel = new QLabel(this);
|
||||
m_recipeCombo = new QComboBox(this);
|
||||
m_clearBeltBtn = new QPushButton("Clear Items", this);
|
||||
m_buffersLabel = new QLabel(this);
|
||||
m_buffersLabel->setWordWrap(true);
|
||||
|
||||
m_layout->addWidget(m_titleLabel);
|
||||
m_layout->addWidget(m_recipeCombo);
|
||||
m_layout->addWidget(m_clearBeltBtn);
|
||||
m_layout->addWidget(m_buffersLabel);
|
||||
|
||||
connect(m_recipeCombo, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(onRecipeChanged(int)));
|
||||
connect(m_clearBeltBtn, SIGNAL(clicked()),
|
||||
this, SLOT(onClearBelt()));
|
||||
|
||||
buildEmpty();
|
||||
}
|
||||
|
||||
void SelectedBuildingPanel::onSelectionChanged(const std::vector<EntityId>& ids)
|
||||
{
|
||||
m_selection = ids;
|
||||
rebuild();
|
||||
}
|
||||
|
||||
void SelectedBuildingPanel::rebuild()
|
||||
{
|
||||
if (m_selection.empty())
|
||||
{
|
||||
buildEmpty();
|
||||
}
|
||||
else if (m_selection.size() == 1)
|
||||
{
|
||||
buildSingle(m_selection[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
buildMulti(m_selection);
|
||||
}
|
||||
}
|
||||
|
||||
void SelectedBuildingPanel::buildEmpty()
|
||||
{
|
||||
m_singleId = kInvalidEntityId;
|
||||
m_titleLabel->hide();
|
||||
m_recipeCombo->hide();
|
||||
m_clearBeltBtn->hide();
|
||||
m_buffersLabel->hide();
|
||||
}
|
||||
|
||||
void SelectedBuildingPanel::buildSingle(EntityId id)
|
||||
{
|
||||
m_singleId = id;
|
||||
|
||||
const Building* b = m_sim->buildings().findBuilding(id);
|
||||
if (!b)
|
||||
{
|
||||
buildEmpty();
|
||||
return;
|
||||
}
|
||||
|
||||
m_titleLabel->setText(buildingTypeName(b->type));
|
||||
m_titleLabel->show();
|
||||
m_buffersLabel->show();
|
||||
|
||||
if (isProductionBuilding(b->type))
|
||||
{
|
||||
m_recipeCombo->blockSignals(true);
|
||||
m_recipeCombo->clear();
|
||||
|
||||
m_recipeCombo->addItem("(none)", QString());
|
||||
|
||||
if (b->type == BuildingType::Shipyard)
|
||||
{
|
||||
for (const ShipDef& def : m_config->ships.ships)
|
||||
{
|
||||
if (m_sim->isBlueprintUnlocked(def.id))
|
||||
{
|
||||
m_recipeCombo->addItem(
|
||||
QString::fromStdString(def.id),
|
||||
QString::fromStdString(def.id));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const RecipeDef& recipe : m_config->recipes.recipes)
|
||||
{
|
||||
if (recipe.building == b->type)
|
||||
{
|
||||
m_recipeCombo->addItem(
|
||||
QString::fromStdString(recipe.id),
|
||||
QString::fromStdString(recipe.id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const int currentIdx = m_recipeCombo->findData(QString::fromStdString(b->recipeId));
|
||||
m_recipeCombo->setCurrentIndex(currentIdx >= 0 ? currentIdx : 0);
|
||||
m_recipeCombo->blockSignals(false);
|
||||
m_recipeCombo->show();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_recipeCombo->hide();
|
||||
}
|
||||
|
||||
if (isBeltLike(b->type))
|
||||
{
|
||||
m_clearBeltBtn->show();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_clearBeltBtn->hide();
|
||||
}
|
||||
|
||||
QString bufText;
|
||||
if (!b->inputBuffer.counts.empty())
|
||||
{
|
||||
bufText += "Input: ";
|
||||
for (const std::pair<const ItemType, int>& entry : b->inputBuffer.counts)
|
||||
{
|
||||
const std::map<ItemType, int>::const_iterator cap =
|
||||
b->inputBuffer.caps.find(entry.first);
|
||||
const int capVal = (cap != b->inputBuffer.caps.end()) ? cap->second : 0;
|
||||
bufText += QString::fromStdString(entry.first.id)
|
||||
+ ": " + QString::number(entry.second)
|
||||
+ "/" + QString::number(capVal) + " ";
|
||||
}
|
||||
bufText += "\n";
|
||||
}
|
||||
if (!b->outputBuffer.items.empty())
|
||||
{
|
||||
std::map<std::string, int> outCounts;
|
||||
for (const Item& item : b->outputBuffer.items)
|
||||
{
|
||||
outCounts[item.type.id]++;
|
||||
}
|
||||
bufText += "Output(" + QString::number(static_cast<int>(b->outputBuffer.items.size()))
|
||||
+ "/" + QString::number(b->outputBuffer.capacity) + "): ";
|
||||
for (const std::pair<const std::string, int>& entry : outCounts)
|
||||
{
|
||||
bufText += QString::fromStdString(entry.first)
|
||||
+ ":" + QString::number(entry.second) + " ";
|
||||
}
|
||||
}
|
||||
m_buffersLabel->setText(bufText);
|
||||
}
|
||||
|
||||
void SelectedBuildingPanel::buildMulti(const std::vector<EntityId>& ids)
|
||||
{
|
||||
m_singleId = kInvalidEntityId;
|
||||
m_recipeCombo->hide();
|
||||
m_clearBeltBtn->hide();
|
||||
m_buffersLabel->hide();
|
||||
|
||||
std::map<BuildingType, int> counts;
|
||||
for (EntityId id : ids)
|
||||
{
|
||||
const Building* b = m_sim->buildings().findBuilding(id);
|
||||
if (b)
|
||||
{
|
||||
counts[b->type]++;
|
||||
}
|
||||
}
|
||||
|
||||
bool hasBelt = false;
|
||||
QString text;
|
||||
for (const std::pair<const BuildingType, int>& entry : counts)
|
||||
{
|
||||
text += buildingTypeName(entry.first) + ": "
|
||||
+ QString::number(entry.second) + "\n";
|
||||
if (isBeltLike(entry.first))
|
||||
{
|
||||
hasBelt = true;
|
||||
}
|
||||
}
|
||||
m_titleLabel->setText(text.trimmed());
|
||||
m_titleLabel->show();
|
||||
|
||||
if (hasBelt)
|
||||
{
|
||||
m_clearBeltBtn->show();
|
||||
}
|
||||
}
|
||||
|
||||
void SelectedBuildingPanel::onRecipeChanged(int comboIndex)
|
||||
{
|
||||
if (m_singleId == kInvalidEntityId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
const QString recipeId = m_recipeCombo->itemData(comboIndex).toString();
|
||||
m_sim->buildings().setRecipe(m_singleId, recipeId.toStdString());
|
||||
}
|
||||
|
||||
void SelectedBuildingPanel::onClearBelt()
|
||||
{
|
||||
std::vector<QPoint> tiles;
|
||||
for (EntityId id : m_selection)
|
||||
{
|
||||
const Building* b = m_sim->buildings().findBuilding(id);
|
||||
if (b && isBeltLike(b->type))
|
||||
{
|
||||
for (const QPoint& cell : b->bodyCells)
|
||||
{
|
||||
tiles.push_back(cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!tiles.empty())
|
||||
{
|
||||
m_sim->belts().clearTiles(tiles);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user