diff options
Diffstat (limited to 'source/windowing/StarItemGridWidget.cpp')
-rw-r--r-- | source/windowing/StarItemGridWidget.cpp | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/source/windowing/StarItemGridWidget.cpp b/source/windowing/StarItemGridWidget.cpp new file mode 100644 index 0000000..624385b --- /dev/null +++ b/source/windowing/StarItemGridWidget.cpp @@ -0,0 +1,289 @@ +#include "StarItemGridWidget.hpp" +#include "StarRoot.hpp" +#include "StarJsonExtra.hpp" +#include "StarAssets.hpp" + +namespace Star { + +ItemGridWidget::ItemGridWidget(ItemBagConstPtr bag, Vec2I const& dimensions, Vec2I const& spacing, String const& backingImage, unsigned bagOffset) + : ItemGridWidget(bag, dimensions, {spacing[0], 0}, {0, spacing[1]}, backingImage, bagOffset) {} + +ItemGridWidget::ItemGridWidget(ItemBagConstPtr bag, Vec2I const& dimensions, Vec2I const& rowSpacing, Vec2I const& columnSpacing, String const& backingImage, unsigned bagOffset) + : m_bagOffset(bagOffset), m_dimensions(dimensions), m_rowSpacing(rowSpacing), m_columnSpacing(columnSpacing), m_backingImage(backingImage) { + m_selectedIndex = 0; + m_progress = 1; + + m_drawBackingImageWhenFull = false; + m_drawBackingImageWhenEmpty = true; + m_showDurability = false; + m_highlightEmpty = false; + + setItemBag(bag); + + auto assets = Root::singleton().assets(); + m_itemDraggableArea = jsonToRectI(assets->json("/interface.config:itemDraggableArea")); + Vec2I calculatedSize = { + m_dimensions[0] * m_rowSpacing[0] + m_dimensions[1] * m_columnSpacing[0], + m_dimensions[0] * m_rowSpacing[1] + m_dimensions[1] * m_columnSpacing[1] + }; + setSize(calculatedSize.piecewiseMax(m_itemDraggableArea.size())); + + disableScissoring(); + markAsContainer(); +} + +ItemBagConstPtr ItemGridWidget::bag() const { + return m_bag; +} + +ItemPtr ItemGridWidget::itemAt(Vec2I const& position) const { + auto pos = bagLocationAt(position); + if (pos != NPos && m_bag) + return m_bag->at(pos); + + return {}; +} + +ItemPtr ItemGridWidget::itemAt(size_t index) const { + if (index < m_bag->size()) + return m_bag->at(index); + return {}; +} + +ItemPtr ItemGridWidget::selectedItem() const { + return itemAt(selectedIndex()); +} + +ItemSlotWidgetPtr ItemGridWidget::itemWidgetAt(Vec2I const& position) const { + auto pos = bagLocationAt(position); + if (pos != NPos) + return m_slots[pos]; + return {}; +} + +ItemSlotWidgetPtr ItemGridWidget::itemWidgetAt(size_t index) const { + if (index < m_slots.size()) + return m_slots[index]; + return {}; +} + +Vec2I ItemGridWidget::dimensions() const { + return m_dimensions; +} + +size_t ItemGridWidget::itemSlots() const { + return m_dimensions.x() * m_dimensions.y(); +} + +size_t ItemGridWidget::bagSize() const { + if (!m_bag) + return 0; + + return m_bag->size(); +} + +size_t ItemGridWidget::effectiveSize() const { + return min(itemSlots(), bagSize()); +} + +size_t ItemGridWidget::bagLocationAt(Vec2I const& position) const { + if (m_bag) { + for (size_t i = 0; i < (m_bag->size() - m_bagOffset) && i < unsigned(m_dimensions[0] * m_dimensions[1]); ++i) { + Vec2I loc = locOfItemSlot(i); + RectI bagItemArea = RectI(m_itemDraggableArea).translated(screenPosition() + loc); + if (bagItemArea.contains(position)) + return i + m_bagOffset; + } + } + + return NPos; +} + +Vec2I ItemGridWidget::positionOfSlot(size_t slotNumber) { + return m_slots.at(slotNumber)->position() + position(); +} + +bool ItemGridWidget::sendEvent(InputEvent const& event) { + if (m_visible) { + if (auto mouseButton = event.ptr<MouseButtonDownEvent>()) { + if (mouseButton->mouseButton == MouseButton::Left || (m_rightClickCallback && mouseButton->mouseButton == MouseButton::Right)) { + Vec2I mousePos = *context()->mousePosition(event); + for (size_t i = 0; i < (m_bag->size() - m_bagOffset) && i < unsigned(m_dimensions[0] * m_dimensions[1]); ++i) { + Vec2I loc = locOfItemSlot(i); + RectI bagItemArea = RectI(m_itemDraggableArea).translated(screenPosition() + loc); + + if (bagItemArea.contains(mousePos)) { + m_selectedIndex = i; + if (mouseButton->mouseButton == MouseButton::Right) + m_rightClickCallback(this); + else + m_callback(this); + return true; + } + } + } + } + } + return false; +} + +Vec2I ItemGridWidget::locOfItemSlot(unsigned slot) const { + Vec2I loc = { + (int)slot % (int)m_dimensions[0] * m_rowSpacing[0] + // x contribution from row + (int)slot / (int)m_dimensions[0] * m_columnSpacing[0], // x contribution from column + (m_dimensions[0] - 1) * m_rowSpacing[1] - (int)slot % (int)m_dimensions[0] * m_rowSpacing[1] + // y contribution from row + (m_dimensions[1] - 1) * m_columnSpacing[1] - (int)slot / (int)m_dimensions[0] * m_columnSpacing[1] // y contribution from column + }; + return loc; +} + +void ItemGridWidget::setCallback(WidgetCallbackFunc callback) { + m_callback = callback; +} + +void ItemGridWidget::setRightClickCallback(WidgetCallbackFunc callback) { + m_rightClickCallback = callback; +} + +void ItemGridWidget::setItemBag(ItemBagConstPtr bag) { + m_bag = bag; + + if (!m_bag) + return; + + removeAllChildren(); + m_slots.clear(); + for (size_t i = 0; i < m_bag->size() - m_bagOffset && i < (unsigned)m_dimensions[0] * m_dimensions[1]; ++i) { + auto itemSlot = make_shared<ItemSlotWidget>(m_bag->at(i), m_backingImage); + addChild(strf("%d", i), itemSlot); + m_slots.append(itemSlot); + itemSlot->setBackingImageAffinity(m_drawBackingImageWhenFull, m_drawBackingImageWhenEmpty); + itemSlot->setProgress(m_progress); + itemSlot->setPosition(locOfItemSlot(i)); + itemSlot->showDurability(m_showDurability); + } + + m_itemNames = slotItemNames(); +} + +void ItemGridWidget::setProgress(float progress) { + m_progress = progress; + + if (!m_bag) + return; + + for (size_t i = 0; i < m_bag->size() - m_bagOffset && i < (unsigned)m_dimensions[0] * m_dimensions[1]; ++i) { + auto itemSlot = m_slots.at(i); + itemSlot->setProgress(m_progress); + } +} + +size_t ItemGridWidget::selectedIndex() const { + return m_selectedIndex + m_bagOffset; +} + +void ItemGridWidget::updateAllItemSlots() { + if (!m_bag) + return; + + for (size_t i = 0; i < m_bag->size() - m_bagOffset && i < (unsigned)m_dimensions[0] * m_dimensions[1]; ++i) { + auto item = m_bag->at(i + m_bagOffset); + auto slot = m_slots.at(i); + slot->setItem(item); + slot->setHighlightEnabled(!item && m_highlightEmpty); + } +} + +void ItemGridWidget::updateItemState() { + updateAllItemSlots(); + auto newState = slotItemNames(); + for (size_t i = 0; i < newState.size(); ++i) { + if (newState[i].empty()) { + m_changedSlots.remove(i); + continue; + } + + if (newState[i].compare(m_itemNames[i]) != 0) + m_changedSlots.insert(i); + } + m_itemNames = newState; +} + +void ItemGridWidget::indicateChangedSlots() { + for (auto i : m_changedSlots) + m_slots[i]->indicateNew(); +} + +void ItemGridWidget::setHighlightEmpty(bool highlight) { + m_highlightEmpty = highlight; +} + +void ItemGridWidget::clearChangedSlots() { + m_changedSlots.clear(); +} + +bool ItemGridWidget::slotsChanged() { + return m_changedSlots.size() > 0; +} + +HashSet<ItemDescriptor> ItemGridWidget::uniqueItemState() { + HashSet<ItemDescriptor> state; + if (!m_bag) + return state; + for (auto item : m_bag->items()) { + if (item) + state.add(item->descriptor().singular()); + } + return state; +} + +List<String> ItemGridWidget::slotItemNames() { + List<String> itemNames; + for (auto slot : m_slots) { + if (slot->item()) + itemNames.append(slot->item()->name()); + else + itemNames.append(String()); + } + return itemNames; +} + +void ItemGridWidget::setBackingImageAffinity(bool full, bool empty) { + m_drawBackingImageWhenFull = full; + m_drawBackingImageWhenEmpty = empty; + + if (!m_bag) + return; + + for (size_t i = 0; i < m_bag->size() - m_bagOffset && i < (unsigned)m_dimensions[0] * m_dimensions[1]; ++i) { + auto itemSlot = m_slots.at(i); + itemSlot->setBackingImageAffinity(m_drawBackingImageWhenFull, m_drawBackingImageWhenEmpty); + } +} + +void ItemGridWidget::showDurability(bool show) { + m_showDurability = show; + + if (!m_bag) + return; + + for (size_t i = 0; i < m_bag->size() - m_bagOffset && i < (unsigned)m_dimensions[0] * m_dimensions[1]; ++i) { + auto itemSlot = m_slots.at(i); + itemSlot->showDurability(m_showDurability); + } +} + +RectI ItemGridWidget::getScissorRect() const { + auto assets = Root::singleton().assets(); + auto durabilityOffset = jsonToVec2I(assets->json("/interface.config:itemIconDurabilityOffset")); + auto itemCountRightAnchor = jsonToVec2I(assets->json("/interface.config:itemCountRightAnchor")); + + Vec2I extra = Vec2I(durabilityOffset * -1).piecewiseMax(itemCountRightAnchor * -1).piecewiseMax(Vec2I()); + return RectI::withSize(screenPosition() - extra, size() + extra); +} + +void ItemGridWidget::renderImpl() { + updateAllItemSlots(); +} + +} |