mirror of
https://github.com/risingPhil/PokeMe64.git
synced 2026-04-26 08:03:31 -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
|
#define _TESTSCENE_H
|
||||||
|
|
||||||
#include "scenes/AbstractUIScene.h"
|
#include "scenes/AbstractUIScene.h"
|
||||||
#include "core/RDPQGraphics.h"
|
|
||||||
#include "core/Sprite.h"
|
#include "core/Sprite.h"
|
||||||
|
#include "widget/ScrollWidget.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class ImageWidget;
|
||||||
|
class TextWidget;
|
||||||
|
|
||||||
|
typedef std::vector<IWidget*> WidgetList;
|
||||||
|
|
||||||
|
|
||||||
class TestScene : public AbstractUIScene
|
class TestScene : public AbstractUIScene
|
||||||
{
|
{
|
||||||
|
|
@ -17,20 +25,11 @@ public:
|
||||||
void render(RDPQGraphics& gfx, const Rectangle& sceneBounds) override;
|
void render(RDPQGraphics& gfx, const Rectangle& sceneBounds) override;
|
||||||
protected:
|
protected:
|
||||||
private:
|
private:
|
||||||
rdpq_font_t* arialFont_;
|
ScrollWidget scrollWidget_;
|
||||||
uint8_t arialFontId_;
|
WidgetFocusChainSegment scrollWidgetFocusSegment_;
|
||||||
uint8_t fontStyleWhite_;
|
WidgetList widgets_;
|
||||||
sprite_t* pokeballSprite_;
|
sprite_t* pokeballSprite_;
|
||||||
sprite_t* oakSprite_;
|
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
|
#endif
|
||||||
|
|
@ -12,6 +12,7 @@ class RDPQGraphics;
|
||||||
class IWidget
|
class IWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
virtual ~IWidget(){}
|
||||||
/**
|
/**
|
||||||
* @brief Returns whether the widget is currently focused
|
* @brief Returns whether the widget is currently focused
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,12 @@ public:
|
||||||
uint32_t getDurationInMs() const override;
|
uint32_t getDurationInMs() const override;
|
||||||
|
|
||||||
void start(const Point& startPoint, const Point& endPoint);
|
void start(const Point& startPoint, const Point& endPoint);
|
||||||
|
void extend(const Point& endPoint);
|
||||||
protected:
|
protected:
|
||||||
void apply(float pos) override;
|
void apply(float pos) override;
|
||||||
private:
|
private:
|
||||||
|
Point calculatePoint(float pos);
|
||||||
|
|
||||||
ScrollWidget* list_;
|
ScrollWidget* list_;
|
||||||
Point windowStartPoint_;
|
Point windowStartPoint_;
|
||||||
Point windowEndPoint_;
|
Point windowEndPoint_;
|
||||||
|
|
@ -69,6 +72,7 @@ public:
|
||||||
|
|
||||||
void addWidget(IWidget* widget);
|
void addWidget(IWidget* widget);
|
||||||
void removeWidget(IWidget* widget);
|
void removeWidget(IWidget* widget);
|
||||||
|
void clearWidgets();
|
||||||
|
|
||||||
bool handleUserInput(const joypad_inputs_t& userInput) override;
|
bool handleUserInput(const joypad_inputs_t& userInput) override;
|
||||||
void render(RDPQGraphics& gfx, const Rectangle& parentBounds) override;
|
void render(RDPQGraphics& gfx, const Rectangle& parentBounds) override;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
#include "scenes/TestScene.h"
|
#include "scenes/TestScene.h"
|
||||||
#include "core/RDPQGraphics.h"
|
#include "core/RDPQGraphics.h"
|
||||||
|
#include "core/FontManager.h"
|
||||||
|
#include "widget/ImageWidget.h"
|
||||||
|
#include "widget/TextWidget.h"
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
#include <n64sys.h>
|
#include <n64sys.h>
|
||||||
|
|
||||||
static const char* tvtypeToString(tv_type_t type)
|
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*)
|
TestScene::TestScene(SceneDependencies& deps, void*)
|
||||||
: AbstractUIScene(deps)
|
: AbstractUIScene(deps)
|
||||||
, arialFont_(nullptr)
|
, scrollWidget_(deps.animationManager)
|
||||||
, arialFontId_(1)
|
, scrollWidgetFocusSegment_({
|
||||||
, fontStyleWhite_(0)
|
.current = &scrollWidget_
|
||||||
|
})
|
||||||
|
, widgets_()
|
||||||
, pokeballSprite_(nullptr)
|
, pokeballSprite_(nullptr)
|
||||||
, oakSprite_(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()
|
void TestScene::init()
|
||||||
{
|
{
|
||||||
arialFont_ = rdpq_font_load("rom://Arial.font64");
|
uint8_t widgetType;
|
||||||
rdpq_fontstyle_t arialWhiteFontStyle = {
|
const uint8_t fontId = deps_.fontManager.getFont("rom://Arial.font64");
|
||||||
.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_;
|
|
||||||
|
|
||||||
pokeballSprite_ = sprite_load("rom:/pokeball.sprite");
|
pokeballSprite_ = sprite_load("rom:/pokeball.sprite");
|
||||||
oakSprite_ = sprite_load("rom://oak.sprite");
|
oakSprite_ = sprite_load("rom://oak.sprite");
|
||||||
menu9SliceSprite_ = sprite_load("rom://menu-bg-9slice.sprite");
|
|
||||||
|
|
||||||
oakBounds_ ={10, 80, oakSprite_->width, oakSprite_->height};
|
debugf("Hello Phil! Your tv type is: %s\r\n", tvtypeToString(get_tv_type()));
|
||||||
oakSrcBounds_ = {oakSprite_->width / 3, oakSprite_->height / 3, oakSprite_->width * 2 / 3, oakSprite_->height * 2 / 3};
|
|
||||||
|
|
||||||
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()
|
void TestScene::destroy()
|
||||||
{
|
{
|
||||||
sprite_free(menu9SliceSprite_);
|
scrollWidget_.clearWidgets();
|
||||||
menu9SliceSprite_ = nullptr;
|
for(IWidget* widget : widgets_)
|
||||||
|
{
|
||||||
|
delete widget;
|
||||||
|
}
|
||||||
|
widgets_.clear();
|
||||||
|
|
||||||
sprite_free(oakSprite_);
|
sprite_free(oakSprite_);
|
||||||
oakSprite_ = nullptr;
|
oakSprite_ = nullptr;
|
||||||
|
|
||||||
sprite_free(pokeballSprite_);
|
sprite_free(pokeballSprite_);
|
||||||
pokeballSprite_ = nullptr;
|
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));
|
scrollWidget_.render(gfx, sceneBounds);
|
||||||
// gfx.drawText(textRect_, "Hello Phil!", textRenderSettings_);
|
|
||||||
// gfx.drawSprite(spriteBounds_, pokeballSprite_, SpriteRenderSettings());
|
|
||||||
// gfx.drawSprite(oakBounds_, oakSprite_, {.srcRect = oakSrcBounds_});
|
|
||||||
gfx.drawSprite(menuBounds_, menu9SliceSprite_, menuRenderSettings_);
|
|
||||||
}
|
}
|
||||||
|
|
@ -110,15 +110,28 @@ uint32_t MoveScrollWidgetWindowAnimation::getDurationInMs() const
|
||||||
|
|
||||||
void MoveScrollWidgetWindowAnimation::start(const Point& startPoint, const Point& endPoint)
|
void MoveScrollWidgetWindowAnimation::start(const Point& startPoint, const Point& endPoint)
|
||||||
{
|
{
|
||||||
|
currentTimePos_ = 0.f;
|
||||||
windowStartPoint_ = startPoint;
|
windowStartPoint_ = startPoint;
|
||||||
windowEndPoint_ = endPoint;
|
windowEndPoint_ = endPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MoveScrollWidgetWindowAnimation::extend(const Point& endPoint)
|
||||||
|
{
|
||||||
|
const Point currentPoint = calculatePoint(currentTimePos_);
|
||||||
|
start(currentPoint, endPoint);
|
||||||
|
}
|
||||||
|
|
||||||
void MoveScrollWidgetWindowAnimation::apply(float pos)
|
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 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))));
|
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)
|
ScrollWidget::ScrollWidget(AnimationManager& animManager)
|
||||||
|
|
@ -195,6 +208,12 @@ void ScrollWidget::removeWidget(IWidget* widget)
|
||||||
recalculateWindowSize();
|
recalculateWindowSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScrollWidget::clearWidgets()
|
||||||
|
{
|
||||||
|
widgets_.clear();
|
||||||
|
windowBounds_ = {0};
|
||||||
|
}
|
||||||
|
|
||||||
bool ScrollWidget::handleUserInput(const joypad_inputs_t& userInput)
|
bool ScrollWidget::handleUserInput(const joypad_inputs_t& userInput)
|
||||||
{
|
{
|
||||||
if(!focused_ || style_.scrollStep == 0)
|
if(!focused_ || style_.scrollStep == 0)
|
||||||
|
|
@ -203,21 +222,25 @@ bool ScrollWidget::handleUserInput(const joypad_inputs_t& userInput)
|
||||||
}
|
}
|
||||||
|
|
||||||
const FloatVector scrollDirection = determineScrollDirection(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)
|
if(scrollDirection.x == 0.f && scrollDirection.y == 0.f)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(!windowAnimation_.isFinished())
|
|
||||||
{
|
|
||||||
windowAnimation_.skipToEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
const Point windowStartPoint = {.x = windowBounds_.x, .y = windowBounds_.y};
|
|
||||||
Point windowEndPoint = {.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.x += static_cast<int>(ceil(scrollDirection.x * style_.scrollStep));
|
||||||
windowEndPoint.y += static_cast<int>(ceil(scrollDirection.y * 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user