Commit 1a79cc32 authored by Supernature2k's avatar Supernature2k

popup

parent 9d839f7a
......@@ -4,6 +4,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
### Added
- Added pop-ups
- Added tag in theme to force transition style
- Added dynamic change of volume and audio output in menu
- Added ubuntu_condensed.ttf as fallback font
......
This diff is collapsed.
......@@ -29,6 +29,7 @@ set(ES_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiScraperMulti.h
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiScraperStart.h
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiUpdate.h
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiInfoPopup.h
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiRomsManager.h
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/MenuMessages.h
......@@ -88,6 +89,7 @@ set(ES_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiScraperMulti.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiScraperStart.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiUpdate.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiInfoPopup.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiRomsManager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/guis/MenuMessages.cpp
......
//
// Created by xizor on 30/03/18.
//
#include "GuiInfoPopup.h"
#include "components/ComponentGrid.h"
#include "components/NinePatchComponent.h"
#include "components/TextComponent.h"
#include "Renderer.h"
#include <SDL_timer.h>
#include <MenuThemeData.h>
#include <components/ScrollableContainer.h>
GuiInfoPopup::GuiInfoPopup(Window* window, std::string message, int duration, std::string icon) :
GuiComponent(window), mMessage(message), mDuration(duration * 1000), running(true)
{
mFrame = new NinePatchComponent(window);
float maxWidth = Renderer::getScreenWidth() * 0.2f;
float maxHeight = Renderer::getScreenHeight() * 0.2f;
auto menuTheme = MenuThemeData::getInstance()->getCurrentTheme();
maxAlpha = menuTheme->menuBackground.color & 0xFF;
mFrameColor = menuTheme->menuBackground.color;
unsigned int FONT_SIZE_ICON = 0.05f * std::min(Renderer::getScreenHeight(), Renderer::getScreenWidth());
unsigned int FONT_SIZE_TEXT = 0.02f * std::min(Renderer::getScreenHeight(), Renderer::getScreenWidth());
auto iconText = std::make_shared<TextComponent>(mWindow, icon, Font::get(FONT_SIZE_ICON), menuTheme->menuText.color, ALIGN_CENTER);
auto text = std::make_shared<TextComponent>(mWindow, message, Font::get(FONT_SIZE_TEXT), menuTheme->menuText.color, ALIGN_LEFT);
mGrid = new ComponentGrid(window, Eigen::Vector2i(2, 1));
mGrid->setEntry(iconText, Eigen::Vector2i(0, 0), false, false);
mGrid->setEntry(text, Eigen::Vector2i(1, 0), false, false);
text->setSize(maxWidth - iconText->getSize().y(), 0);
const float msgHeight = std::min(maxHeight, std::max(text->getSize().y(), iconText->getSize().y()));
// add a padding to the box
int paddingX = (int) (Renderer::getScreenWidth() * 0.02f);
int paddingY = (int) (Renderer::getScreenHeight() * 0.02f);
mGrid->setColWidthPerc(0, (iconText->getFont()->getSize() + paddingX) / maxWidth);
mGrid->setSize(maxWidth + paddingX, msgHeight + paddingY);
float posX = Renderer::getScreenWidth()*0.98f - mGrid->getSize().x()*0.98f;
float posY = Renderer::getScreenHeight() * 0.02f;
setPosition(posX, posY, 0);
mFrame->setImagePath(menuTheme->menuBackground.path);
mFrame->setCenterColor(mFrameColor);
mFrame->setEdgeColor(mFrameColor);
mFrame->fitTo(mGrid->getSize(), Eigen::Vector3f::Zero(), Eigen::Vector2f(-32, -32));
addChild(mFrame);
// we only init the actual time when we first start to render
mStartTime = 0;
addChild(mGrid);
}
GuiInfoPopup::~GuiInfoPopup()
{
delete mGrid;
delete mFrame;
}
GuiInfoPopup::GuiInfoPopup(Window* window, std::string message, int duration) :
GuiComponent(window), mMessage(message), mDuration(duration * 1000), running(true)
{
mFrame = new NinePatchComponent(window);
float maxWidth = Renderer::getScreenWidth() * 0.2f;
float maxHeight = Renderer::getScreenHeight() * 0.2f;
auto menuTheme = MenuThemeData::getInstance()->getCurrentTheme();
maxAlpha = menuTheme->menuBackground.color & 0xFF;
mFrameColor = menuTheme->menuBackground.color;
unsigned int FONT_SIZE_TEXT = 0.02f * std::min(Renderer::getScreenHeight(), Renderer::getScreenWidth());
auto text = std::make_shared<TextComponent>(mWindow, message, Font::get(FONT_SIZE_TEXT), menuTheme->menuText.color, ALIGN_LEFT);
mGrid = new ComponentGrid(window, Eigen::Vector2i(1, 1));
mGrid->setEntry(text, Eigen::Vector2i(0, 0), false, false);
text->setSize(maxWidth, 0);
const float msgHeight = std::min(maxHeight, text->getSize().y());
// add a padding to the box
int paddingX = (int) (Renderer::getScreenWidth() * 0.02f);
int paddingY = (int) (Renderer::getScreenHeight() * 0.02f);
mGrid->setSize(maxWidth + paddingX, msgHeight + paddingY);
float posX = Renderer::getScreenWidth()*0.98f - mGrid->getSize().x()*0.98f;
float posY = Renderer::getScreenHeight() * 0.02f;
setPosition(posX, posY, 0);
mFrame->setImagePath(menuTheme->menuBackground.path);
mFrame->setCenterColor(mFrameColor);
mFrame->setEdgeColor(mFrameColor);
mFrame->fitTo(mGrid->getSize(), Eigen::Vector3f::Zero(), Eigen::Vector2f(-32, -32));
addChild(mFrame);
// we only init the actual time when we first start to render
mStartTime = 0;
addChild(mGrid);
}
void GuiInfoPopup::render(const Eigen::Affine3f& parentTrans)
{
// we use identity as we want to render on a specific window position, not on the view
Eigen::Affine3f trans = getTransform() * Eigen::Affine3f::Identity();
if(running && updateState())
{
// if we're still supposed to be rendering it
Renderer::setMatrix(trans);
renderChildren(trans);
}
}
bool GuiInfoPopup::updateState()
{
int curTime = SDL_GetTicks();
// we only init the actual time when we first start to render
if(mStartTime == 0)
{
mStartTime = curTime;
}
// compute fade in effect
if (curTime - mStartTime > mDuration)
{
// we're past the popup duration, no need to render
running = false;
return false;
}
else if (curTime < mStartTime) {
// if SDL reset
running = false;
return false;
}
else if (curTime - mStartTime <= 500) {
alpha = ((curTime - mStartTime)*255/500);
}
else if (curTime - mStartTime < mDuration - 500)
{
alpha = 255;
}
else
{
alpha = ((-(curTime - mStartTime - mDuration)*255)/500);
}
if (alpha > maxAlpha)
alpha = maxAlpha;
mGrid->setOpacity(alpha);
// apply fade in effect to popup frame
mFrame->setEdgeColor((mFrameColor & 0xffffff00) | alpha);
mFrame->setCenterColor((mFrameColor & 0xffffff00) | alpha);
return true;
}
\ No newline at end of file
//
// Created by xizor on 30/03/18.
//
#pragma once
#include "GuiComponent.h"
#include "components/NinePatchComponent.h"
#include "components/ComponentGrid.h"
#include "Window.h"
#include "Log.h"
class GuiInfoPopup : public GuiComponent, public Window::InfoPopup
{
public:
GuiInfoPopup(Window* window, std::string message, int duration, std::string icon);
GuiInfoPopup(Window* window, std::string message, int duration);
~GuiInfoPopup();
void render(const Eigen::Affine3f& parentTrans) override;
inline void stop() { running = false; };
private:
std::string mMessage;
int mDuration;
int alpha;
unsigned int maxAlpha;
unsigned int mFrameColor;
bool updateState();
int mStartTime;
ComponentGrid* mGrid;
NinePatchComponent* mFrame;
bool running;
};
\ No newline at end of file
......@@ -34,7 +34,7 @@ void ViewController::init(Window* window)
}
ViewController::ViewController(Window* window)
: GuiComponent(window), mCurrentView(nullptr), mCamera(Eigen::Affine3f::Identity()), mFadeOpacity(0), mLockInput(false)
: GuiComponent(window), mCurrentView(nullptr), mCamera(Eigen::Affine3f::Identity()), mFadeOpacity(0), mLockInput(false), mWindow(window)
{
mState.viewing = NOTHING;
mFavoritesOnly = Settings::getInstance()->getBool("FavoritesOnly");
......
......@@ -11,6 +11,7 @@ class ViewController : public GuiComponent
public:
static void init(Window* window);
static ViewController* get();
inline static Window* getWindow(){return sInstance->mWindow;}
virtual ~ViewController();
......@@ -95,4 +96,6 @@ private:
State mState;
int getFirstSystemIndex();
Window* mWindow;
};
......@@ -10,6 +10,8 @@
#include "ThemeData.h"
#include <unistd.h>
#include <time.h>
#include <views/ViewController.h>
#include <guis/GuiInfoPopup.h>
std::vector<std::shared_ptr<Sound>> AudioManager::sSoundVector;
std::vector<std::shared_ptr<Music>> AudioManager::sMusicVector;
......@@ -19,6 +21,9 @@ std::shared_ptr<AudioManager> AudioManager::sInstance;
AudioManager::AudioManager() : currentMusic(NULL), running(0) {
if (!mWindow)
mWindow = ViewController::getWindow();
init();
}
......@@ -107,6 +112,8 @@ void AudioManager::playRandomMusic() {// Find a random song in user directory or
stopMusic();
bgsound->play(false, musicEndInternal);
currentMusic = bgsound;
auto s = new GuiInfoPopup(mWindow, "Now playing:\n" + currentMusic->getName(), 2, "\uF1b0");
mWindow->setInfoPopup(s);
return;
} else {
// Not running from playlist, and no theme song found
......
......@@ -9,6 +9,8 @@
#include "Sound.h"
#include "Music.h"
#include "Window.h"
class AudioManager {
static std::vector<std::shared_ptr<Sound>> sSoundVector;
......@@ -51,6 +53,8 @@ public:
virtual ~AudioManager();
inline std::string getCurrentMusicName(){return currentMusic->getName();}
private:
bool running;
int lastTime = 0;
......@@ -64,6 +68,8 @@ private:
std::string currentThemeMusicDirectory;
void playRandomMusic();
Window* mWindow;
};
#endif
......@@ -63,6 +63,46 @@ bool InputConfig::isConfigured()
return mNameMap.size() > 0;
}
std::string InputConfig::getSDLPowerLevel()
{
SDL_Joystick* joy;
//joy = InputManager::getInstance()->getJoystickByJoystickID(getDeviceId());
joy = SDL_JoystickOpen(getDeviceId());
SDL_JoystickPowerLevel power = SDL_JoystickCurrentPowerLevel(joy);
switch(power)
{
case SDL_JOYSTICK_POWER_EMPTY:
return "\uF1b6";
case SDL_JOYSTICK_POWER_FULL:
return "\uF1b7";
case SDL_JOYSTICK_POWER_LOW:
return "\uF1b1";
case SDL_JOYSTICK_POWER_MAX:
return "\uF1ba";
case SDL_JOYSTICK_POWER_MEDIUM:
return "\uF1b8";
case SDL_JOYSTICK_POWER_UNKNOWN:
return "\uF1b9";
case SDL_JOYSTICK_POWER_WIRED:
return "\uF1b4";
}
}
std::string InputConfig::getSysPowerLevel()
{
SDL_Joystick* joy;
//joy = InputManager::getInstance()->getJoystickByJoystickID(getDeviceId());
joy = SDL_JoystickOpen(getDeviceId());
return "\uF1be";
}
void InputConfig::mapInput(const std::string& name, Input input)
{
mNameMap[toLower(name)] = input;
......
......@@ -96,6 +96,8 @@ public:
inline const std::string& getDeviceName() { return mDeviceName; }
inline const std::string& getDeviceGUIDString() { return mDeviceGUID; }
inline int getDeviceNbAxes() const { return mDeviceNbAxes; };
std::string getSDLPowerLevel();
std::string getSysPowerLevel();
//Returns true if Input is mapped to this name, false otherwise.
bool isMappedTo(const std::string& name, Input input);
......
......@@ -90,6 +90,11 @@ void InputManager::addJoystickByDeviceIndex(int id)
std::fill(mPrevAxisValues[joyId], mPrevAxisValues[joyId] + numAxes, 0); //initialize array to 0
}
SDL_Joystick* InputManager::getJoystickByJoystickID(int id)
{
return mJoysticks[id];
}
void InputManager::removeJoystickByJoystickID(SDL_JoystickID joyId)
{
assert(joyId != -1);
......
......@@ -51,6 +51,8 @@ public:
int getButtonCountByDevice(int deviceId);
int getAxisCountByDevice(int deviceId);
SDL_Joystick* getJoystickByJoystickID(int id);
int getNumConfiguredDevices();
std::string getDeviceGUIDString(int deviceId);
......
......@@ -43,6 +43,12 @@ Music::~Music()
deinitMusic();
}
std::string Music::getName()
{
boost::filesystem::path p(mPath);
return p.stem().string();
}
void Music::initMusic()
{
......
......@@ -16,9 +16,10 @@ class Music
public:
static std::shared_ptr<Music> getFromTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element);
static std::shared_ptr<Music> get(const std::string& path);
void play(bool repeat, void (* callback)());
static std::shared_ptr<Music> getFromTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element);
static std::shared_ptr<Music> get(const std::string& path);
void play(bool repeat, void (* callback)());
std::string getName();
~Music();
......
......@@ -7,6 +7,7 @@
#include <algorithm>
#include <iomanip>
#include <guis/GuiMsgBoxScroll.h>
#include <guis/GuiInfoPopup.h>
#include "components/HelpComponent.h"
#include "components/ImageComponent.h"
#include "guis/GuiMsgBox.h"
......@@ -17,7 +18,7 @@
#include "views/ViewController.h"
Window::Window() : mNormalizeNextUpdate(false), mFrameTimeElapsed(0), mFrameCountElapsed(0), mAverageDeltaTime(10),
mAllowSleep(true), mSleeping(false), mTimeSinceLastInput(0), launchKodi(false)
mAllowSleep(true), mSleeping(false), mTimeSinceLastInput(0), launchKodi(false), mInfoPopup(NULL)
{
mHelp = new HelpComponent(this);
mBackgroundOverlay = new ImageComponent(this);
......@@ -153,7 +154,7 @@ void Window::input(InputConfig* config, Input input)
{
launchKodi = true;
Window * window = this;
this->pushGui(new GuiMsgBox(this, _("DO YOU WANT TO START KODI MEDIA CENTER ?"),
this->pushGui(new GuiMsgBox(this, _("DO YOU WANT TO START KODI MEDIA CENTER ?"),
_("YES"), [window, this] {
if( ! RecalboxSystem::getInstance()->launchKodi(window)) {
LOG(LogWarning) << "Shutdown terminated with non-zero result!";
......@@ -165,7 +166,14 @@ void Window::input(InputConfig* config, Input input)
}
));
}
else if(peekGui())
/*else if(config->isMappedTo("PageDown", input) && input.value
&& ViewController::get()->isViewing(ViewController::SYSTEM_SELECT)
&& mGuiStack.size() == 1 )
{
auto s = new GuiInfoPopup(this, "Controller:\n" + config->getDeviceName(), 2);
this->setInfoPopup(s);
}*/
else if(peekGui() && !KonamiCode(config, input, this))
{
this->peekGui()->input(config, input);
}
......@@ -270,6 +278,10 @@ void Window::render()
onSleep();
}
}
if(mInfoPopup)
{
mInfoPopup->render(transform);
}
}
void Window::normalizeNextUpdate()
......@@ -424,3 +436,33 @@ void Window::doWake()
mSleeping = false;
onWake();
}
bool Window::KonamiCode(InputConfig* config, Input input, Window* window)
{
if (!input.value)
return false;
bool codeOk = false;
for (auto valstring : mInputVals)
{
if (config->isMappedTo(valstring, input) && (this->mKonami[this->mKonamiCount] == valstring[0]))
{
this->mKonamiCount ++;
codeOk = true;
}
}
if (!codeOk)
{
this->mKonamiCount = 0; // current input is incorrect, reset counter
}
if (this->mKonamiCount == (this->mKonami.length()))
{
auto s = new GuiInfoPopup(this, "I entered Konami Code and all I get is this lame popup", 4, "\uF200");
this->setInfoPopup(s);
return true;
}
return false;
}
......@@ -11,6 +11,13 @@ class ImageComponent;
class Window
{
public:
class InfoPopup
{
public:
virtual void render(const Eigen::Affine3f& parentTrans) = 0;
virtual void stop() = 0;
virtual ~InfoPopup() {};
};
Window();
~Window();
......@@ -39,6 +46,9 @@ public:
void renderHelpPromptsEarly(); // used to render HelpPrompts before a fade
void setHelpPrompts(const std::vector<HelpPrompt>& prompts, const HelpStyle& style);
void setInfoPopup(InfoPopup* infoPopup) { delete mInfoPopup; mInfoPopup = infoPopup; }
inline void stopInfoPopup() { if (mInfoPopup) mInfoPopup->stop(); };
void renderShutdownScreen();
void doWake();
......@@ -52,8 +62,11 @@ private:
bool isProcessing();
void renderScreenSaver();
bool KonamiCode(InputConfig* config, Input input, Window* window);
HelpComponent* mHelp;
ImageComponent* mBackgroundOverlay;
InfoPopup* mInfoPopup;
std::vector<GuiComponent*> mGuiStack;
std::vector<std::string> mMessages;
......@@ -77,4 +90,8 @@ private:
bool mRenderedHelpPrompts;
bool launchKodi;
std::string mKonami = "uuddlrlrba";
int mKonamiCount;
const std::vector<std::string> mInputVals = { "up", "down", "left", "right", "a", "b" };
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment