Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/UI/DisplayLayoutScreen.cpp
3185 views
1
// Copyright (c) 2013- PPSSPP Project.
2
3
// This program is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, version 2.0 or later versions.
6
7
// This program is distributed in the hope that it will be useful,
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
// GNU General Public License 2.0 for more details.
11
12
// A copy of the GPL 2.0 should have been included with the program.
13
// If not, see http://www.gnu.org/licenses/
14
15
// Official git repository and contact information can be found at
16
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17
18
#include <algorithm>
19
20
#include "Common/System/Display.h"
21
#include "Common/System/System.h"
22
#include "Common/Render/TextureAtlas.h"
23
#include "Common/Render/DrawBuffer.h"
24
#include "Common/UI/Context.h"
25
#include "Common/UI/View.h"
26
#include "Common/UI/UIScreen.h"
27
#include "Common/Math/math_util.h"
28
#include "Common/System/Display.h"
29
#include "Common/System/NativeApp.h"
30
#include "Common/VR/PPSSPPVR.h"
31
#include "Common/StringUtils.h"
32
33
#include "Common/Data/Color/RGBAUtil.h"
34
#include "Common/Data/Text/I18n.h"
35
#include "UI/DisplayLayoutScreen.h"
36
#include "Core/Config.h"
37
#include "Core/ConfigValues.h"
38
#include "Core/System.h"
39
#include "GPU/Common/FramebufferManagerCommon.h"
40
#include "GPU/Common/PresentationCommon.h"
41
42
static const int leftColumnWidth = 200;
43
static const float orgRatio = 1.764706f; // 480.0 / 272.0
44
45
enum Mode {
46
MODE_INACTIVE = 0,
47
MODE_MOVE = 1,
48
MODE_RESIZE = 2,
49
};
50
51
static Bounds FRectToBounds(FRect rc) {
52
Bounds b;
53
b.x = rc.x * g_display.dpi_scale_x;
54
b.y = rc.y * g_display.dpi_scale_y;
55
b.w = rc.w * g_display.dpi_scale_x;
56
b.h = rc.h * g_display.dpi_scale_y;
57
return b;
58
}
59
60
class DisplayLayoutBackground : public UI::View {
61
public:
62
DisplayLayoutBackground(UI::ChoiceStrip *mode, UI::LayoutParams *layoutParams) : UI::View(layoutParams), mode_(mode) {}
63
64
bool Touch(const TouchInput &touch) override {
65
int mode = mode_ ? mode_->GetSelection() : 0;
66
67
if ((touch.flags & TOUCH_MOVE) != 0 && dragging_) {
68
float relativeTouchX = touch.x - startX_;
69
float relativeTouchY = touch.y - startY_;
70
71
switch (mode) {
72
case MODE_MOVE:
73
g_Config.fDisplayOffsetX = clamp_value(startDisplayOffsetX_ + relativeTouchX / bounds_.w, 0.0f, 1.0f);
74
g_Config.fDisplayOffsetY = clamp_value(startDisplayOffsetY_ + relativeTouchY / bounds_.h, 0.0f, 1.0f);
75
break;
76
case MODE_RESIZE:
77
{
78
// Resize. Vertical = scaling; Up should be bigger so let's negate in that direction
79
float diffYProp = -relativeTouchY * 0.007f;
80
g_Config.fDisplayScale = clamp_value(startScale_ * powf(2.0f, diffYProp), 0.2f, 2.0f);
81
break;
82
}
83
}
84
}
85
86
if ((touch.flags & TOUCH_DOWN) != 0 && !dragging_) {
87
// Check that we're in the central 80% of the screen.
88
// If outside, it may be a drag from displaying the back button on phones
89
// where you have to drag from the side, etc.
90
if (touch.x >= bounds_.w * 0.1f && touch.x <= bounds_.w * 0.9f &&
91
touch.y >= bounds_.h * 0.1f && touch.y <= bounds_.h * 0.9f) {
92
dragging_ = true;
93
startX_ = touch.x;
94
startY_ = touch.y;
95
startDisplayOffsetX_ = g_Config.fDisplayOffsetX;
96
startDisplayOffsetY_ = g_Config.fDisplayOffsetY;
97
startScale_ = g_Config.fDisplayScale;
98
}
99
}
100
101
if ((touch.flags & TOUCH_UP) != 0 && dragging_) {
102
dragging_ = false;
103
}
104
105
return true;
106
}
107
108
private:
109
UI::ChoiceStrip *mode_;
110
bool dragging_ = false;
111
112
// Touch down state for drag to resize etc
113
float startX_ = 0.0f;
114
float startY_ = 0.0f;
115
float startScale_ = -1.0f;
116
float startDisplayOffsetX_ = -1.0f;
117
float startDisplayOffsetY_ = -1.0f;
118
};
119
120
DisplayLayoutScreen::DisplayLayoutScreen(const Path &filename) : UIDialogScreenWithGameBackground(filename) {}
121
122
void DisplayLayoutScreen::DrawBackground(UIContext &dc) {
123
if (PSP_GetBootState() == BootState::Complete && !g_Config.bSkipBufferEffects) {
124
// We normally rely on the PSP screen showing through.
125
} else {
126
// But if it's not present (we're not in game, or skip buffer effects is used),
127
// we have to draw a substitute ourselves.
128
UIContext &dc = *screenManager()->getUIContext();
129
130
// TODO: Clean this up a bit, this GetScreenFrame/CenterDisplay combo is too common.
131
FRect screenFrame = GetScreenFrame(g_display.pixel_xres, g_display.pixel_yres);
132
FRect rc;
133
CalculateDisplayOutputRect(&rc, 480.0f, 272.0f, screenFrame, g_Config.iInternalScreenRotation);
134
135
dc.Flush();
136
ImageID bg = ImageID("I_PSP_DISPLAY");
137
dc.Draw()->DrawImageStretch(bg, dc.GetBounds(), 0x7F000000);
138
dc.Draw()->DrawImageStretch(bg, FRectToBounds(rc), 0x7FFFFFFF);
139
}
140
}
141
142
void DisplayLayoutScreen::onFinish(DialogResult reason) {
143
g_Config.Save("DisplayLayoutScreen::onFinish");
144
}
145
146
void DisplayLayoutScreen::dialogFinished(const Screen *dialog, DialogResult result) {
147
RecreateViews();
148
}
149
150
static void NotifyPostChanges() {
151
System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED);
152
System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED); // To deal with shaders that can change render resolution like upscaling.
153
System_PostUIMessage(UIMessage::POSTSHADER_UPDATED);
154
155
if (gpu) {
156
gpu->NotifyConfigChanged();
157
}
158
}
159
160
UI::EventReturn DisplayLayoutScreen::OnPostProcShaderChange(UI::EventParams &e) {
161
// Remove the virtual "Off" entry. TODO: Get rid of it generally.
162
g_Config.vPostShaderNames.erase(std::remove(g_Config.vPostShaderNames.begin(), g_Config.vPostShaderNames.end(), "Off"), g_Config.vPostShaderNames.end());
163
FixPostShaderOrder(&g_Config.vPostShaderNames);
164
NotifyPostChanges();
165
return UI::EVENT_DONE;
166
}
167
168
static std::string PostShaderTranslateName(std::string_view value) {
169
if (value == "Off") {
170
auto gr = GetI18NCategory(I18NCat::GRAPHICS);
171
// Off is a legacy fake item (gonna migrate off it later).
172
return std::string(gr->T("Add postprocessing shader"));
173
}
174
175
const ShaderInfo *info = GetPostShaderInfo(value);
176
if (info) {
177
auto ps = GetI18NCategory(I18NCat::POSTSHADERS);
178
return std::string(ps->T(value, info->name));
179
} else {
180
return std::string(value);
181
}
182
}
183
184
void DisplayLayoutScreen::sendMessage(UIMessage message, const char *value) {
185
UIDialogScreenWithGameBackground::sendMessage(message, value);
186
if (message == UIMessage::POSTSHADER_UPDATED) {
187
g_Config.bShaderChainRequires60FPS = PostShaderChainRequires60FPS(GetFullPostShadersChain(g_Config.vPostShaderNames));
188
RecreateViews();
189
}
190
}
191
192
void DisplayLayoutScreen::CreateViews() {
193
const Bounds &bounds = screenManager()->getUIContext()->GetBounds();
194
195
using namespace UI;
196
197
auto di = GetI18NCategory(I18NCat::DIALOG);
198
auto gr = GetI18NCategory(I18NCat::GRAPHICS);
199
auto co = GetI18NCategory(I18NCat::CONTROLS);
200
auto ps = GetI18NCategory(I18NCat::POSTSHADERS);
201
202
root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
203
204
bool vertical = bounds.h > bounds.w;
205
206
// Make it so that a touch can only affect one view. Makes manipulating the background through the buttons
207
// impossible.
208
root_->SetExclusiveTouch(true);
209
210
LinearLayout *leftColumn;
211
if (!vertical) {
212
ScrollView *leftScrollView = new ScrollView(ORIENT_VERTICAL, new AnchorLayoutParams(420.0f, FILL_PARENT, 0.f, 0.f, NONE, 0.f, false));
213
leftColumn = new LinearLayout(ORIENT_VERTICAL);
214
leftColumn->padding.SetAll(8.0f);
215
leftScrollView->Add(leftColumn);
216
leftScrollView->SetClickableBackground(true);
217
root_->Add(leftScrollView);
218
}
219
220
ScrollView *rightScrollView = new ScrollView(ORIENT_VERTICAL, new AnchorLayoutParams(300.0f, FILL_PARENT, NONE, 0.f, 0.f, 0.f, false));
221
LinearLayout *rightColumn = new LinearLayout(ORIENT_VERTICAL);
222
rightColumn->padding.SetAll(8.0f);
223
rightScrollView->Add(rightColumn);
224
rightScrollView->SetClickableBackground(true);
225
root_->Add(rightScrollView);
226
227
LinearLayout *bottomControls;
228
if (vertical) {
229
bottomControls = new LinearLayout(ORIENT_HORIZONTAL);
230
rightColumn->Add(bottomControls);
231
leftColumn = rightColumn;
232
} else {
233
bottomControls = new LinearLayout(ORIENT_HORIZONTAL, new AnchorLayoutParams(NONE, NONE, NONE, 10.0f, false));
234
root_->Add(bottomControls);
235
}
236
237
// Set backgrounds for readability
238
Drawable backgroundWithAlpha(GetBackgroundColorWithAlpha(*screenManager()->getUIContext()));
239
leftColumn->SetBG(backgroundWithAlpha);
240
rightColumn->SetBG(backgroundWithAlpha);
241
242
if (!IsVREnabled()) {
243
auto stretch = new CheckBox(&g_Config.bDisplayStretch, gr->T("Stretch"));
244
stretch->SetDisabledPtr(&g_Config.bDisplayIntegerScale);
245
rightColumn->Add(stretch);
246
247
PopupSliderChoiceFloat *aspectRatio = new PopupSliderChoiceFloat(&g_Config.fDisplayAspectRatio, 0.1f, 2.0f, 1.0f, gr->T("Aspect Ratio"), screenManager());
248
rightColumn->Add(aspectRatio);
249
aspectRatio->SetEnabledFunc([]() {
250
return !g_Config.bDisplayStretch && !g_Config.bDisplayIntegerScale;
251
});
252
aspectRatio->SetHasDropShadow(false);
253
aspectRatio->SetLiveUpdate(true);
254
255
rightColumn->Add(new CheckBox(&g_Config.bDisplayIntegerScale, gr->T("Integer scale factor")));
256
257
#if PPSSPP_PLATFORM(ANDROID)
258
// Hide insets option if no insets, or OS too old.
259
if (System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= 28 &&
260
(System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_LEFT) != 0.0f ||
261
System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_TOP) != 0.0f ||
262
System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_RIGHT) != 0.0f ||
263
System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_BOTTOM) != 0.0f)) {
264
rightColumn->Add(new CheckBox(&g_Config.bIgnoreScreenInsets, gr->T("Ignore camera notch when centering")));
265
}
266
#endif
267
268
mode_ = new ChoiceStrip(ORIENT_HORIZONTAL, new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT));
269
mode_->AddChoice(di->T("Inactive"));
270
mode_->AddChoice(di->T("Move"));
271
mode_->AddChoice(di->T("Resize"));
272
mode_->SetSelection(0, false);
273
bottomControls->Add(mode_);
274
275
static const char *displayRotation[] = { "Landscape", "Portrait", "Landscape Reversed", "Portrait Reversed" };
276
auto rotation = new PopupMultiChoice(&g_Config.iInternalScreenRotation, gr->T("Rotation"), displayRotation, 1, ARRAY_SIZE(displayRotation), I18NCat::CONTROLS, screenManager());
277
rotation->SetEnabledFunc([] {
278
return !g_Config.bSkipBufferEffects || g_Config.bSoftwareRendering;
279
});
280
rotation->SetHideTitle(true);
281
rightColumn->Add(rotation);
282
283
Choice *center = new Choice(di->T("Reset"));
284
center->OnClick.Add([&](UI::EventParams &) {
285
g_Config.fDisplayAspectRatio = 1.0f;
286
g_Config.fDisplayScale = 1.0f;
287
g_Config.fDisplayOffsetX = 0.5f;
288
g_Config.fDisplayOffsetY = 0.5f;
289
return UI::EVENT_DONE;
290
});
291
rightColumn->Add(center);
292
293
rightColumn->Add(new Spacer(12.0f));
294
}
295
296
Choice *back = new Choice(di->T("Back"), "", false);
297
back->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
298
rightColumn->Add(back);
299
300
if (vertical) {
301
leftColumn->Add(new Spacer(24.0f));
302
}
303
304
if (!IsVREnabled()) {
305
static const char *bufFilters[] = { "Linear", "Nearest", };
306
leftColumn->Add(new PopupMultiChoice(&g_Config.iDisplayFilter, gr->T("Screen Scaling Filter"), bufFilters, 1, ARRAY_SIZE(bufFilters), I18NCat::GRAPHICS, screenManager()));
307
}
308
309
Draw::DrawContext *draw = screenManager()->getDrawContext();
310
311
bool multiViewSupported = draw->GetDeviceCaps().multiViewSupported;
312
313
auto enableStereo = [=]() -> bool {
314
return g_Config.bStereoRendering && multiViewSupported;
315
};
316
317
leftColumn->Add(new ItemHeader(gr->T("Postprocessing shaders")));
318
319
std::set<std::string> alreadyAddedShader;
320
// If there's a single post shader and we're just entering the dialog,
321
// auto-open the settings.
322
if (settingsVisible_.empty() && g_Config.vPostShaderNames.size() == 1) {
323
settingsVisible_.push_back(true);
324
} else if (settingsVisible_.size() < g_Config.vPostShaderNames.size()) {
325
settingsVisible_.resize(g_Config.vPostShaderNames.size());
326
}
327
328
static const ContextMenuItem postShaderContextMenu[] = {
329
{ "Move Up", "I_ARROW_UP" },
330
{ "Move Down", "I_ARROW_DOWN" },
331
{ "Remove", "I_TRASHCAN" },
332
};
333
334
for (int i = 0; i < (int)g_Config.vPostShaderNames.size() + 1 && i < ARRAY_SIZE(shaderNames_); ++i) {
335
// Vector element pointer get invalidated on resize, cache name to have always a valid reference in the rendering thread
336
shaderNames_[i] = i == g_Config.vPostShaderNames.size() ? "Off" : g_Config.vPostShaderNames[i];
337
338
LinearLayout *shaderRow = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(UI::FILL_PARENT, UI::WRAP_CONTENT));
339
shaderRow->SetSpacing(4.0f);
340
leftColumn->Add(shaderRow);
341
342
if (shaderNames_[i] != "Off") {
343
postProcChoice_ = shaderRow->Add(new ChoiceWithValueDisplay(&shaderNames_[i], "", &PostShaderTranslateName, new LinearLayoutParams(1.0f)));
344
} else {
345
postProcChoice_ = shaderRow->Add(new Choice(ImageID("I_PLUS")));
346
}
347
postProcChoice_->OnClick.Add([=](EventParams &e) {
348
auto gr = GetI18NCategory(I18NCat::GRAPHICS);
349
auto procScreen = new PostProcScreen(gr->T("Postprocessing shaders"), i, false);
350
procScreen->SetHasDropShadow(false);
351
procScreen->OnChoice.Handle(this, &DisplayLayoutScreen::OnPostProcShaderChange);
352
if (e.v)
353
procScreen->SetPopupOrigin(e.v);
354
screenManager()->push(procScreen);
355
return UI::EVENT_DONE;
356
});
357
postProcChoice_->SetEnabledFunc([=] {
358
return !g_Config.bSkipBufferEffects && !enableStereo();
359
});
360
361
if (i < g_Config.vPostShaderNames.size()) {
362
bool hasSettings = false;
363
std::vector<const ShaderInfo *> shaderChain = GetPostShaderChain(g_Config.vPostShaderNames[i]);
364
for (auto shaderInfo : shaderChain) {
365
for (size_t i = 0; i < ARRAY_SIZE(shaderInfo->settings); ++i) {
366
auto &setting = shaderInfo->settings[i];
367
if (!setting.name.empty()) {
368
hasSettings = true;
369
break;
370
}
371
}
372
}
373
if (hasSettings) {
374
CheckBox *checkBox = new CheckBox(&settingsVisible_[i], ImageID("I_SLIDERS"), new LinearLayoutParams(0.0f));
375
auto settingsButton = shaderRow->Add(checkBox);
376
settingsButton->OnClick.Add([=](EventParams &e) {
377
RecreateViews();
378
return UI::EVENT_DONE;
379
});
380
}
381
382
auto removeButton = shaderRow->Add(new Choice(ImageID("I_TRASHCAN"), new LinearLayoutParams(0.0f)));
383
removeButton->OnClick.Add([=](EventParams &e) -> UI::EventReturn {
384
// Protect against possible race conditions.
385
if (i < g_Config.vPostShaderNames.size()) {
386
g_Config.vPostShaderNames.erase(g_Config.vPostShaderNames.begin() + i);
387
FixPostShaderOrder(&g_Config.vPostShaderNames);
388
NotifyPostChanges();
389
RecreateViews();
390
}
391
return UI::EVENT_DONE;
392
});
393
394
auto moreButton = shaderRow->Add(new Choice(ImageID("I_THREE_DOTS"), new LinearLayoutParams(0.0f)));
395
moreButton->OnClick.Add([=](EventParams &e) -> UI::EventReturn {
396
if (i >= g_Config.vPostShaderNames.size()) {
397
// Protect against possible race conditions.
398
return UI::EVENT_DONE;
399
}
400
401
PopupContextMenuScreen *contextMenu = new UI::PopupContextMenuScreen(postShaderContextMenu, ARRAY_SIZE(postShaderContextMenu), I18NCat::DIALOG, moreButton);
402
screenManager()->push(contextMenu);
403
const ShaderInfo *info = GetPostShaderInfo(g_Config.vPostShaderNames[i]);
404
bool usesLastFrame = info ? info->usePreviousFrame : false;
405
contextMenu->SetEnabled(0, i > 0 && !usesLastFrame);
406
contextMenu->SetEnabled(1, i < g_Config.vPostShaderNames.size() - 1);
407
contextMenu->OnChoice.Add([=](EventParams &e) -> UI::EventReturn {
408
switch (e.a) {
409
case 0: // Move up
410
std::swap(g_Config.vPostShaderNames[i - 1], g_Config.vPostShaderNames[i]);
411
break;
412
case 1: // Move down
413
std::swap(g_Config.vPostShaderNames[i], g_Config.vPostShaderNames[i + 1]);
414
break;
415
case 2: // Remove
416
g_Config.vPostShaderNames.erase(g_Config.vPostShaderNames.begin() + i);
417
break;
418
default:
419
return UI::EVENT_DONE;
420
}
421
FixPostShaderOrder(&g_Config.vPostShaderNames);
422
NotifyPostChanges();
423
RecreateViews();
424
return UI::EVENT_DONE;
425
});
426
return UI::EVENT_DONE;
427
});
428
}
429
430
431
// No need for settings on the last one.
432
if (i == g_Config.vPostShaderNames.size())
433
continue;
434
435
if (!settingsVisible_[i])
436
continue;
437
438
std::vector<const ShaderInfo *> shaderChain = GetPostShaderChain(g_Config.vPostShaderNames[i]);
439
for (auto shaderInfo : shaderChain) {
440
// Disable duplicated shader slider
441
bool duplicated = alreadyAddedShader.find(shaderInfo->section) != alreadyAddedShader.end();
442
alreadyAddedShader.insert(shaderInfo->section);
443
444
LinearLayout *settingContainer = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(UI::FILL_PARENT, UI::WRAP_CONTENT, UI::Margins(24.0f, 0.0f, 0.0f, 0.0f)));
445
leftColumn->Add(settingContainer);
446
for (size_t i = 0; i < ARRAY_SIZE(shaderInfo->settings); ++i) {
447
auto &setting = shaderInfo->settings[i];
448
if (!setting.name.empty()) {
449
// This map lookup will create the setting in the mPostShaderSetting map if it doesn't exist, with a default value of 0.0.
450
std::string key = StringFromFormat("%sSettingCurrentValue%d", shaderInfo->section.c_str(), i + 1);
451
bool keyExisted = g_Config.mPostShaderSetting.find(key) != g_Config.mPostShaderSetting.end();
452
auto &value = g_Config.mPostShaderSetting[key];
453
if (!keyExisted)
454
value = setting.value;
455
456
if (duplicated) {
457
auto sliderName = StringFromFormat("%s %s", ps->T_cstr(setting.name.c_str()), ps->T_cstr("(duplicated setting, previous slider will be used)"));
458
PopupSliderChoiceFloat *settingValue = settingContainer->Add(new PopupSliderChoiceFloat(&value, setting.minValue, setting.maxValue, setting.value, sliderName, setting.step, screenManager()));
459
settingValue->SetEnabled(false);
460
} else {
461
PopupSliderChoiceFloat *settingValue = settingContainer->Add(new PopupSliderChoiceFloat(&value, setting.minValue, setting.maxValue, setting.value, ps->T(setting.name), setting.step, screenManager()));
462
settingValue->SetLiveUpdate(true);
463
settingValue->SetHasDropShadow(false);
464
settingValue->SetEnabledFunc([=] {
465
return !g_Config.bSkipBufferEffects && !enableStereo();
466
});
467
}
468
}
469
}
470
}
471
}
472
473
root_->Add(new DisplayLayoutBackground(mode_, new AnchorLayoutParams(FILL_PARENT, FILL_PARENT, 0.0f, 0.0f, 0.0f, 0.0f)));
474
}
475
476
void PostProcScreen::CreateViews() {
477
auto ps = GetI18NCategory(I18NCat::POSTSHADERS);
478
ReloadAllPostShaderInfo(screenManager()->getDrawContext());
479
shaders_ = GetAllPostShaderInfo();
480
std::vector<std::string> items;
481
int selected = -1;
482
const std::string selectedName = id_ >= (int)g_Config.vPostShaderNames.size() ? "Off" : g_Config.vPostShaderNames[id_];
483
484
for (int i = 0; i < (int)shaders_.size(); i++) {
485
if (!shaders_[i].visible)
486
continue;
487
if (shaders_[i].isStereo != showStereoShaders_)
488
continue;
489
if (shaders_[i].section == selectedName)
490
selected = (int)indexTranslation_.size();
491
items.push_back(std::string(ps->T(shaders_[i].section.c_str(), shaders_[i].name.c_str())));
492
indexTranslation_.push_back(i);
493
}
494
adaptor_ = UI::StringVectorListAdaptor(items, selected);
495
ListPopupScreen::CreateViews();
496
}
497
498
void PostProcScreen::OnCompleted(DialogResult result) {
499
if (result != DR_OK)
500
return;
501
const std::string &value = shaders_[indexTranslation_[listView_->GetSelected()]].section;
502
// I feel this logic belongs more in the caller, but eh...
503
if (showStereoShaders_) {
504
if (g_Config.sStereoToMonoShader != value) {
505
g_Config.sStereoToMonoShader = value;
506
System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED);
507
}
508
} else {
509
if (id_ < (int)g_Config.vPostShaderNames.size()) {
510
if (g_Config.vPostShaderNames[id_] != value) {
511
g_Config.vPostShaderNames[id_] = value;
512
System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED);
513
}
514
} else {
515
g_Config.vPostShaderNames.push_back(value);
516
System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED);
517
}
518
}
519
}
520
521