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-27 10:15:46 +00:00
# include <algorithm>
2021-01-09 22:45:49 +00:00
# include <cmath>
# include <sstream>
2013-11-26 13:45:36 +00:00
2017-02-27 10:32:40 +00:00
# include "ppsspp_config.h"
2020-10-03 22:25:21 +00:00
2020-10-04 08:10:55 +00:00
# include "Common/System/Display.h"
2020-10-04 08:30:18 +00:00
# include "Common/System/System.h"
2020-10-04 21:24:14 +00:00
# include "Common/Render/TextureAtlas.h"
# include "Common/Render/DrawBuffer.h"
2020-10-04 18:48:47 +00:00
# include "Common/UI/Root.h"
# include "Common/UI/Context.h"
# include "Common/UI/View.h"
# include "Common/UI/ViewGroup.h"
2013-07-21 11:31:46 +00:00
2020-10-01 11:05:04 +00:00
# include "Common/Data/Color/RGBAUtil.h"
# include "Common/Data/Encoding/Utf8.h"
2020-10-03 22:25:21 +00:00
# include "Common/File/PathBrowser.h"
# include "Common/Math/curves.h"
2021-01-08 19:05:43 +00:00
# include "Common/Net/URL.h"
2020-10-04 18:48:47 +00:00
# include "Common/File/FileUtil.h"
2020-08-15 18:53:08 +00:00
# include "Common/TimeUtil.h"
2020-09-29 10:19:22 +00:00
# include "Common/StringUtils.h"
2013-07-21 11:31:46 +00:00
# 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"
2020-03-08 04:30:55 +00:00
# include "Core/ELF/PBPReader.h"
# include "Core/ELF/ParamSFO.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"
2020-07-27 14:53:02 +00:00
# include "UI/InstallZipScreen.h"
2013-06-10 20:06:51 +00:00
# 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"
2020-10-01 11:05:04 +00:00
# include "Common/Data/Text/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-12-06 11:29:27 +00:00
bool MainScreen : : showHomebrewTab = false ;
2020-07-27 14:53:02 +00:00
bool LaunchFile ( ScreenManager * screenManager , std : : string path ) {
// Depending on the file type, we don't want to launch EmuScreen at all.
auto loader = ConstructFileLoader ( path ) ;
if ( ! loader ) {
return false ;
}
IdentifiedFileType type = Identify_File ( loader ) ;
delete loader ;
switch ( type ) {
case IdentifiedFileType : : ARCHIVE_ZIP :
screenManager - > push ( new InstallZipScreen ( path ) ) ;
break ;
default :
// Let the EmuScreen take care of it.
screenManager - > switchScreen ( new EmuScreen ( path ) ) ;
break ;
}
2020-07-28 08:03:55 +00:00
return true ;
2020-07-27 14:53:02 +00:00
}
2018-06-02 23:32:55 +00:00
static bool IsTempPath ( const std : : string & str ) {
std : : string item = str ;
2021-01-09 22:45:49 +00:00
# ifdef _WIN32
// Normalize slashes.
item = ReplaceAll ( str , " / " , " \\ " ) ;
# endif
2018-06-02 23:32:55 +00:00
2021-01-09 22:45:49 +00:00
std : : vector < std : : string > tempPaths = System_GetPropertyStringVec ( SYSPROP_TEMP_DIRS ) ;
for ( auto temp : tempPaths ) {
2018-06-02 23:32:55 +00:00
# ifdef _WIN32
temp = ReplaceAll ( temp , " / " , " \\ " ) ;
if ( ! temp . empty ( ) & & temp [ temp . size ( ) - 1 ] ! = ' \\ ' )
temp + = " \\ " ;
# else
if ( ! temp . empty ( ) & & temp [ temp . size ( ) - 1 ] ! = ' / ' )
temp + = " / " ;
# endif
2021-01-09 22:45:49 +00:00
if ( startsWith ( item , temp ) )
return true ;
2020-01-04 19:06:12 +00:00
}
2018-06-02 23:32:55 +00:00
return false ;
}
2013-06-10 20:06:51 +00:00
class GameButton : public UI : : Clickable {
public :
2019-02-27 09:05:15 +00:00
GameButton ( const std : : string & gamePath , bool gridStyle , UI : : LayoutParams * layoutParams = 0 )
: UI : : Clickable ( layoutParams ) , gridStyle_ ( gridStyle ) , gamePath_ ( gamePath ) { }
2013-06-10 20:06:51 +00:00
2015-02-02 23:11:51 +00:00
void Draw ( UIContext & dc ) override ;
2021-02-22 00:38:02 +00:00
std : : string DescribeText ( ) const override ;
2015-02-02 23:11:51 +00:00
void GetContentDimensions ( const UIContext & dc , float & w , float & h ) const override {
2013-08-16 10:52:16 +00:00
if ( gridStyle_ ) {
2020-03-01 14:34:35 +00:00
w = 144 * g_Config . fGameGridScale ;
h = 80 * g_Config . fGameGridScale ;
2013-08-16 10:52:16 +00:00
} 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.
2019-03-04 01:50:54 +00:00
if ( key . flags & KEY_DOWN ) {
showInfoPressed_ = true ;
}
if ( ( key . flags & KEY_UP ) & & showInfoPressed_ ) {
2014-01-25 19:24:06 +00:00
showInfo = true ;
2019-03-04 01:50:54 +00:00
showInfoPressed_ = false ;
2014-01-25 19:24:06 +00:00
}
}
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
2019-02-27 09:05:15 +00:00
double holdStart_ = 0.0 ;
bool holdEnabled_ = true ;
2019-03-04 01:50:54 +00:00
bool showInfoPressed_ = false ;
2019-02-27 09:05:15 +00:00
bool hovering_ = false ;
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 ;
2020-03-01 14:34:35 +00:00
int w = gridStyle_ ? bounds_ . 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.
2019-10-07 21:58:23 +00:00
// Make sure it's not wider than 144 (like Doom Legacy homebrew), ugly in the grid mode.
2020-03-01 14:34:35 +00:00
float nw = std : : min ( h * tw / th , ( float ) w ) ;
2013-06-10 20:06:51 +00:00
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 ) {
2020-02-25 18:29:41 +00:00
if ( ! gridStyle_ ) {
x + = 4 ;
}
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 ( ) ;
2020-08-15 22:13:19 +00:00
float pulse = sin ( time_now_d ( ) * 7.0 ) * 0.25 + 0.8 ;
2014-06-22 16:16:10 +00:00
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
}
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 ;
2020-02-25 16:59:24 +00:00
if ( g_Config . bShowIDOnGameIcon ) {
float vw , vh ;
dc . MeasureText ( dc . GetFontStyle ( ) , 0.7f , 0.7f , ginfo - > id_version . c_str ( ) , & vw , & vh , 0 ) ;
availableWidth - = vw + 20 ;
dc . SetFontScale ( 0.7f , 0.7f ) ;
dc . DrawText ( ginfo - > id_version . c_str ( ) , availableWidth + 160 , bounds_ . centerY ( ) , style . fgColor , ALIGN_VCENTER ) ;
dc . SetFontScale ( 1.0f , 1.0f ) ;
}
2013-11-26 13:45:36 +00:00
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 ;
2020-02-25 16:59:24 +00:00
tb . w = availableWidth ;
2013-11-26 13:45:36 +00:00
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 ( ) ) {
2020-02-29 20:51:14 +00:00
const AtlasImage * gearImage = dc . Draw ( ) - > GetAtlas ( ) - > getImage ( ImageID ( " I_GEAR " ) ) ;
if ( gearImage ) {
if ( gridStyle_ ) {
2020-03-01 14:34:35 +00:00
dc . Draw ( ) - > DrawImage ( ImageID ( " I_GEAR " ) , x , y + h - gearImage - > h * g_Config . fGameGridScale , g_Config . fGameGridScale ) ;
2020-02-29 20:51:14 +00:00
} else {
dc . Draw ( ) - > DrawImage ( ImageID ( " I_GEAR " ) , x - gearImage - > w , y , 1.0f ) ;
}
2020-02-24 12:53:06 +00:00
}
2014-12-15 22:01:07 +00:00
}
2020-02-23 07:33:44 +00:00
if ( g_Config . bShowRegionOnGameIcon & & ginfo - > region > = 0 & & ginfo - > region < GAMEREGION_MAX & & ginfo - > region ! = GAMEREGION_OTHER ) {
2020-02-29 20:51:14 +00:00
const ImageID regionIcons [ GAMEREGION_MAX ] = {
ImageID ( " I_FLAG_JP " ) ,
ImageID ( " I_FLAG_US " ) ,
ImageID ( " I_FLAG_EU " ) ,
ImageID ( " I_FLAG_HK " ) ,
ImageID ( " I_FLAG_AS " ) ,
ImageID ( " I_FLAG_KO " ) ,
ImageID : : invalid ( ) ,
2020-02-23 07:33:44 +00:00
} ;
2020-02-29 20:51:14 +00:00
const AtlasImage * image = dc . Draw ( ) - > GetAtlas ( ) - > getImage ( regionIcons [ ginfo - > region ] ) ;
if ( image ) {
if ( gridStyle_ ) {
2020-03-01 14:34:35 +00:00
dc . Draw ( ) - > DrawImage ( regionIcons [ ginfo - > region ] , x + w - ( image - > w + 5 ) * g_Config . fGameGridScale ,
y + h - ( image - > h + 5 ) * g_Config . fGameGridScale , g_Config . fGameGridScale ) ;
2020-02-29 20:51:14 +00:00
} else {
dc . Draw ( ) - > DrawImage ( regionIcons [ ginfo - > region ] , x - 2 - image - > w - 3 , y + h - image - > h - 5 , 1.0f ) ;
}
2020-02-24 12:53:06 +00:00
}
2020-02-23 07:33:44 +00:00
}
2020-02-24 12:53:06 +00:00
if ( gridStyle_ & & g_Config . bShowIDOnGameIcon ) {
2020-03-01 14:34:35 +00:00
dc . SetFontScale ( 0.5f * g_Config . fGameGridScale , 0.5f * g_Config . fGameGridScale ) ;
2020-02-25 18:29:41 +00:00
dc . DrawText ( ginfo - > id_version . c_str ( ) , x + 5 , y + 1 , 0xFF000000 , ALIGN_TOPLEFT ) ;
dc . DrawText ( ginfo - > id_version . c_str ( ) , x + 4 , y , 0xFFffFFff , ALIGN_TOPLEFT ) ;
2020-02-23 13:01:15 +00:00
dc . SetFontScale ( 1.0f , 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
}
2021-02-22 00:38:02 +00:00
std : : string GameButton : : DescribeText ( ) const {
std : : shared_ptr < GameInfo > ginfo = g_gameInfoCache - > GetInfo ( nullptr , gamePath_ , 0 ) ;
auto u = GetI18NCategory ( " UI Elements " ) ;
return ReplaceAll ( u - > T ( " %1 button " ) , " %1 " , ginfo - > GetTitle ( ) ) ;
}
2013-12-11 10:03:43 +00:00
class DirButton : public UI : : Button {
public :
2020-03-01 14:34:35 +00:00
DirButton ( const std : : string & path , bool gridStyle , UI : : LayoutParams * layoutParams )
: UI : : Button ( path , layoutParams ) , path_ ( path ) , gridStyle_ ( gridStyle ) , absolute_ ( false ) { }
DirButton ( const std : : string & path , const std : : string & text , bool gridStyle , UI : : LayoutParams * layoutParams = 0 )
: UI : : Button ( text , layoutParams ) , path_ ( path ) , gridStyle_ ( gridStyle ) , 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_ ;
2020-03-01 14:34:35 +00:00
bool gridStyle_ ;
2021-02-15 18:29:34 +00:00
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 ( ) ;
2020-02-29 20:51:14 +00:00
ImageID image = ImageID ( " I_FOLDER " ) ;
2013-12-11 10:03:43 +00:00
if ( text = = " .. " ) {
2020-02-29 20:51:14 +00:00
image = ImageID ( " I_UP_DIRECTORY " ) ;
2013-12-11 10:03:43 +00:00
}
2019-02-27 09:05:15 +00:00
2013-12-11 10:03:43 +00:00
float tw , th ;
2020-03-01 14:34:35 +00:00
dc . MeasureText ( dc . GetFontStyle ( ) , gridStyle_ ? g_Config . fGameGridScale : 1.0 , gridStyle_ ? g_Config . fGameGridScale : 1.0 , text . c_str ( ) , & tw , & th , 0 ) ;
2013-12-11 10:03:43 +00:00
2020-03-01 14:34:35 +00:00
bool compact = bounds_ . w < 180 * ( gridStyle_ ? g_Config . fGameGridScale : 1.0 ) ;
2013-12-11 10:03:43 +00:00
2020-03-01 14:34:35 +00:00
if ( gridStyle_ ) {
dc . SetFontScale ( g_Config . fGameGridScale , g_Config . fGameGridScale ) ;
}
2013-12-11 10:03:43 +00:00
if ( compact ) {
// No icon, except "up"
dc . PushScissor ( bounds_ ) ;
2020-02-29 20:51:14 +00:00
if ( image = = ImageID ( " I_FOLDER " ) ) {
2013-12-11 10:03:43 +00:00
dc . DrawText ( text . c_str ( ) , bounds_ . x + 5 , bounds_ . centerY ( ) , style . fgColor , ALIGN_VCENTER ) ;
} else {
2020-03-01 14:34:35 +00:00
dc . Draw ( ) - > DrawImage ( image , bounds_ . centerX ( ) , bounds_ . centerY ( ) , gridStyle_ ? g_Config . fGameGridScale : 1.0 , 0xFFFFFFFF , ALIGN_CENTER ) ;
2013-12-11 10:03:43 +00:00
}
dc . PopScissor ( ) ;
} else {
bool scissor = false ;
if ( tw + 150 > bounds_ . w ) {
dc . PushScissor ( bounds_ ) ;
scissor = true ;
}
2020-03-01 14:34:35 +00:00
dc . Draw ( ) - > DrawImage ( image , bounds_ . x + 72 , bounds_ . centerY ( ) , 0.88f * ( gridStyle_ ? g_Config . fGameGridScale : 1.0 ) , 0xFFFFFFFF , ALIGN_CENTER ) ;
2013-12-11 10:03:43 +00:00
dc . DrawText ( text . c_str ( ) , bounds_ . x + 150 , bounds_ . centerY ( ) , style . fgColor , ALIGN_VCENTER ) ;
if ( scissor ) {
dc . PopScissor ( ) ;
}
}
2020-03-01 14:34:35 +00:00
if ( gridStyle_ ) {
dc . SetFontScale ( 1.0 , 1.0 ) ;
}
2013-12-11 10:03:43 +00:00
}
2020-03-01 14:34:35 +00:00
GameBrowser : : GameBrowser ( std : : string path , BrowseFlags browseFlags , bool * gridStyle , ScreenManager * screenManager , std : : string lastText , std : : string lastLink , UI : : LayoutParams * layoutParams )
2021-02-15 18:29:34 +00:00
: LinearLayout ( UI : : ORIENT_VERTICAL , layoutParams ) , path_ ( path ) , gridStyle_ ( gridStyle ) , browseFlags_ ( browseFlags ) , lastText_ ( lastText ) , lastLink_ ( lastLink ) , screenManager_ ( screenManager ) {
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 ;
}
2020-03-30 20:45:29 +00:00
UI : : EventReturn GameBrowser : : BrowseClick ( UI : : EventParams & e ) {
System_SendMessage ( " browse_folder " , " " ) ;
return UI : : EVENT_DONE ;
}
UI : : EventReturn GameBrowser : : StorageClick ( UI : : EventParams & e ) {
2021-01-06 15:37:04 +00:00
std : : vector < std : : string > storageDirs = System_GetPropertyStringVec ( SYSPROP_ADDITIONAL_STORAGE_DIRS ) ;
if ( storageDirs . empty ( ) ) {
// Shouldn't happen - this button shouldn't be clickable.
return UI : : EVENT_DONE ;
}
if ( storageDirs . size ( ) = = 1 ) {
SetPath ( storageDirs [ 0 ] ) ;
} else {
// TODO: We should popup a dialog letting the user choose one.
SetPath ( storageDirs [ 0 ] ) ;
}
2020-03-30 20:45:29 +00:00
return UI : : EVENT_DONE ;
}
2013-08-16 10:52:16 +00:00
UI : : EventReturn GameBrowser : : HomeClick ( UI : : EventParams & e ) {
2021-01-07 08:40:01 +00:00
# if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(SWITCH) || defined(USING_WIN_UI) || PPSSPP_PLATFORM(UWP)
SetPath ( g_Config . memStickDirectory ) ;
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 ;
}
2019-10-06 18:49:35 +00:00
void GameBrowser : : Update ( ) {
LinearLayout : : Update ( ) ;
if ( listingPending_ & & path_ . IsListingReady ( ) ) {
Refresh ( ) ;
}
}
2020-03-01 14:34:35 +00:00
void GameBrowser : : Draw ( UIContext & dc ) {
using namespace UI ;
if ( lastScale_ ! = g_Config . fGameGridScale | | lastLayoutWasGrid_ ! = * gridStyle_ ) {
Refresh ( ) ;
}
if ( hasDropShadow_ ) {
// Darken things behind.
dc . FillRect ( UI : : Drawable ( 0x60000000 ) , dc . GetBounds ( ) . Expand ( dropShadowExpand_ ) ) ;
float dropsize = 30.0f ;
dc . Draw ( ) - > DrawImage4Grid ( dc . theme - > dropShadow4Grid ,
bounds_ . x - dropsize , bounds_ . y ,
bounds_ . x2 ( ) + dropsize , bounds_ . y2 ( ) + dropsize * 1.5f , 0xDF000000 , 3.0f ) ;
}
if ( clip_ ) {
dc . PushScissor ( bounds_ ) ;
}
dc . FillRect ( bg_ , bounds_ ) ;
for ( View * view : views_ ) {
if ( view - > GetVisibility ( ) = = V_VISIBLE ) {
// Check if bounds are in current scissor rectangle.
if ( dc . GetScissorBounds ( ) . Intersects ( dc . TransformBounds ( view - > GetBounds ( ) ) ) )
view - > Draw ( dc ) ;
}
}
if ( clip_ ) {
dc . PopScissor ( ) ;
}
}
2020-05-17 13:12:38 +00:00
static bool IsValidPBP ( const std : : string & path , bool allowHomebrew ) {
2020-03-08 04:30:55 +00:00
if ( ! File : : Exists ( path ) )
return false ;
std : : unique_ptr < FileLoader > loader ( ConstructFileLoader ( path ) ) ;
PBPReader pbp ( loader . get ( ) ) ;
std : : vector < u8 > sfoData ;
if ( ! pbp . GetSubFile ( PBP_PARAM_SFO , & sfoData ) )
return false ;
ParamSFOData sfo ;
sfo . ReadSFO ( sfoData ) ;
2020-05-17 13:12:38 +00:00
if ( ! allowHomebrew & & sfo . GetValueString ( " DISC_ID " ) . empty ( ) )
2020-03-08 04:30:55 +00:00
return false ;
if ( sfo . GetValueString ( " CATEGORY " ) = = " ME " )
return false ;
return true ;
}
2013-06-10 20:06:51 +00:00
void GameBrowser : : Refresh ( ) {
2013-08-16 10:52:16 +00:00
using namespace UI ;
2020-03-01 14:34:35 +00:00
lastScale_ = g_Config . fGameGridScale ;
lastLayoutWasGrid_ = * gridStyle_ ;
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 ) ) ;
2020-01-26 18:43:18 +00:00
auto 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 ) ) ;
2019-10-06 19:40:00 +00:00
if ( browseFlags_ & BrowseFlags : : NAVIGATE ) {
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 ) ) ) ;
2021-01-07 08:40:01 +00:00
topBar - > Add ( new Choice ( ImageID ( " I_HOME " ) , new LayoutParams ( WRAP_CONTENT , 64.0f ) ) ) - > OnClick . Handle ( this , & GameBrowser : : HomeClick ) ;
2021-01-06 15:37:04 +00:00
if ( System_GetPropertyBool ( SYSPROP_HAS_ADDITIONAL_STORAGE ) ) {
2020-03-30 20:45:29 +00:00
topBar - > Add ( new Choice ( ImageID ( " I_SDCARD " ) , new LayoutParams ( WRAP_CONTENT , 64.0f ) ) ) - > OnClick . Handle ( this , & GameBrowser : : StorageClick ) ;
}
2021-01-07 08:40:01 +00:00
if ( System_GetPropertyBool ( SYSPROP_HAS_FOLDER_BROWSER ) ) {
topBar - > Add ( new Choice ( mm - > T ( " Browse " , " Browse... " ) , new LayoutParams ( WRAP_CONTENT , 64.0f ) ) ) - > OnClick . Handle ( this , & GameBrowser : : BrowseClick ) ;
}
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
}
ChoiceStrip * layoutChoice = topBar - > Add ( new ChoiceStrip ( ORIENT_HORIZONTAL ) ) ;
2020-02-29 20:51:14 +00:00
layoutChoice - > AddChoice ( ImageID ( " I_GRID " ) ) ;
layoutChoice - > AddChoice ( ImageID ( " I_LINES " ) ) ;
2021-02-28 20:25:37 +00:00
layoutChoice - > SetSelection ( * gridStyle_ ? 0 : 1 , false ) ;
2013-12-03 15:17:24 +00:00
layoutChoice - > OnChoice . Handle ( this , & GameBrowser : : LayoutChange ) ;
2020-03-01 14:34:35 +00:00
topBar - > Add ( new Choice ( ImageID ( " I_GEAR " ) , new LayoutParams ( 64.0f , 64.0f ) ) ) - > OnClick . Handle ( this , & GameBrowser : : GridSettingsClick ) ;
2013-12-03 15:17:24 +00:00
Add ( topBar ) ;
2013-11-29 15:46:47 +00:00
2020-03-01 14:34:35 +00:00
if ( * gridStyle_ ) {
2021-02-22 02:41:08 +00:00
gameList_ = new UI : : GridLayoutList ( UI : : GridLayoutSettings ( 150 * g_Config . fGameGridScale , 85 * g_Config . fGameGridScale ) , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ;
2020-03-01 14:34:35 +00:00
Add ( gameList_ ) ;
} else {
2021-02-22 02:41:08 +00:00
UI : : LinearLayout * gl = new UI : : LinearLayoutList ( UI : : ORIENT_VERTICAL , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ;
2020-03-01 14:34:35 +00:00
gl - > SetSpacing ( 4.0f ) ;
gameList_ = gl ;
Add ( gameList_ ) ;
}
2013-08-16 10:52:16 +00:00
} else {
2020-03-01 14:34:35 +00:00
if ( * gridStyle_ ) {
2021-02-22 02:41:08 +00:00
gameList_ = new UI : : GridLayoutList ( UI : : GridLayoutSettings ( 150 * g_Config . fGameGridScale , 85 * g_Config . fGameGridScale ) , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ;
2020-03-01 14:34:35 +00:00
} else {
UI : : LinearLayout * gl = new UI : : LinearLayout ( UI : : ORIENT_VERTICAL , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) ) ;
gl - > SetSpacing ( 4.0f ) ;
gameList_ = gl ;
}
2020-03-08 21:21:59 +00:00
// Until we can come up with a better space to put it (next to the tabs?) let's get rid of the icon config
// button on the Recent tab, it's ugly. You can use the button from the other tabs.
// LinearLayout *gridOptionColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(64.0, 64.0f));
// gridOptionColumn->Add(new Spacer(12.0));
// gridOptionColumn->Add(new Choice(ImageID("I_GEAR"), new LayoutParams(64.0f, 64.0f)))->OnClick.Handle(this, &GameBrowser::GridSettingsClick);
// LinearLayout *grid = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT));
// gameList_->ReplaceLayoutParams(new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT, 0.75));
// grid->Add(gameList_);
// grid->Add(gridOptionColumn);
// Add(grid);
Add ( gameList_ ) ;
2013-08-16 10:52:16 +00:00
}
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 ;
2019-10-06 18:49:35 +00:00
listingPending_ = ! path_ . IsListingReady ( ) ;
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
}
2019-10-06 18:49:35 +00:00
} else if ( ! listingPending_ ) {
2021-04-25 18:38:22 +00:00
std : : vector < File : : 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
2020-05-17 13:12:38 +00:00
if ( ! isGame & & path_ . GetPath ( ) . size ( ) > = 4 & & IsValidPBP ( path_ . GetPath ( ) + fileInfo [ i ] . name + " /EBOOT.PBP " , true ) )
2013-12-08 06:54:23 +00:00
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 ) {
2019-10-06 19:40:00 +00:00
if ( browseFlags_ & BrowseFlags : : NAVIGATE ) {
2020-03-01 14:34:35 +00:00
dirButtons . push_back ( new DirButton ( fileInfo [ i ] . fullName , fileInfo [ i ] . name , * gridStyle_ , 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...
2019-10-06 19:40:00 +00:00
if ( browseFlags_ & BrowseFlags : : ARCHIVES ) {
2013-08-19 22:49:25 +00:00
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 ( ) ) {
2021-02-22 02:41:08 +00:00
UI : : LinearLayout * zl = new UI : : LinearLayoutList ( 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
}
2019-10-06 19:40:00 +00:00
if ( browseFlags_ & BrowseFlags : : NAVIGATE ) {
2020-12-20 00:38:45 +00:00
if ( path_ . CanNavigateUp ( ) ) {
gameList_ - > Add ( new DirButton ( " .. " , * gridStyle_ , new UI : : LinearLayoutParams ( UI : : FILL_PARENT , UI : : FILL_PARENT ) ) ) - >
OnClick . Handle ( this , & GameBrowser : : NavigateClick ) ;
}
2020-03-30 20:45:29 +00:00
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 ) {
2020-03-01 14:34:35 +00:00
gameList_ - > Add ( new DirButton ( * it , GetBaseName ( * it ) , * gridStyle_ , new UI : : LinearLayoutParams ( UI : : FILL_PARENT , UI : : FILL_PARENT ) ) ) - >
2013-12-08 06:39:35 +00:00
OnClick . Handle ( this , & GameBrowser : : NavigateClick ) ;
}
2013-12-05 11:07:21 +00:00
}
2013-06-27 14:28:11 +00:00
2019-10-06 18:49:35 +00:00
if ( listingPending_ ) {
gameList_ - > Add ( new UI : : TextView ( mm - > T ( " Loading... " ) , ALIGN_CENTER , false , new UI : : LinearLayoutParams ( UI : : FILL_PARENT , UI : : FILL_PARENT ) ) ) ;
}
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.
2019-10-06 19:40:00 +00:00
if ( browseFlags_ & BrowseFlags : : PIN ) {
2013-12-08 06:39:35 +00:00
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 ) ;
}
2019-10-06 19:40:00 +00:00
if ( browseFlags_ & BrowseFlags : : HOMEBREW_STORE ) {
2013-11-29 12:02:08 +00:00
Add ( new Spacer ( ) ) ;
2020-05-17 12:57:12 +00:00
Add ( new Choice ( mm - > T ( " DownloadFromStore " , " Download from the PPSSPP Homebrew Store " ) , new UI : : LinearLayoutParams ( UI : : WRAP_CONTENT , UI : : WRAP_CONTENT ) ) ) - > OnClick . Handle ( this , & GameBrowser : : OnHomebrewStore ) ;
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 ;
}
2020-03-02 07:34:26 +00:00
UI : : EventReturn GameBrowser : : GridSettingsClick ( UI : : EventParams & e ) {
auto sy = GetI18NCategory ( " System " ) ;
auto gridSettings = new GridSettingsScreen ( sy - > T ( " Games list settings " ) ) ;
gridSettings - > OnRecentChanged . Handle ( this , & GameBrowser : : OnRecentClear ) ;
if ( e . v )
gridSettings - > SetPopupOrigin ( e . v ) ;
screenManager_ - > push ( gridSettings ) ;
return UI : : EVENT_DONE ;
}
UI : : EventReturn GameBrowser : : OnRecentClear ( UI : : EventParams & e ) {
screenManager_ - > RecreateAllViews ( ) ;
if ( host ) {
host - > UpdateUI ( ) ;
}
return UI : : EVENT_DONE ;
}
2020-05-17 12:57:12 +00:00
UI : : EventReturn GameBrowser : : OnHomebrewStore ( UI : : EventParams & e ) {
screenManager_ - > push ( new StoreScreen ( ) ) ;
return UI : : EVENT_DONE ;
}
MainScreen : : MainScreen ( ) {
2013-12-04 16:41:59 +00:00
System_SendMessage ( " event " , " mainscreen " ) ;
2020-08-02 17:44:48 +00:00
g_BackgroundAudio . SetGame ( " " ) ;
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 ( ) {
2020-08-02 17:44:48 +00:00
g_BackgroundAudio . SetGame ( " " ) ;
2014-06-22 15:02:04 +00:00
}
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
2020-01-26 18:43:18 +00:00
auto 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 (
2020-03-01 14:34:35 +00:00
" !RECENT " , BrowseFlags : : NONE , & g_Config . bGridView1 , screenManager ( ) , " " , " " ,
2014-06-29 03:44:24 +00:00
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 ) {
2020-11-23 09:06:48 +00:00
scrollAllGames_ = new ScrollView ( ORIENT_VERTICAL , new LinearLayoutParams ( FILL_PARENT , WRAP_CONTENT ) , true ) ;
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
2020-03-01 14:34:35 +00:00
GameBrowser * tabAllGames = new GameBrowser ( g_Config . currentDirectory , BrowseFlags : : STANDARD , & g_Config . bGridView2 , screenManager ( ) ,
2019-10-06 19:40:00 +00:00
mm - > T ( " How to get games " ) , " https://www.ppsspp.org/getgames.html " ,
2015-12-17 21:41:50 +00:00
new LinearLayoutParams ( FILL_PARENT , FILL_PARENT ) ) ;
2020-03-01 14:34:35 +00:00
GameBrowser * tabHomebrew = new GameBrowser ( GetSysDirectory ( DIRECTORY_GAME ) , BrowseFlags : : HOMEBREW_STORE , & g_Config . bGridView3 , screenManager ( ) ,
2019-03-04 05:39:21 +00:00
mm - > T ( " How to get homebrew & demos " , " How to get homebrew && demos " ) , " https://www.ppsspp.org/gethomebrew.html " ,
2015-12-17 21:41:50 +00:00
new LinearLayoutParams ( FILL_PARENT , FILL_PARENT ) ) ;
2013-11-29 12:02:08 +00:00
2020-11-23 09:06:48 +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
2020-11-23 09:06:48 +00:00
tabHolder_ - > AddTab ( mm - > T ( " Games " ) , scrollAllGames_ ) ;
2017-12-13 05:35:18 +00:00
tabHolder_ - > AddTab ( mm - > T ( " Homebrew & Demos " ) , scrollHomebrew ) ;
2020-11-23 09:06:48 +00:00
scrollAllGames_ - > ScrollTo ( g_Config . fGameListScrollPosition ) ;
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 {
2020-12-06 17:27:11 +00:00
scrollAllGames_ = nullptr ;
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 ) ;
2021-01-08 19:29:09 +00:00
AnchorLayout * logos = new AnchorLayout ( new AnchorLayoutParams ( FILL_PARENT , 60.0f , false ) ) ;
2017-04-30 00:35:12 +00:00
if ( System_GetPropertyBool ( SYSPROP_APP_GOLD ) ) {
2021-02-22 00:38:02 +00:00
logos - > Add ( new ImageView ( ImageID ( " I_ICONGOLD " ) , " " , IS_DEFAULT , new AnchorLayoutParams ( 64 , 64 , 0 , 0 , NONE , NONE , false ) ) ) ;
2017-04-05 14:21:08 +00:00
} else {
2021-02-22 00:38:02 +00:00
logos - > Add ( new ImageView ( ImageID ( " I_ICON " ) , " " , IS_DEFAULT , new AnchorLayoutParams ( 64 , 64 , 0 , 0 , NONE , NONE , false ) ) ) ;
2017-04-05 14:21:08 +00:00
}
2021-02-22 00:38:02 +00:00
logos - > Add ( new ImageView ( ImageID ( " I_LOGO " ) , " PPSSPP " , IS_DEFAULT , new AnchorLayoutParams ( 180 , 64 , 64 , - 5.0f , NONE , NONE , false ) ) ) ;
2020-03-30 20:45:29 +00:00
2021-01-08 21:25:33 +00:00
# if !defined(MOBILE_DEVICE)
2020-03-30 20:45:29 +00:00
if ( ! g_Config . bFullScreen ) {
2021-02-22 02:48:01 +00:00
auto gr = GetI18NCategory ( " Graphics " ) ;
fullscreenButton_ = logos - > Add ( new Button ( gr - > T ( " FullScreen " , " Full Screen " ) , ImageID ( g_Config . bFullScreen ? " I_RESTORE " : " I_FULLSCREEN " ) , new AnchorLayoutParams ( 48 , 48 , NONE , 0 , 0 , NONE , false ) ) ) ;
fullscreenButton_ - > SetIgnoreText ( true ) ;
2021-01-08 19:05:43 +00:00
fullscreenButton_ - > OnClick . Handle ( this , & MainScreen : : OnFullScreenToggle ) ;
2020-03-30 20:45:29 +00:00
}
# endif
2013-08-19 22:49:25 +00:00
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 ) ;
2020-07-16 13:49:18 +00:00
if ( System_GetPropertyBool ( SYSPROP_HAS_FILE_BROWSER ) ) {
rightColumnItems - > Add ( new Choice ( mm - > T ( " Load " , " Load... " ) ) ) - > OnClick . Handle ( this , & MainScreen : : OnLoadFile ) ;
}
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 ) ;
2020-02-29 20:51:14 +00:00
gold - > SetIcon ( ImageID ( " I_ICONGOLD " ) ) ;
2017-04-05 14:21:08 +00:00
}
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
2020-01-26 18:43:18 +00:00
auto u = GetI18NCategory ( " Upgrade " ) ;
2013-11-26 13:04:29 +00:00
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 ) ) ) ;
2021-01-03 19:07:59 +00:00
# if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(WINDOWS)
2013-11-26 13:04:29 +00:00
upgradeBar_ - > Add ( new Button ( u - > T ( " Download " ) , new LinearLayoutParams ( buttonMargins ) ) ) - > OnClick . Handle ( this , & MainScreen : : OnDownloadUpgrade ) ;
2021-01-03 19:07:59 +00:00
# else
upgradeBar_ - > Add ( new Button ( u - > T ( " Details " ) , new LinearLayoutParams ( buttonMargins ) ) ) - > OnClick . Handle ( this , & MainScreen : : OnDownloadUpgrade ) ;
# endif
2013-11-26 13:04:29 +00:00
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 " ) ;
}
2021-01-03 19:07:59 +00:00
# elif PPSSPP_PLATFORM(WINDOWS)
LaunchBrowser ( " https://www.ppsspp.org/downloads.html " ) ;
2013-11-26 13:04:29 +00:00
# else
// Go directly to ppsspp.org and let the user sort it out
2021-01-03 19:07:59 +00:00
// (for details and in case downloads doesn't have their platform.)
LaunchBrowser ( " https://www.ppsspp.org/ " ) ;
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 " ) ) {
2020-07-27 14:53:02 +00:00
LaunchFile ( screenManager ( ) , std : : string ( value ) ) ;
2019-02-17 15:48:32 +00:00
}
2021-02-27 12:48:07 +00:00
if ( ! strcmp ( message , " browse_fileSelect " ) ) {
INFO_LOG ( SYSTEM , " Attempting to launch: '%s' " , value ) ;
LaunchFile ( screenManager ( ) , std : : string ( value ) ) ;
}
2019-02-17 15:48:32 +00:00
if ( ! strcmp ( message , " browse_folderSelect " ) ) {
2021-01-08 19:05:43 +00:00
std : : string filename ;
# if PPSSPP_PLATFORM(ANDROID)
2021-01-09 00:26:53 +00:00
// Hacky way to get a normal path from a Android Storage Framework path.
// Is not gonna work forever, but ship-hack for 1.11.
2021-01-08 19:05:43 +00:00
std : : string url = value ;
const char * prefix = " content://com.android.externalstorage.documents/tree/ " ;
2021-01-09 00:26:53 +00:00
const char * primaryPrefix = " /storage/primary/ " ;
2021-01-08 19:05:43 +00:00
if ( startsWith ( url , prefix ) ) {
2021-01-09 00:26:53 +00:00
url = UriDecode ( url . substr ( strlen ( prefix ) ) ) ;
size_t colonPos = url . find ( " : " ) ;
if ( colonPos ! = std : : string : : npos ) {
url [ colonPos ] = ' / ' ;
}
url = " /storage/ " + url ;
if ( startsWith ( url , primaryPrefix ) ) {
url = g_Config . memStickDirectory + url . substr ( strlen ( primaryPrefix ) ) ;
}
INFO_LOG ( SYSTEM , " Translated '%s' into '%s' " , value , url . c_str ( ) ) ;
2021-01-08 19:05:43 +00:00
} else {
// It's not gonna work.
// TODO: Show an error message?
2021-01-09 00:26:53 +00:00
INFO_LOG ( SYSTEM , " Failed to parse content string: '%s' " , value ) ;
2021-01-08 19:05:43 +00:00
return ;
}
filename = url ;
# else
filename = value ;
# endif
2021-01-09 00:26:53 +00:00
INFO_LOG ( SYSTEM , " Got folder: '%s' " , filename . c_str ( ) ) ;
2019-02-17 15:48:32 +00:00
int tab = tabHolder_ - > GetCurrentTab ( ) ;
if ( tab > = 0 & & tab < ( int ) gameBrowsers_ . size ( ) ) {
2021-01-08 19:05:43 +00:00
gameBrowsers_ [ tab ] - > SetPath ( filename ) ;
2019-02-17 15:48:32 +00:00
}
}
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 ;
}
2020-12-06 17:27:11 +00:00
if ( scrollAllGames_ ) {
g_Config . fGameListScrollPosition = scrollAllGames_ - > GetScrollPosition ( ) ;
}
2014-06-29 19:02:32 +00:00
}
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 ;
}
2021-01-08 19:05:43 +00:00
UI : : EventReturn MainScreen : : OnFullScreenToggle ( UI : : EventParams & e ) {
if ( fullscreenButton_ ) {
fullscreenButton_ - > SetImageID ( ImageID ( ! g_Config . bFullScreen ? " I_RESTORE " : " I_FULLSCREEN " ) ) ;
}
2021-01-08 21:25:33 +00:00
# if !defined(MOBILE_DEVICE)
g_Config . bFullScreen = ! g_Config . bFullScreen ;
System_SendMessage ( " toggle_fullscreen " , " " ) ;
2021-01-08 19:05:43 +00:00
# endif
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 ;
}
2021-04-04 17:57:40 +00:00
auto pic = ginfo - > GetBGPic ( ) ;
Draw : : Texture * texture = pic ? pic - > texture - > GetTexture ( ) : nullptr ;
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 ) {
2021-01-05 16:01:05 +00:00
g_Config . Save ( " MainScreen::OnGameSelected " ) ;
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_ ;
2020-08-02 17:44:48 +00:00
g_BackgroundAudio . SetGame ( 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_ ) {
2020-08-02 17:44:48 +00:00
g_BackgroundAudio . SetGame ( 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 ) {
2021-01-05 16:01:05 +00:00
g_Config . Save ( " MainScreen::OnGameSelectedInstant " ) ;
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
2020-07-28 08:03:55 +00:00
ScreenManager * screen = screenManager ( ) ;
LaunchFile ( screen , 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 ) {
2020-03-02 07:34:26 +00:00
screenManager ( ) - > push ( new GameSettingsScreen ( " " , " " ) ) ;
2020-03-01 14:34:35 +00:00
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 ;
}
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 ) {
2020-12-13 09:29:12 +00:00
// Let's make sure the config was saved, since it may not have been.
g_Config . Save ( " MainScreen::OnExit " ) ;
2014-02-11 10:32:54 +00:00
// Request the framework to exit cleanly.
System_SendMessage ( " finish " , " " ) ;
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.
2020-08-02 17:44:48 +00:00
g_BackgroundAudio . SetGame ( " " ) ;
2016-02-08 01:15:19 +00:00
}
}
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 ) ;
2020-01-26 18:43:18 +00:00
auto mm = GetI18NCategory ( " MainMenu " ) ;
auto 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 (
2020-03-01 14:34:35 +00:00
" !RECENT " , BrowseFlags : : NONE , & g_Config . bGridView1 , screenManager ( ) , " " , " " ,
2014-06-29 03:44:24 +00:00
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
2020-03-01 14:34:35 +00:00
GameBrowser * tabAllGames = new GameBrowser ( g_Config . currentDirectory , BrowseFlags : : STANDARD , & g_Config . bGridView2 , screenManager ( ) ,
2019-10-06 19:40:00 +00:00
mm - > T ( " How to get games " ) , " https://www.ppsspp.org/getgames.html " ,
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 ;
}
2020-03-01 14:34:35 +00:00
void GridSettingsScreen : : CreatePopupContents ( UI : : ViewGroup * parent ) {
using namespace UI ;
auto di = GetI18NCategory ( " Dialog " ) ;
auto sy = GetI18NCategory ( " System " ) ;
2020-03-03 07:47:14 +00:00
ScrollView * scroll = new ScrollView ( ORIENT_VERTICAL , new LinearLayoutParams ( FILL_PARENT , 50 , 1.0f ) ) ;
2021-02-22 02:41:08 +00:00
LinearLayout * items = new LinearLayoutList ( ORIENT_VERTICAL ) ;
2020-03-01 14:34:35 +00:00
items - > Add ( new CheckBox ( & g_Config . bGridView1 , sy - > T ( " Display Recent on a grid " ) ) ) ;
items - > Add ( new CheckBox ( & g_Config . bGridView2 , sy - > T ( " Display Games on a grid " ) ) ) ;
items - > Add ( new CheckBox ( & g_Config . bGridView3 , sy - > T ( " Display Homebrew on a grid " ) ) ) ;
items - > Add ( new ItemHeader ( sy - > T ( " Grid icon size " ) ) ) ;
items - > Add ( new Choice ( sy - > T ( " Increase size " ) ) ) - > OnClick . Handle ( this , & GridSettingsScreen : : GridPlusClick ) ;
items - > Add ( new Choice ( sy - > T ( " Decrease size " ) ) ) - > OnClick . Handle ( this , & GridSettingsScreen : : GridMinusClick ) ;
2020-03-02 07:34:26 +00:00
items - > Add ( new ItemHeader ( sy - > T ( " Display Extra Info " ) ) ) ;
items - > Add ( new CheckBox ( & g_Config . bShowIDOnGameIcon , sy - > T ( " Show ID " ) ) ) ;
items - > Add ( new CheckBox ( & g_Config . bShowRegionOnGameIcon , sy - > T ( " Show region flag " ) ) ) ;
if ( g_Config . iMaxRecent > 0 ) {
items - > Add ( new ItemHeader ( sy - > T ( " Clear Recent " ) ) ) ;
items - > Add ( new Choice ( sy - > T ( " Clear Recent Games List " ) ) ) - > OnClick . Handle ( this , & GridSettingsScreen : : OnRecentClearClick ) ;
}
2020-03-01 14:34:35 +00:00
scroll - > Add ( items ) ;
parent - > Add ( scroll ) ;
}
UI : : EventReturn GridSettingsScreen : : GridPlusClick ( UI : : EventParams & e ) {
g_Config . fGameGridScale = std : : min ( g_Config . fGameGridScale * 1.25f , MAX_GAME_GRID_SCALE ) ;
return UI : : EVENT_DONE ;
}
UI : : EventReturn GridSettingsScreen : : GridMinusClick ( UI : : EventParams & e ) {
g_Config . fGameGridScale = std : : max ( g_Config . fGameGridScale / 1.25f , MIN_GAME_GRID_SCALE ) ;
return UI : : EVENT_DONE ;
}
2020-03-02 07:34:26 +00:00
UI : : EventReturn GridSettingsScreen : : OnRecentClearClick ( UI : : EventParams & e ) {
g_Config . recentIsos . clear ( ) ;
OnRecentChanged . Trigger ( e ) ;
return UI : : EVENT_DONE ;
}