diff --git a/Core/Config.cpp b/Core/Config.cpp index 34758863c9..daf7d00873 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -54,6 +54,7 @@ void Config::Load(const char *iniFileName) bSpeedLimit = false; general->Get("FirstRun", &bFirstRun, true); + general->Get("NewUI", &bNewUI, false); general->Get("AutoLoadLast", &bAutoLoadLast, false); general->Get("AutoRun", &bAutoRun, true); general->Get("Browse", &bBrowse, false); @@ -64,11 +65,11 @@ void Config::Load(const char *iniFileName) general->Get("Language", &languageIni, "en_US"); general->Get("NumWorkerThreads", &iNumWorkerThreads, cpu_info.num_cores); general->Get("EnableCheats", &bEnableCheats, false); - general->Get("MaxRecent", &iMaxRecent, 12); + general->Get("MaxRecent", &iMaxRecent, 24); // Fix issue from switching from uint (hex in .ini) to int (dec) if (iMaxRecent == 0) - iMaxRecent = 12; + iMaxRecent = 24; // "default" means let emulator decide, "" means disable. general->Get("ReportHost", &sReportHost, "default"); diff --git a/Core/Config.h b/Core/Config.h index 2b617b96cb..fa9b996b7d 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -43,6 +43,7 @@ public: bool bBrowse; // General + bool bNewUI; // "Hidden" setting, does not get saved to ini file. int iNumWorkerThreads; // Core diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index aebc111626..1ff9f12aa7 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -43,6 +43,7 @@ #include "UI/GamepadEmu.h" #include "UI/UIShader.h" +#include "UI/MainScreen.h" #include "UI/MenuScreens.h" #include "UI/EmuScreen.h" #include "UI/GameInfoCache.h" @@ -107,7 +108,10 @@ EmuScreen::~EmuScreen() { void EmuScreen::dialogFinished(const Screen *dialog, DialogResult result) { if (result == DR_OK) { - screenManager()->switchScreen(new MenuScreen()); + if (g_Config.bNewUI) + screenManager()->switchScreen(new MainScreen()); + else + screenManager()->switchScreen(new MenuScreen()); } } @@ -116,13 +120,19 @@ void EmuScreen::sendMessage(const char *message, const char *value) { if (!strcmp(message, "pause")) { screenManager()->push(new PauseScreen()); } else if (!strcmp(message, "stop")) { - screenManager()->switchScreen(new MenuScreen()); + if (g_Config.bNewUI) + screenManager()->switchScreen(new MainScreen()); + else + screenManager()->switchScreen(new MenuScreen()); } else if (!strcmp(message, "reset")) { PSP_Shutdown(); std::string resetError; if (!PSP_Init(PSP_CoreParameter(), &resetError)) { ELOG("Error resetting: %s", resetError.c_str()); - screenManager()->switchScreen(new MenuScreen()); + if (g_Config.bNewUI) + screenManager()->switchScreen(new MainScreen()); + else + screenManager()->switchScreen(new MenuScreen()); return; } host->BootDone(); @@ -280,7 +290,10 @@ void EmuScreen::render() { coreState = CORE_RUNNING; } else if (coreState == CORE_POWERDOWN) { ILOG("SELF-POWERDOWN!"); - screenManager()->switchScreen(new MenuScreen()); + if (g_Config.bNewUI) + screenManager()->switchScreen(new MainScreen()); + else + screenManager()->switchScreen(new MenuScreen()); } if (invalid_) diff --git a/UI/GameScreen.cpp b/UI/GameScreen.cpp index 9112ad3096..16a8f809e2 100644 --- a/UI/GameScreen.cpp +++ b/UI/GameScreen.cpp @@ -26,6 +26,7 @@ #include "UI/GameSettingsScreen.h" #include "UI/GameInfoCache.h" #include "UI/MenuScreens.h" +#include "UI/MainScreen.h" void GameScreen::CreateViews() { GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, true); @@ -114,7 +115,7 @@ void GameScreen::update(InputState &input) { } UI::EventReturn GameScreen::OnSwitchBack(UI::EventParams &e) { - screenManager()->switchScreen(new MenuScreen()); + screenManager()->switchScreen(new MainScreen()); return UI::EVENT_DONE; } @@ -167,7 +168,7 @@ void GameScreen::CallbackDeleteGame(bool yes) { if (yes) { info->DeleteGame(); g_gameInfoCache.Clear(); - screenManager()->switchScreen(new MenuScreen()); + screenManager()->switchScreen(new MainScreen()); } } diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index af739fb773..495965d0f9 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -35,6 +35,9 @@ void GameSettingsScreen::CreateViews() { I18NCategory *g = GetI18NCategory("General"); I18NCategory *gs = GetI18NCategory("Graphics"); + I18NCategory *c = GetI18NCategory("Controls"); + I18NCategory *a = GetI18NCategory("Audio"); + I18NCategory *s = GetI18NCategory("System"); Margins actionMenuMargins(0, 0, 15, 0); @@ -49,7 +52,6 @@ void GameSettingsScreen::CreateViews() { TabHolder *tabHolder = new TabHolder(ORIENT_VERTICAL, 200, new LinearLayoutParams(600, FILL_PARENT, actionMenuMargins)); root_->Add(tabHolder); - // TODO: These currently point to global settings, not game specific ones. ViewGroup *graphicsSettingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); @@ -64,29 +66,31 @@ void GameSettingsScreen::CreateViews() { graphicsSettings->Add(new CheckBox(&g_Config.bVertexCache, gs->T("Vertex Cache"))); graphicsSettings->Add(new CheckBox(&g_Config.bUseVBO, gs->T("Stream VBO"))); graphicsSettings->Add(new CheckBox(&g_Config.SSAntiAliasing, gs->T("Anti Aliasing"))); + graphicsSettings->Add(new CheckBox(&g_Config.SSAntiAliasing, gs->T("Show FPS"))); ViewGroup *audioSettingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); ViewGroup *audioSettings = new LinearLayout(ORIENT_VERTICAL); audioSettingsScroll->Add(audioSettings); tabHolder->AddTab("Audio", audioSettingsScroll); - audioSettings->Add(new CheckBox(&g_Config.bEnableSound, "Enable Sound")); - audioSettings->Add(new CheckBox(&g_Config.bEnableAtrac3plus, "Enable Atrac3+")); - audioSettings->Add(new Choice("Download Atrac3+ plugin"))->OnClick.Handle(this, &GameSettingsScreen::OnDownloadPlugin); + audioSettings->Add(new CheckBox(&g_Config.bEnableSound, a->T("Enable Sound"))); + audioSettings->Add(new CheckBox(&g_Config.bEnableAtrac3plus, a->T("Enable Atrac3+"))); + audioSettings->Add(new Choice(a->T("Download Atrac3+ plugin")))->OnClick.Handle(this, &GameSettingsScreen::OnDownloadPlugin); ViewGroup *controlsSettingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); - ViewGroup *controlsSettings = new LinearLayout(ORIENT_VERTICAL); + ViewGroup *controlsSettings = new LinearLayout(ORIENT_VERTICAL); controlsSettingsScroll->Add(controlsSettings); tabHolder->AddTab("Controls", controlsSettingsScroll); - controlsSettings->Add(new CheckBox(&g_Config.bShowTouchControls, "Show Touch Controls")); - controlsSettings->Add(new CheckBox(&g_Config.bShowAnalogStick, "Show analog stick")); - controlsSettings->Add(new CheckBox(&g_Config.bAccelerometerToAnalogHoriz, "Horizontal tilt to analog")); + controlsSettings->Add(new CheckBox(&g_Config.bShowTouchControls, c->T("OnScreen", "On-Screen Touch Controls"))); + controlsSettings->Add(new CheckBox(&g_Config.bShowTouchControls, c->T("Large Controls"))); + controlsSettings->Add(new CheckBox(&g_Config.bShowAnalogStick, c->T("Show Analog Stick"))); + controlsSettings->Add(new CheckBox(&g_Config.bAccelerometerToAnalogHoriz, c->T("Tilt", "Tilt to Analog (horizontal)"))); ViewGroup *systemSettingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); ViewGroup *systemSettings = new LinearLayout(ORIENT_VERTICAL); systemSettingsScroll->Add(systemSettings); tabHolder->AddTab("System", systemSettingsScroll); - systemSettings->Add(new CheckBox(&g_Config.bJit, "Enable JIT (dynarec)")); - systemSettings->Add(new CheckBox(&g_Config.bFastMemory, "Fast Memory (unstable)")); + systemSettings->Add(new CheckBox(&g_Config.bJit, s->T("Dynarec", "Dynarec (JIT)"))); + systemSettings->Add(new CheckBox(&g_Config.bFastMemory, s->T("Fast Memory", "Fast Memory (unstable)"))); } UI::EventReturn GameSettingsScreen::OnDownloadPlugin(UI::EventParams &e) { diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp new file mode 100644 index 0000000000..0571170a7e --- /dev/null +++ b/UI/MainScreen.cpp @@ -0,0 +1,227 @@ +// Copyright (c) 2013- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include "base/colorutil.h" +#include "base/timeutil.h" +#include "math/curves.h" +#include "ui/ui_context.h" +#include "ui/view.h" +#include "ui/viewgroup.h" +#include "UI/EmuScreen.h" +#include "UI/MainScreen.h" +#include "UI/GameScreen.h" +#include "UI/MenuScreens.h" +#include "UI/GameInfoCache.h" +#include "UI/ui_atlas.h" +#include "Core/Config.h" + +class GameButton : public UI::Clickable { +public: + GameButton(const std::string &gamePath, UI::LayoutParams *layoutParams = 0) + : UI::Clickable(layoutParams), gamePath_(gamePath) {} + + virtual void Draw(UIContext &dc); + virtual void GetContentDimensions(const UIContext &dc, float &w, float &h) const { + w = 144; + h = 80; + } + const std::string &GamePath() const { return gamePath_; } + +private: + std::string gamePath_; +}; + +void GameButton::Draw(UIContext &dc) { + GameInfo *ginfo = g_gameInfoCache.GetInfo(gamePath_, false); + Texture *texture = 0; + u32 color = 0; + if (ginfo->iconTexture) { + texture = ginfo->iconTexture; + } else { + return; + } + + int x = bounds_.x; + int y = bounds_.y; + int w = bounds_.w; + int h = bounds_.h; + + if (texture) { + color = whiteAlpha(ease((time_now_d() - ginfo->timeIconWasLoaded) * 2)); + + float tw = texture->Width(); + float th = texture->Height(); + + // Adjust position so we don't stretch the image vertically or horizontally. + // TODO: Add a param to specify fit? The below assumes it's never too wide. + float nw = h * tw / th; + x += (w - nw) / 2.0f; + w = nw; + } + + int txOffset = down_ ? 4 : 0; + + // Render button + int dropsize = 10; + if (texture) { + if (txOffset) { + dropsize = 3; + y += txOffset * 2; + } + dc.Draw()->DrawImage4Grid(I_DROP_SHADOW, x - dropsize, y, x+w + dropsize, y+h+dropsize*1.5, alphaMul(color, 0.5f), 1.0f); + dc.Draw()->Flush(); + } + + if (texture) { + texture->Bind(0); + dc.Draw()->DrawTexRect(x, y, x+w, y+h, 0, 0, 1, 1, color); + dc.Draw()->Flush(); + } else { + dc.FillRect(dc.theme->buttonStyle.background, bounds_); + dc.Draw()->Flush(); + Texture::Unbind(); + } + + dc.RebindTexture(); +} + +class GameBrowser : public UI::GridLayout { +public: + GameBrowser(std::string path, bool allowBrowsing, UI::LayoutParams *layoutParams = 0) + : UI::GridLayout(UI::GridLayoutSettings(150, 85), layoutParams), path_(path), allowBrowsing_(allowBrowsing) { + Refresh(); + } + + UI::Event OnChoice; + + virtual void Update(const InputState &input_state) { + UI::GridLayout::Update(input_state); + OnChoice.Update(); + } + +private: + void Refresh(); + + UI::EventReturn GameButtonClick(UI::EventParams &e); + + bool allowBrowsing_; + std::string path_; +}; + +void GameBrowser::Refresh() { + // Kill all the buttons + for (size_t i = 0; i < views_.size(); i++) { + delete views_[i]; + } + views_.clear(); + + // Find games in the current directory and create new ones. + std::vector games; + + if (path_ == "") + games = g_Config.recentIsos; + else { + std::vector fileInfo; + getFilesInDir(path_.c_str(), &fileInfo); + for (size_t i = 0; i < fileInfo.size(); i++) { + games.push_back(fileInfo[i].fullName); + } + } + + for (size_t i = 0; i < games.size(); i++) { + Add(new GameButton(games[i]))->OnClick.Handle(this, &GameBrowser::GameButtonClick); + } +} + +UI::EventReturn GameBrowser::GameButtonClick(UI::EventParams &e) { + GameButton *button = static_cast(e.v); + UI::EventParams e2; + e2.s = button->GamePath(); + // Insta-update - here we know we are already on the right thread. + OnChoice.Trigger(e2); + return UI::EVENT_DONE; +} + +void MainScreen::CreateViews() { + // Information in the top left. + // Back button to the bottom left. + // Scrolling action menu to the right. + using namespace UI; + + Margins actionMenuMargins(0, 100, 15, 0); + + root_ = new LinearLayout(ORIENT_HORIZONTAL); + + TabHolder *leftColumn = new TabHolder(ORIENT_HORIZONTAL, 64, new LinearLayoutParams(1.0)); + root_->Add(leftColumn); + + GameBrowser *tabRecentGames = new GameBrowser("", false); + GameBrowser *tabAllGames = new GameBrowser(g_Config.currentDirectory, true); + GameBrowser *tabHomebrew = new GameBrowser(g_Config.memCardDirectory + "PSP/GAME/", false); + + leftColumn->AddTab("Recent", tabRecentGames); + leftColumn->AddTab("Games", tabAllGames); + leftColumn->AddTab("Homebrew & Demos", tabHomebrew); + + tabRecentGames->OnChoice.Handle(this, &MainScreen::OnGameSelected); + tabAllGames->OnChoice.Handle(this, &MainScreen::OnGameSelected); + tabHomebrew->OnChoice.Handle(this, &MainScreen::OnGameSelected); + +/* + if (info) { + texvGameIcon_ = leftColumn->Add(new TextureView(0, IS_DEFAULT, new AnchorLayoutParams(144 * 2, 80 * 2, 10, 10, NONE, NONE))); + tvTitle_ = leftColumn->Add(new TextView(0, info->title, ALIGN_LEFT, 1.0f, new AnchorLayoutParams(10, 200, NONE, NONE))); + tvGameSize_ = leftColumn->Add(new TextView(0, "...", ALIGN_LEFT, 1.0f, new AnchorLayoutParams(10, 250, NONE, NONE))); + tvSaveDataSize_ = leftColumn->Add(new TextView(0, "...", ALIGN_LEFT, 1.0f, new AnchorLayoutParams(10, 290, NONE, NONE))); + } + */ + + ViewGroup *rightColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(300, FILL_PARENT, actionMenuMargins)); + root_->Add(rightColumn); + + ViewGroup *rightColumnItems = new LinearLayout(ORIENT_VERTICAL); + rightColumn->Add(rightColumnItems); + rightColumnItems->Add(new Choice("Settings"))->OnClick.Handle(this, &MainScreen::OnSettings); + rightColumnItems->Add(new Choice("Credits"))->OnClick.Handle(this, &MainScreen::OnCredits); + rightColumnItems->Add(new Choice("Support PPSSPP"))->OnClick.Handle(this, &MainScreen::OnSupport); +} + +void DrawBackground(float alpha); + +void MainScreen::DrawBackground(UIContext &dc) { + ::DrawBackground(1.0f); + dc.Flush(); +} + +UI::EventReturn MainScreen::OnGameSelected(UI::EventParams &e) { + screenManager()->switchScreen(new GameScreen(e.s)); + return UI::EVENT_DONE; +} + +UI::EventReturn MainScreen::OnSettings(UI::EventParams &e) { + screenManager()->push(new SettingsScreen()); + return UI::EVENT_DONE; +} + +UI::EventReturn MainScreen::OnCredits(UI::EventParams &e) { + screenManager()->push(new CreditsScreen()); + return UI::EVENT_DONE; +} + +UI::EventReturn MainScreen::OnSupport(UI::EventParams &e) { + return UI::EVENT_DONE; +} \ No newline at end of file diff --git a/UI/MainScreen.h b/UI/MainScreen.h new file mode 100644 index 0000000000..b232effdf6 --- /dev/null +++ b/UI/MainScreen.h @@ -0,0 +1,41 @@ +// Copyright (c) 2013- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +#include "base/functional.h" +#include "ui/ui_screen.h" + +// Game screen: Allows you to start a game, delete saves, delete the game, +// set game specific settings, etc. +// Uses GameInfoCache heavily to implement the functionality. + +class MainScreen : public UIScreen { +public: + MainScreen() {} + +protected: + virtual void CreateViews(); + virtual void DrawBackground(UIContext &dc); + +private: + UI::EventReturn OnGameSelected(UI::EventParams &e); + // Event handlers + UI::EventReturn OnSettings(UI::EventParams &e); + UI::EventReturn OnCredits(UI::EventParams &e); + UI::EventReturn OnSupport(UI::EventParams &e); +}; \ No newline at end of file diff --git a/UI/MenuScreens.cpp b/UI/MenuScreens.cpp index 95247b7e5e..c10e28cfdd 100644 --- a/UI/MenuScreens.cpp +++ b/UI/MenuScreens.cpp @@ -58,6 +58,7 @@ #include "UI/GameScreen.h" #include "UI/EmuScreen.h" #include "UI/PluginScreen.h" +#include "UI/MainScreen.h" #include "GameInfoCache.h" #include "android/jni/TestRunner.h" @@ -141,7 +142,10 @@ void LogoScreen::update(InputState &input_state) { if (bootFilename_.size()) { screenManager()->switchScreen(new EmuScreen(bootFilename_)); } else { - screenManager()->switchScreen(new MenuScreen()); + if (g_Config.bNewUI) + screenManager()->switchScreen(new MainScreen()); + else + screenManager()->switchScreen(new MenuScreen()); } } } @@ -249,7 +253,7 @@ void MenuScreen::render() { } if (UIButton(GEN_ID, vlinear, w, 0, m->T("Credits"), ALIGN_RIGHT)) { - screenManager()->switchScreen(new CreditsScreen()); + screenManager()->push(new CreditsScreen()); UIReset(); } @@ -1059,11 +1063,15 @@ void SystemScreen::render() { if (UICheckBox(GEN_ID, x, y += stride, s->T("12HR Time Format"), ALIGN_TOPLEFT, &tf)) { g_Config.itimeformat = tf ? 1 : 0; } + +#ifndef ANDROID UICheckBox(GEN_ID, x, y += stride, s->T("Enable Cheats"), ALIGN_TOPLEFT, &g_Config.bEnableCheats); HLinear hlinear2(x, y += stride + 10, 20); if (UIButton(GEN_ID, hlinear2, LARGE_BUTTON_WIDTH + 150, 0, s->T("Reload Cheats"), ALIGN_TOPLEFT)) { g_Config.bReloadCheats = true; } +#endif + if (UIButton(GEN_ID, hlinear2, LARGE_BUTTON_WIDTH, 0, s->T("Language"), ALIGN_TOPLEFT)) { screenManager()->push(new LanguageScreen()); } @@ -1320,7 +1328,7 @@ void CreditsScreen::render() { I18NCategory *g = GetI18NCategory("General"); if (UIButton(GEN_ID, Pos(dp_xres - 10, dp_yres - 10), 200, 0, g->T("Back"), ALIGN_BOTTOMRIGHT)) { - screenManager()->switchScreen(new MenuScreen()); + screenManager()->finishDialog(this, DR_OK); } UIEnd(); diff --git a/UI/UI.vcxproj b/UI/UI.vcxproj index 4ae459485e..94f11e5c3d 100644 --- a/UI/UI.vcxproj +++ b/UI/UI.vcxproj @@ -24,6 +24,7 @@ + @@ -37,6 +38,7 @@ + diff --git a/UI/UI.vcxproj.filters b/UI/UI.vcxproj.filters index 70fb666141..f2925573ba 100644 --- a/UI/UI.vcxproj.filters +++ b/UI/UI.vcxproj.filters @@ -22,6 +22,9 @@ Screens + + Screens + @@ -44,6 +47,9 @@ Screens + + Screens + diff --git a/native b/native index 3a51252fb9..cf7ccddf1e 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit 3a51252fb9c44f1d95941ce11c5cd53a3d0cf05c +Subproject commit cf7ccddf1e936ec1eeaf34160ec6bfd9c85ece74