mirror of
https://github.com/risingPhil/PokeMe64.git
synced 2026-03-21 18:04:15 -05:00
Work on ScrollWidget (Work In Progress/Incomplete)
This commit is contained in:
parent
9313571610
commit
65a59d050e
|
|
@ -2,8 +2,16 @@
|
|||
#define _TESTSCENE_H
|
||||
|
||||
#include "scenes/AbstractUIScene.h"
|
||||
#include "core/RDPQGraphics.h"
|
||||
#include "core/Sprite.h"
|
||||
#include "widget/ScrollWidget.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class ImageWidget;
|
||||
class TextWidget;
|
||||
|
||||
typedef std::vector<IWidget*> WidgetList;
|
||||
|
||||
|
||||
class TestScene : public AbstractUIScene
|
||||
{
|
||||
|
|
@ -17,20 +25,11 @@ public:
|
|||
void render(RDPQGraphics& gfx, const Rectangle& sceneBounds) override;
|
||||
protected:
|
||||
private:
|
||||
rdpq_font_t* arialFont_;
|
||||
uint8_t arialFontId_;
|
||||
uint8_t fontStyleWhite_;
|
||||
ScrollWidget scrollWidget_;
|
||||
WidgetFocusChainSegment scrollWidgetFocusSegment_;
|
||||
WidgetList widgets_;
|
||||
sprite_t* pokeballSprite_;
|
||||
sprite_t* oakSprite_;
|
||||
sprite_t* menu9SliceSprite_;
|
||||
const Rectangle rectBounds_;
|
||||
const Rectangle textRect_;
|
||||
const Rectangle spriteBounds_;
|
||||
Rectangle oakBounds_;
|
||||
Rectangle oakSrcBounds_;
|
||||
const Rectangle menuBounds_;
|
||||
TextRenderSettings textRenderSettings_;
|
||||
const SpriteRenderSettings menuRenderSettings_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -12,6 +12,7 @@ class RDPQGraphics;
|
|||
class IWidget
|
||||
{
|
||||
public:
|
||||
virtual ~IWidget(){}
|
||||
/**
|
||||
* @brief Returns whether the widget is currently focused
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -33,9 +33,12 @@ public:
|
|||
uint32_t getDurationInMs() const override;
|
||||
|
||||
void start(const Point& startPoint, const Point& endPoint);
|
||||
void extend(const Point& endPoint);
|
||||
protected:
|
||||
void apply(float pos) override;
|
||||
private:
|
||||
Point calculatePoint(float pos);
|
||||
|
||||
ScrollWidget* list_;
|
||||
Point windowStartPoint_;
|
||||
Point windowEndPoint_;
|
||||
|
|
@ -69,6 +72,7 @@ public:
|
|||
|
||||
void addWidget(IWidget* widget);
|
||||
void removeWidget(IWidget* widget);
|
||||
void clearWidgets();
|
||||
|
||||
bool handleUserInput(const joypad_inputs_t& userInput) override;
|
||||
void render(RDPQGraphics& gfx, const Rectangle& parentBounds) override;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
#include "scenes/TestScene.h"
|
||||
#include "core/RDPQGraphics.h"
|
||||
#include "core/FontManager.h"
|
||||
#include "widget/ImageWidget.h"
|
||||
#include "widget/TextWidget.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <n64sys.h>
|
||||
|
||||
static const char* tvtypeToString(tv_type_t type)
|
||||
|
|
@ -21,23 +23,13 @@ static const char* tvtypeToString(tv_type_t type)
|
|||
|
||||
TestScene::TestScene(SceneDependencies& deps, void*)
|
||||
: AbstractUIScene(deps)
|
||||
, arialFont_(nullptr)
|
||||
, arialFontId_(1)
|
||||
, fontStyleWhite_(0)
|
||||
, scrollWidget_(deps.animationManager)
|
||||
, scrollWidgetFocusSegment_({
|
||||
.current = &scrollWidget_
|
||||
})
|
||||
, widgets_()
|
||||
, pokeballSprite_(nullptr)
|
||||
, oakSprite_(nullptr)
|
||||
, menu9SliceSprite_(nullptr)
|
||||
, rectBounds_({0, 0, 320, 240})
|
||||
, textRect_({70, 70, 180, 60})
|
||||
, spriteBounds_({320 - 128, 0, 128, 128})
|
||||
, oakBounds_({0})
|
||||
, oakSrcBounds_({0})
|
||||
, menuBounds_({ 100, 20, 100, 100})
|
||||
, textRenderSettings_({})
|
||||
, menuRenderSettings_({
|
||||
.renderMode = SpriteRenderMode::NINESLICE,
|
||||
.srcRect = { 6, 6, 6, 6 }
|
||||
})
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -47,47 +39,129 @@ TestScene::~TestScene()
|
|||
|
||||
void TestScene::init()
|
||||
{
|
||||
arialFont_ = rdpq_font_load("rom://Arial.font64");
|
||||
rdpq_fontstyle_t arialWhiteFontStyle = {
|
||||
.color = RGBA32(0xFF, 0xFF, 0xFF, 0xFF)
|
||||
};
|
||||
rdpq_font_style(arialFont_, fontStyleWhite_, &arialWhiteFontStyle);
|
||||
|
||||
// TODO: this is a problem: there's no way to unregister a font.
|
||||
// Therefore if we'd load the same font > 1 times, we'll get a crash (due to assert)
|
||||
// We'll need to create a FontManager class to handle this
|
||||
rdpq_text_register_font(arialFontId_, arialFont_);
|
||||
textRenderSettings_.fontId = arialFontId_;
|
||||
|
||||
uint8_t widgetType;
|
||||
const uint8_t fontId = deps_.fontManager.getFont("rom://Arial.font64");
|
||||
pokeballSprite_ = sprite_load("rom:/pokeball.sprite");
|
||||
oakSprite_ = sprite_load("rom://oak.sprite");
|
||||
menu9SliceSprite_ = sprite_load("rom://menu-bg-9slice.sprite");
|
||||
|
||||
oakBounds_ ={10, 80, oakSprite_->width, oakSprite_->height};
|
||||
oakSrcBounds_ = {oakSprite_->width / 3, oakSprite_->height / 3, oakSprite_->width * 2 / 3, oakSprite_->height * 2 / 3};
|
||||
debugf("Hello Phil! Your tv type is: %s\r\n", tvtypeToString(get_tv_type()));
|
||||
|
||||
printf("Hello Phil! Your tv type is: %s\n", tvtypeToString(get_tv_type()));
|
||||
const ScrollWidgetStyle scrollStyle = {
|
||||
.scrollStep = 10
|
||||
};
|
||||
|
||||
scrollWidget_.setBounds(Rectangle{0, 0, 320, 240});
|
||||
scrollWidget_.setStyle(scrollStyle);
|
||||
scrollWidget_.setFocused(true);
|
||||
setFocusChain(&scrollWidgetFocusSegment_);
|
||||
|
||||
const Dimensions textDimensions = {.width = 50, .height = 16};
|
||||
const Dimensions oakDimensions = {.width = oakSprite_->width, .height = oakSprite_->height };
|
||||
const Dimensions pokeballDimensions = {.width = pokeballSprite_->width, .height = pokeballSprite_->height};
|
||||
|
||||
TextWidgetStyle type1Style = {
|
||||
.size = {textDimensions.width, textDimensions.height},
|
||||
.renderSettingsNotFocused = {
|
||||
.fontId = fontId
|
||||
}
|
||||
};
|
||||
|
||||
ImageWidgetStyle type2Style = {
|
||||
.size = oakDimensions,
|
||||
.image = {
|
||||
.sprite = oakSprite_,
|
||||
.spriteBounds = {0, 0, oakDimensions.width, oakDimensions.height}
|
||||
}
|
||||
};
|
||||
|
||||
ImageWidgetStyle type3Style = {
|
||||
.size = pokeballDimensions,
|
||||
.image = {
|
||||
.sprite = pokeballSprite_,
|
||||
.spriteBounds = {0, 0, pokeballDimensions.width, pokeballDimensions.height}
|
||||
}
|
||||
};
|
||||
|
||||
int curXPos = 0;
|
||||
int curYPos = 0;
|
||||
int nextYPos = 0;
|
||||
for(uint8_t i=0; i < 6; ++i)
|
||||
{
|
||||
for(uint8_t j=0; j < 6; ++j)
|
||||
{
|
||||
widgetType = (j % 3);
|
||||
|
||||
switch(widgetType)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
TextWidget* textWidget = new TextWidget();
|
||||
textWidget->setStyle(type1Style);
|
||||
textWidget->setBounds(Rectangle{curXPos, curYPos, textDimensions.width, textDimensions.height});
|
||||
textWidget->setData("Hello!");
|
||||
scrollWidget_.addWidget(textWidget);
|
||||
widgets_.push_back(textWidget);
|
||||
curXPos += textDimensions.width;
|
||||
if(curYPos + textDimensions.height > nextYPos)
|
||||
{
|
||||
nextYPos = curYPos + textDimensions.height;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
ImageWidget* imageWidget = new ImageWidget();
|
||||
imageWidget->setStyle(type2Style);
|
||||
imageWidget->setBounds(Rectangle{curXPos, curYPos, oakDimensions.width, oakDimensions.height});
|
||||
scrollWidget_.addWidget(imageWidget);
|
||||
widgets_.push_back(imageWidget);
|
||||
curXPos += oakDimensions.width;
|
||||
if(curYPos + oakDimensions.height > nextYPos)
|
||||
{
|
||||
nextYPos = curYPos + oakDimensions.height;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
ImageWidget* imageWidget = new ImageWidget();
|
||||
imageWidget->setStyle(type3Style);
|
||||
imageWidget->setBounds(Rectangle{curXPos, curYPos, pokeballDimensions.width, pokeballDimensions.height});
|
||||
scrollWidget_.addWidget(imageWidget);
|
||||
widgets_.push_back(imageWidget);
|
||||
curXPos += pokeballDimensions.width;
|
||||
if(curYPos + pokeballDimensions.height > nextYPos)
|
||||
{
|
||||
nextYPos = curYPos + pokeballDimensions.height;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
curYPos = nextYPos;
|
||||
curXPos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TestScene::destroy()
|
||||
{
|
||||
sprite_free(menu9SliceSprite_);
|
||||
menu9SliceSprite_ = nullptr;
|
||||
scrollWidget_.clearWidgets();
|
||||
for(IWidget* widget : widgets_)
|
||||
{
|
||||
delete widget;
|
||||
}
|
||||
widgets_.clear();
|
||||
|
||||
sprite_free(oakSprite_);
|
||||
oakSprite_ = nullptr;
|
||||
|
||||
sprite_free(pokeballSprite_);
|
||||
pokeballSprite_ = nullptr;
|
||||
|
||||
rdpq_font_free(arialFont_);
|
||||
}
|
||||
|
||||
void TestScene::render(RDPQGraphics& gfx, const Rectangle& /*sceneBounds*/)
|
||||
void TestScene::render(RDPQGraphics& gfx, const Rectangle& sceneBounds)
|
||||
{
|
||||
// gfx.fillRectangle(rectBounds_, RGBA32(200, 0, 0, 0));
|
||||
// gfx.drawText(textRect_, "Hello Phil!", textRenderSettings_);
|
||||
// gfx.drawSprite(spriteBounds_, pokeballSprite_, SpriteRenderSettings());
|
||||
// gfx.drawSprite(oakBounds_, oakSprite_, {.srcRect = oakSrcBounds_});
|
||||
gfx.drawSprite(menuBounds_, menu9SliceSprite_, menuRenderSettings_);
|
||||
scrollWidget_.render(gfx, sceneBounds);
|
||||
}
|
||||
|
|
@ -110,15 +110,28 @@ uint32_t MoveScrollWidgetWindowAnimation::getDurationInMs() const
|
|||
|
||||
void MoveScrollWidgetWindowAnimation::start(const Point& startPoint, const Point& endPoint)
|
||||
{
|
||||
currentTimePos_ = 0.f;
|
||||
windowStartPoint_ = startPoint;
|
||||
windowEndPoint_ = endPoint;
|
||||
}
|
||||
|
||||
void MoveScrollWidgetWindowAnimation::extend(const Point& endPoint)
|
||||
{
|
||||
const Point currentPoint = calculatePoint(currentTimePos_);
|
||||
start(currentPoint, endPoint);
|
||||
}
|
||||
|
||||
void MoveScrollWidgetWindowAnimation::apply(float pos)
|
||||
{
|
||||
const Point newWindowStart = calculatePoint(pos);
|
||||
list_->setWindowStart(newWindowStart);
|
||||
}
|
||||
|
||||
Point MoveScrollWidgetWindowAnimation::calculatePoint(float pos)
|
||||
{
|
||||
const int px = static_cast<int>(ceil(windowStartPoint_.x + (pos * (windowEndPoint_.x - windowStartPoint_.x))));
|
||||
const int py = static_cast<int>(ceil(windowStartPoint_.y + (pos * (windowEndPoint_.y - windowStartPoint_.y))));
|
||||
list_->setWindowStart(Point{px, py});
|
||||
return Point{px, py};
|
||||
}
|
||||
|
||||
ScrollWidget::ScrollWidget(AnimationManager& animManager)
|
||||
|
|
@ -195,6 +208,12 @@ void ScrollWidget::removeWidget(IWidget* widget)
|
|||
recalculateWindowSize();
|
||||
}
|
||||
|
||||
void ScrollWidget::clearWidgets()
|
||||
{
|
||||
widgets_.clear();
|
||||
windowBounds_ = {0};
|
||||
}
|
||||
|
||||
bool ScrollWidget::handleUserInput(const joypad_inputs_t& userInput)
|
||||
{
|
||||
if(!focused_ || style_.scrollStep == 0)
|
||||
|
|
@ -203,21 +222,25 @@ bool ScrollWidget::handleUserInput(const joypad_inputs_t& userInput)
|
|||
}
|
||||
|
||||
const FloatVector scrollDirection = determineScrollDirection(userInput);
|
||||
// debugf("[ScrollWidget]: %s: scrollDirection [%f, %f]\r\n", __FUNCTION__, scrollDirection.x, scrollDirection.y);
|
||||
if(scrollDirection.x == 0.f && scrollDirection.y == 0.f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(!windowAnimation_.isFinished())
|
||||
{
|
||||
windowAnimation_.skipToEnd();
|
||||
}
|
||||
|
||||
const Point windowStartPoint = {.x = windowBounds_.x, .y = windowBounds_.y};
|
||||
Point windowEndPoint = {.x = windowBounds_.x, .y = windowBounds_.y};
|
||||
|
||||
windowEndPoint.x += static_cast<int>(ceil(scrollDirection.x * style_.scrollStep));
|
||||
windowEndPoint.y += static_cast<int>(ceil(scrollDirection.y * style_.scrollStep));
|
||||
windowAnimation_.start(windowStartPoint, windowEndPoint);
|
||||
|
||||
if(!windowAnimation_.isFinished())
|
||||
{
|
||||
windowAnimation_.extend(windowEndPoint);
|
||||
}
|
||||
else
|
||||
{
|
||||
const Point windowStartPoint = {.x = windowBounds_.x, .y = windowBounds_.y};
|
||||
windowAnimation_.start(windowStartPoint, windowEndPoint);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user