mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 13:30:02 +00:00
If there are multiple Vulkan devices, show a setting to allow the user to choose.
This commit is contained in:
parent
b9388f50e1
commit
b037efdb55
@ -213,6 +213,7 @@ VkResult VulkanContext::CreateInstance(const CreateInfo &info) {
|
||||
|
||||
assert(gpu_count > 0);
|
||||
physical_devices_.resize(gpu_count);
|
||||
physicalDeviceProperties_.resize(gpu_count);
|
||||
res = vkEnumeratePhysicalDevices(instance_, &gpu_count, physical_devices_.data());
|
||||
if (res != VK_SUCCESS) {
|
||||
init_error_ = "Failed to enumerate physical devices";
|
||||
@ -221,6 +222,9 @@ VkResult VulkanContext::CreateInstance(const CreateInfo &info) {
|
||||
return res;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < gpu_count; i++) {
|
||||
vkGetPhysicalDeviceProperties(physical_devices_[i], &physicalDeviceProperties_[i]);
|
||||
}
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
@ -417,6 +421,14 @@ bool VulkanContext::CheckLayers(const std::vector<LayerProperties> &layer_props,
|
||||
return true;
|
||||
}
|
||||
|
||||
int VulkanContext::GetPhysicalDeviceByName(std::string name) {
|
||||
for (size_t i = 0; i < physical_devices_.size(); i++) {
|
||||
if (physicalDeviceProperties_[i].deviceName == name)
|
||||
return (int)i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int VulkanContext::GetBestPhysicalDevice() {
|
||||
// Rules: Prefer discrete over embedded.
|
||||
// Prefer nVidia over Intel.
|
||||
@ -490,7 +502,6 @@ void VulkanContext::ChooseDevice(int physical_device) {
|
||||
|
||||
// This is as good a place as any to do this
|
||||
vkGetPhysicalDeviceMemoryProperties(physical_devices_[physical_device_], &memory_properties);
|
||||
vkGetPhysicalDeviceProperties(physical_devices_[physical_device_], &gpu_props);
|
||||
|
||||
// Optional features
|
||||
vkGetPhysicalDeviceFeatures(physical_devices_[physical_device_], &featuresAvailable_);
|
||||
|
@ -128,6 +128,7 @@ public:
|
||||
void DestroyInstance();
|
||||
|
||||
int GetBestPhysicalDevice();
|
||||
int GetPhysicalDeviceByName(std::string name);
|
||||
void ChooseDevice(int physical_device);
|
||||
bool EnableDeviceExtension(const char *extension);
|
||||
VkResult CreateDevice();
|
||||
@ -173,6 +174,12 @@ public:
|
||||
VkPhysicalDevice GetPhysicalDevice(int n = 0) const {
|
||||
return physical_devices_[n];
|
||||
}
|
||||
int GetCurrentPhysicalDevice() const {
|
||||
return physical_device_;
|
||||
}
|
||||
int GetNumPhysicalDevices() const {
|
||||
return (int)physical_devices_.size();
|
||||
}
|
||||
|
||||
VkQueue GetGraphicsQueue() const {
|
||||
return gfx_queue_;
|
||||
@ -182,8 +189,8 @@ public:
|
||||
return graphics_queue_family_index_;
|
||||
}
|
||||
|
||||
const VkPhysicalDeviceProperties &GetPhysicalDeviceProperties() {
|
||||
return gpu_props;
|
||||
const VkPhysicalDeviceProperties &GetPhysicalDeviceProperties(int i) const {
|
||||
return physicalDeviceProperties_[i];
|
||||
}
|
||||
|
||||
VkResult GetInstanceLayerExtensionList(const char *layerName, std::vector<VkExtensionProperties> &extensions);
|
||||
@ -281,7 +288,7 @@ private:
|
||||
int physical_device_ = -1;
|
||||
|
||||
uint32_t graphics_queue_family_index_ = -1;
|
||||
VkPhysicalDeviceProperties gpu_props{};
|
||||
std::vector<VkPhysicalDeviceProperties> physicalDeviceProperties_{};
|
||||
std::vector<VkQueueFamilyProperties> queue_props;
|
||||
VkPhysicalDeviceMemoryProperties memory_properties{};
|
||||
|
||||
|
@ -507,6 +507,7 @@ static ConfigSetting graphicsSettings[] = {
|
||||
ConfigSetting("CardboardYShift", &g_Config.iCardboardXShift, 0, true, true),
|
||||
ConfigSetting("ShowFPSCounter", &g_Config.iShowFPSCounter, 0, true, true),
|
||||
ReportedConfigSetting("GraphicsBackend", &g_Config.iGPUBackend, &DefaultGPUBackend),
|
||||
ConfigSetting("VulkanDevice", &g_Config.VulkanDevice, "", true, false),
|
||||
ReportedConfigSetting("RenderingMode", &g_Config.iRenderingMode, &DefaultRenderingMode, true, true),
|
||||
ConfigSetting("SoftwareRenderer", &g_Config.bSoftwareRendering, false, true, true),
|
||||
ReportedConfigSetting("HardwareTransform", &g_Config.bHardwareTransform, true, true, true),
|
||||
|
@ -153,6 +153,9 @@ public:
|
||||
|
||||
// GFX
|
||||
int iGPUBackend;
|
||||
// We have separate device parameters for each backend so it doesn't get erased if you switch backends.
|
||||
// If not set, will use the "best" device.
|
||||
std::string VulkanDevice;
|
||||
bool bSoftwareRendering;
|
||||
bool bHardwareTransform; // only used in the GLES backend
|
||||
bool bSoftwareSkinning; // may speed up some games
|
||||
|
@ -1007,7 +1007,7 @@ void DrawEngineVulkan::TessellationDataTransferVulkan::PrepareBuffers(float *&po
|
||||
float color[4];
|
||||
};
|
||||
|
||||
int ssboAlignment = vulkan_->GetPhysicalDeviceProperties().limits.minStorageBufferOffsetAlignment;
|
||||
int ssboAlignment = vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).limits.minStorageBufferOffsetAlignment;
|
||||
uint8_t *data = (uint8_t *)push_->PushAligned(size * sizeof(TessData), &offset_, &buf_, ssboAlignment);
|
||||
range_ = size * sizeof(TessData);
|
||||
|
||||
|
@ -175,7 +175,7 @@ GPU_Vulkan::~GPU_Vulkan() {
|
||||
void GPU_Vulkan::CheckGPUFeatures() {
|
||||
uint32_t features = 0;
|
||||
|
||||
switch (vulkan_->GetPhysicalDeviceProperties().vendorID) {
|
||||
switch (vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).vendorID) {
|
||||
case VULKAN_VENDOR_AMD:
|
||||
// Accurate depth is required on AMD (due to reverse-Z driver bug) so we ignore the compat flag to disable it on those. See #9545
|
||||
features |= GPU_SUPPORTS_ACCURATE_DEPTH;
|
||||
@ -183,7 +183,7 @@ void GPU_Vulkan::CheckGPUFeatures() {
|
||||
case VULKAN_VENDOR_ARM:
|
||||
// Also required on older ARM Mali drivers, like the one on many Galaxy S7.
|
||||
if (!PSP_CoreParameter().compat.flags().DisableAccurateDepth ||
|
||||
vulkan_->GetPhysicalDeviceProperties().driverVersion <= VK_MAKE_VERSION(428, 811, 2674)) {
|
||||
vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).driverVersion <= VK_MAKE_VERSION(428, 811, 2674)) {
|
||||
features |= GPU_SUPPORTS_ACCURATE_DEPTH;
|
||||
}
|
||||
break;
|
||||
@ -212,7 +212,7 @@ void GPU_Vulkan::CheckGPUFeatures() {
|
||||
features |= GPU_SUPPORTS_DEPTH_CLAMP;
|
||||
}
|
||||
if (vulkan_->GetFeaturesEnabled().dualSrcBlend) {
|
||||
switch (vulkan_->GetPhysicalDeviceProperties().vendorID) {
|
||||
switch (vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).vendorID) {
|
||||
// We thought we had a bug here on nVidia but turns out we accidentally #ifdef-ed out crucial
|
||||
// code on Android.
|
||||
case VULKAN_VENDOR_INTEL:
|
||||
@ -220,7 +220,7 @@ void GPU_Vulkan::CheckGPUFeatures() {
|
||||
break;
|
||||
case VULKAN_VENDOR_AMD:
|
||||
// See issue #10074, and also #10065 (AMD) and #10109 for the choice of the driver version to check for
|
||||
if (vulkan_->GetPhysicalDeviceProperties().driverVersion >= 0x00407000)
|
||||
if (vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).driverVersion >= 0x00407000)
|
||||
features |= GPU_SUPPORTS_DUALSOURCE_BLEND;
|
||||
break;
|
||||
default:
|
||||
@ -310,7 +310,7 @@ void GPU_Vulkan::EndHostFrame() {
|
||||
|
||||
// Needs to be called on GPU thread, not reporting thread.
|
||||
void GPU_Vulkan::BuildReportingInfo() {
|
||||
const auto &props = vulkan_->GetPhysicalDeviceProperties();
|
||||
const auto &props = vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice());
|
||||
const auto &features = vulkan_->GetFeaturesAvailable();
|
||||
|
||||
#define CHECK_BOOL_FEATURE(n) do { if (features.n) { featureNames += ", " #n; } } while (false)
|
||||
|
@ -676,7 +676,7 @@ bool PipelineManagerVulkan::LoadCache(FILE *file, bool loadRawPipelineCache, Sha
|
||||
WARN_LOG(G3D, "Bad Vulkan pipeline cache header - ignoring");
|
||||
return false;
|
||||
}
|
||||
if (0 != memcmp(header->uuid, vulkan_->GetPhysicalDeviceProperties().pipelineCacheUUID, VK_UUID_SIZE)) {
|
||||
if (0 != memcmp(header->uuid, vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).pipelineCacheUUID, VK_UUID_SIZE)) {
|
||||
// Wrong hardware/driver/etc.
|
||||
WARN_LOG(G3D, "Bad Vulkan pipeline cache UUID - ignoring");
|
||||
return false;
|
||||
|
@ -159,7 +159,7 @@ std::string VulkanVertexShader::GetShaderString(DebugShaderStringType type) cons
|
||||
ShaderManagerVulkan::ShaderManagerVulkan(VulkanContext *vulkan)
|
||||
: vulkan_(vulkan), lastVShader_(nullptr), lastFShader_(nullptr), fsCache_(16), vsCache_(16) {
|
||||
codeBuffer_ = new char[16384];
|
||||
uboAlignment_ = vulkan_->GetPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment;
|
||||
uboAlignment_ = vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).limits.minUniformBufferOffsetAlignment;
|
||||
memset(&ub_base, 0, sizeof(ub_base));
|
||||
memset(&ub_lights, 0, sizeof(ub_lights));
|
||||
memset(&ub_bones, 0, sizeof(ub_bones));
|
||||
@ -176,7 +176,7 @@ ShaderManagerVulkan::~ShaderManagerVulkan() {
|
||||
|
||||
void ShaderManagerVulkan::DeviceRestore(VulkanContext *vulkan) {
|
||||
vulkan_ = vulkan;
|
||||
uboAlignment_ = vulkan_->GetPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment;
|
||||
uboAlignment_ = vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).limits.minUniformBufferOffsetAlignment;
|
||||
}
|
||||
|
||||
void ShaderManagerVulkan::Clear() {
|
||||
|
@ -683,7 +683,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) {
|
||||
uint32_t bufferOffset;
|
||||
VkBuffer texBuf;
|
||||
// nvidia returns 1 but that can't be healthy... let's align by 16 as a minimum.
|
||||
int pushAlignment = std::max(16, (int)vulkan_->GetPhysicalDeviceProperties().limits.optimalBufferCopyOffsetAlignment);
|
||||
int pushAlignment = std::max(16, (int)vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).limits.optimalBufferCopyOffsetAlignment);
|
||||
void *data = drawEngine_->GetPushBufferForTextureData()->PushAligned(size, &bufferOffset, &texBuf, pushAlignment);
|
||||
if (replaced.Valid()) {
|
||||
replaced.Load(i, data, stride);
|
||||
|
@ -202,6 +202,19 @@ void GameSettingsScreen::CreateViews() {
|
||||
renderingBackendChoice->HideChoice(3);
|
||||
}
|
||||
#endif
|
||||
Draw::DrawContext *draw = screenManager()->getDrawContext();
|
||||
if (draw->GetDeviceList().size() > 0) {
|
||||
// Some backends don't support switching so no point in showing multiple devices.
|
||||
std::string *deviceNameSetting = nullptr;
|
||||
if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) {
|
||||
deviceNameSetting = &g_Config.VulkanDevice;
|
||||
}
|
||||
|
||||
if (deviceNameSetting) {
|
||||
PopupMultiChoiceDynamic *deviceChoice = graphicsSettings->Add(new PopupMultiChoiceDynamic(deviceNameSetting, gr->T("Device"), draw->GetDeviceList(), nullptr, screenManager()));
|
||||
deviceChoice->OnChoice.Handle(this, &GameSettingsScreen::OnRenderingBackend);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *renderingMode[] = { "Non-Buffered Rendering", "Buffered Rendering"};
|
||||
PopupMultiChoice *renderingModeChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iRenderingMode, gr->T("Mode"), renderingMode, 0, ARRAY_SIZE(renderingMode), gr->GetName(), screenManager()));
|
||||
|
@ -109,7 +109,12 @@ bool WindowsVulkanContext::Init(HINSTANCE hInst, HWND hWnd, std::string *error_m
|
||||
g_Vulkan = nullptr;
|
||||
return false;
|
||||
}
|
||||
g_Vulkan->ChooseDevice(g_Vulkan->GetBestPhysicalDevice());
|
||||
int deviceNum = g_Vulkan->GetPhysicalDeviceByName(g_Config.VulkanDevice);
|
||||
if (deviceNum < 0) {
|
||||
deviceNum = g_Vulkan->GetBestPhysicalDevice();
|
||||
g_Config.VulkanDevice = g_Vulkan->GetPhysicalDeviceProperties(deviceNum).deviceName;
|
||||
}
|
||||
g_Vulkan->ChooseDevice(deviceNum);
|
||||
if (g_Vulkan->EnableDeviceExtension(VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME)) {
|
||||
supportsDedicatedAlloc_ = true;
|
||||
}
|
||||
|
@ -850,7 +850,7 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step
|
||||
// See pull request #10723.
|
||||
bool maliBugWorkaround = step.render.numDraws == 0 &&
|
||||
step.render.color == VKRRenderPassAction::CLEAR &&
|
||||
vulkan_->GetPhysicalDeviceProperties().driverVersion == 0xaa9c4b29;
|
||||
vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).driverVersion == 0xaa9c4b29;
|
||||
if (maliBugWorkaround) {
|
||||
TransitionImageLayout2(cmd, step.render.framebuffer->color.image, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
fb->color.layout, VK_IMAGE_LAYOUT_GENERAL,
|
||||
|
@ -136,7 +136,7 @@ VulkanRenderManager::VulkanRenderManager(VulkanContext *vulkan) : vulkan_(vulkan
|
||||
queueRunner_.CreateDeviceObjects();
|
||||
|
||||
// Temporary AMD hack for issue #10097
|
||||
if (vulkan_->GetPhysicalDeviceProperties().vendorID == VULKAN_VENDOR_AMD) {
|
||||
if (vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).vendorID == VULKAN_VENDOR_AMD) {
|
||||
useThread_ = false;
|
||||
}
|
||||
}
|
||||
|
@ -491,6 +491,7 @@ struct DeviceCaps {
|
||||
bool framebufferBlitSupported;
|
||||
bool framebufferDepthCopySupported;
|
||||
bool framebufferDepthBlitSupported;
|
||||
std::string deviceName; // The device name to use when creating the thin3d context, to get the same one.
|
||||
};
|
||||
|
||||
struct TextureDesc {
|
||||
@ -532,6 +533,7 @@ public:
|
||||
virtual uint32_t GetDataFormatSupport(DataFormat fmt) const = 0;
|
||||
virtual std::vector<std::string> GetFeatureList() const { return std::vector<std::string>(); }
|
||||
virtual std::vector<std::string> GetExtensionList() const { return std::vector<std::string>(); }
|
||||
virtual std::vector<std::string> GetDeviceList() const { return std::vector<std::string>(); }
|
||||
|
||||
virtual uint32_t GetSupportedShaderLanguages() const = 0;
|
||||
|
||||
|
@ -33,6 +33,6 @@ DrawContext *T3DCreateDX9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapt
|
||||
DrawContext *T3DCreateD3D11Context(ID3D11Device *device, ID3D11DeviceContext *context, ID3D11Device1 *device1, ID3D11DeviceContext1 *context1, D3D_FEATURE_LEVEL featureLevel, HWND hWnd);
|
||||
#endif
|
||||
|
||||
DrawContext *T3DCreateVulkanContext(VulkanContext *context, bool split);
|
||||
DrawContext *T3DCreateVulkanContext(VulkanContext *context, bool splitSubmit);
|
||||
|
||||
} // namespace Draw
|
||||
|
@ -261,7 +261,7 @@ public:
|
||||
|
||||
// Returns the binding offset, and the VkBuffer to bind.
|
||||
size_t PushUBO(VulkanPushBuffer *buf, VulkanContext *vulkan, VkBuffer *vkbuf) {
|
||||
return buf->PushAligned(ubo_, uboSize_, vulkan->GetPhysicalDeviceProperties().limits.minUniformBufferOffsetAlignment, vkbuf);
|
||||
return buf->PushAligned(ubo_, uboSize_, vulkan->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).limits.minUniformBufferOffsetAlignment, vkbuf);
|
||||
}
|
||||
|
||||
int GetUniformLoc(const char *name);
|
||||
@ -350,6 +350,13 @@ public:
|
||||
const DeviceCaps &GetDeviceCaps() const override {
|
||||
return caps_;
|
||||
}
|
||||
std::vector<std::string> GetDeviceList() const override {
|
||||
std::vector<std::string> list;
|
||||
for (int i = 0; i < vulkan_->GetNumPhysicalDevices(); i++) {
|
||||
list.push_back(vulkan_->GetPhysicalDeviceProperties(i).deviceName);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
uint32_t GetSupportedShaderLanguages() const override {
|
||||
return (uint32_t)ShaderLanguage::GLSL_VULKAN | (uint32_t)ShaderLanguage::SPIRV_VULKAN;
|
||||
}
|
||||
@ -446,13 +453,13 @@ public:
|
||||
// TODO: Make these actually query the right information
|
||||
switch (info) {
|
||||
case APINAME: return "Vulkan";
|
||||
case VENDORSTRING: return vulkan_->GetPhysicalDeviceProperties().deviceName;
|
||||
case VENDOR: return VulkanVendorString(vulkan_->GetPhysicalDeviceProperties().vendorID);
|
||||
case DRIVER: return FormatDriverVersion(vulkan_->GetPhysicalDeviceProperties());
|
||||
case VENDORSTRING: return vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).deviceName;
|
||||
case VENDOR: return VulkanVendorString(vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).vendorID);
|
||||
case DRIVER: return FormatDriverVersion(vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()));
|
||||
case SHADELANGVERSION: return "N/A";;
|
||||
case APIVERSION:
|
||||
{
|
||||
uint32_t ver = vulkan_->GetPhysicalDeviceProperties().apiVersion;
|
||||
uint32_t ver = vulkan_->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).apiVersion;
|
||||
return StringFromFormat("%d.%d.%d", ver >> 22, (ver >> 12) & 0x3ff, ver & 0xfff);
|
||||
}
|
||||
default: return "?";
|
||||
@ -746,7 +753,7 @@ VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit)
|
||||
caps_.framebufferDepthCopySupported = true; // Will pretty much always be the case.
|
||||
caps_.preferredDepthBufferFormat = DataFormat::D24_S8; // TODO: Ask vulkan.
|
||||
|
||||
switch (vulkan->GetPhysicalDeviceProperties().vendorID) {
|
||||
switch (vulkan->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDevice()).vendorID) {
|
||||
case VULKAN_VENDOR_AMD: caps_.vendor = GPUVendor::VENDOR_AMD; break;
|
||||
case VULKAN_VENDOR_ARM: caps_.vendor = GPUVendor::VENDOR_ARM; break;
|
||||
case VULKAN_VENDOR_IMGTEC: caps_.vendor = GPUVendor::VENDOR_IMGTEC; break;
|
||||
|
@ -444,6 +444,8 @@ void PopupMultiChoice::Update() {
|
||||
}
|
||||
|
||||
void PopupMultiChoice::UpdateText() {
|
||||
if (!choices_)
|
||||
return;
|
||||
I18NCategory *category = GetI18NCategory(category_);
|
||||
// Clamp the value to be safe.
|
||||
if (*value_ < minVal_ || *value_ > minVal_ + numChoices_ - 1) {
|
||||
@ -466,6 +468,7 @@ void PopupMultiChoice::ChoiceCallback(int num) {
|
||||
if (restoreFocus_) {
|
||||
SetFocusedView(this);
|
||||
}
|
||||
PostChoiceCallback(num);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,11 +237,13 @@ private:
|
||||
class PopupMultiChoice : public UI::Choice {
|
||||
public:
|
||||
PopupMultiChoice(int *value, const std::string &text, const char **choices, int minVal, int numChoices,
|
||||
const char *category, ScreenManager *screenManager, UI::LayoutParams *layoutParams = 0)
|
||||
const char *category, ScreenManager *screenManager, UI::LayoutParams *layoutParams = nullptr)
|
||||
: UI::Choice(text, "", false, layoutParams), value_(value), choices_(choices), minVal_(minVal), numChoices_(numChoices),
|
||||
category_(category), screenManager_(screenManager) {
|
||||
if (*value >= numChoices+minVal) *value = numChoices+minVal-1;
|
||||
if (*value < minVal) *value = minVal;
|
||||
if (*value >= numChoices + minVal)
|
||||
*value = numChoices + minVal - 1;
|
||||
if (*value < minVal)
|
||||
*value = minVal;
|
||||
OnClick.Handle(this, &PopupMultiChoice::HandleClick);
|
||||
UpdateText();
|
||||
}
|
||||
@ -255,16 +257,19 @@ public:
|
||||
|
||||
UI::Event OnChoice;
|
||||
|
||||
private:
|
||||
void UpdateText();
|
||||
UI::EventReturn HandleClick(UI::EventParams &e);
|
||||
|
||||
void ChoiceCallback(int num);
|
||||
|
||||
protected:
|
||||
int *value_;
|
||||
const char **choices_;
|
||||
int minVal_;
|
||||
int numChoices_;
|
||||
void UpdateText();
|
||||
|
||||
private:
|
||||
UI::EventReturn HandleClick(UI::EventParams &e);
|
||||
|
||||
void ChoiceCallback(int num);
|
||||
virtual void PostChoiceCallback(int num) {}
|
||||
|
||||
const char *category_;
|
||||
ScreenManager *screenManager_;
|
||||
std::string valueText_;
|
||||
@ -272,6 +277,40 @@ private:
|
||||
std::set<int> hidden_;
|
||||
};
|
||||
|
||||
// Allows passing in a dynamic vector of strings. Saves the string.
|
||||
class PopupMultiChoiceDynamic : public PopupMultiChoice {
|
||||
public:
|
||||
PopupMultiChoiceDynamic(std::string *value, const std::string &text, std::vector<std::string> choices,
|
||||
const char *category, ScreenManager *screenManager, UI::LayoutParams *layoutParams = nullptr)
|
||||
: UI::PopupMultiChoice(&valueInt_, text, nullptr, 0, (int)choices.size(), category, screenManager, layoutParams),
|
||||
valueStr_(value) {
|
||||
choices_ = new const char *[numChoices_];
|
||||
valueInt_ = 0;
|
||||
for (int i = 0; i < numChoices_; i++) {
|
||||
choices_[i] = new char[choices[i].size() + 1];
|
||||
memcpy((char *)choices_[i], choices[i].c_str(), choices[i].size() + 1);
|
||||
if (*value == choices_[i])
|
||||
valueInt_ = i;
|
||||
}
|
||||
value_ = &valueInt_;
|
||||
UpdateText();
|
||||
}
|
||||
~PopupMultiChoiceDynamic() {
|
||||
for (int i = 0; i < numChoices_; i++) {
|
||||
delete[] choices_[i];
|
||||
}
|
||||
delete[] choices_;
|
||||
}
|
||||
|
||||
protected:
|
||||
void PostChoiceCallback(int num) {
|
||||
*valueStr_ = choices_[num];
|
||||
}
|
||||
|
||||
private:
|
||||
int valueInt_;
|
||||
std::string *valueStr_;
|
||||
};
|
||||
|
||||
class PopupSliderChoice : public Choice {
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user