PokeMe64/include/widget/PokemonPartyIconWidget.h
2024-11-25 16:42:38 +01:00

161 lines
4.5 KiB
C++

#ifndef _POKEMONPARTYICONWIDGET_H
#define _POKEMONPARTYICONWIDGET_H
#include "widget/IWidget.h"
#include "core/Sprite.h"
#include "gen1/Gen1Common.h"
#include "gen2/Gen2Common.h"
class IRomReader;
class ISaveManager;
/**
* This factory class provides a function to obtain a surface_t instance for a given icon.
* It acts as a form of cache to prevent decoding/allocating the same icon more than once if multiple
* instances of PokemonPartyIconWidget are created.
*/
class PokemonPartyIconFactory
{
public:
typedef struct IconMapEntry
{
surface_t frame1;
surface_t frame2;
} IconMapEntry;
PokemonPartyIconFactory(IRomReader& romReader);
~PokemonPartyIconFactory();
surface_t getIcon(uint8_t generation, uint8_t specificGenType, uint8_t localization, uint8_t iconType, bool firstFrame);
protected:
private:
// This is the map of icons. Gen2 has the most icons, that's why I'm using GEN2_ICONTYPE_MAX as the array size
IconMapEntry iconMap_[(unsigned)Gen2PokemonIconType::GEN2_ICONTYPE_MAX];
IRomReader& romReader_;
};
typedef struct PokemonPartyIconWidgetStyle
{
struct {
/**
* (optional) background sprite
*/
sprite_t* sprite;
/*
* RenderSettings that influence how the backgroundSprite is
* being rendered
*/
SpriteRenderSettings spriteSettings;
} background;
struct {
Rectangle bounds;
int8_t yOffsetWhenTheresNoFrame2;
} icon;
uint8_t fpsWhenFocused;
uint8_t fpsWhenNotFocused;
} PokemonPartyIconWidgetStyle;
typedef struct PokemonPartyIconWidgetData
{
PokemonPartyIconFactory* iconFactory;
/**
* The generation of the pokemon game (gen 1/2)
*/
uint8_t generation;
/**
* The specific variant of the game
*/
uint8_t specificGenVersion;
/**
* @brief The specific localization of the game
*/
uint8_t localization;
/**
* The pokemon icon type we need to display
*/
uint8_t iconType;
} PokemonPartyIconWidgetData;
class PokemonPartyIconWidget : public IWidget
{
public:
PokemonPartyIconWidget();
virtual ~PokemonPartyIconWidget();
void setStyle(const PokemonPartyIconWidgetStyle& style);
void setData(const PokemonPartyIconWidgetData& data);
/**
* @brief Returns whether the widget is currently focused
*/
bool isFocused() const override;
/**
* @brief Sets whether the widget is currently focused
*
*/
void setFocused(bool isFocused) override;
/**
* @brief Returns whether the widget is currently visible
*/
bool isVisible() const override;
/**
* @brief Changes the visibility of the widget
*/
void setVisible(bool visible) override;
/**
* @brief Returns the current (relative) bounds of the widget
*/
Rectangle getBounds() const override;
/**
* @brief Changes the current (relative) bounds of the widget
*/
void setBounds(const Rectangle& bounds) override;
/**
* @brief Returns the size (width/height) of the widget
*/
Dimensions getSize() const override;
/**
* @brief Handles user input
*
* For button presses, it is advised to track button release situations instead of
* button presses for executing an action. Otherwise the key press might be handled again immediately
* in the next scene/widget because the user wouldn't have had the time to actually release the key.
*/
bool handleUserInput(const joypad_inputs_t& userInput) override;
/**
* @brief Renders the widget
*
* @param gfx The graphics instance that must be used to render the widget
* @param parentBounds The bounds of the parent widget or scene. You must add the x,y offset of your own bounds
* to the parentBounds to get the absolute bounds for rendering.
*
* Getting the parentBounds as an argument of this function was done because a parent widget may be
* animated or change positions independent of the child widget. But when the parent widget moves, the child must as well!
*/
void render(RDPQGraphics& gfx, const Rectangle& parentBounds) override;
protected:
private:
void reset();
PokemonPartyIconWidgetStyle style_;
PokemonPartyIconWidgetData data_;
surface_t iconFrame1_;
surface_t iconFrame2_;
Rectangle bounds_;
uint32_t frameSwitchTimeoutInTicks_;
uint64_t nextFrameSwitchTime_;
bool focused_;
bool visible_;
bool showFirstIconFrame_;
};
#endif