CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/UI/DisplayLayoutScreen.cpp
Views: 1401
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_IsInited() && !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
UI::EventReturn DisplayLayoutScreen::OnPostProcShaderChange(UI::EventParams &e) {
151
// Remove the virtual "Off" entry. TODO: Get rid of it generally.
152
g_Config.vPostShaderNames.erase(std::remove(g_Config.vPostShaderNames.begin(), g_Config.vPostShaderNames.end(), "Off"), g_Config.vPostShaderNames.end());
153
FixPostShaderOrder(&g_Config.vPostShaderNames);
154
155
System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED);
156
System_PostUIMessage(UIMessage::GPU_RENDER_RESIZED); // To deal with shaders that can change render resolution like upscaling.
157
System_PostUIMessage(UIMessage::POSTSHADER_UPDATED);
158
159
if (gpu) {
160
gpu->NotifyConfigChanged();
161
}
162
return UI::EVENT_DONE;
163
}
164
165
static std::string PostShaderTranslateName(std::string_view value) {
166
if (value == "Off") {
167
auto gr = GetI18NCategory(I18NCat::GRAPHICS);
168
// Off is a legacy fake item (gonna migrate off it later).
169
return std::string(gr->T("Add postprocessing shader"));
170
}
171
172
const ShaderInfo *info = GetPostShaderInfo(value);
173
if (info) {
174
auto ps = GetI18NCategory(I18NCat::POSTSHADERS);
175
return std::string(ps->T(value, info->name));
176
} else {
177
return std::string(value);
178
}
179
}
180
181
void DisplayLayoutScreen::sendMessage(UIMessage message, const char *value) {
182
UIDialogScreenWithGameBackground::sendMessage(message, value);
183
if (message == UIMessage::POSTSHADER_UPDATED) {
184
g_Config.bShaderChainRequires60FPS = PostShaderChainRequires60FPS(GetFullPostShadersChain(g_Config.vPostShaderNames));
185
RecreateViews();
186
}
187
}
188
189
void DisplayLayoutScreen::CreateViews() {
190
const Bounds &bounds = screenManager()->getUIContext()->GetBounds();
191
192
using namespace UI;
193
194
auto di = GetI18NCategory(I18NCat::DIALOG);
195
auto gr = GetI18NCategory(I18NCat::GRAPHICS);
196
auto co = GetI18NCategory(I18NCat::CONTROLS);
197
auto ps = GetI18NCategory(I18NCat::POSTSHADERS);
198
199
root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
200
201
bool vertical = bounds.h > bounds.w;
202
203
// Make it so that a touch can only affect one view. Makes manipulating the background through the buttons
204
// impossible.
205
root_->SetExclusiveTouch(true);
206
207
LinearLayout *leftColumn;
208
if (!vertical) {
209
ScrollView *leftScrollView = new ScrollView(ORIENT_VERTICAL, new AnchorLayoutParams(420.0f, FILL_PARENT, 0.f, 0.f, NONE, 0.f, false));
210
leftColumn = new LinearLayout(ORIENT_VERTICAL);
211
leftColumn->padding.SetAll(8.0f);
212
leftScrollView->Add(leftColumn);
213
leftScrollView->SetClickableBackground(true);
214
root_->Add(leftScrollView);
215
}
216
217
ScrollView *rightScrollView = new ScrollView(ORIENT_VERTICAL, new AnchorLayoutParams(300.0f, FILL_PARENT, NONE, 0.f, 0.f, 0.f, false));
218
LinearLayout *rightColumn = new LinearLayout(ORIENT_VERTICAL);
219
rightColumn->padding.SetAll(8.0f);
220
rightScrollView->Add(rightColumn);
221
rightScrollView->SetClickableBackground(true);
222
root_->Add(rightScrollView);
223
224
LinearLayout *bottomControls;
225
if (vertical) {
226
bottomControls = new LinearLayout(ORIENT_HORIZONTAL);
227
rightColumn->Add(bottomControls);
228
leftColumn = rightColumn;
229
} else {
230
bottomControls = new LinearLayout(ORIENT_HORIZONTAL, new AnchorLayoutParams(NONE, NONE, NONE, 10.0f, false));
231
root_->Add(bottomControls);
232
}
233
234
// Set backgrounds for readability
235
Drawable backgroundWithAlpha(GetBackgroundColorWithAlpha(*screenManager()->getUIContext()));
236
leftColumn->SetBG(backgroundWithAlpha);
237
rightColumn->SetBG(backgroundWithAlpha);
238
239
if (!IsVREnabled()) {
240
auto stretch = new CheckBox(&g_Config.bDisplayStretch, gr->T("Stretch"));
241
stretch->SetDisabledPtr(&g_Config.bDisplayIntegerScale);
242
rightColumn->Add(stretch);
243
244
PopupSliderChoiceFloat *aspectRatio = new PopupSliderChoiceFloat(&g_Config.fDisplayAspectRatio, 0.1f, 2.0f, 1.0f, gr->T("Aspect Ratio"), screenManager());
245
rightColumn->Add(aspectRatio);
246
aspectRatio->SetEnabledFunc([]() {
247
return !g_Config.bDisplayStretch && !g_Config.bDisplayIntegerScale;
248
});
249
aspectRatio->SetHasDropShadow(false);
250
aspectRatio->SetLiveUpdate(true);
251
252
rightColumn->Add(new CheckBox(&g_Config.bDisplayIntegerScale, gr->T("Integer scale factor")));
253
254
#if PPSSPP_PLATFORM(ANDROID)
255
// Hide insets option if no insets, or OS too old.
256
if (System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= 28 &&
257
(System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_LEFT) != 0.0f ||
258
System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_TOP) != 0.0f ||
259
System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_RIGHT) != 0.0f ||
260
System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_BOTTOM) != 0.0f)) {
261
rightColumn->Add(new CheckBox(&g_Config.bIgnoreScreenInsets, gr->T("Ignore camera notch when centering")));
262
}
263
#endif
264
265
mode_ = new ChoiceStrip(ORIENT_HORIZONTAL, new LinearLayoutParams(WRAP_CONTENT, WRAP_CONTENT));
266
mode_->AddChoice(di->T("Inactive"));
267
mode_->AddChoice(di->T("Move"));
268
mode_->AddChoice(di->T("Resize"));
269
mode_->SetSelection(0, false);
270
bottomControls->Add(mode_);
271
272
static const char *displayRotation[] = { "Landscape", "Portrait", "Landscape Reversed", "Portrait Reversed" };
273
auto rotation = new PopupMultiChoice(&g_Config.iInternalScreenRotation, gr->T("Rotation"), displayRotation, 1, ARRAY_SIZE(displayRotation), I18NCat::CONTROLS, screenManager());
274
rotation->SetEnabledFunc([] {
275
return !g_Config.bSkipBufferEffects || g_Config.bSoftwareRendering;
276
});
277
rotation->SetHideTitle(true);
278
rightColumn->Add(rotation);
279
280
Choice *center = new Choice(di->T("Reset"));
281
center->OnClick.Add([&](UI::EventParams &) {
282
g_Config.fDisplayAspectRatio = 1.0f;
283
g_Config.fDisplayScale = 1.0f;
284
g_Config.fDisplayOffsetX = 0.5f;
285
g_Config.fDisplayOffsetY = 0.5f;
286
return UI::EVENT_DONE;
287
});
288
rightColumn->Add(center);
289
290
rightColumn->Add(new Spacer(12.0f));
291
}
292
293
Choice *back = new Choice(di->T("Back"), "", false);
294
back->OnClick.Handle<UIScreen>(this, &UIScreen::OnBack);
295
rightColumn->Add(back);
296
297
if (vertical) {
298
leftColumn->Add(new Spacer(24.0f));
299
}
300
301
if (!IsVREnabled()) {
302
static const char *bufFilters[] = { "Linear", "Nearest", };
303
leftColumn->Add(new PopupMultiChoice(&g_Config.iDisplayFilter, gr->T("Screen Scaling Filter"), bufFilters, 1, ARRAY_SIZE(bufFilters), I18NCat::GRAPHICS, screenManager()));
304
}
305
306
Draw::DrawContext *draw = screenManager()->getDrawContext();
307
308
bool multiViewSupported = draw->GetDeviceCaps().multiViewSupported;
309
310
auto enableStereo = [=]() -> bool {
311
return g_Config.bStereoRendering && multiViewSupported;
312
};
313
314
leftColumn->Add(new ItemHeader(gr->T("Postprocessing shaders")));
315
316
std::set<std::string> alreadyAddedShader;
317
// If there's a single post shader and we're just entering the dialog,
318
// auto-open the settings.
319
if (settingsVisible_.empty() && g_Config.vPostShaderNames.size() == 1) {
320
settingsVisible_.push_back(true);
321
} else if (settingsVisible_.size() < g_Config.vPostShaderNames.size()) {
322
settingsVisible_.resize(g_Config.vPostShaderNames.size());
323
}
324
325
static ContextMenuItem postShaderContextMenu[] = {
326
{ "Move Up", "I_ARROW_UP" },
327
{ "Move Down", "I_ARROW_DOWN" },
328
{ "Remove", "I_TRASHCAN" },
329
};
330
331
for (int i = 0; i < (int)g_Config.vPostShaderNames.size() + 1 && i < ARRAY_SIZE(shaderNames_); ++i) {
332
// Vector element pointer get invalidated on resize, cache name to have always a valid reference in the rendering thread
333
shaderNames_[i] = i == g_Config.vPostShaderNames.size() ? "Off" : g_Config.vPostShaderNames[i];
334
335
LinearLayout *shaderRow = new LinearLayout(ORIENT_HORIZONTAL, new LinearLayoutParams(UI::FILL_PARENT, UI::WRAP_CONTENT));
336
shaderRow->SetSpacing(4.0f);
337
leftColumn->Add(shaderRow);
338
339
if (shaderNames_[i] != "Off") {
340
postProcChoice_ = shaderRow->Add(new ChoiceWithValueDisplay(&shaderNames_[i], "", &PostShaderTranslateName, new LinearLayoutParams(1.0f)));
341
} else {
342
postProcChoice_ = shaderRow->Add(new Choice(ImageID("I_PLUS")));
343
}
344
postProcChoice_->OnClick.Add([=](EventParams &e) {
345
auto gr = GetI18NCategory(I18NCat::GRAPHICS);
346
auto procScreen = new PostProcScreen(gr->T("Postprocessing shaders"), i, false);
347
procScreen->SetHasDropShadow(false);
348
procScreen->OnChoice.Handle(this, &DisplayLayoutScreen::OnPostProcShaderChange);
349
if (e.v)
350
procScreen->SetPopupOrigin(e.v);
351
screenManager()->push(procScreen);
352
return UI::EVENT_DONE;
353
});
354
postProcChoice_->SetEnabledFunc([=] {
355
return !g_Config.bSkipBufferEffects && !enableStereo();
356
});
357
358
if (i < g_Config.vPostShaderNames.size()) {
359
bool hasSettings = false;
360
std::vector<const ShaderInfo *> shaderChain = GetPostShaderChain(g_Config.vPostShaderNames[i]);
361
for (auto shaderInfo : shaderChain) {
362
for (size_t i = 0; i < ARRAY_SIZE(shaderInfo->settings); ++i) {
363
auto &setting = shaderInfo->settings[i];
364
if (!setting.name.empty()) {
365
hasSettings = true;
366
break;
367
}
368
}
369
}
370
if (hasSettings) {
371
CheckBox *checkBox = new CheckBox(&settingsVisible_[i], ImageID("I_SLIDERS"), new LinearLayoutParams(0.0f));
372
auto settingsButton = shaderRow->Add(checkBox);
373
settingsButton->OnClick.Add([=](EventParams &e) {
374
RecreateViews();
375
return UI::EVENT_DONE;
376
});
377
}
378
379
auto removeButton = shaderRow->Add(new Choice(ImageID("I_TRASHCAN"), new LinearLayoutParams(0.0f)));
380
removeButton->OnClick.Add([=](EventParams &e) -> UI::EventReturn {
381
g_Config.vPostShaderNames.erase(g_Config.vPostShaderNames.begin() + i);
382
System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED);
383
RecreateViews();
384
return UI::EVENT_DONE;
385
});
386
387
auto moreButton = shaderRow->Add(new Choice(ImageID("I_THREE_DOTS"), new LinearLayoutParams(0.0f)));
388
moreButton->OnClick.Add([=](EventParams &e) -> UI::EventReturn {
389
PopupContextMenuScreen *contextMenu = new UI::PopupContextMenuScreen(postShaderContextMenu, ARRAY_SIZE(postShaderContextMenu), I18NCat::DIALOG, moreButton);
390
screenManager()->push(contextMenu);
391
const ShaderInfo *info = GetPostShaderInfo(g_Config.vPostShaderNames[i]);
392
bool usesLastFrame = info ? info->usePreviousFrame : false;
393
contextMenu->SetEnabled(0, i > 0 && !usesLastFrame);
394
contextMenu->SetEnabled(1, i < g_Config.vPostShaderNames.size() - 1);
395
contextMenu->OnChoice.Add([=](EventParams &e) -> UI::EventReturn {
396
switch (e.a) {
397
case 0: // Move up
398
std::swap(g_Config.vPostShaderNames[i - 1], g_Config.vPostShaderNames[i]);
399
break;
400
case 1: // Move down
401
std::swap(g_Config.vPostShaderNames[i], g_Config.vPostShaderNames[i + 1]);
402
break;
403
case 2: // Remove
404
g_Config.vPostShaderNames.erase(g_Config.vPostShaderNames.begin() + i);
405
break;
406
default:
407
return UI::EVENT_DONE;
408
}
409
FixPostShaderOrder(&g_Config.vPostShaderNames);
410
System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED);
411
RecreateViews();
412
return UI::EVENT_DONE;
413
});
414
return UI::EVENT_DONE;
415
});
416
}
417
418
419
// No need for settings on the last one.
420
if (i == g_Config.vPostShaderNames.size())
421
continue;
422
423
if (!settingsVisible_[i])
424
continue;
425
426
std::vector<const ShaderInfo *> shaderChain = GetPostShaderChain(g_Config.vPostShaderNames[i]);
427
for (auto shaderInfo : shaderChain) {
428
// Disable duplicated shader slider
429
bool duplicated = alreadyAddedShader.find(shaderInfo->section) != alreadyAddedShader.end();
430
alreadyAddedShader.insert(shaderInfo->section);
431
432
LinearLayout *settingContainer = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(UI::FILL_PARENT, UI::WRAP_CONTENT, UI::Margins(24.0f, 0.0f, 0.0f, 0.0f)));
433
leftColumn->Add(settingContainer);
434
for (size_t i = 0; i < ARRAY_SIZE(shaderInfo->settings); ++i) {
435
auto &setting = shaderInfo->settings[i];
436
if (!setting.name.empty()) {
437
// This map lookup will create the setting in the mPostShaderSetting map if it doesn't exist, with a default value of 0.0.
438
std::string key = StringFromFormat("%sSettingCurrentValue%d", shaderInfo->section.c_str(), i + 1);
439
bool keyExisted = g_Config.mPostShaderSetting.find(key) != g_Config.mPostShaderSetting.end();
440
auto &value = g_Config.mPostShaderSetting[key];
441
if (!keyExisted)
442
value = setting.value;
443
444
if (duplicated) {
445
auto sliderName = StringFromFormat("%s %s", ps->T(setting.name), ps->T("(duplicated setting, previous slider will be used)"));
446
PopupSliderChoiceFloat *settingValue = settingContainer->Add(new PopupSliderChoiceFloat(&value, setting.minValue, setting.maxValue, setting.value, sliderName, setting.step, screenManager()));
447
settingValue->SetEnabled(false);
448
} else {
449
PopupSliderChoiceFloat *settingValue = settingContainer->Add(new PopupSliderChoiceFloat(&value, setting.minValue, setting.maxValue, setting.value, ps->T(setting.name), setting.step, screenManager()));
450
settingValue->SetLiveUpdate(true);
451
settingValue->SetHasDropShadow(false);
452
settingValue->SetEnabledFunc([=] {
453
return !g_Config.bSkipBufferEffects && !enableStereo();
454
});
455
}
456
}
457
}
458
}
459
}
460
461
root_->Add(new DisplayLayoutBackground(mode_, new AnchorLayoutParams(FILL_PARENT, FILL_PARENT, 0.0f, 0.0f, 0.0f, 0.0f)));
462
}
463
464
void PostProcScreen::CreateViews() {
465
auto ps = GetI18NCategory(I18NCat::POSTSHADERS);
466
ReloadAllPostShaderInfo(screenManager()->getDrawContext());
467
shaders_ = GetAllPostShaderInfo();
468
std::vector<std::string> items;
469
int selected = -1;
470
const std::string selectedName = id_ >= (int)g_Config.vPostShaderNames.size() ? "Off" : g_Config.vPostShaderNames[id_];
471
472
for (int i = 0; i < (int)shaders_.size(); i++) {
473
if (!shaders_[i].visible)
474
continue;
475
if (shaders_[i].isStereo != showStereoShaders_)
476
continue;
477
if (shaders_[i].section == selectedName)
478
selected = (int)indexTranslation_.size();
479
items.push_back(std::string(ps->T(shaders_[i].section.c_str(), shaders_[i].name.c_str())));
480
indexTranslation_.push_back(i);
481
}
482
adaptor_ = UI::StringVectorListAdaptor(items, selected);
483
ListPopupScreen::CreateViews();
484
}
485
486
void PostProcScreen::OnCompleted(DialogResult result) {
487
if (result != DR_OK)
488
return;
489
const std::string &value = shaders_[indexTranslation_[listView_->GetSelected()]].section;
490
// I feel this logic belongs more in the caller, but eh...
491
if (showStereoShaders_) {
492
if (g_Config.sStereoToMonoShader != value) {
493
g_Config.sStereoToMonoShader = value;
494
System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED);
495
}
496
} else {
497
if (id_ < (int)g_Config.vPostShaderNames.size()) {
498
if (g_Config.vPostShaderNames[id_] != value) {
499
g_Config.vPostShaderNames[id_] = value;
500
System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED);
501
}
502
} else {
503
g_Config.vPostShaderNames.push_back(value);
504
System_PostUIMessage(UIMessage::GPU_CONFIG_CHANGED);
505
}
506
}
507
}
508
509