888cde79ef
makes carrying around shop objects easier might need to restrict the allowed interaction types more, as some may break due to the source entity being the player
219 lines
7.1 KiB
C++
219 lines
7.1 KiB
C++
#include "StarItemSlotWidget.hpp"
|
|
#include "StarRoot.hpp"
|
|
#include "StarJsonExtra.hpp"
|
|
#include "StarWidgetParsing.hpp"
|
|
#include "StarImageMetadataDatabase.hpp"
|
|
#include "StarItem.hpp"
|
|
#include "StarDurabilityItem.hpp"
|
|
#include "StarAssets.hpp"
|
|
#include "StarGameTypes.hpp"
|
|
|
|
namespace Star {
|
|
|
|
ItemSlotWidget::ItemSlotWidget(ItemPtr const& item, String const& backingImage)
|
|
: m_item(item), m_backingImage(backingImage) {
|
|
m_drawBackingImageWhenFull = false;
|
|
m_drawBackingImageWhenEmpty = true;
|
|
m_fontSize = 0;
|
|
m_progress = 1;
|
|
|
|
auto assets = Root::singleton().assets();
|
|
auto interfaceConfig = assets->json("/interface.config");
|
|
m_countPosition = TextPositioning(jsonToVec2F(interfaceConfig.get("itemCountRightAnchor")), HorizontalAnchor::RightAnchor);
|
|
m_countFontMode = FontMode::Normal;
|
|
m_fontSize = interfaceConfig.query("font.itemSize").toInt();
|
|
m_font = interfaceConfig.query("font.defaultFont").toString();
|
|
m_fontColor = Color::rgb(jsonToVec3B(interfaceConfig.query("font.defaultColor")));
|
|
m_itemDraggableArea = jsonToRectI(interfaceConfig.get("itemDraggableArea"));
|
|
m_durabilityOffset = jsonToVec2I(interfaceConfig.get("itemIconDurabilityOffset"));
|
|
|
|
auto newItemIndicatorConfig = interfaceConfig.get("newItemAnimation");
|
|
m_newItemIndicator = Animation(newItemIndicatorConfig);
|
|
// End animation before it begins, only display when triggered
|
|
m_newItemIndicator.update(newItemIndicatorConfig.getDouble("animationCycle") * newItemIndicatorConfig.getDouble("loops", 1.0f));
|
|
|
|
Json highlightAnimationConfig = interfaceConfig.get("highlightAnimation");
|
|
m_highlightAnimation = Animation(highlightAnimationConfig);
|
|
m_highlightEnabled = false;
|
|
|
|
Vec2I backingImageSize;
|
|
if (m_backingImage.size()) {
|
|
auto imgMetadata = Root::singleton().imageMetadataDatabase();
|
|
backingImageSize = Vec2I(imgMetadata->imageSize(m_backingImage));
|
|
}
|
|
setSize(m_itemDraggableArea.max().piecewiseMax(backingImageSize));
|
|
|
|
WidgetParser parser;
|
|
|
|
parser.construct(assets->json("/interface/itemSlot.config").get("config"), this);
|
|
m_durabilityBar = fetchChild<ProgressWidget>("durabilityBar");
|
|
m_durabilityBar->hide();
|
|
m_showDurability = false;
|
|
m_showCount = true;
|
|
m_showRarity = true;
|
|
m_showLinkIndicator = false;
|
|
|
|
disableScissoring();
|
|
}
|
|
|
|
void ItemSlotWidget::update(float dt) {
|
|
if (m_item)
|
|
m_newItemIndicator.update(dt);
|
|
if (m_highlightEnabled)
|
|
m_highlightAnimation.update(dt);
|
|
Widget::update(dt);
|
|
}
|
|
|
|
bool ItemSlotWidget::sendEvent(InputEvent const& event) {
|
|
if (m_visible) {
|
|
if (auto mouseButton = event.ptr<MouseButtonDownEvent>()) {
|
|
if (mouseButton->mouseButton == MouseButton::Left
|
|
|| (m_rightClickCallback && mouseButton->mouseButton == MouseButton::Right)
|
|
|| (m_middleClickCallback && mouseButton->mouseButton == MouseButton::Middle)) {
|
|
Vec2I mousePos = *context()->mousePosition(event);
|
|
RectI itemArea = m_itemDraggableArea.translated(screenPosition());
|
|
if (itemArea.contains(mousePos)) {
|
|
if (mouseButton->mouseButton == MouseButton::Right)
|
|
m_rightClickCallback(this);
|
|
else if (mouseButton->mouseButton == MouseButton::Middle)
|
|
m_middleClickCallback(this);
|
|
else
|
|
m_callback(this);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void ItemSlotWidget::setCallback(WidgetCallbackFunc callback) {
|
|
m_callback = callback;
|
|
}
|
|
|
|
void ItemSlotWidget::setRightClickCallback(WidgetCallbackFunc callback) {
|
|
m_rightClickCallback = callback;
|
|
}
|
|
|
|
void ItemSlotWidget::setMiddleClickCallback(WidgetCallbackFunc callback) {
|
|
m_middleClickCallback = callback;
|
|
}
|
|
|
|
void ItemSlotWidget::setItem(ItemPtr const& item) {
|
|
m_item = item;
|
|
}
|
|
|
|
ItemPtr ItemSlotWidget::item() const {
|
|
return m_item;
|
|
}
|
|
|
|
void ItemSlotWidget::setProgress(float progress) {
|
|
m_progress = progress;
|
|
}
|
|
|
|
void ItemSlotWidget::setBackingImageAffinity(bool full, bool empty) {
|
|
m_drawBackingImageWhenFull = full;
|
|
m_drawBackingImageWhenEmpty = empty;
|
|
}
|
|
|
|
void ItemSlotWidget::setCountPosition(TextPositioning textPositioning) {
|
|
m_countPosition = textPositioning;
|
|
}
|
|
|
|
void ItemSlotWidget::setCountFontMode(FontMode fontMode) {
|
|
m_countFontMode = fontMode;
|
|
}
|
|
|
|
void ItemSlotWidget::showDurability(bool show) {
|
|
m_showDurability = show;
|
|
}
|
|
|
|
void ItemSlotWidget::showCount(bool show) {
|
|
m_showCount = show;
|
|
}
|
|
|
|
void ItemSlotWidget::showRarity(bool showRarity) {
|
|
m_showRarity = showRarity;
|
|
}
|
|
|
|
void ItemSlotWidget::showLinkIndicator(bool showLinkIndicator) {
|
|
m_showLinkIndicator = showLinkIndicator;
|
|
}
|
|
|
|
void ItemSlotWidget::indicateNew() {
|
|
m_newItemIndicator.reset();
|
|
}
|
|
|
|
void ItemSlotWidget::setHighlightEnabled(bool highlight) {
|
|
if (!m_highlightEnabled && highlight)
|
|
m_highlightAnimation.reset();
|
|
m_highlightEnabled = highlight;
|
|
}
|
|
|
|
void ItemSlotWidget::renderImpl() {
|
|
if (m_item) {
|
|
if (m_drawBackingImageWhenFull && m_backingImage != "")
|
|
context()->drawInterfaceQuad(m_backingImage, Vec2F(screenPosition()));
|
|
|
|
List<Drawable> iconDrawables = m_item->iconDrawables();
|
|
|
|
if (m_showRarity) {
|
|
String border = rarityBorder(m_item->rarity());
|
|
context()->drawInterfaceQuad(border, Vec2F(screenPosition()));
|
|
}
|
|
|
|
if (m_showLinkIndicator) {
|
|
// TODO: Hardcoded
|
|
context()->drawInterfaceQuad(String("/interface/inventory/itemlinkindicator.png"), Vec2F(screenPosition() - Vec2I(1, 1)));
|
|
}
|
|
|
|
for (auto i : iconDrawables)
|
|
context()->drawInterfaceDrawable(i, Vec2F(screenPosition() + size() / 2));
|
|
|
|
if (!m_newItemIndicator.isComplete())
|
|
context()->drawInterfaceDrawable(m_newItemIndicator.drawable(1.0), Vec2F(screenPosition() + size() / 2), Color::White.toRgba());
|
|
|
|
if (m_showDurability) {
|
|
if (auto durabilityItem = as<DurabilityItem>(m_item)) {
|
|
float amount = durabilityItem->durabilityStatus();
|
|
m_durabilityBar->setCurrentProgressLevel(amount);
|
|
|
|
if (amount < 1)
|
|
m_durabilityBar->show();
|
|
else
|
|
m_durabilityBar->hide();
|
|
} else {
|
|
m_durabilityBar->hide();
|
|
}
|
|
}
|
|
|
|
int frame = (int)roundf(m_progress * 18); // TODO: Hardcoded lol
|
|
context()->drawInterfaceQuad(String(strf("/interface/cooldown.png:{}", frame)), Vec2F(screenPosition()));
|
|
|
|
if (m_item->count() > 1 && m_showCount) { // we don't need to tell people that there's only 1 of something
|
|
context()->setFont(m_font);
|
|
context()->setFontSize(m_fontSize);
|
|
context()->setFontColor(m_fontColor.toRgba());
|
|
context()->setFontMode(m_countFontMode);
|
|
context()->renderInterfaceText(toString(m_item->count()), m_countPosition.translated(Vec2F(screenPosition())));
|
|
context()->setFontMode(FontMode::Normal);
|
|
context()->setDefaultFont();
|
|
}
|
|
|
|
} else if (m_drawBackingImageWhenEmpty && m_backingImage != "") {
|
|
context()->drawInterfaceQuad(m_backingImage, Vec2F(screenPosition()));
|
|
int frame = (int)roundf(m_progress * 18); // TODO: Hardcoded lol
|
|
context()->drawInterfaceQuad(String(strf("/interface/cooldown.png:{}", frame)), Vec2F(screenPosition()));
|
|
}
|
|
|
|
if (m_highlightEnabled) {
|
|
context()->drawInterfaceDrawable(m_highlightAnimation.drawable(1.0), Vec2F(screenPosition() + size() / 2), Color::White.toRgba());
|
|
}
|
|
|
|
if (!m_item)
|
|
m_durabilityBar->hide();
|
|
}
|
|
|
|
}
|