diff --git a/README.md b/README.md
index 94010f1..ee9d0f4 100644
--- a/README.md
+++ b/README.md
@@ -94,7 +94,11 @@ class selection to 8 classes as NWN:EE allows.
Feat selection with handy fuzzy searching.
-![stats](screenshots/creature-view-feats.png)
+![feats](screenshots/creature-view-feats.png)
+
+### Creature View - Inventory
+
+![inventory](screenshots/creature-inventory-view-2024-11-04.png)
### Dialog View
diff --git a/screenshots/creature-inventory-view-2024-11-04.png b/screenshots/creature-inventory-view-2024-11-04.png
new file mode 100644
index 0000000..6405ff5
Binary files /dev/null and b/screenshots/creature-inventory-view-2024-11-04.png differ
diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt
index 32bb772..2e04e91 100644
--- a/src/widgets/CMakeLists.txt
+++ b/src/widgets/CMakeLists.txt
@@ -31,6 +31,8 @@ add_library(arclight-widgets STATIC
TlkSelector/tlkselector.ui
util/restypeicons.cpp
+ util/items.cpp
+
checkboxdelegate.h
checkboxdelegate.cpp
arealistview.h
diff --git a/src/widgets/CreatureView/CMakeLists.txt b/src/widgets/CreatureView/CMakeLists.txt
index dc81081..46e8d31 100644
--- a/src/widgets/CreatureView/CMakeLists.txt
+++ b/src/widgets/CreatureView/CMakeLists.txt
@@ -2,26 +2,32 @@ find_package(Qt6 REQUIRED COMPONENTS Widgets)
find_package(Qt6 REQUIRED COMPONENTS OpenGL OpenGLWidgets)
add_library(CreatureView STATIC
+ creatureappearanceview.cpp
+ creatureappearanceview.h
+ creatureappearanceview.ui
+ creatureequipview.cpp
+ creatureequipview.h
+ creatureequipview.ui
creaturefeatselector.cpp
creaturefeatselector.h
creaturefeatselector.ui
- creaturefeatselectormodel.h
creaturefeatselectormodel.cpp
creaturefeatselectormodel.h
+ creaturefeatselectormodel.h
+ creatureinventorypanel.cpp
+ creatureinventorypanel.h
+ creatureinventorypanel.ui
+ creatureinventoryview.cpp
+ creatureinventoryview.h
+ creatureinventoryview.ui
+ creaturestatsview.cpp
+ creaturestatsview.h
+ creaturestatsview.ui
creatureview.cpp
creatureview.h
creatureview.ui
- creaturestatsview.h
- creaturestatsview.cpp
- creaturestatsview.ui
- creatureappearanceview.h
- creatureappearanceview.cpp
- creatureappearanceview.ui
- creatureequipview.h
- creatureequipview.cpp
- creatureequipview.ui
- inventoryslot.h
inventoryslot.cpp
+ inventoryslot.h
resources.qrc
)
@@ -49,6 +55,6 @@ target_link_libraries(CreatureView PRIVATE
Qt6::OpenGL
Qt6::OpenGLWidgets
nw
- renderer
+ renderer
VariableTableView
)
diff --git a/src/widgets/CreatureView/CreatureInventoryView.ui b/src/widgets/CreatureView/CreatureInventoryView.ui
new file mode 100644
index 0000000..99353cd
--- /dev/null
+++ b/src/widgets/CreatureView/CreatureInventoryView.ui
@@ -0,0 +1,19 @@
+
+
+ Form
+
+
+
+ 0
+ 0
+ 400
+ 300
+
+
+
+ Form
+
+
+
+
+
diff --git a/src/widgets/CreatureView/creatureequipview.ui b/src/widgets/CreatureView/creatureequipview.ui
index 1245dd7..1d04d6d 100644
--- a/src/widgets/CreatureView/creatureequipview.ui
+++ b/src/widgets/CreatureView/creatureequipview.ui
@@ -6,8 +6,8 @@
0
0
- 733
- 370
+ 705
+ 316
@@ -21,26 +21,114 @@
-
-
+
+
+
+ 0
+ 0
+
+
Equipment
-
+
+
-
+
+
+
+ 0
+
+
+ 0
+
+
+ 5
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 64
+ 240
+
+
+
+
+ 64
+ 240
+
+
+
+
+
+
+
+
+
+ :/resources/images/inv_slot_right.png
+
+
+ false
+
+
+ Qt::AlignmentFlag::AlignCenter
+
+
+
+
+
+
-
-
+
-
+
0
0
-
- Standard
-
-
+
+
+ 5
+
+
+ 0
+
+
+ 5
+
+
+ 0
+
-
-
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
0
@@ -48,13 +136,13 @@
0
- 5
+ 0
0
-
-
+
0
@@ -64,23 +152,20 @@
64
- 240
+ 120
64
- 240
+ 122
-
-
-
- :/resources/images/inv_slot_right.png
+ :/resources/images/inv_slot_armor.png
false
@@ -94,105 +179,300 @@
-
-
+
0
0
-
+
- 5
+ 0
0
- 5
+ 0
0
-
-
-
-
- 0
- 0
-
+
+
+
+ 32
+ 64
+
+
+
+
+ 32
+ 64
+
+
+
+
+
+
+ :/resources/images/inv_slot_arrow.png
+
+ false
+
+
+
+ -
+
- 0
- 0
+ 32
+ 32
- 16777215
- 16777215
+ 32
+ 32
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
-
- 0
- 0
-
-
-
-
- 64
- 120
-
-
-
-
- 64
- 122
-
-
-
-
-
-
- :/resources/images/inv_slot_armor.png
-
-
- false
-
-
- Qt::AlignmentFlag::AlignCenter
-
-
-
-
+
+
+
+
+ :/resources/images/inv_slot_sling.png
+
+
+ false
+
+
+ Qt::AlignmentFlag::AlignCenter
+
+
+
+ -
+
+
+
+ 32
+ 64
+
+
+
+
+ 32
+ 64
+
+
+
+
+
+
+ :/resources/images/inv_slot_bolts.png
+
+
+ false
+
+
+ Qt::AlignmentFlag::AlignCenter
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 5
+
+
+ 0
+
+
+ 5
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 64
+ 128
+
+
+
+
+ 64
+ 128
+
+
+
+
+
+
+ :/resources/images/inv_slot_left.png
+
+
+ false
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 64
+ 32
+
+
+
+
+ 64
+ 32
+
+
+
+
+
+
+ :/resources/images/inv_slot_belt.png
+
+
+ false
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 5
+
+
+ 0
+
+
+ 5
+
+
+ 0
+
+
-
+
+
+
+ 64
+ 64
+
+
+
+
+ 64
+ 64
+
+
+
+
+
+
+ :/resources/images/inv_slot_helm.png
+
+
+ false
+
+
+
+ -
+
+
+
+ 64
+ 32
+
+
+
+
+ 64
+ 32
+
+
+
+
+
+
+ :/resources/images/inv_slot_gloves.png
+
+
+ false
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
-
-
+
0
0
-
+
0
@@ -206,32 +486,13 @@
0
-
-
-
-
- 32
- 64
-
-
-
-
- 32
- 64
-
-
-
-
-
-
- :/resources/images/inv_slot_arrow.png
-
-
- false
+
+
+
+ 64
+ 64
+
-
-
- -
-
32
@@ -248,73 +509,49 @@
- :/resources/images/inv_slot_sling.png
+ :/resources/images/inv_slot_ring.png
false
-
- Qt::AlignmentFlag::AlignCenter
-
-
-
+
+
+
+ 64
+ 64
+
+
32
- 64
+ 32
32
- 64
+ 32
- :/resources/images/inv_slot_bolts.png
+ :/resources/images/inv_slot_ring.png
false
-
- Qt::AlignmentFlag::AlignCenter
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 5
-
-
- 0
-
-
- 5
-
-
- 0
-
-
-
+
0
@@ -323,52 +560,21 @@
- 64
- 128
-
-
-
-
- 64
- 128
-
-
-
-
-
-
- :/resources/images/inv_slot_left.png
-
-
- false
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 64
- 32
+ 32
+ 64
- 64
- 32
+ 32
+ 64
- :/resources/images/inv_slot_belt.png
+ :/resources/images/inv_slot_amulet.png
false
@@ -378,29 +584,136 @@
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 5
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
-
-
+
0
0
-
-
- 5
-
-
- 0
-
-
- 5
-
-
- 0
-
+
+
+ 64
+ 120
+
+
+
+
+ 64
+ 120
+
+
+
+
+
+
+ false
+
+
+ Qt::AlignmentFlag::AlignCenter
+
+
+
+ -
+
+
+
+ 32
+ 32
+
+
+
+
+ 64
+ 64
+
+
+
+
+ 64
+ 64
+
+
+
+
+
+
+ :/resources/images/inv_slot_boots.png
+
+
+ false
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Creature Items
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
-
-
+
+
+
+ 0
+ 0
+
+
64
@@ -417,205 +730,52 @@
- :/resources/images/inv_slot_helm.png
-
-
- false
+ :/resources/images/inv_slot_cre_1.png
-
-
+
+
+
+ 0
+ 0
+
+
64
- 32
+ 64
64
- 32
+ 64
- :/resources/images/inv_slot_gloves.png
-
-
- false
+ :/resources/images/inv_slot_cre_2.png
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
-
- 0
- 0
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
-
- 64
- 64
-
-
-
-
- 32
- 32
-
-
-
-
- 32
- 32
-
-
-
-
-
-
- :/resources/images/inv_slot_ring.png
-
-
- false
-
-
-
- -
-
-
-
- 64
- 64
-
-
-
-
- 32
- 32
-
-
-
-
- 32
- 32
-
-
-
-
-
-
- :/resources/images/inv_slot_ring.png
-
-
- false
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 32
- 64
-
-
-
-
- 32
- 64
-
-
-
-
-
-
- :/resources/images/inv_slot_amulet.png
-
-
- false
-
-
-
-
-
-
-
-
+
0
0
-
-
- 5
-
-
- 0
-
-
- 0
-
-
- 0
-
+
-
-
+
0
@@ -625,32 +785,29 @@
64
- 120
+ 64
64
- 120
+ 64
-
- false
-
-
- Qt::AlignmentFlag::AlignCenter
+
+ :/resources/images/inv_slot_cre_3.png
-
-
+
- 32
- 32
+ 0
+ 0
@@ -669,174 +826,8 @@
- :/resources/images/inv_slot_boots.png
-
-
- false
-
-
-
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Creature
-
-
-
-
-
-
-
- 0
- 0
-
-
-
-
-
-
-
-
- 0
- 0
-
-
-
-
-
-
-
-
- 0
- 0
-
-
-
-
- 64
- 64
-
-
-
-
- 64
- 64
-
-
-
-
-
-
- :/resources/images/inv_slot_cre_1.png
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 64
- 64
-
-
-
-
- 64
- 64
-
-
-
-
-
-
- :/resources/images/inv_slot_cre_2.png
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
+ :/resources/images/inv_slot_cre_skin.png
-
-
-
-
-
-
- 0
- 0
-
-
-
-
- 64
- 64
-
-
-
-
- 64
- 64
-
-
-
-
-
-
- :/resources/images/inv_slot_cre_3.png
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 64
- 64
-
-
-
-
- 64
- 64
-
-
-
-
-
-
- :/resources/images/inv_slot_cre_skin.png
-
-
-
-
diff --git a/src/widgets/CreatureView/creatureinventorypanel.cpp b/src/widgets/CreatureView/creatureinventorypanel.cpp
new file mode 100644
index 0000000..8adf711
--- /dev/null
+++ b/src/widgets/CreatureView/creatureinventorypanel.cpp
@@ -0,0 +1,20 @@
+#include "creatureinventorypanel.h"
+#include "ui_creatureinventorypanel.h"
+
+CreatureInventoryPanel::CreatureInventoryPanel(QWidget* parent)
+ : QWidget(parent)
+ , ui(new Ui::CreatureInventoryPanel)
+{
+ ui->setupUi(this);
+}
+
+CreatureInventoryPanel::~CreatureInventoryPanel()
+{
+ delete ui;
+}
+
+void CreatureInventoryPanel::setCreature(nw::Creature* creature)
+{
+ ui->equips->setCreature(creature);
+ ui->inventory->setCreature(creature);
+}
diff --git a/src/widgets/CreatureView/creatureinventorypanel.h b/src/widgets/CreatureView/creatureinventorypanel.h
new file mode 100644
index 0000000..06e90f5
--- /dev/null
+++ b/src/widgets/CreatureView/creatureinventorypanel.h
@@ -0,0 +1,27 @@
+#ifndef CREATUREINVENTORYPANEL_H
+#define CREATUREINVENTORYPANEL_H
+
+#include
+
+namespace nw {
+struct Creature;
+}
+
+namespace Ui {
+class CreatureInventoryPanel;
+}
+
+class CreatureInventoryPanel : public QWidget {
+ Q_OBJECT
+
+public:
+ explicit CreatureInventoryPanel(QWidget* parent = nullptr);
+ ~CreatureInventoryPanel();
+
+ void setCreature(nw::Creature* creature);
+
+private:
+ Ui::CreatureInventoryPanel* ui;
+};
+
+#endif // CREATUREINVENTORYPANEL_H
diff --git a/src/widgets/CreatureView/creatureinventorypanel.ui b/src/widgets/CreatureView/creatureinventorypanel.ui
new file mode 100644
index 0000000..1a3dfc4
--- /dev/null
+++ b/src/widgets/CreatureView/creatureinventorypanel.ui
@@ -0,0 +1,97 @@
+
+
+ CreatureInventoryPanel
+
+
+
+ 0
+ 0
+ 918
+ 722
+
+
+
+ Form
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Qt::Orientation::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ -
+
+
+ Qt::Orientation::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+ CreatureEquipView
+ QWidget
+
+ 1
+
+
+ CreatureInventoryView
+ QWidget
+
+ 1
+
+
+
+
+
diff --git a/src/widgets/CreatureView/creatureinventoryview.cpp b/src/widgets/CreatureView/creatureinventoryview.cpp
new file mode 100644
index 0000000..2ef397f
--- /dev/null
+++ b/src/widgets/CreatureView/creatureinventoryview.cpp
@@ -0,0 +1,170 @@
+#include "creatureinventoryview.h"
+#include "ui_creatureinventoryview.h"
+
+#include "../util/items.h"
+
+#include "ZFontIcon/ZFontIcon.h"
+#include "ZFontIcon/ZFont_fa6.h"
+
+#include
+#include
+
+// == InventoryItemDelegate ===================================================
+// ============================================================================
+
+InventoryItemDelegate::InventoryItemDelegate(QObject* parent)
+ : QStyledItemDelegate(parent)
+{
+}
+
+void InventoryItemDelegate::initStyleOption(QStyleOptionViewItem* option, const QModelIndex& index) const
+{
+ QStyledItemDelegate::initStyleOption(option, index);
+ option->displayAlignment = Qt::AlignCenter;
+}
+
+void InventoryItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
+{
+ if (index.column() == 0) {
+ QPixmap pixmap = index.data(Qt::DecorationRole).value();
+ if (!pixmap.isNull()) {
+ if (pixmap.height() > 128) {
+ pixmap = pixmap.scaled(QSize(64, 128), Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ }
+ int x = option.rect.x() + (option.rect.width() - pixmap.width()) / 2;
+ int y = option.rect.y() + (option.rect.height() - pixmap.height()) / 2;
+ painter->drawPixmap(x, y, pixmap);
+ return;
+ }
+ }
+
+ QStyledItemDelegate::paint(painter, option, index);
+}
+
+QSize InventoryItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
+{
+ if (index.column() == 0) {
+ QPixmap pixmap = index.data(Qt::DecorationRole).value();
+ int height = qMin(pixmap.height(), 128);
+
+ QFontMetrics fontMetrics(option.font);
+ int text = fontMetrics.height();
+
+ int row = qMax(height, text) + 8;
+ return QSize(option.rect.width(), row);
+ }
+ return QStyledItemDelegate::sizeHint(option, index);
+}
+
+// == InventoryModel ==========================================================
+// ============================================================================
+
+InventoryModel::InventoryModel(nw::Creature* creature, QObject* parent)
+ : QAbstractTableModel(parent)
+ , creature_{creature}
+{
+}
+
+QVariant InventoryModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
+ switch (section) {
+ case 0:
+ return "Icon";
+ case 1:
+ return "Name";
+ case 2:
+ return "Stack Size";
+ default:
+ return QVariant();
+ }
+ }
+ return QAbstractTableModel::headerData(section, orientation, role);
+}
+
+int InventoryModel::rowCount(const QModelIndex& parent) const
+{
+ Q_UNUSED(parent);
+ return creature_ ? static_cast(creature_->inventory.items.size()) : 0;
+}
+
+int InventoryModel::columnCount(const QModelIndex& parent) const
+{
+ Q_UNUSED(parent);
+ return 3;
+}
+
+QVariant InventoryModel::data(const QModelIndex& index, int role) const
+{
+ if (!creature_) { return QVariant(); }
+ if (!index.isValid() || index.row() >= static_cast(creature_->inventory.items.size())) {
+ return QVariant();
+ }
+
+ const auto item = creature_->inventory.items[index.row()].item.as();
+
+ switch (index.column()) {
+ case 0:
+ if (role == Qt::DecorationRole) {
+ return item_to_image(item, creature_->gender == 1);
+ }
+ break;
+ case 1:
+ if (role == Qt::DisplayRole) {
+ return QString::fromStdString(nw::kernel::strings().get(item->common.name));
+ }
+ break;
+ case 2:
+ if (role == Qt::DisplayRole) {
+ return item->stacksize;
+ }
+ break;
+ }
+ return QVariant();
+}
+
+Qt::ItemFlags InventoryModel::flags(const QModelIndex& index) const
+{
+ Qt::ItemFlags flags = QAbstractTableModel::flags(index);
+ return flags;
+}
+
+void InventoryModel::addItem(nw::Item* item)
+{
+ // beginInsertRows(QModelIndex(), items.size(), items.size());
+ // items.append({image, name, stackSize, stackable});
+ // endInsertRows();
+}
+
+// == CreatureInventoryView ===================================================
+// ============================================================================
+
+CreatureInventoryView::CreatureInventoryView(QWidget* parent)
+ : QWidget(parent)
+ , ui(new Ui::CreatureInventoryView)
+{
+ ui->setupUi(this);
+ ui->add->setIcon(ZFontIcon::icon(Fa6::FAMILY, Fa6::fa_plus, Qt::green));
+ ui->remove->setIcon(ZFontIcon::icon(Fa6::FAMILY, Fa6::fa_minus, Qt::red));
+}
+
+CreatureInventoryView::~CreatureInventoryView()
+{
+ delete ui;
+}
+
+void CreatureInventoryView::setCreature(nw::Creature* creature)
+{
+ creature_ = creature;
+ model_ = new InventoryModel(creature_, this);
+ ui->inventoryView->setModel(model_);
+ ui->inventoryView->setItemDelegate(new InventoryItemDelegate(this));
+ ui->inventoryView->setColumnWidth(0, 64);
+ ui->inventoryView->setColumnWidth(2, 80);
+
+ ui->inventoryView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
+ ui->inventoryView->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);
+ ui->inventoryView->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Fixed);
+ ui->inventoryView->resizeRowsToContents();
+ ui->inventoryView->setSelectionBehavior(QAbstractItemView::SelectRows);
+}
diff --git a/src/widgets/CreatureView/creatureinventoryview.h b/src/widgets/CreatureView/creatureinventoryview.h
new file mode 100644
index 0000000..476757e
--- /dev/null
+++ b/src/widgets/CreatureView/creatureinventoryview.h
@@ -0,0 +1,70 @@
+#ifndef CREATUREINVENTORYVIEW_H
+#define CREATUREINVENTORYVIEW_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace nw {
+struct Creature;
+struct Item;
+}
+
+// == InventoryItemDelegate ===================================================
+// ============================================================================
+
+constexpr int StackableRole = Qt::UserRole + 1;
+
+class InventoryItemDelegate : public QStyledItemDelegate {
+public:
+ InventoryItemDelegate(QObject* parent = nullptr);
+
+ void initStyleOption(QStyleOptionViewItem* option, const QModelIndex& index) const override;
+ void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
+ QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
+};
+
+// == InventoryModel ==========================================================
+// ============================================================================
+
+class InventoryModel : public QAbstractTableModel {
+ Q_OBJECT
+
+public:
+ InventoryModel(nw::Creature* creature, QObject* parent = nullptr);
+
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
+ int rowCount(const QModelIndex& parent = QModelIndex()) const override;
+ int columnCount(const QModelIndex& parent = QModelIndex()) const override;
+ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
+ Qt::ItemFlags flags(const QModelIndex& index) const override;
+
+ void addItem(nw::Item* item);
+
+private:
+ nw::Creature* creature_;
+};
+
+namespace Ui {
+class CreatureInventoryView;
+}
+
+class CreatureInventoryView : public QWidget {
+ Q_OBJECT
+
+public:
+ explicit CreatureInventoryView(QWidget* parent = nullptr);
+ ~CreatureInventoryView();
+
+ void setCreature(nw::Creature* creature);
+
+private:
+ Ui::CreatureInventoryView* ui;
+ nw::Creature* creature_ = nullptr;
+ InventoryModel* model_ = nullptr;
+};
+
+#endif // CREATUREINVENTORYVIEW_H
diff --git a/src/widgets/CreatureView/creatureinventoryview.ui b/src/widgets/CreatureView/creatureinventoryview.ui
new file mode 100644
index 0000000..7920859
--- /dev/null
+++ b/src/widgets/CreatureView/creatureinventoryview.ui
@@ -0,0 +1,85 @@
+
+
+ CreatureInventoryView
+
+
+
+ 0
+ 0
+ 1038
+ 626
+
+
+
+ Form
+
+
+ -
+
+
+ Inventory
+
+
+
-
+
+
+
+
+
+ -
+
+
+
-
+
+
+ Qt::Orientation::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Add Item
+
+
+
+
+
+
+ -
+
+
+ Remove Item
+
+
+
+
+
+
+ -
+
+
+ Qt::Orientation::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/widgets/CreatureView/creatureview.cpp b/src/widgets/CreatureView/creatureview.cpp
index 2aaddd1..5b5dc06 100644
--- a/src/widgets/CreatureView/creatureview.cpp
+++ b/src/widgets/CreatureView/creatureview.cpp
@@ -1,4 +1,5 @@
#include "creatureview.h"
+#include "creatureinventorypanel.h"
#include "ui_creatureview.h"
#include "VariableTableView/vartabledialog.h"
@@ -36,9 +37,10 @@ CreatureView::CreatureView(nw::Creature* creature, QWidget* parent)
auto appearance = new CreatureAppearanceView(creature, this);
ui->tabWidget->addTab(appearance, "Appearance");
connect(appearance, &CreatureAppearanceView::dataChanged, this, &CreatureView::onDataChanged);
- auto equips = new CreatureEquipView(this);
- equips->setCreature(creature);
- ui->tabWidget->addTab(equips, "Inventory");
+
+ auto inv = new CreatureInventoryPanel(this);
+ inv->setCreature(creature);
+ ui->tabWidget->addTab(inv, "Inventory");
ui->portraitEdit->setIcon(ZFontIcon::icon(Fa6::FAMILY, Fa6::fa_ellipsis));
diff --git a/src/widgets/CreatureView/inventoryslot.cpp b/src/widgets/CreatureView/inventoryslot.cpp
index 9f338d8..2cbdd67 100644
--- a/src/widgets/CreatureView/inventoryslot.cpp
+++ b/src/widgets/CreatureView/inventoryslot.cpp
@@ -1,89 +1,12 @@
#include "inventoryslot.h"
-#include "nw/formats/Image.hpp"
+#include "../util/items.h"
+
#include "nw/kernel/Strings.hpp"
-#include "nw/kernel/TwoDACache.hpp"
#include "nw/objects/Item.hpp"
#include
-QImage item_to_image(const nw::Item* item, bool female)
-{
- auto* bi2da = nw::kernel::twodas().get("baseitems");
- auto int_type = bi2da->get(*item->baseitem, "ModelType");
- nw::ItemModelType type;
-
- if (int_type) {
- type = static_cast(*int_type);
- } else {
- return QImage();
- }
-
- if (type == nw::ItemModelType::simple || type == nw::ItemModelType::layered) {
- auto icon = item->get_icon_by_part();
- if (!icon.valid()) { return QImage{}; }
- QImage image(icon.release(), icon.width(), icon.height(), icon.channels() == 4 ? QImage::Format_RGBA8888 : QImage::Format_RGB888,
- [](void* bytes) { if (bytes) { free(bytes); } });
- return image.mirrored();
- } else if (type == nw::ItemModelType::composite) {
- auto img1 = item->get_icon_by_part(nw::ItemModelParts::model1);
- if (!img1.valid()) { return QImage{}; }
- QImage bottom(img1.release(), img1.width(), img1.height(), img1.channels() == 4 ? QImage::Format_RGBA8888 : QImage::Format_RGB888,
- [](void* bytes) { if (bytes) { free(bytes); } });
- if (!img1.is_bio_dds()) { bottom.mirror(); }
-
- auto img2 = item->get_icon_by_part(nw::ItemModelParts::model2);
- if (!img2.valid()) { return QImage{}; }
- QImage middle(img2.release(), img2.width(), img2.height(), img2.channels() == 4 ? QImage::Format_RGBA8888 : QImage::Format_RGB888,
- [](void* bytes) { if (bytes) { free(bytes); } });
- if (!img2.is_bio_dds()) { middle.mirror(); }
-
- auto img3 = item->get_icon_by_part(nw::ItemModelParts::model3);
- if (!img3.valid()) { return QImage{}; }
- QImage top(img3.release(), img3.width(), img3.height(), img3.channels() == 4 ? QImage::Format_RGBA8888 : QImage::Format_RGB888,
- [](void* bytes) { if (bytes) { free(bytes); } });
- if (!img3.is_bio_dds()) { top.mirror(); }
-
- QPainter painter(&bottom);
- painter.drawImage(0, 0, middle);
- painter.drawImage(0, 0, top);
- painter.end();
- return bottom.mirrored();
-
- } else if (type == nw::ItemModelType::armor) {
- QImage base;
-
- for (auto part : {
- nw::ItemModelParts::armor_pelvis,
- nw::ItemModelParts::armor_belt,
- nw::ItemModelParts::armor_torso,
- nw::ItemModelParts::armor_lshoul,
- nw::ItemModelParts::armor_rshoul,
- nw::ItemModelParts::armor_robe}) {
-
- if (item->model_parts[part] == 0) { continue; }
- auto texture = item->get_icon_by_part(part, female);
-
- if (texture.valid()) {
- QImage image(texture.release(), texture.width(), texture.height(), texture.channels() == 4 ? QImage::Format_RGBA8888 : QImage::Format_RGB888,
- [](void* bytes) { if (bytes) { free(bytes); } });
- if (base.isNull()) {
- base = image;
- } else {
- QPainter painter(&base);
- painter.drawImage(0, 0, image);
- }
- }
- }
-
- if (!base.isNull()) {
- return base.mirrored();
- }
- }
-
- return QImage();
-}
-
InventorySlot::InventorySlot(QWidget* parent)
: QLabel(parent)
{
diff --git a/src/widgets/util/items.cpp b/src/widgets/util/items.cpp
new file mode 100644
index 0000000..7128c76
--- /dev/null
+++ b/src/widgets/util/items.cpp
@@ -0,0 +1,86 @@
+#include "items.h"
+
+#include "nw/formats/Image.hpp"
+#include "nw/kernel/Strings.hpp"
+#include "nw/kernel/TwoDACache.hpp"
+#include "nw/objects/Item.hpp"
+
+#include
+#include
+
+QImage item_to_image(const nw::Item* item, bool female)
+{
+ auto* bi2da = nw::kernel::twodas().get("baseitems");
+ auto int_type = bi2da->get(*item->baseitem, "ModelType");
+ nw::ItemModelType type;
+
+ if (int_type) {
+ type = static_cast(*int_type);
+ } else {
+ return QImage();
+ }
+
+ if (type == nw::ItemModelType::simple || type == nw::ItemModelType::layered) {
+ auto icon = item->get_icon_by_part();
+ if (!icon.valid()) { return QImage{}; }
+ QImage image(icon.release(), icon.width(), icon.height(), icon.channels() == 4 ? QImage::Format_RGBA8888 : QImage::Format_RGB888,
+ [](void* bytes) { if (bytes) { free(bytes); } });
+ return image.mirrored();
+ } else if (type == nw::ItemModelType::composite) {
+ auto img1 = item->get_icon_by_part(nw::ItemModelParts::model1);
+ if (!img1.valid()) { return QImage{}; }
+ QImage bottom(img1.release(), img1.width(), img1.height(), img1.channels() == 4 ? QImage::Format_RGBA8888 : QImage::Format_RGB888,
+ [](void* bytes) { if (bytes) { free(bytes); } });
+ if (!img1.is_bio_dds()) { bottom.mirror(); }
+
+ auto img2 = item->get_icon_by_part(nw::ItemModelParts::model2);
+ if (!img2.valid()) { return QImage{}; }
+ QImage middle(img2.release(), img2.width(), img2.height(), img2.channels() == 4 ? QImage::Format_RGBA8888 : QImage::Format_RGB888,
+ [](void* bytes) { if (bytes) { free(bytes); } });
+ if (!img2.is_bio_dds()) { middle.mirror(); }
+
+ auto img3 = item->get_icon_by_part(nw::ItemModelParts::model3);
+ if (!img3.valid()) { return QImage{}; }
+ QImage top(img3.release(), img3.width(), img3.height(), img3.channels() == 4 ? QImage::Format_RGBA8888 : QImage::Format_RGB888,
+ [](void* bytes) { if (bytes) { free(bytes); } });
+ if (!img3.is_bio_dds()) { top.mirror(); }
+
+ QPainter painter(&bottom);
+ painter.drawImage(0, 0, middle);
+ painter.drawImage(0, 0, top);
+ painter.end();
+ return bottom.mirrored();
+
+ } else if (type == nw::ItemModelType::armor) {
+ QImage base;
+
+ for (auto part : {
+ nw::ItemModelParts::armor_pelvis,
+ nw::ItemModelParts::armor_belt,
+ nw::ItemModelParts::armor_torso,
+ nw::ItemModelParts::armor_lshoul,
+ nw::ItemModelParts::armor_rshoul,
+ nw::ItemModelParts::armor_robe}) {
+
+ if (item->model_parts[part] == 0) { continue; }
+ auto texture = item->get_icon_by_part(part, female);
+
+ if (texture.valid()) {
+ QImage image(texture.release(), texture.width(), texture.height(), texture.channels() == 4 ? QImage::Format_RGBA8888 : QImage::Format_RGB888,
+ [](void* bytes) { if (bytes) { free(bytes); } });
+ if (base.isNull()) {
+ base = image;
+ } else {
+ QPainter painter(&base);
+ painter.drawImage(0, 0, image);
+ }
+ }
+ }
+
+ if (!base.isNull()) {
+ return base.mirrored();
+ }
+ }
+
+ return QImage();
+}
diff --git a/src/widgets/util/items.h b/src/widgets/util/items.h
new file mode 100644
index 0000000..e0bd594
--- /dev/null
+++ b/src/widgets/util/items.h
@@ -0,0 +1,9 @@
+#pragma once
+
+namespace nw {
+struct Item;
+}
+
+class QImage;
+
+QImage item_to_image(const nw::Item* item, bool female);