mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-10 14:51:40 +00:00
- add a system for setting all of 2D drawing's transform, not just shapes
This commit is contained in:
parent
c6ae73d6d2
commit
1e27fac288
5 changed files with 145 additions and 39 deletions
|
@ -42,7 +42,7 @@
|
|||
#include "v_video.h"
|
||||
#include "fcolormap.h"
|
||||
|
||||
static F2DDrawer drawer;
|
||||
static F2DDrawer drawer = F2DDrawer();
|
||||
F2DDrawer* twod = &drawer;
|
||||
|
||||
EXTERN_CVAR(Float, transsouls)
|
||||
|
@ -104,6 +104,33 @@ DEFINE_ACTION_FUNCTION_NATIVE(DShape2DTransform, Translate, Shape2DTransform_Tra
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void Shape2DTransform_From2D(
|
||||
DShape2DTransform* self,
|
||||
double m00, double m01, double m10, double m11, double vx, double vy
|
||||
)
|
||||
{
|
||||
self->transform.Cells[0][0] = m00;
|
||||
self->transform.Cells[0][1] = m01;
|
||||
self->transform.Cells[1][0] = m10;
|
||||
self->transform.Cells[1][1] = m11;
|
||||
|
||||
self->transform.Cells[0][2] = vx;
|
||||
self->transform.Cells[1][2] = vy;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_NATIVE(DShape2DTransform, From2D, Shape2DTransform_From2D)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DShape2DTransform);
|
||||
PARAM_FLOAT(m00);
|
||||
PARAM_FLOAT(m01);
|
||||
PARAM_FLOAT(m10);
|
||||
PARAM_FLOAT(m11);
|
||||
PARAM_FLOAT(vx);
|
||||
PARAM_FLOAT(vy);
|
||||
Shape2DTransform_From2D(self, m00, m01, m10, m11, vx, vy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
IMPLEMENT_CLASS(DShape2D, false, false)
|
||||
|
||||
static void Shape2D_SetTransform(DShape2D* self, DShape2DTransform *transform)
|
||||
|
@ -114,7 +141,7 @@ static void Shape2D_SetTransform(DShape2D* self, DShape2DTransform *transform)
|
|||
DEFINE_ACTION_FUNCTION_NATIVE(DShape2D, SetTransform, Shape2D_SetTransform)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(DShape2D);
|
||||
PARAM_OBJECT(transform, DShape2DTransform);
|
||||
PARAM_OBJECT_NOT_NULL(transform, DShape2DTransform);
|
||||
Shape2D_SetTransform(self, transform);
|
||||
return 0;
|
||||
}
|
||||
|
@ -462,8 +489,19 @@ void F2DDrawer::AddTexture(FGameTexture* img, DrawParms& parms)
|
|||
u1 = float(u1 + parms.windowleft / parms.texwidth);
|
||||
u2 = float(u2 - (parms.texwidth - wi) / parms.texwidth);
|
||||
}
|
||||
auto t = this->transform;
|
||||
auto tCorners = {
|
||||
(t * DVector3(x, y, 1.0)).XY(),
|
||||
(t * DVector3(x, y + h, 1.0)).XY(),
|
||||
(t * DVector3(x + w, y, 1.0)).XY(),
|
||||
(t * DVector3(x + w, y + h, 1.0)).XY()
|
||||
};
|
||||
double minx = std::min_element(tCorners.begin(), tCorners.end(), [] (auto d0, auto d1) { return d0.X < d1.X; })->X;
|
||||
double maxx = std::max_element(tCorners.begin(), tCorners.end(), [] (auto d0, auto d1) { return d0.X < d1.X; })->X;
|
||||
double miny = std::min_element(tCorners.begin(), tCorners.end(), [] (auto d0, auto d1) { return d0.Y < d1.Y; })->Y;
|
||||
double maxy = std::max_element(tCorners.begin(), tCorners.end(), [] (auto d0, auto d1) { return d0.Y < d1.Y; })->Y;
|
||||
|
||||
if (x < (double)parms.lclip || y < (double)parms.uclip || x + w >(double)parms.rclip || y + h >(double)parms.dclip)
|
||||
if (minx < (double)parms.lclip || miny < (double)parms.uclip || maxx >(double)parms.rclip || maxy >(double)parms.dclip)
|
||||
{
|
||||
dg.mScissor[0] = parms.lclip + int(offset.X);
|
||||
dg.mScissor[1] = parms.uclip + int(offset.Y);
|
||||
|
@ -479,10 +517,10 @@ void F2DDrawer::AddTexture(FGameTexture* img, DrawParms& parms)
|
|||
dg.mVertCount = 4;
|
||||
dg.mVertIndex = (int)mVertices.Reserve(4);
|
||||
TwoDVertex* ptr = &mVertices[dg.mVertIndex];
|
||||
Set(ptr, x, y, 0, u1, v1, vertexcolor); ptr++;
|
||||
Set(ptr, x, y + h, 0, u1, v2, vertexcolor); ptr++;
|
||||
Set(ptr, x + w, y, 0, u2, v1, vertexcolor); ptr++;
|
||||
Set(ptr, x + w, y + h, 0, u2, v2, vertexcolor); ptr++;
|
||||
ptr->Set(x, y, 0, u1, v1, vertexcolor); ptr++;
|
||||
ptr->Set(x, y + h, 0, u1, v2, vertexcolor); ptr++;
|
||||
ptr->Set(x + w, y, 0, u2, v1, vertexcolor); ptr++;
|
||||
ptr->Set(x + w, y + h, 0, u2, v2, vertexcolor); ptr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -515,12 +553,16 @@ void F2DDrawer::AddTexture(FGameTexture* img, DrawParms& parms)
|
|||
dg.mVertCount = 4;
|
||||
dg.mVertIndex = (int)mVertices.Reserve(4);
|
||||
TwoDVertex* ptr = &mVertices[dg.mVertIndex];
|
||||
Set(ptr, x1, y1, 0, u1, v1, vertexcolor); ptr++;
|
||||
Set(ptr, x2, y2, 0, u1, v2, vertexcolor); ptr++;
|
||||
Set(ptr, x3, y3, 0, u2, v1, vertexcolor); ptr++;
|
||||
Set(ptr, x4, y4, 0, u2, v2, vertexcolor); ptr++;
|
||||
ptr->Set(x1, y1, 0, u1, v1, vertexcolor); ptr++;
|
||||
ptr->Set(x2, y2, 0, u1, v2, vertexcolor); ptr++;
|
||||
ptr->Set(x3, y3, 0, u2, v1, vertexcolor); ptr++;
|
||||
ptr->Set(x4, y4, 0, u2, v2, vertexcolor); ptr++;
|
||||
|
||||
}
|
||||
dg.useTransform = true;
|
||||
dg.transform = this->transform;
|
||||
dg.transform.Cells[0][2] += offset.X;
|
||||
dg.transform.Cells[1][2] += offset.Y;
|
||||
dg.mIndexIndex = mIndices.Size();
|
||||
dg.mIndexCount += 6;
|
||||
AddIndices(dg.mVertIndex, 6, 0, 1, 2, 1, 3, 2);
|
||||
|
@ -599,11 +641,12 @@ void F2DDrawer::AddShape(FGameTexture* img, DShape2D* shape, DrawParms& parms)
|
|||
if ( shape->mVertices[i].Y > shape->maxy ) shape->maxy = shape->mVertices[i].Y;
|
||||
}
|
||||
}
|
||||
auto t = this->transform * shape->transform;
|
||||
auto tCorners = {
|
||||
(shape->transform * DVector3(shape->minx, shape->miny, 1.0)).XY(),
|
||||
(shape->transform * DVector3(shape->minx, shape->maxy, 1.0)).XY(),
|
||||
(shape->transform * DVector3(shape->maxx, shape->miny, 1.0)).XY(),
|
||||
(shape->transform * DVector3(shape->maxx, shape->maxy, 1.0)).XY()
|
||||
(t * DVector3(shape->minx, shape->miny, 1.0)).XY(),
|
||||
(t * DVector3(shape->minx, shape->maxy, 1.0)).XY(),
|
||||
(t * DVector3(shape->maxx, shape->miny, 1.0)).XY(),
|
||||
(t * DVector3(shape->maxx, shape->maxy, 1.0)).XY()
|
||||
};
|
||||
double minx = std::min_element(tCorners.begin(), tCorners.end(), [] (auto d0, auto d1) { return d0.X < d1.X; })->X;
|
||||
double maxx = std::max_element(tCorners.begin(), tCorners.end(), [] (auto d0, auto d1) { return d0.X < d1.X; })->X;
|
||||
|
@ -621,7 +664,7 @@ void F2DDrawer::AddShape(FGameTexture* img, DShape2D* shape, DrawParms& parms)
|
|||
memset(dg.mScissor, 0, sizeof(dg.mScissor));
|
||||
|
||||
dg.useTransform = true;
|
||||
dg.transform = shape->transform;
|
||||
dg.transform = t;
|
||||
dg.transform.Cells[0][2] += offset.X;
|
||||
dg.transform.Cells[1][2] += offset.Y;
|
||||
dg.shape2DBufInfo = shape->bufferInfo;
|
||||
|
@ -715,7 +758,7 @@ void F2DDrawer::AddPoly(FGameTexture *texture, FVector2 *points, int npoints,
|
|||
u = t * cosrot - v * sinrot;
|
||||
v = v * cosrot + t * sinrot;
|
||||
}
|
||||
Set(&mVertices[poly.mVertIndex+i], points[i].X, points[i].Y, 0, u*uscale, v*vscale, color0);
|
||||
mVertices[poly.mVertIndex+i].Set(points[i].X, points[i].Y, 0, u*uscale, v*vscale, color0);
|
||||
}
|
||||
poly.mIndexIndex = mIndices.Size();
|
||||
|
||||
|
@ -736,6 +779,10 @@ void F2DDrawer::AddPoly(FGameTexture *texture, FVector2 *points, int npoints,
|
|||
mIndices[addr + i] = poly.mVertIndex + indices[i];
|
||||
}
|
||||
}
|
||||
poly.useTransform = true;
|
||||
poly.transform = this->transform;
|
||||
poly.transform.Cells[0][2] += offset.X;
|
||||
poly.transform.Cells[1][2] += offset.Y;
|
||||
|
||||
AddCommand(&poly);
|
||||
}
|
||||
|
@ -773,7 +820,7 @@ void F2DDrawer::AddPoly(FGameTexture* img, FVector4* vt, size_t vtcount, const u
|
|||
|
||||
for (size_t i=0;i<vtcount;i++)
|
||||
{
|
||||
Set(ptr, vt[i].X, vt[i].Y, 0.f, vt[i].Z, vt[i].W, color);
|
||||
ptr->Set(vt[i].X, vt[i].Y, 0.f, vt[i].Z, vt[i].W, color);
|
||||
ptr++;
|
||||
}
|
||||
dg.mIndexIndex = mIndices.Size();
|
||||
|
@ -798,6 +845,10 @@ void F2DDrawer::AddPoly(FGameTexture* img, FVector4* vt, size_t vtcount, const u
|
|||
dg.mIndexCount = (int)vtcount;
|
||||
|
||||
}
|
||||
dg.useTransform = true;
|
||||
dg.transform = this->transform;
|
||||
dg.transform.Cells[0][2] += offset.X;
|
||||
dg.transform.Cells[1][2] += offset.Y;
|
||||
AddCommand(&dg);
|
||||
}
|
||||
|
||||
|
@ -916,18 +967,22 @@ void F2DDrawer::AddFlatFill(int left, int top, int right, int bottom, FGameTextu
|
|||
dg.mVertIndex = (int)mVertices.Reserve(4);
|
||||
auto ptr = &mVertices[dg.mVertIndex];
|
||||
|
||||
Set(ptr, left, top, 0, fU1, fV1, color); ptr++;
|
||||
ptr->Set(left, top, 0, fU1, fV1, color); ptr++;
|
||||
if (local_origin < 4)
|
||||
{
|
||||
Set(ptr, left, bottom, 0, fU1, fV2, color); ptr++;
|
||||
Set(ptr, right, top, 0, fU2, fV1, color); ptr++;
|
||||
ptr->Set(left, bottom, 0, fU1, fV2, color); ptr++;
|
||||
ptr->Set(right, top, 0, fU2, fV1, color); ptr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Set(ptr, left, bottom, 0, fU2, fV1, color); ptr++;
|
||||
Set(ptr, right, top, 0, fU1, fV2, color); ptr++;
|
||||
ptr->Set(left, bottom, 0, fU2, fV1, color); ptr++;
|
||||
ptr->Set(right, top, 0, fU1, fV2, color); ptr++;
|
||||
}
|
||||
Set(ptr, right, bottom, 0, fU2, fV2, color); ptr++;
|
||||
ptr->Set(right, bottom, 0, fU2, fV2, color); ptr++;
|
||||
dg.useTransform = true;
|
||||
dg.transform = this->transform;
|
||||
dg.transform.Cells[0][2] += offset.X;
|
||||
dg.transform.Cells[1][2] += offset.Y;
|
||||
dg.mIndexIndex = mIndices.Size();
|
||||
dg.mIndexCount += 6;
|
||||
AddIndices(dg.mVertIndex, 6, 0, 1, 2, 1, 3, 2);
|
||||
|
@ -950,10 +1005,14 @@ void F2DDrawer::AddColorOnlyQuad(int x1, int y1, int w, int h, PalEntry color, F
|
|||
dg.mVertIndex = (int)mVertices.Reserve(4);
|
||||
dg.mRenderStyle = style? *style : LegacyRenderStyles[STYLE_Translucent];
|
||||
auto ptr = &mVertices[dg.mVertIndex];
|
||||
Set(ptr, x1, y1, 0, 0, 0, color); ptr++;
|
||||
Set(ptr, x1, y1 + h, 0, 0, 0, color); ptr++;
|
||||
Set(ptr, x1 + w, y1, 0, 0, 0, color); ptr++;
|
||||
Set(ptr, x1 + w, y1 + h, 0, 0, 0, color); ptr++;
|
||||
ptr->Set(x1, y1, 0, 0, 0, color); ptr++;
|
||||
ptr->Set(x1, y1 + h, 0, 0, 0, color); ptr++;
|
||||
ptr->Set(x1 + w, y1, 0, 0, 0, color); ptr++;
|
||||
ptr->Set(x1 + w, y1 + h, 0, 0, 0, color); ptr++;
|
||||
dg.useTransform = true;
|
||||
dg.transform = this->transform;
|
||||
dg.transform.Cells[0][2] += offset.X;
|
||||
dg.transform.Cells[1][2] += offset.Y;
|
||||
dg.mIndexIndex = mIndices.Size();
|
||||
dg.mIndexCount += 6;
|
||||
AddIndices(dg.mVertIndex, 6, 0, 1, 2, 1, 3, 2);
|
||||
|
@ -998,8 +1057,12 @@ void F2DDrawer::AddLine(double x1, double y1, double x2, double y2, int clipx1,
|
|||
dg.mRenderStyle = LegacyRenderStyles[STYLE_Translucent];
|
||||
dg.mVertCount = 2;
|
||||
dg.mVertIndex = (int)mVertices.Reserve(2);
|
||||
Set(&mVertices[dg.mVertIndex], x1, y1, 0, 0, 0, p);
|
||||
Set(&mVertices[dg.mVertIndex+1], x2, y2, 0, 0, 0, p);
|
||||
dg.useTransform = true;
|
||||
dg.transform = this->transform;
|
||||
dg.transform.Cells[0][2] += offset.X;
|
||||
dg.transform.Cells[1][2] += offset.Y;
|
||||
mVertices[dg.mVertIndex].Set(x1, y1, 0, 0, 0, p);
|
||||
mVertices[dg.mVertIndex+1].Set(x2, y2, 0, 0, 0, p);
|
||||
AddCommand(&dg);
|
||||
}
|
||||
|
||||
|
@ -1034,10 +1097,14 @@ void F2DDrawer::AddThickLine(int x1, int y1, int x2, int y2, double thickness, u
|
|||
dg.mVertIndex = (int)mVertices.Reserve(4);
|
||||
dg.mRenderStyle = LegacyRenderStyles[STYLE_Translucent];
|
||||
auto ptr = &mVertices[dg.mVertIndex];
|
||||
Set(ptr, corner0.X, corner0.Y, 0, 0, 0, p); ptr++;
|
||||
Set(ptr, corner1.X, corner1.Y, 0, 0, 0, p); ptr++;
|
||||
Set(ptr, corner2.X, corner2.Y, 0, 0, 0, p); ptr++;
|
||||
Set(ptr, corner3.X, corner3.Y, 0, 0, 0, p); ptr++;
|
||||
ptr->Set(corner0.X, corner0.Y, 0, 0, 0, p); ptr++;
|
||||
ptr->Set(corner1.X, corner1.Y, 0, 0, 0, p); ptr++;
|
||||
ptr->Set(corner2.X, corner2.Y, 0, 0, 0, p); ptr++;
|
||||
ptr->Set(corner3.X, corner3.Y, 0, 0, 0, p); ptr++;
|
||||
dg.useTransform = true;
|
||||
dg.transform = this->transform;
|
||||
dg.transform.Cells[0][2] += offset.X;
|
||||
dg.transform.Cells[1][2] += offset.Y;
|
||||
dg.mIndexIndex = mIndices.Size();
|
||||
dg.mIndexCount += 6;
|
||||
AddIndices(dg.mVertIndex, 6, 0, 1, 2, 1, 3, 2);
|
||||
|
@ -1061,7 +1128,11 @@ void F2DDrawer::AddPixel(int x1, int y1, uint32_t color)
|
|||
dg.mRenderStyle = LegacyRenderStyles[STYLE_Translucent];
|
||||
dg.mVertCount = 1;
|
||||
dg.mVertIndex = (int)mVertices.Reserve(1);
|
||||
Set(&mVertices[dg.mVertIndex], x1, y1, 0, 0, 0, p);
|
||||
mVertices[dg.mVertIndex].Set(x1, y1, 0, 0, 0, p);
|
||||
dg.useTransform = true;
|
||||
dg.transform = this->transform;
|
||||
dg.transform.Cells[0][2] += offset.X;
|
||||
dg.transform.Cells[1][2] += offset.Y;
|
||||
AddCommand(&dg);
|
||||
}
|
||||
|
||||
|
|
|
@ -55,6 +55,9 @@ struct DShape2DBufferInfo;
|
|||
class F2DDrawer
|
||||
{
|
||||
public:
|
||||
F2DDrawer() {
|
||||
this->transform.Identity();
|
||||
}
|
||||
|
||||
enum EDrawType : uint8_t
|
||||
{
|
||||
|
@ -172,6 +175,7 @@ public:
|
|||
bool locked; // prevents clearing of the data so it can be reused multiple times (useful for screen fades)
|
||||
float screenFade = 1.f;
|
||||
DVector2 offset;
|
||||
DMatrix3x3 transform;
|
||||
public:
|
||||
int fullscreenautoaspect = 3;
|
||||
int cliptop = -1, clipleft = -1, clipwidth = -1, clipheight = -1;
|
||||
|
@ -229,11 +233,14 @@ public:
|
|||
return v;
|
||||
}
|
||||
|
||||
void Set(TwoDVertex* v, double xx, double yy, double zz, double uu, double vv, PalEntry col)
|
||||
void SetTransform(const DShape2DTransform& transform)
|
||||
{
|
||||
v->Set(xx + offset.X, yy + offset.Y, zz, uu, vv, col);
|
||||
this->transform = transform.transform;
|
||||
}
|
||||
void ClearTransform()
|
||||
{
|
||||
this->transform.Identity();
|
||||
}
|
||||
|
||||
|
||||
int DrawCount() const
|
||||
{
|
||||
|
|
|
@ -1625,3 +1625,26 @@ DEFINE_ACTION_FUNCTION(_Screen, SetOffset)
|
|||
PARAM_FLOAT(y);
|
||||
ACTION_RETURN_VEC2(twod->SetOffset(DVector2(x, y)));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Screen, SetTransform)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_OBJECT_NOT_NULL(transform, DShape2DTransform);
|
||||
|
||||
if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function");
|
||||
|
||||
twod->SetTransform(*transform);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Screen, ClearTransform)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
|
||||
if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function");
|
||||
|
||||
twod->ClearTransform();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -915,6 +915,7 @@ struct TMatrix3x3
|
|||
|
||||
TMatrix3x3() = default;
|
||||
TMatrix3x3(const TMatrix3x3 &other) = default;
|
||||
TMatrix3x3& operator=(const TMatrix3x3& other) = default;
|
||||
|
||||
TMatrix3x3(const Vector3 &row1, const Vector3 &row2, const Vector3 &row3)
|
||||
{
|
||||
|
|
|
@ -469,6 +469,7 @@ class Shape2DTransform : Object native
|
|||
native void Rotate(double angle);
|
||||
native void Scale(Vector2 scaleVec);
|
||||
native void Translate(Vector2 translateVec);
|
||||
native void From2D(double m00, double m01, double m10, double m11, double vx, double vy);
|
||||
}
|
||||
|
||||
class Shape2D : Object native
|
||||
|
@ -514,6 +515,9 @@ struct Screen native
|
|||
native static Vector2 SetOffset(double x, double y);
|
||||
native static void ClearScreen(color col = 0);
|
||||
native static void SetScreenFade(double factor);
|
||||
|
||||
native static void SetTransform(Shape2DTransform transform);
|
||||
native static void ClearTransform();
|
||||
}
|
||||
|
||||
struct Font native
|
||||
|
|
Loading…
Reference in a new issue