diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 658b4b001..3ae8ba1c3 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -622,6 +622,7 @@ file( GLOB HEADER_FILES common/audio/sound/thirdparty/*.h common/audio/sound/*.h common/audio/music/*.h* + common/2d/*.h common/console/*.h common/utility/*.h common/engine/*.h @@ -751,9 +752,6 @@ set (PCH_SOURCES core/raze_music.cpp core/raze_sound.cpp - core/2d/v_2ddrawer.cpp - core/2d/v_draw.cpp - core/2d/v_drawtext.cpp core/2d/screentext.cpp core/console/c_console.cpp @@ -768,6 +766,9 @@ set (PCH_SOURCES common/audio/music/i_music.cpp common/audio/music/i_soundfont.cpp common/audio/music/music_config.cpp + common/2d/v_2ddrawer.cpp + common/2d/v_drawtext.cpp + common/2d/v_draw.cpp common/thirdparty/sfmt/SFMT.cpp common/fonts/singlelumpfont.cpp common/fonts/singlepicfont.cpp @@ -775,9 +776,10 @@ set (PCH_SOURCES common/fonts/font.cpp common/fonts/hexfont.cpp common/fonts/v_font.cpp + common/fonts/v_text.cpp common/textures/hw_ihwtexture.cpp common/textures/hw_material.cpp - common/fonts/v_text.cpp + common/textures/bitmap.cpp common/textures/m_png.cpp common/textures/texture.cpp @@ -1011,6 +1013,7 @@ include_directories( platform common/audio/sound common/audio/music + common/2d common/thirdparty common/textures common/textures/formats @@ -1139,6 +1142,7 @@ source_group("Common\\Audio\\Music" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_ source_group("Common\\Console" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/console/.+") source_group("Common\\Utility" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/utility/.+") source_group("Common\\Engine" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/engine/.+") +source_group("Common\\2D" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/2d/.+") source_group("Common\\Objects" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/objects/.+") source_group("Common\\Fonts" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/fonts/.+") source_group("Common\\File System" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/filesystem/.+") diff --git a/source/blood/src/globals.cpp b/source/blood/src/globals.cpp index b0543fda1..8da19385a 100644 --- a/source/blood/src/globals.cpp +++ b/source/blood/src/globals.cpp @@ -59,7 +59,7 @@ void _consoleSysMsg(const char* pzFormat, ...) { va_start(args, pzFormat); vsprintf(buffer, pzFormat, args); - Printf(OSDTEXT_RED "%s(%i): %s\n", _module, _line, buffer); + Printf(TEXTCOLOR_RED "%s(%i): %s\n", _module, _line, buffer); } END_BLD_NS diff --git a/source/blood/src/osdcmd.cpp b/source/blood/src/osdcmd.cpp index 8d3020a59..4652509b1 100644 --- a/source/blood/src/osdcmd.cpp +++ b/source/blood/src/osdcmd.cpp @@ -60,7 +60,7 @@ static int osdcmd_map(CCmdFuncPtr parm) if (!fileSystem.Lookup(filename, "MAP")) { - Printf(OSD_ERROR "map: file \"%s\" not found.\n", filename); + Printf(TEXTCOLOR_RED "map: file \"%s\" not found.\n", filename); return OSDCMD_OK; } @@ -237,7 +237,7 @@ static int osdcmd_levelwarp(CCmdFuncPtr parm) int m = atoi(parm->parms[1]); if (e == 0 || m == 0) { - Printf(OSD_ERROR "Invalid level!: E%sM%s\n", parm->parms[0], parm->parms[1]); + Printf(TEXTCOLOR_RED "Invalid level!: E%sM%s\n", parm->parms[0], parm->parms[1]); return OSDCMD_OK; } LevelWarp(e - 1, m - 1); diff --git a/source/build/include/build.h b/source/build/include/build.h index 82496f43c..d1cf94582 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -1296,4 +1296,35 @@ extern int32_t(*loadboard_replace)(const char *filename, char flags, vec3_t *dap extern void(*PolymostProcessVoxels_Callback)(void); #endif +class F2DDrawer; + +extern F2DDrawer twodgen; +extern F2DDrawer twodpsp; +extern F2DDrawer* twod; + +// This is for safely substituting the 2D drawer for a block of code. +class PspTwoDSetter +{ + F2DDrawer* old; +public: + PspTwoDSetter() + { + old = twod; + twod = &twodpsp; + } + ~PspTwoDSetter() + { + twod = old; + } + // Shadow Warrior fucked this up and draws the weapons in the same pass as the hud, meaning we have to switch this on and off depending on context. + void set() + { + twod = &twodpsp; + } + void clear() + { + twod = old; + } +}; + #endif // build_h_ diff --git a/source/build/src/animvpx.cpp b/source/build/src/animvpx.cpp index ca6cc4f6e..4b25e4df4 100644 --- a/source/build/src/animvpx.cpp +++ b/source/build/src/animvpx.cpp @@ -13,6 +13,7 @@ #include "textures.h" #include "bitmap.h" #include "v_draw.h" +#include "v_video.h" #undef UNUSED #define VPX_CODEC_DISABLE_COMPAT 1 diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index 7b4eed9ad..b367d0024 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -27,6 +27,7 @@ #include "stats.h" #include "menu.h" #include "version.h" +#include "earcut.hpp" #ifdef USE_OPENGL # include "hightile.h" @@ -2863,6 +2864,323 @@ killsprite: } +//========================================================================== +// +// +// +//========================================================================== + +void FillPolygon(int* rx1, int* ry1, int* xb1, int32_t npoints, int picnum, int palette, int shade, int props, const FVector2& xtex, const FVector2& ytex, const FVector2& otex, + int clipx1, int clipy1, int clipx2, int clipy2) +{ + //Convert int32_t to float (in-place) + TArray points(npoints, true); + using Point = std::pair; + std::vector> polygon; + std::vector* curPoly; + + polygon.resize(1); + curPoly = &polygon.back(); + + for (bssize_t i = 0; i < npoints; ++i) + { + auto X = ((float)rx1[i]) * (1.0f / 4096.f); + auto Y = ((float)ry1[i]) * (1.0f / 4096.f); + curPoly->push_back(std::make_pair(X, Y)); + if (xb1[i] < i && i < npoints - 1) + { + polygon.resize(polygon.size() + 1); + curPoly = &polygon.back(); + } + } + // Now make sure that the outer boundary is the first polygon by picking a point that's as much to the outside as possible. + int outer = 0; + float minx = FLT_MAX; + float miny = FLT_MAX; + for (size_t a = 0; a < polygon.size(); a++) + { + for (auto& pt : polygon[a]) + { + if (pt.first < minx || (pt.first == minx && pt.second < miny)) + { + minx = pt.first; + miny = pt.second; + outer = a; + } + } + } + if (outer != 0) std::swap(polygon[0], polygon[outer]); + auto indices = mapbox::earcut(polygon); + + int p = 0; + for (size_t a = 0; a < polygon.size(); a++) + { + for (auto& pt : polygon[a]) + { + FVector4 point = { pt.first, pt.second, float(pt.first * xtex.X + pt.second * ytex.X + otex.X), float(pt.first * xtex.Y + pt.second * ytex.Y + otex.Y) }; + points[p++] = point; + } + } + + int maskprops = (props >> 7) & DAMETH_MASKPROPS; + FRenderStyle rs = LegacyRenderStyles[STYLE_Translucent]; + double alpha = 1.; + if (maskprops > DAMETH_MASK) + { + rs = GetRenderStyle(0, maskprops == DAMETH_TRANS2); + alpha = GetAlphaFromBlend(maskprops, 0); + } + int translation = TRANSLATION(Translation_Remap + curbasepal, palette); + int light = clamp(scale((numshades - shade), 255, numshades), 0, 255); + PalEntry pe = PalEntry(uint8_t(alpha*255), light, light, light); + + twod->AddPoly(tileGetTexture(picnum), points.Data(), points.Size(), indices.data(), indices.size(), translation, pe, rs, clipx1, clipy1, clipx2, clipy2); +} + +void drawlinergb(int32_t x1, int32_t y1, int32_t x2, int32_t y2, PalEntry p) +{ + twod->AddLine(x1 / 4096.f, y1 / 4096.f, x2 / 4096.f, y2 / 4096.f, windowxy1.x, windowxy1.y, windowxy2.x, windowxy2.y, p); +} + +void drawlinergb(int32_t x1, int32_t y1, int32_t x2, int32_t y2, palette_t p) +{ + drawlinergb(x1, y1, x2, y2, PalEntry(p.r, p.g, p.b)); +} + +void renderDrawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint8_t col) +{ + drawlinergb(x1, y1, x2, y2, GPalette.BaseColors[GPalette.Remap[col]]); +} + + +//========================================================================== +// +// +// +//========================================================================== + + +#include "build.h" +#include "../src/engine_priv.h" + +//sx,sy center of sprite; screen coords*65536 +//z zoom*65536. > is zoomed in +//a angle (0 is default) +//dastat&1 1:translucence +//dastat&2 1:auto-scale mode (use 320*200 coordinates) +//dastat&4 1:y-flip +//dastat&8 1:don't clip to startumost/startdmost +//dastat&16 1:force point passed to be top-left corner, 0:Editart center +//dastat&32 1:reverse translucence +//dastat&64 1:non-masked, 0:masked +//dastat&128 1:draw all pages (permanent - no longer used) +//cx1,... clip window (actual screen coords) + +//========================================================================== +// +// INTERNAL helper function for classic/polymost dorotatesprite +// sxptr, sxptr, z: in/out +// ret_yxaspect, ret_xyaspect: out +// +//========================================================================== + +static int32_t dorotspr_handle_bit2(int32_t* sxptr, int32_t* syptr, int32_t* z, int32_t dastat, int32_t cx1_plus_cx2, int32_t cy1_plus_cy2) +{ + if ((dastat & RS_AUTO) == 0) + { + if (!(dastat & RS_STRETCH) && 4 * ydim <= 3 * xdim) + { + return (10 << 16) / 12; + } + else + { + return xyaspect; + } + } + else + { + // dastat&2: Auto window size scaling + const int32_t oxdim = xdim; + const int32_t oydim = ydim; + int32_t xdim = oxdim; // SHADOWS global + int32_t ydim = oydim; + + int32_t zoomsc, sx = *sxptr, sy = *syptr; + int32_t ouryxaspect = yxaspect, ourxyaspect = xyaspect; + + sy += rotatesprite_y_offset; + + if (!(dastat & RS_STRETCH) && 4 * ydim <= 3 * xdim) + { + if ((dastat & RS_ALIGN_MASK) && (dastat & RS_ALIGN_MASK) != RS_ALIGN_MASK) + sx += NEGATE_ON_CONDITION(scale(120 << 16, xdim, ydim) - (160 << 16), !(dastat & RS_ALIGN_R)); + + if ((dastat & RS_ALIGN_MASK) == RS_ALIGN_MASK) + ydim = scale(xdim, 3, 4); + else + xdim = scale(ydim, 4, 3); + + ouryxaspect = (12 << 16) / 10; + ourxyaspect = (10 << 16) / 12; + } + + ouryxaspect = mulscale16(ouryxaspect, rotatesprite_yxaspect); + ourxyaspect = divscale16(ourxyaspect, rotatesprite_yxaspect); + + // screen center to s[xy], 320<<16 coords. + const int32_t normxofs = sx - (320 << 15), normyofs = sy - (200 << 15); + + // nasty hacks go here + if (!(dastat & RS_NOCLIP)) + { + const int32_t twice_midcx = cx1_plus_cx2 + 2; + + // screen x center to sx1, scaled to viewport + const int32_t scaledxofs = scale(normxofs, scale(xdimen, xdim, oxdim), 320); + + sx = ((twice_midcx) << 15) + scaledxofs; + + zoomsc = xdimenscale; //= scale(xdimen,yxaspect,320); + zoomsc = mulscale16(zoomsc, rotatesprite_yxaspect); + + if ((dastat & RS_ALIGN_MASK) == RS_ALIGN_MASK) + zoomsc = scale(zoomsc, ydim, oydim); + + sy = ((cy1_plus_cy2 + 2) << 15) + mulscale16(normyofs, zoomsc); + } + else + { + //If not clipping to startmosts, & auto-scaling on, as a + //hard-coded bonus, scale to full screen instead + + sx = (xdim << 15) + 32768 + scale(normxofs, xdim, 320); + + zoomsc = scale(xdim, ouryxaspect, 320); + sy = (ydim << 15) + 32768 + mulscale16(normyofs, zoomsc); + + if ((dastat & RS_ALIGN_MASK) == RS_ALIGN_MASK) + sy += (oydim - ydim) << 15; + else + sx += (oxdim - xdim) << 15; + + if (dastat & RS_CENTERORIGIN) + sx += oxdim << 15; + } + + *sxptr = sx; + *syptr = sy; + *z = mulscale16(*z, zoomsc); + + return ourxyaspect; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void twod_rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, + int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend, + int32_t clipx1, int32_t clipy1, int32_t clipx2, int32_t clipy2, FTexture* pic, int basepal) +{ + F2DDrawer::RenderCommand dg = {}; + int method = 0; + + dg.mTranslationId = TRANSLATION(Translation_Remap + basepal, dapalnum); + dg.mType = F2DDrawer::DrawTypeTriangles; + if (clipx1 > 0 || clipy1 > 0 || clipx2 < screen->GetWidth() - 1 || clipy2 < screen->GetHeight() - 1) + { + dg.mScissor[0] = clipx1; + dg.mScissor[1] = clipy1; + dg.mScissor[2] = clipx2 + 1; + dg.mScissor[3] = clipy2 + 1; + dg.mFlags |= F2DDrawer::DTF_Scissor; + } + + if (!(dastat & RS_NOMASK)) + { + if (dastat & RS_TRANS1) + method |= (dastat & RS_TRANS2) ? DAMETH_TRANS2 : DAMETH_TRANS1; + else + method |= DAMETH_MASK; + + dg.mRenderStyle = GetRenderStyle(dablend, (dastat & RS_TRANS2) ? 1 : 0); + } + else + { + dg.mRenderStyle = LegacyRenderStyles[STYLE_Normal]; + } + + dg.mTexture = pic ? pic : tileGetTexture(picnum); + dg.mVertCount = 4; + dg.mVertIndex = (int)twod->mVertices.Reserve(4); + auto ptr = &twod->mVertices[dg.mVertIndex]; + float drawpoly_alpha = daalpha * (1.0f / 255.0f); + float alpha = GetAlphaFromBlend(method, dablend) * (1.f - drawpoly_alpha); // Hmmm... + int light = clamp(scale((numshades - dashade), 255, numshades), 0, 255); + auto p = PalEntry((uint8_t)(alpha * 255), light, light, light); + + vec2_t const siz = { dg.mTexture->GetDisplayWidth(), dg.mTexture->GetDisplayHeight() }; + vec2_16_t ofs = { 0, 0 }; + + if (!(dastat & RS_TOPLEFT)) + { + if (!pic) + { + ofs = { int16_t(tileLeftOffset(picnum) + (siz.x >> 1)), + int16_t(tileTopOffset(picnum) + (siz.y >> 1)) }; + } + else + { + ofs = { int16_t((siz.x >> 1)), + int16_t((siz.y >> 1)) }; + } + } + + if (dastat & RS_YFLIP) + ofs.y = siz.y - ofs.y; + + int32_t aspectcorrect = dorotspr_handle_bit2(&sx, &sy, &z, dastat, clipx1 + clipx2, clipy1 + clipy2); + + int32_t cosang = mulscale14(sintable[(a + 512) & 2047], z); + int32_t cosang2 = cosang; + int32_t sinang = mulscale14(sintable[a & 2047], z); + int32_t sinang2 = sinang; + + if ((dastat & RS_AUTO) || (!(dastat & RS_NOCLIP))) // Don't aspect unscaled perms + { + cosang2 = mulscale16(cosang2, aspectcorrect); + sinang2 = mulscale16(sinang2, aspectcorrect); + } + + int cx0 = sx - ofs.x * cosang2 + ofs.y * sinang2; + int cy0 = sy - ofs.x * sinang - ofs.y * cosang; + + int cx1 = cx0 + siz.x * cosang2; + int cy1 = cy0 + siz.x * sinang; + + int cx3 = cx0 - siz.y * sinang2; + int cy3 = cy0 + siz.y * cosang; + + int cx2 = cx1 + cx3 - cx0; + int cy2 = cy1 + cy3 - cy0; + + float y = (dastat & RS_YFLIP) ? 1.f : 0.f; + + ptr->Set(cx0 / 65536.f, cy0 / 65536.f, 0.f, 0.f, y, p); ptr++; + ptr->Set(cx1 / 65536.f, cy1 / 65536.f, 0.f, 1.f, y, p); ptr++; + ptr->Set(cx2 / 65536.f, cy2 / 65536.f, 0.f, 1.f, 1.f - y, p); ptr++; + ptr->Set(cx3 / 65536.f, cy3 / 65536.f, 0.f, 0.f, 1.f - y, p); ptr++; + dg.mIndexIndex = twod->mIndices.Size(); + dg.mIndexCount += 6; + twod->AddIndices(dg.mVertIndex, 6, 0, 1, 2, 0, 2, 3); + twod->AddCommand(&dg); + +} + + // // fillpolygon (internal) // @@ -2882,7 +3200,7 @@ static void renderFillPolygon(int32_t npoints) ytex.Y = ((float)y2) * (-1.f / 4294967296.f); otex.X = (fxdim * xtex.X + fydim * ytex.X) * -0.5f + fglobalposx * (1.f / 4294967296.f); otex.Y = (fxdim * xtex.Y + fydim * ytex.Y) * -0.5f - fglobalposy * (1.f / 4294967296.f); - twod->FillPolygon(rx1, ry1, xb1, npoints, globalpicnum, globalpal, globalshade, globalorientation, xtex, ytex, otex, windowxy1.x, windowxy1.y, windowxy2.x, windowxy2.y); + FillPolygon(rx1, ry1, xb1, npoints, globalpicnum, globalpal, globalshade, globalorientation, xtex, ytex, otex, windowxy1.x, windowxy1.y, windowxy2.x, windowxy2.y); } // @@ -3750,7 +4068,7 @@ void videoNextPage(void) // Ideally this stuff should be moved out of videoNextPage so that all those busy loops won't call UI overlays at all. recursion = true; M_Drawer(); - FStat::PrintStat(); + FStat::PrintStat(twod); C_DrawConsole(); recursion = false; } @@ -5035,7 +5353,7 @@ void rotatesprite_(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, } // We must store all calls in the 2D drawer so that the backend can operate on a clean 3D view. - twod->rotatesprite(sx, sy, z, a, picnum, dashade, dapalnum, dastat, daalpha, dablend, cx1, cy1, cx2, cy2, tex, basepal); + twod_rotatesprite(sx, sy, z, a, picnum, dashade, dapalnum, dastat, daalpha, dablend, cx1, cy1, cx2, cy2, tex, basepal); // RS_PERM code was removed because the current backend supports only one page that needs to be redrawn each frame in which case the perm list was skipped anyway. } diff --git a/source/core/2d/v_2ddrawer.cpp b/source/common/2d/v_2ddrawer.cpp similarity index 56% rename from source/core/2d/v_2ddrawer.cpp rename to source/common/2d/v_2ddrawer.cpp index 1d2eef0c3..39398b800 100644 --- a/source/core/2d/v_2ddrawer.cpp +++ b/source/common/2d/v_2ddrawer.cpp @@ -1,49 +1,183 @@ -// scissi -//--------------------------------------------------------------------------- -// -// Copyright(C) 2016-2018 Christoph Oelckers -// All rights reserved. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 2 of the License, or -// (at your option) any later version. -// -// 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 Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with this program. If not, see http://www.gnu.org/licenses/ -// -//-------------------------------------------------------------------------- -// /* ** v_2ddrawer.h ** Device independent 2D draw list ** -**/ +**--------------------------------------------------------------------------- +** Copyright 2016-2020 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ #include -#include "c_cvars.h" -#include "v_2ddrawer.h" -#include "renderstyle.h" -#include "drawparms.h" -#include "vectors.h" -#include "gamecvars.h" -#include "earcut.hpp" -#include "palettecontainer.h" -//#include "doomtype.h" #include "templates.h" -//#include "r_utility.h" -#include "v_video.h" -//#include "g_levellocals.h" -//#include "vm.h" +#include "vm.h" +#include "c_cvars.h" +#include "v_draw.h" +#include "fcolormap.h" -F2DDrawer twodpsp; -F2DDrawer twodgen; -F2DDrawer *twod = &twodgen; +F2DDrawer* twod; + +EXTERN_CVAR(Float, transsouls) + +IMPLEMENT_CLASS(DShape2DTransform, false, false) + +static void Shape2DTransform_Clear(DShape2DTransform* self) +{ + self->transform.Identity(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DShape2DTransform, Clear, Shape2DTransform_Clear) +{ + PARAM_SELF_PROLOGUE(DShape2DTransform); + Shape2DTransform_Clear(self); + return 0; +} + +static void Shape2DTransform_Rotate(DShape2DTransform* self, double angle) +{ + self->transform = DMatrix3x3::Rotate2D(DEG2RAD(angle)) * self->transform; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DShape2DTransform, Rotate, Shape2DTransform_Rotate) +{ + PARAM_SELF_PROLOGUE(DShape2DTransform); + PARAM_FLOAT(angle); + Shape2DTransform_Rotate(self, angle); + return 0; +} + +static void Shape2DTransform_Scale(DShape2DTransform* self, double x, double y) +{ + self->transform = DMatrix3x3::Scale2D(DVector2(x, y)) * self->transform; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DShape2DTransform, Scale, Shape2DTransform_Scale) +{ + PARAM_SELF_PROLOGUE(DShape2DTransform); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + Shape2DTransform_Scale(self, x, y); + return 0; +} + +static void Shape2DTransform_Translate(DShape2DTransform* self, double x, double y) +{ + self->transform = DMatrix3x3::Translate2D(DVector2(x, y)) * self->transform; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DShape2DTransform, Translate, Shape2DTransform_Translate) +{ + PARAM_SELF_PROLOGUE(DShape2DTransform); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + Shape2DTransform_Translate(self, x, y); + return 0; +} + +IMPLEMENT_CLASS(DShape2D, false, false) + +static void Shape2D_SetTransform(DShape2D* self, DShape2DTransform *transform) +{ + self->transform = transform->transform; + self->dirty = true; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DShape2D, SetTransform, Shape2D_SetTransform) +{ + PARAM_SELF_PROLOGUE(DShape2D); + PARAM_OBJECT(transform, DShape2DTransform); + Shape2D_SetTransform(self, transform); + return 0; +} + +static void Shape2D_Clear(DShape2D* self, int which) +{ + if (which & C_Verts) + { + self->mVertices.Clear(); + self->dirty = true; + } + if (which & C_Coords) self->mCoords.Clear(); + if (which & C_Indices) self->mIndices.Clear(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DShape2D, Clear, Shape2D_Clear) +{ + PARAM_SELF_PROLOGUE(DShape2D); + PARAM_INT(which); + Shape2D_Clear(self, which); + return 0; +} + +static void Shape2D_PushVertex(DShape2D* self, double x, double y) +{ + self->mVertices.Push(DVector2(x, y)); + self->dirty = true; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DShape2D, PushVertex, Shape2D_PushVertex) +{ + PARAM_SELF_PROLOGUE(DShape2D); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + Shape2D_PushVertex(self, x, y); + return 0; +} + +static void Shape2D_PushCoord(DShape2D* self, double u, double v) +{ + self->mCoords.Push(DVector2(u, v)); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DShape2D, PushCoord, Shape2D_PushCoord) +{ + PARAM_SELF_PROLOGUE(DShape2D); + PARAM_FLOAT(u); + PARAM_FLOAT(v); + Shape2D_PushCoord(self, u, v); + return 0; +} + +static void Shape2D_PushTriangle(DShape2D* self, int a, int b, int c) +{ + self->mIndices.Push(a); + self->mIndices.Push(b); + self->mIndices.Push(c); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DShape2D, PushTriangle, Shape2D_PushTriangle) +{ + PARAM_SELF_PROLOGUE(DShape2D); + PARAM_INT(a); + PARAM_INT(b); + PARAM_INT(c); + Shape2D_PushTriangle(self, a, b, c); + return 0; +} //========================================================================== // @@ -106,7 +240,11 @@ bool F2DDrawer::SetStyle(FTexture *tex, DrawParms &parms, PalEntry &vertexcolor, float alpha; bool stencilling; - if (style.Flags & STYLEF_Alpha1) + if (style.Flags & STYLEF_TransSoulsAlpha) + { + alpha = transsouls; + } + else if (style.Flags & STYLEF_Alpha1) { alpha = 1; } @@ -192,6 +330,16 @@ bool F2DDrawer::SetStyle(FTexture *tex, DrawParms &parms, PalEntry &vertexcolor, { quad.mDrawMode = TM_INVERSE; } + + if (parms.specialcolormap != nullptr) + { // draw with an invulnerability or similar colormap. + + auto scm = parms.specialcolormap; + + quad.mSpecialColormap[0] = PalEntry(255, int(scm->ColorizeStart[0] * 127.5f), int(scm->ColorizeStart[1] * 127.5f), int(scm->ColorizeStart[2] * 127.5f)); + quad.mSpecialColormap[1] = PalEntry(255, int(scm->ColorizeEnd[0] * 127.5f), int(scm->ColorizeEnd[1] * 127.5f), int(scm->ColorizeEnd[2] * 127.5f)); + quad.mColor1 = 0; // this disables the color overlay. + } quad.mDesaturate = parms.desaturate; } // apply the element's own color. This is being blended with anything that came before. @@ -260,10 +408,15 @@ void F2DDrawer::AddTexture(FTexture *img, DrawParms &parms) dg.mType = DrawTypeTriangles; dg.mVertCount = 4; dg.mTexture = img; + if (img->isWarped()) dg.mFlags |= DTF_Wrap; - dg.mRemapIndex = parms.TranslationId; + dg.mTranslationId = 0; SetStyle(img, parms, vertexcolor, dg); + if (!img->isHardwareCanvas() && parms.TranslationId != -1) + { + dg.mTranslationId = parms.TranslationId; + } u1 = parms.srcx; v1 = parms.srcy; u2 = parms.srcx + parms.srcwidth; @@ -319,6 +472,211 @@ void F2DDrawer::AddTexture(FTexture *img, DrawParms &parms) // //========================================================================== +void F2DDrawer::AddShape( FTexture *img, DShape2D *shape, DrawParms &parms ) +{ + // [MK] bail out if vertex/coord array sizes are mismatched + if ( shape->mVertices.Size() != shape->mCoords.Size() ) + ThrowAbortException(X_OTHER, "Mismatch in vertex/coord count: %u != %u", shape->mVertices.Size(), shape->mCoords.Size()); + + if (parms.style.BlendOp == STYLEOP_None) return; // not supposed to be drawn. + + PalEntry vertexcolor; + + RenderCommand dg; + + dg.mType = DrawTypeTriangles; + dg.mVertCount = shape->mVertices.Size(); + dg.mFlags |= DTF_Wrap; + dg.mTexture = img; + + dg.mTranslationId = 0; + SetStyle(img, parms, vertexcolor, dg); + + if (!img->isHardwareCanvas() && parms.TranslationId != -1) + dg.mTranslationId = parms.TranslationId; + + if (shape->dirty) { + if (shape->mVertices.Size() != shape->mTransformedVertices.Size()) + shape->mTransformedVertices.Resize(shape->mVertices.Size()); + for (int i = 0; i < dg.mVertCount; i++) { + shape->mTransformedVertices[i] = (shape->transform * DVector3(shape->mVertices[i], 1.0)).XY(); + } + shape->dirty = false; + } + + double minx = 16383, miny = 16383, maxx = -16384, maxy = -16384; + for ( int i=0; imTransformedVertices[i].X < minx ) minx = shape->mTransformedVertices[i].X; + if ( shape->mTransformedVertices[i].Y < miny ) miny = shape->mTransformedVertices[i].Y; + if ( shape->mTransformedVertices[i].X > maxx ) maxx = shape->mTransformedVertices[i].X; + if ( shape->mTransformedVertices[i].Y > maxy ) maxy = shape->mTransformedVertices[i].Y; + } + if (minx < (double)parms.lclip || miny < (double)parms.uclip || maxx >(double)parms.rclip || maxy >(double)parms.dclip) + { + dg.mScissor[0] = parms.lclip; + dg.mScissor[1] = parms.uclip; + dg.mScissor[2] = parms.rclip; + dg.mScissor[3] = parms.dclip; + dg.mFlags |= DTF_Scissor; + } + else + memset(dg.mScissor, 0, sizeof(dg.mScissor)); + + dg.mVertIndex = (int)mVertices.Reserve(dg.mVertCount); + TwoDVertex *ptr = &mVertices[dg.mVertIndex]; + for ( int i=0; imTransformedVertices[i].X, shape->mTransformedVertices[i].Y, 0, shape->mCoords[i].X, shape->mCoords[i].Y, vertexcolor); + dg.mIndexIndex = mIndices.Size(); + dg.mIndexCount += shape->mIndices.Size(); + for ( int i=0; imIndices.Size()); i+=3 ) + { + // [MK] bail out if any indices are out of bounds + for ( int j=0; j<3; j++ ) + { + if ( shape->mIndices[i+j] < 0 ) + ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Triangle %u index %u is negative: %i\n", i/3, j, shape->mIndices[i+j]); + if ( shape->mIndices[i+j] >= dg.mVertCount ) + ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "Triangle %u index %u: %u, max: %u\n", i/3, j, shape->mIndices[i+j], dg.mVertCount-1); + } + AddIndices(dg.mVertIndex, 3, shape->mIndices[i], shape->mIndices[i+1], shape->mIndices[i+2]); + } + AddCommand(&dg); +} + +//========================================================================== +// +// +// +//========================================================================== + +void F2DDrawer::AddPoly(FTexture *texture, FVector2 *points, int npoints, + double originx, double originy, double scalex, double scaley, + DAngle rotation, const FColormap &colormap, PalEntry flatcolor, double fadelevel, + uint32_t *indices, size_t indexcount) +{ + + RenderCommand poly; + + poly.mType = DrawTypeTriangles; + poly.mTexture = texture; + poly.mRenderStyle = DefaultRenderStyle(); + poly.mFlags |= DTF_Wrap; + poly.mDesaturate = colormap.Desaturation; + + PalEntry color0; + double invfade = 1. - fadelevel; + + color0.r = uint8_t(colormap.LightColor.r * invfade); + color0.g = uint8_t(colormap.LightColor.g * invfade); + color0.b = uint8_t(colormap.LightColor.b * invfade); + color0.a = 255; + + poly.mColor1.a = 0; + poly.mColor1.r = uint8_t(colormap.FadeColor.r * fadelevel); + poly.mColor1.g = uint8_t(colormap.FadeColor.g * fadelevel); + poly.mColor1.b = uint8_t(colormap.FadeColor.b * fadelevel); + + bool dorotate = rotation != 0; + + float cosrot = (float)cos(rotation.Radians()); + float sinrot = (float)sin(rotation.Radians()); + + float uscale = float(1.f / (texture->GetDisplayWidth() * scalex)); + float vscale = float(1.f / (texture->GetDisplayHeight() * scaley)); + float ox = float(originx); + float oy = float(originy); + + poly.mVertCount = npoints; + poly.mVertIndex = (int)mVertices.Reserve(npoints); + for (int i = 0; i < npoints; ++i) + { + float u = points[i].X - 0.5f - ox; + float v = points[i].Y - 0.5f - oy; + if (dorotate) + { + float t = u; + u = t * cosrot - v * sinrot; + v = v * cosrot + t * sinrot; + } + mVertices[poly.mVertIndex+i].Set(points[i].X, points[i].Y, 0, u*uscale, v*vscale, color0); + } + poly.mIndexIndex = mIndices.Size(); + + if (indices == nullptr || indexcount == 0) + { + poly.mIndexCount += (npoints - 2) * 3; + for (int i = 2; i < npoints; ++i) + { + AddIndices(poly.mVertIndex, 3, 0, i - 1, i); + } + } + else + { + poly.mIndexCount += (int)indexcount; + int addr = mIndices.Reserve(indexcount); + for (size_t i = 0; i < indexcount; i++) + { + mIndices[addr + i] = poly.mVertIndex + indices[i]; + } + } + + AddCommand(&poly); +} + +//========================================================================== +// +// +// +//========================================================================== + +void F2DDrawer::AddPoly(FTexture* img, FVector4* vt, size_t vtcount, unsigned int* ind, size_t idxcount, int translation, PalEntry color, FRenderStyle style, int clipx1, int clipy1, int clipx2, int clipy2) +{ + RenderCommand dg = {}; + int method = 0; + + dg.mType = DrawTypeTriangles; + if (clipx1 > 0 || clipy1 > 0 || clipx2 < GetWidth() - 1 || clipy2 < GetHeight() - 1) + { + dg.mScissor[0] = clipx1; + dg.mScissor[1] = clipy1; + dg.mScissor[2] = clipx2 + 1; + dg.mScissor[3] = clipy2 + 1; + dg.mFlags |= DTF_Scissor; + } + + dg.mTexture = img; + dg.mTranslationId = translation; + dg.mColor1 = color; + dg.mVertCount = (int)vtcount; + dg.mVertIndex = (int)mVertices.Reserve(vtcount); + dg.mRenderStyle = LegacyRenderStyles[STYLE_Translucent]; + dg.mIndexIndex = mIndices.Size(); + dg.mFlags |= DTF_Wrap; + auto ptr = &mVertices[dg.mVertIndex]; + + for (size_t i=0;iSet(vt[i].X, vt[i].Y, 0.f, vt[i].Z, vt[i].W, color); + ptr++; + } + + dg.mIndexIndex = mIndices.Size(); + mIndices.Reserve(idxcount); + for (size_t i = 0; i < idxcount; i++) + { + mIndices[dg.mIndexIndex + i] = ind[i] + dg.mVertIndex; + } + dg.mIndexCount = (int)idxcount; + AddCommand(&dg); +} + +//========================================================================== +// +// +// +//========================================================================== + void F2DDrawer::AddFlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin) { float fU1, fU2, fV1, fV2; @@ -388,7 +746,7 @@ void F2DDrawer::AddColorOnlyQuad(int x1, int y1, int w, int h, PalEntry color, F void F2DDrawer::ClearScreen(PalEntry color) { - AddColorOnlyQuad(0, 0, screen->GetWidth(), screen->GetHeight(), color); + AddColorOnlyQuad(0, 0, GetWidth(), GetHeight(), color); } //========================================================================== @@ -404,7 +762,7 @@ void F2DDrawer::AddLine(float x1, float y1, float x2, float y2, int clipx1, int RenderCommand dg; - if (clipx1 > 0 || clipy1 > 0 || clipx2 < screen->GetWidth()- 1 || clipy2 < screen->GetHeight() - 1) + if (clipx1 > 0 || clipy1 > 0 || clipx2 < GetWidth()- 1 || clipy2 < GetHeight() - 1) { dg.mScissor[0] = clipx1; dg.mScissor[1] = clipy1; @@ -497,360 +855,3 @@ void F2DDrawer::Clear() mData.Clear(); mIsFirstPass = true; } - -//========================================================================== -// -// -// -//========================================================================== - - -#include "build.h" -#include "../src/engine_priv.h" - -//sx,sy center of sprite; screen coords*65536 -//z zoom*65536. > is zoomed in -//a angle (0 is default) -//dastat&1 1:translucence -//dastat&2 1:auto-scale mode (use 320*200 coordinates) -//dastat&4 1:y-flip -//dastat&8 1:don't clip to startumost/startdmost -//dastat&16 1:force point passed to be top-left corner, 0:Editart center -//dastat&32 1:reverse translucence -//dastat&64 1:non-masked, 0:masked -//dastat&128 1:draw all pages (permanent - no longer used) -//cx1,... clip window (actual screen coords) - -//========================================================================== -// -// INTERNAL helper function for classic/polymost dorotatesprite -// sxptr, sxptr, z: in/out -// ret_yxaspect, ret_xyaspect: out -// -//========================================================================== - -static int32_t dorotspr_handle_bit2(int32_t* sxptr, int32_t* syptr, int32_t* z, int32_t dastat, int32_t cx1_plus_cx2, int32_t cy1_plus_cy2) -{ - if ((dastat & RS_AUTO) == 0) - { - if (!(dastat & RS_STRETCH) && 4 * ydim <= 3 * xdim) - { - return (10 << 16) / 12; - } - else - { - return xyaspect; - } - } - else - { - // dastat&2: Auto window size scaling - const int32_t oxdim = xdim; - const int32_t oydim = ydim; - int32_t xdim = oxdim; // SHADOWS global - int32_t ydim = oydim; - - int32_t zoomsc, sx = *sxptr, sy = *syptr; - int32_t ouryxaspect = yxaspect, ourxyaspect = xyaspect; - - sy += rotatesprite_y_offset; - - if (!(dastat & RS_STRETCH) && 4 * ydim <= 3 * xdim) - { - if ((dastat & RS_ALIGN_MASK) && (dastat & RS_ALIGN_MASK) != RS_ALIGN_MASK) - sx += NEGATE_ON_CONDITION(scale(120 << 16, xdim, ydim) - (160 << 16), !(dastat & RS_ALIGN_R)); - - if ((dastat & RS_ALIGN_MASK) == RS_ALIGN_MASK) - ydim = scale(xdim, 3, 4); - else - xdim = scale(ydim, 4, 3); - - ouryxaspect = (12 << 16) / 10; - ourxyaspect = (10 << 16) / 12; - } - - ouryxaspect = mulscale16(ouryxaspect, rotatesprite_yxaspect); - ourxyaspect = divscale16(ourxyaspect, rotatesprite_yxaspect); - - // screen center to s[xy], 320<<16 coords. - const int32_t normxofs = sx - (320 << 15), normyofs = sy - (200 << 15); - - // nasty hacks go here - if (!(dastat & RS_NOCLIP)) - { - const int32_t twice_midcx = cx1_plus_cx2 + 2; - - // screen x center to sx1, scaled to viewport - const int32_t scaledxofs = scale(normxofs, scale(xdimen, xdim, oxdim), 320); - - sx = ((twice_midcx) << 15) + scaledxofs; - - zoomsc = xdimenscale; //= scale(xdimen,yxaspect,320); - zoomsc = mulscale16(zoomsc, rotatesprite_yxaspect); - - if ((dastat & RS_ALIGN_MASK) == RS_ALIGN_MASK) - zoomsc = scale(zoomsc, ydim, oydim); - - sy = ((cy1_plus_cy2 + 2) << 15) + mulscale16(normyofs, zoomsc); - } - else - { - //If not clipping to startmosts, & auto-scaling on, as a - //hard-coded bonus, scale to full screen instead - - sx = (xdim << 15) + 32768 + scale(normxofs, xdim, 320); - - zoomsc = scale(xdim, ouryxaspect, 320); - sy = (ydim << 15) + 32768 + mulscale16(normyofs, zoomsc); - - if ((dastat & RS_ALIGN_MASK) == RS_ALIGN_MASK) - sy += (oydim - ydim) << 15; - else - sx += (oxdim - xdim) << 15; - - if (dastat & RS_CENTERORIGIN) - sx += oxdim << 15; - } - - *sxptr = sx; - *syptr = sy; - *z = mulscale16(*z, zoomsc); - - return ourxyaspect; - } -} - -//========================================================================== -// -// -// -//========================================================================== - -void F2DDrawer::rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, - int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend, - int32_t clipx1, int32_t clipy1, int32_t clipx2, int32_t clipy2, FTexture *pic, int basepal) -{ - RenderCommand dg = {}; - int method = 0; - - dg.mType = pic? DrawTypeTriangles : DrawTypeRotateSprite; - if (clipx1 > 0 || clipy1 > 0 || clipx2 < screen->GetWidth() - 1 || clipy2 < screen->GetHeight() - 1) - { - dg.mScissor[0] = clipx1; - dg.mScissor[1] = clipy1; - dg.mScissor[2] = clipx2 + 1; - dg.mScissor[3] = clipy2 + 1; - dg.mFlags |= DTF_Scissor; - } - - if (!(dastat & RS_NOMASK)) - { - if (dastat & RS_TRANS1) - method |= (dastat & RS_TRANS2) ? DAMETH_TRANS2 : DAMETH_TRANS1; - else - method |= DAMETH_MASK; - - dg.mRenderStyle = GetRenderStyle(dablend, (dastat & RS_TRANS2) ? 1 : 0); - } - else - { - dg.mRenderStyle = LegacyRenderStyles[STYLE_Normal]; - } - - PalEntry p = 0xffffffff; - dg.mTexture = pic? pic : tileGetTexture(picnum); - dg.mRemapIndex = dapalnum | (basepal << 8) | (dashade << 16); - dg.mVertCount = 4; - dg.mVertIndex = (int)mVertices.Reserve(4); - auto ptr = &mVertices[dg.mVertIndex]; - float drawpoly_alpha = daalpha * (1.0f / 255.0f); - float alpha = GetAlphaFromBlend(method, dablend) * (1.f - drawpoly_alpha); // Hmmm... - p.a = (uint8_t)(alpha * 255); - - vec2_t const siz = { dg.mTexture->GetDisplayWidth(), dg.mTexture->GetDisplayHeight() }; - vec2_16_t ofs = { 0, 0 }; - - if (!(dastat & RS_TOPLEFT)) - { - if (!pic) - { - ofs = { int16_t(tileLeftOffset(picnum) + (siz.x >> 1)), - int16_t(tileTopOffset(picnum) + (siz.y >> 1)) }; - } - else - { - ofs = { int16_t((siz.x >> 1)), - int16_t((siz.y >> 1)) }; - } - } - - if (dastat & RS_YFLIP) - ofs.y = siz.y - ofs.y; - - int32_t aspectcorrect = dorotspr_handle_bit2(&sx, &sy, &z, dastat, clipx1 + clipx2, clipy1 + clipy2); - - int32_t cosang = mulscale14(sintable[(a + 512) & 2047], z); - int32_t cosang2 = cosang; - int32_t sinang = mulscale14(sintable[a & 2047], z); - int32_t sinang2 = sinang; - - if ((dastat & RS_AUTO) || (!(dastat & RS_NOCLIP))) // Don't aspect unscaled perms - { - cosang2 = mulscale16(cosang2, aspectcorrect); - sinang2 = mulscale16(sinang2, aspectcorrect); - } - - int cx0 = sx - ofs.x * cosang2 + ofs.y * sinang2; - int cy0 = sy - ofs.x * sinang - ofs.y * cosang; - - int cx1 = cx0 + siz.x * cosang2; - int cy1 = cy0 + siz.x * sinang; - - int cx3 = cx0 - siz.y * sinang2; - int cy3 = cy0 + siz.y * cosang; - - int cx2 = cx1 + cx3 - cx0; - int cy2 = cy1 + cy3 - cy0; - - float y = (dastat & RS_YFLIP) ? 1.f : 0.f; - - ptr->Set(cx0 / 65536.f, cy0 / 65536.f, 0.f, 0.f, y, p); ptr++; - ptr->Set(cx1 / 65536.f, cy1 / 65536.f, 0.f, 1.f, y, p); ptr++; - ptr->Set(cx2 / 65536.f, cy2 / 65536.f, 0.f, 1.f, 1.f-y, p); ptr++; - ptr->Set(cx3 / 65536.f, cy3 / 65536.f, 0.f, 0.f, 1.f-y, p); ptr++; - dg.mIndexIndex = mIndices.Size(); - dg.mIndexCount += 6; - AddIndices(dg.mVertIndex, 6, 0, 1, 2, 0, 2, 3); - AddCommand(&dg); - -} - -//========================================================================== -// -// -// -//========================================================================== - -void F2DDrawer::AddPoly(FTexture* img, FVector4* vt, size_t vtcount, unsigned int* ind, size_t idxcount, int palette, int shade, int maskprops, int clipx1, int clipy1, int clipx2, int clipy2) -{ - RenderCommand dg = {}; - int method = 0; - - dg.mType = DrawTypeRotateSprite; - if (clipx1 > 0 || clipy1 > 0 || clipx2 < screen->GetWidth() - 1 || clipy2 < screen->GetHeight() - 1) - { - dg.mScissor[0] = clipx1; - dg.mScissor[1] = clipy1; - dg.mScissor[2] = clipx2 + 1; - dg.mScissor[3] = clipy2 + 1; - dg.mFlags |= DTF_Scissor; - } - - PalEntry p = 0xffffffff; - if (maskprops > DAMETH_MASK) - { - dg.mRenderStyle = GetRenderStyle(0, maskprops == DAMETH_TRANS2); - p.a = (uint8_t)(GetAlphaFromBlend(maskprops, 0) * 255); - } - dg.mTexture = img; - dg.mRemapIndex = palette | (shade << 16); - dg.mVertCount = vtcount; - dg.mVertIndex = (int)mVertices.Reserve(vtcount); - dg.mRenderStyle = LegacyRenderStyles[STYLE_Translucent]; - dg.mIndexIndex = mIndices.Size(); - dg.mFlags |= DTF_Wrap; - auto ptr = &mVertices[dg.mVertIndex]; - - for (size_t i=0;iSet(vt[i].X, vt[i].Y, 0.f, vt[i].Z, vt[i].W, p); - ptr++; - } - - dg.mIndexIndex = mIndices.Size(); - mIndices.Reserve(idxcount); - for (size_t i = 0; i < idxcount; i++) - { - mIndices[dg.mIndexIndex + i] = ind[i] + dg.mVertIndex; - } - dg.mIndexCount = idxcount; - AddCommand(&dg); -} - -//========================================================================== -// -// -// -//========================================================================== - -void F2DDrawer::FillPolygon(int *rx1, int *ry1, int *xb1, int32_t npoints, int picnum, int palette, int shade, int props, const FVector2& xtex, const FVector2& ytex, const FVector2 &otex, - int clipx1, int clipy1, int clipx2, int clipy2) -{ - //Convert int32_t to float (in-place) - TArray points(npoints, true); - using Point = std::pair; - std::vector> polygon; - std::vector* curPoly; - - polygon.resize(1); - curPoly = &polygon.back(); - - for (bssize_t i = 0; i < npoints; ++i) - { - auto X = ((float)rx1[i]) * (1.0f / 4096.f); - auto Y = ((float)ry1[i]) * (1.0f / 4096.f); - curPoly->push_back(std::make_pair(X, Y)); - if (xb1[i] < i && i < npoints - 1) - { - polygon.resize(polygon.size() + 1); - curPoly = &polygon.back(); - } - } - // Now make sure that the outer boundary is the first polygon by picking a point that's as much to the outside as possible. - int outer = 0; - float minx = FLT_MAX; - float miny = FLT_MAX; - for (size_t a = 0; a < polygon.size(); a++) - { - for (auto& pt : polygon[a]) - { - if (pt.first < minx || (pt.first == minx && pt.second < miny)) - { - minx = pt.first; - miny = pt.second; - outer = a; - } - } - } - if (outer != 0) std::swap(polygon[0], polygon[outer]); - auto indices = mapbox::earcut(polygon); - - int p = 0; - for (size_t a = 0; a < polygon.size(); a++) - { - for (auto& pt : polygon[a]) - { - FVector4 point = { pt.first, pt.second, float(pt.first * xtex.X + pt.second * ytex.X + otex.X), float(pt.first * xtex.Y + pt.second * ytex.Y + otex.Y) }; - points[p++] = point; - } - } - - AddPoly(tileGetTexture(picnum), points.Data(), points.Size(), indices.data(), indices.size(), palette, shade, (props >> 7)& DAMETH_MASKPROPS, clipx1, clipy1, clipx2, clipy2); -} - -void drawlinergb(int32_t x1, int32_t y1, int32_t x2, int32_t y2, PalEntry p) -{ - twod->AddLine(x1 / 4096.f, y1 / 4096.f, x2 / 4096.f, y2 / 4096.f, windowxy1.x, windowxy1.y, windowxy2.x, windowxy2.y, p); -} - -void drawlinergb(int32_t x1, int32_t y1, int32_t x2, int32_t y2, palette_t p) -{ - drawlinergb(x1, y1, x2, y2, PalEntry(p.r, p.g, p.b)); -} - -void renderDrawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint8_t col) -{ - drawlinergb(x1, y1, x2, y2, GPalette.BaseColors[GPalette.Remap[col]]); -} - - diff --git a/source/core/2d/v_2ddrawer.h b/source/common/2d/v_2ddrawer.h similarity index 63% rename from source/core/2d/v_2ddrawer.h rename to source/common/2d/v_2ddrawer.h index 46d96875f..a7abb6c5b 100644 --- a/source/core/2d/v_2ddrawer.h +++ b/source/common/2d/v_2ddrawer.h @@ -5,10 +5,53 @@ #include "vectors.h" #include "textures.h" #include "renderstyle.h" +#include "dobject.h" struct DrawParms; -class FFont; +struct FColormap; +class DShape2DTransform : public DObject +{ + +DECLARE_CLASS(DShape2DTransform, DObject) +public: + DShape2DTransform() + { + transform.Identity(); + } + DMatrix3x3 transform; +}; + +// intermediate struct for shape drawing + +enum EClearWhich +{ + C_Verts = 1, + C_Coords = 2, + C_Indices = 4, +}; + +class DShape2D : public DObject +{ + + DECLARE_CLASS(DShape2D,DObject) +public: + DShape2D() + { + transform.Identity(); + } + + TArray mIndices; + TArray mVertices; + TArray mCoords; + + DMatrix3x3 transform; + + // dirty stores whether we need to re-apply the transformation + // otherwise it uses the cached values + bool dirty = true; + TArray mTransformedVertices; +}; struct F2DPolygons { @@ -24,8 +67,6 @@ struct F2DPolygons }; - - class F2DDrawer { public: @@ -84,7 +125,7 @@ public: int mIndexCount; FTexture *mTexture; - int mRemapIndex; + int mTranslationId; PalEntry mSpecialColormap[2]; int mScissor[4]; int mDesaturate; @@ -103,7 +144,7 @@ public: { return mTexture == other.mTexture && mType == other.mType && - mRemapIndex == other.mRemapIndex && + mTranslationId == other.mTranslationId && mSpecialColormap[0].d == other.mSpecialColormap[0].d && mSpecialColormap[1].d == other.mSpecialColormap[1].d && !memcmp(mScissor, other.mScissor, sizeof(mScissor)) && @@ -119,70 +160,54 @@ public: TArray mIndices; TArray mVertices; TArray mData; + int Width, Height; + bool isIn2D; +public: + int fullscreenautoaspect = 0; + int cliptop = -1, clipleft = -1, clipwidth = -1, clipheight = -1; int AddCommand(const RenderCommand *data); void AddIndices(int firstvert, int count, ...); +private: void AddIndices(int firstvert, TArray &v); bool SetStyle(FTexture *tex, DrawParms &parms, PalEntry &color0, RenderCommand &quad); void SetColorOverlay(PalEntry color, float alpha, PalEntry &vertexcolor, PalEntry &overlaycolor); public: void AddTexture(FTexture *img, DrawParms &parms); - void AddPoly(FTexture* img, FVector4 *vt, size_t vtcount, unsigned int *ind, size_t idxcount, int palette, int shade, int maskprops, int clipx1, int clipy1, int clipx2, int clipy2); + void AddShape(FTexture *img, DShape2D *shape, DrawParms &parms); + void AddPoly(FTexture *texture, FVector2 *points, int npoints, + double originx, double originy, double scalex, double scaley, + DAngle rotation, const FColormap &colormap, PalEntry flatcolor, double lightlevel, uint32_t *indices, size_t indexcount); + void AddPoly(FTexture* img, FVector4 *vt, size_t vtcount, unsigned int *ind, size_t idxcount, int translation, PalEntry color, FRenderStyle style, int clipx1, int clipy1, int clipx2, int clipy2); void FillPolygon(int* rx1, int* ry1, int* xb1, int32_t npoints, int picnum, int palette, int shade, int props, const FVector2& xtex, const FVector2& ytex, const FVector2& otex, int clipx1, int clipy1, int clipx2, int clipy2); - void AddFlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin); + void AddFlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin = false); void AddColorOnlyQuad(int left, int top, int width, int height, PalEntry color, FRenderStyle *style = nullptr); void ClearScreen(PalEntry color = 0xff000000); + void AddDim(PalEntry color, float damount, int x1, int y1, int w, int h); + void AddClear(int left, int top, int right, int bottom, int palcolor, uint32_t color); - void AddLine(float x1, float y1, float x2, float y2, uint32_t color, uint8_t alpha = 255); + void AddLine(float x1, float y1, float x2, float y2, int cx, int cy, int cx2, int cy2, uint32_t color, uint8_t alpha = 255); void AddThickLine(int x1, int y1, int x2, int y2, double thickness, uint32_t color, uint8_t alpha = 255); void AddPixel(int x1, int y1, uint32_t color); - void rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, - int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend, - int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, FTexture *pic = nullptr, int basepal = 0); - void Clear(); + int GetWidth() const { return Width; } + int GetHeight() const { return Height; } + void SetSize(int w, int h) { Width = w; Height = h; } + void Begin() { isIn2D = true; } + void End() { isIn2D = false; } + bool HasBegun2D() { return isIn2D; } + + void ClearClipRect() { clipleft = cliptop = 0; clipwidth = clipheight = -1; } + void SetClipRect(int x, int y, int w, int h); + void GetClipRect(int* x, int* y, int* w, int* h); bool mIsFirstPass = true; }; -extern F2DDrawer twodgen; -extern F2DDrawer twodpsp; -extern F2DDrawer* twod; - -// This is for safely substituting the 2D drawer for a block of code. -class PspTwoDSetter -{ - F2DDrawer* old; -public: - PspTwoDSetter() - { - old = twod; - twod = &twodpsp; - } - ~PspTwoDSetter() - { - twod = old; - } - // Shadow Warrior fucked this up and draws the weapons in the same pass as the hud, meaning we have to switch this on and off depending on context. - void set() - { - twod = &twodpsp; - } - void clear() - { - twod = old; - } -}; - -void DrawTexture(F2DDrawer* drawer, FTexture* img, double x, double y, int tags_first, ...); -void DrawChar(F2DDrawer* drawer, FFont* font, int normalcolor, double x, double y, int character, int tag_first, ...); -void DrawText(F2DDrawer* drawer, FFont* font, int normalcolor, double x, double y, const char* string, int tag_first, ...); -void DrawText(F2DDrawer* drawer, FFont* font, int normalcolor, double x, double y, const char32_t* string, int tag_first, ...); -void DrawFrame(F2DDrawer* twod, PalEntry color, int left, int top, int width, int height, int thickness); #endif diff --git a/source/common/2d/v_draw.cpp b/source/common/2d/v_draw.cpp new file mode 100644 index 000000000..a70d47e5f --- /dev/null +++ b/source/common/2d/v_draw.cpp @@ -0,0 +1,1384 @@ +/* +** v_draw.cpp +** Draw patches and blocks to a canvas +** +**--------------------------------------------------------------------------- +** Copyright 1998-2008 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include +#include +#include "v_draw.h" +#include "vm.h" +#include "templates.h" +#include "texturemanager.h" +#include "r_videoscale.h" +#include "c_cvars.h" + +EXTERN_CVAR(Int, vid_aspect) +EXTERN_CVAR(Int, uiscale) + +// Helper for ActiveRatio and CheckRatio. Returns the forced ratio type, or -1 if none. +int ActiveFakeRatio(int width, int height) +{ + int fakeratio = -1; + if ((vid_aspect >= 1) && (vid_aspect <= 6)) + { + // [SP] User wants to force aspect ratio; let them. + fakeratio = int(vid_aspect); + if (fakeratio == 3) + { + fakeratio = 0; + } + else if (fakeratio == 5) + { + fakeratio = 3; + } + } + return fakeratio; +} + +// Active screen ratio based on cvars and size +float ActiveRatio(int width, int height, float* trueratio) +{ + static float forcedRatioTypes[] = + { + 4 / 3.0f, + 16 / 9.0f, + 16 / 10.0f, + 17 / 10.0f, + 5 / 4.0f, + 17 / 10.0f, + 21 / 9.0f + }; + + float ratio = width / (float)height; + int fakeratio = ActiveFakeRatio(width, height); + + if (trueratio) + *trueratio = ratio; + return (fakeratio != -1) ? forcedRatioTypes[fakeratio] : (ratio / ViewportPixelAspect()); +} + + +bool AspectTallerThanWide(float aspect) +{ + return aspect < 1.333f; +} + +int AspectBaseWidth(float aspect) +{ + return (int)round(240.0f * aspect * 3.0f); +} + +int AspectBaseHeight(float aspect) +{ + if (!AspectTallerThanWide(aspect)) + return (int)round(200.0f * (320.0f / (AspectBaseWidth(aspect) / 3.0f)) * 3.0f); + else + return (int)round((200.0f * (4.0f / 3.0f)) / aspect * 3.0f); +} + +double AspectPspriteOffset(float aspect) +{ + if (!AspectTallerThanWide(aspect)) + return 0.0; + else + return ((4.0 / 3.0) / aspect - 1.0) * 97.5; +} + +int AspectMultiplier(float aspect) +{ + if (!AspectTallerThanWide(aspect)) + return (int)round(320.0f / (AspectBaseWidth(aspect) / 3.0f) * 48.0f); + else + return (int)round(200.0f / (AspectBaseHeight(aspect) / 3.0f) * 48.0f); +} + +int GetUIScale(F2DDrawer *drawer, int altval) +{ + int scaleval; + if (altval > 0) scaleval = altval; + else if (uiscale == 0) + { + // Default should try to scale to 640x400 + int vscale = drawer->GetHeight() / 400; + int hscale = drawer->GetWidth() / 640; + scaleval = clamp(vscale, 1, hscale); + } + else scaleval = uiscale; + + // block scales that result in something larger than the current screen. + int vmax = drawer->GetHeight() / 200; + int hmax = drawer->GetWidth() / 320; + int max = MAX(vmax, hmax); + return MAX(1,MIN(scaleval, max)); +} + +// The new console font is twice as high, so the scaling calculation must factor that in. +int GetConScale(F2DDrawer* drawer, int altval) +{ + int scaleval; + if (altval > 0) scaleval = (altval+1) / 2; + else if (uiscale == 0) + { + // Default should try to scale to 640x400 + int vscale = drawer->GetHeight() / 800; + int hscale = drawer->GetWidth() / 1280; + scaleval = clamp(vscale, 1, hscale); + } + else scaleval = (uiscale+1) / 2; + + // block scales that result in something larger than the current screen. + int vmax = drawer->GetHeight() / 400; + int hmax = drawer->GetWidth() / 640; + int max = MAX(vmax, hmax); + return MAX(1, MIN(scaleval, max)); +} + + +// [RH] Stretch values to make a 320x200 image best fit the screen +// without using fractional steppings +int CleanXfac, CleanYfac; + +// [RH] Effective screen sizes that the above scale values give you +int CleanWidth, CleanHeight; + +// Above minus 1 (or 1, if they are already 1) +int CleanXfac_1, CleanYfac_1, CleanWidth_1, CleanHeight_1; + + +//========================================================================== +// +// Internal texture drawing function +// +//========================================================================== + +void DrawTexture(F2DDrawer *drawer, FTexture* img, double x, double y, int tags_first, ...) +{ + Va_List tags; + va_start(tags.list, tags_first); + DrawParms parms; + + bool res = ParseDrawTextureTags(drawer, img, x, y, tags_first, tags, &parms, false); + va_end(tags.list); + if (!res) + { + return; + } + drawer->AddTexture(img, parms); +} + +//========================================================================== +// +// ZScript texture drawing function +// +//========================================================================== + +int ListGetInt(VMVa_List &tags); + +static void DrawTexture(F2DDrawer *drawer, FTexture *img, double x, double y, VMVa_List &args) +{ + DrawParms parms; + uint32_t tag = ListGetInt(args); + bool res = ParseDrawTextureTags(drawer, img, x, y, tag, args, &parms, false); + if (!res) return; + drawer->AddTexture(img, parms); +} + +DEFINE_ACTION_FUNCTION(_Screen, DrawTexture) +{ + PARAM_PROLOGUE; + PARAM_INT(texid); + PARAM_BOOL(animate); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + + PARAM_VA_POINTER(va_reginfo) // Get the hidden type information array + + if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); + + FTexture *tex = TexMan.ByIndex(texid, animate); + VMVa_List args = { param + 4, 0, numparam - 5, va_reginfo + 4 }; + DrawTexture(twod, tex, x, y, args); + return 0; +} + +//========================================================================== +// +// ZScript arbitrary textured shape drawing functions +// +//========================================================================== + +void DrawShape(F2DDrawer *drawer, FTexture *img, DShape2D *shape, int tags_first, ...) +{ + Va_List tags; + va_start(tags.list, tags_first); + DrawParms parms; + + bool res = ParseDrawTextureTags(drawer, img, 0, 0, tags_first, tags, &parms, false); + va_end(tags.list); + if (!res) return; + drawer->AddShape(img, shape, parms); +} + +void DrawShape(F2DDrawer *drawer, FTexture *img, DShape2D *shape, VMVa_List &args) +{ + DrawParms parms; + uint32_t tag = ListGetInt(args); + + bool res = ParseDrawTextureTags(drawer, img, 0, 0, tag, args, &parms, false); + if (!res) return; + drawer->AddShape(img, shape, parms); +} + +DEFINE_ACTION_FUNCTION(_Screen, DrawShape) +{ + PARAM_PROLOGUE; + PARAM_INT(texid); + PARAM_BOOL(animate); + PARAM_POINTER(shape, DShape2D); + + PARAM_VA_POINTER(va_reginfo) // Get the hidden type information array + + if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); + + FTexture *tex = TexMan.ByIndex(texid, animate); + VMVa_List args = { param + 3, 0, numparam - 4, va_reginfo + 3 }; + + DrawShape(twod, tex, shape, args); + return 0; +} + +//========================================================================== +// +// Clipping rect +// +//========================================================================== + +void F2DDrawer::SetClipRect(int x, int y, int w, int h) +{ + clipleft = clamp(x, 0, GetWidth()); + clipwidth = clamp(w, -1, GetWidth() - x); + cliptop = clamp(y, 0, GetHeight()); + clipheight = clamp(h, -1, GetHeight() - y); +} + +DEFINE_ACTION_FUNCTION(_Screen, SetClipRect) +{ + PARAM_PROLOGUE; + PARAM_INT(x); + PARAM_INT(y); + PARAM_INT(w); + PARAM_INT(h); + twod->SetClipRect(x, y, w, h); + return 0; +} + +DEFINE_ACTION_FUNCTION(_Screen, ClearClipRect) +{ + PARAM_PROLOGUE; + twod->ClearClipRect(); + return 0; +} + +void F2DDrawer::GetClipRect(int *x, int *y, int *w, int *h) +{ + if (x) *x = clipleft; + if (y) *y = cliptop; + if (w) *w = clipwidth; + if (h) *h = clipheight; +} + +DEFINE_ACTION_FUNCTION(_Screen, GetClipRect) +{ + PARAM_PROLOGUE; + int x, y, w, h; + twod->GetClipRect(&x, &y, &w, &h); + if (numret > 0) ret[0].SetInt(x); + if (numret > 1) ret[1].SetInt(y); + if (numret > 2) ret[2].SetInt(w); + if (numret > 3) ret[3].SetInt(h); + return MIN(numret, 4); +} + +//========================================================================== +// +// Draw parameter parsing +// +//========================================================================== + +bool SetTextureParms(F2DDrawer * drawer, DrawParms *parms, FTexture *img, double xx, double yy) +{ + auto GetWidth = [=]() { return drawer->GetWidth(); }; + auto GetHeight = [=]() {return drawer->GetHeight(); }; + if (img != NULL) + { + parms->x = xx; + parms->y = yy; + parms->texwidth = img->GetDisplayWidthDouble(); + parms->texheight = img->GetDisplayHeightDouble(); + if (parms->top == INT_MAX || parms->fortext) + { + parms->top = img->GetDisplayTopOffset(); + } + if (parms->left == INT_MAX || parms->fortext) + { + parms->left = img->GetDisplayLeftOffset(); + } + if (parms->destwidth == INT_MAX || parms->fortext) + { + parms->destwidth = img->GetDisplayWidthDouble(); + } + if (parms->destheight == INT_MAX || parms->fortext) + { + parms->destheight = img->GetDisplayHeightDouble(); + } + + switch (parms->cleanmode) + { + default: + break; + + case DTA_Clean: + parms->x = (parms->x - 160.0) * CleanXfac + (GetWidth() * 0.5); + parms->y = (parms->y - 100.0) * CleanYfac + (GetHeight() * 0.5); + parms->destwidth = parms->texwidth * CleanXfac; + parms->destheight = parms->texheight * CleanYfac; + break; + + case DTA_CleanNoMove: + parms->destwidth = parms->texwidth * CleanXfac; + parms->destheight = parms->texheight * CleanYfac; + break; + + case DTA_CleanNoMove_1: + parms->destwidth = parms->texwidth * CleanXfac_1; + parms->destheight = parms->texheight * CleanYfac_1; + break; + + case DTA_Fullscreen: + case DTA_FullscreenEx: + { + double aspect; + double srcwidth = img->GetDisplayWidthDouble(); + double srcheight = img->GetDisplayHeightDouble(); + int autoaspect = parms->fsscalemode; + aspect = autoaspect == 0 || (srcwidth == 320 && srcheight == 200) || (srcwidth == 640 && srcheight == 400)? 1.333 : srcwidth / srcheight; + parms->x = parms->y = 0; + parms->keepratio = true; + auto screenratio = ActiveRatio(GetWidth(), GetHeight()); + if (autoaspect == 3) + { + if (screenratio >= aspect || aspect < 1.4) autoaspect = 1; // screen is wider than the image -> pillarbox it. 4:3 images must also be pillarboxes if the screen is taller than the image + else if (screenratio > 1.32) autoaspect = 2; // on anything 4:3 and wider crop the sides of the image. + else + { + // special case: Crop image to 4:3 and then letterbox this. This avoids too much cropping on narrow windows. + double width4_3 = srcheight * (4. / 3.); + parms->destwidth = (double)GetWidth() * srcwidth / width4_3; + parms->destheight = GetHeight() * screenratio * (3. / 4.); // use 4:3 for the image + parms->y = (GetHeight() - parms->destheight) / 2; + parms->x = -(srcwidth - width4_3) / 2; + return false; // Do not call VirtualToRealCoords for this! + } + } + + if ((screenratio > aspect) ^ (autoaspect == 2)) + { + // pillarboxed or vertically cropped (i.e. scale to height) + parms->destheight = GetHeight(); + parms->destwidth =GetWidth() * aspect / screenratio; + parms->x = (GetWidth() - parms->destwidth) / 2; + } + else + { + // letterboxed or horizontally cropped (i.e. scale to width) + parms->destwidth = GetWidth(); + parms->destheight = GetHeight() * screenratio / aspect; + parms->y = (GetHeight() - parms->destheight) / 2; + } + return false; // Do not call VirtualToRealCoords for this! + } + + case DTA_HUDRules: + case DTA_HUDRulesC: + { + // Note that this has been deprecated and become non-functional. The HUD should be drawn by the status bar. + bool xright = parms->x < 0; + bool ybot = parms->y < 0; + DVector2 scale = { 1., 1. }; + + parms->x *= scale.X; + if (parms->cleanmode == DTA_HUDRulesC) + parms->x += GetWidth() * 0.5; + else if (xright) + parms->x = GetWidth() + parms->x; + parms->y *= scale.Y; + if (ybot) + parms->y = GetHeight() + parms->y; + parms->destwidth = parms->texwidth * scale.X; + parms->destheight = parms->texheight * scale.Y; + break; + } + } + if (parms->virtWidth != GetWidth() || parms->virtHeight != GetHeight()) + { + VirtualToRealCoords(drawer, parms->x, parms->y, parms->destwidth, parms->destheight, + parms->virtWidth, parms->virtHeight, parms->virtBottom, !parms->keepratio); + } + } + + return false; +} + +//========================================================================== +// +// template helpers +// +//========================================================================== + +static void ListEnd(Va_List &tags) +{ + va_end(tags.list); +} + +static int ListGetInt(Va_List &tags) +{ + return va_arg(tags.list, int); +} + +static inline double ListGetDouble(Va_List &tags) +{ + return va_arg(tags.list, double); +} + +static inline FSpecialColormap * ListGetSpecialColormap(Va_List &tags) +{ + return va_arg(tags.list, FSpecialColormap *); +} + +static void ListEnd(VMVa_List &tags) +{ +} + +int ListGetInt(VMVa_List &tags) +{ + if (tags.curindex < tags.numargs) + { + if (tags.reginfo[tags.curindex] == REGT_INT) + { + return tags.args[tags.curindex++].i; + } + ThrowAbortException(X_OTHER, "Invalid parameter in draw function, int expected"); + } + return TAG_DONE; +} + +static inline double ListGetDouble(VMVa_List &tags) +{ + if (tags.curindex < tags.numargs) + { + if (tags.reginfo[tags.curindex] == REGT_FLOAT) + { + return tags.args[tags.curindex++].f; + } + if (tags.reginfo[tags.curindex] == REGT_INT) + { + return tags.args[tags.curindex++].i; + } + ThrowAbortException(X_OTHER, "Invalid parameter in draw function, float expected"); + } + return 0; +} + +static inline FSpecialColormap * ListGetSpecialColormap(VMVa_List &tags) +{ + ThrowAbortException(X_OTHER, "Invalid tag in draw function"); + return nullptr; +} + +//========================================================================== +// +// Main taglist parsing +// +//========================================================================== + +template +bool ParseDrawTextureTags(F2DDrawer *drawer, FTexture *img, double x, double y, uint32_t tag, T& tags, DrawParms *parms, bool fortext) +{ + INTBOOL boolval; + int intval; + bool translationset = false; + bool fillcolorset = false; + + if (!fortext) + { + if (img == NULL || !img->isValid()) + { + ListEnd(tags); + return false; + } + } + + // Do some sanity checks on the coordinates. + if (x < -16383 || x > 16383 || y < -16383 || y > 16383) + { + ListEnd(tags); + return false; + } + + parms->fortext = fortext; + parms->windowleft = 0; + parms->windowright = INT_MAX; + parms->dclip = drawer->GetHeight(); + parms->uclip = 0; + parms->lclip = 0; + parms->rclip = drawer->GetWidth(); + parms->left = INT_MAX; + parms->top = INT_MAX; + parms->destwidth = INT_MAX; + parms->destheight = INT_MAX; + parms->Alpha = 1.f; + parms->fillcolor = -1; + parms->TranslationId = -1; + parms->colorOverlay = 0; + parms->alphaChannel = false; + parms->flipX = false; + parms->flipY = false; + parms->color = 0xffffffff; + //parms->shadowAlpha = 0; + parms->shadowColor = 0; + parms->virtWidth = drawer->GetWidth(); + parms->virtHeight = drawer->GetHeight(); + parms->keepratio = false; + parms->style.BlendOp = 255; // Dummy "not set" value + parms->masked = true; + parms->bilinear = false; + parms->specialcolormap = NULL; + parms->desaturate = 0; + parms->cleanmode = DTA_Base; + parms->scalex = parms->scaley = 1; + parms->cellx = parms->celly = 0; + parms->maxstrlen = INT_MAX; + parms->virtBottom = false; + parms->srcx = 0.; + parms->srcy = 0.; + parms->srcwidth = 1.; + parms->srcheight = 1.; + parms->burn = false; + parms->monospace = EMonospacing::Off; + parms->spacing = 0; + + // Parse the tag list for attributes. (For floating point attributes, + // consider that the C ABI dictates that all floats be promoted to + // doubles when passed as function arguments.) + while (tag != TAG_DONE) + { + switch (tag) + { + default: + ListGetInt(tags); + break; + + case DTA_DestWidth: + assert(fortext == false); + if (fortext) return false; + parms->cleanmode = DTA_Base; + parms->destwidth = ListGetInt(tags); + break; + + case DTA_DestWidthF: + assert(fortext == false); + if (fortext) return false; + parms->cleanmode = DTA_Base; + parms->destwidth = ListGetDouble(tags); + break; + + case DTA_DestHeight: + assert(fortext == false); + if (fortext) return false; + parms->cleanmode = DTA_Base; + parms->destheight = ListGetInt(tags); + break; + + case DTA_DestHeightF: + assert(fortext == false); + if (fortext) return false; + parms->cleanmode = DTA_Base; + parms->destheight = ListGetDouble(tags); + break; + + case DTA_Clean: + boolval = ListGetInt(tags); + if (boolval) + { + parms->scalex = 1; + parms->scaley = 1; + parms->cleanmode = tag; + } + break; + + case DTA_CleanNoMove: + boolval = ListGetInt(tags); + if (boolval) + { + parms->scalex = CleanXfac; + parms->scaley = CleanYfac; + parms->cleanmode = tag; + } + break; + + case DTA_CleanNoMove_1: + boolval = ListGetInt(tags); + if (boolval) + { + parms->scalex = CleanXfac_1; + parms->scaley = CleanYfac_1; + parms->cleanmode = tag; + } + break; + + case DTA_320x200: + boolval = ListGetInt(tags); + if (boolval) + { + parms->cleanmode = DTA_Base; + parms->scalex = 1; + parms->scaley = 1; + parms->virtWidth = 320; + parms->virtHeight = 200; + } + break; + + case DTA_Bottom320x200: + boolval = ListGetInt(tags); + if (boolval) + { + parms->cleanmode = DTA_Base; + parms->scalex = 1; + parms->scaley = 1; + parms->virtWidth = 320; + parms->virtHeight = 200; + } + parms->virtBottom = true; + break; + + case DTA_HUDRules: + intval = ListGetInt(tags); + parms->cleanmode = intval == HUD_HorizCenter ? DTA_HUDRulesC : DTA_HUDRules; + break; + + case DTA_VirtualWidth: + parms->cleanmode = DTA_Base; + parms->virtWidth = ListGetInt(tags); + break; + + case DTA_VirtualWidthF: + parms->cleanmode = DTA_Base; + parms->virtWidth = ListGetDouble(tags); + break; + + case DTA_VirtualHeight: + parms->cleanmode = DTA_Base; + parms->virtHeight = ListGetInt(tags); + break; + + case DTA_VirtualHeightF: + parms->cleanmode = DTA_Base; + parms->virtHeight = ListGetDouble(tags); + break; + + case DTA_Fullscreen: + + boolval = ListGetInt(tags); + if (boolval) + { + assert(fortext == false); + if (img == NULL) return false; + parms->cleanmode = DTA_Fullscreen; + parms->fsscalemode = (uint8_t)twod->fullscreenautoaspect; + parms->virtWidth = img->GetDisplayWidthDouble(); + parms->virtHeight = img->GetDisplayHeightDouble(); + } + break; + + case DTA_FullscreenEx: + + intval = ListGetInt(tags); + if (intval >= 0 && intval <= 3) + { + assert(fortext == false); + if (img == NULL) return false; + parms->cleanmode = DTA_Fullscreen; + parms->fsscalemode = (uint8_t)intval; + parms->virtWidth = img->GetDisplayWidthDouble(); + parms->virtHeight = img->GetDisplayHeightDouble(); + } + break; + + case DTA_Alpha: + parms->Alpha = (float)(MIN(1., ListGetDouble(tags))); + break; + + case DTA_AlphaChannel: + parms->alphaChannel = ListGetInt(tags); + break; + + case DTA_FillColor: + parms->fillcolor = ListGetInt(tags); + if (parms->fillcolor != ~0u) + { + fillcolorset = true; + } + else if (parms->fillcolor != 0) + { + // The crosshair is the only thing which uses a non-black fill color. + parms->fillcolor = PalEntry(ColorMatcher.Pick(parms->fillcolor), RPART(parms->fillcolor), GPART(parms->fillcolor), BPART(parms->fillcolor)); + } + break; + + case DTA_TranslationIndex: + parms->TranslationId = ListGetInt(tags); + break; + + case DTA_ColorOverlay: + parms->colorOverlay = ListGetInt(tags); + break; + + case DTA_Color: + parms->color = ListGetInt(tags); + break; + + case DTA_FlipX: + parms->flipX = ListGetInt(tags); + break; + + case DTA_FlipY: + parms->flipY = ListGetInt(tags); + break; + + case DTA_SrcX: + parms->srcx = ListGetDouble(tags) / img->GetDisplayWidthDouble(); + break; + + case DTA_SrcY: + parms->srcy = ListGetDouble(tags) / img->GetDisplayHeightDouble(); + break; + + case DTA_SrcWidth: + parms->srcwidth = ListGetDouble(tags) / img->GetDisplayWidthDouble(); + break; + + case DTA_SrcHeight: + parms->srcheight = ListGetDouble(tags) / img->GetDisplayHeightDouble(); + break; + + case DTA_TopOffset: + assert(fortext == false); + if (fortext) return false; + parms->top = ListGetInt(tags); + break; + + case DTA_TopOffsetF: + assert(fortext == false); + if (fortext) return false; + parms->top = ListGetDouble(tags); + break; + + case DTA_LeftOffset: + assert(fortext == false); + if (fortext) return false; + parms->left = ListGetInt(tags); + break; + + case DTA_LeftOffsetF: + assert(fortext == false); + if (fortext) return false; + parms->left = ListGetDouble(tags); + break; + + case DTA_CenterOffset: + assert(fortext == false); + if (fortext) return false; + if (ListGetInt(tags)) + { + parms->left = img->GetDisplayWidthDouble() * 0.5; + parms->top = img->GetDisplayHeightDouble() * 0.5; + } + break; + + case DTA_CenterBottomOffset: + assert(fortext == false); + if (fortext) return false; + if (ListGetInt(tags)) + { + parms->left = img->GetDisplayWidthDouble() * 0.5; + parms->top = img->GetDisplayHeightDouble(); + } + break; + + case DTA_WindowLeft: + assert(fortext == false); + if (fortext) return false; + parms->windowleft = ListGetInt(tags); + break; + + case DTA_WindowLeftF: + assert(fortext == false); + if (fortext) return false; + parms->windowleft = ListGetDouble(tags); + break; + + case DTA_WindowRight: + assert(fortext == false); + if (fortext) return false; + parms->windowright = ListGetInt(tags); + break; + + case DTA_WindowRightF: + assert(fortext == false); + if (fortext) return false; + parms->windowright = ListGetDouble(tags); + break; + + case DTA_ClipTop: + parms->uclip = ListGetInt(tags); + if (parms->uclip < 0) + { + parms->uclip = 0; + } + break; + + case DTA_ClipBottom: + parms->dclip = ListGetInt(tags); + if (parms->dclip > drawer->GetHeight()) + { + parms->dclip = drawer->GetHeight(); + } + break; + + case DTA_ClipLeft: + parms->lclip = ListGetInt(tags); + if (parms->lclip < 0) + { + parms->lclip = 0; + } + break; + + case DTA_ClipRight: + parms->rclip = ListGetInt(tags); + if (parms->rclip > drawer->GetWidth()) + { + parms->rclip = drawer->GetWidth(); + } + break; + + case DTA_ShadowAlpha: + //parms->shadowAlpha = (float)MIN(1., ListGetDouble(tags)); + break; + + case DTA_ShadowColor: + parms->shadowColor = ListGetInt(tags); + break; + + case DTA_Shadow: + boolval = ListGetInt(tags); + if (boolval) + { + //parms->shadowAlpha = 0.5; + parms->shadowColor = 0; + } + else + { + //parms->shadowAlpha = 0; + } + break; + + case DTA_Masked: + parms->masked = ListGetInt(tags); + break; + + case DTA_BilinearFilter: + parms->bilinear = ListGetInt(tags); + break; + + case DTA_KeepRatio: + // I think this is a terribly misleading name, since it actually turns + // *off* aspect ratio correction. + parms->keepratio = ListGetInt(tags); + break; + + case DTA_RenderStyle: + parms->style.AsDWORD = ListGetInt(tags); + break; + + case DTA_LegacyRenderStyle: // mainly for ZScript which does not handle FRenderStyle that well. + parms->style = (ERenderStyle)ListGetInt(tags); + break; + + case DTA_SpecialColormap: + parms->specialcolormap = ListGetSpecialColormap(tags); + break; + + case DTA_Desaturate: + parms->desaturate = ListGetInt(tags); + break; + + case DTA_TextLen: + parms->maxstrlen = ListGetInt(tags); + break; + + case DTA_CellX: + parms->cellx = ListGetInt(tags); + break; + + case DTA_CellY: + parms->celly = ListGetInt(tags); + break; + + case DTA_Monospace: + parms->monospace = ListGetInt(tags); + break; + + case DTA_Spacing: + parms->spacing = ListGetInt(tags); + break; + + case DTA_Burn: + parms->burn = true; + break; + + } + tag = ListGetInt(tags); + } + ListEnd(tags); + + auto clipleft = drawer->clipleft; + auto cliptop = drawer->cliptop; + auto clipwidth = drawer->clipwidth; + auto clipheight = drawer->clipheight; + // intersect with the canvas's clipping rectangle. + if (clipwidth >= 0 && clipheight >= 0) + { + if (parms->lclip < clipleft) parms->lclip = clipleft; + if (parms->rclip > clipleft + clipwidth) parms->rclip = clipleft + clipwidth; + if (parms->uclip < cliptop) parms->uclip = cliptop; + if (parms->dclip > cliptop + clipheight) parms->dclip = cliptop + clipheight; + } + + if (parms->uclip >= parms->dclip || parms->lclip >= parms->rclip) + { + return false; + } + + if (img != NULL) + { + SetTextureParms(drawer, parms, img, x, y); + + if (parms->destwidth <= 0 || parms->destheight <= 0) + { + return false; + } + } + + if (parms->style.BlendOp == 255) + { + if (fillcolorset) + { + if (parms->alphaChannel) + { + parms->style = STYLE_Shaded; + } + else if (parms->Alpha < 1.f) + { + parms->style = STYLE_TranslucentStencil; + } + else + { + parms->style = STYLE_Stencil; + } + } + else if (parms->Alpha < 1.f) + { + parms->style = STYLE_Translucent; + } + else + { + parms->style = STYLE_Normal; + } + } + return true; +} +// explicitly instantiate both versions for v_text.cpp. + +template bool ParseDrawTextureTags(F2DDrawer* drawer, FTexture *img, double x, double y, uint32_t tag, Va_List& tags, DrawParms *parms, bool fortext); +template bool ParseDrawTextureTags(F2DDrawer* drawer, FTexture *img, double x, double y, uint32_t tag, VMVa_List& tags, DrawParms *parms, bool fortext); + +//========================================================================== +// +// Coordinate conversion +// +//========================================================================== + +void VirtualToRealCoords(F2DDrawer *drawer, double &x, double &y, double &w, double &h, + double vwidth, double vheight, bool vbottom, bool handleaspect) +{ + auto Width = drawer->GetWidth(); + auto Height = drawer->GetHeight(); + float myratio = handleaspect ? ActiveRatio (Width, Height) : (4.0f / 3.0f); + + // if 21:9 AR, map to 16:9 for all callers. + // this allows for black bars and stops the stretching of fullscreen images + if (myratio > 1.7f) { + myratio = 16.0f / 9.0f; + } + + double right = x + w; + double bottom = y + h; + + if (myratio > 1.334f) + { // The target surface is either 16:9 or 16:10, so expand the + // specified virtual size to avoid undesired stretching of the + // image. Does not handle non-4:3 virtual sizes. I'll worry about + // those if somebody expresses a desire to use them. + x = (x - vwidth * 0.5) * Width * 960 / (vwidth * AspectBaseWidth(myratio)) + Width * 0.5; + w = (right - vwidth * 0.5) * Width * 960 / (vwidth * AspectBaseWidth(myratio)) + Width * 0.5 - x; + } + else + { + x = x * Width / vwidth; + w = right * Width / vwidth - x; + } + if (AspectTallerThanWide(myratio)) + { // The target surface is 5:4 + y = (y - vheight * 0.5) * Height * 600 / (vheight * AspectBaseHeight(myratio)) + Height * 0.5; + h = (bottom - vheight * 0.5) * Height * 600 / (vheight * AspectBaseHeight(myratio)) + Height * 0.5 - y; + if (vbottom) + { + y += (Height - Height * AspectMultiplier(myratio) / 48.0) * 0.5; + } + } + else + { + y = y * Height / vheight; + h = bottom * Height / vheight - y; + } +} + +DEFINE_ACTION_FUNCTION(_Screen, VirtualToRealCoords) +{ + PARAM_PROLOGUE; + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(w); + PARAM_FLOAT(h); + PARAM_FLOAT(vw); + PARAM_FLOAT(vh); + PARAM_BOOL(vbottom); + PARAM_BOOL(handleaspect); + VirtualToRealCoords(twod, x, y, w, h, vw, vh, vbottom, handleaspect); + if (numret >= 1) ret[0].SetVector2(DVector2(x, y)); + if (numret >= 2) ret[1].SetVector2(DVector2(w, h)); + return MIN(numret, 2); +} + +void VirtualToRealCoordsInt(F2DDrawer *drawer, int &x, int &y, int &w, int &h, + int vwidth, int vheight, bool vbottom, bool handleaspect) +{ + double dx, dy, dw, dh; + + dx = x; + dy = y; + dw = w; + dh = h; + VirtualToRealCoords(drawer, dx, dy, dw, dh, vwidth, vheight, vbottom, handleaspect); + x = int(dx + 0.5); + y = int(dy + 0.5); + w = int(dx + dw + 0.5) - x; + h = int(dy + dh + 0.5) - y; +} + +//========================================================================== +// +// +// +//========================================================================== + +void FillBorder (F2DDrawer *drawer, FTexture *img) +{ + auto Width = drawer->GetWidth(); + auto Height = drawer->GetHeight(); + float myratio = ActiveRatio (Width, Height); + + if (myratio >= 1.3f && myratio <= 1.4f) + { // This is a 4:3 display, so no border to show + return; + } + int bordtop, bordbottom, bordleft, bordright, bord; + if (AspectTallerThanWide(myratio)) + { // Screen is taller than it is wide + bordleft = bordright = 0; + bord = Height - Height * AspectMultiplier(myratio) / 48; + bordtop = bord / 2; + bordbottom = bord - bordtop; + } + else + { // Screen is wider than it is tall + bordtop = bordbottom = 0; + bord = Width - Width * AspectMultiplier(myratio) / 48; + bordleft = bord / 2; + bordright = bord - bordleft; + } + + if (img != NULL) + { + drawer->AddFlatFill(0, 0, Width, bordtop, img); // Top + drawer->AddFlatFill(0, bordtop, bordleft, Height - bordbottom, img); // Left + drawer->AddFlatFill(Width - bordright, bordtop, Width, Height - bordbottom, img); // Right + drawer->AddFlatFill(0, Height - bordbottom, Width, Height, img); // Bottom + } + else + { + ClearRect(drawer, 0, 0, Width, bordtop, GPalette.BlackIndex, 0); // Top + ClearRect(drawer, 0, bordtop, bordleft, Height - bordbottom, GPalette.BlackIndex, 0); // Left + ClearRect(drawer, Width - bordright, bordtop, Width, Height - bordbottom, GPalette.BlackIndex, 0); // Right + ClearRect(drawer, 0, Height - bordbottom, Width, Height, GPalette.BlackIndex, 0); // Bottom + } +} + +//========================================================================== +// +// Draw a line +// +//========================================================================== + +static void DrawLine(int x0, int y0, int x1, int y1, uint32_t realcolor, int alpha) +{ + if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); + twod->AddLine((float)x0, (float)y0, (float)x1, (float)y1, -1, -1, INT_MAX, INT_MAX, realcolor | MAKEARGB(255, 0, 0, 0), alpha); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_Screen, DrawLine, DrawLine) +{ + PARAM_PROLOGUE; + PARAM_INT(x0); + PARAM_INT(y0); + PARAM_INT(x1); + PARAM_INT(y1); + PARAM_INT(color); + PARAM_INT(alpha); + DrawLine(x0, y0, x1, y1, color, alpha); + return 0; +} + +static void DrawThickLine(int x0, int y0, int x1, int y1, double thickness, uint32_t realcolor, int alpha) +{ + if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); + twod->AddThickLine(x0, y0, x1, y1, thickness, realcolor, alpha); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_Screen, DrawThickLine, DrawThickLine) +{ + PARAM_PROLOGUE; + PARAM_INT(x0); + PARAM_INT(y0); + PARAM_INT(x1); + PARAM_INT(y1); + PARAM_FLOAT(thickness); + PARAM_INT(color); + PARAM_INT(alpha); + DrawThickLine(x0, y0, x1, y1, thickness, color, alpha); + return 0; +} + +//========================================================================== +// +// DCanvas :: Clear +// +// Set an area to a specified color. +// +//========================================================================== + +void ClearRect(F2DDrawer *drawer, int left, int top, int right, int bottom, int palcolor, uint32_t color) +{ + auto clipleft = drawer->clipleft; + auto cliptop = drawer->cliptop; + auto clipwidth = drawer->clipwidth; + auto clipheight = drawer->clipheight; + + if (clipwidth >= 0 && clipheight >= 0) + { + int w = right - left; + int h = bottom - top; + if (left < clipleft) + { + w -= (clipleft - left); + left = clipleft; + } + if (w > clipwidth) w = clipwidth; + if (w <= 0) return; + + if (top < cliptop) + { + h -= (cliptop - top); + top = cliptop; + } + if (h > clipheight) w = clipheight; + if (h <= 0) return; + right = left + w; + bottom = top + h; + } + + if (palcolor >= 0 && color == 0) + { + color = GPalette.BaseColors[palcolor] | 0xff000000; + } + drawer->AddColorOnlyQuad(left, top, right - left, bottom - top, color | 0xFF000000, nullptr); +} + +DEFINE_ACTION_FUNCTION(_Screen, Clear) +{ + PARAM_PROLOGUE; + PARAM_INT(x1); + PARAM_INT(y1); + PARAM_INT(x2); + PARAM_INT(y2); + PARAM_INT(color); + PARAM_INT(palcol); + if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); + ClearRect(twod, x1, y1, x2, y2, palcol, color); + return 0; +} + +//========================================================================== +// +// DCanvas :: Dim +// +// Applies a colored overlay to an area of the screen. +// +//========================================================================== + +void DoDim(F2DDrawer *drawer, PalEntry color, float amount, int x1, int y1, int w, int h, FRenderStyle *style) +{ + if (amount <= 0) + { + return; + } + if (amount > 1) + { + amount = 1; + } + drawer->AddColorOnlyQuad(x1, y1, w, h, (color.d & 0xffffff) | (int(amount * 255) << 24), style); +} + +void Dim(F2DDrawer *drawer, PalEntry color, float damount, int x1, int y1, int w, int h, FRenderStyle *style) +{ + auto clipleft = drawer->clipleft; + auto cliptop = drawer->cliptop; + auto clipwidth = drawer->clipwidth; + auto clipheight = drawer->clipheight; + + if (clipwidth >= 0 && clipheight >= 0) + { + if (x1 < clipleft) + { + w -= (clipleft - x1); + x1 = clipleft; + } + if (w > clipwidth) w = clipwidth; + if (w <= 0) return; + + if (y1 < cliptop) + { + h -= (cliptop - y1); + y1 = cliptop; + } + if (h > clipheight) h = clipheight; + if (h <= 0) return; + } + DoDim(drawer, color, damount, x1, y1, w, h, style); +} + +DEFINE_ACTION_FUNCTION(_Screen, Dim) +{ + PARAM_PROLOGUE; + PARAM_INT(color); + PARAM_FLOAT(amount); + PARAM_INT(x1); + PARAM_INT(y1); + PARAM_INT(w); + PARAM_INT(h); + if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); + Dim(twod, color, float(amount), x1, y1, w, h); + return 0; +} + + +//========================================================================== +// +// screen->DrawBorder +// +//========================================================================== + +void DrawBorder (F2DDrawer *drawer, FTextureID picnum, int x1, int y1, int x2, int y2) +{ + if (picnum.isValid()) + { + drawer->AddFlatFill (x1, y1, x2, y2, TexMan.GetTexture(picnum, false)); + } + else + { + ClearRect(drawer, x1, y1, x2, y2, 0, 0); + } +} + +//========================================================================== +// +// V_DrawFrame +// +// Draw a frame around the specified area using the view border +// frame graphics. The border is drawn outside the area, not in it. +// +//========================================================================== + +void DrawFrame(F2DDrawer* twod, PalEntry color, int left, int top, int width, int height, int thickness) +{ + // Sanity check for incomplete gameinfo + int offset = thickness == -1 ? twod->GetHeight() / 400 : thickness; + int right = left + width; + int bottom = top + height; + + // Draw top and bottom sides. + twod->AddColorOnlyQuad(left, top - offset, width, offset, color); + twod->AddColorOnlyQuad(left - offset, top - offset, offset, height + 2 * offset, color); + twod->AddColorOnlyQuad(left, bottom, width, offset, color); + twod->AddColorOnlyQuad(right, top - offset, offset, height + 2 * offset, color); +} + diff --git a/source/core/2d/drawparms.h b/source/common/2d/v_draw.h similarity index 56% rename from source/core/2d/drawparms.h rename to source/common/2d/v_draw.h index afe34a126..a3e6b747c 100644 --- a/source/core/2d/drawparms.h +++ b/source/common/2d/v_draw.h @@ -1,50 +1,27 @@ #pragma once -/* -** v_video.h -** -**--------------------------------------------------------------------------- -** Copyright 1998-2008 Randy Heit -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#include "palentry.h" -#include "renderstyle.h" -#include "c_cvars.h" #include "v_2ddrawer.h" +#include "c_cvars.h" + +// TagItem definitions for DrawTexture. As far as I know, tag lists +// originated on the Amiga. +// +// Think of TagItems as an array of the following structure: +// +// struct TagItem { +// uint32_t ti_Tag; +// uint32_t ti_Data; +// }; #define TAG_DONE (0) /* Used to indicate the end of the Tag list */ #define TAG_END (0) /* Ditto */ /* list pointed to in ti_Data */ +#define TAG_USER ((uint32_t)(1u<<30)) + enum { - DTA_Base = 1, + DTA_Base = TAG_USER + 5000, DTA_DestWidth, // width of area to draw to DTA_DestHeight, // height of area to draw to DTA_Alpha, // alpha value for translucency @@ -129,6 +106,9 @@ enum class FFont; +struct FRemapTable; +class player_t; +typedef uint32_t angle_t; struct DrawParms { @@ -149,8 +129,8 @@ struct DrawParms double top; double left; float Alpha; - int TranslationId; PalEntry fillcolor; + int TranslationId; PalEntry colorOverlay; PalEntry color; int alphaChannel; @@ -162,6 +142,7 @@ struct DrawParms int masked; int bilinear; FRenderStyle style; + struct FSpecialColormap *specialcolormap; int desaturate; int scalex, scaley; int cellx, celly; @@ -170,9 +151,10 @@ struct DrawParms int maxstrlen; bool fortext; bool virtBottom; + bool burn; + uint8_t fsscalemode; double srcx, srcy; double srcwidth, srcheight; - bool burn; }; struct Va_List @@ -180,3 +162,73 @@ struct Va_List va_list list; }; +struct VMVa_List +{ + VMValue *args; + int curindex; + int numargs; + const uint8_t *reginfo; +}; + +float ActiveRatio (int width, int height, float *trueratio = NULL); +inline double ActiveRatio (double width, double height) { return ActiveRatio(int(width), int(height)); } + +int AspectBaseWidth(float aspect); +int AspectBaseHeight(float aspect); +double AspectPspriteOffset(float aspect); +int AspectMultiplier(float aspect); +bool AspectTallerThanWide(float aspect); + +extern F2DDrawer* twod; + +int GetUIScale(F2DDrawer* drawer, int altval); +int GetConScale(F2DDrawer* drawer, int altval); + +EXTERN_CVAR(Int, uiscale); +EXTERN_CVAR(Int, con_scaletext); +EXTERN_CVAR(Int, con_scale); + +inline int active_con_scaletext(F2DDrawer* drawer, bool newconfont = false) +{ + return newconfont ? GetConScale(drawer, con_scaletext) : GetUIScale(drawer, con_scaletext); +} + +inline int active_con_scale(F2DDrawer *drawer) +{ + return GetConScale(drawer, con_scale); +} + +#ifdef DrawText +#undef DrawText // See WinUser.h for the definition of DrawText as a macro +#endif + +template +bool ParseDrawTextureTags(F2DDrawer *drawer, FTexture* img, double x, double y, uint32_t tag, T& tags, DrawParms* parms, bool fortext); + +template +void DrawTextCommon(F2DDrawer *drawer, FFont* font, int normalcolor, double x, double y, const T* string, DrawParms& parms); +bool SetTextureParms(F2DDrawer *drawer, DrawParms* parms, FTexture* img, double x, double y); + +void DrawText(F2DDrawer* drawer, FFont* font, int normalcolor, double x, double y, const char* string, int tag_first, ...); +void DrawText(F2DDrawer* drawer, FFont* font, int normalcolor, double x, double y, const char32_t* string, int tag_first, ...); +void DrawChar(F2DDrawer* drawer, FFont* font, int normalcolor, double x, double y, int character, int tag_first, ...); +void DrawTexture(F2DDrawer* drawer, FTexture* img, double x, double y, int tags_first, ...); + +void DoDim(F2DDrawer* drawer, PalEntry color, float amount, int x1, int y1, int w, int h, FRenderStyle* style = nullptr); +void Dim(F2DDrawer* drawer, PalEntry color, float damount, int x1, int y1, int w, int h, FRenderStyle* style = nullptr); +void FillBorder(F2DDrawer *drawer, FTexture* img); // Fills the border around a 4:3 part of the screen on non-4:3 displays + +void DrawFrame(F2DDrawer* drawer, int left, int top, int width, int height); +void DrawBorder(F2DDrawer* drawer, FTextureID, int x1, int y1, int x2, int y2); +void DrawFrame(F2DDrawer* twod, PalEntry color, int left, int top, int width, int height, int thickness); + +// Set an area to a specified color +void ClearRect(F2DDrawer* drawer, int left, int top, int right, int bottom, int palcolor, uint32_t color); + +void VirtualToRealCoords(F2DDrawer* drawer, double& x, double& y, double& w, double& h, double vwidth, double vheight, bool vbottom = false, bool handleaspect = true); + +// Code that uses these (i.e. SBARINFO) should probably be evaluated for using doubles all around instead. +void VirtualToRealCoordsInt(F2DDrawer* drawer, int& x, int& y, int& w, int& h, int vwidth, int vheight, bool vbottom = false, bool handleaspect = true); + +extern int CleanWidth, CleanHeight, CleanXfac, CleanYfac; +extern int CleanWidth_1, CleanHeight_1, CleanXfac_1, CleanYfac_1; diff --git a/source/core/2d/v_drawtext.cpp b/source/common/2d/v_drawtext.cpp similarity index 50% rename from source/core/2d/v_drawtext.cpp rename to source/common/2d/v_drawtext.cpp index 52dcb7b58..a475e9e9a 100644 --- a/source/core/2d/v_drawtext.cpp +++ b/source/common/2d/v_drawtext.cpp @@ -37,38 +37,122 @@ #include #include -#include "utf8.h" #include "v_text.h" - -#include "drawparms.h" +#include "utf8.h" #include "v_draw.h" -#include "image.h" -#include "v_2ddrawer.h" #include "gstrings.h" -#include "v_font.h" +#include "vm.h" +#include "printf.h" + +int ListGetInt(VMVa_List &tags); -class FFont; //========================================================================== // -// Internal texture drawing function +// Create a texture from a text in a given font. // //========================================================================== - -void DrawTexture(F2DDrawer *drawer, FTexture* img, double x, double y, int tags_first, ...) +#if 0 +FTexture * BuildTextTexture(FFont *font, const char *string, int textcolor) { - Va_List tags; - va_start(tags.list, tags_first); - DrawParms parms; + int w; + const uint8_t *ch; + int cx; + int cy; + int trans = -1; + int kerning; + FTexture *pic; - bool res = ParseDrawTextureTags(img, x, y, tags_first, tags, &parms, false); - va_end(tags.list); - if (!res) + kerning = font->GetDefaultKerning(); + + ch = (const uint8_t *)string; + cx = 0; + cy = 0; + + + IntRect box; + + while (auto c = GetCharFromString(ch)) { - return; + if (c == TEXTCOLOR_ESCAPE) + { + // Here we only want to measure the texture so just parse over the color. + V_ParseFontColor(ch, 0, 0); + continue; + } + + if (c == '\n') + { + cx = 0; + cy += font->GetHeight(); + continue; + } + + if (nullptr != (pic = font->GetChar(c, CR_UNTRANSLATED, &w, nullptr))) + { + auto img = pic->GetImage(); + auto offsets = img->GetOffsets(); + int x = cx - offsets.first; + int y = cy - offsets.second; + int ww = img->GetWidth(); + int h = img->GetHeight(); + + box.AddToRect(x, y); + box.AddToRect(x + ww, y + h); + } + cx += (w + kerning); } - drawer->AddTexture(img, parms); + + cx = -box.left; + cy = -box.top; + + TArray part(strlen(string)); + + while (auto c = GetCharFromString(ch)) + { + if (c == TEXTCOLOR_ESCAPE) + { + EColorRange newcolor = V_ParseFontColor(ch, textcolor, textcolor); + if (newcolor != CR_UNDEFINED) + { + trans = font->GetColorTranslation(newcolor); + textcolor = newcolor; + } + continue; + } + + if (c == '\n') + { + cx = 0; + cy += font->GetHeight(); + continue; + } + + if (nullptr != (pic = font->GetChar(c, textcolor, &w, nullptr))) + { + auto img = pic->GetImage(); + auto offsets = img->GetOffsets(); + int x = cx - offsets.first; + int y = cy - offsets.second; + + auto &tp = part[part.Reserve(1)]; + + tp.OriginX = x; + tp.OriginY = y; + tp.Image = img; + tp.Translation = range; + } + cx += (w + kerning); + } + FMultiPatchTexture *image = new FMultiPatchTexture(box.width, box.height, part, false, false); + image->SetOffsets(-box.left, -box.top); + FImageTexture *tex = new FImageTexture(image, ""); + tex->SetUseType(ETextureType::MiscPatch); + TexMan.AddTexture(tex); + return tex; } +#endif + //========================================================================== // @@ -78,7 +162,37 @@ void DrawTexture(F2DDrawer *drawer, FTexture* img, double x, double y, int tags_ // //========================================================================== -void DrawChar (F2DDrawer* drawer, FFont *font, int normalcolor, double x, double y, int character, int tag_first, ...) +void DrawChar(F2DDrawer *drawer, FFont* font, int normalcolor, double x, double y, int character, int tag_first, ...) +{ + if (font == NULL) + return; + + if (normalcolor >= NumTextColors) + normalcolor = CR_UNTRANSLATED; + + FTexture* pic; + int dummy; + bool redirected; + + if (NULL != (pic = font->GetChar(character, normalcolor, &dummy, &redirected))) + { + DrawParms parms; + Va_List tags; + va_start(tags.list, tag_first); + bool res = ParseDrawTextureTags(drawer, pic, x, y, tag_first, tags, &parms, false); + va_end(tags.list); + if (!res) + { + return; + } + PalEntry color = 0xffffffff; + parms.TranslationId = redirected ? -1 : font->GetColorTranslation((EColorRange)normalcolor, &color); + parms.color = PalEntry((color.a * parms.color.a) / 255, (color.r * parms.color.r) / 255, (color.g * parms.color.g) / 255, (color.b * parms.color.b) / 255); + drawer->AddTexture(pic, parms); + } +} + +void DrawChar(F2DDrawer *drawer, FFont *font, int normalcolor, double x, double y, int character, VMVa_List &args) { if (font == NULL) return; @@ -90,24 +204,36 @@ void DrawChar (F2DDrawer* drawer, FFont *font, int normalcolor, double x, double int dummy; bool redirected; - if (NULL != (pic = font->GetChar (character, normalcolor, &dummy, &redirected))) + if (NULL != (pic = font->GetChar(character, normalcolor, &dummy, &redirected))) { DrawParms parms; - Va_List tags; - va_start(tags.list, tag_first); - bool res = ParseDrawTextureTags(pic, x, y, tag_first, tags, &parms, false); - va_end(tags.list); - if (!res) - { - return; - } + uint32_t tag = ListGetInt(args); + bool res = ParseDrawTextureTags(drawer, pic, x, y, tag, args, &parms, false); + if (!res) return; PalEntry color = 0xffffffff; - parms.TranslationId = redirected? -1 : font->GetColorTranslation((EColorRange)normalcolor, &color); + parms.TranslationId = redirected ? -1 : font->GetColorTranslation((EColorRange)normalcolor, &color); parms.color = PalEntry((color.a * parms.color.a) / 255, (color.r * parms.color.r) / 255, (color.g * parms.color.g) / 255, (color.b * parms.color.b) / 255); drawer->AddTexture(pic, parms); } } +DEFINE_ACTION_FUNCTION(_Screen, DrawChar) +{ + PARAM_PROLOGUE; + PARAM_POINTER(font, FFont); + PARAM_INT(cr); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_INT(chr); + + PARAM_VA_POINTER(va_reginfo) // Get the hidden type information array + + if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); + VMVa_List args = { param + 5, 0, numparam - 6, va_reginfo + 5 }; + DrawChar(twod, font, cr, x, y, chr, args); + return 0; +} + //========================================================================== // // DrawText @@ -120,7 +246,7 @@ void DrawChar (F2DDrawer* drawer, FFont *font, int normalcolor, double x, double EColorRange V_ParseFontColor(const char32_t *&color_value, int normalcolor, int boldcolor) { return CR_UNTRANSLATED; } template -void DrawTextCommon(F2DDrawer* drawer, FFont *font, int normalcolor, double x, double y, const chartype *string, DrawParms &parms) +void DrawTextCommon(F2DDrawer *drawer, FFont *font, int normalcolor, double x, double y, const chartype *string, DrawParms &parms) { int w; const chartype *ch; @@ -128,6 +254,7 @@ void DrawTextCommon(F2DDrawer* drawer, FFont *font, int normalcolor, double x, d double cx; double cy; int boldcolor; + int trans = -1; int kerning; FTexture *pic; @@ -140,7 +267,7 @@ void DrawTextCommon(F2DDrawer* drawer, FFont *font, int normalcolor, double x, d PalEntry colorparm = parms.color; PalEntry color = 0xffffffff; - parms.TranslationId = font->GetColorTranslation((EColorRange)normalcolor, &color); + trans = font->GetColorTranslation((EColorRange)normalcolor, &color); parms.color = PalEntry(colorparm.a, (color.r * colorparm.r) / 255, (color.g * colorparm.g) / 255, (color.b * colorparm.b) / 255); kerning = font->GetDefaultKerning(); @@ -167,7 +294,7 @@ void DrawTextCommon(F2DDrawer* drawer, FFont *font, int normalcolor, double x, d EColorRange newcolor = V_ParseFontColor(ch, normalcolor, boldcolor); if (newcolor != CR_UNDEFINED) { - parms.TranslationId = font->GetColorTranslation(newcolor, &color); + trans = font->GetColorTranslation(newcolor, &color); parms.color = PalEntry(colorparm.a, (color.r * colorparm.r) / 255, (color.g * colorparm.g) / 255, (color.b * colorparm.b) / 255); currentcolor = newcolor; } @@ -184,7 +311,8 @@ void DrawTextCommon(F2DDrawer* drawer, FFont *font, int normalcolor, double x, d bool redirected = false; if (NULL != (pic = font->GetChar(c, currentcolor, &w, &redirected))) { - SetTextureParms(&parms, pic, cx, cy); + parms.TranslationId = redirected? -1 : trans; + SetTextureParms(drawer, &parms, pic, cx, cy); if (parms.cellx) { w = parms.cellx; @@ -208,10 +336,13 @@ void DrawTextCommon(F2DDrawer* drawer, FFont *font, int normalcolor, double x, d { cx += (parms.spacing) * parms.scalex; } + } } -void DrawText(F2DDrawer* drawer, FFont *font, int normalcolor, double x, double y, const char *string, int tag_first, ...) + +// For now the 'drawer' parameter is a placeholder - this should be the way to handle it later to allow different drawers. +void DrawText(F2DDrawer *drawer, FFont* font, int normalcolor, double x, double y, const char* string, int tag_first, ...) { Va_List tags; DrawParms parms; @@ -220,16 +351,17 @@ void DrawText(F2DDrawer* drawer, FFont *font, int normalcolor, double x, double return; va_start(tags.list, tag_first); - bool res = ParseDrawTextureTags(nullptr, 0, 0, tag_first, tags, &parms, true); + bool res = ParseDrawTextureTags(drawer, nullptr, 0, 0, tag_first, tags, &parms, true); va_end(tags.list); if (!res) { return; } - DrawTextCommon(drawer, font, normalcolor, x, y, (const uint8_t*)GStrings.localize(string), parms); + DrawTextCommon(drawer, font, normalcolor, x, y, (const uint8_t*)string, parms); } -void DrawText(F2DDrawer* drawer, FFont *font, int normalcolor, double x, double y, const char32_t *string, int tag_first, ...) + +void DrawText(F2DDrawer *drawer, FFont* font, int normalcolor, double x, double y, const char32_t* string, int tag_first, ...) { Va_List tags; DrawParms parms; @@ -238,7 +370,7 @@ void DrawText(F2DDrawer* drawer, FFont *font, int normalcolor, double x, double return; va_start(tags.list, tag_first); - bool res = ParseDrawTextureTags(nullptr, 0, 0, tag_first, tags, &parms, true); + bool res = ParseDrawTextureTags(drawer, nullptr, 0, 0, tag_first, tags, &parms, true); va_end(tags.list); if (!res) { @@ -247,25 +379,38 @@ void DrawText(F2DDrawer* drawer, FFont *font, int normalcolor, double x, double DrawTextCommon(drawer, font, normalcolor, x, y, string, parms); } -//========================================================================== -// -// V_DrawFrame -// -// Draw a frame around the specified area using the view border -// frame graphics. The border is drawn outside the area, not in it. -// -//========================================================================== -void DrawFrame(F2DDrawer* twod, PalEntry color, int left, int top, int width, int height, int thickness) +void DrawText(F2DDrawer *drawer, FFont *font, int normalcolor, double x, double y, const char *string, VMVa_List &args) { - // Sanity check for incomplete gameinfo - int offset = thickness == -1 ? screen->GetHeight() / 400 : thickness; - int right = left + width; - int bottom = top + height; + DrawParms parms; - // Draw top and bottom sides. - twod->AddColorOnlyQuad(left, top - offset, width, offset, color); - twod->AddColorOnlyQuad(left - offset, top - offset, offset, height + 2 * offset, color); - twod->AddColorOnlyQuad(left, bottom, width, offset, color); - twod->AddColorOnlyQuad(right, top - offset, offset, height + 2 * offset, color); + if (font == NULL || string == NULL) + return; + + uint32_t tag = ListGetInt(args); + bool res = ParseDrawTextureTags(drawer, nullptr, 0, 0, tag, args, &parms, true); + if (!res) + { + return; + } + DrawTextCommon(drawer, font, normalcolor, x, y, (const uint8_t*)string, parms); } + +DEFINE_ACTION_FUNCTION(_Screen, DrawText) +{ + PARAM_PROLOGUE; + PARAM_POINTER_NOT_NULL(font, FFont); + PARAM_INT(cr); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_STRING(chr); + + PARAM_VA_POINTER(va_reginfo) // Get the hidden type information array + + if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); + VMVa_List args = { param + 5, 0, numparam - 6, va_reginfo + 5 }; + const char *txt = chr[0] == '$' ? GStrings(&chr[1]) : chr.GetChars(); + DrawText(twod, font, cr, x, y, txt, args); + return 0; +} + diff --git a/source/common/engine/fcolormap.h b/source/common/engine/fcolormap.h new file mode 100644 index 000000000..ffb0c136e --- /dev/null +++ b/source/common/engine/fcolormap.h @@ -0,0 +1,67 @@ +#pragma once + +#include +#include "palentry.h" + +// for internal use +struct FColormap +{ + PalEntry LightColor; // a is saturation (0 full, 31=b/w, other=custom colormap) + PalEntry FadeColor; // a is fadedensity>>1 + uint8_t Desaturation; + uint8_t BlendFactor; // This is for handling Legacy-style colormaps which use a different formula to calculate how the color affects lighting. + uint16_t FogDensity; + + void Clear() + { + LightColor = 0xffffff; + FadeColor = 0; + Desaturation = 0; + BlendFactor = 0; + FogDensity = 0; + } + + void MakeWhite() + { + LightColor = 0xffffff; + } + + void ClearColor() + { + LightColor = 0xffffff; + BlendFactor = 0; + Desaturation = 0; + } + + void CopyLight(FColormap &from) + { + LightColor = from.LightColor; + Desaturation = from.Desaturation; + BlendFactor = from.BlendFactor; + } + + void CopyFog(FColormap &from) + { + FadeColor = from.FadeColor; + FogDensity = from.FogDensity; + } + + void Decolorize() + { + LightColor.Decolorize(); + } + + bool operator == (const FColormap &other) + { + return LightColor == other.LightColor && FadeColor == other.FadeColor && Desaturation == other.Desaturation && + BlendFactor == other.BlendFactor && FogDensity == other.FogDensity; + } + + bool operator != (const FColormap &other) + { + return !operator==(other); + } + +}; + + diff --git a/source/common/engine/stats.cpp b/source/common/engine/stats.cpp index 4e6a329ee..0a295c8c6 100644 --- a/source/common/engine/stats.cpp +++ b/source/common/engine/stats.cpp @@ -33,9 +33,7 @@ */ #include "stats.h" -#include "v_video.h" -#include "v_2ddrawer.h" -#include "drawparms.h" +#include "v_draw.h" #include "v_text.h" #include "v_font.h" #include "c_console.h" @@ -96,12 +94,12 @@ void FStat::ToggleStat () m_Active = !m_Active; } -void FStat::PrintStat () +void FStat::PrintStat (F2DDrawer *drawer) { - int textScale = active_con_scale(); + int textScale = active_con_scale(drawer); int fontheight = NewConsoleFont->GetHeight() + 1; - int y = screen->GetHeight() / textScale; + int y = drawer->GetHeight() / textScale; int count = 0; for (FStat *stat = FirstStat; stat != NULL; stat = stat->m_Next) @@ -118,9 +116,9 @@ void FStat::PrintStat () // Count number of linefeeds but ignore terminating ones. if (stattext[i] == '\n') y -= fontheight; } - DrawText(twod, NewConsoleFont, CR_GREEN, 5 / textScale, y, stattext, - DTA_VirtualWidth, screen->GetWidth() / textScale, - DTA_VirtualHeight, screen->GetHeight() / textScale, + DrawText(drawer, NewConsoleFont, CR_GREEN, 5 / textScale, y, stattext, + DTA_VirtualWidth, twod->GetWidth() / textScale, + DTA_VirtualHeight, twod->GetHeight() / textScale, DTA_KeepRatio, true, TAG_DONE); count++; } diff --git a/source/common/engine/stats.h b/source/common/engine/stats.h index 1a01b674c..6734bfe72 100644 --- a/source/common/engine/stats.h +++ b/source/common/engine/stats.h @@ -223,6 +223,7 @@ private: }; +class F2DDrawer; class FStat { @@ -238,7 +239,7 @@ public: return m_Active; } - static void PrintStat (); + static void PrintStat (F2DDrawer *drawer); static FStat *FindStat (const char *name); static void ToggleStat (const char *name); static void EnableStat(const char* name, bool on); diff --git a/source/common/fonts/v_font.h b/source/common/fonts/v_font.h index 59c87c125..41fabb096 100644 --- a/source/common/fonts/v_font.h +++ b/source/common/fonts/v_font.h @@ -1,3 +1,4 @@ +#pragma once /* ** v_font.h ** @@ -31,8 +32,6 @@ ** */ -#ifndef __V_FONT_H__ -#define __V_FONT_H__ #include "filesystem.h" #include "vectors.h" @@ -195,4 +194,3 @@ void V_InitFontColors(); char* CleanseString(char* str); -#endif //__V_FONT_H__ diff --git a/source/core/2d/v_draw.cpp b/source/core/2d/v_draw.cpp deleted file mode 100644 index 62018b459..000000000 --- a/source/core/2d/v_draw.cpp +++ /dev/null @@ -1,720 +0,0 @@ -/* -** v_draw.cpp -** Draw patches and blocks to a canvas -** -**--------------------------------------------------------------------------- -** Copyright 1998-2008 Randy Heit -** Copyright 2005-2019 Christoph Oelckers -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#include -#include -#include "c_cvars.h" -#include "drawparms.h" -#include "templates.h" -#include "v_draw.h" -#include "v_video.h" - -CUSTOM_CVAR(Int, uiscale, 0, CVAR_ARCHIVE | CVAR_NOINITCALL) -{ - if (self < 0) - { - self = 0; - return; - } - //setsizeneeded = true; -} - -int GetUIScale(int altval) -{ - int scaleval; - if (altval > 0) scaleval = altval; - else if (uiscale == 0) - { - // Default should try to scale to 640x400 - int vscale = screen->GetHeight() / 400; - int hscale = screen->GetWidth() / 640; - scaleval = clamp(vscale, 1, hscale); - } - else scaleval = uiscale; - - // block scales that result in something larger than the current screen. - int vmax = screen->GetHeight() / 200; - int hmax = screen->GetWidth() / 320; - int max = std::max(vmax, hmax); - return std::max(1,std::min(scaleval, max)); -} - -// The new console font is twice as high, so the scaling calculation must factor that in. -int GetConScale(int altval) -{ - int scaleval; - if (altval > 0) scaleval = (altval+1) / 2; - else if (uiscale == 0) - { - // Default should try to scale to 640x400 - int vscale = screen->GetHeight() / 800; - int hscale = screen->GetWidth() / 1280; - scaleval = clamp(vscale, 1, hscale); - } - else scaleval = (uiscale+1) / 2; - - // block scales that result in something larger than the current screen. - int vmax = screen->GetHeight() / 400; - int hmax = screen->GetWidth() / 640; - int max = std::max(vmax, hmax); - return std::max(1, std::min(scaleval, max)); -} - - -// [RH] Stretch values to make a 320x200 image best fit the screen -// without using fractional steppings -int CleanXfac, CleanYfac; - -// [RH] Effective screen sizes that the above scale values give you -int CleanWidth, CleanHeight; - -// Above minus 1 (or 1, if they are already 1) -int CleanXfac_1, CleanYfac_1, CleanWidth_1, CleanHeight_1; - - -//========================================================================== -// -// Draw parameter parsing -// -//========================================================================== - -bool SetTextureParms(DrawParms *parms, FTexture *img, double xx, double yy) -{ - if (img != NULL) - { - parms->x = xx; - parms->y = yy; - parms->texwidth = img->GetDisplayWidth(); - parms->texheight = img->GetDisplayHeight(); - if (parms->top == INT_MAX || parms->fortext) - { - parms->top = img->GetDisplayTopOffset(); - } - if (parms->left == INT_MAX || parms->fortext) - { - parms->left = img->GetDisplayLeftOffset(); - } - if (parms->destwidth == INT_MAX || parms->fortext) - { - parms->destwidth = img->GetDisplayWidth(); - } - if (parms->destheight == INT_MAX || parms->fortext) - { - parms->destheight = img->GetDisplayHeight(); - } - - switch (parms->cleanmode) - { - default: - break; - - case DTA_Clean: - parms->x = (parms->x - 160.0) * CleanXfac + (screen->GetWidth() * 0.5); - parms->y = (parms->y - 100.0) * CleanYfac + (screen->GetHeight() * 0.5); - parms->destwidth = parms->texwidth * CleanXfac; - parms->destheight = parms->texheight * CleanYfac; - break; - - case DTA_CleanNoMove: - parms->destwidth = parms->texwidth * CleanXfac; - parms->destheight = parms->texheight * CleanYfac; - break; - - case DTA_CleanNoMove_1: - parms->destwidth = parms->texwidth * CleanXfac_1; - parms->destheight = parms->texheight * CleanYfac_1; - break; - - case DTA_Fullscreen: - parms->x = parms->y = 0; - break; - - } - if (parms->virtWidth != screen->GetWidth() || parms->virtHeight != screen->GetHeight()) - { - VirtualToRealCoords(parms->x, parms->y, parms->destwidth, parms->destheight, - parms->virtWidth, parms->virtHeight, parms->virtBottom, !parms->keepratio); - } - } - - return false; -} - -//========================================================================== -// -// template helpers -// -//========================================================================== - -static void ListEnd(Va_List &tags) -{ - va_end(tags.list); -} - -static int ListGetInt(Va_List &tags) -{ - return va_arg(tags.list, int); -} - -static inline double ListGetDouble(Va_List &tags) -{ - return va_arg(tags.list, double); -} - - -//========================================================================== -// -// Main taglist parsing -// -//========================================================================== - -bool ParseDrawTextureTags(FTexture *img, double x, double y, uint32_t tag, Va_List& tags, DrawParms *parms, bool fortext) -{ - int boolval; - int intval; - bool translationset = false; - bool fillcolorset = false; - - if (!fortext) - { - if (img == NULL) - { - ListEnd(tags); - return false; - } - } - - // Do some sanity checks on the coordinates. - if (x < -16383 || x > 16383 || y < -16383 || y > 16383) - { - ListEnd(tags); - return false; - } - - parms->fortext = fortext; - parms->windowleft = 0; - parms->windowright = INT_MAX; - parms->dclip = screen->GetHeight(); - parms->uclip = 0; - parms->lclip = 0; - parms->rclip = screen->GetWidth(); - parms->left = INT_MAX; - parms->top = INT_MAX; - parms->destwidth = INT_MAX; - parms->destheight = INT_MAX; - parms->Alpha = 1.f; - parms->fillcolor = -1; - parms->colorOverlay = 0; - parms->alphaChannel = false; - parms->flipX = false; - parms->flipY = false; - parms->color = 0xffffffff; - //parms->shadowAlpha = 0; - parms->shadowColor = 0; - parms->virtWidth = screen->GetWidth(); - parms->virtHeight = screen->GetHeight(); - parms->keepratio = false; - parms->style.BlendOp = 255; // Dummy "not set" value - parms->masked = true; - parms->bilinear = false; - parms->desaturate = 0; - parms->cleanmode = DTA_Base; - parms->scalex = parms->scaley = 1; - parms->cellx = parms->celly = 0; - parms->maxstrlen = INT_MAX; - parms->virtBottom = false; - parms->srcx = 0.; - parms->srcy = 0.; - parms->srcwidth = 1.; - parms->srcheight = 1.; - parms->burn = false; - parms->monospace = EMonospacing::Off; - parms->spacing = 0; - parms->TranslationId = -1; - - // Parse the tag list for attributes. (For floating point attributes, - // consider that the C ABI dictates that all floats be promoted to - // doubles when passed as function arguments.) - while (tag != TAG_DONE) - { - switch (tag) - { - default: - ListGetInt(tags); - break; - - case DTA_DestWidth: - assert(fortext == false); - if (fortext) return false; - parms->cleanmode = DTA_Base; - parms->destwidth = ListGetInt(tags); - break; - - case DTA_DestWidthF: - assert(fortext == false); - if (fortext) return false; - parms->cleanmode = DTA_Base; - parms->destwidth = ListGetDouble(tags); - break; - - case DTA_DestHeight: - assert(fortext == false); - if (fortext) return false; - parms->cleanmode = DTA_Base; - parms->destheight = ListGetInt(tags); - break; - - case DTA_DestHeightF: - assert(fortext == false); - if (fortext) return false; - parms->cleanmode = DTA_Base; - parms->destheight = ListGetDouble(tags); - break; - - case DTA_Clean: - boolval = ListGetInt(tags); - if (boolval) - { - parms->scalex = 1; - parms->scaley = 1; - parms->cleanmode = tag; - } - break; - - case DTA_CleanNoMove: - boolval = ListGetInt(tags); - if (boolval) - { - parms->scalex = CleanXfac; - parms->scaley = CleanYfac; - parms->cleanmode = tag; - } - break; - - case DTA_CleanNoMove_1: - boolval = ListGetInt(tags); - if (boolval) - { - parms->scalex = CleanXfac_1; - parms->scaley = CleanYfac_1; - parms->cleanmode = tag; - } - break; - - case DTA_320x200: - boolval = ListGetInt(tags); - if (boolval) - { - parms->cleanmode = DTA_Base; - parms->scalex = 1; - parms->scaley = 1; - parms->virtWidth = 320; - parms->virtHeight = 200; - } - break; - - case DTA_Bottom320x200: - boolval = ListGetInt(tags); - if (boolval) - { - parms->cleanmode = DTA_Base; - parms->scalex = 1; - parms->scaley = 1; - parms->virtWidth = 320; - parms->virtHeight = 200; - } - parms->virtBottom = true; - break; - - case DTA_HUDRules: - intval = ListGetInt(tags); - parms->cleanmode = intval == HUD_HorizCenter ? DTA_HUDRulesC : DTA_HUDRules; - break; - - case DTA_VirtualWidth: - parms->cleanmode = DTA_Base; - parms->virtWidth = ListGetInt(tags); - break; - - case DTA_VirtualWidthF: - parms->cleanmode = DTA_Base; - parms->virtWidth = ListGetDouble(tags); - break; - - case DTA_VirtualHeight: - parms->cleanmode = DTA_Base; - parms->virtHeight = ListGetInt(tags); - break; - - case DTA_VirtualHeightF: - parms->cleanmode = DTA_Base; - parms->virtHeight = ListGetDouble(tags); - break; - - case DTA_Fullscreen: - boolval = ListGetInt(tags); - if (boolval) - { - assert(fortext == false); - if (img == NULL) return false; - parms->cleanmode = DTA_Fullscreen; - parms->virtWidth = img->GetDisplayWidth(); - parms->virtHeight = img->GetDisplayHeight(); - } - break; - - case DTA_Alpha: - parms->Alpha = (float)(std::min(1., ListGetDouble(tags))); - break; - - case DTA_AlphaChannel: - parms->alphaChannel = ListGetInt(tags); - break; - - case DTA_FillColor: - parms->fillcolor = ListGetInt(tags); - if (parms->fillcolor != ~0u) - { - fillcolorset = true; - } - break; - - case DTA_TranslationIndex: - parms->TranslationId = ListGetInt(tags); - break; - - case DTA_ColorOverlay: - parms->colorOverlay = ListGetInt(tags); - break; - - case DTA_Color: - parms->color = ListGetInt(tags); - break; - - case DTA_FlipX: - parms->flipX = ListGetInt(tags); - break; - - case DTA_FlipY: - parms->flipY = ListGetInt(tags); - break; - - case DTA_SrcX: - parms->srcx = ListGetDouble(tags) / img->GetDisplayWidth(); - break; - - case DTA_SrcY: - parms->srcy = ListGetDouble(tags) / img->GetDisplayHeight(); - break; - - case DTA_SrcWidth: - parms->srcwidth = ListGetDouble(tags) / img->GetDisplayWidth(); - break; - - case DTA_SrcHeight: - parms->srcheight = ListGetDouble(tags) / img->GetDisplayHeight(); - break; - - case DTA_TopOffset: - assert(fortext == false); - if (fortext) return false; - parms->top = ListGetInt(tags); - break; - - case DTA_TopOffsetF: - assert(fortext == false); - if (fortext) return false; - parms->top = ListGetDouble(tags); - break; - - case DTA_LeftOffset: - assert(fortext == false); - if (fortext) return false; - parms->left = ListGetInt(tags); - break; - - case DTA_LeftOffsetF: - assert(fortext == false); - if (fortext) return false; - parms->left = ListGetDouble(tags); - break; - - case DTA_CenterOffset: - assert(fortext == false); - if (fortext) return false; - if (ListGetInt(tags)) - { - parms->left = img->GetDisplayWidth() * 0.5; - parms->top = img->GetDisplayHeight() * 0.5; - } - break; - - case DTA_CenterBottomOffset: - assert(fortext == false); - if (fortext) return false; - if (ListGetInt(tags)) - { - parms->left = img->GetDisplayWidth() * 0.5; - parms->top = img->GetDisplayHeight(); - } - break; - - case DTA_WindowLeft: - assert(fortext == false); - if (fortext) return false; - parms->windowleft = ListGetInt(tags); - break; - - case DTA_WindowLeftF: - assert(fortext == false); - if (fortext) return false; - parms->windowleft = ListGetDouble(tags); - break; - - case DTA_WindowRight: - assert(fortext == false); - if (fortext) return false; - parms->windowright = ListGetInt(tags); - break; - - case DTA_WindowRightF: - assert(fortext == false); - if (fortext) return false; - parms->windowright = ListGetDouble(tags); - break; - - case DTA_ClipTop: - parms->uclip = ListGetInt(tags); - if (parms->uclip < 0) - { - parms->uclip = 0; - } - break; - - case DTA_ClipBottom: - parms->dclip = ListGetInt(tags); - if (parms->dclip > screen->GetHeight()) - { - parms->dclip = screen->GetHeight(); - } - break; - - case DTA_ClipLeft: - parms->lclip = ListGetInt(tags); - if (parms->lclip < 0) - { - parms->lclip = 0; - } - break; - - case DTA_ClipRight: - parms->rclip = ListGetInt(tags); - if (parms->rclip > screen->GetWidth()) - { - parms->rclip = screen->GetWidth(); - } - break; - - case DTA_ShadowAlpha: - //parms->shadowAlpha = (float)std::min(1., ListGetDouble(tags)); - break; - - case DTA_ShadowColor: - parms->shadowColor = ListGetInt(tags); - break; - - case DTA_Shadow: - boolval = ListGetInt(tags); - if (boolval) - { - //parms->shadowAlpha = 0.5; - parms->shadowColor = 0; - } - else - { - //parms->shadowAlpha = 0; - } - break; - - case DTA_Masked: - parms->masked = ListGetInt(tags); - break; - - case DTA_BilinearFilter: - parms->bilinear = ListGetInt(tags); - break; - - case DTA_KeepRatio: - // I think this is a terribly misleading name, since it actually turns - // *off* aspect ratio correction. - parms->keepratio = ListGetInt(tags); - break; - - case DTA_RenderStyle: - parms->style.AsDWORD = ListGetInt(tags); - break; - - case DTA_LegacyRenderStyle: // mainly for ZScript which does not handle FRenderStyle that well. - parms->style = (ERenderStyle)ListGetInt(tags); - break; - - case DTA_Desaturate: - parms->desaturate = ListGetInt(tags); - break; - - case DTA_TextLen: - parms->maxstrlen = ListGetInt(tags); - break; - - case DTA_CellX: - parms->cellx = ListGetInt(tags); - break; - - case DTA_CellY: - parms->celly = ListGetInt(tags); - break; - - case DTA_Monospace: - parms->monospace = ListGetInt(tags); - break; - - case DTA_Spacing: - parms->spacing = ListGetInt(tags); - break; - - case DTA_Burn: - parms->burn = true; - break; - - } - tag = ListGetInt(tags); - } - ListEnd(tags); - - if (parms->uclip >= parms->dclip || parms->lclip >= parms->rclip) - { - return false; - } - - if (img != NULL) - { - SetTextureParms(parms, img, x, y); - - if (parms->destwidth <= 0 || parms->destheight <= 0) - { - return false; - } - } - - if (parms->style.BlendOp == 255) - { - if (fillcolorset) - { - if (parms->alphaChannel) - { - parms->style = STYLE_Shaded; - } - else if (parms->Alpha < 1.f) - { - parms->style = STYLE_TranslucentStencil; - } - else - { - parms->style = STYLE_Stencil; - } - } - else //if (parms->Alpha < 1.f) - { - parms->style = STYLE_Translucent; - } - /* - else - { - parms->style = STYLE_Normal; - } - */ - } - return true; -} - -//========================================================================== -// -// Coordinate conversion -// -//========================================================================== - -void VirtualToRealCoords(double &x, double &y, double &w, double &h, - double vwidth, double vheight, bool vbottom, bool handleaspect) -{ - float myratio = handleaspect ? ActiveRatio (screen->GetWidth(), screen->GetHeight()) : (4.0f / 3.0f); - - // if 21:9 AR, map to 16:9 for all callers. - // this allows for black bars and stops the stretching of fullscreen images - if (myratio > 1.7f) { - myratio = 16.0f / 9.0f; - } - - double right = x + w; - double bottom = y + h; - - if (myratio > 1.334f) - { // The target surface is either 16:9 or 16:10, so expand the - // specified virtual size to avoid undesired stretching of the - // image. Does not handle non-4:3 virtual sizes. I'll worry about - // those if somebody expresses a desire to use them. - x = (x - vwidth * 0.5) * screen->GetWidth() * 960 / (vwidth * AspectBaseWidth(myratio)) + screen->GetWidth() * 0.5; - w = (right - vwidth * 0.5) * screen->GetWidth() * 960 / (vwidth * AspectBaseWidth(myratio)) + screen->GetWidth() * 0.5 - x; - } - else - { - x = x * screen->GetWidth() / vwidth; - w = right * screen->GetWidth() / vwidth - x; - } - if (AspectTallerThanWide(myratio)) - { // The target surface is 5:4 - y = (y - vheight * 0.5) * screen->GetHeight() * 600 / (vheight * AspectBaseHeight(myratio)) + screen->GetHeight() * 0.5; - h = (bottom - vheight * 0.5) * screen->GetHeight() * 600 / (vheight * AspectBaseHeight(myratio)) + screen->GetHeight() * 0.5 - y; - if (vbottom) - { - y += (screen->GetHeight() - screen->GetHeight() * AspectMultiplier(myratio) / 48.0) * 0.5; - } - } - else - { - y = y * screen->GetHeight() / vheight; - h = bottom * screen->GetHeight() / vheight - y; - } -} - diff --git a/source/core/2d/v_draw.h b/source/core/2d/v_draw.h deleted file mode 100644 index f7868bd80..000000000 --- a/source/core/2d/v_draw.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "drawparms.h" -#include "c_cvars.h" -#include "v_video.h" -// Undo Windows's forced #defines -#ifdef DrawText -#undef DrawText -#endif - -extern int32_t xdim, ydim; - -int GetUIScale(int altval); -int GetConScale(int altval); - - -// [RH] Stretch values to make a 320x200 image best fit the screen -// without using fractional steppings -extern int CleanXfac, CleanYfac; - -// [RH] Effective screen sizes that the above scale values give you -extern int CleanWidth, CleanHeight; - -// Above minus 1 (or 1, if they are already 1) -extern int CleanXfac_1, CleanYfac_1, CleanWidth_1, CleanHeight_1; - - -bool SetTextureParms(DrawParms *parms, FTexture *img, double xx, double yy); -bool ParseDrawTextureTags(FTexture *img, double x, double y, uint32_t tag, Va_List& tags, DrawParms *parms, bool fortext); -void VirtualToRealCoords(double &x, double &y, double &w, double &h, double vwidth, double vheight, bool vbottom, bool handleaspect); -//int ActiveFakeRatio(int width, int height); -float ActiveRatio(int width, int height, float* trueratio); -int CheckRatio(int width, int height, int* trueratio); -int AspectBaseWidth(float aspect);; -int AspectBaseHeight(float aspect); -double AspectPspriteOffset(float aspect); -int AspectMultiplier(float aspect); -bool AspectTallerThanWide(float aspect); -void ScaleWithAspect(int& w, int& h, int Width, int Height); -void V_UpdateModeSize(int width, int height); - -EXTERN_CVAR(Int, con_scaletext) // Scale notify text at high resolutions? -EXTERN_CVAR(Int, con_scale) - diff --git a/source/core/2d/v_text.h b/source/core/2d/v_text.h deleted file mode 100644 index f90cd542c..000000000 --- a/source/core/2d/v_text.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -** v_text.h -** -**--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit -** All rights reserved. -** -** Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions -** are met: -** -** 1. Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** 2. Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in the -** documentation and/or other materials provided with the distribution. -** 3. The name of the author may not be used to endorse or promote products -** derived from this software without specific prior written permission. -** -** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -**--------------------------------------------------------------------------- -** -*/ - -#ifndef __V_TEXT_H__ -#define __V_TEXT_H__ - -#include "zstring.h" -#include "tarray.h" -#include "printf.h" - -class FFont; - -struct FBrokenLines -{ - unsigned Width; - FString Text; -}; - -#define TEXTCOLOR_ESCAPE '\034' -#define TEXTCOLOR_ESCAPESTR "\034" - -#define TEXTCOLOR_NORMAL "\034-" -#define TEXTCOLOR_BOLD "\034+" - -#define TEXTCOLOR_CHAT "\034*" -#define TEXTCOLOR_TEAMCHAT "\034!" - -#define OSDTEXT_DEFAULT TEXTCOLOR_GRAY -#define OSDTEXT_DARKRED TEXTCOLOR_DARKRED -#define OSDTEXT_GREEN TEXTCOLOR_GREEN -#define OSDTEXT_RED TEXTCOLOR_RED -#define OSDTEXT_YELLOW TEXTCOLOR_GOLD - -#define OSDTEXT_BRIGHT "" - -#define OSD_ERROR TEXTCOLOR_RED - - -extern int NumTextColors; - -TArray V_BreakLines (FFont *font, int maxwidth, const uint8_t *str, bool preservecolor = false); -inline TArray V_BreakLines (FFont *font, int maxwidth, const char *str, bool preservecolor = false) - { return V_BreakLines (font, maxwidth, (const uint8_t *)str, preservecolor); } -inline TArray V_BreakLines (FFont *font, int maxwidth, const FString &str, bool preservecolor = false) - { return V_BreakLines (font, maxwidth, (const uint8_t *)str.GetChars(), preservecolor); } - -#endif //__V_TEXT_H__ diff --git a/source/core/console/c_console.cpp b/source/core/console/c_console.cpp index 3da41fdfc..89f9cf903 100644 --- a/source/core/console/c_console.cpp +++ b/source/core/console/c_console.cpp @@ -60,6 +60,8 @@ #include "s_soundinternal.h" #include "engineerrors.h" #include "gamecontrol.h" +#include "v_video.h" +#include "v_draw.h" #define LEFTMARGIN 8 #define RIGHTMARGIN 8 @@ -276,7 +278,7 @@ public: unsigned LengthCells = CalcCellSize((unsigned)Text.length()); int n = StartPosCells; - unsigned cols = ConCols / active_con_scale(); + unsigned cols = ConCols / active_con_scale(twod); if (StartPosCells >= LengthCells) { // Start of visible line is beyond end of line @@ -781,7 +783,7 @@ void FNotifyBuffer::AddString(int printlevel, FString source) con_notifylines == 0) return; - width = screen->GetWidth() / active_con_scaletext(generic_ui); + width = screen->GetWidth() / active_con_scaletext(twod, generic_ui); FFont *font = generic_ui ? NewSmallFont : AlternativeSmallFont; if (font == nullptr) return; // Without an initialized font we cannot handle the message (this is for those which come here before the font system is ready.) @@ -1101,7 +1103,7 @@ void FNotifyBuffer::Draw() else color = PrintColors[notify.PrintLevel]; - int scale = active_con_scaletext(generic_ui); + int scale = active_con_scaletext(twod, generic_ui); if (!center) DrawText (twod, font, color, 0, line, notify.Text, DTA_VirtualWidth, screen->GetWidth() / scale, @@ -1135,7 +1137,7 @@ void C_DrawConsole () static int oldbottom = 0; int lines, left, offset; - int textScale = active_con_scale(); + int textScale = active_con_scale(twod); left = LEFTMARGIN; lines = (ConBottom/textScale-CurrentConsoleFont->GetHeight()*2)/CurrentConsoleFont->GetHeight(); @@ -1383,7 +1385,7 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer) case GK_PGUP: if (ev->data3 & (GKM_SHIFT|GKM_CTRL)) { // Scroll console buffer up one page - RowAdjust += (screen->GetHeight()-4)/active_con_scale() / + RowAdjust += (screen->GetHeight()-4)/active_con_scale(twod) / ((/*gamestate == GS_FULLCONSOLE || gamestate == GS_STARTUP*/false) ? CurrentConsoleFont->GetHeight() : CurrentConsoleFont->GetHeight()*2) - 3; } else if (RowAdjust < conbuffer->GetFormattedLineCount()) @@ -1406,7 +1408,7 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer) case GK_PGDN: if (ev->data3 & (GKM_SHIFT|GKM_CTRL)) { // Scroll console buffer down one page - const int scrollamt = (screen->GetHeight()-4)/active_con_scale() / + const int scrollamt = (screen->GetHeight()-4)/active_con_scale(twod) / ((/*gamestate == GS_FULLCONSOLE || gamestate == GS_STARTUP*/false) ? CurrentConsoleFont->GetHeight() : CurrentConsoleFont->GetHeight()*2) - 3; if (RowAdjust < scrollamt) { @@ -2047,7 +2049,7 @@ static bool C_TabCompleteList () Printf ("%s%-*s", colorcode, int(maxwidth), TabCommands[i].TabName.GetChars()); x += maxwidth; - if (x > ConCols / active_con_scale() - maxwidth) + if (x > ConCols / active_con_scale(twod) - maxwidth) { x = 0; Printf ("\n"); diff --git a/source/core/inputstate.cpp b/source/core/inputstate.cpp index 2c72520ea..bc38b34d0 100644 --- a/source/core/inputstate.cpp +++ b/source/core/inputstate.cpp @@ -35,6 +35,7 @@ #include "v_draw.h" #include "build.h" #include "gamecvars.h" +#include "v_video.h" int GUICapture = false; diff --git a/source/core/menu/joystickmenu.cpp b/source/core/menu/joystickmenu.cpp index bbdf92421..f25c11163 100644 --- a/source/core/menu/joystickmenu.cpp +++ b/source/core/menu/joystickmenu.cpp @@ -43,6 +43,7 @@ #include "d_event.h" #include "d_gui.h" #include "input/m_joy.h" +#include "v_video.h" #define NO_IMP #include "optionmenuitems.h" diff --git a/source/core/menu/listmenu.cpp b/source/core/menu/listmenu.cpp index 8528b02f2..aa23b676d 100644 --- a/source/core/menu/listmenu.cpp +++ b/source/core/menu/listmenu.cpp @@ -42,6 +42,7 @@ #include "baselayer.h" #include "gamecontrol.h" #include "build.h" +#include "v_video.h" //============================================================================= // diff --git a/source/core/menu/loadsavemenu.cpp b/source/core/menu/loadsavemenu.cpp index 64dfedfa1..3e8dfdabc 100644 --- a/source/core/menu/loadsavemenu.cpp +++ b/source/core/menu/loadsavemenu.cpp @@ -47,6 +47,7 @@ #include "savegamehelp.h" #include "i_specialpaths.h" #include "findfile.h" +#include "v_video.h" diff --git a/source/core/menu/menu.cpp b/source/core/menu/menu.cpp index c589fcc9b..b0e6123be 100644 --- a/source/core/menu/menu.cpp +++ b/source/core/menu/menu.cpp @@ -55,6 +55,7 @@ #include "input/m_joy.h" #include "raze_sound.h" #include "texturemanager.h" +#include "v_video.h" void RegisterDukeMenus(); void RegisterRedneckMenus(); diff --git a/source/core/menu/menu.h b/source/core/menu/menu.h index d9a491473..2d9621c38 100644 --- a/source/core/menu/menu.h +++ b/source/core/menu/menu.h @@ -4,12 +4,13 @@ -#include "c_cvars.h" #include "v_font.h" +#include "c_cvars.h" #include "version.h" #include "textures.h" #include "zstring.h" #include "baselayer.h" +#include "v_draw.h" EXTERN_CVAR(Float, snd_menuvolume) EXTERN_CVAR(Int, m_use_mouse); @@ -217,28 +218,7 @@ struct FListMenuDescriptor : public FMenuDescriptor Reset(); } - void Reset() - { - // Reset the default settings (ignore all other values in the struct) - mSelectOfsX = 0; - mSelectOfsY = 0; - mSelector = nullptr; - mDisplayTop = 0; - mXpos = 0; - mYpos = 0; - mLinespacing = 0; - mNetgameMessage = ""; - mFont = NULL; - mFontColor = CR_UNTRANSLATED; - mFontColor2 = CR_UNTRANSLATED; - mScriptId = -1; - mSecondaryId = 0; - mNativeFontNum = NIT_BigFont; - mNativePalNum = NIT_ActiveColor; - mNativeFontScale = 1.f; - mFlags = 0; - mSpacing = 0; - } + void Reset(); }; struct FOptionMenuSettings diff --git a/source/core/menu/menudef.cpp b/source/core/menu/menudef.cpp index 426558f8a..32774d9d2 100644 --- a/source/core/menu/menudef.cpp +++ b/source/core/menu/menudef.cpp @@ -49,6 +49,7 @@ #include "i_soundfont.h" #include "zstring.h" #include "texturemanager.h" +#include "v_video.h" #include // Menu-relevant content that gets filled in by scripts. This will get processed after the game has loaded. @@ -1539,3 +1540,26 @@ int M_GetDefaultSkill() { return gDefaultSkill; } + +void FListMenuDescriptor::Reset() +{ + // Reset the default settings (ignore all other values in the struct) + mSelectOfsX = 0; + mSelectOfsY = 0; + mSelector = nullptr; + mDisplayTop = 0; + mXpos = 0; + mYpos = 0; + mLinespacing = 0; + mNetgameMessage = ""; + mFont = NULL; + mFontColor = CR_UNTRANSLATED; + mFontColor2 = CR_UNTRANSLATED; + mScriptId = -1; + mSecondaryId = 0; + mNativeFontNum = NIT_BigFont; + mNativePalNum = NIT_ActiveColor; + mNativeFontScale = 1.f; + mFlags = 0; + mSpacing = 0; +} diff --git a/source/core/menu/menuinput.cpp b/source/core/menu/menuinput.cpp index 8f7d07b7c..d04e0f130 100644 --- a/source/core/menu/menuinput.cpp +++ b/source/core/menu/menuinput.cpp @@ -40,6 +40,7 @@ #include "v_font.h" #include "v_text.h" #include "v_draw.h" +#include "v_video.h" #define INPUTGRID_WIDTH 13 #define INPUTGRID_HEIGHT 5 diff --git a/source/core/menu/messagebox.cpp b/source/core/menu/messagebox.cpp index c990426e9..4fdf781b6 100644 --- a/source/core/menu/messagebox.cpp +++ b/source/core/menu/messagebox.cpp @@ -41,6 +41,7 @@ #include "c_dispatch.h" #include "statistics.h" #include "v_2ddrawer.h" +#include "v_video.h" extern FSaveGameNode *quickSaveSlot; diff --git a/source/core/menu/optionmenu.cpp b/source/core/menu/optionmenu.cpp index 43770e808..1558a9099 100644 --- a/source/core/menu/optionmenu.cpp +++ b/source/core/menu/optionmenu.cpp @@ -45,6 +45,7 @@ #include "menu/menu.h" #include "v_draw.h" #include "v_2ddrawer.h" +#include "v_video.h" //============================================================================= // diff --git a/source/core/menu/optionmenuitems.h b/source/core/menu/optionmenuitems.h index 7a1a3a7a9..47523fe09 100644 --- a/source/core/menu/optionmenuitems.h +++ b/source/core/menu/optionmenuitems.h @@ -223,7 +223,7 @@ public: { if (mCenter) { - indent = (screen->GetWidth() / 2); + indent = (twod->GetWidth() / 2); } drawLabel(indent, y, selected? OptionSettings.mFontColorSelection : OptionSettings.mFontColor, isGrayed()); @@ -543,7 +543,7 @@ public: { const char *txt = GStrings.localize(mCurrent? mAltText.GetChars() : mLabel.GetChars()); int w = OptionWidth(txt) * CleanXfac_1; - int x = (screen->GetWidth() - w) / 2; + int x = (twod->GetWidth() - w) / 2; drawText(x, y, mColor, txt); return -1; } @@ -631,7 +631,7 @@ public: maxlen = NewSmallFont->StringWidth(textbuf) * CleanXfac_1; } - mSliderShort = right + maxlen > screen->GetWidth(); + mSliderShort = right + maxlen > twod->GetWidth(); if (!mSliderShort) { @@ -646,7 +646,7 @@ public: right -= 5*8*CleanXfac_1; } - if (fracdigits >= 0 && right + maxlen <= screen->GetWidth()) + if (fracdigits >= 0 && right + maxlen <= twod->GetWidth()) { snprintf(textbuf, countof(textbuf), "%.*f", fracdigits, cur); drawText(right, y, CR_DARKGRAY, textbuf); @@ -895,7 +895,7 @@ public: // reposition the text so that the cursor is visible when in entering mode. FString text = Represent(); int tlen = NewSmallFont->StringWidth(text) * CleanXfac_1; - int newindent = screen->GetWidth() - tlen - CursorSpace(); + int newindent = twod->GetWidth() - tlen - CursorSpace(); if (newindent < indent) indent = newindent; } return FOptionMenuFieldBase::Draw(desc, y, indent, selected); diff --git a/source/core/rendering/gl/system/gl_framebuffer.cpp b/source/core/rendering/gl/system/gl_framebuffer.cpp index 91ebca2bb..bd48bb054 100644 --- a/source/core/rendering/gl/system/gl_framebuffer.cpp +++ b/source/core/rendering/gl/system/gl_framebuffer.cpp @@ -40,6 +40,7 @@ #include "printf.h" #include "templates.h" #include "palette.h" +#include "build.h" #include "glbackend/glbackend.h" #include "gl_load/gl_interface.h" diff --git a/source/core/rendering/r_videoscale.cpp b/source/core/rendering/r_videoscale.cpp index d4daa51c5..ef21c8141 100644 --- a/source/core/rendering/r_videoscale.cpp +++ b/source/core/rendering/r_videoscale.cpp @@ -37,6 +37,7 @@ #include "templates.h" #include "r_videoscale.h" #include "cmdlib.h" +#include "v_draw.h" #include "c_console.h" #include "menu/menu.h" diff --git a/source/core/rendering/v_framebuffer.cpp b/source/core/rendering/v_framebuffer.cpp index bc974f159..c5765d88d 100644 --- a/source/core/rendering/v_framebuffer.cpp +++ b/source/core/rendering/v_framebuffer.cpp @@ -112,6 +112,8 @@ void DFrameBuffer::SetSize(int width, int height) { Width = ViewportScaledWidth(width, height); Height = ViewportScaledHeight(width, height); + twodgen.SetSize(Width, Height); + twodpsp.SetSize(Width, Height); } //========================================================================== @@ -129,7 +131,7 @@ void DFrameBuffer::DrawRateStuff () { FString fpsbuff = gi->statFPS(); - int textScale = active_con_scale(); + int textScale = active_con_scale(twod); int rate_x = Width / textScale - NewConsoleFont->StringWidth(&fpsbuff[0]); twod->AddColorOnlyQuad(rate_x * textScale, 0, Width, NewConsoleFont->GetHeight() * textScale, MAKEARGB(255,0,0,0)); DrawText (twod, NewConsoleFont, CR_WHITE, rate_x, 0, (char *)&fpsbuff[0], diff --git a/source/core/rendering/v_video.cpp b/source/core/rendering/v_video.cpp index e460f7b2c..99afef84e 100644 --- a/source/core/rendering/v_video.cpp +++ b/source/core/rendering/v_video.cpp @@ -370,6 +370,7 @@ void V_InitScreen() void V_Init2() { palettePostLoadLookups(); + twod = &twodgen; float gamma = static_cast(screen)->Gamma; @@ -408,153 +409,7 @@ void V_Init2() //setsizeneeded = true; } -// Helper for ActiveRatio and CheckRatio. Returns the forced ratio type, or -1 if none. -static int ActiveFakeRatio(int width, int height) -{ - int fakeratio = -1; - if ((vid_aspect >= 1) && (vid_aspect <= 6)) - { - // [SP] User wants to force aspect ratio; let them. - fakeratio = int(vid_aspect); - if (fakeratio == 3) - { - fakeratio = 0; - } - else if (fakeratio == 5) - { - fakeratio = 3; - } - } - return fakeratio; -} -// Active screen ratio based on cvars and size -float ActiveRatio(int width, int height, float *trueratio) -{ - static float forcedRatioTypes[] = - { - 4 / 3.0f, - 16 / 9.0f, - 16 / 10.0f, - 17 / 10.0f, - 5 / 4.0f, - 17 / 10.0f, - 21 / 9.0f - }; - - float ratio = width / (float)height; - int fakeratio = ActiveFakeRatio(width, height); - - if (trueratio) - *trueratio = ratio; - return (fakeratio != -1) ? forcedRatioTypes[fakeratio] : ratio; -} - - -// Tries to guess the physical dimensions of the screen based on the -// screen's pixel dimensions. Can return: -// 0: 4:3 -// 1: 16:9 -// 2: 16:10 -// 3: 17:10 -// 4: 5:4 -// 5: 17:10 (redundant, never returned) -// 6: 21:9 -int CheckRatio (int width, int height, int *trueratio) -{ - float aspect = width / (float)height; - - static std::pair ratioTypes[] = - { - { 21 / 9.0f , 6 }, - { 16 / 9.0f , 1 }, - { 17 / 10.0f , 3 }, - { 16 / 10.0f , 2 }, - { 4 / 3.0f , 0 }, - { 5 / 4.0f , 4 }, - { 0.0f, 0 } - }; - - int ratio = ratioTypes[0].second; - float distance = fabs(ratioTypes[0].first - aspect); - for (int i = 1; ratioTypes[i].first != 0.0f; i++) - { - float d = fabs(ratioTypes[i].first - aspect); - if (d < distance) - { - ratio = ratioTypes[i].second; - distance = d; - } - } - - int fakeratio = ActiveFakeRatio(width, height); - if (fakeratio == -1) - fakeratio = ratio; - - if (trueratio) - *trueratio = ratio; - return fakeratio; -} - -int AspectBaseWidth(float aspect) -{ - return (int)round(240.0f * aspect * 3.0f); -} - -int AspectBaseHeight(float aspect) -{ - if (!AspectTallerThanWide(aspect)) - return (int)round(200.0f * (320.0f / (AspectBaseWidth(aspect) / 3.0f)) * 3.0f); - else - return (int)round((200.0f * (4.0f / 3.0f)) / aspect * 3.0f); -} - -double AspectPspriteOffset(float aspect) -{ - if (!AspectTallerThanWide(aspect)) - return 0.0; - else - return ((4.0 / 3.0) / aspect - 1.0) * 97.5; -} - -int AspectMultiplier(float aspect) -{ - if (!AspectTallerThanWide(aspect)) - return (int)round(320.0f / (AspectBaseWidth(aspect) / 3.0f) * 48.0f); - else - return (int)round(200.0f / (AspectBaseHeight(aspect) / 3.0f) * 48.0f); -} - -bool AspectTallerThanWide(float aspect) -{ - return aspect < 1.333f; -} - -void ScaleWithAspect (int &w, int &h, int Width, int Height) -{ - int resRatio = CheckRatio (Width, Height); - int screenRatio; - CheckRatio (w, h, &screenRatio); - if (resRatio == screenRatio) - return; - - double yratio; - switch(resRatio) - { - case 0: yratio = 4./3.; break; - case 1: yratio = 16./9.; break; - case 2: yratio = 16./10.; break; - case 3: yratio = 17./10.; break; - case 4: yratio = 5./4.; break; - case 6: yratio = 21./9.; break; - default: return; - } - double y = w/yratio; - if (y > h) - w = static_cast(h * yratio); - else - h = static_cast(y); -} CCMD(vid_setsize) { @@ -592,3 +447,6 @@ CCMD(vid_listadapters) } bool vid_hdr_active = false; +F2DDrawer twodpsp, twodgen; +CVAR(Float, transsouls, 1, 0) +CVAR(Int, uiscale, 0, CVAR_ARCHIVE) \ No newline at end of file diff --git a/source/core/rendering/v_video.h b/source/core/rendering/v_video.h index 58b52055e..aefb66f09 100644 --- a/source/core/rendering/v_video.h +++ b/source/core/rendering/v_video.h @@ -412,38 +412,11 @@ void V_Init2 (); void V_Shutdown (); -int CheckRatio (int width, int height, int *trueratio=NULL); -static inline int CheckRatio (double width, double height) { return CheckRatio(int(width), int(height)); } inline bool IsRatioWidescreen(int ratio) { return (ratio & 3) != 0; } -float ActiveRatio (int width, int height, float *trueratio = NULL); -static inline double ActiveRatio (double width, double height) { return ActiveRatio(int(width), int(height)); } - -int AspectBaseWidth(float aspect); -int AspectBaseHeight(float aspect); -double AspectPspriteOffset(float aspect); -int AspectMultiplier(float aspect); -bool AspectTallerThanWide(float aspect); void ScaleWithAspect(int &w, int &h, int Width, int Height); -int GetUIScale(int altval); -int GetConScale(int altval); - extern bool setsizeneeded, setmodeneeded; -EXTERN_CVAR(Int, uiscale); -EXTERN_CVAR(Int, con_scaletext); -EXTERN_CVAR(Int, con_scale); - -inline int active_con_scaletext(bool newconfont = false) -{ - return newconfont? GetConScale(con_scaletext) : GetUIScale(con_scaletext); -} - -inline int active_con_scale() -{ - return GetConScale(con_scale); -} - #endif // __V_VIDEO_H__ diff --git a/source/core/secrets.cpp b/source/core/secrets.cpp index 81337b8f0..71cf9d526 100644 --- a/source/core/secrets.cpp +++ b/source/core/secrets.cpp @@ -8,6 +8,9 @@ #include "v_draw.h" #include "serializer.h" #include "mapinfo.h" +#include "v_video.h" +#include "v_text.h" +#include "c_cvars.h" // Unlike in GZDoom we have to maintain this list here, because we got different game frontents that all store this info differently. // So the games will have to report the credited secrets so that this code can keep track of how to display them. diff --git a/source/duke3d/src/actors.cpp b/source/duke3d/src/actors.cpp index 0aa5d4ea4..81ac60e0b 100644 --- a/source/duke3d/src/actors.cpp +++ b/source/duke3d/src/actors.cpp @@ -30,6 +30,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "duke3d.h" #include "sounds.h" +#include "v_text.h" +#include "printf.h" BEGIN_DUKE_NS @@ -689,7 +691,7 @@ void A_DeleteSprite(int spriteNum) { if (EDUKE32_PREDICT_FALSE(block_deletesprite)) { - Printf(OSD_ERROR "A_DeleteSprite(): tried to remove sprite %d in EVENT_EGS\n", spriteNum); + Printf(TEXTCOLOR_RED "A_DeleteSprite(): tried to remove sprite %d in EVENT_EGS\n", spriteNum); return; } @@ -1402,7 +1404,7 @@ ACTOR_STATIC void G_MovePlayers(void) if (ud.god == 0) if (G_CheckForSpaceCeiling(pSprite->sectnum) || G_CheckForSpaceFloor(pSprite->sectnum)) { - Printf(OSD_ERROR "%s: player killed by space sector!\n", EDUKE32_FUNCTION); + Printf(TEXTCOLOR_RED "%s: player killed by space sector!\n", EDUKE32_FUNCTION); P_QuickKill(pPlayer); } } diff --git a/source/duke3d/src/demo.cpp b/source/duke3d/src/demo.cpp index 785271fd7..d62848b2c 100644 --- a/source/duke3d/src/demo.cpp +++ b/source/duke3d/src/demo.cpp @@ -101,7 +101,7 @@ static int32_t G_OpenDemoRead(int32_t g_whichDemo) // 0 = mine i = sv_loadsnapshot(g_demo_recFilePtr, -g_whichDemo, &saveh); if (i) { - Printf(OSD_ERROR "There were errors opening demo %d (code: %d).\n", g_whichDemo, i); + Printf(TEXTCOLOR_RED "There were errors opening demo %d (code: %d).\n", g_whichDemo, i); g_demo_recFilePtr.Close(); return 0; } @@ -656,7 +656,7 @@ RECHECK: if (0) { corrupt: - Printf(OSD_ERROR "Demo %d is corrupt (code %d).\n", g_whichDemo-1, corruptcode); + Printf(TEXTCOLOR_RED "Demo %d is corrupt (code %d).\n", g_whichDemo-1, corruptcode); nextdemo: M_StartControlPanel(false); nextdemo_nomenu: diff --git a/source/duke3d/src/game.cpp b/source/duke3d/src/game.cpp index f156e1d72..5557d334a 100644 --- a/source/duke3d/src/game.cpp +++ b/source/duke3d/src/game.cpp @@ -674,7 +674,7 @@ void G_DrawRooms(int32_t playerNum, int32_t smoothRatio) { #ifdef DEBUGGINGAIDS if (EDUKE32_PREDICT_FALSE(noDraw != 0)) - Printf(OSD_ERROR "ERROR: EVENT_DISPLAYROOMSCAMERA return value must be 0 or 1, " + Printf(TEXTCOLOR_RED "ERROR: EVENT_DISPLAYROOMSCAMERA return value must be 0 or 1, " "other values are reserved.\n"); #endif @@ -840,7 +840,7 @@ void G_DrawRooms(int32_t playerNum, int32_t smoothRatio) { #ifdef DEBUGGINGAIDS if (EDUKE32_PREDICT_FALSE(noDraw != 0)) - Printf(OSD_ERROR "ERROR: EVENT_DISPLAYROOMS return value must be 0 or 1, " + Printf(TEXTCOLOR_RED "ERROR: EVENT_DISPLAYROOMS return value must be 0 or 1, " "other values are reserved.\n"); #endif screen->BeginScene(); @@ -2477,7 +2477,7 @@ int A_Spawn(int spriteNum, int tileNum) if (EDUKE32_PREDICT_FALSE(pSprite->hitag && pSprite->picnum == WATERBUBBLEMAKER)) { // JBF 20030913: Pisses off X_Move(), eg. in bobsp2 - Printf(OSD_ERROR "WARNING: WATERBUBBLEMAKER %d @ %d,%d with hitag!=0. Applying fixup.\n", + Printf(TEXTCOLOR_RED "WARNING: WATERBUBBLEMAKER %d @ %d,%d with hitag!=0. Applying fixup.\n", newSprite,TrackerCast(pSprite->x),TrackerCast(pSprite->y)); pSprite->hitag = 0; } @@ -2735,7 +2735,7 @@ int A_Spawn(int spriteNum, int tileNum) // use elevator sector's ceiling as heuristic T4(newSprite) = sector[sectNum].ceilingz; - Printf(OSD_ERROR "WARNING: SE17 sprite %d using own sector's ceilingz to " + Printf(TEXTCOLOR_RED "WARNING: SE17 sprite %d using own sector's ceilingz to " "determine when to warp. Sector %d adjacent to a door?\n", newSprite, sectNum); } @@ -2749,7 +2749,7 @@ int A_Spawn(int spriteNum, int tileNum) // heuristic T5(newSprite) = sector[sectNum].floorz; - Printf(OSD_ERROR "WARNING: SE17 sprite %d using own sector %d's floorz.\n", + Printf(TEXTCOLOR_RED "WARNING: SE17 sprite %d using own sector %d's floorz.\n", newSprite, sectNum); } @@ -2956,7 +2956,7 @@ int A_Spawn(int spriteNum, int tileNum) } if (EDUKE32_PREDICT_FALSE(spriteNum == -1)) { - Printf(OSD_ERROR "Found lonely Sector Effector (lotag 0) at (%d,%d)\n", + Printf(TEXTCOLOR_RED "Found lonely Sector Effector (lotag 0) at (%d,%d)\n", TrackerCast(pSprite->x),TrackerCast(pSprite->y)); changespritestat(newSprite, STAT_ACTOR); goto SPAWN_END; @@ -3998,7 +3998,7 @@ skip: #ifdef DEBUGGINGAIDS // A negative actor[i].dispicnum used to mean 'no floor shadow please', but // that was a bad hack since the value could propagate to sprite[].picnum. - Printf(OSD_ERROR "actor[%d].dispicnum = %d\n", i, actor[i].dispicnum); + Printf(TEXTCOLOR_RED "actor[%d].dispicnum = %d\n", i, actor[i].dispicnum); #endif actor[i].dispicnum=0; continue; diff --git a/source/duke3d/src/gameexec.cpp b/source/duke3d/src/gameexec.cpp index dbc9b07e5..6147b2426 100644 --- a/source/duke3d/src/gameexec.cpp +++ b/source/duke3d/src/gameexec.cpp @@ -537,7 +537,7 @@ GAMEEXEC_STATIC void VM_AlterAng(int32_t const moveFlags) { AC_MOVE_ID(vm.pData) = 0; - Printf(OSD_ERROR "bad moveptr for actor %d (%d)!\n", vm.spriteNum, vm.pUSprite->picnum); + Printf(TEXTCOLOR_RED "bad moveptr for actor %d (%d)!\n", vm.spriteNum, vm.pUSprite->picnum); return; } @@ -694,7 +694,7 @@ GAMEEXEC_STATIC void VM_Move(void) if (EDUKE32_PREDICT_FALSE((unsigned)AC_MOVE_ID(vm.pData) >= (unsigned)g_scriptSize-1)) { AC_MOVE_ID(vm.pData) = 0; - Printf(OSD_ERROR "clearing bad moveptr for actor %d (%d)\n", vm.spriteNum, vm.pUSprite->picnum); + Printf(TEXTCOLOR_RED "clearing bad moveptr for actor %d (%d)\n", vm.spriteNum, vm.pUSprite->picnum); return; } @@ -1268,7 +1268,7 @@ static void SetArray(int const arrayNum, int const arrayIndex, int const newValu { if (EDUKE32_PREDICT_FALSE((unsigned)arrayNum >= (unsigned)g_gameArrayCount || (unsigned)arrayIndex >= (unsigned)aGameArrays[arrayNum].size)) { - Printf(OSD_ERROR "Gv_SetVar(): tried to set invalid array %d or index out of bounds from " + Printf(TEXTCOLOR_RED "Gv_SetVar(): tried to set invalid array %d or index out of bounds from " "sprite %d (%d), player %d\n", (int)arrayNum, vm.spriteNum, vm.pUSprite->picnum, vm.playerNum); vm.flags |= VM_RETURN; @@ -1279,7 +1279,7 @@ static void SetArray(int const arrayNum, int const arrayIndex, int const newValu if (EDUKE32_PREDICT_FALSE(arr.flags & GAMEARRAY_READONLY)) { - Printf(OSD_ERROR "Tried to set value in read-only array `%s'", arr.szLabel); + Printf(TEXTCOLOR_RED "Tried to set value in read-only array `%s'", arr.szLabel); vm.flags |= VM_RETURN; return; } @@ -1310,7 +1310,7 @@ static void ResizeArray(int const arrayNum, int const newSize) if (newSize == oldSize || newSize < 0) return; #if 0 - Printf(OSDTEXT_GREEN "CON_RESIZEARRAY: resizing array %s from %d to %d\n", + Printf(TEXTCOLOR_GREEN "CON_RESIZEARRAY: resizing array %s from %d to %d\n", array.szLabel, array.size, newSize); #endif if (newSize == 0) @@ -2834,7 +2834,7 @@ GAMEEXEC_STATIC void VM_Execute(int const loop /*= false*/) return; break; badindex: - Printf(OSD_ERROR "Line %d, for %s: index %d out of range!\n", VM_DECODE_LINE_NUMBER(g_tw), iter_tokens[iterType].token, nIndex); + Printf(TEXTCOLOR_RED "Line %d, for %s: index %d out of range!\n", VM_DECODE_LINE_NUMBER(g_tw), iter_tokens[iterType].token, nIndex); vm.flags |= VM_RETURN; dispatch(); } @@ -5197,7 +5197,7 @@ badindex: index = Gv_GetVar(*insptr++); if (EDUKE32_PREDICT_TRUE((unsigned)index < (unsigned)aGameArrays[lVarID].size)) { - Printf(OSDTEXT_GREEN "CONLOGVAR: L=%d %s[%d] =%d\n", VM_DECODE_LINE_NUMBER(g_tw), aGameArrays[lVarID].szLabel, index, + Printf(TEXTCOLOR_GREEN "CONLOGVAR: L=%d %s[%d] =%d\n", VM_DECODE_LINE_NUMBER(g_tw), aGameArrays[lVarID].szLabel, index, (int32_t)(m * Gv_GetArrayValue(lVarID, index))); dispatch(); } @@ -5221,7 +5221,7 @@ badindex: CON_ERRPRINTF("invalid array index\n"); abort_after_error(); } - Printf(OSDTEXT_GREEN "CONLOGVAR: L=%d %d %d\n", VM_DECODE_LINE_NUMBER(g_tw), index, Gv_GetVar(*insptr++, index, vm.playerNum)); + Printf(TEXTCOLOR_GREEN "CONLOGVAR: L=%d %d %d\n", VM_DECODE_LINE_NUMBER(g_tw), index, Gv_GetVar(*insptr++, index, vm.playerNum)); dispatch(); } } @@ -5259,7 +5259,7 @@ badindex: Bstrcat(tempbuf, szBuf); Bsprintf(szBuf, " =%d\n", Gv_GetVar(lVarID) * m); Bstrcat(tempbuf, szBuf); - Printf(OSDTEXT_GREEN "%s", tempbuf); + Printf(TEXTCOLOR_GREEN "%s", tempbuf); insptr++; dispatch(); } diff --git a/source/duke3d/src/gamevars.cpp b/source/duke3d/src/gamevars.cpp index fccee3c2b..70d87003d 100644 --- a/source/duke3d/src/gamevars.cpp +++ b/source/duke3d/src/gamevars.cpp @@ -542,7 +542,7 @@ static int Gv_GetVarIndex(const char *szGameLabel) if (EDUKE32_PREDICT_FALSE((unsigned)gameVar >= MAXGAMEVARS)) { - Printf(OSD_ERROR "Gv_GetVarIndex(): INTERNAL ERROR: couldn't find gamevar %s!\n", szGameLabel); + Printf(TEXTCOLOR_RED "Gv_GetVarIndex(): INTERNAL ERROR: couldn't find gamevar %s!\n", szGameLabel); return 0; } @@ -555,7 +555,7 @@ static int Gv_GetArrayIndex(const char *szArrayLabel) if (EDUKE32_PREDICT_FALSE((unsigned)arrayIdx >= MAXGAMEARRAYS)) { - Printf(OSD_ERROR "Gv_GetArrayIndex(): INTERNAL ERROR: couldn't find array %s!\n", szArrayLabel); + Printf(TEXTCOLOR_RED "Gv_GetArrayIndex(): INTERNAL ERROR: couldn't find array %s!\n", szArrayLabel); return 0; } diff --git a/source/duke3d/src/osdcmds.cpp b/source/duke3d/src/osdcmds.cpp index aed9ef0db..30880d711 100644 --- a/source/duke3d/src/osdcmds.cpp +++ b/source/duke3d/src/osdcmds.cpp @@ -46,7 +46,7 @@ static int osdcmd_levelwarp(CCmdFuncPtr parm) int m = atoi(parm->parms[1]); if (e == 0 || m == 0) { - Printf(OSD_ERROR "Invalid level!: E%sL%s\n", parm->parms[0], parm->parms[1]); + Printf(TEXTCOLOR_RED "Invalid level!: E%sL%s\n", parm->parms[0], parm->parms[1]); return OSDCMD_OK; } @@ -82,7 +82,7 @@ static int osdcmd_map(CCmdFuncPtr parm) if (!fileSystem.Lookup(mapname, "MAP")) { - Printf(OSD_ERROR "map: file \"%s\" not found.\n", mapname.GetChars()); + Printf(TEXTCOLOR_RED "map: file \"%s\" not found.\n", mapname.GetChars()); return OSDCMD_OK; } @@ -98,7 +98,7 @@ static int osdcmd_map(CCmdFuncPtr parm) } if (VOLUMEONE) { - Printf(OSD_ERROR "Cannot use user maps in shareware.\n"); + Printf(TEXTCOLOR_RED "Cannot use user maps in shareware.\n"); return OSDCMD_OK; } // Treat as user map diff --git a/source/duke3d/src/player.cpp b/source/duke3d/src/player.cpp index 9f90fc518..43bcf0f5c 100644 --- a/source/duke3d/src/player.cpp +++ b/source/duke3d/src/player.cpp @@ -4969,7 +4969,7 @@ void P_ProcessInput(int playerNum) { if (pSprite->extra > 0 && ud.noclip == 0) { - Printf(OSD_ERROR "%s: player killed by cursectnum == -1!\n", EDUKE32_FUNCTION); + Printf(TEXTCOLOR_RED "%s: player killed by cursectnum == -1!\n", EDUKE32_FUNCTION); P_QuickKill(pPlayer); if (!FURY) A_PlaySound(SQUISHED, pPlayer->i); @@ -5727,7 +5727,7 @@ RECHECK: { if (mashedPotato) { - Printf(OSD_ERROR "%s: player killed by pushmove()!\n", EDUKE32_FUNCTION); + Printf(TEXTCOLOR_RED "%s: player killed by pushmove()!\n", EDUKE32_FUNCTION); P_QuickKill(pPlayer); return; } diff --git a/source/duke3d/src/premap.cpp b/source/duke3d/src/premap.cpp index d44583fe5..f33901424 100644 --- a/source/duke3d/src/premap.cpp +++ b/source/duke3d/src/premap.cpp @@ -1272,7 +1272,7 @@ static void prelevel(int g) } if (missedCloudSectors > 0) - Printf(OSDTEXT_RED "Map warning: have %d unhandled CLOUDYSKIES ceilings.\n", missedCloudSectors); + Printf(TEXTCOLOR_RED "Map warning: have %d unhandled CLOUDYSKIES ceilings.\n", missedCloudSectors); // NOTE: must be safe loop because callbacks could delete sprites. for (int nextSprite, SPRITES_OF_STAT_SAFE(STAT_DEFAULT, i, nextSprite)) @@ -1764,7 +1764,7 @@ int G_EnterLevel(int gameMode) { if (mm.fileName.IsEmpty()) { - Printf(OSDTEXT_RED "Map E%dL%d not defined!\n", ud.volume_number+1, ud.level_number+1); + Printf(TEXTCOLOR_RED "Map E%dL%d not defined!\n", ud.volume_number+1, ud.level_number+1); return 1; } } @@ -1789,7 +1789,7 @@ int G_EnterLevel(int gameMode) { if (engineLoadBoard(boardfilename, 0, &p0.pos, &playerAngle, &p0.cursectnum) < 0) { - Printf(OSD_ERROR "Map \"%s\" not found or invalid map version!\n", boardfilename); + Printf(TEXTCOLOR_RED "Map \"%s\" not found or invalid map version!\n", boardfilename); return 1; } userMapRecord.name = ""; @@ -1803,7 +1803,7 @@ int G_EnterLevel(int gameMode) } else if (engineLoadBoard(mm.fileName, VOLUMEONE, &p0.pos, &playerAngle, &p0.cursectnum) < 0) { - Printf(OSD_ERROR "Map \"%s\" not found or invalid map version!\n", mm.fileName.GetChars()); + Printf(TEXTCOLOR_RED "Map \"%s\" not found or invalid map version!\n", mm.fileName.GetChars()); return 1; } else @@ -1895,11 +1895,11 @@ int G_EnterLevel(int gameMode) } if (G_HaveUserMap()) - Printf(OSDTEXT_YELLOW "%s: %s\n", GStrings("TXT_USERMAP"), boardfilename); + Printf(TEXTCOLOR_GOLD "%s: %s\n", GStrings("TXT_USERMAP"), boardfilename); else if (FURY) - Printf(OSDTEXT_YELLOW "%s: %s\n", GStrings("TXT_ENTERING"), mm.DisplayName()); + Printf(TEXTCOLOR_GOLD "%s: %s\n", GStrings("TXT_ENTERING"), mm.DisplayName()); else - Printf(OSDTEXT_YELLOW "E%dL%d: %s\n", ud.volume_number + 1, ud.level_number + 1, mm.DisplayName()); + Printf(TEXTCOLOR_GOLD "E%dL%d: %s\n", ud.volume_number + 1, ud.level_number + 1, mm.DisplayName()); g_restorePalette = -1; diff --git a/source/duke3d/src/sector.cpp b/source/duke3d/src/sector.cpp index 3f291f67d..78c28676e 100644 --- a/source/duke3d/src/sector.cpp +++ b/source/duke3d/src/sector.cpp @@ -397,7 +397,7 @@ static void G_SetupCamTile(int spriteNum, int tileNum, int smoothRatio) goto finishTileSetup; #ifdef DEBUGGINGAIDS else if (EDUKE32_PREDICT_FALSE(noDraw != 0)) // event return values other than 0 and 1 are reserved - Printf(OSD_ERROR "ERROR: EVENT_DISPLAYROOMSCAMERATILE return value must be 0 or 1, " + Printf(TEXTCOLOR_RED "ERROR: EVENT_DISPLAYROOMSCAMERATILE return value must be 0 or 1, " "other values are reserved.\n"); #endif screen->BeginScene(); diff --git a/source/duke3d/src/text.cpp b/source/duke3d/src/text.cpp index 70935d3d3..cd51778aa 100644 --- a/source/duke3d/src/text.cpp +++ b/source/duke3d/src/text.cpp @@ -355,7 +355,7 @@ void GameInterface::DoPrintMessage(int prio, const char* t) if (p->ftq == QUOTE_RESERVED || p->ftq == QUOTE_RESERVED2) return; if (p == g_player[screenpeek].ps) - Printf(prio | PRINT_NOTIFY, cq ? OSDTEXT_DEFAULT "%s\n" : "%s\n", t); + Printf(prio | PRINT_NOTIFY, cq ? TEXTCOLOR_TAN "%s\n" : "%s\n", t); if (hud_messages == 1) { diff --git a/source/exhumed/src/osdcmds.cpp b/source/exhumed/src/osdcmds.cpp index ef405387a..a43c03a66 100644 --- a/source/exhumed/src/osdcmds.cpp +++ b/source/exhumed/src/osdcmds.cpp @@ -71,7 +71,7 @@ static int osdcmd_map(CCmdFuncPtr parm) if (!fileSystem.Lookup(mapname, "MAP")) { - Printf(OSD_ERROR "map: file \"%s\" not found.\n", mapname.GetChars()); + Printf(TEXTCOLOR_RED "map: file \"%s\" not found.\n", mapname.GetChars()); return OSDCMD_OK; } diff --git a/source/glbackend/hw_draw2d.cpp b/source/glbackend/hw_draw2d.cpp index 4af19143d..adca3a9a4 100644 --- a/source/glbackend/hw_draw2d.cpp +++ b/source/glbackend/hw_draw2d.cpp @@ -42,6 +42,7 @@ #include "palette.h" #include "flatvertices.h" #include "build.h" +#include "v_video.h" extern int16_t numshades; extern TArray matrixArray; @@ -161,34 +162,13 @@ void GLInstance::Draw2D(F2DDrawer *drawer) DisableScissor(); } - //state.SetFog(cmd.mColor1, 0); - SetColor(1, 1, 1); - //state.SetColor(1, 1, 1, 1, cmd.mDesaturate); - if (cmd.mTexture != nullptr) { auto tex = cmd.mTexture; - if (cmd.mType == F2DDrawer::DrawTypeRotateSprite) - { - // todo: Set up hictinting. (broken as the feature is...) - SetShade(cmd.mRemapIndex >> 16, numshades); - SetFadeDisable(false); - auto saved = curbasepal; // screw Build's dependencies on global state variables. We only need to change this for the following SetTexture call. - curbasepal = (cmd.mRemapIndex >> 8) & 0xff; - auto savedf = globalflags; - if (curbasepal > 0) - globalflags |= GLOBAL_NO_GL_FULLBRIGHT; // temp. hack to disable brightmaps. - SetTexture(-1, tex, cmd.mRemapIndex & 0xff, 4/*DAMETH_CLAMPED*/, cmd.mFlags & F2DDrawer::DTF_Wrap ? SamplerRepeat : SamplerClampXY); - curbasepal = saved; - globalflags = savedf; - } - else - { SetFadeDisable(true); SetShade(0, numshades); - SetNamedTexture(cmd.mTexture, cmd.mRemapIndex, cmd.mFlags & F2DDrawer::DTF_Wrap ? SamplerRepeat : SamplerClampXY); - } + SetNamedTexture(cmd.mTexture, cmd.mTranslationId, cmd.mFlags & F2DDrawer::DTF_Wrap ? SamplerRepeat : SamplerClampXY); EnableBlend(!(cmd.mRenderStyle.Flags & STYLEF_Alpha1)); UseColorOnly(false); } diff --git a/source/rr/src/actors.cpp b/source/rr/src/actors.cpp index cb76f6443..f97c6df6d 100644 --- a/source/rr/src/actors.cpp +++ b/source/rr/src/actors.cpp @@ -517,7 +517,7 @@ void A_DeleteSprite(int spriteNum) { if (EDUKE32_PREDICT_FALSE(block_deletesprite)) { - Printf(OSD_ERROR "A_DeleteSprite(): tried to remove sprite %d in EVENT_EGS\n", spriteNum); + Printf(TEXTCOLOR_RED "A_DeleteSprite(): tried to remove sprite %d in EVENT_EGS\n", spriteNum); return; } diff --git a/source/rr/src/demo.cpp b/source/rr/src/demo.cpp index 8f52b4bef..5d23fecff 100644 --- a/source/rr/src/demo.cpp +++ b/source/rr/src/demo.cpp @@ -103,7 +103,7 @@ static int32_t G_OpenDemoRead(int32_t g_whichDemo) // 0 = mine i = sv_loadsnapshot(g_demo_recFilePtr, -g_whichDemo, &saveh); if (i) { - Printf(OSD_ERROR "There were errors opening demo %d (code: %d).\n", g_whichDemo, i); + Printf(TEXTCOLOR_RED "There were errors opening demo %d (code: %d).\n", g_whichDemo, i); g_demo_recFilePtr.Close(); return 0; } @@ -659,7 +659,7 @@ RECHECK: if (0) { corrupt: - Printf(OSD_ERROR "Demo %d is corrupt (code %d).\n", g_whichDemo-1, corruptcode); + Printf(TEXTCOLOR_RED "Demo %d is corrupt (code %d).\n", g_whichDemo-1, corruptcode); nextdemo: M_StartControlPanel(false); nextdemo_nomenu: diff --git a/source/rr/src/game.cpp b/source/rr/src/game.cpp index 73609f896..3e6476d67 100644 --- a/source/rr/src/game.cpp +++ b/source/rr/src/game.cpp @@ -2692,7 +2692,7 @@ rrbloodpool_fallthrough: if (EDUKE32_PREDICT_FALSE(pSprite->hitag && pSprite->picnum == WATERBUBBLEMAKER)) { // JBF 20030913: Pisses off X_Move(), eg. in bobsp2 - Printf(OSD_ERROR "WARNING: WATERBUBBLEMAKER %d @ %d,%d with hitag!=0. Applying fixup.\n", + Printf(TEXTCOLOR_RED "WARNING: WATERBUBBLEMAKER %d @ %d,%d with hitag!=0. Applying fixup.\n", newSprite,TrackerCast(pSprite->x),TrackerCast(pSprite->y)); pSprite->hitag = 0; } @@ -3819,7 +3819,7 @@ rr_badguy: // use elevator sector's ceiling as heuristic T4(newSprite) = sector[sectNum].ceilingz; - Printf(OSD_ERROR "WARNING: SE17 sprite %d using own sector's ceilingz to " + Printf(TEXTCOLOR_RED "WARNING: SE17 sprite %d using own sector's ceilingz to " "determine when to warp. Sector %d adjacent to a door?\n", newSprite, sectNum); } @@ -3833,7 +3833,7 @@ rr_badguy: // heuristic T5(newSprite) = sector[sectNum].floorz; - Printf(OSD_ERROR "WARNING: SE17 sprite %d using own sector %d's floorz.\n", + Printf(TEXTCOLOR_RED "WARNING: SE17 sprite %d using own sector %d's floorz.\n", newSprite, sectNum); } @@ -4057,7 +4057,7 @@ rr_badguy: } if (EDUKE32_PREDICT_FALSE(spriteNum == -1)) { - Printf(OSD_ERROR "Found lonely Sector Effector (lotag 0) at (%d,%d)\n", + Printf(TEXTCOLOR_RED "Found lonely Sector Effector (lotag 0) at (%d,%d)\n", TrackerCast(pSprite->x),TrackerCast(pSprite->y)); changespritestat(newSprite, STAT_ACTOR); goto SPAWN_END; @@ -5386,7 +5386,7 @@ skip: #ifdef DEBUGGINGAIDS // A negative actor[i].dispicnum used to mean 'no floor shadow please', but // that was a bad hack since the value could propagate to sprite[].picnum. - Printf(OSD_ERROR "actor[%d].dispicnum = %d\n", i, actor[i].dispicnum); + Printf(TEXTCOLOR_RED "actor[%d].dispicnum = %d\n", i, actor[i].dispicnum); #endif actor[i].dispicnum=0; continue; diff --git a/source/rr/src/gameexec.cpp b/source/rr/src/gameexec.cpp index 5fac6f5c5..165f7d37d 100644 --- a/source/rr/src/gameexec.cpp +++ b/source/rr/src/gameexec.cpp @@ -515,7 +515,7 @@ GAMEEXEC_STATIC void VM_AlterAng(int32_t const moveFlags) { AC_MOVE_ID(vm.pData) = 0; - Printf(OSD_ERROR "bad moveptr for actor %d (%d)!\n", vm.spriteNum, vm.pUSprite->picnum); + Printf(TEXTCOLOR_RED "bad moveptr for actor %d (%d)!\n", vm.spriteNum, vm.pUSprite->picnum); return; } @@ -722,7 +722,7 @@ GAMEEXEC_STATIC void VM_Move(void) if (EDUKE32_PREDICT_FALSE((unsigned)AC_MOVE_ID(vm.pData) >= (unsigned)g_scriptSize-1)) { AC_MOVE_ID(vm.pData) = 0; - Printf(OSD_ERROR "clearing bad moveptr for actor %d (%d)\n", vm.spriteNum, vm.pUSprite->picnum); + Printf(TEXTCOLOR_RED "clearing bad moveptr for actor %d (%d)\n", vm.spriteNum, vm.pUSprite->picnum); return; } @@ -2825,7 +2825,7 @@ GAMEEXEC_STATIC void VM_Execute(native_t loop) Bstrcat(tempbuf, szBuf); Bsprintf(szBuf, " =%d\n", Gv_GetVar(lVarID) * m); Bstrcat(tempbuf, szBuf); - Printf(OSDTEXT_GREEN "%s", tempbuf); + Printf(TEXTCOLOR_GREEN "%s", tempbuf); insptr++; continue; } diff --git a/source/rr/src/gamevars.cpp b/source/rr/src/gamevars.cpp index 39c43e673..a95e8e3d7 100644 --- a/source/rr/src/gamevars.cpp +++ b/source/rr/src/gamevars.cpp @@ -368,7 +368,7 @@ static int Gv_GetVarIndex(const char *szGameLabel) if (EDUKE32_PREDICT_FALSE((unsigned)gameVar >= MAXGAMEVARS)) { - Printf(OSD_ERROR "Gv_GetVarIndex(): INTERNAL ERROR: couldn't find gamevar %s!\n", szGameLabel); + Printf(TEXTCOLOR_RED "Gv_GetVarIndex(): INTERNAL ERROR: couldn't find gamevar %s!\n", szGameLabel); return 0; } diff --git a/source/rr/src/osdcmds.cpp b/source/rr/src/osdcmds.cpp index 0383bcef2..2e3158ad7 100644 --- a/source/rr/src/osdcmds.cpp +++ b/source/rr/src/osdcmds.cpp @@ -44,7 +44,7 @@ static int osdcmd_levelwarp(CCmdFuncPtr parm) int m = atoi(parm->parms[1]); if (e == 0 || m == 0) { - Printf(OSD_ERROR "Invalid level!: E%sL%s\n", parm->parms[0], parm->parms[1]); + Printf(TEXTCOLOR_RED "Invalid level!: E%sL%s\n", parm->parms[0], parm->parms[1]); return OSDCMD_OK; } @@ -79,7 +79,7 @@ static int osdcmd_map(CCmdFuncPtr parm) if (!fileSystem.Lookup(mapname, "MAP")) { - Printf(OSD_ERROR "map: file \"%s\" not found.\n", mapname.GetChars()); + Printf(TEXTCOLOR_RED "map: file \"%s\" not found.\n", mapname.GetChars()); return OSDCMD_OK; } @@ -95,7 +95,7 @@ static int osdcmd_map(CCmdFuncPtr parm) } if (VOLUMEONE) { - Printf(OSD_ERROR "Cannot use user maps in shareware.\n"); + Printf(TEXTCOLOR_RED "Cannot use user maps in shareware.\n"); return OSDCMD_OK; } // Treat as user map diff --git a/source/rr/src/premap.cpp b/source/rr/src/premap.cpp index 2078c7f3d..f117cc3ef 100644 --- a/source/rr/src/premap.cpp +++ b/source/rr/src/premap.cpp @@ -1489,7 +1489,7 @@ static void prelevel(char g) } if (missedCloudSectors > 0) - Printf(OSDTEXT_RED "Map warning: have %d unhandled CLOUDYSKIES ceilings.\n", missedCloudSectors); + Printf(TEXTCOLOR_RED "Map warning: have %d unhandled CLOUDYSKIES ceilings.\n", missedCloudSectors); // NOTE: must be safe loop because callbacks could delete sprites. if (!DEER) @@ -2323,7 +2323,7 @@ int G_EnterLevel(int gameMode) if (mi.fileName.IsEmpty() && !Menu_HaveUserMap()) { - Printf(OSDTEXT_RED "Map E%dL%d not defined!\n", ud.volume_number+1, ud.level_number+1); + Printf(TEXTCOLOR_RED "Map E%dL%d not defined!\n", ud.volume_number+1, ud.level_number+1); return 1; } @@ -2343,7 +2343,7 @@ int G_EnterLevel(int gameMode) { if (engineLoadBoard(boardfilename, 0, &pPlayer->pos, &lbang, &pPlayer->cursectnum) < 0) { - Printf(OSD_ERROR "Map \"%s\" not found or invalid map version!\n", boardfilename); + Printf(TEXTCOLOR_RED "Map \"%s\" not found or invalid map version!\n", boardfilename); return 1; } userMapRecord.name = ""; @@ -2356,7 +2356,7 @@ int G_EnterLevel(int gameMode) } else if (engineLoadBoard(mi.fileName, VOLUMEONE, &pPlayer->pos, &lbang, &pPlayer->cursectnum) < 0) { - Printf(OSD_ERROR "Map \"%s\" not found or invalid map version!\n", mi.fileName.GetChars()); + Printf(TEXTCOLOR_RED "Map \"%s\" not found or invalid map version!\n", mi.fileName.GetChars()); return 1; } else @@ -2493,11 +2493,11 @@ int G_EnterLevel(int gameMode) if (G_HaveUserMap()) { - Printf(OSDTEXT_YELLOW "%s: %s\n", GStrings("TXT_USERMAP"), boardfilename); + Printf(TEXTCOLOR_GOLD "%s: %s\n", GStrings("TXT_USERMAP"), boardfilename); } else { - Printf(OSDTEXT_YELLOW "E%dL%d: %s\n", ud.volume_number+1, ud.level_number+1, + Printf(TEXTCOLOR_GOLD "E%dL%d: %s\n", ud.volume_number+1, ud.level_number+1, mapList[mii].DisplayName()); } diff --git a/source/rr/src/sbar.cpp b/source/rr/src/sbar.cpp index a4e6026c8..42d408457 100644 --- a/source/rr/src/sbar.cpp +++ b/source/rr/src/sbar.cpp @@ -36,7 +36,7 @@ void InitFonts() // Small font for (int i = 0; i < 95; i++) { - auto tile = TileFiles.GetTile(STARTALPHANUM + i); + auto tile = tileGetTexture(STARTALPHANUM + i); if (tile && tile->GetTexelWidth() > 0 && tile->GetTexelHeight() > 0) fontdata.Insert('!' + i, tile); } @@ -46,29 +46,29 @@ void InitFonts() // Big font // This font is VERY messy... - fontdata.Insert('_', TileFiles.GetTile(BIGALPHANUM - 11)); - fontdata.Insert('-', TileFiles.GetTile(BIGALPHANUM - 11)); - for (int i = 0; i < 10; i++) fontdata.Insert('0' + i, TileFiles.GetTile(BIGALPHANUM - 10 + i)); - for (int i = 0; i < 26; i++) fontdata.Insert('A' + i, TileFiles.GetTile(BIGALPHANUM + i)); - fontdata.Insert('.', TileFiles.GetTile(BIGPERIOD)); - fontdata.Insert(',', TileFiles.GetTile(BIGCOMMA)); - fontdata.Insert('!', TileFiles.GetTile(BIGX_)); - fontdata.Insert('?', TileFiles.GetTile(BIGQ)); - fontdata.Insert(';', TileFiles.GetTile(BIGSEMI)); - fontdata.Insert(':', TileFiles.GetTile(BIGCOLIN)); - fontdata.Insert('\\', TileFiles.GetTile(BIGALPHANUM + 68)); - fontdata.Insert('/', TileFiles.GetTile(BIGALPHANUM + 68)); - fontdata.Insert('%', TileFiles.GetTile(BIGALPHANUM + 69)); - fontdata.Insert('`', TileFiles.GetTile(BIGAPPOS)); - fontdata.Insert('"', TileFiles.GetTile(BIGAPPOS)); - fontdata.Insert('\'', TileFiles.GetTile(BIGAPPOS)); + fontdata.Insert('_', tileGetTexture(BIGALPHANUM - 11)); + fontdata.Insert('-', tileGetTexture(BIGALPHANUM - 11)); + for (int i = 0; i < 10; i++) fontdata.Insert('0' + i, tileGetTexture(BIGALPHANUM - 10 + i)); + for (int i = 0; i < 26; i++) fontdata.Insert('A' + i, tileGetTexture(BIGALPHANUM + i)); + fontdata.Insert('.', tileGetTexture(BIGPERIOD)); + fontdata.Insert(',', tileGetTexture(BIGCOMMA)); + fontdata.Insert('!', tileGetTexture(BIGX_)); + fontdata.Insert('?', tileGetTexture(BIGQ)); + fontdata.Insert(';', tileGetTexture(BIGSEMI)); + fontdata.Insert(':', tileGetTexture(BIGCOLIN)); + fontdata.Insert('\\', tileGetTexture(BIGALPHANUM + 68)); + fontdata.Insert('/', tileGetTexture(BIGALPHANUM + 68)); + fontdata.Insert('%', tileGetTexture(BIGALPHANUM + 69)); + fontdata.Insert('`', tileGetTexture(BIGAPPOS)); + fontdata.Insert('"', tileGetTexture(BIGAPPOS)); + fontdata.Insert('\'', tileGetTexture(BIGAPPOS)); BigFont = new ::FFont("BigFont", nullptr, "defbigfont", 0, 0, 0, -1, -1, false, false, false, &fontdata); fontdata.Clear(); // Tiny font for (int i = 0; i < 95; i++) { - auto tile = TileFiles.GetTile(MINIFONT + i); + auto tile = tileGetTexture(MINIFONT + i); if (tile && tile->GetTexelWidth() > 0 && tile->GetTexelHeight() > 0) fontdata.Insert('!' + i, tile); } @@ -76,9 +76,9 @@ void InitFonts() fontdata.Clear(); // SBAR index font - for (int i = 0; i < 10; i++) fontdata.Insert('0' + i, TileFiles.GetTile(THREEBYFIVE + i)); - fontdata.Insert(':', TileFiles.GetTile(THREEBYFIVE + 10)); - fontdata.Insert('/', TileFiles.GetTile(THREEBYFIVE + 11)); + for (int i = 0; i < 10; i++) fontdata.Insert('0' + i, tileGetTexture(THREEBYFIVE + i)); + fontdata.Insert(':', tileGetTexture(THREEBYFIVE + 10)); + fontdata.Insert('/', tileGetTexture(THREEBYFIVE + 11)); new ::FFont("IndexFont", nullptr, nullptr, 0, 0, 0, -1, -1, false, false, false, &fontdata); } @@ -98,7 +98,7 @@ static int32_t sbarxr(int32_t x) static int32_t sbary(int32_t y) { if (hud_position == 1 && ud.screen_size == 4 && ud.althud == 1) return sbarsc(y << 16); - else return (100<<16) - sbarsc(200<<16) + sbarsc(y<<16); + else return (200<<16) - sbarsc(200<<16) + sbarsc(y<<16); } int32_t sbarx16(int32_t x) @@ -123,7 +123,7 @@ static int32_t sbarxr16(int32_t x) int32_t sbary16(int32_t y) { - return (100<<16) - sbarsc(200<<16) + sbarsc(y); + return (200<<16) - sbarsc(200<<16) + sbarsc(y); } static void G_PatchStatusBar(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t aspectCorrect = 1) diff --git a/source/rr/src/text.cpp b/source/rr/src/text.cpp index d8d99b07b..f5c72a01d 100644 --- a/source/rr/src/text.cpp +++ b/source/rr/src/text.cpp @@ -359,7 +359,7 @@ void GameInterface::DoPrintMessage(int prio, const char* t) if (p->ftq == QUOTE_RESERVED || p->ftq == QUOTE_RESERVED2) return; if (p == g_player[screenpeek].ps) - Printf(prio|PRINT_NOTIFY, cq ? OSDTEXT_DEFAULT "%s\n" : "%s\n", t); + Printf(prio|PRINT_NOTIFY, cq ? TEXTCOLOR_TAN "%s\n" : "%s\n", t); if (hud_messages == 1) { diff --git a/source/sw/src/osdcmds.cpp b/source/sw/src/osdcmds.cpp index 294155307..55e4ef2ba 100644 --- a/source/sw/src/osdcmds.cpp +++ b/source/sw/src/osdcmds.cpp @@ -40,7 +40,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "gstrings.h" #include "common.h" -#include "core/2d/v_text.h" +#include "v_text.h" +#include "printf.h" #include "cheats.h" #include "demo.h" // g_firstDemoFile[] @@ -63,7 +64,7 @@ static int osdcmd_map(CCmdFuncPtr parm) if (!fileSystem.Lookup(mapname, "MAP")) { - Printf(OSD_ERROR "map: file \"%s\" not found.\n", mapname.GetChars()); + Printf(TEXTCOLOR_RED "map: file \"%s\" not found.\n", mapname.GetChars()); return OSDCMD_OK; }