2013-06-10 20:06:51 +00:00
// 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/.
2013-11-26 13:45:36 +00:00
# include <cmath>
2013-11-27 10:15:46 +00:00
# include <algorithm>
2013-11-26 13:45:36 +00:00
2017-02-27 10:32:40 +00:00
# include "ppsspp_config.h"
2013-06-10 20:06:51 +00:00
# include "base/colorutil.h"
2014-04-03 15:31:59 +00:00
# include "base/display.h"
2013-06-10 20:06:51 +00:00
# include "base/timeutil.h"
2013-11-18 13:05:26 +00:00
# include "file/path.h"
2013-08-18 18:25:33 +00:00
# include "gfx_es2/draw_buffer.h"
2013-06-10 20:06:51 +00:00
# include "math/curves.h"
2013-12-06 10:44:46 +00:00
# include "base/stringutil.h"
2013-06-10 20:06:51 +00:00
# include "ui/ui_context.h"
# include "ui/view.h"
# include "ui/viewgroup.h"
2018-06-02 23:32:55 +00:00
# include "util/text/utf8.h"
2013-07-21 11:31:46 +00:00
# include "Common/FileUtil.h"
# include "Core/System.h"
2013-09-01 20:29:23 +00:00
# include "Core/Host.h"
2014-02-09 22:04:16 +00:00
# include "Core/Reporting.h"
2017-05-18 12:21:13 +00:00
# include "Core/Util/GameManager.h"
2013-07-21 11:31:46 +00:00
2014-06-22 15:02:04 +00:00
# include "UI/BackgroundAudio.h"
2013-06-10 20:06:51 +00:00
# include "UI/EmuScreen.h"
# include "UI/MainScreen.h"
# include "UI/GameScreen.h"
# include "UI/GameInfoCache.h"
2013-07-17 20:27:05 +00:00
# include "UI/GameSettingsScreen.h"
2013-08-14 21:05:02 +00:00
# include "UI/MiscScreens.h"
2013-09-07 15:29:44 +00:00
# include "UI/ControlMappingScreen.h"
2015-12-21 05:32:05 +00:00
# include "UI/DisplayLayoutScreen.h"
2015-06-11 18:22:16 +00:00
# include "UI/SavedataScreen.h"
2013-11-20 13:42:48 +00:00
# include "UI/Store.h"
2013-06-10 20:06:51 +00:00
# include "UI/ui_atlas.h"
# include "Core/Config.h"
2017-03-02 11:29:03 +00:00
# include "Core/Loaders.h"
2013-07-21 23:33:18 +00:00
# include "GPU/GPUInterface.h"
2013-08-11 15:25:50 +00:00
# include "i18n/i18n.h"
2013-06-27 14:28:11 +00:00
2014-06-14 21:55:16 +00:00
# include "Core/HLE/sceDisplay.h"
2013-11-24 03:02:36 +00:00
# include "Core/HLE/sceUmd.h"
2013-10-15 11:28:09 +00:00
# ifdef _WIN32
# include "Windows/W32Util/ShellUtil.h"
2015-09-19 11:14:05 +00:00
# include "Windows/MainWindow.h"
2013-10-15 11:28:09 +00:00
# endif
2014-03-19 06:55:17 +00:00
# ifdef ANDROID_NDK_PROFILER
# include <stdlib.h>
# include "android/android-ndk-profiler/prof.h"
# endif
2013-10-08 13:38:50 +00:00
# include <sstream>
2013-12-06 11:29:27 +00:00
bool MainScreen : : showHomebrewTab = false ;
2018-06-02 23:32:55 +00:00
static bool IsTempPath ( const std : : string & str ) {
std : : string item = str ;
const auto testPath = [ & ] ( std : : string temp ) {
# ifdef _WIN32
temp = ReplaceAll ( temp , " / " , " \\ " ) ;
if ( ! temp . empty ( ) & & temp [ temp . size ( ) - 1 ] ! = ' \\ ' )
temp + = " \\ " ;
# else
if ( ! temp . empty ( ) & & temp [ temp . size ( ) - 1 ] ! = ' / ' )
temp + = " / " ;
# endif
return startsWith ( item , temp ) ;
} ;
const auto testCPath = [ & ] ( const char * temp ) {
if ( temp & & temp [ 0 ] )
return testPath ( temp ) ;
return false ;
} ;
# ifdef _WIN32
// Normalize slashes.
item = ReplaceAll ( str , " / " , " \\ " ) ;
wchar_t tempPath [ MAX_PATH ] ;
GetTempPath ( MAX_PATH , tempPath ) ;
if ( testPath ( ConvertWStringToUTF8 ( tempPath ) ) )
return true ;
# endif
if ( testCPath ( getenv ( " TMPDIR " ) ) )
return true ;
if ( testCPath ( getenv ( " TMP " ) ) )
return true ;
if ( testCPath ( getenv ( " TEMP " ) ) )
return true ;
return false ;
}
2013-06-10 20:06:51 +00:00
class GameButton : public UI : : Clickable {
public :
2013-08-16 10:52:16 +00:00
GameButton ( const std : : string & gamePath , bool gridStyle , UI : : LayoutParams * layoutParams = 0 )
2015-03-01 14:59:17 +00:00
: UI : : Clickable ( layoutParams ) , gridStyle_ ( gridStyle ) , gamePath_ ( gamePath ) , holdStart_ ( 0 ) , holdEnabled_ ( true ) { }
2013-06-10 20:06:51 +00:00
2015-02-02 23:11:51 +00:00
void Draw ( UIContext & dc ) override ;
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override {
2013-08-16 10:52:16 +00:00
if ( gridStyle_ ) {
w = 144 ;
h = 80 ;
} else {
w = 500 ;
h = 50 ;
}
2013-06-10 20:06:51 +00:00
}
2013-08-16 10:52:16 +00:00
2013-06-10 20:06:51 +00:00
const std : : string & GamePath ( ) const { return gamePath_ ; }
2013-12-06 10:44:46 +00:00
2013-12-11 19:37:57 +00:00
void SetHoldEnabled ( bool hold ) {
holdEnabled_ = hold ;
}
2015-02-02 23:11:51 +00:00
void Touch ( const TouchInput & input ) override {
2013-07-22 20:36:56 +00:00
UI : : Clickable : : Touch ( input ) ;
2014-01-25 19:24:06 +00:00
hovering_ = bounds_ . Contains ( input . x , input . y ) ;
2015-03-01 14:59:17 +00:00
if ( hovering_ & & ( input . flags & TOUCH_DOWN ) ) {
holdStart_ = time_now_d ( ) ;
}
2013-07-22 20:36:56 +00:00
if ( input . flags & TOUCH_UP ) {
2015-03-01 14:59:17 +00:00
holdStart_ = 0 ;
2013-07-22 20:36:56 +00:00
}
}
2013-12-06 10:44:46 +00:00
2015-02-02 23:11:51 +00:00
bool Key ( const KeyInput & key ) override {
2014-01-25 19:24:06 +00:00
std : : vector < int > pspKeys ;
bool showInfo = false ;
2014-01-31 05:54:38 +00:00
if ( KeyMap : : KeyToPspButton ( key . deviceId , key . keyCode , & pspKeys ) ) {
2014-01-25 19:24:06 +00:00
for ( auto it = pspKeys . begin ( ) , end = pspKeys . end ( ) ; it ! = end ; + + it ) {
// If the button mapped to triangle, then show the info.
2014-01-31 05:54:38 +00:00
if ( HasFocus ( ) & & ( key . flags & KEY_UP ) & & * it = = CTRL_TRIANGLE ) {
2014-01-25 19:24:06 +00:00
showInfo = true ;
}
}
} else if ( hovering_ & & key . deviceId = = DEVICE_ID_MOUSE & & key . keyCode = = NKCODE_EXT_MOUSEBUTTON_2 ) {
// If it's the right mouse button, and it's not otherwise mapped, show the info also.
2014-01-31 05:54:38 +00:00
if ( key . flags & KEY_UP ) {
2014-01-25 19:24:06 +00:00
showInfo = true ;
}
}
if ( showInfo ) {
TriggerOnHoldClick ( ) ;
2015-02-02 23:11:51 +00:00
return true ;
2014-01-25 19:24:06 +00:00
}
2015-02-02 23:11:51 +00:00
return Clickable : : Key ( key ) ;
2014-01-25 19:24:06 +00:00
}
2017-03-15 05:01:18 +00:00
void Update ( ) override {
2014-01-25 19:24:06 +00:00
// Hold button for 1.5 seconds to launch the game options
2015-03-01 14:59:17 +00:00
if ( holdEnabled_ & & holdStart_ ! = 0.0 & & holdStart_ < time_now_d ( ) - 1.5 ) {
2014-01-25 19:24:06 +00:00
TriggerOnHoldClick ( ) ;
2013-07-22 20:36:56 +00:00
}
}
2015-02-02 23:11:51 +00:00
void FocusChanged ( int focusFlags ) override {
2014-06-22 01:04:27 +00:00
UI : : Clickable : : FocusChanged ( focusFlags ) ;
TriggerOnHighlight ( focusFlags ) ;
}
2013-07-22 20:36:56 +00:00
UI : : Event OnHoldClick ;
2014-06-22 01:04:27 +00:00
UI : : Event OnHighlight ;
2013-07-22 20:36:56 +00:00
2013-06-10 20:06:51 +00:00
private :
2014-01-25 19:24:06 +00:00
void TriggerOnHoldClick ( ) {
2015-03-01 14:59:17 +00:00
holdStart_ = 0.0 ;
2017-03-22 01:34:52 +00:00
UI : : EventParams e { } ;
2014-01-25 19:24:06 +00:00
e . v = this ;
e . s = gamePath_ ;
down_ = false ;
OnHoldClick . Trigger ( e ) ;
}
2014-06-22 01:04:27 +00:00
void TriggerOnHighlight ( int focusFlags ) {
2017-03-22 01:34:52 +00:00
UI : : EventParams e { } ;
2014-06-22 01:04:27 +00:00
e . v = this ;
e . s = gamePath_ ;
e . a = focusFlags ;
OnHighlight . Trigger ( e ) ;
}
2014-01-25 19:24:06 +00:00
2013-08-16 10:52:16 +00:00
bool gridStyle_ ;
2013-06-10 20:06:51 +00:00
std : : string gamePath_ ;
2013-12-06 10:44:46 +00:00
std : : string title_ ;
2013-10-09 14:26:15 +00:00
2015-03-01 14:59:17 +00:00
double holdStart_ ;
2013-12-11 19:37:57 +00:00
bool holdEnabled_ ;
2014-01-25 19:24:06 +00:00
bool hovering_ ;
2013-06-10 20:06:51 +00:00
} ;
void GameButton : : Draw ( UIContext & dc ) {
2017-05-18 10:52:03 +00:00
std : : shared_ptr < GameInfo > ginfo = g_gameInfoCache - > GetInfo ( dc . GetDrawContext ( ) , gamePath_ , 0 ) ;
2016-12-25 19:54:37 +00:00
Draw : : Texture * texture = 0 ;
2013-07-15 15:41:24 +00:00
u32 color = 0 , shadowColor = 0 ;
2014-12-22 09:48:17 +00:00
using namespace UI ;
2013-07-15 15:41:24 +00:00
2017-03-26 07:00:57 +00:00
if ( ginfo - > icon . texture ) {
texture = ginfo - > icon . texture - > GetTexture ( ) ;
2013-06-10 20:06:51 +00:00
}
int x = bounds_ . x ;
int y = bounds_ . y ;
2013-08-16 10:52:16 +00:00
int w = 144 ;
2013-06-10 20:06:51 +00:00
int h = bounds_ . h ;
2013-08-16 10:52:16 +00:00
UI : : Style style = dc . theme - > itemStyle ;
2013-08-20 16:18:30 +00:00
if ( down_ )
style = dc . theme - > itemDownStyle ;
2013-08-16 10:52:16 +00:00
if ( ! gridStyle_ | | ! texture ) {
h = 50 ;
if ( HasFocus ( ) )
style = down_ ? dc . theme - > itemDownStyle : dc . theme - > itemFocusedStyle ;
2013-12-11 19:37:57 +00:00
Drawable bg = style . background ;
2013-08-18 20:30:34 +00:00
dc . Draw ( ) - > Flush ( ) ;
dc . RebindTexture ( ) ;
2013-12-11 19:37:57 +00:00
dc . FillRect ( bg , bounds_ ) ;
2013-08-18 20:30:34 +00:00
dc . Draw ( ) - > Flush ( ) ;
2013-08-16 10:52:16 +00:00
}
2013-06-10 20:06:51 +00:00
if ( texture ) {
2017-03-26 07:00:57 +00:00
color = whiteAlpha ( ease ( ( time_now_d ( ) - ginfo - > icon . timeLoaded ) * 2 ) ) ;
shadowColor = blackAlpha ( ease ( ( time_now_d ( ) - ginfo - > icon . timeLoaded ) * 2 ) ) ;
2013-06-10 20:06:51 +00:00
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 ;
2013-08-20 16:18:30 +00:00
if ( ! gridStyle_ ) txOffset = 0 ;
2013-06-10 20:06:51 +00:00
2013-12-11 19:37:57 +00:00
Bounds overlayBounds = bounds_ ;
u32 overlayColor = 0 ;
2015-03-01 14:59:17 +00:00
if ( holdEnabled_ & & holdStart_ ! = 0.0 ) {
double time_held = time_now_d ( ) - holdStart_ ;
overlayColor = whiteAlpha ( time_held / 2.5f ) ;
}
2013-12-11 19:37:57 +00:00
2013-06-10 20:06:51 +00:00
// Render button
int dropsize = 10 ;
if ( texture ) {
2013-08-12 22:06:48 +00:00
if ( txOffset ) {
dropsize = 3 ;
y + = txOffset * 2 ;
2013-12-11 19:37:57 +00:00
overlayBounds . y + = txOffset * 2 ;
2013-08-12 22:06:48 +00:00
}
2013-07-15 15:41:24 +00:00
if ( HasFocus ( ) ) {
2013-08-19 22:49:25 +00:00
dc . Draw ( ) - > Flush ( ) ;
dc . RebindTexture ( ) ;
2014-06-22 16:16:10 +00:00
float pulse = sinf ( time_now ( ) * 7.0f ) * 0.25 + 0.8 ;
dc . Draw ( ) - > DrawImage4Grid ( dc . theme - > dropShadow4Grid , x - dropsize * 1.5f , y - dropsize * 1.5f , x + w + dropsize * 1.5f , y + h + dropsize * 1.5f , alphaMul ( color , pulse ) , 1.0f ) ;
2013-08-19 22:49:25 +00:00
dc . Draw ( ) - > Flush ( ) ;
2013-07-15 15:41:24 +00:00
} else {
2013-08-10 21:04:23 +00:00
dc . Draw ( ) - > Flush ( ) ;
dc . RebindTexture ( ) ;
2013-08-19 22:49:25 +00:00
dc . Draw ( ) - > DrawImage4Grid ( dc . theme - > dropShadow4Grid , x - dropsize , y - dropsize * 0.5f , x + w + dropsize , y + h + dropsize * 1.5 , alphaMul ( shadowColor , 0.5f ) , 1.0f ) ;
2013-07-15 15:41:24 +00:00
dc . Draw ( ) - > Flush ( ) ;
2013-06-10 20:06:51 +00:00
}
}
if ( texture ) {
2013-07-15 16:57:42 +00:00
dc . Draw ( ) - > Flush ( ) ;
2017-01-30 13:33:38 +00:00
dc . GetDrawContext ( ) - > BindTexture ( 0 , texture ) ;
2015-03-01 14:59:17 +00:00
if ( holdStart_ ! = 0.0 ) {
double time_held = time_now_d ( ) - holdStart_ ;
int holdFrameCount = ( int ) ( time_held * 60.0f ) ;
if ( holdFrameCount > 60 ) {
// Blink before launching by holding
if ( ( ( holdFrameCount > > 3 ) & 1 ) = = 0 )
color = darkenColor ( color ) ;
}
2013-07-22 20:36:56 +00:00
}
2013-06-10 20:06:51 +00:00
dc . Draw ( ) - > DrawTexRect ( x , y , x + w , y + h , 0 , 0 , 1 , 1 , color ) ;
dc . Draw ( ) - > Flush ( ) ;
2013-08-16 10:52:16 +00:00
}
2013-11-25 17:14:11 +00:00
char discNumInfo [ 8 ] ;
if ( ginfo - > disc_total > 1 )
2013-11-28 06:22:39 +00:00
sprintf ( discNumInfo , " -DISC%d " , ginfo - > disc_number ) ;
2013-11-25 17:14:11 +00:00
else
2013-11-28 06:22:39 +00:00
strcpy ( discNumInfo , " " ) ;
2013-11-25 17:14:11 +00:00
2013-08-18 20:30:34 +00:00
dc . Draw ( ) - > Flush ( ) ;
dc . RebindTexture ( ) ;
2013-08-30 12:47:28 +00:00
dc . SetFontStyle ( dc . theme - > uiFont ) ;
2013-08-16 10:52:16 +00:00
if ( ! gridStyle_ ) {
2013-11-26 13:45:36 +00:00
float tw , th ;
2013-08-18 20:30:34 +00:00
dc . Draw ( ) - > Flush ( ) ;
dc . PushScissor ( bounds_ ) ;
2015-12-24 21:18:46 +00:00
const std : : string currentTitle = ginfo - > GetTitle ( ) ;
if ( ! currentTitle . empty ( ) ) {
title_ = ReplaceAll ( currentTitle + discNumInfo , " & " , " && " ) ;
2013-12-11 09:32:39 +00:00
title_ = ReplaceAll ( title_ , " \n " , " " ) ;
2013-12-06 10:44:46 +00:00
}
2013-11-26 13:45:36 +00:00
2016-08-07 23:49:50 +00:00
dc . MeasureText ( dc . GetFontStyle ( ) , 1.0f , 1.0f , title_ . c_str ( ) , & tw , & th , 0 ) ;
2013-11-26 13:45:36 +00:00
int availableWidth = bounds_ . w - 150 ;
float sineWidth = std : : max ( 0.0f , ( tw - availableWidth ) ) / 2.0f ;
float tx = 150 ;
if ( availableWidth < tw ) {
tx - = ( 1.0f + sin ( time_now_d ( ) * 1.5f ) ) * sineWidth ;
Bounds tb = bounds_ ;
tb . x = bounds_ . x + 150 ;
tb . w = bounds_ . w - 150 ;
dc . PushScissor ( tb ) ;
}
2013-12-06 10:44:46 +00:00
dc . DrawText ( title_ . c_str ( ) , bounds_ . x + tx , bounds_ . centerY ( ) , style . fgColor , ALIGN_VCENTER ) ;
2013-11-26 13:45:36 +00:00
if ( availableWidth < tw ) {
dc . PopScissor ( ) ;
}
2013-08-18 20:30:34 +00:00
dc . Draw ( ) - > Flush ( ) ;
dc . PopScissor ( ) ;
} else if ( ! texture ) {
dc . Draw ( ) - > Flush ( ) ;
2013-08-16 10:52:16 +00:00
dc . PushScissor ( bounds_ ) ;
2013-12-06 10:44:46 +00:00
dc . DrawText ( title_ . c_str ( ) , bounds_ . x + 4 , bounds_ . centerY ( ) , style . fgColor , ALIGN_VCENTER ) ;
2013-08-18 20:30:34 +00:00
dc . Draw ( ) - > Flush ( ) ;
2013-08-16 10:52:16 +00:00
dc . PopScissor ( ) ;
2013-08-18 20:30:34 +00:00
} else {
dc . Draw ( ) - > Flush ( ) ;
2013-06-10 20:06:51 +00:00
}
2015-12-24 21:18:46 +00:00
if ( ginfo - > hasConfig & & ! ginfo - > id . empty ( ) ) {
2014-12-15 22:01:07 +00:00
dc . Draw ( ) - > DrawImage ( I_GEAR , x , y + h - ui_images [ I_GEAR ] . h , 1.0f ) ;
}
2013-12-11 19:37:57 +00:00
if ( overlayColor ) {
dc . FillRect ( Drawable ( overlayColor ) , overlayBounds ) ;
}
2013-08-30 12:47:28 +00:00
dc . RebindTexture ( ) ;
2013-06-10 20:06:51 +00:00
}
2013-11-29 12:02:08 +00:00
enum GameBrowserFlags {
FLAG_HOMEBREWSTOREBUTTON = 1
} ;
2013-12-11 10:03:43 +00:00
class DirButton : public UI : : Button {
public :
2013-12-08 06:39:35 +00:00
DirButton ( const std : : string & path , UI : : LayoutParams * layoutParams )
: UI : : Button ( path , layoutParams ) , path_ ( path ) , absolute_ ( false ) { }
2014-12-22 09:48:17 +00:00
DirButton ( const std : : string & path , const std : : string & text , UI : : LayoutParams * layoutParams = 0 )
2013-12-08 06:39:35 +00:00
: UI : : Button ( text , layoutParams ) , path_ ( path ) , absolute_ ( true ) { }
2013-12-11 10:03:43 +00:00
virtual void Draw ( UIContext & dc ) ;
2013-12-08 06:39:35 +00:00
const std : : string GetPath ( ) const {
return path_ ;
}
bool PathAbsolute ( ) const {
return absolute_ ;
}
private :
std : : string path_ ;
bool absolute_ ;
2013-12-11 10:03:43 +00:00
} ;
void DirButton : : Draw ( UIContext & dc ) {
2014-12-22 09:48:17 +00:00
using namespace UI ;
2013-12-11 10:03:43 +00:00
Style style = dc . theme - > buttonStyle ;
if ( HasFocus ( ) ) style = dc . theme - > buttonFocusedStyle ;
if ( down_ ) style = dc . theme - > buttonDownStyle ;
if ( ! IsEnabled ( ) ) style = dc . theme - > buttonDisabledStyle ;
dc . FillRect ( style . background , bounds_ ) ;
const std : : string text = GetText ( ) ;
int image = I_FOLDER ;
if ( text = = " .. " ) {
image = I_UP_DIRECTORY ;
}
float tw , th ;
2016-08-07 23:49:50 +00:00
dc . MeasureText ( dc . GetFontStyle ( ) , 1.0f , 1.0f , text . c_str ( ) , & tw , & th , 0 ) ;
2013-12-11 10:03:43 +00:00
bool compact = bounds_ . w < 180 ;
if ( compact ) {
// No icon, except "up"
dc . PushScissor ( bounds_ ) ;
if ( image = = I_FOLDER ) {
dc . DrawText ( text . c_str ( ) , bounds_ . x + 5 , bounds_ . centerY ( ) , style . fgColor , ALIGN_VCENTER ) ;
} else {
dc . Draw ( ) - > DrawImage ( image , bounds_ . centerX ( ) , bounds_ . centerY ( ) , 1.0f , 0xFFFFFFFF , ALIGN_CENTER ) ;
}
dc . PopScissor ( ) ;
} else {
bool scissor = false ;
if ( tw + 150 > bounds_ . w ) {
dc . PushScissor ( bounds_ ) ;
scissor = true ;
}
dc . Draw ( ) - > DrawImage ( image , bounds_ . x + 72 , bounds_ . centerY ( ) , .88f , 0xFFFFFFFF , ALIGN_CENTER ) ;
dc . DrawText ( text . c_str ( ) , bounds_ . x + 150 , bounds_ . centerY ( ) , style . fgColor , ALIGN_VCENTER ) ;
if ( scissor ) {
dc . PopScissor ( ) ;
}
}
}
2013-11-29 12:02:08 +00:00
GameBrowser : : GameBrowser ( std : : string path , bool allowBrowsing , bool * gridStyle , std : : string lastText , std : : string lastLink , int flags , UI : : LayoutParams * layoutParams )
: LinearLayout ( UI : : ORIENT_VERTICAL , layoutParams ) , gameList_ ( 0 ) , path_ ( path ) , gridStyle_ ( gridStyle ) , allowBrowsing_ ( allowBrowsing ) , lastText_ ( lastText ) , lastLink_ ( lastLink ) , flags_ ( flags ) {
2013-08-16 10:52:16 +00:00
using namespace UI ;
2013-06-27 14:28:11 +00:00
Refresh ( ) ;
2013-08-16 10:52:16 +00:00
}
2013-06-27 14:28:11 +00:00
2019-02-17 15:48:32 +00:00
void GameBrowser : : FocusGame ( const std : : string & gamePath ) {
2016-02-08 01:15:19 +00:00
focusGamePath_ = gamePath ;
Refresh ( ) ;
focusGamePath_ . clear ( ) ;
}
2019-02-17 15:48:32 +00:00
void GameBrowser : : SetPath ( const std : : string & path ) {
path_ . SetPath ( path ) ;
g_Config . currentDirectory = path_ . GetPath ( ) ;
Refresh ( ) ;
}
2013-08-16 10:52:16 +00:00
UI : : EventReturn GameBrowser : : LayoutChange ( UI : : EventParams & e ) {
2013-08-18 20:30:34 +00:00
* gridStyle_ = e . a = = 0 ? true : false ;
2013-08-16 10:52:16 +00:00
Refresh ( ) ;
return UI : : EVENT_DONE ;
}
UI : : EventReturn GameBrowser : : LastClick ( UI : : EventParams & e ) {
LaunchBrowser ( lastLink_ . c_str ( ) ) ;
return UI : : EVENT_DONE ;
}
UI : : EventReturn GameBrowser : : HomeClick ( UI : : EventParams & e ) {
2016-10-12 09:13:16 +00:00
# ifdef __ANDROID__
2019-02-17 15:48:32 +00:00
SetPath ( g_Config . memStickDirectory ) ;
2013-10-19 18:48:28 +00:00
# elif defined(USING_QT_UI)
2019-02-17 15:48:32 +00:00
System_SendMessage ( " browse_folder " , " " ) ;
2013-10-15 11:28:09 +00:00
# elif defined(_WIN32)
2017-02-24 23:25:46 +00:00
# if PPSSPP_PLATFORM(UWP)
// TODO UWP
# else
2015-07-01 22:02:08 +00:00
I18NCategory * mm = GetI18NCategory ( " MainMenu " ) ;
std : : string folder = W32Util : : BrowseForFolder ( MainWindow : : GetHWND ( ) , mm - > T ( " Choose folder " ) ) ;
2013-10-15 11:28:09 +00:00
if ( ! folder . size ( ) )
return UI : : EVENT_DONE ;
2019-02-17 15:48:32 +00:00
SetPath ( folder ) ;
2017-02-24 23:25:46 +00:00
# endif
2013-10-21 10:21:22 +00:00
# else
2019-02-17 15:48:32 +00:00
SetPath ( getenv ( " HOME " ) ) ;
2013-10-15 11:28:09 +00:00
# endif
2013-08-16 10:52:16 +00:00
return UI : : EVENT_DONE ;
2013-06-27 14:28:11 +00:00
}
2013-12-08 06:39:35 +00:00
UI : : EventReturn GameBrowser : : PinToggleClick ( UI : : EventParams & e ) {
auto & pinnedPaths = g_Config . vPinnedPaths ;
2018-09-05 04:53:20 +00:00
const std : : string path = File : : ResolvePath ( path_ . GetPath ( ) ) ;
2013-12-08 06:39:35 +00:00
if ( IsCurrentPathPinned ( ) ) {
2018-09-05 04:53:20 +00:00
pinnedPaths . erase ( std : : remove ( pinnedPaths . begin ( ) , pinnedPaths . end ( ) , path ) , pinnedPaths . end ( ) ) ;
2013-12-08 06:39:35 +00:00
} else {
2018-09-05 04:53:20 +00:00
pinnedPaths . push_back ( path ) ;
2013-12-08 06:39:35 +00:00
}
Refresh ( ) ;
return UI : : EVENT_DONE ;
}
2016-07-04 03:48:27 +00:00
bool GameBrowser : : DisplayTopBar ( ) {
return path_ . GetPath ( ) ! = " !RECENT " ;
}
bool GameBrowser : : HasSpecialFiles ( std : : vector < std : : string > & filenames ) {
if ( path_ . GetPath ( ) = = " !RECENT " ) {
filenames = g_Config . recentIsos ;
return true ;
}
return false ;
}
2013-06-10 20:06:51 +00:00
void GameBrowser : : Refresh ( ) {
2013-08-16 10:52:16 +00:00
using namespace UI ;
2013-11-29 12:02:08 +00:00
homebrewStoreButton_ = 0 ;
2013-08-16 10:52:16 +00:00
// Kill all the contents
Clear ( ) ;
2013-12-03 16:38:58 +00:00
Add ( new Spacer ( 1.0f ) ) ;
2015-07-01 22:02:08 +00:00
I18NCategory * mm = GetI18NCategory ( " MainMenu " ) ;
2013-08-20 10:28:17 +00:00
2013-12-03 15:17:24 +00:00
// No topbar on recent screen
2016-07-04 03:48:27 +00:00
if ( DisplayTopBar ( ) ) {
2013-12-03 15:17:24 +00:00
LinearLayout * topBar = new LinearLayout ( ORIENT_HORIZONTAL , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ;
if ( allowBrowsing_ ) {
2013-12-03 16:38:58 +00:00
topBar - > Add ( new Spacer ( 2.0f ) ) ;
2016-08-07 20:37:20 +00:00
topBar - > Add ( new TextView ( path_ . GetFriendlyPath ( ) . c_str ( ) , ALIGN_VCENTER | FLAG_WRAP_TEXT , true , new LinearLayoutParams ( FILL_PARENT , 64.0f , 1.0f ) ) ) ;
2013-11-21 02:44:06 +00:00
# if defined(_WIN32) || defined(USING_QT_UI)
2016-08-07 20:34:47 +00:00
topBar - > Add ( new Choice ( mm - > T ( " Browse " , " Browse... " ) , new LayoutParams ( WRAP_CONTENT , 64.0f ) ) ) - > OnClick . Handle ( this , & GameBrowser : : HomeClick ) ;
2013-10-21 10:21:22 +00:00
# else
2016-08-07 20:34:47 +00:00
topBar - > Add ( new Choice ( mm - > T ( " Home " ) , new LayoutParams ( WRAP_CONTENT , 64.0f ) ) ) - > OnClick . Handle ( this , & GameBrowser : : HomeClick ) ;
2013-08-16 10:52:16 +00:00
# endif
2013-12-03 15:17:24 +00:00
} else {
2016-08-07 20:34:47 +00:00
topBar - > Add ( new Spacer ( new LinearLayoutParams ( FILL_PARENT , 64.0f , 1.0f ) ) ) ;
2013-12-03 15:17:24 +00:00
}
2013-11-29 15:46:47 +00:00
2013-12-03 15:17:24 +00:00
ChoiceStrip * layoutChoice = topBar - > Add ( new ChoiceStrip ( ORIENT_HORIZONTAL ) ) ;
layoutChoice - > AddChoice ( I_GRID ) ;
layoutChoice - > AddChoice ( I_LINES ) ;
layoutChoice - > SetSelection ( * gridStyle_ ? 0 : 1 ) ;
layoutChoice - > OnChoice . Handle ( this , & GameBrowser : : LayoutChange ) ;
Add ( topBar ) ;
}
2013-11-29 15:46:47 +00:00
2013-08-18 20:30:34 +00:00
if ( * gridStyle_ ) {
2013-08-16 10:52:16 +00:00
gameList_ = new UI : : GridLayout ( UI : : GridLayoutSettings ( 150 , 85 ) , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ;
} else {
2013-08-20 16:18:30 +00:00
UI : : LinearLayout * gl = new UI : : LinearLayout ( UI : : ORIENT_VERTICAL , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ;
gl - > SetSpacing ( 4.0f ) ;
gameList_ = gl ;
2013-08-16 10:52:16 +00:00
}
Add ( gameList_ ) ;
2013-06-10 20:06:51 +00:00
// Find games in the current directory and create new ones.
2013-12-08 06:39:35 +00:00
std : : vector < DirButton * > dirButtons ;
2013-06-27 14:28:11 +00:00
std : : vector < GameButton * > gameButtons ;
2016-07-04 03:48:27 +00:00
std : : vector < std : : string > filenames ;
if ( HasSpecialFiles ( filenames ) ) {
for ( size_t i = 0 ; i < filenames . size ( ) ; i + + ) {
gameButtons . push_back ( new GameButton ( filenames [ i ] , * gridStyle_ , new UI : : LinearLayoutParams ( * gridStyle_ = = true ? UI : : WRAP_CONTENT : UI : : FILL_PARENT , UI : : WRAP_CONTENT ) ) ) ;
2013-06-27 14:28:11 +00:00
}
} else {
2013-06-10 20:06:51 +00:00
std : : vector < FileInfo > fileInfo ;
2017-11-22 09:52:57 +00:00
path_ . GetListing ( fileInfo , " iso:cso:pbp:elf:prx:ppdmp: " ) ;
2013-06-10 20:06:51 +00:00
for ( size_t i = 0 ; i < fileInfo . size ( ) ; i + + ) {
2013-12-08 06:54:23 +00:00
bool isGame = ! fileInfo [ i ] . isDirectory ;
2015-06-11 18:22:16 +00:00
bool isSaveData = false ;
2013-12-08 06:54:23 +00:00
// Check if eboot directory
if ( ! isGame & & path_ . GetPath ( ) . size ( ) > = 4 & & File : : Exists ( path_ . GetPath ( ) + fileInfo [ i ] . name + " /EBOOT.PBP " ) )
isGame = true ;
else if ( ! isGame & & File : : Exists ( path_ . GetPath ( ) + fileInfo [ i ] . name + " /PSP_GAME/SYSDIR " ) )
isGame = true ;
2015-06-11 18:22:16 +00:00
else if ( ! isGame & & File : : Exists ( path_ . GetPath ( ) + fileInfo [ i ] . name + " /PARAM.SFO " ) )
isSaveData = true ;
2013-12-08 06:54:23 +00:00
2015-06-11 18:22:16 +00:00
if ( ! isGame & & ! isSaveData ) {
2013-12-11 09:11:01 +00:00
if ( allowBrowsing_ ) {
2013-12-11 10:03:43 +00:00
dirButtons . push_back ( new DirButton ( fileInfo [ i ] . name , new UI : : LinearLayoutParams ( UI : : FILL_PARENT , UI : : FILL_PARENT ) ) ) ;
2013-12-11 09:11:01 +00:00
}
2013-06-27 14:28:11 +00:00
} else {
2013-08-18 20:30:34 +00:00
gameButtons . push_back ( new GameButton ( fileInfo [ i ] . fullName , * gridStyle_ , new UI : : LinearLayoutParams ( * gridStyle_ = = true ? UI : : WRAP_CONTENT : UI : : FILL_PARENT , UI : : WRAP_CONTENT ) ) ) ;
2013-06-27 14:28:11 +00:00
}
2013-06-10 20:06:51 +00:00
}
2013-08-19 22:49:25 +00:00
// Put RAR/ZIP files at the end to get them out of the way. They're only shown so that people
// can click them and get an explanation that they need to unpack them. This is necessary due
// to a flood of support email...
if ( allowBrowsing_ ) {
fileInfo . clear ( ) ;
2014-10-20 22:09:24 +00:00
path_ . GetListing ( fileInfo , " zip:rar:r01:7z: " ) ;
2013-12-11 17:25:55 +00:00
if ( ! fileInfo . empty ( ) ) {
UI : : LinearLayout * zl = new UI : : LinearLayout ( UI : : ORIENT_VERTICAL , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ;
2013-12-11 19:01:17 +00:00
zl - > SetSpacing ( 4.0f ) ;
2013-12-11 17:25:55 +00:00
Add ( zl ) ;
for ( size_t i = 0 ; i < fileInfo . size ( ) ; i + + ) {
if ( ! fileInfo [ i ] . isDirectory ) {
2013-12-11 19:37:57 +00:00
GameButton * b = zl - > Add ( new GameButton ( fileInfo [ i ] . fullName , false , new UI : : LinearLayoutParams ( UI : : FILL_PARENT , UI : : WRAP_CONTENT ) ) ) ;
b - > OnClick . Handle ( this , & GameBrowser : : GameButtonClick ) ;
b - > SetHoldEnabled ( false ) ;
2013-12-11 17:25:55 +00:00
}
2013-08-19 22:49:25 +00:00
}
}
}
2013-06-10 20:06:51 +00:00
}
2013-12-05 11:07:21 +00:00
if ( allowBrowsing_ ) {
2013-12-11 10:03:43 +00:00
gameList_ - > Add ( new DirButton ( " .. " , new UI : : LinearLayoutParams ( UI : : FILL_PARENT , UI : : FILL_PARENT ) ) ) - >
OnClick . Handle ( this , & GameBrowser : : NavigateClick ) ;
2013-12-08 06:39:35 +00:00
// Add any pinned paths before other directories.
auto pinnedPaths = GetPinnedPaths ( ) ;
for ( auto it = pinnedPaths . begin ( ) , end = pinnedPaths . end ( ) ; it ! = end ; + + it ) {
gameList_ - > Add ( new DirButton ( * it , GetBaseName ( * it ) , new UI : : LinearLayoutParams ( UI : : FILL_PARENT , UI : : FILL_PARENT ) ) ) - >
OnClick . Handle ( this , & GameBrowser : : NavigateClick ) ;
}
2013-12-05 11:07:21 +00:00
}
2013-06-27 14:28:11 +00:00
for ( size_t i = 0 ; i < dirButtons . size ( ) ; i + + ) {
2013-08-16 10:52:16 +00:00
gameList_ - > Add ( dirButtons [ i ] ) - > OnClick . Handle ( this , & GameBrowser : : NavigateClick ) ;
2013-06-27 14:28:11 +00:00
}
for ( size_t i = 0 ; i < gameButtons . size ( ) ; i + + ) {
2013-08-16 10:52:16 +00:00
GameButton * b = gameList_ - > Add ( gameButtons [ i ] ) ;
2013-07-22 20:36:56 +00:00
b - > OnClick . Handle ( this , & GameBrowser : : GameButtonClick ) ;
b - > OnHoldClick . Handle ( this , & GameBrowser : : GameButtonHoldClick ) ;
2014-06-22 01:04:27 +00:00
b - > OnHighlight . Handle ( this , & GameBrowser : : GameButtonHighlight ) ;
2016-02-08 01:15:19 +00:00
if ( ! focusGamePath_ . empty ( ) & & b - > GamePath ( ) = = focusGamePath_ ) {
b - > SetFocus ( ) ;
}
2013-06-10 20:06:51 +00:00
}
2013-08-16 10:52:16 +00:00
2013-12-08 06:39:35 +00:00
// Show a button to toggle pinning at the very end.
if ( allowBrowsing_ ) {
std : : string caption = IsCurrentPathPinned ( ) ? " - " : " + " ;
if ( ! * gridStyle_ ) {
2015-07-01 22:02:08 +00:00
caption = IsCurrentPathPinned ( ) ? mm - > T ( " UnpinPath " , " Unpin " ) : mm - > T ( " PinPath " , " Pin " ) ;
2013-12-08 06:39:35 +00:00
}
gameList_ - > Add ( new UI : : Button ( caption , new UI : : LinearLayoutParams ( UI : : FILL_PARENT , UI : : FILL_PARENT ) ) ) - >
OnClick . Handle ( this , & GameBrowser : : PinToggleClick ) ;
}
2015-07-04 08:33:36 +00:00
if ( flags_ & FLAG_HOMEBREWSTOREBUTTON ) {
2013-11-29 12:02:08 +00:00
Add ( new Spacer ( ) ) ;
2015-07-01 22:02:08 +00:00
homebrewStoreButton_ = Add ( new Choice ( mm - > T ( " DownloadFromStore " , " Download from the PPSSPP Homebrew Store " ) , new UI : : LinearLayoutParams ( UI : : WRAP_CONTENT , UI : : WRAP_CONTENT ) ) ) ;
2013-12-05 11:07:21 +00:00
} else {
homebrewStoreButton_ = 0 ;
2013-11-29 12:02:08 +00:00
}
2013-08-17 04:47:50 +00:00
if ( ! lastText_ . empty ( ) & & gameButtons . empty ( ) ) {
2013-08-16 10:52:16 +00:00
Add ( new Spacer ( ) ) ;
2013-08-16 14:48:43 +00:00
Add ( new Choice ( lastText_ , new UI : : LinearLayoutParams ( UI : : WRAP_CONTENT , UI : : WRAP_CONTENT ) ) ) - > OnClick . Handle ( this , & GameBrowser : : LastClick ) ;
2013-08-16 10:52:16 +00:00
}
2013-06-10 20:06:51 +00:00
}
2013-12-08 06:39:35 +00:00
bool GameBrowser : : IsCurrentPathPinned ( ) {
const auto paths = g_Config . vPinnedPaths ;
2018-09-05 04:53:20 +00:00
return std : : find ( paths . begin ( ) , paths . end ( ) , File : : ResolvePath ( path_ . GetPath ( ) ) ) ! = paths . end ( ) ;
2013-12-08 06:39:35 +00:00
}
const std : : vector < std : : string > GameBrowser : : GetPinnedPaths ( ) {
2014-01-02 00:45:37 +00:00
# ifndef _WIN32
2013-12-08 06:39:35 +00:00
static const std : : string sepChars = " / " ;
# else
static const std : : string sepChars = " / \\ " ;
# endif
2018-09-05 04:53:20 +00:00
const std : : string currentPath = File : : ResolvePath ( path_ . GetPath ( ) ) ;
2013-12-08 06:39:35 +00:00
const std : : vector < std : : string > paths = g_Config . vPinnedPaths ;
std : : vector < std : : string > results ;
for ( size_t i = 0 ; i < paths . size ( ) ; + + i ) {
// We want to exclude the current path, and its direct children.
if ( paths [ i ] = = currentPath ) {
continue ;
}
if ( startsWith ( paths [ i ] , currentPath ) ) {
std : : string descendant = paths [ i ] . substr ( currentPath . size ( ) ) ;
// If there's only one separator (or none), its a direct child.
if ( descendant . find_last_of ( sepChars ) = = descendant . find_first_of ( sepChars ) ) {
continue ;
}
}
results . push_back ( paths [ i ] ) ;
}
return results ;
}
const std : : string GameBrowser : : GetBaseName ( const std : : string & path ) {
2014-01-02 00:45:37 +00:00
# ifndef _WIN32
2013-12-08 06:39:35 +00:00
static const std : : string sepChars = " / " ;
# else
static const std : : string sepChars = " / \\ " ;
# endif
auto trailing = path . find_last_not_of ( sepChars ) ;
if ( trailing ! = path . npos ) {
size_t start = path . find_last_of ( sepChars , trailing ) ;
if ( start ! = path . npos ) {
return path . substr ( start + 1 , trailing - start ) ;
}
return path . substr ( 0 , trailing ) ;
}
size_t start = path . find_last_of ( sepChars ) ;
if ( start ! = path . npos ) {
return path . substr ( start + 1 ) ;
}
return path ;
}
2013-06-10 20:06:51 +00:00
UI : : EventReturn GameBrowser : : GameButtonClick ( UI : : EventParams & e ) {
GameButton * button = static_cast < GameButton * > ( e . v ) ;
2017-02-27 20:57:46 +00:00
UI : : EventParams e2 { } ;
2013-06-10 20:06:51 +00:00
e2 . s = button - > GamePath ( ) ;
// Insta-update - here we know we are already on the right thread.
OnChoice . Trigger ( e2 ) ;
return UI : : EVENT_DONE ;
}
2013-07-22 20:36:56 +00:00
UI : : EventReturn GameBrowser : : GameButtonHoldClick ( UI : : EventParams & e ) {
GameButton * button = static_cast < GameButton * > ( e . v ) ;
2017-02-27 20:57:46 +00:00
UI : : EventParams e2 { } ;
2013-07-22 20:36:56 +00:00
e2 . s = button - > GamePath ( ) ;
// Insta-update - here we know we are already on the right thread.
OnHoldChoice . Trigger ( e2 ) ;
return UI : : EVENT_DONE ;
}
2014-06-22 01:04:27 +00:00
UI : : EventReturn GameBrowser : : GameButtonHighlight ( UI : : EventParams & e ) {
// Insta-update - here we know we are already on the right thread.
OnHighlight . Trigger ( e ) ;
return UI : : EVENT_DONE ;
}
2013-06-27 14:28:11 +00:00
UI : : EventReturn GameBrowser : : NavigateClick ( UI : : EventParams & e ) {
2019-02-17 15:48:32 +00:00
DirButton * button = static_cast < DirButton * > ( e . v ) ;
2013-12-08 06:39:35 +00:00
std : : string text = button - > GetPath ( ) ;
if ( button - > PathAbsolute ( ) ) {
path_ . SetPath ( text ) ;
} else {
path_ . Navigate ( text ) ;
}
2013-06-27 14:28:11 +00:00
g_Config . currentDirectory = path_ . GetPath ( ) ;
Refresh ( ) ;
return UI : : EVENT_DONE ;
}
2014-06-22 16:32:57 +00:00
MainScreen : : MainScreen ( ) : highlightProgress_ ( 0.0f ) , prevHighlightProgress_ ( 0.0f ) , backFromStore_ ( false ) , lockBackgroundAudio_ ( false ) {
2013-12-04 16:41:59 +00:00
System_SendMessage ( " event " , " mainscreen " ) ;
2014-06-22 15:02:04 +00:00
SetBackgroundAudioGame ( " " ) ;
2014-06-29 19:02:32 +00:00
lastVertical_ = UseVerticalLayout ( ) ;
2013-12-04 16:41:59 +00:00
}
2014-06-22 15:02:04 +00:00
MainScreen : : ~ MainScreen ( ) {
SetBackgroundAudioGame ( " " ) ;
}
2013-06-10 20:06:51 +00:00
void MainScreen : : CreateViews ( ) {
// Information in the top left.
// Back button to the bottom left.
// Scrolling action menu to the right.
using namespace UI ;
2014-06-29 19:02:32 +00:00
bool vertical = UseVerticalLayout ( ) ;
2013-10-10 09:09:48 +00:00
2015-07-01 22:02:08 +00:00
I18NCategory * mm = GetI18NCategory ( " MainMenu " ) ;
2013-08-11 15:25:50 +00:00
2013-08-20 18:02:20 +00:00
Margins actionMenuMargins ( 0 , 10 , 10 , 0 ) ;
2013-06-10 20:06:51 +00:00
2017-12-13 05:38:45 +00:00
tabHolder_ = new TabHolder ( ORIENT_HORIZONTAL , 64 , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT , 1.0f ) ) ;
ViewGroup * leftColumn = tabHolder_ ;
2016-01-23 06:38:21 +00:00
tabHolder_ - > SetTag ( " MainScreenGames " ) ;
2016-02-08 01:15:19 +00:00
gameBrowsers_ . clear ( ) ;
2014-03-03 11:56:01 +00:00
2017-12-13 05:35:18 +00:00
tabHolder_ - > SetClip ( true ) ;
2013-06-10 20:06:51 +00:00
2016-03-06 01:18:24 +00:00
bool showRecent = g_Config . iMaxRecent > 0 ;
bool hasStorageAccess = System_GetPermissionStatus ( SYSTEM_PERMISSION_STORAGE ) = = PERMISSION_STATUS_GRANTED ;
2018-06-02 23:32:55 +00:00
bool storageIsTemporary = IsTempPath ( GetSysDirectory ( DIRECTORY_SAVEDATA ) ) & & ! confirmedTemporary_ ;
2016-03-06 01:18:24 +00:00
if ( showRecent & & ! hasStorageAccess ) {
showRecent = ! g_Config . recentIsos . empty ( ) ;
}
if ( showRecent ) {
2014-06-29 03:44:24 +00:00
ScrollView * scrollRecentGames = new ScrollView ( ORIENT_VERTICAL , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ;
2016-01-23 06:52:13 +00:00
scrollRecentGames - > SetTag ( " MainScreenRecentGames " ) ;
2014-06-29 03:44:24 +00:00
GameBrowser * tabRecentGames = new GameBrowser (
" !RECENT " , false , & g_Config . bGridView1 , " " , " " , 0 ,
new LinearLayoutParams ( FILL_PARENT , FILL_PARENT ) ) ;
scrollRecentGames - > Add ( tabRecentGames ) ;
2016-02-08 01:15:19 +00:00
gameBrowsers_ . push_back ( tabRecentGames ) ;
2017-12-13 05:35:18 +00:00
tabHolder_ - > AddTab ( mm - > T ( " Recent " ) , scrollRecentGames ) ;
2014-06-29 03:44:24 +00:00
tabRecentGames - > OnChoice . Handle ( this , & MainScreen : : OnGameSelectedInstant ) ;
tabRecentGames - > OnHoldChoice . Handle ( this , & MainScreen : : OnGameSelected ) ;
tabRecentGames - > OnHighlight . Handle ( this , & MainScreen : : OnGameHighlight ) ;
}
2013-06-27 14:28:11 +00:00
2018-06-02 23:32:55 +00:00
Button * focusButton = nullptr ;
2016-03-06 01:18:24 +00:00
if ( hasStorageAccess ) {
2015-12-17 21:41:50 +00:00
ScrollView * scrollAllGames = new ScrollView ( ORIENT_VERTICAL , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ;
2016-01-23 06:52:13 +00:00
scrollAllGames - > SetTag ( " MainScreenAllGames " ) ;
2015-12-17 21:41:50 +00:00
ScrollView * scrollHomebrew = new ScrollView ( ORIENT_VERTICAL , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ;
2016-01-23 06:52:13 +00:00
scrollHomebrew - > SetTag ( " MainScreenHomebrew " ) ;
2013-06-27 14:28:11 +00:00
2015-12-17 21:41:50 +00:00
GameBrowser * tabAllGames = new GameBrowser ( g_Config . currentDirectory , true , & g_Config . bGridView2 ,
mm - > T ( " How to get games " ) , " http://www.ppsspp.org/getgames.html " , 0 ,
new LinearLayoutParams ( FILL_PARENT , FILL_PARENT ) ) ;
GameBrowser * tabHomebrew = new GameBrowser ( GetSysDirectory ( DIRECTORY_GAME ) , false , & g_Config . bGridView3 ,
mm - > T ( " How to get homebrew & demos " , " How to get homebrew && demos " ) , " http://www.ppsspp.org/gethomebrew.html " ,
FLAG_HOMEBREWSTOREBUTTON ,
new LinearLayoutParams ( FILL_PARENT , FILL_PARENT ) ) ;
2013-11-29 12:02:08 +00:00
2015-12-17 21:41:50 +00:00
Choice * hbStore = tabHomebrew - > HomebrewStoreButton ( ) ;
if ( hbStore ) {
hbStore - > OnClick . Handle ( this , & MainScreen : : OnHomebrewStore ) ;
}
2013-06-27 14:28:11 +00:00
2015-12-17 21:41:50 +00:00
scrollAllGames - > Add ( tabAllGames ) ;
2016-02-08 01:15:19 +00:00
gameBrowsers_ . push_back ( tabAllGames ) ;
2015-12-17 21:41:50 +00:00
scrollHomebrew - > Add ( tabHomebrew ) ;
2016-02-08 01:15:19 +00:00
gameBrowsers_ . push_back ( tabHomebrew ) ;
2013-06-10 20:06:51 +00:00
2017-12-13 05:35:18 +00:00
tabHolder_ - > AddTab ( mm - > T ( " Games " ) , scrollAllGames ) ;
tabHolder_ - > AddTab ( mm - > T ( " Homebrew & Demos " ) , scrollHomebrew ) ;
2014-06-29 03:44:24 +00:00
2015-12-17 21:41:50 +00:00
tabAllGames - > OnChoice . Handle ( this , & MainScreen : : OnGameSelectedInstant ) ;
tabHomebrew - > OnChoice . Handle ( this , & MainScreen : : OnGameSelectedInstant ) ;
2014-06-29 03:44:24 +00:00
2015-12-17 21:41:50 +00:00
tabAllGames - > OnHoldChoice . Handle ( this , & MainScreen : : OnGameSelected ) ;
tabHomebrew - > OnHoldChoice . Handle ( this , & MainScreen : : OnGameSelected ) ;
2013-06-10 20:06:51 +00:00
2015-12-17 21:41:50 +00:00
tabAllGames - > OnHighlight . Handle ( this , & MainScreen : : OnGameHighlight ) ;
tabHomebrew - > OnHighlight . Handle ( this , & MainScreen : : OnGameHighlight ) ;
if ( g_Config . recentIsos . size ( ) > 0 ) {
2017-12-13 05:34:17 +00:00
tabHolder_ - > SetCurrentTab ( 0 , true ) ;
2015-12-17 21:41:50 +00:00
} else if ( g_Config . iMaxRecent > 0 ) {
2017-12-13 05:34:17 +00:00
tabHolder_ - > SetCurrentTab ( 1 , true ) ;
2015-12-17 21:41:50 +00:00
}
2013-06-10 20:06:51 +00:00
2015-12-17 21:41:50 +00:00
if ( backFromStore_ | | showHomebrewTab ) {
2017-12-13 05:34:17 +00:00
tabHolder_ - > SetCurrentTab ( 2 , true ) ;
2015-12-17 21:41:50 +00:00
backFromStore_ = false ;
showHomebrewTab = false ;
}
2018-06-02 23:32:55 +00:00
if ( storageIsTemporary ) {
LinearLayout * buttonHolder = new LinearLayout ( ORIENT_HORIZONTAL , new LinearLayoutParams ( WRAP_CONTENT , WRAP_CONTENT ) ) ;
buttonHolder - > Add ( new Spacer ( new LinearLayoutParams ( 1.0f ) ) ) ;
focusButton = new Button ( mm - > T ( " SavesAreTemporaryIgnore " , " Ignore warning " ) , new LinearLayoutParams ( WRAP_CONTENT , WRAP_CONTENT ) ) ;
focusButton - > SetPadding ( 32 , 16 ) ;
buttonHolder - > Add ( focusButton ) - > OnClick . Add ( [ this ] ( UI : : EventParams & e ) {
confirmedTemporary_ = true ;
RecreateViews ( ) ;
return UI : : EVENT_DONE ;
} ) ;
buttonHolder - > Add ( new Spacer ( new LinearLayoutParams ( 1.0f ) ) ) ;
leftColumn - > Add ( new Spacer ( new LinearLayoutParams ( 0.1f ) ) ) ;
leftColumn - > Add ( new TextView ( mm - > T ( " SavesAreTemporary " , " PPSSPP saving in temporary storage " ) , ALIGN_HCENTER , false ) ) ;
leftColumn - > Add ( new TextView ( mm - > T ( " SavesAreTemporaryGuidance " , " Extract PPSSPP somewhere to save permanently " ) , ALIGN_HCENTER , false ) ) ;
leftColumn - > Add ( new Spacer ( 10.0f ) ) ;
leftColumn - > Add ( buttonHolder ) ;
leftColumn - > Add ( new Spacer ( new LinearLayoutParams ( 0.1f ) ) ) ;
}
2015-12-17 21:41:50 +00:00
} else {
2017-12-13 05:38:45 +00:00
if ( ! showRecent ) {
leftColumn = new LinearLayout ( ORIENT_VERTICAL , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT , 1.0f ) ) ;
// Just so it's destroyed on recreate.
leftColumn - > Add ( tabHolder_ ) ;
tabHolder_ - > SetVisibility ( V_GONE ) ;
}
2016-03-06 01:18:24 +00:00
LinearLayout * buttonHolder = new LinearLayout ( ORIENT_HORIZONTAL , new LinearLayoutParams ( WRAP_CONTENT , WRAP_CONTENT ) ) ;
buttonHolder - > Add ( new Spacer ( new LinearLayoutParams ( 1.0f ) ) ) ;
2018-06-02 23:32:55 +00:00
focusButton = new Button ( mm - > T ( " Give PPSSPP permission to access storage " ) , new LinearLayoutParams ( WRAP_CONTENT , WRAP_CONTENT ) ) ;
focusButton - > SetPadding ( 32 , 16 ) ;
buttonHolder - > Add ( focusButton ) - > OnClick . Handle ( this , & MainScreen : : OnAllowStorage ) ;
2016-03-06 01:18:24 +00:00
buttonHolder - > Add ( new Spacer ( new LinearLayoutParams ( 1.0f ) ) ) ;
2017-12-13 05:35:18 +00:00
leftColumn - > Add ( new Spacer ( new LinearLayoutParams ( 0.1f ) ) ) ;
2016-03-06 01:18:24 +00:00
leftColumn - > Add ( buttonHolder ) ;
leftColumn - > Add ( new Spacer ( 10.0f ) ) ;
leftColumn - > Add ( new TextView ( mm - > T ( " PPSSPP can't load games or save right now " ) , ALIGN_HCENTER , false ) ) ;
2017-12-13 05:35:18 +00:00
leftColumn - > Add ( new Spacer ( new LinearLayoutParams ( 0.1f ) ) ) ;
2013-11-20 15:36:58 +00:00
}
2013-11-29 15:46:47 +00:00
2013-10-09 14:26:15 +00:00
ViewGroup * rightColumn = new ScrollView ( ORIENT_VERTICAL ) ;
LinearLayout * rightColumnItems = new LinearLayout ( ORIENT_VERTICAL , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ;
2013-10-22 14:18:43 +00:00
rightColumnItems - > SetSpacing ( 0.0f ) ;
2013-06-10 20:06:51 +00:00
rightColumn - > Add ( rightColumnItems ) ;
2013-06-27 14:28:11 +00:00
2013-08-19 22:49:25 +00:00
char versionString [ 256 ] ;
sprintf ( versionString , " %s " , PPSSPP_GIT_VERSION ) ;
rightColumnItems - > SetSpacing ( 0.0f ) ;
LinearLayout * logos = new LinearLayout ( ORIENT_HORIZONTAL ) ;
2017-04-30 00:35:12 +00:00
if ( System_GetPropertyBool ( SYSPROP_APP_GOLD ) ) {
2017-04-05 14:21:08 +00:00
logos - > Add ( new ImageView ( I_ICONGOLD , IS_DEFAULT , new AnchorLayoutParams ( 64 , 64 , 10 , 10 , NONE , NONE , false ) ) ) ;
} else {
logos - > Add ( new ImageView ( I_ICON , IS_DEFAULT , new AnchorLayoutParams ( 64 , 64 , 10 , 10 , NONE , NONE , false ) ) ) ;
}
2013-08-19 22:49:25 +00:00
logos - > Add ( new ImageView ( I_LOGO , IS_DEFAULT , new LinearLayoutParams ( Margins ( - 12 , 0 , 0 , 0 ) ) ) ) ;
rightColumnItems - > Add ( logos ) ;
2015-09-23 15:34:16 +00:00
TextView * ver = rightColumnItems - > Add ( new TextView ( versionString , new LinearLayoutParams ( Margins ( 70 , - 6 , 0 , 0 ) ) ) ) ;
ver - > SetSmall ( true ) ;
ver - > SetClip ( false ) ;
2019-02-17 15:30:40 +00:00
# if defined(_WIN32) || defined(USING_QT_UI)
2015-07-01 22:02:08 +00:00
rightColumnItems - > Add ( new Choice ( mm - > T ( " Load " , " Load... " ) ) ) - > OnClick . Handle ( this , & MainScreen : : OnLoadFile ) ;
2013-06-27 14:28:11 +00:00
# endif
2015-07-01 22:02:08 +00:00
rightColumnItems - > Add ( new Choice ( mm - > T ( " Game Settings " , " Settings " ) ) ) - > OnClick . Handle ( this , & MainScreen : : OnGameSettings ) ;
rightColumnItems - > Add ( new Choice ( mm - > T ( " Credits " ) ) ) - > OnClick . Handle ( this , & MainScreen : : OnCredits ) ;
rightColumnItems - > Add ( new Choice ( mm - > T ( " www.ppsspp.org " ) ) ) - > OnClick . Handle ( this , & MainScreen : : OnPPSSPPOrg ) ;
2017-04-30 00:35:12 +00:00
if ( ! System_GetPropertyBool ( SYSPROP_APP_GOLD ) ) {
2018-11-03 16:35:21 +00:00
Choice * gold = rightColumnItems - > Add ( new Choice ( mm - > T ( " Buy PPSSPP Gold " ) ) ) ;
2017-04-05 14:21:08 +00:00
gold - > OnClick . Handle ( this , & MainScreen : : OnSupport ) ;
gold - > SetIcon ( I_ICONGOLD ) ;
}
2017-02-27 10:32:40 +00:00
# if !PPSSPP_PLATFORM(UWP)
// Having an exit button is against UWP guidelines.
2014-03-03 11:56:01 +00:00
rightColumnItems - > Add ( new Spacer ( 25.0 ) ) ;
2015-07-01 22:02:08 +00:00
rightColumnItems - > Add ( new Choice ( mm - > T ( " Exit " ) ) ) - > OnClick . Handle ( this , & MainScreen : : OnExit ) ;
2017-02-27 10:32:40 +00:00
# endif
2013-11-26 13:04:29 +00:00
2013-10-09 14:26:15 +00:00
if ( vertical ) {
root_ = new LinearLayout ( ORIENT_VERTICAL ) ;
2017-02-18 21:35:31 +00:00
rightColumn - > ReplaceLayoutParams ( new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT , 0.75 ) ) ;
2013-11-29 15:46:47 +00:00
root_ - > Add ( rightColumn ) ;
2013-10-09 14:26:15 +00:00
root_ - > Add ( leftColumn ) ;
} else {
root_ = new LinearLayout ( ORIENT_HORIZONTAL ) ;
rightColumn - > ReplaceLayoutParams ( new LinearLayoutParams ( 300 , FILL_PARENT , actionMenuMargins ) ) ;
2013-11-24 08:08:05 +00:00
root_ - > Add ( leftColumn ) ;
2013-10-09 14:26:15 +00:00
root_ - > Add ( rightColumn ) ;
}
2013-11-26 13:04:29 +00:00
2018-06-02 23:32:55 +00:00
if ( focusButton ) {
root_ - > SetDefaultFocusView ( focusButton ) ;
2017-12-30 01:55:37 +00:00
} else if ( tabHolder_ - > GetVisibility ( ) ! = V_GONE ) {
root_ - > SetDefaultFocusView ( tabHolder_ ) ;
}
2014-03-03 11:56:01 +00:00
2013-11-26 13:04:29 +00:00
I18NCategory * u = GetI18NCategory ( " Upgrade " ) ;
upgradeBar_ = 0 ;
if ( ! g_Config . upgradeMessage . empty ( ) ) {
upgradeBar_ = new LinearLayout ( ORIENT_HORIZONTAL , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ;
UI : : Margins textMargins ( 10 , 5 ) ;
UI : : Margins buttonMargins ( 0 , 0 ) ;
UI : : Drawable solid ( 0xFFbd9939 ) ;
upgradeBar_ - > SetBG ( solid ) ;
upgradeBar_ - > Add ( new TextView ( u - > T ( " New version of PPSSPP available " ) + std : : string ( " : " ) + g_Config . upgradeVersion , new LinearLayoutParams ( 1.0f , textMargins ) ) ) ;
upgradeBar_ - > Add ( new Button ( u - > T ( " Download " ) , new LinearLayoutParams ( buttonMargins ) ) ) - > OnClick . Handle ( this , & MainScreen : : OnDownloadUpgrade ) ;
upgradeBar_ - > Add ( new Button ( u - > T ( " Dismiss " ) , new LinearLayoutParams ( buttonMargins ) ) ) - > OnClick . Handle ( this , & MainScreen : : OnDismissUpgrade ) ;
// Slip in under root_
LinearLayout * newRoot = new LinearLayout ( ORIENT_VERTICAL ) ;
newRoot - > Add ( root_ ) ;
newRoot - > Add ( upgradeBar_ ) ;
root_ - > ReplaceLayoutParams ( new LinearLayoutParams ( 1.0 ) ) ;
root_ = newRoot ;
}
}
2015-12-17 21:41:50 +00:00
UI : : EventReturn MainScreen : : OnAllowStorage ( UI : : EventParams & e ) {
System_AskForPermission ( SYSTEM_PERMISSION_STORAGE ) ;
return UI : : EVENT_DONE ;
}
2013-11-26 13:04:29 +00:00
UI : : EventReturn MainScreen : : OnDownloadUpgrade ( UI : : EventParams & e ) {
2017-04-05 14:21:08 +00:00
# if PPSSPP_PLATFORM(ANDROID)
2013-11-26 13:04:29 +00:00
// Go to app store
2017-04-30 00:35:12 +00:00
if ( System_GetPropertyBool ( SYSPROP_APP_GOLD ) ) {
2017-04-05 14:21:08 +00:00
LaunchBrowser ( " market://details?id=org.ppsspp.ppssppgold " ) ;
} else {
LaunchBrowser ( " market://details?id=org.ppsspp.ppsspp " ) ;
}
2013-11-26 13:04:29 +00:00
# else
// Go directly to ppsspp.org and let the user sort it out
2017-11-14 11:50:27 +00:00
LaunchBrowser ( " https://www.ppsspp.org/downloads.html " ) ;
2013-11-26 13:04:29 +00:00
# endif
2014-12-22 09:48:17 +00:00
return UI : : EVENT_DONE ;
2013-11-26 13:04:29 +00:00
}
UI : : EventReturn MainScreen : : OnDismissUpgrade ( UI : : EventParams & e ) {
g_Config . DismissUpgrade ( ) ;
2014-12-22 09:48:17 +00:00
upgradeBar_ - > SetVisibility ( UI : : V_GONE ) ;
return UI : : EVENT_DONE ;
2013-06-10 20:06:51 +00:00
}
2013-07-08 10:35:08 +00:00
void MainScreen : : sendMessage ( const char * message , const char * value ) {
2013-10-21 20:52:44 +00:00
// Always call the base class method first to handle the most common messages.
UIScreenWithBackground : : sendMessage ( message , value ) ;
2019-02-17 15:48:32 +00:00
if ( screenManager ( ) - > topScreen ( ) = = this ) {
if ( ! strcmp ( message , " boot " ) ) {
screenManager ( ) - > switchScreen ( new EmuScreen ( value ) ) ;
}
if ( ! strcmp ( message , " browse_folderSelect " ) ) {
int tab = tabHolder_ - > GetCurrentTab ( ) ;
if ( tab > = 0 & & tab < ( int ) gameBrowsers_ . size ( ) ) {
gameBrowsers_ [ tab ] - > SetPath ( value ) ;
}
}
2013-07-08 10:35:08 +00:00
}
2015-12-17 21:41:50 +00:00
if ( ! strcmp ( message , " permission_granted " ) & & ! strcmp ( value , " storage " ) ) {
RecreateViews ( ) ;
}
2013-07-08 10:35:08 +00:00
}
2017-03-15 05:01:18 +00:00
void MainScreen : : update ( ) {
UIScreen : : update ( ) ;
2013-09-15 16:35:58 +00:00
UpdateUIState ( UISTATE_MENU ) ;
2014-06-29 19:02:32 +00:00
bool vertical = UseVerticalLayout ( ) ;
if ( vertical ! = lastVertical_ ) {
RecreateViews ( ) ;
lastVertical_ = vertical ;
}
}
bool MainScreen : : UseVerticalLayout ( ) const {
return dp_yres > dp_xres * 1.1f ;
2013-06-10 20:06:51 +00:00
}
2013-06-27 14:28:11 +00:00
UI : : EventReturn MainScreen : : OnLoadFile ( UI : : EventParams & e ) {
2017-04-30 00:35:12 +00:00
if ( System_GetPropertyBool ( SYSPROP_HAS_FILE_BROWSER ) ) {
2017-04-02 17:50:09 +00:00
System_SendMessage ( " browse_file " , " " ) ;
}
2013-06-27 14:28:11 +00:00
return UI : : EVENT_DONE ;
}
2014-06-22 01:04:27 +00:00
void MainScreen : : DrawBackground ( UIContext & dc ) {
UIScreenWithBackground : : DrawBackground ( dc ) ;
if ( highlightedGamePath_ . empty ( ) & & prevHighlightedGamePath_ . empty ( ) ) {
return ;
}
if ( DrawBackgroundFor ( dc , prevHighlightedGamePath_ , 1.0f - prevHighlightProgress_ ) ) {
if ( prevHighlightProgress_ < 1.0f ) {
prevHighlightProgress_ + = 1.0f / 20.0f ;
}
}
if ( ! highlightedGamePath_ . empty ( ) ) {
if ( DrawBackgroundFor ( dc , highlightedGamePath_ , highlightProgress_ ) ) {
if ( highlightProgress_ < 1.0f ) {
highlightProgress_ + = 1.0f / 20.0f ;
}
}
}
}
bool MainScreen : : DrawBackgroundFor ( UIContext & dc , const std : : string & gamePath , float progress ) {
dc . Flush ( ) ;
2017-05-18 10:52:03 +00:00
std : : shared_ptr < GameInfo > ginfo ;
2014-06-22 01:04:27 +00:00
if ( ! gamePath . empty ( ) ) {
2017-01-30 13:33:38 +00:00
ginfo = g_gameInfoCache - > GetInfo ( dc . GetDrawContext ( ) , gamePath , GAMEINFO_WANTBG ) ;
2014-06-22 01:04:27 +00:00
// Loading texture data may bind a texture.
dc . RebindTexture ( ) ;
// Let's not bother if there's no picture.
2017-03-26 07:00:57 +00:00
if ( ! ginfo | | ( ! ginfo - > pic1 . texture & & ! ginfo - > pic0 . texture ) ) {
2014-06-22 01:04:27 +00:00
return false ;
}
} else {
return false ;
}
2018-07-21 20:47:29 +00:00
Draw : : Texture * texture = nullptr ;
2017-03-26 07:00:57 +00:00
if ( ginfo - > pic1 . texture ) {
2018-07-21 20:47:29 +00:00
texture = ginfo - > pic1 . texture - > GetTexture ( ) ;
2017-03-26 07:00:57 +00:00
} else if ( ginfo - > pic0 . texture ) {
2018-07-21 20:47:29 +00:00
texture = ginfo - > pic0 . texture - > GetTexture ( ) ;
2014-06-22 01:04:27 +00:00
}
uint32_t color = whiteAlpha ( ease ( progress ) ) & 0xFFc0c0c0 ;
2018-07-21 20:47:29 +00:00
if ( texture ) {
dc . GetDrawContext ( ) - > BindTexture ( 0 , texture ) ;
dc . Draw ( ) - > DrawTexRect ( dc . GetBounds ( ) , 0 , 0 , 1 , 1 , color ) ;
dc . Flush ( ) ;
dc . RebindTexture ( ) ;
}
2014-06-22 01:04:27 +00:00
return true ;
}
2013-06-10 20:06:51 +00:00
UI : : EventReturn MainScreen : : OnGameSelected ( UI : : EventParams & e ) {
2014-06-22 16:16:10 +00:00
# ifdef _WIN32
2013-10-12 00:03:11 +00:00
std : : string path = ReplaceAll ( e . s , " \\ " , " / " ) ;
2013-09-15 04:08:53 +00:00
# else
std : : string path = e . s ;
# endif
2017-05-18 10:52:03 +00:00
std : : shared_ptr < GameInfo > ginfo = g_gameInfoCache - > GetInfo ( nullptr , path , GAMEINFO_WANTBG ) ;
2017-03-02 11:29:03 +00:00
if ( ginfo & & ginfo - > fileType = = IdentifiedFileType : : PSP_SAVEDATA_DIRECTORY ) {
2015-06-12 12:46:34 +00:00
return UI : : EVENT_DONE ;
}
2017-05-18 12:21:13 +00:00
if ( g_GameManager . GetState ( ) = = GameManagerState : : INSTALLING )
return UI : : EVENT_DONE ;
2016-02-08 01:15:19 +00:00
// Restore focus if it was highlighted (e.g. by gamepad.)
restoreFocusGamePath_ = highlightedGamePath_ ;
2014-06-22 16:16:10 +00:00
SetBackgroundAudioGame ( path ) ;
2014-06-22 16:32:57 +00:00
lockBackgroundAudio_ = true ;
2013-09-15 04:08:53 +00:00
screenManager ( ) - > push ( new GameScreen ( path ) ) ;
2013-06-10 20:06:51 +00:00
return UI : : EVENT_DONE ;
}
2014-06-22 01:04:27 +00:00
UI : : EventReturn MainScreen : : OnGameHighlight ( UI : : EventParams & e ) {
2014-12-22 09:48:17 +00:00
using namespace UI ;
2014-06-22 16:16:10 +00:00
# ifdef _WIN32
2014-06-22 01:04:27 +00:00
std : : string path = ReplaceAll ( e . s , " \\ " , " / " ) ;
# else
std : : string path = e . s ;
# endif
2016-02-08 01:15:19 +00:00
// Don't change when re-highlighting what's already highlighted.
if ( path ! = highlightedGamePath_ | | e . a = = FF_LOSTFOCUS ) {
if ( ! highlightedGamePath_ . empty ( ) ) {
if ( prevHighlightedGamePath_ . empty ( ) | | prevHighlightProgress_ > = 0.75f ) {
prevHighlightedGamePath_ = highlightedGamePath_ ;
prevHighlightProgress_ = 1.0 - highlightProgress_ ;
}
highlightedGamePath_ . clear ( ) ;
}
if ( e . a = = FF_GOTFOCUS ) {
highlightedGamePath_ = path ;
highlightProgress_ = 0.0f ;
2014-06-22 01:04:27 +00:00
}
}
2014-06-22 16:16:10 +00:00
2016-02-13 09:48:11 +00:00
if ( ( ! highlightedGamePath_ . empty ( ) | | e . a = = FF_LOSTFOCUS ) & & ! lockBackgroundAudio_ ) {
2014-06-22 16:16:10 +00:00
SetBackgroundAudioGame ( highlightedGamePath_ ) ;
2016-02-13 09:48:11 +00:00
}
2014-06-22 16:32:57 +00:00
lockBackgroundAudio_ = false ;
2014-06-22 01:04:27 +00:00
return UI : : EVENT_DONE ;
}
2013-08-16 10:52:16 +00:00
UI : : EventReturn MainScreen : : OnGameSelectedInstant ( UI : : EventParams & e ) {
2014-06-22 16:16:10 +00:00
# ifdef _WIN32
2013-10-12 00:03:11 +00:00
std : : string path = ReplaceAll ( e . s , " \\ " , " / " ) ;
2013-09-15 04:08:53 +00:00
# else
std : : string path = e . s ;
# endif
2013-07-22 20:36:56 +00:00
// Go directly into the game.
2013-09-15 04:08:53 +00:00
screenManager ( ) - > switchScreen ( new EmuScreen ( path ) ) ;
2013-07-22 20:36:56 +00:00
return UI : : EVENT_DONE ;
}
2013-08-16 10:52:16 +00:00
UI : : EventReturn MainScreen : : OnGameSettings ( UI : : EventParams & e ) {
2013-09-01 20:29:23 +00:00
auto gameSettings = new GameSettingsScreen ( " " , " " ) ;
2013-09-07 16:44:28 +00:00
gameSettings - > OnRecentChanged . Handle ( this , & MainScreen : : OnRecentChange ) ;
2013-09-01 20:29:23 +00:00
screenManager ( ) - > push ( gameSettings ) ;
return UI : : EVENT_DONE ;
}
2013-09-07 16:44:28 +00:00
UI : : EventReturn MainScreen : : OnRecentChange ( UI : : EventParams & e ) {
RecreateViews ( ) ;
if ( host ) {
host - > UpdateUI ( ) ;
}
return UI : : EVENT_DONE ;
}
2013-06-10 20:06:51 +00:00
UI : : EventReturn MainScreen : : OnCredits ( UI : : EventParams & e ) {
screenManager ( ) - > push ( new CreditsScreen ( ) ) ;
return UI : : EVENT_DONE ;
}
2013-11-20 13:42:48 +00:00
UI : : EventReturn MainScreen : : OnHomebrewStore ( UI : : EventParams & e ) {
screenManager ( ) - > push ( new StoreScreen ( ) ) ;
return UI : : EVENT_DONE ;
}
2013-06-10 20:06:51 +00:00
UI : : EventReturn MainScreen : : OnSupport ( UI : : EventParams & e ) {
2016-10-12 09:13:16 +00:00
# ifdef __ANDROID__
2013-07-15 15:41:24 +00:00
LaunchBrowser ( " market://details?id=org.ppsspp.ppssppgold " ) ;
# else
2017-11-14 11:50:27 +00:00
LaunchBrowser ( " https://central.ppsspp.org/buygold " ) ;
2013-07-15 15:41:24 +00:00
# endif
2013-06-10 20:06:51 +00:00
return UI : : EVENT_DONE ;
2013-06-27 17:40:45 +00:00
}
2013-06-28 12:29:15 +00:00
2013-08-19 22:49:25 +00:00
UI : : EventReturn MainScreen : : OnPPSSPPOrg ( UI : : EventParams & e ) {
2017-11-14 11:50:27 +00:00
LaunchBrowser ( " https://www.ppsspp.org " ) ;
2013-08-19 22:49:25 +00:00
return UI : : EVENT_DONE ;
}
UI : : EventReturn MainScreen : : OnForums ( UI : : EventParams & e ) {
2017-11-14 11:50:27 +00:00
LaunchBrowser ( " https://forums.ppsspp.org " ) ;
2013-08-19 22:49:25 +00:00
return UI : : EVENT_DONE ;
}
2013-06-28 12:29:15 +00:00
UI : : EventReturn MainScreen : : OnExit ( UI : : EventParams & e ) {
2013-12-04 16:41:59 +00:00
System_SendMessage ( " event " , " exitprogram " ) ;
2014-02-11 10:32:54 +00:00
// Request the framework to exit cleanly.
System_SendMessage ( " finish " , " " ) ;
2015-12-26 03:41:17 +00:00
// However, let's make sure the config was saved, since it may not have been.
g_Config . Save ( ) ;
2016-10-12 09:13:16 +00:00
# ifdef __ANDROID__
2014-03-19 06:55:17 +00:00
# ifdef ANDROID_NDK_PROFILER
moncleanup ( ) ;
# endif
2014-02-15 09:00:29 +00:00
# endif
2014-02-11 10:32:54 +00:00
2014-06-22 07:38:46 +00:00
UpdateUIState ( UISTATE_EXIT ) ;
2013-06-28 12:29:15 +00:00
return UI : : EVENT_DONE ;
}
2013-07-21 11:31:46 +00:00
2013-11-20 15:36:58 +00:00
void MainScreen : : dialogFinished ( const Screen * dialog , DialogResult result ) {
if ( dialog - > tag ( ) = = " store " ) {
backFromStore_ = true ;
RecreateViews ( ) ;
}
2016-02-08 01:15:19 +00:00
if ( dialog - > tag ( ) = = " game " ) {
2016-02-13 09:48:11 +00:00
if ( ! restoreFocusGamePath_ . empty ( ) & & UI : : IsFocusMovementEnabled ( ) ) {
2016-02-08 01:15:19 +00:00
// Prevent the background from fading, since we just were displaying it.
highlightedGamePath_ = restoreFocusGamePath_ ;
highlightProgress_ = 1.0f ;
// Refocus the game button itself.
int tab = tabHolder_ - > GetCurrentTab ( ) ;
2016-02-13 18:57:05 +00:00
if ( tab > = 0 & & tab < ( int ) gameBrowsers_ . size ( ) ) {
2016-02-08 01:15:19 +00:00
gameBrowsers_ [ tab ] - > FocusGame ( restoreFocusGamePath_ ) ;
}
// Don't get confused next time.
restoreFocusGamePath_ . clear ( ) ;
} else {
// Not refocusing, so we need to stop the audio.
SetBackgroundAudioGame ( " " ) ;
}
}
2013-11-20 15:36:58 +00:00
}
2013-11-24 03:02:36 +00:00
void UmdReplaceScreen : : CreateViews ( ) {
2014-12-22 09:48:17 +00:00
using namespace UI ;
2013-11-24 04:14:44 +00:00
Margins actionMenuMargins ( 0 , 100 , 15 , 0 ) ;
2015-07-01 22:02:08 +00:00
I18NCategory * mm = GetI18NCategory ( " MainMenu " ) ;
2015-07-01 21:26:55 +00:00
I18NCategory * di = GetI18NCategory ( " Dialog " ) ;
2013-11-24 03:02:36 +00:00
2015-12-23 04:43:54 +00:00
TabHolder * leftColumn = new TabHolder ( ORIENT_HORIZONTAL , 64 , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT , 1.0 ) ) ;
2016-01-23 06:38:21 +00:00
leftColumn - > SetTag ( " UmdReplace " ) ;
2013-11-24 03:02:36 +00:00
leftColumn - > SetClip ( true ) ;
2013-11-24 04:14:44 +00:00
ViewGroup * rightColumn = new ScrollView ( ORIENT_VERTICAL , new LinearLayoutParams ( 270 , FILL_PARENT , actionMenuMargins ) ) ;
LinearLayout * rightColumnItems = new LinearLayout ( ORIENT_VERTICAL , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ;
rightColumnItems - > SetSpacing ( 0.0f ) ;
rightColumn - > Add ( rightColumnItems ) ;
2014-06-29 03:44:24 +00:00
if ( g_Config . iMaxRecent > 0 ) {
ScrollView * scrollRecentGames = new ScrollView ( ORIENT_VERTICAL , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ;
2016-01-23 06:52:13 +00:00
scrollRecentGames - > SetTag ( " UmdReplaceRecentGames " ) ;
2014-06-29 03:44:24 +00:00
GameBrowser * tabRecentGames = new GameBrowser (
" !RECENT " , false , & g_Config . bGridView1 , " " , " " , 0 ,
new LinearLayoutParams ( FILL_PARENT , FILL_PARENT ) ) ;
scrollRecentGames - > Add ( tabRecentGames ) ;
2015-07-01 22:02:08 +00:00
leftColumn - > AddTab ( mm - > T ( " Recent " ) , scrollRecentGames ) ;
2014-06-29 03:44:24 +00:00
tabRecentGames - > OnChoice . Handle ( this , & UmdReplaceScreen : : OnGameSelectedInstant ) ;
tabRecentGames - > OnHoldChoice . Handle ( this , & UmdReplaceScreen : : OnGameSelected ) ;
}
2013-11-24 03:02:36 +00:00
ScrollView * scrollAllGames = new ScrollView ( ORIENT_VERTICAL , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ;
2016-01-23 06:52:13 +00:00
scrollAllGames - > SetTag ( " UmdReplaceAllGames " ) ;
2013-11-24 03:02:36 +00:00
2013-11-29 12:02:08 +00:00
GameBrowser * tabAllGames = new GameBrowser ( g_Config . currentDirectory , true , & g_Config . bGridView2 ,
2015-07-01 22:02:08 +00:00
mm - > T ( " How to get games " ) , " http://www.ppsspp.org/getgames.html " , 0 ,
2013-11-24 03:02:36 +00:00
new LinearLayoutParams ( FILL_PARENT , FILL_PARENT ) ) ;
scrollAllGames - > Add ( tabAllGames ) ;
2015-07-01 22:02:08 +00:00
leftColumn - > AddTab ( mm - > T ( " Games " ) , scrollAllGames ) ;
2013-11-24 03:02:36 +00:00
tabAllGames - > OnChoice . Handle ( this , & UmdReplaceScreen : : OnGameSelectedInstant ) ;
2014-06-29 03:44:24 +00:00
2013-11-24 03:02:36 +00:00
tabAllGames - > OnHoldChoice . Handle ( this , & UmdReplaceScreen : : OnGameSelected ) ;
2015-07-01 21:26:55 +00:00
rightColumnItems - > Add ( new Choice ( di - > T ( " Cancel " ) ) ) - > OnClick . Handle ( this , & UmdReplaceScreen : : OnCancel ) ;
2015-07-01 22:02:08 +00:00
rightColumnItems - > Add ( new Choice ( mm - > T ( " Game Settings " ) ) ) - > OnClick . Handle ( this , & UmdReplaceScreen : : OnGameSettings ) ;
2013-11-24 04:14:44 +00:00
2013-11-24 03:02:36 +00:00
if ( g_Config . recentIsos . size ( ) > 0 ) {
2017-12-13 05:34:17 +00:00
leftColumn - > SetCurrentTab ( 0 , true ) ;
2014-06-29 03:44:24 +00:00
} else if ( g_Config . iMaxRecent > 0 ) {
2017-12-13 05:34:17 +00:00
leftColumn - > SetCurrentTab ( 1 , true ) ;
2013-11-24 03:02:36 +00:00
}
root_ = new LinearLayout ( ORIENT_HORIZONTAL ) ;
2013-11-29 12:02:08 +00:00
root_ - > Add ( leftColumn ) ;
root_ - > Add ( rightColumn ) ;
2013-11-24 03:02:36 +00:00
}
2017-03-15 05:01:18 +00:00
void UmdReplaceScreen : : update ( ) {
2013-11-24 03:02:36 +00:00
UpdateUIState ( UISTATE_PAUSEMENU ) ;
2017-03-15 05:01:18 +00:00
UIScreen : : update ( ) ;
2013-11-24 03:02:36 +00:00
}
UI : : EventReturn UmdReplaceScreen : : OnGameSelected ( UI : : EventParams & e ) {
__UmdReplace ( e . s ) ;
2017-03-20 00:43:03 +00:00
TriggerFinish ( DR_OK ) ;
2013-11-24 03:02:36 +00:00
return UI : : EVENT_DONE ;
}
2014-12-22 09:48:17 +00:00
UI : : EventReturn UmdReplaceScreen : : OnCancel ( UI : : EventParams & e ) {
2017-03-20 00:43:03 +00:00
TriggerFinish ( DR_CANCEL ) ;
2013-11-24 04:14:44 +00:00
return UI : : EVENT_DONE ;
}
2014-12-22 09:48:17 +00:00
UI : : EventReturn UmdReplaceScreen : : OnGameSettings ( UI : : EventParams & e ) {
2013-11-24 04:14:44 +00:00
screenManager ( ) - > push ( new GameSettingsScreen ( " " ) ) ;
return UI : : EVENT_DONE ;
}
2015-06-12 18:37:42 +00:00
2014-12-22 09:48:17 +00:00
UI : : EventReturn UmdReplaceScreen : : OnGameSelectedInstant ( UI : : EventParams & e ) {
2013-11-24 03:02:36 +00:00
__UmdReplace ( e . s ) ;
2017-03-20 00:43:03 +00:00
TriggerFinish ( DR_OK ) ;
2013-11-24 03:02:36 +00:00
return UI : : EVENT_DONE ;
}