diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index 7e2408e091..c59e9c4cc3 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -937,6 +937,7 @@ void ConvertBlendState(GenericBlendState &blendState, bool allowShaderBlend) { blendState.applyShaderBlending = false; blendState.dirtyShaderBlend = false; blendState.useBlendColor = false; + blendState.replaceAlphaWithStencil = REPLACE_ALPHA_NO; ReplaceBlendType replaceBlend = ReplaceBlendWithShader(allowShaderBlend, gstate.FrameBufFormat()); ReplaceAlphaType replaceAlphaWithStencil = ReplaceAlphaWithStencil(replaceBlend); diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index 1a541e1681..00a05dc4a0 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -96,16 +96,14 @@ static bool IsReallyAClear(const TransformedVertex *transformed, int numVerts) { if (transformed[0].x != 0.0f || transformed[0].y != 0.0f) return false; - u32 matchcolor = transformed[0].color0_32; - float matchz = transformed[0].z; + // Color and Z are decided by the second vertex, so only need to check those for matching color. + u32 matchcolor = transformed[1].color0_32; + float matchz = transformed[1].z; int bufW = gstate_c.curRTWidth; int bufH = gstate_c.curRTHeight; for (int i = 1; i < numVerts; i++) { - if (transformed[i].color0_32 != matchcolor || transformed[i].z != matchz) - return false; - if ((i & 1) == 0) { // Top left of a rectangle if (transformed[i].y != 0) @@ -113,6 +111,8 @@ static bool IsReallyAClear(const TransformedVertex *transformed, int numVerts) { if (i > 0 && transformed[i].x != transformed[i - 1].x) return false; } else { + if ((i & 1) && transformed[i].color0_32 != matchcolor || transformed[i].z != matchz) + return false; // Bottom right if (transformed[i].y != bufH) return false; @@ -406,9 +406,9 @@ void SoftwareTransform( // Experiment: Disable on PowerVR (see issue #6290) // TODO: This bleeds outside the play area in non-buffered mode. Big deal? Probably not. if (maxIndex > 1 && gstate.isModeClear() && prim == GE_PRIM_RECTANGLES && IsReallyAClear(transformed, maxIndex) && gl_extensions.gpuVendor != GPU_VENDOR_POWERVR) { // && g_Config.iRenderingMode != FB_NON_BUFFERED_MODE) { - result->color = transformed[0].color0_32; + result->color = transformed[1].color0_32; // Need to rescale from a [0, 1] float. This is the final transformed value. - result->depth = ToScaledDepth((s16)(int)(transformed[0].z * 65535.0f)); + result->depth = ToScaledDepth((s16)(int)(transformed[1].z * 65535.0f)); result->action = SW_CLEAR; return; } @@ -552,7 +552,7 @@ void SoftwareTransform( result->setStencil = true; if (vertexCount > 1) { // Take the bottom right alpha value of the first rect as the stencil value. - // Technically, each rect should individually fill its stencil, but most of the + // Technically, each rect could individually fill its stencil, but most of the // time they use the same one. result->stencilValue = transformed[indsIn[1]].color0[3]; } else { diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index a4a9320a32..5ab4079e1a 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -75,7 +75,7 @@ int TextureCacheCommon::AttachedDrawingHeight() { void TextureCacheCommon::GetSamplingParams(int &minFilt, int &magFilt, bool &sClamp, bool &tClamp, float &lodBias, u8 maxLevel) { minFilt = gstate.texfilter & 0x7; - magFilt = (gstate.texfilter>>8) & 1; + magFilt = (gstate.texfilter >> 8) & 1; sClamp = gstate.isTexCoordClampedS(); tClamp = gstate.isTexCoordClampedT(); diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index caae0c6ecc..95ff12aa60 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -17,8 +17,12 @@ #pragma once +#include +#include + #include "Common/CommonTypes.h" #include "GPU/Common/GPUDebugInterface.h" +#include "Common/MemoryUtil.h" enum TextureFiltering { TEX_FILTER_AUTO = 1, diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index 8b7bd4db32..69dbe4da53 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -75,7 +75,6 @@ struct DecVtxFormat { short stride; }; -// This struct too. struct TransformedVertex { union { diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index 40831cba10..0d470ef4cf 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -404,12 +404,12 @@ void ShaderManagerDX9::VSUpdateUniforms(int dirtyUniforms) { } if (allDirty) { // Set them all with one call - glUniformMatrix4fv(u_bone, numBones, GL_FALSE, allBones); + //glUniformMatrix4fv(u_bone, numBones, GL_FALSE, allBones); } else { // Set them one by one. Could try to coalesce two in a row etc but too lazy. for (int i = 0; i < numBones; i++) { if (dirtyUniforms & (DIRTY_BONEMATRIX0 << i)) { - glUniformMatrix4fv(u_bone + i, 1, GL_FALSE, allBones + 16 * i); + //glUniformMatrix4fv(u_bone + i, 1, GL_FALSE, allBones + 16 * i); } } } diff --git a/GPU/GLES/StateMapping.cpp b/GPU/GLES/StateMapping.cpp index 1d3c5adc0a..e693bd3768 100644 --- a/GPU/GLES/StateMapping.cpp +++ b/GPU/GLES/StateMapping.cpp @@ -77,7 +77,7 @@ static const GLushort cullingMode[] = { GL_BACK, }; -static const GLushort ztests[] = { +static const GLushort compareOps[] = { GL_NEVER, GL_ALWAYS, GL_EQUAL, GL_NOTEQUAL, GL_LESS, GL_LEQUAL, GL_GREATER, GL_GEQUAL, }; @@ -289,7 +289,7 @@ void TransformDrawEngine::ApplyDrawState(int prim) { // Depth Test if (gstate.isDepthTestEnabled()) { glstate.depthTest.enable(); - glstate.depthFunc.set(ztests[gstate.getDepthTestFunction()]); + glstate.depthFunc.set(compareOps[gstate.getDepthTestFunction()]); glstate.depthWrite.set(gstate.isDepthWriteEnabled() || alwaysDepthWrite ? GL_TRUE : GL_FALSE); if (gstate.isDepthWriteEnabled() || alwaysDepthWrite) { framebufferManager_->SetDepthUpdated(); @@ -337,7 +337,7 @@ void TransformDrawEngine::ApplyDrawState(int prim) { // Stencil Test if (stencilState.enabled) { glstate.stencilTest.enable(); - glstate.stencilFunc.set(ztests[stencilState.testFunc], stencilState.testRef, stencilState.testMask); + glstate.stencilFunc.set(compareOps[stencilState.testFunc], stencilState.testRef, stencilState.testMask); glstate.stencilOp.set(stencilOps[stencilState.sFail], stencilOps[stencilState.zFail], stencilOps[stencilState.zPass]); glstate.stencilMask.set(stencilState.writeMask); } else { diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index 6325ba7e79..38afafa231 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -429,41 +429,42 @@ void SystemInfoScreen::CreateViews() { oglExtensions->SetSpacing(0); oglExtensionsScroll->Add(oglExtensions); - tabHolder->AddTab("OGL Extensions", oglExtensionsScroll); - - if (!gl_extensions.IsGLES) { - oglExtensions->Add(new ItemHeader("OpenGL Extensions")); - } else if (gl_extensions.GLES3) { - oglExtensions->Add(new ItemHeader("OpenGL ES 3.0 Extensions")); - } else { - oglExtensions->Add(new ItemHeader("OpenGL ES 2.0 Extensions")); - } - - exts.clear(); - SplitString(g_all_gl_extensions, ' ', exts); - std::sort(exts.begin(), exts.end()); - for (size_t i = 0; i < exts.size(); i++) { - oglExtensions->Add(new TextView(exts[i]))->SetFocusable(true); - } - - exts.clear(); - SplitString(g_all_egl_extensions, ' ', exts); - std::sort(exts.begin(), exts.end()); - - // If there aren't any EGL extensions, no need to show the tab. - if (exts.size() > 0) { - ViewGroup *eglExtensionsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); - eglExtensionsScroll->SetTag("DevSystemInfoEGLExt"); - LinearLayout *eglExtensions = new LinearLayout(ORIENT_VERTICAL); - eglExtensions->SetSpacing(0); - eglExtensionsScroll->Add(eglExtensions); - - tabHolder->AddTab("EGL Extensions", eglExtensionsScroll); - - eglExtensions->Add(new ItemHeader("EGL Extensions")); + if (g_Config.iGPUBackend == GPU_BACKEND_OPENGL) { + tabHolder->AddTab("OGL Extensions", oglExtensionsScroll); + if (!gl_extensions.IsGLES) { + oglExtensions->Add(new ItemHeader("OpenGL Extensions")); + } else if (gl_extensions.GLES3) { + oglExtensions->Add(new ItemHeader("OpenGL ES 3.0 Extensions")); + } else { + oglExtensions->Add(new ItemHeader("OpenGL ES 2.0 Extensions")); + } + exts.clear(); + SplitString(g_all_gl_extensions, ' ', exts); + std::sort(exts.begin(), exts.end()); for (size_t i = 0; i < exts.size(); i++) { - eglExtensions->Add(new TextView(exts[i]))->SetFocusable(true); + oglExtensions->Add(new TextView(exts[i]))->SetFocusable(true); + } + + exts.clear(); + SplitString(g_all_egl_extensions, ' ', exts); + std::sort(exts.begin(), exts.end()); + + // If there aren't any EGL extensions, no need to show the tab. + if (exts.size() > 0) { + ViewGroup *eglExtensionsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT)); + eglExtensionsScroll->SetTag("DevSystemInfoEGLExt"); + LinearLayout *eglExtensions = new LinearLayout(ORIENT_VERTICAL); + eglExtensions->SetSpacing(0); + eglExtensionsScroll->Add(eglExtensions); + + tabHolder->AddTab("EGL Extensions", eglExtensionsScroll); + + eglExtensions->Add(new ItemHeader("EGL Extensions")); + + for (size_t i = 0; i < exts.size(); i++) { + eglExtensions->Add(new TextView(exts[i]))->SetFocusable(true); + } } } } diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index f9e616263e..a30c55036f 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -450,7 +450,7 @@ void LogoScreen::render() { } #ifdef _WIN32 - dc.DrawText(screenManager()->getThin3DContext()->GetInfoString(T3DInfo::APINAME), bounds.centerX(), bounds.y2() - 100, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER); + dc.DrawText(screenManager()->getThin3DContext()->GetInfoString(T3DInfo::APINAME).c_str(), bounds.centerX(), bounds.y2() - 100, colorAlpha(0xFFFFFFFF, alphaText), ALIGN_CENTER); #endif dc.End(); diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index ed8c845d23..521e90cba4 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -356,7 +356,6 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch logger = new AndroidLogger(); LogManager::Init(); - LogManager *logman = LogManager::GetInstance(); g_Config.AddSearchPath(user_data_path); g_Config.AddSearchPath(g_Config.memStickDirectory + "PSP/SYSTEM/"); @@ -364,6 +363,7 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch g_Config.Load(); g_Config.externalDirectory = external_dir; #endif + LogManager *logman = LogManager::GetInstance(); #ifdef ANDROID // On Android, create a PSP directory tree in the external_dir, @@ -453,10 +453,12 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch logman->AddListener(type, logger); #endif } - // Special hack for G3D as it's very spammy. Need to make a flag for this. - if (!gfxLog) - logman->SetLogLevel(LogTypes::G3D, LogTypes::LERROR); #endif + // Special hack for G3D as it's very spammy. Need to make a flag for this. + if (!gfxLog) { + logman->SetLogLevel(LogTypes::G3D, LogTypes::LERROR); + logman->SetLogLevel(LogTypes::SCEGE, LogTypes::LERROR); + } // Allow the lang directory to be overridden for testing purposes (e.g. Android, where it's hard to // test new languages without recompiling the entire app, which is a hassle). const std::string langOverridePath = g_Config.memStickDirectory + "PSP/SYSTEM/lang/"; diff --git a/Windows/GPU/D3D9Context.h b/Windows/GPU/D3D9Context.h index 11d334ca92..e80d04b97c 100644 --- a/Windows/GPU/D3D9Context.h +++ b/Windows/GPU/D3D9Context.h @@ -1,3 +1,20 @@ +// Copyright (c) 2015- 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/. + // Modelled on OpenD3DBase. Might make a cleaner interface later. #pragma once diff --git a/ext/native/gfx_es2/draw_text.cpp b/ext/native/gfx_es2/draw_text.cpp index a4ebb22bfe..03de087229 100644 --- a/ext/native/gfx_es2/draw_text.cpp +++ b/ext/native/gfx_es2/draw_text.cpp @@ -186,7 +186,7 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float for (int y = 0; y < entry->bmHeight; y++) { for (int x = 0; x < entry->bmWidth; x++) { BYTE bAlpha = (BYTE)((ctx_->pBitmapBits[MAX_TEXT_WIDTH * y + x] & 0xff) >> 4); - bitmapData[entry->bmWidth * y + x] = (bAlpha) | 0xfff0; // ^ rand(); + bitmapData[entry->bmWidth * y + x] = (bAlpha) | 0xfff0; } } entry->texture->SetImageData(0, 0, 0, entry->bmWidth, entry->bmHeight, 1, 0, entry->bmWidth * 2, (const uint8_t *)bitmapData); diff --git a/ext/native/math/dataconv.h b/ext/native/math/dataconv.h new file mode 100644 index 0000000000..046bb63f35 --- /dev/null +++ b/ext/native/math/dataconv.h @@ -0,0 +1,88 @@ +#pragma once + +#include +#include + +// Utilities useful for filling in std140-layout uniform buffers. + + +// LSBs in f[0], etc. +// Could be SSE optimized. +inline void Uint8x4ToFloat4(float f[4], uint32_t u) { + f[0] = ((u >> 0) & 0xFF) * (1.0f / 255.0f); + f[1] = ((u >> 8) & 0xFF) * (1.0f / 255.0f); + f[2] = ((u >> 16) & 0xFF) * (1.0f / 255.0f); + f[3] = ((u >> 24) & 0xFF) * (1.0f / 255.0f); +} + +inline void Uint8x3ToFloat4(float f[4], uint32_t u) { + f[0] = ((u >> 0) & 0xFF) * (1.0f / 255.0f); + f[1] = ((u >> 8) & 0xFF) * (1.0f / 255.0f); + f[2] = ((u >> 16) & 0xFF) * (1.0f / 255.0f); + f[3] = 0.0f; +} + +inline void Uint8x3ToInt4(int i[4], uint32_t u) { + i[0] = ((u >> 0) & 0xFF); + i[1] = ((u >> 8) & 0xFF); + i[2] = ((u >> 16) & 0xFF); + i[3] = 0; +} + +inline void Uint8x3ToFloat4_Alpha(float f[4], uint32_t u, float alpha) { + f[0] = ((u >> 0) & 0xFF) * (1.0f / 255.0f); + f[1] = ((u >> 8) & 0xFF) * (1.0f / 255.0f); + f[2] = ((u >> 16) & 0xFF) * (1.0f / 255.0f); + f[3] = alpha; +} + +inline void Uint8x3ToFloat4_AlphaUint8(float f[4], uint32_t u, uint8_t alpha) { + f[0] = ((u >> 0) & 0xFF) * (1.0f / 255.0f); + f[1] = ((u >> 8) & 0xFF) * (1.0f / 255.0f); + f[2] = ((u >> 16) & 0xFF) * (1.0f / 255.0f); + f[3] = alpha * (1.0f / 255.0f); +} + +inline void Uint8x1ToFloat4(float f[4], uint32_t u) { + f[0] = ((u >> 0) & 0xFF) * (1.0f / 255.0f); + f[1] = 0.0f; + f[2] = 0.0f; + f[3] = 0.0f; +} + +// These are just for readability. + +inline void CopyFloat2(float dest[2], const float src[2]) { + memcpy(dest, src, sizeof(float) * 2); +} + +inline void CopyFloat1To4(float dest[4], const float src) { + dest[0] = src; + dest[1] = 0.0f; + dest[2] = 0.0f; + dest[3] = 0.0f; +} + +inline void CopyFloat2To4(float dest[4], const float src[2]) { + memcpy(dest, src, sizeof(float) * 2); + dest[2] = 0.0f; + dest[3] = 0.0f; +} + +inline void CopyFloat3To4(float dest[4], const float src[3]) { + memcpy(dest, src, sizeof(float) * 3); + dest[3] = 0.0f; +} + +inline void CopyFloat4(float dest[4], const float src[4]) { + memcpy(dest, src, sizeof(float) * 4); +} + +inline void CopyMatrix4x4(float dest[16], const float src[16]) { + memcpy(dest, src, sizeof(float) * 16); +} + +inline void ExpandFloat24x3ToFloat4(float dest[4], uint32_t src[3]) { + uint32_t temp[4] = { src[0] << 8, src[1] << 8, src[2] << 8, 0 }; + memcpy(dest, temp, sizeof(float) * 4); +} \ No newline at end of file diff --git a/ext/native/native.vcxproj b/ext/native/native.vcxproj index d4527121a9..93d7860e03 100644 --- a/ext/native/native.vcxproj +++ b/ext/native/native.vcxproj @@ -247,6 +247,7 @@ + diff --git a/ext/native/native.vcxproj.filters b/ext/native/native.vcxproj.filters index 87ee09ad91..acbf041728 100644 --- a/ext/native/native.vcxproj.filters +++ b/ext/native/native.vcxproj.filters @@ -305,6 +305,9 @@ file + + math + @@ -765,9 +768,6 @@ {49afd06e-eb44-41ac-b038-e109e444a834} - - {a52d761c-4c72-4261-be17-50d071bd5cc8} - {95e41110-57a2-497f-a938-b4c8e9dd6a27} diff --git a/ext/native/thin3d/thin3d.h b/ext/native/thin3d/thin3d.h index 38d1bea866..4a73aa75b7 100644 --- a/ext/native/thin3d/thin3d.h +++ b/ext/native/thin3d/thin3d.h @@ -282,6 +282,8 @@ class Thin3DContext : public Thin3DObject { public: virtual ~Thin3DContext(); + virtual std::vector GetFeatureList() { return std::vector(); } + virtual Thin3DDepthStencilState *CreateDepthStencilState(bool depthTestEnabled, bool depthWriteEnabled, T3DComparison depthCompare) = 0; virtual Thin3DBlendState *CreateBlendState(const T3DBlendStateDesc &desc) = 0; virtual Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) = 0; @@ -334,7 +336,7 @@ public: targetHeight_ = h; } - virtual const char *GetInfoString(T3DInfo info) const = 0; + virtual std::string GetInfoString(T3DInfo info) const = 0; protected: void CreatePresets(); diff --git a/ext/native/thin3d/thin3d_d3d9.cpp b/ext/native/thin3d/thin3d_d3d9.cpp index 44f5ab3015..78bd121999 100644 --- a/ext/native/thin3d/thin3d_d3d9.cpp +++ b/ext/native/thin3d/thin3d_d3d9.cpp @@ -429,7 +429,7 @@ public: void DrawUP(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, const void *vdata, int vertexCount) override; void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal); - const char *GetInfoString(T3DInfo info) const override { + std::string GetInfoString(T3DInfo info) const override { switch (info) { case APIVERSION: return "DirectX 9.0"; case VENDORSTRING: return identifier_.Description; diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 62101d27be..04330a2c96 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -5,6 +5,7 @@ #include "base/logging.h" #include "image/zim_load.h" +#include "math/dataconv.h" #include "math/lin/matrix4x4.h" #include "thin3d/thin3d.h" #include "gfx/gl_common.h" @@ -74,13 +75,6 @@ static const char *glsl_fragment_prelude = "precision mediump float;\n" "#endif\n"; -static inline void Uint32ToFloat4(uint32_t u, float f[4]) { - f[0] = ((u >> 0) & 0xFF) * (1.0f / 255.0f); - f[1] = ((u >> 8) & 0xFF) * (1.0f / 255.0f); - f[2] = ((u >> 16) & 0xFF) * (1.0f / 255.0f); - f[3] = ((u >> 24) & 0xFF) * (1.0f / 255.0f); -} - class Thin3DGLBlendState : public Thin3DBlendState { public: bool enabled; @@ -361,7 +355,7 @@ public: void DrawUP(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3DVertexFormat *format, const void *vdata, int vertexCount) override; void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override; - const char *GetInfoString(T3DInfo info) const override { + std::string GetInfoString(T3DInfo info) const override { // TODO: Make these actually query the right information switch (info) { case APINAME: @@ -810,7 +804,7 @@ void Thin3DGLContext::DrawUP(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin void Thin3DGLContext::Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) { float col[4]; - Uint32ToFloat4(colorval, col); + Uint8x4ToFloat4(col, colorval); GLuint glMask = 0; if (mask & T3DClear::COLOR) { glClearColor(col[0], col[1], col[2], col[3]); diff --git a/ext/native/ui/ui_screen.cpp b/ext/native/ui/ui_screen.cpp index ef0e0bbce8..172b357273 100644 --- a/ext/native/ui/ui_screen.cpp +++ b/ext/native/ui/ui_screen.cpp @@ -288,7 +288,7 @@ UI::EventReturn PopupScreen::OnCancel(UI::EventParams &e) { void ListPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { using namespace UI; - listView_ = parent->Add(new ListView(&adaptor_)); //, new LinearLayoutParams(1.0))); + listView_ = parent->Add(new ListView(&adaptor_, hidden_)); //, new LinearLayoutParams(1.0))); listView_->SetMaxHeight(screenManager()->getUIContext()->GetBounds().h - 140); listView_->OnChoice.Handle(this, &ListPopupScreen::OnListChoice); } @@ -315,8 +315,9 @@ UI::EventReturn PopupMultiChoice::HandleClick(UI::EventParams &e) { choices.push_back(category ? category->T(choices_[i]) : choices_[i]); } - Screen *popupScreen = new ListPopupScreen(text_, choices, *value_ - minVal_, + ListPopupScreen *popupScreen = new ListPopupScreen(text_, choices, *value_ - minVal_, std::bind(&PopupMultiChoice::ChoiceCallback, this, placeholder::_1)); + popupScreen->SetHiddenChoices(hidden_); screenManager_->push(popupScreen); return UI::EVENT_DONE; } diff --git a/ext/native/ui/ui_screen.h b/ext/native/ui/ui_screen.h index 6ac9730176..63397e854e 100644 --- a/ext/native/ui/ui_screen.h +++ b/ext/native/ui/ui_screen.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "ui/screen.h" #include "ui/viewgroup.h" @@ -93,9 +95,13 @@ public: std::string GetChoiceString() const { return adaptor_.GetTitle(listView_->GetSelected()); } - UI::Event OnChoice; + void SetHiddenChoices(std::set hidden) { + hidden_ = hidden; + } virtual std::string tag() const override { return std::string("listpopup"); } + UI::Event OnChoice; + protected: virtual bool FillVertical() const override { return false; } virtual bool ShowButtons() const override { return showButtons_; } @@ -108,6 +114,7 @@ private: std::function callback_; bool showButtons_; + std::set hidden_; }; class MessagePopupScreen : public PopupScreen { @@ -215,6 +222,10 @@ public: virtual void Draw(UIContext &dc) override; virtual void Update(const InputState &input_state) override; + void HideChoice(int c) { + hidden_.insert(c); + } + UI::Event OnChoice; private: @@ -231,6 +242,7 @@ private: ScreenManager *screenManager_; std::string valueText_; bool restoreFocus_; + std::set hidden_; }; diff --git a/ext/native/ui/viewgroup.cpp b/ext/native/ui/viewgroup.cpp index 2254757653..9a5fbc2af8 100644 --- a/ext/native/ui/viewgroup.cpp +++ b/ext/native/ui/viewgroup.cpp @@ -1258,9 +1258,8 @@ StickyChoice *ChoiceStrip::Choice(int index) { return static_cast(views_[index]); return nullptr; } - -ListView::ListView(ListAdaptor *a, LayoutParams *layoutParams) - : ScrollView(ORIENT_VERTICAL, layoutParams), adaptor_(a), maxHeight_(0) { +ListView::ListView(ListAdaptor *a, std::set hidden, LayoutParams *layoutParams) + : ScrollView(ORIENT_VERTICAL, layoutParams), adaptor_(a), maxHeight_(0), hidden_(hidden) { linLayout_ = new LinearLayout(ORIENT_VERTICAL); linLayout_->SetSpacing(0.0f); @@ -1272,8 +1271,10 @@ void ListView::CreateAllItems() { linLayout_->Clear(); // Let's not be clever yet, we'll just create them all up front and add them all in. for (int i = 0; i < adaptor_->GetNumItems(); i++) { - View * v = linLayout_->Add(adaptor_->CreateItemView(i)); - adaptor_->AddEventCallback(v, std::bind(&ListView::OnItemCallback, this, i, placeholder::_1)); + if (hidden_.find(i) == hidden_.end()) { + View * v = linLayout_->Add(adaptor_->CreateItemView(i)); + adaptor_->AddEventCallback(v, std::bind(&ListView::OnItemCallback, this, i, placeholder::_1)); + } } } diff --git a/ext/native/ui/viewgroup.h b/ext/native/ui/viewgroup.h index c1d150cda5..98f7868730 100644 --- a/ext/native/ui/viewgroup.h +++ b/ext/native/ui/viewgroup.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include "base/logging.h" #include "base/mutex.h" @@ -389,7 +390,7 @@ private: // In the future, it might be smart and load/unload items as they go, but currently not. class ListView : public ScrollView { public: - ListView(ListAdaptor *a, LayoutParams *layoutParams = 0); + ListView(ListAdaptor *a, std::set hidden = std::set(), LayoutParams *layoutParams = 0); int GetSelected() { return adaptor_->GetSelected(); } virtual void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert) override; @@ -403,6 +404,7 @@ private: ListAdaptor *adaptor_; LinearLayout *linLayout_; float maxHeight_; + std::set hidden_; }; void LayoutViewHierarchy(const UIContext &dc, ViewGroup *root);