diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index b157b4a63..d50d02070 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -55,11 +55,11 @@ body: validations: required: false - type: input - id: other + id: os_detail attributes: - label: If Other OS, please describe + label: Please describe your specific OS version description: Other details - placeholder: "Windows, Mac OSX version, Debian, Ubuntu, Arch, etc." + placeholder: "Windows 11 Home/Pro/Server/etc, Mac OSX version, Debian 10/11/etc, Ubuntu 18/20/etc, Arch, etc." validations: required: false - type: input diff --git a/bin/windows/vpx/lib/arm64/libvpx.lib b/bin/windows/vpx/lib/arm64/libvpx.lib new file mode 100644 index 000000000..17f7a3294 Binary files /dev/null and b/bin/windows/vpx/lib/arm64/libvpx.lib differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 527ec220d..baddb7067 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -403,7 +403,10 @@ if( MSVC AND NOT VPX_FOUND ) # Use prebuilt library set( VPX_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../bin/Windows/vpx" ) set( VPX_INCLUDE_DIR ${VPX_ROOT_PATH}/include ) - set( VPX_LIBRARIES libvpx libcompat-to-msvc ) + set( VPX_LIBRARIES libvpx ) + if ( NOT ARM64 ) + set (VPX_LIBRARIES ${VPX_LIBRARIES} libcompat-to-msvc ) + endif() if( ARM64 ) link_directories( ${VPX_ROOT_PATH}/lib/arm64 ) elseif( X64 ) diff --git a/src/common/filesystem/file_zip.cpp b/src/common/filesystem/file_zip.cpp index c8977629b..bd0d76624 100644 --- a/src/common/filesystem/file_zip.cpp +++ b/src/common/filesystem/file_zip.cpp @@ -222,7 +222,7 @@ bool FZipFile::Open(bool quiet, LumpFilterInfo* filter) return false; } - NumLumps = info.NumEntries; + NumLumps = (uint32_t)info.NumEntries; dirsize = info.DirectorySize; DirectoryOffset = info.DirectoryOffset; } @@ -521,7 +521,7 @@ int FZipLump::GetFileOffset() { if (Method != METHOD_STORED) return -1; if (NeedFileStart) SetLumpAddress(); - return Position; + return (int)Position; } //========================================================================== diff --git a/src/common/objects/dobjgc.cpp b/src/common/objects/dobjgc.cpp index e407d3d77..8664ac541 100644 --- a/src/common/objects/dobjgc.cpp +++ b/src/common/objects/dobjgc.cpp @@ -277,7 +277,7 @@ void MarkArray(DObject **obj, size_t count) static size_t CalcStepSize() { - int time_passed = CheckTime - LastCollectTime; + int time_passed = int(CheckTime - LastCollectTime); auto alloc = min(LastCollectAlloc, Estimate); size_t bytes_gained = AllocBytes > alloc ? AllocBytes - alloc : 0; return (StepMul > 0 && time_passed > 0) @@ -390,7 +390,7 @@ static size_t SingleStep() case GCS_Finalize: State = GCS_Pause; // end collection LastCollectAlloc = AllocBytes; - LastCollectTime = CheckTime; + LastCollectTime = (int)CheckTime; return 0; default: diff --git a/src/common/rendering/gl/gl_framebuffer.cpp b/src/common/rendering/gl/gl_framebuffer.cpp index 5be590cbc..e4d9f09ad 100644 --- a/src/common/rendering/gl/gl_framebuffer.cpp +++ b/src/common/rendering/gl/gl_framebuffer.cpp @@ -561,6 +561,11 @@ void OpenGLFrameBuffer::PostProcessScene(bool swscene, int fixedcm, float flash, GLRenderer->PostProcessScene(fixedcm, flash, afterBloomDrawEndScene2D); } +bool OpenGLFrameBuffer::CompileNextShader() +{ + return GLRenderer->mShaderManager->CompileNextShader(); +} + //========================================================================== // // OpenGLFrameBuffer :: WipeStartScreen diff --git a/src/common/rendering/gl/gl_framebuffer.h b/src/common/rendering/gl/gl_framebuffer.h index 1455ead3e..84242d792 100644 --- a/src/common/rendering/gl/gl_framebuffer.h +++ b/src/common/rendering/gl/gl_framebuffer.h @@ -23,7 +23,7 @@ public: explicit OpenGLFrameBuffer() {} OpenGLFrameBuffer(void *hMonitor, bool fullscreen) ; ~OpenGLFrameBuffer(); - + bool CompileNextShader() override; void InitializeState() override; void Update() override; diff --git a/src/common/rendering/gl/gl_shader.cpp b/src/common/rendering/gl/gl_shader.cpp index 88596b367..80e6a0e8a 100644 --- a/src/common/rendering/gl/gl_shader.cpp +++ b/src/common/rendering/gl/gl_shader.cpp @@ -672,7 +672,7 @@ bool FShader::Bind() FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderPath, const char *LightModePath, const char *shaderdefines, bool usediscard, EPassType passType) { FString defines; - defines += shaderdefines; + if (shaderdefines) defines += shaderdefines; // this can't be in the shader code due to ATI strangeness. if (!usediscard) defines += "#define NO_ALPHATEST\n"; if (passType == GBUFFER_PASS) defines += "#define GBUFFER_PASS\n"; @@ -707,6 +707,20 @@ FShaderManager::FShaderManager() mPassShaders.Push(new FShaderCollection((EPassType)passType)); } +bool FShaderManager::CompileNextShader() +{ + if (mPassShaders[mCompilePass]->CompileNextShader()) + { + mCompilePass++; + if (mCompilePass >= MAX_PASS_TYPES) + { + mCompilePass = -1; + return true; + } + } + return false; +} + FShaderManager::~FShaderManager() { glUseProgram(0); @@ -727,7 +741,7 @@ void FShaderManager::SetActiveShader(FShader *sh) FShader *FShaderManager::BindEffect(int effect, EPassType passType) { - if (passType < mPassShaders.Size()) + if (passType < mPassShaders.Size() && mCompilePass == -1) return mPassShaders[passType]->BindEffect(effect); else return nullptr; @@ -735,7 +749,11 @@ FShader *FShaderManager::BindEffect(int effect, EPassType passType) FShader *FShaderManager::Get(unsigned int eff, bool alphateston, EPassType passType) { - if (r_skipmats && eff >= 3 && eff <= 4) + if (mCompilePass > -1) + { + return mPassShaders[0]->Get(0, false); + } + if ((r_skipmats && eff >= 3 && eff <= 4)) eff = 0; if (passType < mPassShaders.Size()) @@ -752,7 +770,14 @@ FShader *FShaderManager::Get(unsigned int eff, bool alphateston, EPassType passT FShaderCollection::FShaderCollection(EPassType passType) { - CompileShaders(passType); + mPassType = passType; + mMaterialShaders.Clear(); + mMaterialShadersNAT.Clear(); + for (int i = 0; i < MAX_EFFECTS; i++) + { + mEffectShaders[i] = NULL; + } + CompileNextShader(); } //========================================================================== @@ -772,35 +797,47 @@ FShaderCollection::~FShaderCollection() // //========================================================================== -void FShaderCollection::CompileShaders(EPassType passType) +bool FShaderCollection::CompileNextShader() { - mMaterialShaders.Clear(); - mMaterialShadersNAT.Clear(); - for (int i = 0; i < MAX_EFFECTS; i++) + int i = mCompileIndex; + if (mCompileState == 0) { - mEffectShaders[i] = NULL; - } - - for(int i=0;defaultshaders[i].ShaderName != NULL;i++) - { - FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, passType); + FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, mPassType); mMaterialShaders.Push(shc); - if (i < SHADER_NoTexture) + mCompileIndex++; + if (defaultshaders[mCompileIndex].ShaderName == nullptr) { - FShader *shc1 = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, passType); - mMaterialShadersNAT.Push(shc1); + mCompileIndex = 0; + mCompileState++; + } } - - for(unsigned i = 0; i < usershaders.Size(); i++) + else if (mCompileState == 1) + { + FShader *shc1 = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, mPassType); + mMaterialShadersNAT.Push(shc1); + mCompileIndex++; + if (mCompileIndex >= SHADER_NoTexture) + { + mCompileIndex = 0; + mCompileState++; + if (usershaders.Size() == 0) mCompileState++; + } + } + else if (mCompileState == 2) { FString name = ExtractFileBase(usershaders[i].shader); FString defines = defaultshaders[usershaders[i].shaderType].Defines + usershaders[i].defines; - FShader *shc = Compile(name, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, passType); + FShader *shc = Compile(name, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, mPassType); mMaterialShaders.Push(shc); + mCompileIndex++; + if (mCompileIndex >= (int)usershaders.Size()) + { + mCompileIndex = 0; + mCompileState++; + } } - - for(int i=0;iLoad(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].fp1, @@ -809,7 +846,13 @@ void FShaderCollection::CompileShaders(EPassType passType) delete eff; } else mEffectShaders[i] = eff; + mCompileIndex++; + if (mCompileIndex >= MAX_EFFECTS) + { + return true; + } } + return false; } //========================================================================== diff --git a/src/common/rendering/gl/gl_shader.h b/src/common/rendering/gl/gl_shader.h index ec2289833..33381b6dc 100644 --- a/src/common/rendering/gl/gl_shader.h +++ b/src/common/rendering/gl/gl_shader.h @@ -309,10 +309,12 @@ public: FShader *Get(unsigned int eff, bool alphateston, EPassType passType); void SetActiveShader(FShader *sh); + bool CompileNextShader(); private: FShader *mActiveShader = nullptr; TArray mPassShaders; + int mCompilePass = 0; friend class FShader; }; @@ -322,21 +324,23 @@ class FShaderCollection TArray mMaterialShaders; TArray mMaterialShadersNAT; FShader *mEffectShaders[MAX_EFFECTS]; + int mCompileState = 0, mCompileIndex = 0; + EPassType mPassType; void Clean(); - void CompileShaders(EPassType passType); public: FShaderCollection(EPassType passType); ~FShaderCollection(); FShader *Compile(const char *ShaderName, const char *ShaderPath, const char *LightModePath, const char *shaderdefines, bool usediscard, EPassType passType); int Find(const char *mame); + bool CompileNextShader(); FShader *BindEffect(int effect); FShader *Get(unsigned int eff, bool alphateston) { // indices 0-2 match the warping modes, 3 no texture, the following are custom - if (!alphateston && eff <= 2) + if (!alphateston && eff < SHADER_NoTexture) { return mMaterialShadersNAT[eff]; // Non-alphatest shaders are only created for default, warp1+2 and brightmap. The rest won't get used anyway } diff --git a/src/common/rendering/gles/gles_framebuffer.h b/src/common/rendering/gles/gles_framebuffer.h index d550b8f10..9e7d14fdc 100644 --- a/src/common/rendering/gles/gles_framebuffer.h +++ b/src/common/rendering/gles/gles_framebuffer.h @@ -26,6 +26,7 @@ public: void InitializeState() override; void Update() override; + int GetShaderCount() override { return 0; } void FirstEye() override; void NextEye(int eyecount) override; diff --git a/src/common/rendering/gles/gles_shader.cpp b/src/common/rendering/gles/gles_shader.cpp index f67aa375e..daba34f6d 100644 --- a/src/common/rendering/gles/gles_shader.cpp +++ b/src/common/rendering/gles/gles_shader.cpp @@ -733,7 +733,7 @@ bool FShader::Bind(ShaderFlavourData& flavour) //========================================================================== // -// Since all shaders are REQUIRED, any error here needs to be fatal +// // //========================================================================== @@ -744,21 +744,8 @@ FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderP // this can't be in the shader code due to ATI strangeness. if (!usediscard) defines += "#define NO_ALPHATEST\n"; - FShader *shader = NULL; - try - { - shader = new FShader(ShaderName); - if (!shader->Configure(ShaderName, "shaders_gles/glsl/main.vp", "shaders_gles/glsl/main.fp", ShaderPath, LightModePath, defines.GetChars())) - { - I_FatalError("Unable to load shader %s\n", ShaderName); - } - } - catch(CRecoverableError &err) - { - if (shader != NULL) delete shader; - shader = NULL; - I_FatalError("Unable to load shader %s:\n%s\n", ShaderName, err.GetMessage()); - } + FShader *shader = new FShader(ShaderName); + shader->Configure(ShaderName, "shaders_gles/glsl/main.vp", "shaders_gles/glsl/main.fp", ShaderPath, LightModePath, defines.GetChars()); return shader; } diff --git a/src/common/rendering/hwrenderer/data/hw_shaderpatcher.cpp b/src/common/rendering/hwrenderer/data/hw_shaderpatcher.cpp index 2bb1747d3..50fed5a94 100644 --- a/src/common/rendering/hwrenderer/data/hw_shaderpatcher.cpp +++ b/src/common/rendering/hwrenderer/data/hw_shaderpatcher.cpp @@ -34,7 +34,11 @@ */ +#include "cmdlib.h" #include "hw_shaderpatcher.h" +#include "textures.h" +#include "hw_renderstate.h" +#include "v_video.h" static bool IsGlslWhitespace(char c) @@ -296,3 +300,12 @@ const FEffectShader effectshaders[] = { "burn", "shaders/glsl/main.vp", "shaders/glsl/burn.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" }, { "stencil", "shaders/glsl/main.vp", "shaders/glsl/stencil.fp", nullptr, nullptr, "#define SIMPLE\n#define NO_ALPHATEST\n" }, }; + +int DFrameBuffer::GetShaderCount() +{ + int i; + for (i = 0; defaultshaders[i].ShaderName != nullptr; i++); + + return MAX_PASS_TYPES * (countof(defaultshaders) - 1 + usershaders.Size() + MAX_EFFECTS + SHADER_NoTexture); +} + diff --git a/src/common/rendering/hwrenderer/data/hw_shaderpatcher.h b/src/common/rendering/hwrenderer/data/hw_shaderpatcher.h index 7133441a2..4a3a1c39f 100644 --- a/src/common/rendering/hwrenderer/data/hw_shaderpatcher.h +++ b/src/common/rendering/hwrenderer/data/hw_shaderpatcher.h @@ -28,3 +28,4 @@ struct FEffectShader extern const FDefaultShader defaultshaders[]; extern const FEffectShader effectshaders[]; + diff --git a/src/common/rendering/polyrenderer/backend/poly_framebuffer.h b/src/common/rendering/polyrenderer/backend/poly_framebuffer.h index 76eae0ced..9be76481f 100644 --- a/src/common/rendering/polyrenderer/backend/poly_framebuffer.h +++ b/src/common/rendering/polyrenderer/backend/poly_framebuffer.h @@ -26,6 +26,7 @@ public: PolyFrameBuffer(void *hMonitor, bool fullscreen); ~PolyFrameBuffer(); + int GetShaderCount() override { return 0; } void Update() override; diff --git a/src/common/rendering/v_video.h b/src/common/rendering/v_video.h index 4322165bf..30b120eac 100644 --- a/src/common/rendering/v_video.h +++ b/src/common/rendering/v_video.h @@ -158,6 +158,8 @@ public: virtual void InitializeState() = 0; // For stuff that needs 'screen' set. virtual bool IsVulkan() { return false; } virtual bool IsPoly() { return false; } + virtual int GetShaderCount(); + virtual bool CompileNextShader() { return true; } void SetAABBTree(hwrenderer::LevelAABBTree * tree) { mShadowMap.SetAABBTree(tree); diff --git a/src/common/rendering/vulkan/shaders/vk_shader.cpp b/src/common/rendering/vulkan/shaders/vk_shader.cpp index 05042807b..dd8d442e3 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.cpp +++ b/src/common/rendering/vulkan/shaders/vk_shader.cpp @@ -28,51 +28,93 @@ #include "version.h" #include +bool VkShaderManager::CompileNextShader() +{ + const char *mainvp = "shaders/glsl/main.vp"; + const char *mainfp = "shaders/glsl/main.fp"; + int i = compileIndex; + + if (compileState == 0) + { + // regular material shaders + + VkShaderProgram prog; + prog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines); + prog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, compilePass == GBUFFER_PASS); + mMaterialShaders[compilePass].push_back(std::move(prog)); + + compileIndex++; + if (defaultshaders[compileIndex].ShaderName == nullptr) + { + compileIndex = 0; + compileState++; + } + } + else if (compileState == 1) + { + // NAT material shaders + + VkShaderProgram natprog; + natprog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines); + natprog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, compilePass == GBUFFER_PASS); + mMaterialShadersNAT[compilePass].push_back(std::move(natprog)); + + compileIndex++; + if (compileIndex == SHADER_NoTexture) + { + compileIndex = 0; + compileState++; + if (usershaders.Size() == 0) compileState++; + } + } + else if (compileState == 2) + { + // user shaders + + const FString& name = ExtractFileBase(usershaders[i].shader); + FString defines = defaultshaders[usershaders[i].shaderType].Defines + usershaders[i].defines; + + VkShaderProgram prog; + prog.vert = LoadVertShader(name, mainvp, defines); + prog.frag = LoadFragShader(name, mainfp, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, compilePass == GBUFFER_PASS); + mMaterialShaders[compilePass].push_back(std::move(prog)); + + compileIndex++; + if (compileIndex >= (int)usershaders.Size()) + { + compileIndex = 0; + compileState++; + } + } + else if (compileState == 3) + { + // Effect shaders + + VkShaderProgram prog; + prog.vert = LoadVertShader(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].defines); + prog.frag = LoadFragShader(effectshaders[i].ShaderName, effectshaders[i].fp1, effectshaders[i].fp2, effectshaders[i].fp3, effectshaders[i].defines, true, compilePass == GBUFFER_PASS); + mEffectShaders[compilePass].push_back(std::move(prog)); + + compileIndex++; + if (compileIndex >= MAX_EFFECTS) + { + compileIndex = 0; + compilePass++; + if (compilePass == MAX_PASS_TYPES) + { + compileIndex = -1; // we're done. + return true; + } + compileState = 0; + } + } + return false; +} + VkShaderManager::VkShaderManager(VulkanDevice *device) : device(device) { ShInitialize(); - - const char *mainvp = "shaders/glsl/main.vp"; - const char *mainfp = "shaders/glsl/main.fp"; - - for (int j = 0; j < MAX_PASS_TYPES; j++) - { - bool gbufferpass = j; - for (int i = 0; defaultshaders[i].ShaderName != nullptr; i++) - { - VkShaderProgram prog; - prog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines); - prog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, gbufferpass); - mMaterialShaders[j].push_back(std::move(prog)); - - if (i < SHADER_NoTexture) - { - VkShaderProgram natprog; - natprog.vert = LoadVertShader(defaultshaders[i].ShaderName, mainvp, defaultshaders[i].Defines); - natprog.frag = LoadFragShader(defaultshaders[i].ShaderName, mainfp, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, gbufferpass); - mMaterialShadersNAT[j].push_back(std::move(natprog)); - } - } - - for (unsigned i = 0; i < usershaders.Size(); i++) - { - FString name = ExtractFileBase(usershaders[i].shader); - FString defines = defaultshaders[usershaders[i].shaderType].Defines + usershaders[i].defines; - - VkShaderProgram prog; - prog.vert = LoadVertShader(name, mainvp, defines); - prog.frag = LoadFragShader(name, mainfp, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, gbufferpass); - mMaterialShaders[j].push_back(std::move(prog)); - } - - for (int i = 0; i < MAX_EFFECTS; i++) - { - VkShaderProgram prog; - prog.vert = LoadVertShader(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].defines); - prog.frag = LoadFragShader(effectshaders[i].ShaderName, effectshaders[i].fp1, effectshaders[i].fp2, effectshaders[i].fp3, effectshaders[i].defines, true, gbufferpass); - mEffectShaders[j].push_back(std::move(prog)); - } - } + CompileNextShader(); } VkShaderManager::~VkShaderManager() @@ -82,7 +124,7 @@ VkShaderManager::~VkShaderManager() VkShaderProgram *VkShaderManager::GetEffect(int effect, EPassType passType) { - if (effect >= 0 && effect < MAX_EFFECTS && mEffectShaders[passType][effect].frag) + if (compileIndex == -1 && effect >= 0 && effect < MAX_EFFECTS && mEffectShaders[passType][effect].frag) { return &mEffectShaders[passType][effect]; } @@ -91,8 +133,9 @@ VkShaderProgram *VkShaderManager::GetEffect(int effect, EPassType passType) VkShaderProgram *VkShaderManager::Get(unsigned int eff, bool alphateston, EPassType passType) { + if (compileIndex != -1) return &mMaterialShaders[0][0]; // indices 0-2 match the warping modes, 3 no texture, the following are custom - if (!alphateston && eff <= 2) + if (!alphateston && eff < SHADER_NoTexture) { return &mMaterialShadersNAT[passType][eff]; // Non-alphatest shaders are only created for default, warp1+2. The rest won't get used anyway } diff --git a/src/common/rendering/vulkan/shaders/vk_shader.h b/src/common/rendering/vulkan/shaders/vk_shader.h index daa9dc845..0b610ca33 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.h +++ b/src/common/rendering/vulkan/shaders/vk_shader.h @@ -65,6 +65,7 @@ public: VkShaderProgram *GetEffect(int effect, EPassType passType); VkShaderProgram *Get(unsigned int eff, bool alphateston, EPassType passType); + bool CompileNextShader(); private: std::unique_ptr LoadVertShader(FString shadername, const char *vert_lump, const char *defines); @@ -79,4 +80,6 @@ private: std::vector mMaterialShaders[MAX_PASS_TYPES]; std::vector mMaterialShadersNAT[MAX_PASS_TYPES]; std::vector mEffectShaders[MAX_PASS_TYPES]; + uint8_t compilePass = 0, compileState = 0; + int compileIndex = 0; }; diff --git a/src/common/rendering/vulkan/system/vk_device.cpp b/src/common/rendering/vulkan/system/vk_device.cpp index 720188096..5aa229cb1 100644 --- a/src/common/rendering/vulkan/system/vk_device.cpp +++ b/src/common/rendering/vulkan/system/vk_device.cpp @@ -277,16 +277,20 @@ void VulkanDevice::CreateInstance() Extensions = GetExtensions(); EnabledExtensions = GetPlatformExtensions(); - std::string debugLayer = "VK_LAYER_LUNARG_standard_validation"; + std::string debugLayer = "VK_LAYER_KHRONOS_validation"; bool wantDebugLayer = vk_debug; bool debugLayerFound = false; - for (const VkLayerProperties &layer : AvailableLayers) + if (wantDebugLayer) { - if (layer.layerName == debugLayer && wantDebugLayer) + for (const VkLayerProperties& layer : AvailableLayers) { - EnabledValidationLayers.push_back(debugLayer.c_str()); - EnabledExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); - debugLayerFound = true; + if (layer.layerName == debugLayer) + { + EnabledValidationLayers.push_back(layer.layerName); + EnabledExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + debugLayerFound = true; + break; + } } } diff --git a/src/common/rendering/vulkan/system/vk_framebuffer.cpp b/src/common/rendering/vulkan/system/vk_framebuffer.cpp index 213cf56a4..b0a35399a 100644 --- a/src/common/rendering/vulkan/system/vk_framebuffer.cpp +++ b/src/common/rendering/vulkan/system/vk_framebuffer.cpp @@ -207,6 +207,11 @@ void VulkanFrameBuffer::Update() Super::Update(); } +bool VulkanFrameBuffer::CompileNextShader() +{ + return mShaderManager->CompileNextShader(); +} + void VulkanFrameBuffer::DeleteFrameObjects(bool uploadOnly) { FrameTextureUpload.Buffers.clear(); diff --git a/src/common/rendering/vulkan/system/vk_framebuffer.h b/src/common/rendering/vulkan/system/vk_framebuffer.h index 4098fd7ff..d234505cb 100644 --- a/src/common/rendering/vulkan/system/vk_framebuffer.h +++ b/src/common/rendering/vulkan/system/vk_framebuffer.h @@ -77,7 +77,7 @@ public: void Update() override; void InitializeState() override; - + bool CompileNextShader() override; void PrecacheMaterial(FMaterial *mat, int translation) override; void UpdatePalette() override; const char* DeviceName() const override; diff --git a/src/common/textures/bitmap.cpp b/src/common/textures/bitmap.cpp index bfe79dbb4..f944f2782 100644 --- a/src/common/textures/bitmap.cpp +++ b/src/common/textures/bitmap.cpp @@ -209,13 +209,14 @@ typedef void (*CopyFunc)(uint8_t *pout, const uint8_t *pin, int count, int step, iCopyColors, \ iCopyColors, \ iCopyColors, \ + iCopyColors, \ iCopyColors, \ iCopyColors, \ iCopyColors, \ iCopyColors, \ iCopyColors \ } -static const CopyFunc copyfuncs[][11]={ +static const CopyFunc copyfuncs[][12]={ COPY_FUNCS(bCopy), COPY_FUNCS(bBlend), COPY_FUNCS(bAdd), diff --git a/src/common/textures/bitmap.h b/src/common/textures/bitmap.h index 34fff5516..ae5ede88f 100644 --- a/src/common/textures/bitmap.h +++ b/src/common/textures/bitmap.h @@ -65,6 +65,7 @@ enum ColorType CF_IA, CF_CMYK, CF_YCbCr, + CF_YCCK, CF_BGR, CF_BGRA, CF_I16, @@ -326,6 +327,15 @@ struct cYCbCr static __forceinline int Gray(const unsigned char * p) { return (R(p) * 77 + G(p) * 143 + B(p) * 36) >> 8; } }; +struct cYCCK +{ + static __forceinline unsigned char R(const unsigned char* p) { auto myR = cYCbCr::R(p); return p[3] - ((myR * p[3]) >> 8); } + static __forceinline unsigned char G(const unsigned char* p) { auto myG = cYCbCr::G(p); return p[3] - ((myG * p[3]) >> 8); } + static __forceinline unsigned char B(const unsigned char* p) { auto myB = cYCbCr::B(p); return p[3] - ((myB * p[3]) >> 8); } + static __forceinline unsigned char A(const unsigned char* p, uint8_t x, uint8_t y, uint8_t z) { return 255; } + static __forceinline int Gray(const unsigned char* p) { return (R(p) * 77 + G(p) * 143 + B(p) * 36) >> 8; } +}; + struct cBGR { static __forceinline unsigned char R(const unsigned char * p) { return p[2]; } diff --git a/src/common/textures/formats/jpegtexture.cpp b/src/common/textures/formats/jpegtexture.cpp index 89ce068e2..75f4185b1 100644 --- a/src/common/textures/formats/jpegtexture.cpp +++ b/src/common/textures/formats/jpegtexture.cpp @@ -282,6 +282,7 @@ TArray FJPEGTexture::CreatePalettedPixels(int conversion) jpeg_read_header(&cinfo, TRUE); if (!((cinfo.out_color_space == JCS_RGB && cinfo.num_components == 3) || (cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) || + (cinfo.out_color_space == JCS_YCCK && cinfo.num_components == 4) || (cinfo.out_color_space == JCS_YCbCr && cinfo.num_components == 3) || (cinfo.out_color_space == JCS_GRAYSCALE && cinfo.num_components == 1))) { @@ -350,6 +351,24 @@ TArray FJPEGTexture::CreatePalettedPixels(int conversion) } break; + case JCS_YCCK: + // Probably useless but since I had the formula available... + for (int x = Width; x > 0; --x) + { + double Y = in[0], Cb = in[1], Cr = in[2]; + int K = in[3]; + int r = clamp((int)(Y + 1.40200 * (Cr - 0x80)), 0, 255); + int g = clamp((int)(Y - 0.34414 * (Cb - 0x80) - 0.71414 * (Cr - 0x80)), 0, 255); + int b = clamp((int)(Y + 1.77200 * (Cb - 0x80)), 0, 255); + r = r - ((r * K) >> 8); + g = g - ((g * K) >> 8); + b = b - ((b * K) >> 8); + *out = ImageHelpers::RGBToPalette(doalpha, r, g, b); + out += Height; + in += 4; + } + break; + default: // The other colorspaces were considered above and discarded, // but GCC will complain without a default for them here. @@ -402,6 +421,7 @@ int FJPEGTexture::CopyPixels(FBitmap *bmp, int conversion) if (!((cinfo.out_color_space == JCS_RGB && cinfo.num_components == 3) || (cinfo.out_color_space == JCS_CMYK && cinfo.num_components == 4) || + (cinfo.out_color_space == JCS_YCCK && cinfo.num_components == 4) || (cinfo.out_color_space == JCS_YCbCr && cinfo.num_components == 3) || (cinfo.out_color_space == JCS_GRAYSCALE && cinfo.num_components == 1))) { @@ -439,6 +459,11 @@ int FJPEGTexture::CopyPixels(FBitmap *bmp, int conversion) 4, cinfo.output_width * cinfo.output_components, 0, CF_CMYK); break; + case JCS_YCCK: + bmp->CopyPixelDataRGB(0, 0, buff.Data(), cinfo.output_width, cinfo.output_height, + 4, cinfo.output_width * cinfo.output_components, 0, CF_YCCK); + break; + case JCS_YCbCr: bmp->CopyPixelDataRGB(0, 0, buff.Data(), cinfo.output_width, cinfo.output_height, 4, cinfo.output_width * cinfo.output_components, 0, CF_YCbCr); diff --git a/src/common/thirdparty/rapidjson/rapidjson.h b/src/common/thirdparty/rapidjson/rapidjson.h index 053b2ce43..d5b7630b5 100644 --- a/src/common/thirdparty/rapidjson/rapidjson.h +++ b/src/common/thirdparty/rapidjson/rapidjson.h @@ -238,6 +238,8 @@ # define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN # elif defined(_MSC_VER) && defined(_M_ARM) # define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN +# elif defined(_MSC_VER) && defined(_M_ARM64) +# define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN # elif defined(RAPIDJSON_DOXYGEN_RUNNING) # define RAPIDJSON_ENDIAN # else diff --git a/src/console/c_cmds.cpp b/src/console/c_cmds.cpp index 15e932d20..33f107d1a 100644 --- a/src/console/c_cmds.cpp +++ b/src/console/c_cmds.cpp @@ -1023,10 +1023,10 @@ CCMD(secret) maphdr.Format("[%s]", mapname); FString linebuild; - char readbuffer[1024]; + char readbuffer[10240]; bool inlevel = false; - while (lump.Gets(readbuffer, 1024)) + while (lump.Gets(readbuffer, 10240)) { if (!inlevel) { diff --git a/src/d_main.cpp b/src/d_main.cpp index 43f368552..9091e7889 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -3356,6 +3356,10 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray& allwads, TArr } V_Init2(); + while(!screen->CompileNextShader()) + { + // here we can do some visual updates later + } twod->fullscreenautoaspect = gameinfo.fullscreenautoaspect; // Initialize the size of the 2D drawer so that an attempt to access it outside the draw code won't crash. twod->Begin(screen->GetWidth(), screen->GetHeight()); diff --git a/src/events.cpp b/src/events.cpp index 6da8118bb..d3a739495 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -162,7 +162,7 @@ bool EventManager::UnregisterHandler(DStaticEventHandler* handler) bool EventManager::SendNetworkEvent(FString name, int arg1, int arg2, int arg3, bool manual) { - if (gamestate != GS_LEVEL) + if (gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL) return false; Net_WriteByte(DEM_NETEVENT); diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index 0efbf3729..03034a2dd 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -144,12 +144,7 @@ void DrawFullscreenSubtitle(FFont* font, const char *text) void DIntermissionScreen::Init(FIntermissionAction *desc, bool first) { - if (desc->mMusic.IsEmpty()) - { - // only start the default music if this is the first action in an intermission - if (first) S_ChangeMusic (gameinfo.finaleMusic, gameinfo.finaleOrder, desc->mMusicLooping); - } - else + if (!first && desc->mMusic.IsNotEmpty()) { S_ChangeMusic (desc->mMusic, desc->mMusicOrder, desc->mMusicLooping); } @@ -193,8 +188,27 @@ void DIntermissionScreen::Init(FIntermissionAction *desc, bool first) } mTicker = 0; mSubtitle = desc->mSubtitle; + mFirst = first; + // If this is the first element of an intermission we must delay starting the music until Start() is called. + mMusic = desc->mMusic; + mMusicLooping = desc->mMusicLooping; + mMusicOrder = desc->mMusicOrder; } +void DIntermissionScreen::Start() +{ + if (mFirst) + { + if (mMusic.IsEmpty()) + { + S_ChangeMusic(gameinfo.finaleMusic, gameinfo.finaleOrder, mMusicLooping); + } + else + { + S_ChangeMusic(mMusic, mMusicOrder, mMusicLooping); + } + } +} int DIntermissionScreen::Responder (FInputEvent *ev) { @@ -900,6 +914,11 @@ again: return false; } +void DIntermissionController::Start() +{ + if (mScreen) mScreen->Start(); +} + bool DIntermissionController::Responder (FInputEvent *ev) { if (mScreen != NULL) @@ -994,6 +1013,7 @@ DIntermissionController* F_StartIntermission(FIntermissionDescriptor *desc, bool if (!CurrentIntermission->NextPage()) { CurrentIntermission->Destroy(); + return nullptr; } GC::WriteBarrier(CurrentIntermission); @@ -1042,10 +1062,17 @@ DEFINE_ACTION_FUNCTION(DIntermissionController, Ticker) ACTION_RETURN_BOOL(self->Ticker()); } +DEFINE_ACTION_FUNCTION(DIntermissionController, Start) +{ + PARAM_SELF_PROLOGUE(DIntermissionController); + self->Start(); + return 0; +} + DEFINE_ACTION_FUNCTION(DIntermissionController, Drawer) { PARAM_SELF_PROLOGUE(DIntermissionController); - self->Drawer (); + self->Drawer(); return 0; } diff --git a/src/intermission/intermission.h b/src/intermission/intermission.h index db2e76ecb..e25354c87 100644 --- a/src/intermission/intermission.h +++ b/src/intermission/intermission.h @@ -166,7 +166,11 @@ protected: int mDuration; FTextureID mBackground; FString mSubtitle; + FString mMusic; + int mMusicOrder; + bool mMusicLooping; bool mFlatfill; + bool mFirst; TArray mOverlays; bool CheckOverlay(int i); @@ -176,6 +180,7 @@ public: DIntermissionScreen() {} virtual void Init(FIntermissionAction *desc, bool first); + virtual void Start(); virtual int Responder (FInputEvent *ev); virtual int Ticker (); virtual void Drawer (); @@ -304,6 +309,7 @@ public: DIntermissionController(FIntermissionDescriptor *mDesc = NULL, bool mDeleteDesc = false, bool ending = false); bool Responder (FInputEvent *ev); bool Ticker (); + void Start(); void Drawer (); void OnDestroy() override; bool NextPage(); diff --git a/src/maploader/strifedialogue.cpp b/src/maploader/strifedialogue.cpp index 247aaa5a9..181405bb5 100644 --- a/src/maploader/strifedialogue.cpp +++ b/src/maploader/strifedialogue.cpp @@ -345,7 +345,7 @@ FStrifeDialogueNode *MapLoader::ReadRetailNode (const char *name, FileReader &lu for (j = 0; j < 3; ++j) { auto inv = GetStrifeType(speech.ItemCheck[j]); - if (!inv->IsDescendantOf(NAME_Inventory)) inv = nullptr; + if (inv == NULL || !inv->IsDescendantOf(NAME_Inventory)) inv = nullptr; node->ItemCheck[j].Item = inv; node->ItemCheck[j].Amount = -1; } @@ -516,7 +516,7 @@ void MapLoader::ParseReplies (const char *name, int pos, FStrifeDialogueReply ** for (k = 0; k < 3; ++k) { auto inv = GetStrifeType(rsp->Item[k]); - if (!inv->IsDescendantOf(NAME_Inventory)) inv = nullptr; + if (inv == NULL || !inv->IsDescendantOf(NAME_Inventory)) inv = nullptr; reply->ItemCheck[k].Item = inv; reply->ItemCheck[k].Amount = rsp->Count[k]; } diff --git a/src/playsim/actor.h b/src/playsim/actor.h index cbb98f69c..6ba1e706c 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -423,7 +423,8 @@ enum ActorFlag8 MF8_MAP07BOSS2 = 0x00800000, // MBF21 boss death. MF8_AVOIDHAZARDS = 0x01000000, // MBF AI enhancement. MF8_STAYONLIFT = 0x02000000, // MBF AI enhancement. - MF8_DONTFOLLOWPLAYERS = 0x04000000, // [inkoalwetrust] Friendly monster will not follow players. + MF8_DONTFOLLOWPLAYERS = 0x04000000, // [inkoalawetrust] Friendly monster will not follow players. + MF8_SEEFRIENDLYMONSTERS = 0X08000000, // [inkoalawetrust] Hostile monster can see friendly monsters. }; // --- mobj.renderflags --- diff --git a/src/playsim/mapthinkers/a_floor.cpp b/src/playsim/mapthinkers/a_floor.cpp index 21eccaa4d..ce2ba5960 100644 --- a/src/playsim/mapthinkers/a_floor.cpp +++ b/src/playsim/mapthinkers/a_floor.cpp @@ -663,6 +663,7 @@ bool FLevelLocals::EV_BuildStairs (int tag, DFloor::EStair type, line_t *line, d // 2. Other side is the next sector to raise // 3. Unless already moving, or different texture, then stop building validcount++; + sec->validcount = validcount; do { ok = 0; diff --git a/src/playsim/p_enemy.cpp b/src/playsim/p_enemy.cpp index 2da804105..8a4a33f03 100644 --- a/src/playsim/p_enemy.cpp +++ b/src/playsim/p_enemy.cpp @@ -1555,25 +1555,32 @@ AActor *LookForEnemiesInBlock (AActor *lookee, int index, void *extparam) continue; other = NULL; - if (link->flags & MF_FRIENDLY) + if (lookee->flags & MF_FRIENDLY) { - if (!lookee->IsFriend(link)) + if (link->flags & MF_FRIENDLY) { - // This is somebody else's friend, so go after it - other = link; - } - else if (link->target != NULL && !(link->target->flags & MF_FRIENDLY)) - { - other = link->target; - if (!(other->flags & MF_SHOOTABLE) || - other->health <= 0 || - (other->flags2 & MF2_DORMANT)) + if (!lookee->IsFriend(link)) { - other = NULL;; + // This is somebody else's friend, so go after it + other = link; + } + else if (link->target != NULL && !(link->target->flags & MF_FRIENDLY)) + { + other = link->target; + if (!(other->flags & MF_SHOOTABLE) || + other->health <= 0 || + (other->flags2 & MF2_DORMANT)) + { + other = NULL;; + } } } + else + { + other = link; + } } - else + else if (lookee->flags8 & MF8_SEEFRIENDLYMONSTERS && link->flags & MF_FRIENDLY) { other = link; } @@ -1617,7 +1624,7 @@ int P_LookForEnemies (AActor *actor, INTBOOL allaround, FLookExParams *params) { AActor *other; - other = P_BlockmapSearch (actor, actor->friendlyseeblocks, LookForEnemiesInBlock, params); + other = P_BlockmapSearch(actor, actor->friendlyseeblocks, LookForEnemiesInBlock, params); if (other != NULL) { @@ -1726,6 +1733,12 @@ int P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params) } // [SP] if false, and in deathmatch, intentional fall-through + else if (actor->flags8 & MF8_SEEFRIENDLYMONSTERS) + { + bool result = P_LookForEnemies (actor, allaround, params); + + if (result) return true; + } if (!(gameinfo.gametype & (GAME_DoomStrifeChex)) && actor->Level->isPrimaryLevel() && diff --git a/src/playsim/p_interaction.cpp b/src/playsim/p_interaction.cpp index b58ba727d..8a8732b3b 100644 --- a/src/playsim/p_interaction.cpp +++ b/src/playsim/p_interaction.cpp @@ -76,6 +76,7 @@ EXTERN_CVAR (Bool, show_obituaries) CVAR (Float, sv_damagefactormobj, 1.0, CVAR_SERVERINFO|CVAR_CHEAT) CVAR (Float, sv_damagefactorfriendly, 1.0, CVAR_SERVERINFO|CVAR_CHEAT) CVAR (Float, sv_damagefactorplayer, 1.0, CVAR_SERVERINFO|CVAR_CHEAT) +CVAR (Float, sv_ammofactor, 1.0, CVAR_SERVERINFO|CVAR_CHEAT) // used in the zscript ammo code // // GET STUFF diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index eeee67547..ebd68beca 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -339,6 +339,7 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(MF8, AVOIDHAZARDS, AActor, flags8), DEFINE_FLAG(MF8, STAYONLIFT, AActor, flags8), DEFINE_FLAG(MF8, DONTFOLLOWPLAYERS, AActor, flags8), + DEFINE_FLAG(MF8, SEEFRIENDLYMONSTERS, AActor, flags8), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), diff --git a/wadsrc/static/zscript/actors/doom/bossbrain.zs b/wadsrc/static/zscript/actors/doom/bossbrain.zs index a2fb6f267..b0033cb2b 100644 --- a/wadsrc/static/zscript/actors/doom/bossbrain.zs +++ b/wadsrc/static/zscript/actors/doom/bossbrain.zs @@ -12,6 +12,7 @@ class BossBrain : Actor Health 250; Mass 10000000; PainChance 255; + Radius 16; +SOLID +SHOOTABLE +NOICEDEATH +OLDRADIUSDMG diff --git a/wadsrc/static/zscript/actors/inventory/ammo.zs b/wadsrc/static/zscript/actors/inventory/ammo.zs index 52b3d8f22..e30a5de60 100644 --- a/wadsrc/static/zscript/actors/inventory/ammo.zs +++ b/wadsrc/static/zscript/actors/inventory/ammo.zs @@ -94,7 +94,7 @@ class Ammo : Inventory if (!item.bIgnoreSkill) { // extra ammo in baby mode and nightmare mode - receiving = int(receiving * G_SkillPropertyFloat(SKILLP_AmmoFactor)); + receiving = int(receiving * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor)); } int oldamount = Amount; @@ -140,7 +140,7 @@ class Ammo : Inventory // extra ammo in baby mode and nightmare mode if (!bIgnoreSkill) { - amount = int(amount * G_SkillPropertyFloat(SKILLP_AmmoFactor)); + amount = int(amount * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor)); } let type = GetParentAmmo(); @@ -258,7 +258,7 @@ class BackpackItem : Inventory // extra ammo in baby mode and nightmare mode if (!bIgnoreSkill) { - amount = int(amount * G_SkillPropertyFloat(SKILLP_AmmoFactor)); + amount = int(amount * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor)); } if (amount < 0) amount = 0; if (ammoitem == NULL) @@ -323,7 +323,7 @@ class BackpackItem : Inventory // extra ammo in baby mode and nightmare mode if (!bIgnoreSkill) { - amount = int(amount * G_SkillPropertyFloat(SKILLP_AmmoFactor)); + amount = int(amount * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor)); } ammoitem.Amount += amount; if (ammoitem.Amount > ammoitem.MaxAmount && !sv_unlimited_pickup) diff --git a/wadsrc/static/zscript/actors/inventory/weapons.zs b/wadsrc/static/zscript/actors/inventory/weapons.zs index eca912291..e3284f913 100644 --- a/wadsrc/static/zscript/actors/inventory/weapons.zs +++ b/wadsrc/static/zscript/actors/inventory/weapons.zs @@ -748,7 +748,7 @@ class Weapon : StateProvider // extra ammoitem in baby mode and nightmare mode if (!bIgnoreSkill) { - amount = int(amount * G_SkillPropertyFloat(SKILLP_AmmoFactor)); + amount = int(amount * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor)); } ammoitem = Ammo(other.FindInventory (ammotype)); if (ammoitem == NULL) @@ -783,7 +783,7 @@ class Weapon : StateProvider // extra ammo in baby mode and nightmare mode if (!bIgnoreSkill) { - amount = int(amount * G_SkillPropertyFloat(SKILLP_AmmoFactor)); + amount = int(amount * (G_SkillPropertyFloat(SKILLP_AmmoFactor) * sv_ammofactor)); } ammo.Amount += amount; if (ammo.Amount > ammo.MaxAmount && !sv_unlimited_pickup) diff --git a/wadsrc/static/zscript/ui/intermission.zs b/wadsrc/static/zscript/ui/intermission.zs index f6a762f1b..cdf4ce03c 100644 --- a/wadsrc/static/zscript/ui/intermission.zs +++ b/wadsrc/static/zscript/ui/intermission.zs @@ -5,6 +5,7 @@ class IntermissionController native ui // This is mostly a black box to the native intermission code. // May be scriptified later, but right now we do not need it. + native void Start(); native bool Responder(InputEvent ev); native bool Ticker(); native void Drawer(); @@ -24,6 +25,7 @@ class IntermissionScreenJob : ScreenJob return self; } + override void Start() { controller.Start(); } override bool OnEvent(InputEvent evt) { return controller.Responder(evt); } override void OnTick() { if (!controller.Ticker()) jobstate = finished; } override void Draw(double smoothratio) { controller.Drawer(); } diff --git a/wadsrc/static/zscript/ui/menu/conversationmenu.zs b/wadsrc/static/zscript/ui/menu/conversationmenu.zs index a849269bc..1b1d3c011 100644 --- a/wadsrc/static/zscript/ui/menu/conversationmenu.zs +++ b/wadsrc/static/zscript/ui/menu/conversationmenu.zs @@ -497,14 +497,13 @@ class ConversationMenu : Menu double sx = (x - 160.0) * CleanXfac + (screen.GetWidth() * 0.5); double sy = (y - 100.0) * CleanYfac + (screen.GetHeight() * 0.5); - ypositions.Push(sy); - screen.DrawText(displayFont, Font.CR_GREEN, sx / fontScale, sy / fontScale, mResponseLines[i], DTA_KeepRatio, true, DTA_VirtualWidth, displayWidth, DTA_VirtualHeight, displayHeight); if (i == mResponses[response]) { String tbuf; + ypositions.Push(sy); response++; tbuf = String.Format("%d.", response); x = 50 - displayFont.StringWidth(tbuf);