From 6352e8e3196f78388b6c771073f9e03eaa612673 Mon Sep 17 00:00:00 2001 From: Kae <80987908+Novaenia@users.noreply.github.com> Date: Tue, 20 Jun 2023 14:33:09 +1000 Subject: everything everywhere all at once --- source/frontend/StarTeamBar.cpp | 393 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 393 insertions(+) create mode 100644 source/frontend/StarTeamBar.cpp (limited to 'source/frontend/StarTeamBar.cpp') diff --git a/source/frontend/StarTeamBar.cpp b/source/frontend/StarTeamBar.cpp new file mode 100644 index 0000000..48a9b51 --- /dev/null +++ b/source/frontend/StarTeamBar.cpp @@ -0,0 +1,393 @@ +#include "StarTeamBar.hpp" +#include "StarMainInterface.hpp" +#include "StarJsonExtra.hpp" +#include "StarRoot.hpp" +#include "StarUniverseClient.hpp" +#include "StarGuiReader.hpp" +#include "StarButtonWidget.hpp" +#include "StarTeamClient.hpp" +#include "StarImageWidget.hpp" +#include "StarProgressWidget.hpp" +#include "StarTextBoxWidget.hpp" +#include "StarLabelWidget.hpp" +#include "StarPlayer.hpp" +#include "StarAssets.hpp" +#include "StarWorldClient.hpp" +#include "StarPortraitWidget.hpp" +#include "StarMathCommon.hpp" + +namespace Star { + +TeamBar::TeamBar(MainInterface* mainInterface, UniverseClientPtr client) { + m_mainInterface = mainInterface; + m_client = client; + + m_guiContext = GuiContext::singletonPtr(); + auto assets = Root::singleton().assets(); + + m_teamInvite = make_shared(this); + m_teamInvitation = make_shared(this); + m_teamMemberMenu = make_shared(this); + + m_nameFontSize = assets->json("/interface.config:font.nameSize").toInt(); + m_nameOffset = jsonToVec2F(assets->json("/interface.config:nameOffset")); + + GuiReader reader; + + reader.registerCallback("inviteButton", [this](Widget*) { inviteButton(); }); + reader.registerCallback("showSelfMenu", [this](Widget*) { + if (!m_client->teamClient()->isMemberOfTeam()) + return; + auto position = jsonToVec2I(Root::singleton().assets()->json("/interface/windowconfig/teambar.config:selfMenuOffset")); + position[1] += windowHeight() / m_guiContext->interfaceScale(); + showMemberMenu(m_client->mainPlayer()->uuid(), position); + }); + + reader.construct(assets->json("/interface/windowconfig/teambar.config:paneLayout"), this); + + m_healthBar = fetchChild("healthBar"); + m_energyBar = fetchChild("energyBar"); + m_foodBar = fetchChild("foodBar"); + + m_energyBarColor = jsonToColor(assets->json("/interface/windowconfig/teambar.config:energyBarColor")); + m_energyBarRegenMixColor = jsonToColor(assets->json("/interface/windowconfig/teambar.config:energyBarRegenMixColor")); + m_energyBarUnusableColor = jsonToColor(assets->json("/interface/windowconfig/teambar.config:energyBarUnusableColor")); + + m_energyBar->setColor(m_energyBarColor); + + auto playerPortrait = fetchChild("portrait"); + playerPortrait->setEntity(as(m_client->mainPlayer())); + + fetchChild("name")->setText(m_client->mainPlayer()->name()); + + disableScissoring(); +} + +bool TeamBar::sendEvent(InputEvent const& event) { + if (event.is() + && (event.get().mouseButton == MouseButton::Left || event.get().mouseButton == MouseButton::Right)) { + if (m_teamMemberMenu->isDisplayed() && !m_teamMemberMenu->inMember(*context()->mousePosition(event))) + m_teamMemberMenu->dismiss(); + } + return Pane::sendEvent(event); +} + +void TeamBar::invitePlayer(String const& playerName) { + m_client->teamClient()->invitePlayer(playerName); +} + +void TeamBar::acceptInvitation(Uuid const& inviterUuid) { + m_client->teamClient()->acceptInvitation(inviterUuid); +} + +void TeamBar::update() { + Pane::update(); + + updatePlayerResources(); + + auto teamClient = m_client->teamClient(); + + if (!m_teamInvitation->active()) { + if (teamClient->hasInvitationPending()) { + auto invitation = teamClient->pullInvitation(); + m_teamInvitation->open(invitation.first, invitation.second); + if (!m_teamInvitation->isDisplayed()) + m_mainInterface->paneManager()->displayPane(PaneLayer::Window, m_teamInvitation); + } + } + + if (teamClient->currentTeam() && !teamClient->isTeamLeader()) + m_teamInvite->dismiss(); + + fetchChild("leader")->setVisibility(teamClient->isTeamLeader()); + + buildTeamBar(); +} + +void TeamBar::updatePlayerResources() { + auto player = m_client->mainPlayer(); + + m_healthBar->setCurrentProgressLevel(player->healthPercentage()); + m_energyBar->setCurrentProgressLevel(player->energyPercentage()); + + if (player->modeConfig().hunger) { + m_foodBar->setCurrentProgressLevel(player->foodPercentage()); + auto assets = Root::singleton().assets(); + if (player->foodPercentage() <= assets->json("/player.config:foodLowThreshold").toFloat()) { + float flashTime = assets->json("/interface/windowconfig/teambar.config:foodBarFlashTime").toFloat(); + if (fmod(Time::monotonicTime(), flashTime * 2) < flashTime) + m_foodBar->setOverlay(assets->json("/interface/windowconfig/teambar.config:foodBarFlashOverlay").toString()); + else + m_foodBar->setOverlay(""); + } else { + m_foodBar->setOverlay(""); + } + } else { + m_foodBar->hide(); + } + + if (player->energyLocked()) { + m_energyBar->setColor(m_energyBarUnusableColor); + } else { + m_energyBar->setColor(m_energyBarColor.mix(m_energyBarRegenMixColor, player->energyRegenBlockPercent())); + } +} + +void TeamBar::inviteButton() { + if (!m_teamInvite->isDisplayed()) + m_mainInterface->paneManager()->displayPane(PaneLayer::Window, m_teamInvite); +} + +void TeamBar::buildTeamBar() { + auto teamClient = m_client->teamClient(); + auto player = m_client->mainPlayer(); + + auto list = fetchChild("list"); + auto assets = Root::singleton().assets(); + + Vec2I offset; + size_t controlIndex = 0; + size_t memberIndex = 0; + + float portraitScale = assets->json("/interface/windowconfig/teambar.config:memberPortraitScale").toFloat(); + int memberSize = assets->json("/interface/windowconfig/teambar.config:memberSize").toInt(); + int memberSpacing = assets->json("/interface/windowconfig/teambar.config:memberSpacing").toInt(); + + for (auto member : teamClient->members()) { + if (member.uuid == player->uuid()) { + memberIndex++; + continue; + } + + String cellName = strf("%s", controlIndex); + WidgetPtr cell = list->fetchChild(cellName); + + if (!cell) { + GuiReader reader; + cell = make_shared(); + cell->disableScissoring(); + cell->markAsContainer(); + + reader.registerCallback("showMemberMenu", [this](Widget* widget) { + auto position = widget->screenPosition() + jsonToVec2I(Root::singleton().assets()->json("/interface/windowconfig/teambar.config:memberMenuOffset")); + showMemberMenu(Uuid(widget->parent()->data().toString()), position); + }); + + reader.construct(assets->json("/interface/windowconfig/teambar.config:entry"), cell.get()); + + list->addChild(cellName, cell); + } + + offset[1] -= memberSize; + cell->setPosition(offset); + + cell->setData(member.uuid.hex()); + + cell->show(); + + if (!teamClient->isTeamLeader(member.uuid)) + cell->fetchChild("leader")->hide(); + else + cell->fetchChild("leader")->show(); + + List drawables = member.portrait; + Drawable::scaleAll(drawables, portraitScale); + cell->fetchChild("portrait")->setDrawables(move(drawables)); + + if (member.world == m_client->playerWorld() && m_client->worldClient()) { + auto mpos = member.position; + if (auto entity = m_client->worldClient()->entity(member.entity)) + mpos = entity->position(); + auto direction = m_client->worldClient()->geometry().diff(mpos, player->position()); + + auto compassImage = cell->fetchChild("compass"); + compassImage->setRotation(direction.angle() - Constants::pi / 2.0f); + compassImage->show(); + cell->fetchChild("compassoffworld")->hide(); + } else { + cell->fetchChild("compass")->hide(); + cell->fetchChild("compassoffworld")->show(); + } + + cell->fetchChild("healthBar")->setCurrentProgressLevel(member.healthPercentage); + cell->fetchChild("energyBar")->setCurrentProgressLevel(member.energyPercentage); + + offset[1] -= memberSpacing; + controlIndex++; + memberIndex++; + } + + auto inviteButton = fetchChild("inviteButton"); + auto noInviteImage = fetchChild("noInviteImage"); + + Vec2I inviteOffset = list->position() + offset; + inviteButton->setPosition(inviteOffset - Vec2I{0, inviteButton->size()[1]}); + noInviteImage->setPosition(inviteOffset - Vec2I{0, noInviteImage->size()[1]}); + + bool couldInvite = (!teamClient->currentTeam() || teamClient->isTeamLeader()) + && m_client->teamClient()->members().size() < Root::singleton().configuration()->get("maxTeamSize").toUInt(); + inviteButton->setVisibility(couldInvite); + inviteButton->setEnabled(!m_teamInvitation->active()); + noInviteImage->setVisibility(!couldInvite); + + while (true) { + String cellName = strf("%s", controlIndex); + WidgetPtr cell = list->fetchChild(cellName); + if (!cell) + break; + cell->hide(); + controlIndex++; + } +} + +void TeamBar::showMemberMenu(Uuid memberUuid, Vec2I position) { + m_teamMemberMenu->open(memberUuid, position); + if (!m_teamMemberMenu->isDisplayed()) + m_mainInterface->paneManager()->displayPane(PaneLayer::Window, m_teamMemberMenu); +} + +TeamInvite::TeamInvite(TeamBar* owner) { + m_owner = owner; + GuiReader reader; + auto assets = Root::singleton().assets(); + reader.registerCallback("ok", [this](Widget*) { ok(); }); + reader.registerCallback("close", [this](Widget*) { close(); }); + reader.registerCallback("name", [](Widget*) {}); + reader.construct(assets->json("/interface/windowconfig/teaminvite.config:paneLayout"), this); + dismiss(); +} + +void TeamInvite::show() { + Pane::show(); + fetchChild("name")->setText("", false); + fetchChild("name")->focus(); +} + +void TeamInvite::ok() { + m_owner->invitePlayer(fetchChild("name")->getText()); + dismiss(); +} + +void TeamInvite::close() { + dismiss(); +} + +TeamInvitation::TeamInvitation(TeamBar* owner) { + m_owner = owner; + GuiReader reader; + auto assets = Root::singleton().assets(); + + reader.registerCallback("ok", [this](Widget*) { ok(); }); + reader.registerCallback("close", [this](Widget*) { close(); }); + + reader.construct(assets->json("/interface/windowconfig/teaminvitation.config:paneLayout"), this); + dismiss(); +} + +void TeamInvitation::open(Uuid const& inviterUuid, String const& inviterName) { + if (active()) + return; + m_inviterUuid = inviterUuid; + fetchChild("inviterName")->setText(inviterName); + Pane::show(); +} + +void TeamInvitation::ok() { + m_owner->acceptInvitation(m_inviterUuid); + dismiss(); +} + +void TeamInvitation::close() { + dismiss(); +} + +TeamMemberMenu::TeamMemberMenu(TeamBar* owner) { + m_owner = owner; + + auto assets = Root::singleton().assets(); + GuiReader reader; + reader.registerCallback("beamToShip", [this](Widget*) { beamToShip(); }); + reader.registerCallback("close", [this](Widget*) { close(); }); + reader.registerCallback("makeLeader", [this](Widget*) { makeLeader(); }); + reader.registerCallback("removeFromTeam", [this](Widget*) { removeFromTeam(); }); + reader.construct(assets->json("/interface/windowconfig/teammembermenu.config:paneLayout"), this); +} + +void TeamMemberMenu::open(Uuid memberUuid, Vec2I position) { + if (active()) + return; + + auto assets = Root::singleton().assets(); + + setPosition(position); + + m_memberUuid = memberUuid; + auto members = m_owner->m_client->teamClient()->members(); + for (auto member : members) { + if (member.uuid == m_memberUuid) { + fetchChild("name")->setText(member.name); + break; + } + } + + updateWidgets(); + + Pane::show(); +} + +void TeamMemberMenu::update() { + auto stillValid = false; + auto members = m_owner->m_client->teamClient()->members(); + for (auto member : members) { + if (member.uuid == m_memberUuid) { + stillValid = true; + m_canBeam = member.warpMode != WarpMode::None && m_owner->m_client->canBeamToTeamShip(); + } + } + + if (!stillValid) { + close(); + return; + } + + updateWidgets(); + + Pane::update(); +} + +void TeamMemberMenu::updateWidgets() { + bool isLeader = m_owner->m_client->teamClient()->isTeamLeader(); + bool isSelf = m_owner->m_client->mainPlayer()->uuid() == m_memberUuid; + + fetchChild("beamToShip")->setEnabled(m_canBeam); + fetchChild("makeLeader")->setEnabled(isLeader && !isSelf); + fetchChild("removeFromTeam")->setEnabled(isLeader || isSelf); + + auto assets = Root::singleton().assets(); + if (isSelf) + fetchChild("removeFromTeam")->setText(assets->json("/interface/windowconfig/teammembermenu.config:removeSelfText").toString()); + else + fetchChild("removeFromTeam")->setText(assets->json("/interface/windowconfig/teammembermenu.config:removeOtherText").toString()); +} + +void TeamMemberMenu::beamToShip() { + if (m_canBeam) + m_owner->m_mainInterface->warpTo(WarpToWorld{ClientShipWorldId(m_memberUuid), {}}); + dismiss(); +} + +void TeamMemberMenu::close() { + dismiss(); +} + +void TeamMemberMenu::makeLeader() { + m_owner->m_client->teamClient()->makeLeader(m_memberUuid); + dismiss(); +} + +void TeamMemberMenu::removeFromTeam() { + m_owner->m_client->teamClient()->removeFromTeam(m_memberUuid); + dismiss(); +} + +} -- cgit v1.2.3