diff --git a/source/common/audio/music/music_config.cpp b/source/common/audio/music/music_config.cpp index efdb05637..5ea5e97d9 100644 --- a/source/common/audio/music/music_config.cpp +++ b/source/common/audio/music/music_config.cpp @@ -95,7 +95,7 @@ CUSTOM_CVAR(Bool, adl_use_custom_bank, false, CVAR_ARCHIVE | CVAR_VIRTUAL) FORWARD_BOOL_CVAR(adl_use_custom_bank); } -CUSTOM_CVAR(String, adl_custom_bank, "", CVAR_ARCHIVE | CVAR_VIRTUAL) +CUSTOM_CVAR(String, adl_custom_bank, "", CVAR_ARCHIVE | CVAR_VIRTUAL | CVAR_SYSTEM_ONLY) { FORWARD_STRING_CVAR(adl_custom_bank); } @@ -111,12 +111,12 @@ CUSTOM_CVAR(Int, adl_volume_model, 0 /*ADLMIDI_VolumeModel_AUTO*/, CVAR_ARCHIVE // //========================================================================== -CUSTOM_CVAR(String, fluid_lib, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(String, fluid_lib, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL | CVAR_SYSTEM_ONLY) { FORWARD_STRING_CVAR(fluid_lib); } -CUSTOM_CVAR(String, fluid_patchset, GAMENAMELOWERCASE, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(String, fluid_patchset, GAMENAMELOWERCASE, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL | CVAR_SYSTEM_ONLY) { FORWARD_STRING_CVAR(fluid_patchset); } @@ -278,7 +278,7 @@ CUSTOM_CVAR(String, opn_custom_bank, "", CVAR_ARCHIVE | CVAR_VIRTUAL) //========================================================================== -CUSTOM_CVAR(String, midi_config, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(String, midi_config, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL | CVAR_SYSTEM_ONLY) { FORWARD_STRING_CVAR(gus_config); } @@ -288,7 +288,7 @@ CUSTOM_CVAR(Bool, midi_dmxgus, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VI FORWARD_BOOL_CVAR(gus_dmxgus); } -CUSTOM_CVAR(String, gus_patchdir, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(String, gus_patchdir, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL | CVAR_SYSTEM_ONLY) { FORWARD_STRING_CVAR(gus_patchdir); } @@ -395,7 +395,7 @@ CUSTOM_CVAR(Float, timidity_min_sustain_time, 5000.f, CVAR_ARCHIVE | CVAR_GLOBAL } #endif -CUSTOM_CVAR(String, timidity_config, GAMENAMELOWERCASE, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(String, timidity_config, GAMENAMELOWERCASE, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL | CVAR_SYSTEM_ONLY) { FORWARD_STRING_CVAR(timidity_config); } @@ -406,7 +406,7 @@ CUSTOM_CVAR(String, timidity_config, GAMENAMELOWERCASE, CVAR_ARCHIVE | CVAR_GLOB // //========================================================================== -CUSTOM_CVAR(String, wildmidi_config, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL) +CUSTOM_CVAR(String, wildmidi_config, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_VIRTUAL | CVAR_SYSTEM_ONLY) { FORWARD_STRING_CVAR(wildmidi_config); } diff --git a/source/common/console/c_cvars.h b/source/common/console/c_cvars.h index c52af0aeb..ccc3cfa6a 100644 --- a/source/common/console/c_cvars.h +++ b/source/common/console/c_cvars.h @@ -75,6 +75,8 @@ enum CVAR_CONFIG_ONLY = 1 << 18, // do not save var to savegame and do not send it across network. CVAR_ZS_CUSTOM = 1 << 19, // Custom CVar backed by a ZScript class CVAR_ZS_CUSTOM_CLONE = 1 << 20, // Clone of a Custom ZScript CVar + + CVAR_SYSTEM_ONLY = 1 << 21, // System-related cvar that should only ever be changed by the user }; enum ECVarType diff --git a/source/common/engine/m_random.h b/source/common/engine/m_random.h index ba0bcaf62..bc7eb4d0d 100644 --- a/source/common/engine/m_random.h +++ b/source/common/engine/m_random.h @@ -37,6 +37,7 @@ #include #include "basics.h" +#include "tarray.h" #include "sfmt/SFMTObj.h" class FSerializer; diff --git a/source/common/menu/savegamemanager.cpp b/source/common/menu/savegamemanager.cpp index 929d631d1..efb5a02af 100644 --- a/source/common/menu/savegamemanager.cpp +++ b/source/common/menu/savegamemanager.cpp @@ -49,7 +49,7 @@ #include "m_argv.h" #include "i_specialpaths.h" -CVAR(String, save_dir, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG); +CVAR(String, save_dir, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_SYSTEM_ONLY); FString SavegameFolder; CVAR(Int, save_sort_order, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) diff --git a/source/common/models/bonecomponents.h b/source/common/models/bonecomponents.h index 313b0832e..f4f221f3b 100644 --- a/source/common/models/bonecomponents.h +++ b/source/common/models/bonecomponents.h @@ -6,17 +6,6 @@ #include - -class DBoneComponents : public DObject -{ - DECLARE_CLASS(DBoneComponents, DObject); -public: - TArray> trscomponents; - TArray> trsmatrix; - - DBoneComponents() = default; -}; - struct ModelAnimFrameInterp { float inter = -1.0f; diff --git a/source/common/models/model.h b/source/common/models/model.h index 2be1f54cc..b6d3f4803 100644 --- a/source/common/models/model.h +++ b/source/common/models/model.h @@ -91,15 +91,15 @@ public: virtual int FindLastFrame(FName name) { return FErr_NotFound; } virtual double FindFramerate(FName name) { return FErr_NotFound; } - virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) = 0; + virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) = 0; virtual void BuildVertexBuffer(FModelRenderer *renderer) = 0; virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) = 0; virtual float getAspectFactor(float vscale) { return 1.f; } virtual const TArray* AttachAnimationData() { return nullptr; }; - virtual ModelAnimFrame PrecalculateFrame(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData, DBoneComponents* bones, int index) { return nullptr; }; + virtual ModelAnimFrame PrecalculateFrame(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData) { return nullptr; }; - virtual const TArray CalculateBones(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData, DBoneComponents* bones, int index) { return {}; }; + virtual const TArray* CalculateBones(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData) { return nullptr; }; void SetVertexBuffer(int type, IModelVertexBuffer *buffer) { mVBuf[type] = buffer; } IModelVertexBuffer *GetVertexBuffer(int type) const { return mVBuf[type]; } diff --git a/source/common/models/model_iqm.h b/source/common/models/model_iqm.h index c16e8372a..cf221595f 100644 --- a/source/common/models/model_iqm.h +++ b/source/common/models/model_iqm.h @@ -116,16 +116,16 @@ public: int FindFirstFrame(FName name) override; int FindLastFrame(FName name) override; double FindFramerate(FName name) override; - void RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; + void RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) override; void BuildVertexBuffer(FModelRenderer* renderer) override; void AddSkins(uint8_t* hitlist, const FTextureID* surfaceskinids) override; const TArray* AttachAnimationData() override; - ModelAnimFrame PrecalculateFrame(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData, DBoneComponents* bones, int index) override; - const TArray CalculateBones(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData, DBoneComponents* bones, int index) override; + ModelAnimFrame PrecalculateFrame(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData) override; + const TArray* CalculateBones(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData) override; - ModelAnimFramePrecalculatedIQM CalculateFrameIQM(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const ModelAnimFramePrecalculatedIQM* precalculated, const TArray* animationData, DBoneComponents* bones, int index); - const TArray CalculateBonesIQM(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const ModelAnimFramePrecalculatedIQM* precalculated, const TArray* animationData, DBoneComponents* bones, int index); + ModelAnimFramePrecalculatedIQM CalculateFrameIQM(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const ModelAnimFramePrecalculatedIQM* precalculated, const TArray* animationData); + const TArray* CalculateBonesIQM(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const ModelAnimFramePrecalculatedIQM* precalculated, const TArray* animationData); private: void LoadGeometry(); @@ -151,6 +151,8 @@ private: TArray VertexArrays; uint32_t NumVertices = 0; + TArray boneData; // temporary array, used to hold animation data during rendering, set during CalculateBones, uploaded during RenderFrame + TArray Vertices; TArray baseframe; diff --git a/source/common/models/model_kvx.h b/source/common/models/model_kvx.h index 2175bcbca..e13ec39e9 100644 --- a/source/common/models/model_kvx.h +++ b/source/common/models/model_kvx.h @@ -59,7 +59,7 @@ public: bool Load(const char * fn, int lumpnum, const char * buffer, int length) override; void Initialize(); virtual int FindFrame(const char* name, bool nodefault) override; - virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; + virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) override; virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override; FTextureID GetPaletteTexture() const { return mPalette; } void BuildVertexBuffer(FModelRenderer *renderer) override; diff --git a/source/common/models/model_md2.h b/source/common/models/model_md2.h index fd1646dc9..201cf6406 100644 --- a/source/common/models/model_md2.h +++ b/source/common/models/model_md2.h @@ -113,7 +113,7 @@ public: virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) override; virtual int FindFrame(const char* name, bool nodefault) override; - virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; + virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) override; virtual void LoadGeometry(); virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override; diff --git a/source/common/models/model_md3.h b/source/common/models/model_md3.h index 045b1cc3b..fae753b58 100644 --- a/source/common/models/model_md3.h +++ b/source/common/models/model_md3.h @@ -67,7 +67,7 @@ public: virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) override; virtual int FindFrame(const char* name, bool nodefault) override; - virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; + virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) override; void LoadGeometry(); void BuildVertexBuffer(FModelRenderer *renderer); virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override; diff --git a/source/common/models/model_obj.h b/source/common/models/model_obj.h index 4fc977c05..760493443 100644 --- a/source/common/models/model_obj.h +++ b/source/common/models/model_obj.h @@ -98,7 +98,7 @@ public: ~FOBJModel(); bool Load(const char* fn, int lumpnum, const char* buffer, int length) override; int FindFrame(const char* name, bool nodefault) override; - void RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; + void RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) override; void BuildVertexBuffer(FModelRenderer* renderer) override; void AddSkins(uint8_t* hitlist, const FTextureID* surfaceskinids) override; }; diff --git a/source/common/models/model_ue1.h b/source/common/models/model_ue1.h index 579002f89..447a69ee0 100644 --- a/source/common/models/model_ue1.h +++ b/source/common/models/model_ue1.h @@ -26,7 +26,7 @@ public: bool Load(const char * fn, int lumpnum, const char * buffer, int length) override; int FindFrame(const char* name, bool nodefault) override; - void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) override; + void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) override; void BuildVertexBuffer(FModelRenderer *renderer) override; void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override; void LoadGeometry(); diff --git a/source/common/models/modelrenderer.h b/source/common/models/modelrenderer.h index d2d774eab..adc93dded 100644 --- a/source/common/models/modelrenderer.h +++ b/source/common/models/modelrenderer.h @@ -24,6 +24,6 @@ public: virtual void SetMaterial(FGameTexture *skin, bool clampNoFilter, FTranslationID translation) = 0; virtual void DrawArrays(int start, int count) = 0; virtual void DrawElements(int numIndices, size_t offset) = 0; - virtual int SetupFrame(FModel* model, unsigned int frame1, unsigned int frame2, unsigned int size, const TArray& bones, int boneStartIndex) { return -1; }; + virtual void SetupFrame(FModel* model, unsigned int frame1, unsigned int frame2, unsigned int size, int boneStartIndex) {}; }; diff --git a/source/common/models/models_iqm.cpp b/source/common/models/models_iqm.cpp index 1384debce..d5fb6a152 100644 --- a/source/common/models/models_iqm.cpp +++ b/source/common/models/models_iqm.cpp @@ -7,9 +7,8 @@ #include "engineerrors.h" #include "dobject.h" #include "bonecomponents.h" - -IMPLEMENT_CLASS(DBoneComponents, false, false); - +#include "v_video.h" +#include "hw_bonebuffer.h" IQMModel::IQMModel() { @@ -469,9 +468,10 @@ double IQMModel::FindFramerate(FName name) return FErr_NotFound; } -void IQMModel::RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame1, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) +void IQMModel::RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame1, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) { - renderer->SetupFrame(this, 0, 0, NumVertices, boneData, boneStartPosition); + + renderer->SetupFrame(this, 0, 0, NumVertices, boneStartPosition >= 0 ? boneStartPosition : screen->mBones->UploadBones(boneData)); FGameTexture* lastSkin = nullptr; for (unsigned i = 0; i < Meshes.Size(); i++) @@ -563,51 +563,51 @@ static TRS InterpolateBone(const TRS &from, const TRS &to, float t, float invt) #include "printf.h" -ModelAnimFrame IQMModel::PrecalculateFrame(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData, DBoneComponents* bones, int index) +ModelAnimFrame IQMModel::PrecalculateFrame(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData) { if(inter <= 0) { - return CalculateFrameIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, nullptr, animationData, bones, index); + return CalculateFrameIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, nullptr, animationData); } else if(std::holds_alternative(from)) { auto &from_interp = std::get(from); - return CalculateFrameIQM(from_interp.frame2, to.frame2, inter, from_interp.frame1, from_interp.inter, to.frame1, to.inter, nullptr, animationData, bones, index); + return CalculateFrameIQM(from_interp.frame2, to.frame2, inter, from_interp.frame1, from_interp.inter, to.frame1, to.inter, nullptr, animationData); } else if(std::holds_alternative(from)) { - return CalculateFrameIQM(0, to.frame2, inter, 0, -1.f, to.frame1, to.inter, &std::get(from), animationData, bones, index); + return CalculateFrameIQM(0, to.frame2, inter, 0, -1.f, to.frame1, to.inter, &std::get(from), animationData); } else { - return CalculateFrameIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, nullptr, animationData, bones, index); + return CalculateFrameIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, nullptr, animationData); } } -const TArray IQMModel::CalculateBones(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData, DBoneComponents* bones, int index) +const TArray* IQMModel::CalculateBones(const ModelAnimFrame &from, const ModelAnimFrameInterp &to, float inter, const TArray* animationData) { if(inter <= 0) { - return CalculateBonesIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, nullptr, animationData, bones, index); + return CalculateBonesIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, nullptr, animationData); } else if(std::holds_alternative(from)) { auto &from_interp = std::get(from); - return CalculateBonesIQM(from_interp.frame2, to.frame2, inter, from_interp.frame1, from_interp.inter, to.frame1, to.inter, nullptr, animationData, bones, index); + return CalculateBonesIQM(from_interp.frame2, to.frame2, inter, from_interp.frame1, from_interp.inter, to.frame1, to.inter, nullptr, animationData); } else if(std::holds_alternative(from)) { - return CalculateBonesIQM(0, to.frame2, inter, 0, -1.f, to.frame1, to.inter, &std::get(from), animationData, bones, index); + return CalculateBonesIQM(0, to.frame2, inter, 0, -1.f, to.frame1, to.inter, &std::get(from), animationData); } else { - return CalculateBonesIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, nullptr, animationData, bones, index); + return CalculateBonesIQM(to.frame1, to.frame2, to.inter, 0, -1.f, 0, -1.f, nullptr, animationData); } } -ModelAnimFramePrecalculatedIQM IQMModel::CalculateFrameIQM(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const ModelAnimFramePrecalculatedIQM* precalculated, const TArray* animationData, DBoneComponents* boneComponentData, int index) +ModelAnimFramePrecalculatedIQM IQMModel::CalculateFrameIQM(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const ModelAnimFramePrecalculatedIQM* precalculated, const TArray* animationData) { ModelAnimFramePrecalculatedIQM out; const TArray& animationFrames = animationData ? *animationData : TRSData; @@ -661,18 +661,13 @@ ModelAnimFramePrecalculatedIQM IQMModel::CalculateFrameIQM(int frame1, int frame return out; } -const TArray IQMModel::CalculateBonesIQM(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const ModelAnimFramePrecalculatedIQM* precalculated, const TArray* animationData, DBoneComponents* boneComponentData, int index) +const TArray* IQMModel::CalculateBonesIQM(int frame1, int frame2, float inter, int frame1_prev, float inter1_prev, int frame2_prev, float inter2_prev, const ModelAnimFramePrecalculatedIQM* precalculated, const TArray* animationData) { const TArray& animationFrames = animationData ? *animationData : TRSData; if (Joints.Size() > 0) { int numbones = Joints.SSize(); - if (boneComponentData->trscomponents[index].SSize() != numbones) - boneComponentData->trscomponents[index].Resize(numbones); - if (boneComponentData->trsmatrix[index].SSize() != numbones) - boneComponentData->trsmatrix[index].Resize(numbones); - frame1 = clamp(frame1, 0, (animationFrames.SSize() - 1) / numbones); frame2 = clamp(frame2, 0, (animationFrames.SSize() - 1) / numbones); @@ -686,14 +681,16 @@ const TArray IQMModel::CalculateBonesIQM(int frame1, int frame2, float float invt1 = 1.0f - inter1_prev; float invt2 = 1.0f - inter2_prev; - float swapYZ[16] = { 0.0f }; - swapYZ[0 + 0 * 4] = 1.0f; - swapYZ[1 + 2 * 4] = 1.0f; - swapYZ[2 + 1 * 4] = 1.0f; - swapYZ[3 + 3 * 4] = 1.0f; + constexpr const float swapYZ[16] + { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + + boneData.Resize(numbones); - TArray bones(numbones, true); - TArray modifiedBone(numbones, true); for (int i = 0; i < numbones; i++) { TRS prev; @@ -724,33 +721,16 @@ const TArray IQMModel::CalculateBonesIQM(int frame1, int frame2, float bone = inter < 0 ? animationFrames[offset1 + i] : InterpolateBone(prev, next , inter, invt); } - if (Joints[i].Parent >= 0 && modifiedBone[Joints[i].Parent]) - { - boneComponentData->trscomponents[index][i] = bone; - modifiedBone[i] = true; - } - else if (boneComponentData->trscomponents[index][i].Equals(bone)) - { - bones[i] = boneComponentData->trsmatrix[index][i]; - modifiedBone[i] = false; - continue; - } - else - { - boneComponentData->trscomponents[index][i] = bone; - modifiedBone[i] = true; - } - VSMatrix m; m.loadIdentity(); m.translate(bone.translation.X, bone.translation.Y, bone.translation.Z); m.multQuaternion(bone.rotation); m.scale(bone.scaling.X, bone.scaling.Y, bone.scaling.Z); - VSMatrix& result = bones[i]; + VSMatrix& result = boneData[i]; if (Joints[i].Parent >= 0) { - result = bones[Joints[i].Parent]; + result = boneData[Joints[i].Parent]; result.multMatrix(swapYZ); result.multMatrix(baseframe[Joints[i].Parent]); result.multMatrix(m); @@ -765,9 +745,7 @@ const TArray IQMModel::CalculateBonesIQM(int frame1, int frame2, float result.multMatrix(swapYZ); } - boneComponentData->trsmatrix[index] = bones; - - return bones; + return &boneData; } - return {}; + return nullptr; } diff --git a/source/common/models/models_md2.cpp b/source/common/models/models_md2.cpp index 280c4d265..d7fa47662 100644 --- a/source/common/models/models_md2.cpp +++ b/source/common/models/models_md2.cpp @@ -364,7 +364,7 @@ int FDMDModel::FindFrame(const char* name, bool nodefault) // //=========================================================================== -void FDMDModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, FTranslationID translation, const FTextureID*, const TArray& boneData, int boneStartPosition) +void FDMDModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, FTranslationID translation, const FTextureID*, int boneStartPosition) { if (frameno >= info.numFrames || frameno2 >= info.numFrames) return; @@ -377,7 +377,7 @@ void FDMDModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int f renderer->SetInterpolation(inter); renderer->SetMaterial(skin, false, translation); - renderer->SetupFrame(this, frames[frameno].vindex, frames[frameno2].vindex, lodInfo[0].numTriangles * 3, {}, -1); + renderer->SetupFrame(this, frames[frameno].vindex, frames[frameno2].vindex, lodInfo[0].numTriangles * 3, -1); renderer->DrawArrays(0, lodInfo[0].numTriangles * 3); renderer->SetInterpolation(0.f); } diff --git a/source/common/models/models_md3.cpp b/source/common/models/models_md3.cpp index 327cbff88..23e811928 100644 --- a/source/common/models/models_md3.cpp +++ b/source/common/models/models_md3.cpp @@ -345,7 +345,7 @@ int FMD3Model::FindFrame(const char* name, bool nodefault) // //=========================================================================== -void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) +void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) { if ((unsigned)frameno >= Frames.Size() || (unsigned)frameno2 >= Frames.Size()) return; @@ -375,7 +375,7 @@ void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int f } renderer->SetMaterial(surfaceSkin, false, translation); - renderer->SetupFrame(this, surf->vindex + frameno * surf->numVertices, surf->vindex + frameno2 * surf->numVertices, surf->numVertices, {}, -1); + renderer->SetupFrame(this, surf->vindex + frameno * surf->numVertices, surf->vindex + frameno2 * surf->numVertices, surf->numVertices, -1); renderer->DrawElements(surf->numTriangles * 3, surf->iindex * sizeof(unsigned int)); } renderer->SetInterpolation(0.f); diff --git a/source/common/models/models_obj.cpp b/source/common/models/models_obj.cpp index 43e89b1d2..0d9b6c951 100644 --- a/source/common/models/models_obj.cpp +++ b/source/common/models/models_obj.cpp @@ -630,7 +630,7 @@ int FOBJModel::FindFrame(const char* name, bool nodefault) * @param inter The amount to interpolate the two frames. * @param translation The translation for the skin */ -void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) +void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) { // Prevent the model from rendering if the frame number is < 0 if (frameno < 0 || frameno2 < 0) return; @@ -659,7 +659,7 @@ void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int f } renderer->SetMaterial(userSkin, false, translation); - renderer->SetupFrame(this, surf->vbStart, surf->vbStart, surf->numTris * 3, {}, -1); + renderer->SetupFrame(this, surf->vbStart, surf->vbStart, surf->numTris * 3, -1); renderer->DrawArrays(0, surf->numTris * 3); } } diff --git a/source/common/models/models_ue1.cpp b/source/common/models/models_ue1.cpp index 810659261..155e6d13f 100644 --- a/source/common/models/models_ue1.cpp +++ b/source/common/models/models_ue1.cpp @@ -232,7 +232,7 @@ int FUE1Model::FindFrame(const char* name, bool nodefault) return index; } -void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, const TArray& boneData, int boneStartPosition) +void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID* surfaceskinids, int boneStartPosition) { // the moment of magic if ( (frame < 0) || (frame2 < 0) || (frame >= numFrames) || (frame2 >= numFrames) ) return; @@ -263,7 +263,7 @@ void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int f // TODO: Handle per-group render styles and other flags once functions for it are implemented // Future note: poly renderstyles should always be enforced unless the actor itself has a style other than Normal renderer->SetMaterial(sskin,false,translation); - renderer->SetupFrame(this, vofs + frame * fsize, vofs + frame2 * fsize, vsize, {}, -1); + renderer->SetupFrame(this, vofs + frame * fsize, vofs + frame2 * fsize, vsize, -1); renderer->DrawArrays(0,vsize); vofs += vsize; } diff --git a/source/common/models/models_voxel.cpp b/source/common/models/models_voxel.cpp index e6cd5f837..9b6657183 100644 --- a/source/common/models/models_voxel.cpp +++ b/source/common/models/models_voxel.cpp @@ -400,9 +400,9 @@ float FVoxelModel::getAspectFactor(float stretch) // //=========================================================================== -void FVoxelModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID*, const TArray& boneData, int boneStartPosition) +void FVoxelModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, FTranslationID translation, const FTextureID*, int boneStartPosition) { renderer->SetMaterial(skin, true, translation); - renderer->SetupFrame(this, 0, 0, 0, {}, -1); + renderer->SetupFrame(this, 0, 0, 0, -1); renderer->DrawElements(mNumIndices, 0); } diff --git a/source/common/platform/win32/i_input.cpp b/source/common/platform/win32/i_input.cpp index 45a74fe0c..fb6ff300f 100644 --- a/source/common/platform/win32/i_input.cpp +++ b/source/common/platform/win32/i_input.cpp @@ -485,14 +485,6 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_ACTIVATEAPP: AppActive = (wParam == TRUE); - if (wParam || !i_pauseinbackground) - { - SetPriorityClass (GetCurrentProcess (), INGAME_PRIORITY_CLASS); - } - else if (!noidle && !(sysCallbacks.NetGame && sysCallbacks.NetGame())) - { - SetPriorityClass (GetCurrentProcess (), IDLE_PRIORITY_CLASS); - } S_SetSoundPaused (wParam); break; diff --git a/source/common/platform/win32/i_system.cpp b/source/common/platform/win32/i_system.cpp index caed820b0..c2615d51f 100644 --- a/source/common/platform/win32/i_system.cpp +++ b/source/common/platform/win32/i_system.cpp @@ -244,6 +244,9 @@ void CalculateCPUSpeed() // probably never use the performance statistics. min_diff = freq.LowPart * 11 / 200; + // just in case we were launched with a custom priority class, keep it + DWORD OldPriorityClass = GetPriorityClass(GetCurrentProcess()); + // Minimize the chance of task switching during the testing by going very // high priority. This is another reason to avoid timing for too long. SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS); @@ -258,7 +261,7 @@ void CalculateCPUSpeed() do { QueryPerformanceCounter(&count1); } while ((count1.QuadPart - count2.QuadPart) < min_diff); ClockCalibration.Unclock(); - SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); + SetPriorityClass(GetCurrentProcess(), OldPriorityClass); SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); PerfToSec = double(count1.QuadPart - count2.QuadPart) / (double(ClockCalibration.GetRawCounter()) * freq.QuadPart); diff --git a/source/common/rendering/hwrenderer/data/hw_bonebuffer.cpp b/source/common/rendering/hwrenderer/data/hw_bonebuffer.cpp index e6de05411..72bd71260 100644 --- a/source/common/rendering/hwrenderer/data/hw_bonebuffer.cpp +++ b/source/common/rendering/hwrenderer/data/hw_bonebuffer.cpp @@ -74,6 +74,7 @@ void BoneBuffer::Clear() int BoneBuffer::UploadBones(const TArray& bones) { + Map(); int totalsize = bones.Size(); if (totalsize > (int)mMaxUploadSize) { @@ -90,10 +91,12 @@ int BoneBuffer::UploadBones(const TArray& bones) if (thisindex + totalsize <= mBufferSize) { memcpy(mBufferPointer + thisindex * BONE_SIZE, bones.Data(), totalsize * BONE_SIZE); + Unmap(); return thisindex; } else { + Unmap(); return -1; // Buffer is full. Since it is being used live at the point of the upload we cannot do much here but to abort. } } diff --git a/source/common/rendering/r_videoscale.cpp b/source/common/rendering/r_videoscale.cpp index 8921d8980..51f2844d1 100644 --- a/source/common/rendering/r_videoscale.cpp +++ b/source/common/rendering/r_videoscale.cpp @@ -102,14 +102,14 @@ namespace float v_MinimumToFill2(uint32_t inwidth, uint32_t inheight) { // sx = screen x dimension, sy = same for y - float sx = (float)inwidth * 1.2f, sy = (float)inheight; + float sx = (float)inwidth * 1.2, sy = (float)inheight; static float lastsx = 0., lastsy = 0., result = 0.; if (lastsx != sx || lastsy != sy) { if (sx <= 0. || sy <= 0.) return 1.; // prevent x/0 error // set absolute minimum scale to fill the entire screen but get as close to 640x400 as possible - float ssx = (float)(VID_MIN_UI_WIDTH) / 1.2f / sx, ssy = (float)(VID_MIN_UI_HEIGHT) / sy; + float ssx = (float)(VID_MIN_UI_WIDTH) / 1.2 / sx, ssy = (float)(VID_MIN_UI_HEIGHT) / sy; result = (ssx < ssy) ? ssy : ssx; lastsx = sx; lastsy = sy; @@ -165,7 +165,7 @@ namespace { true, [](uint32_t Width, uint32_t Height)->uint32_t { return 1280; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 800; }, 1.2f, false }, // 4 - 1280x800 { true, [](uint32_t Width, uint32_t Height)->uint32_t { return vid_scale_customwidth; }, [](uint32_t Width, uint32_t Height)->uint32_t { return vid_scale_customheight; }, 1.0f, true }, // 5 - Custom { true, [](uint32_t Width, uint32_t Height)->uint32_t { return 320; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 200; }, 1.2f, false }, // 6 - 320x200 - { true, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillX2(Width, Height) * 1.2f; }, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillY2(Width, Height); }, 1.2f, false }, // 7 - Minimum Scale to Fill Entire Screen (1.2) + { true, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillX2(Width, Height) * 1.2; }, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillY2(Width, Height); }, 1.2f, false }, // 7 - Minimum Scale to Fill Entire Screen (1.2) }; bool isOutOfBounds(int x) { diff --git a/source/common/scripting/backend/codegen.cpp b/source/common/scripting/backend/codegen.cpp index 07ced853e..10dc29576 100644 --- a/source/common/scripting/backend/codegen.cpp +++ b/source/common/scripting/backend/codegen.cpp @@ -1842,7 +1842,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) { goto basereturn; } - else if (ctx.Version >= MakeVersion(4, 15, 0) && basex->ValueType == TypeNullPtr && (ValueType == TypeSpriteID || ValueType == TypeTextureID || ValueType == TypeTranslationID)) + else if (ctx.Version >= MakeVersion(4, 14, 1) && basex->ValueType == TypeNullPtr && (ValueType == TypeSpriteID || ValueType == TypeTextureID || ValueType == TypeTranslationID)) { delete basex; basex = new FxConstant(0, ScriptPosition); @@ -6783,11 +6783,8 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) { if (sym->mVersion <= ctx.Version) { - // Allow use of deprecated symbols in deprecated functions of the internal code. This is meant to allow deprecated code to remain as it was, - // even if it depends on some deprecated symbol. - // The main motivation here is to keep the deprecated static functions accessing the global level variable as they were. - // Print these only if debug output is active and at the highest verbosity level. - const bool internal = (ctx.Function->Variants[0].Flags & VARF_Deprecated) && fileSystem.GetFileContainer(ctx.Lump) == 0; + // Allow use of deprecated symbols in the internal code. + const bool internal = fileSystem.GetFileContainer(ctx.Lump) == 0; const FString &deprecationMessage = vsym->DeprecationMessage; ScriptPosition.Message(internal ? MSG_DEBUGMSG : MSG_WARNING, @@ -6877,8 +6874,12 @@ FxExpression *FxIdentifier::ResolveMember(FCompileContext &ctx, PContainerType * { if (sym->mVersion <= ctx.Version) { + // Allow use of deprecated symbols in internal code. + const bool internal = fileSystem.GetFileContainer(ctx.Lump) == 0; const FString &deprecationMessage = vsym->DeprecationMessage; - ScriptPosition.Message(MSG_WARNING, "Accessing deprecated member variable %s - deprecated since %d.%d.%d%s%s", sym->SymbolName.GetChars(), vsym->mVersion.major, vsym->mVersion.minor, vsym->mVersion.revision, + + ScriptPosition.Message(internal ? MSG_DEBUGMSG : MSG_WARNING, + "Accessing deprecated member variable %s - deprecated since %d.%d.%d%s%s", sym->SymbolName.GetChars(), vsym->mVersion.major, vsym->mVersion.minor, vsym->mVersion.revision, deprecationMessage.IsEmpty() ? "" : ", ", deprecationMessage.GetChars()); } } @@ -8883,7 +8884,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) return Self; } } - else if (ctx.Version >= MakeVersion(4, 15, 0) && Self->ValueType == TypeSound && MethodName == NAME_IsValid) + else if (ctx.Version >= MakeVersion(4, 14, 1) && Self->ValueType == TypeSound && MethodName == NAME_IsValid) { if (ArgList.Size() > 0) { @@ -8900,7 +8901,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) delete this; return x; } - else if (Self->ValueType == TypeTextureID || (ctx.Version >= MakeVersion(4, 15, 0) && (Self->ValueType == TypeTranslationID))) + else if (Self->ValueType == TypeTextureID || (ctx.Version >= MakeVersion(4, 14, 1) && (Self->ValueType == TypeTranslationID))) { if (MethodName == NAME_IsValid || MethodName == NAME_IsNull || MethodName == NAME_Exists || MethodName == NAME_SetInvalid || MethodName == NAME_SetNull) { @@ -8943,7 +8944,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) } } - else if (ctx.Version >= MakeVersion(4, 15, 0) && Self->ValueType == TypeSpriteID) + else if (ctx.Version >= MakeVersion(4, 14, 1) && Self->ValueType == TypeSpriteID) { if (MethodName == NAME_IsValid || MethodName == NAME_IsEmpty || MethodName == NAME_IsFixed || MethodName == NAME_IsKeep || MethodName == NAME_Exists @@ -9661,8 +9662,12 @@ bool FxVMFunctionCall::CheckAccessibility(const VersionInfo &ver) { if (Function->mVersion <= ver) { + // Allow use of deprecated symbols in internal code. + const bool internal = fileSystem.GetFileContainer(Function->OwningClass->mDefFileNo) == 0; const FString &deprecationMessage = Function->Variants[0].DeprecationMessage; - ScriptPosition.Message(MSG_WARNING, "Accessing deprecated function %s - deprecated since %d.%d.%d%s%s", Function->SymbolName.GetChars(), Function->mVersion.major, Function->mVersion.minor, Function->mVersion.revision, + + ScriptPosition.Message(internal ? MSG_DEBUGMSG : MSG_WARNING, + "Accessing deprecated function %s - deprecated since %d.%d.%d%s%s", Function->SymbolName.GetChars(), Function->mVersion.major, Function->mVersion.minor, Function->mVersion.revision, deprecationMessage.IsEmpty() ? "" : ", ", deprecationMessage.GetChars()); } } diff --git a/source/common/scripting/core/types.cpp b/source/common/scripting/core/types.cpp index b70783f3e..d99f7eb13 100644 --- a/source/common/scripting/core/types.cpp +++ b/source/common/scripting/core/types.cpp @@ -3231,12 +3231,11 @@ PFunctionPointer * NewFunctionPointer(PPrototype * proto, TArray && ar //========================================================================== PStruct::PStruct(FName name, PTypeBase *outer, bool isnative, int fileno) -: PContainerType(name, outer) +: PContainerType(name, outer, fileno) { mDescriptiveName.Format("%sStruct<%s>", isnative? "Native" : "", name.GetChars()); Size = 0; isNative = isnative; - mDefFileNo = fileno; } //========================================================================== diff --git a/source/common/scripting/core/types.h b/source/common/scripting/core/types.h index a092247de..f09ddb32b 100644 --- a/source/common/scripting/core/types.h +++ b/source/common/scripting/core/types.h @@ -253,13 +253,14 @@ class PContainerType : public PCompoundType public: PTypeBase *Outer = nullptr; // object this type is contained within FName TypeName = NAME_None; // this type's name + int mDefFileNo = 0; PContainerType() { mDescriptiveName = "ContainerType"; Flags |= TYPE_Container; } - PContainerType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name) + PContainerType(FName name, PTypeBase *outer, int fileno) : Outer(outer), TypeName(name), mDefFileNo(fileno) { mDescriptiveName = name.GetChars(); Flags |= TYPE_Container; @@ -648,7 +649,6 @@ public: // Some internal structs require explicit construction and destruction of fields the VM cannot handle directly so use these two functions for it. VMFunction *mConstructor = nullptr; VMFunction *mDestructor = nullptr; - int mDefFileNo; PField *AddField(FName name, PType *type, uint32_t flags=0) override; PField *AddNativeField(FName name, PType *type, size_t address, uint32_t flags = 0, int bitvalue = 0) override; @@ -681,7 +681,6 @@ class PClassType : public PContainerType public: PClass *Descriptor; PClassType *ParentType; - int mDefFileNo; PClassType(PClass *cls = nullptr, int fileno = 0); PField *AddField(FName name, PType *type, uint32_t flags = 0) override; diff --git a/source/common/scripting/interface/vmnatives.cpp b/source/common/scripting/interface/vmnatives.cpp index a798f1310..ca967c264 100644 --- a/source/common/scripting/interface/vmnatives.cpp +++ b/source/common/scripting/interface/vmnatives.cpp @@ -1796,3 +1796,16 @@ DEFINE_FIELD_NAMED_X(ScriptScanner, DScriptScanner, wrapped.Number, Number); DEFINE_FIELD_NAMED_X(ScriptScanner, DScriptScanner, wrapped.End, End); DEFINE_FIELD_NAMED_X(ScriptScanner, DScriptScanner, wrapped.Crossed, Crossed); DEFINE_FIELD_NAMED_X(ScriptScanner, DScriptScanner, wrapped.ParseError, ParseError); + +static int ValidateNameIndex(int index) +{ + return FName::IsValidName(index) ? index : 0; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DObject, ValidateNameIndex, ValidateNameIndex) +{ + PARAM_PROLOGUE; + PARAM_INT(index); + + ACTION_RETURN_INT(ValidateNameIndex(index)); +} diff --git a/source/common/utility/name.h b/source/common/utility/name.h index fe2424f45..8b4291d69 100644 --- a/source/common/utility/name.h +++ b/source/common/utility/name.h @@ -76,6 +76,8 @@ public: bool IsValidName() const { return (unsigned)Index < (unsigned)NameData.NumNames; } + static bool IsValidName(int index) { return index >= 0 && index < NameData.NumNames; } + // Note that the comparison operators compare the names' indices, not // their text, so they cannot be used to do a lexicographical sort. bool operator == (const FName &other) const { return Index == other.Index; } diff --git a/source/core/mainloop.cpp b/source/core/mainloop.cpp index 0b2b02a9f..c44444efb 100644 --- a/source/core/mainloop.cpp +++ b/source/core/mainloop.cpp @@ -93,6 +93,7 @@ #include "gameinput.h" CVAR(Bool, vid_activeinbackground, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CVAR(Bool, vid_lowerinbackground, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(Bool, r_ticstability, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Bool, vid_dontdowait, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) EXTERN_CVAR(Bool, cl_capfps) @@ -567,6 +568,9 @@ void TryRunTics (void) if (vid_dontdowait && ((vid_maxfps > 0) || (vid_vsync == true))) doWait = false; + if (!AppActive && vid_lowerinbackground) + doWait = true; + // get real tics if (doWait) {