diff options
Diffstat (limited to 'source/frontend/StarActionBar.cpp')
-rw-r--r-- | source/frontend/StarActionBar.cpp | 317 |
1 files changed, 317 insertions, 0 deletions
diff --git a/source/frontend/StarActionBar.cpp b/source/frontend/StarActionBar.cpp new file mode 100644 index 0000000..6c9b48c --- /dev/null +++ b/source/frontend/StarActionBar.cpp @@ -0,0 +1,317 @@ +#include "StarActionBar.hpp" +#include "StarJsonExtra.hpp" +#include "StarRoot.hpp" +#include "StarGuiReader.hpp" +#include "StarItemTooltip.hpp" +#include "StarUniverseClient.hpp" +#include "StarItemGridWidget.hpp" +#include "StarItemSlotWidget.hpp" +#include "StarButtonWidget.hpp" +#include "StarImageWidget.hpp" +#include "StarPaneManager.hpp" +#include "StarPlayer.hpp" +#include "StarPlayerInventory.hpp" +#include "StarAssets.hpp" +#include "StarItem.hpp" +#include "StarMerchantInterface.hpp" + +namespace Star { + +ActionBar::ActionBar(MainInterfacePaneManager* paneManager, PlayerPtr player) { + m_paneManager = paneManager; + m_player = move(player); + + auto assets = Root::singleton().assets(); + + m_config = assets->json("/interface/windowconfig/actionbar.config"); + + m_actionBarSelectOffset = jsonToVec2I(m_config.get("actionBarSelectOffset")); + m_switchSounds = jsonToStringList(m_config.get("sounds").get("switch")); + + GuiReader reader; + + for (uint8_t i = 0; i < m_player->inventory()->customBarIndexes(); ++i) { + reader.registerCallback(strf("customBar%sL", i + 1), bind(&ActionBar::customBarClick, this, i, true)); + reader.registerCallback(strf("customBar%sR", i + 1), bind(&ActionBar::customBarClick, this, i, false)); + + reader.registerCallback(strf("customBar%sL.right", i + 1), bind(&ActionBar::customBarClickRight, this, i, true)); + reader.registerCallback(strf("customBar%sR.right", i + 1), bind(&ActionBar::customBarClickRight, this, i, false)); + } + + for (uint8_t i = 0; i < EssentialItemCount; ++i) + reader.registerCallback(strf("essentialBar%s", i + 1), bind(&ActionBar::essentialBarClick, this, i)); + + reader.registerCallback("pickupToActionBar", [=](Widget* widget) { + auto button = as<ButtonWidget>(widget); + Root::singleton().configuration()->setPath("inventory.pickupToActionBar", button->isChecked()); + }); + + reader.registerCallback("swapCustomBar", [this](Widget*) { + swapCustomBar(); + }); + + reader.construct(m_config.get("paneLayout"), this); + + for (uint8_t i = 0; i < m_player->inventory()->customBarIndexes(); ++i) { + auto customBarLeft = fetchChild<ItemSlotWidget>(strf("customBar%sL", i + 1)); + auto customBarRight = fetchChild<ItemSlotWidget>(strf("customBar%sR", i + 1)); + auto customBarLeftOverlay = fetchChild<ImageWidget>(strf("customBar%sLOverlay", i + 1)); + auto customBarRightOverlay = fetchChild<ImageWidget>(strf("customBar%sROverlay", i + 1)); + + TextPositioning countPosition = {jsonToVec2F(m_config.get("countMidAnchor")), HorizontalAnchor::HMidAnchor}; + customBarLeft->setCountPosition(countPosition); + customBarLeft->setCountFontMode(FontMode::Shadow); + customBarRight->setCountPosition(countPosition); + customBarRight->setCountFontMode(FontMode::Shadow); + + m_customBarWidgets.append({customBarLeft, customBarRight, customBarLeftOverlay, customBarRightOverlay}); + } + m_customSelectedWidget = fetchChild<ImageWidget>("customSelect"); + + for (uint8_t i = 0; i < EssentialItemCount; ++i) + m_essentialBarWidgets.append(fetchChild<ItemSlotWidget>(strf("essentialBar%s", i + 1))); + m_essentialSelectedWidget = fetchChild<ImageWidget>("essentialSelect"); +} + +PanePtr ActionBar::createTooltip(Vec2I const& screenPosition) { + ItemPtr item; + auto tryItemWidget = [&](ItemSlotWidgetPtr const& isw) { + if (isw->screenBoundRect().contains(screenPosition)) + item = isw->item(); + }; + + for (auto const& p : m_customBarWidgets) { + tryItemWidget(p.left); + tryItemWidget(p.right); + } + + for (auto const& w : m_essentialBarWidgets) + tryItemWidget(w); + + if (!item) + return {}; + + return ItemTooltipBuilder::buildItemTooltip(item, m_player); +} + +bool ActionBar::sendEvent(InputEvent const& event) { + if (Pane::sendEvent(event)) + return true; + + auto inventory = m_player->inventory(); + + auto customBarIndexes = inventory->customBarIndexes(); + if (auto mouseWheel = event.ptr<MouseWheelEvent>()) { + auto abl = inventory->selectedActionBarLocation(); + + int index = 0; + if (!abl) { + if (mouseWheel->mouseWheel == MouseWheel::Down) + index = 0; + else + index = customBarIndexes + EssentialItemCount - 1; + } else { + if (auto cbi = abl.ptr<CustomBarIndex>()) { + if (*cbi < customBarIndexes / 2) + index = *cbi; + else + index = *cbi + EssentialItemCount; + } else { + index = customBarIndexes / 2 + (int)abl.get<EssentialItem>(); + } + + if (mouseWheel->mouseWheel == MouseWheel::Down) + index = pmod(index + 1, customBarIndexes + EssentialItemCount); + else + index = pmod(index - 1, customBarIndexes + EssentialItemCount); + } + + if (index < customBarIndexes / 2) + abl = (CustomBarIndex)index; + else if (index < customBarIndexes / 2 + EssentialItemCount) + abl = (EssentialItem)(index - customBarIndexes / 2); + else + abl = (CustomBarIndex)(index - EssentialItemCount); + + inventory->selectActionBarLocation(abl); + context()->playAudio(RandomSource().randFrom(m_switchSounds)); + + return true; + } + + if (event.is<MouseMoveEvent>()) { + m_customBarHover.reset(); + Vec2I screenPosition = *GuiContext::singleton().mousePosition(event); + for (uint8_t i = 0; i < customBarIndexes; ++i) { + if (m_customBarWidgets[i].left->screenBoundRect().contains(screenPosition)) + m_customBarHover = make_pair((CustomBarIndex)i, false); + else if (m_customBarWidgets[i].right->screenBoundRect().contains(screenPosition)) + m_customBarHover = make_pair((CustomBarIndex)i, true); + } + } + + for (auto action : context()->actions(event)) { + if (action >= InterfaceAction::InterfaceBar1 && action <= InterfaceAction::InterfaceBar6) + inventory->selectActionBarLocation((CustomBarIndex)((int)action - (int)InterfaceAction::InterfaceBar1)); + + if (action >= InterfaceAction::EssentialBar1 && action <= InterfaceAction::EssentialBar4) + inventory->selectActionBarLocation((EssentialItem)((int)action - (int)InterfaceAction::EssentialBar1)); + + if (action == InterfaceAction::InterfaceDeselectHands) { + if (auto previousSelectedLocation = inventory->selectedActionBarLocation()) { + m_emptyHandsPreviousActionBarLocation = inventory->selectedActionBarLocation(); + inventory->selectActionBarLocation({}); + } else { + inventory->selectActionBarLocation(take(m_emptyHandsPreviousActionBarLocation)); + } + } + + if (action == InterfaceAction::InterfaceChangeBarGroup) + swapCustomBar(); + } + + return false; +} + +void ActionBar::update() { + auto inventory = m_player->inventory(); + auto abl = inventory->selectedActionBarLocation(); + if (abl.is<CustomBarIndex>()) { + auto overlayLoc = m_customBarWidgets.at(abl.get<CustomBarIndex>()).left->position(); + m_customSelectedWidget->setPosition(overlayLoc + m_actionBarSelectOffset); + m_customSelectedWidget->show(); + m_essentialSelectedWidget->hide(); + } else if (abl.is<EssentialItem>()) { + auto overlayLoc = m_essentialBarWidgets.at((size_t)abl.get<EssentialItem>())->position(); + m_essentialSelectedWidget->setPosition(overlayLoc + m_actionBarSelectOffset); + m_essentialSelectedWidget->show(); + m_customSelectedWidget->hide(); + } else { + m_essentialSelectedWidget->hide(); + m_customSelectedWidget->hide(); + } + + for (uint8_t i = 0; i < EssentialItemCount; ++i) + m_essentialBarWidgets[i]->setItem(inventory->essentialItem((EssentialItem)i)); + + for (uint8_t i = 0; i < inventory->customBarIndexes(); ++i) { + // If there is no swap slot item being hovered over the custom bar, then + // simply set the left and right item widgets in the custom bar to the + // primary and secondary items. If the primary item is two handed, the + // secondary item will be null and the primary hand item is drawn dimmed in + // the right hand slot. If there IS a swap slot item being hovered over + // this spot in the custom bar, things are more complex. Instead of + // showing what is currently in the custom bar, a preview of what WOULD + // happen when linking is shown, except both the left and right item + // widgets are always shown with no count and always dimmed to indicate + // that it is just a preview. + + ItemPtr primaryItem; + ItemPtr secondaryItem; + + if (auto slot = inventory->customBarPrimarySlot(i)) + primaryItem = inventory->itemsAt(*slot); + + if (auto slot = inventory->customBarSecondarySlot(i)) + secondaryItem = inventory->itemsAt(*slot); + + bool primaryPreview = false; + bool secondaryPreview = false; + + ItemPtr swapSlotItem = inventory->swapSlotItem(); + if (swapSlotItem && m_customBarHover && m_customBarHover->first == i) { + if (!m_customBarHover->second || swapSlotItem->twoHanded()) { + if (!primaryItem && swapSlotItem == secondaryItem) + secondaryItem = {}; + primaryItem = swapSlotItem; + primaryPreview = true; + } else { + if (itemSafeTwoHanded(primaryItem)) + primaryItem = {}; + if (!secondaryItem && swapSlotItem == primaryItem) + primaryItem = {}; + secondaryItem = swapSlotItem; + secondaryPreview = true; + } + } + + auto& widgets = m_customBarWidgets[i]; + widgets.left->setItem(primaryItem); + if (primaryPreview) { + widgets.left->showDurability(false); + widgets.left->showCount(false); + widgets.leftOverlay->show(); + } else { + widgets.left->showDurability(true); + widgets.left->showCount(true); + widgets.leftOverlay->hide(); + } + + if (itemSafeTwoHanded(primaryItem)) { + widgets.right->setItem(primaryItem); + widgets.right->showDurability(false); + widgets.right->showCount(false); + widgets.rightOverlay->show(); + } else { + widgets.right->setItem(secondaryItem); + if (secondaryPreview) { + widgets.right->showDurability(false); + widgets.right->showCount(false); + widgets.rightOverlay->show(); + } else { + widgets.right->showDurability(true); + widgets.right->showCount(true); + widgets.rightOverlay->hide(); + } + } + + widgets.left->setHighlightEnabled(!widgets.left->item() && swapSlotItem); + widgets.right->setHighlightEnabled(!widgets.right->item() && swapSlotItem); + } + + fetchChild<ButtonWidget>("pickupToActionBar")->setChecked(Root::singleton().configuration()->getPath("inventory.pickupToActionBar").toBool()); + fetchChild<ButtonWidget>("swapCustomBar")->setChecked(m_player->inventory()->customBarGroup() != 0); +} + +Maybe<String> ActionBar::cursorOverride(Vec2I const&) { + if (m_customBarHover && m_player->inventory()->swapSlotItem()) + return m_config.getString("linkCursor"); + return {}; +} + +void ActionBar::customBarClick(uint8_t index, bool primary) { + if (auto swapItem = m_player->inventory()->swapSlotItem()) { + if (primary || itemSafeTwoHanded(swapItem)) + m_player->inventory()->setCustomBarPrimarySlot(index, InventorySlot(SwapSlot())); + else + m_player->inventory()->setCustomBarSecondarySlot(index, InventorySlot(SwapSlot())); + + m_player->inventory()->clearSwap(); + + } else { + m_player->inventory()->selectActionBarLocation(index); + } +} + +void ActionBar::customBarClickRight(uint8_t index, bool primary) { + if (m_paneManager->registeredPaneIsDisplayed(MainInterfacePanes::Inventory)) { + auto inventory = m_player->inventory(); + auto primarySlot = inventory->customBarPrimarySlot(index); + auto secondarySlot = inventory->customBarSecondarySlot(index); + + if (primary || (primarySlot && itemSafeTwoHanded(inventory->itemsAt(*primarySlot)))) + inventory->setCustomBarPrimarySlot(index, {}); + else + inventory->setCustomBarSecondarySlot(index, {}); + } +} + +void ActionBar::essentialBarClick(uint8_t index) { + m_player->inventory()->selectActionBarLocation((EssentialItem)index); +} + +void ActionBar::swapCustomBar() { + m_player->inventory()->setCustomBarGroup((m_player->inventory()->customBarGroup() + 1) % m_player->inventory()->customBarGroups()); +} + +} |