Implement States for ControlGuide.

This commit is contained in:
J-D-K 2025-11-15 11:49:00 -05:00
parent 785b51c455
commit 30ffa86b65
2 changed files with 71 additions and 11 deletions

View File

@ -31,6 +31,15 @@ namespace ui
void reset() noexcept;
private:
/// @brief States the guide can be in.
enum class State : uint8_t
{
Opening,
Opened,
Hiding,
Hidden
};
/// @brief Stores the pointer to the guide string.
const char *m_guide{};
@ -46,10 +55,19 @@ namespace ui
/// @brief Transition for the guide string.
ui::Transition m_transition{};
/// @brief Current state of the control guide.
ControlGuide::State m_state{};
/// @brief This is shared by all instances.
static inline sdl::SharedTexture sm_controlCap{};
/// @brief Ensures the control guide cap is loaded for all instances.
void initialize_static_members();
/// @brief Updates the position of the guide.
void update_position_state() noexcept;
/// @brief Updates the current state of the control guide.
void update_state(bool hasFocus) noexcept;
};
}

View File

@ -14,6 +14,9 @@ namespace
/// @brief This is the constant Y of the transition.
constexpr int TRANS_Y = 662;
/// @brief The padding for the control guide container.
constexpr int CONTAINER_PADDING = 24;
}
// ---- Construction ----
@ -21,9 +24,10 @@ namespace
ui::ControlGuide::ControlGuide(const char *guide)
: m_guide(guide)
, m_textWidth(sdl::text::get_width(GUIDE_TEXT_SIZE, m_guide))
, m_targetX(GUIDE_X_OFFSET - (m_textWidth + 24))
, m_targetX(GUIDE_X_OFFSET - (m_textWidth + CONTAINER_PADDING))
, m_guideWidth(graphics::SCREEN_WIDTH - m_targetX)
, m_transition(graphics::SCREEN_WIDTH, TRANS_Y, 0, 0, m_targetX, TRANS_Y, 0, 0, ui::Transition::DEFAULT_THRESHOLD)
, m_state(State::Opening)
{
ui::ControlGuide::initialize_static_members();
}
@ -32,33 +36,36 @@ ui::ControlGuide::ControlGuide(const char *guide)
void ui::ControlGuide::update(bool hasFocus)
{
m_transition.update();
if (!m_transition.in_place()) { return; }
const int targetX = m_transition.get_target_x();
if (hasFocus && targetX != m_targetX) { m_transition.set_target_x(m_targetX); }
switch (m_state)
{
case State::Opening:
case State::Hiding: ControlGuide::update_position_state(); break;
default: ControlGuide::update_state(hasFocus); break;
}
}
void ui::ControlGuide::sub_update()
{
const int targetX = m_transition.get_target_x();
if (targetX != graphics::SCREEN_WIDTH) { m_transition.set_target_x(graphics::SCREEN_WIDTH); }
m_transition.update();
// To do: Maybe this differently?
ControlGuide::update(false);
}
void ui::ControlGuide::render(sdl::SharedTexture &target, bool hasFocus)
{
// These are for the rectangle that makes up the rest of the container.
static constexpr int RECT_OFFSET_X = 16;
static constexpr int RECT_HEIGHT = 48;
// This is where the text is rendered and its size.
static constexpr int TEXT_OFFSET_X = 24;
static constexpr int TEXT_OFFSET_Y = 10;
static constexpr int TEXT_FONT_SIZE = 24;
// Grab the X and Y.
const int guideX = m_transition.get_x();
const int guideY = m_transition.get_y();
// Render the cap and the rectangle.
sm_controlCap->render(sdl::Texture::Null, guideX, guideY);
sdl::render_rect_fill(sdl::Texture::Null,
guideX + RECT_OFFSET_X,
@ -66,6 +73,8 @@ void ui::ControlGuide::render(sdl::SharedTexture &target, bool hasFocus)
m_guideWidth - RECT_OFFSET_X,
RECT_HEIGHT,
colors::GUIDE_COLOR);
// Guide text.
sdl::text::render(sdl::Texture::Null,
guideX + TEXT_OFFSET_X,
guideY + TEXT_OFFSET_Y,
@ -79,15 +88,48 @@ void ui::ControlGuide::render(sdl::SharedTexture &target, bool hasFocus)
void ui::ControlGuide::initialize_static_members()
{
// Name for the texture manager.
static constexpr std::string_view NAME_CAP = "ControlGuideCap";
// If it's already loaded, return.
if (sm_controlCap) { return; }
sm_controlCap = sdl::TextureManager::load(NAME_CAP, "romfs:/Textures/GuideCap.png");
}
void ui::ControlGuide::reset() noexcept
{
// Set both to the width of the screen.
m_transition.set_target_x(graphics::SCREEN_WIDTH);
m_transition.set_x(graphics::SCREEN_WIDTH);
}
void ui::ControlGuide::update_position_state() noexcept
{
// Update the transition.
m_transition.update();
// State conditions.
const bool opened = m_state == State::Opening && m_transition.in_place_xy();
const bool hidden = m_state == State::Hiding && m_transition.in_place_xy();
if (opened) { m_state = State::Opened; }
else if (hidden) { m_state = State::Hidden; }
}
void ui::ControlGuide::update_state(bool hasFocus) noexcept
{
// Conditions.
const bool hide = (m_state == State::Opening || m_state == State::Opened) && !hasFocus;
const bool unhide = (m_state == State::Hiding || m_state == State::Hidden) && hasFocus;
if (hide)
{
// Set target to screen width.
m_transition.set_target_x(graphics::SCREEN_WIDTH);
m_state = State::Hiding;
}
else if (unhide)
{
// Set target to open.
m_transition.set_target_x(m_targetX);
m_state = State::Opening;
}
}