mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
More layout work. Use GameDB titles on the top of the game screen.
This commit is contained in:
@@ -226,15 +226,19 @@ float ScrollView::ChildSize() const {
|
||||
return std::max(0.01f, views_[0]->GetBounds().GetSize(orientation_) + extraSpace);
|
||||
}
|
||||
|
||||
float ScrollView::ScrollMax() const {
|
||||
const float childHeight = ChildSize();
|
||||
return std::max(0.0f, childHeight - bounds_.GetSize(orientation_));
|
||||
}
|
||||
|
||||
ScrollView::Bob ScrollView::ComputeBob() const {
|
||||
Bob bob{};
|
||||
if (views_.empty()) {
|
||||
return bob;
|
||||
}
|
||||
const float childHeight = ChildSize();
|
||||
float scrollMax = std::max(0.0f, childHeight - bounds_.h);
|
||||
float ratio = bounds_.h / childHeight;
|
||||
|
||||
const float ratio = bounds_.h / childHeight;
|
||||
const float scrollMax = ScrollMax();
|
||||
if (ratio < 1.0f && scrollMax > 0.0f) {
|
||||
bob.show = true;
|
||||
bob.thickness = draggingBob_ ? 15.0f : 6.0f;
|
||||
@@ -260,6 +264,8 @@ void ScrollView::Draw(UIContext &dc) {
|
||||
|
||||
// If not anchored at the top of the screen exactly, and not scrolled to the top,
|
||||
// draw a subtle drop shadow to indicate scrollability.
|
||||
|
||||
const float darkness = 0.4f;
|
||||
if (bounds_.y > 0.0f && orientation_ == ORIENT_VERTICAL) {
|
||||
float radius = 20.0f;
|
||||
|
||||
@@ -269,11 +275,33 @@ void ScrollView::Draw(UIContext &dc) {
|
||||
shadowBounds.y -= radius * 2;
|
||||
shadowBounds.h = radius * 2;
|
||||
|
||||
float fade = std::clamp(scrollPos_ * 0.1f, 0.0f, 0.6f);
|
||||
float fade = std::clamp(scrollPos_ * 0.05f, 0.0f, 1.0f) * darkness;
|
||||
|
||||
dc.DrawRectDropShadow(shadowBounds, radius, fade);
|
||||
}
|
||||
|
||||
// Same at the bottom.
|
||||
float y2 = dc.GetLayoutBounds().y2();
|
||||
if (bounds_.y2() < y2 && orientation_ == ORIENT_VERTICAL) {
|
||||
float radius = 20.0f;
|
||||
|
||||
Bounds shadowBounds = bounds_;
|
||||
shadowBounds.x -= radius;
|
||||
shadowBounds.w += radius * 2;
|
||||
shadowBounds.y = bounds_.y2() - radius * 2;
|
||||
shadowBounds.h = radius * 2;
|
||||
|
||||
float fade = std::clamp((ScrollMax() - scrollPos_) * 0.05f, 0.0f, 1.0f) * darkness;
|
||||
|
||||
dc.DrawRectDropShadow(shadowBounds, radius, fade);
|
||||
}
|
||||
|
||||
// If there are any additional views, we treat them as overlays attached at the top - they don't scroll, and they're
|
||||
// drawn on top of the shadow. TODO: Give them an idea about the scroll position so they can fade in?
|
||||
for (size_t i = 1; i < views_.size(); ++i) {
|
||||
views_[i]->Draw(dc);
|
||||
}
|
||||
|
||||
dc.PopScissor();
|
||||
|
||||
// Vertical scroll bob. We don't support a horizontal yet.
|
||||
|
||||
@@ -48,6 +48,7 @@ public:
|
||||
|
||||
private:
|
||||
float ChildSize() const; // in the scrolled direction
|
||||
float ScrollMax() const;
|
||||
float HardClampedScrollPos(float pos) const;
|
||||
|
||||
// TODO: Don't adjust pull_ within this!
|
||||
|
||||
@@ -532,7 +532,7 @@ void AnalogCalibrationScreen::axis(const AxisInput &axis) {
|
||||
|
||||
std::string_view AnalogCalibrationScreen::GetTitle() const {
|
||||
auto co = GetI18NCategory(I18NCat::CONTROLS);
|
||||
return co->T("Analog Settings");
|
||||
return co->T("Calibrate analog stick");
|
||||
}
|
||||
|
||||
void AnalogCalibrationScreen::CreateSettingsViews(UI::LinearLayout *scrollContents) {
|
||||
|
||||
+42
-22
@@ -158,21 +158,28 @@ void GameScreen::CreateContentViews(UI::LinearLayout *parent) {
|
||||
}
|
||||
mainGameInfo->SetSpacing(3.0f);
|
||||
|
||||
GameDBInfo dbInfo;
|
||||
std::vector<GameDBInfo> dbInfos;
|
||||
const bool inGameDB = g_gameDB.GetGameInfos(info_->id_version, &dbInfos);
|
||||
|
||||
if (knownFlags_ & GameInfoFlags::PARAM_SFO) {
|
||||
// TODO: Add non-translated title here if available in gameDB.
|
||||
TextView *tvTitle = mainGameInfo->Add(new TextView(info_->GetTitle(), ALIGN_LEFT | FLAG_WRAP_TEXT, false, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
|
||||
// Show the game ID title below the icon. The top title will be from the DB.
|
||||
std::string title = info_->GetTitle();
|
||||
|
||||
TextView *tvTitle = mainGameInfo->Add(new TextView(title, ALIGN_LEFT | FLAG_WRAP_TEXT, false, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
|
||||
tvTitle->SetShadow(true);
|
||||
|
||||
TextView *tvID = mainGameInfo->Add(new TextView(ReplaceAll(info_->id_version, "_", " v"), ALIGN_LEFT | FLAG_WRAP_TEXT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
|
||||
tvID->SetShadow(true);
|
||||
std::string regionID = ReplaceAll(info_->id_version, "_", " v");
|
||||
regionID += ": ";
|
||||
|
||||
if (info_->region != GameRegion::UNKNOWN) {
|
||||
TextView *tvRegion = mainGameInfo->Add(new TextView(ga->T(GameRegionToString(info_->region)), ALIGN_LEFT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
|
||||
tvRegion->SetShadow(true);
|
||||
regionID += GameRegionToString(info_->region);
|
||||
} else {
|
||||
TextView *tvFileType = mainGameInfo->Add(new TextView(ga->T(IdentifiedFileTypeToString(info_->fileType)), ALIGN_LEFT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
|
||||
tvFileType->SetShadow(true);
|
||||
regionID += IdentifiedFileTypeToString(info_->fileType);
|
||||
}
|
||||
|
||||
TextView *tvID = mainGameInfo->Add(new TextView(regionID, ALIGN_LEFT | FLAG_WRAP_TEXT, true, new LinearLayoutParams(FILL_PARENT, WRAP_CONTENT)));
|
||||
tvID->SetShadow(true);
|
||||
}
|
||||
|
||||
LinearLayout *infoLayout = new LinearLayout(ORIENT_VERTICAL, new AnchorLayoutParams(10, 200, NONE, NONE));
|
||||
@@ -237,7 +244,7 @@ void GameScreen::CreateContentViews(UI::LinearLayout *parent) {
|
||||
std::vector<GameDBInfo> dbInfos;
|
||||
if ((knownFlags_ & GameInfoFlags::PARAM_SFO) && g_gameDB.GetGameInfos(info_->id_version, &dbInfos)) {
|
||||
bool found = false;
|
||||
for (auto &dbInfo : dbInfos) {
|
||||
for (const auto &dbInfo : dbInfos) {
|
||||
if (dbInfo.crc == crcVal) {
|
||||
found = true;
|
||||
}
|
||||
@@ -248,9 +255,7 @@ void GameScreen::CreateContentViews(UI::LinearLayout *parent) {
|
||||
}
|
||||
}
|
||||
} else if (!isHomebrew_) {
|
||||
GameDBInfo dbInfo;
|
||||
std::vector<GameDBInfo> dbInfos;
|
||||
if ((knownFlags_ & GameInfoFlags::PARAM_SFO) && !g_gameDB.GetGameInfos(info_->id_version, &dbInfos)) {
|
||||
if ((knownFlags_ & GameInfoFlags::PARAM_SFO) && !inGameDB) {
|
||||
// tvVerified_->SetText(ga->T("Game ID unknown - not in the ReDump database"));
|
||||
// tvVerified_->SetVisibility(UI::V_VISIBLE);
|
||||
// tvVerified_->SetLevel(NoticeLevel::WARN);
|
||||
@@ -309,12 +314,14 @@ void GameScreen::CreateSettingsViews(UI::LinearLayout *rightColumn) {
|
||||
}
|
||||
|
||||
if (!info_->id.empty()) {
|
||||
Choice *btnGameSettings = rightColumnItems->Add(new Choice(ga->T("Game Settings")));
|
||||
btnGameSettings->OnClick.Handle(this, &GameScreen::OnGameSettings);
|
||||
if (inGame_)
|
||||
btnGameSettings->SetEnabled(false);
|
||||
|
||||
if (info_->hasConfig) {
|
||||
// Only show the Game Settings button here if the game has a config. Always showing it
|
||||
// is confusing since it'll just control the global settings.
|
||||
Choice *btnGameSettings = rightColumnItems->Add(new Choice(ga->T("Game Settings")));
|
||||
btnGameSettings->OnClick.Handle(this, &GameScreen::OnGameSettings);
|
||||
if (inGame_)
|
||||
btnGameSettings->SetEnabled(false);
|
||||
|
||||
Choice *btnDeleteGameConfig = rightColumnItems->Add(new Choice(ga->T("Delete Game Config")));
|
||||
btnDeleteGameConfig->OnClick.Handle(this, &GameScreen::OnDeleteConfig);
|
||||
if (inGame_)
|
||||
@@ -386,17 +393,30 @@ void GameScreen::CreateSettingsViews(UI::LinearLayout *rightColumn) {
|
||||
}
|
||||
|
||||
void GameScreen::OnCreateConfig(UI::EventParams &e) {
|
||||
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath_, GameInfoFlags::PARAM_SFO);
|
||||
if (!info->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||
if (!info_->Ready(GameInfoFlags::PARAM_SFO)) {
|
||||
return;
|
||||
}
|
||||
g_Config.CreateGameConfig(info->id);
|
||||
g_Config.SaveGameConfig(info->id, info->GetTitle());
|
||||
info->hasConfig = true;
|
||||
g_Config.CreateGameConfig(info_->id);
|
||||
g_Config.SaveGameConfig(info_->id, info_->GetTitle());
|
||||
info_->hasConfig = true;
|
||||
|
||||
screenManager()->topScreen()->RecreateViews();
|
||||
}
|
||||
|
||||
std::string_view GameScreen::GetTitle() const {
|
||||
if (knownFlags_ & GameInfoFlags::PARAM_SFO) {
|
||||
std::vector<GameDBInfo> dbInfos;
|
||||
const bool inGameDB = g_gameDB.GetGameInfos(info_->id_version, &dbInfos);
|
||||
if (inGameDB) {
|
||||
titleCache_ = dbInfos[0].title;
|
||||
} else {
|
||||
titleCache_ = std::string(info_->GetTitle());
|
||||
}
|
||||
}
|
||||
|
||||
return titleCache_;
|
||||
}
|
||||
|
||||
void GameScreen::OnDeleteConfig(UI::EventParams &e) {
|
||||
auto di = GetI18NCategory(I18NCat::DIALOG);
|
||||
const bool trashAvailable = System_GetPropertyBool(SYSPROP_HAS_TRASH_BIN);
|
||||
|
||||
@@ -50,6 +50,7 @@ protected:
|
||||
void CreateSettingsViews(UI::LinearLayout *parent) override;
|
||||
|
||||
bool SettingsToTheRight() const override { return true; }
|
||||
std::string_view GetTitle() const override;
|
||||
|
||||
private:
|
||||
// Event handlers
|
||||
@@ -75,4 +76,5 @@ private:
|
||||
bool knownHasCRC_ = false;
|
||||
|
||||
std::shared_ptr<GameInfo> info_;
|
||||
mutable std::string titleCache_;
|
||||
};
|
||||
|
||||
+2
-1
@@ -56,7 +56,8 @@ TopBar::TopBar(const UIContext &ctx, bool usePortraitLayout, std::string_view ti
|
||||
e.bubbleResult = DR_BACK;
|
||||
});
|
||||
if (!usePortraitLayout) {
|
||||
backButton_->SetText(dlg->T("Back"));
|
||||
// Not really liking this..
|
||||
// backButton_->SetText(dlg->T("Back"));
|
||||
}
|
||||
|
||||
if (!title.empty()) {
|
||||
|
||||
@@ -50,7 +50,14 @@ void UITwoPaneBaseDialogScreen::CreateViews() {
|
||||
root_ = root;
|
||||
} else {
|
||||
ignoreBottomInset_ = false;
|
||||
LinearLayout *root = new LinearLayout(ORIENT_HORIZONTAL, new LayoutParams(FILL_PARENT, FILL_PARENT));
|
||||
LinearLayout *root = new LinearLayout(ORIENT_VERTICAL, new LayoutParams(FILL_PARENT, FILL_PARENT));
|
||||
std::string title(GetTitle());
|
||||
root->Add(new TopBar(*screenManager()->getUIContext(), portrait, title));
|
||||
root->SetSpacing(0);
|
||||
|
||||
LinearLayout *columns = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 1.0f));
|
||||
root->Add(columns);
|
||||
|
||||
// root_->Add(new TopBar(*screenManager()->getUIContext(), portrait, GetTitle(), new LayoutParams(FILL_PARENT, FILL_PARENT)));
|
||||
ScrollView *settingsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(SettingsWidth(), FILL_PARENT, 0.0f, Margins(8)));
|
||||
LinearLayout *settingsPane = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT));
|
||||
@@ -61,11 +68,11 @@ void UITwoPaneBaseDialogScreen::CreateViews() {
|
||||
settingsScroll->Add(settingsPane);
|
||||
|
||||
if (SettingsToTheRight()) {
|
||||
CreateContentViews(root);
|
||||
root->Add(settingsScroll);
|
||||
CreateContentViews(columns);
|
||||
columns->Add(settingsScroll);
|
||||
} else {
|
||||
root->Add(settingsScroll);
|
||||
CreateContentViews(root);
|
||||
columns->Add(settingsScroll);
|
||||
CreateContentViews(columns);
|
||||
}
|
||||
|
||||
root_ = root;
|
||||
|
||||
Reference in New Issue
Block a user