#include "Runtime/GuiSys/CGuiTableGroup.hpp" #include "Runtime/Input/CFinalInput.hpp" namespace metaforce { bool CGuiTableGroup::CRepeatState::Update(float dt, bool state) { if (x0_timer == 0.f) { if (state) { x0_timer = 0.6f; return true; } } else { if (state) { x0_timer -= dt; if (x0_timer <= 0.f) { x0_timer = 0.05f; return true; } } else { x0_timer = 0.f; } } return false; } CGuiTableGroup::CGuiTableGroup(const CGuiWidgetParms& parms, int elementCount, int defaultSel, bool selectWraparound) : CGuiCompoundWidget(parms) , xc0_elementCount(elementCount) , xc4_userSelection(defaultSel) , xc8_prevUserSelection(defaultSel) , xcc_defaultUserSelection(defaultSel) , xd0_selectWraparound(selectWraparound) {} void CGuiTableGroup::ProcessUserInput(const CFinalInput& input) { if (input.PA() || input.PSpecialKey(boo::ESpecialKey::Enter)) { DoAdvance(); } else if (input.PB() || input.PSpecialKey(boo::ESpecialKey::Esc)) { DoCancel(); } else { bool decrement; if (xd1_vertical) decrement = (input.DLAUp() || input.DDPUp()); else decrement = (input.DLALeft() || input.DDPLeft()); bool increment; if (xd1_vertical) increment = (input.DLADown() || input.DDPDown()); else increment = (input.DLARight() || input.DDPRight()); if (xb8_decRepeat.Update(input.DeltaTime(), decrement) && decrement) { DoDecrement(); return; } if (xbc_incRepeat.Update(input.DeltaTime(), increment) && increment) { DoIncrement(); return; } } } bool CGuiTableGroup::IsWorkerSelectable(int idx) const { if (CGuiWidget* widget = GetWorkerWidget(idx)) return widget->GetIsSelectable(); return false; } void CGuiTableGroup::SelectWorker(int idx) { idx = zeus::clamp(0, idx, xc0_elementCount - 1); if (idx < xc4_userSelection) { while (idx != xc4_userSelection) DoSelectPrevRow(); } else { while (idx != xc4_userSelection) DoSelectNextRow(); } } void CGuiTableGroup::DoSelectWorker(int worker) { if (worker == xc4_userSelection) return; if (IsWorkerSelectable(worker)) { int oldSel = xc4_userSelection; SelectWorker(worker); if (x104_doMenuSelChange) x104_doMenuSelChange(this, oldSel); } } void CGuiTableGroup::SetWorkersMouseActive(bool active) { CGuiWidget* child = static_cast(GetChildObject()); while (child) { if (child->GetWorkerId() != -1) child->SetMouseActive(active); child = static_cast(child->GetNextSibling()); } } void CGuiTableGroup::DeactivateWorker(CGuiWidget* widget) { widget->SetIsActive(false); } void CGuiTableGroup::ActivateWorker(CGuiWidget* widget) { widget->SetIsActive(true); } CGuiTableGroup::TableSelectReturn CGuiTableGroup::DecrementSelectedRow() { xc8_prevUserSelection = xc4_userSelection; --xc4_userSelection; if (xc4_userSelection < 0) { xc4_userSelection = xd0_selectWraparound ? xc0_elementCount - 1 : 0; return xd0_selectWraparound ? TableSelectReturn::WrappedAround : TableSelectReturn::Unchanged; } return TableSelectReturn::Changed; } CGuiTableGroup::TableSelectReturn CGuiTableGroup::IncrementSelectedRow() { xc8_prevUserSelection = xc4_userSelection; ++xc4_userSelection; if (xc4_userSelection >= xc0_elementCount) { xc4_userSelection = xd0_selectWraparound ? 0 : xc0_elementCount - 1; return xd0_selectWraparound ? TableSelectReturn::WrappedAround : TableSelectReturn::Unchanged; } return TableSelectReturn::Changed; } void CGuiTableGroup::DoSelectPrevRow() { DecrementSelectedRow(); DeactivateWorker(GetWorkerWidget(xc8_prevUserSelection)); ActivateWorker(GetWorkerWidget(xc4_userSelection)); } void CGuiTableGroup::DoSelectNextRow() { IncrementSelectedRow(); DeactivateWorker(GetWorkerWidget(xc8_prevUserSelection)); ActivateWorker(GetWorkerWidget(xc4_userSelection)); } void CGuiTableGroup::DoCancel() { if (xec_doMenuCancel) xec_doMenuCancel(this); } void CGuiTableGroup::DoAdvance() { if (xd4_doMenuAdvance) xd4_doMenuAdvance(this); } bool CGuiTableGroup::PreDecrement() { if (xd0_selectWraparound) { for (int sel = (xc4_userSelection + xc0_elementCount - 1) % xc0_elementCount; sel != xc4_userSelection; sel = (sel + xc0_elementCount - 1) % xc0_elementCount) { if (IsWorkerSelectable(sel)) { SelectWorker(sel); return true; } } } else { for (int sel = std::max(-1, xc4_userSelection - 1); sel >= 0; --sel) { if (IsWorkerSelectable(sel)) { SelectWorker(sel); return true; } } } return false; } void CGuiTableGroup::DoDecrement() { int oldSel = xc4_userSelection; if (!PreDecrement()) return; if (x104_doMenuSelChange) x104_doMenuSelChange(this, oldSel); } bool CGuiTableGroup::PreIncrement() { if (xd0_selectWraparound) { for (int sel = (xc4_userSelection + 1) % xc0_elementCount; sel != xc4_userSelection; sel = (sel + 1) % xc0_elementCount) { if (IsWorkerSelectable(sel)) { SelectWorker(sel); return true; } } } else { for (int sel = std::min(xc0_elementCount, xc4_userSelection + 1); sel < xc0_elementCount; ++sel) { if (IsWorkerSelectable(sel)) { SelectWorker(sel); return true; } } } return false; } void CGuiTableGroup::DoIncrement() { int oldSel = xc4_userSelection; if (!PreIncrement()) return; if (x104_doMenuSelChange) x104_doMenuSelChange(this, oldSel); } std::shared_ptr CGuiTableGroup::Create(CGuiFrame* frame, CInputStream& in, CSimplePool* sp) { CGuiWidgetParms parms = ReadWidgetHeader(frame, in); int elementCount = in.readInt16Big(); in.readInt16Big(); in.readUint32Big(); int defaultSel = in.readInt16Big(); in.readInt16Big(); bool selectWraparound = in.readBool(); in.readBool(); in.readFloatBig(); in.readFloatBig(); in.readBool(); in.readFloatBig(); in.readInt16Big(); in.readInt16Big(); in.readInt16Big(); in.readInt16Big(); std::shared_ptr ret = std::make_shared(parms, elementCount, defaultSel, selectWraparound); ret->ParseBaseInfo(frame, in, parms); return ret; } } // namespace metaforce