mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-13 16:07:45 +00:00
Merge branch 'master' into asmjit
This commit is contained in:
commit
aa4de71e6d
20 changed files with 289 additions and 165 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -56,3 +56,4 @@
|
||||||
/mapfiles_release/*.map
|
/mapfiles_release/*.map
|
||||||
.DS_Store
|
.DS_Store
|
||||||
/build_vc2017-32
|
/build_vc2017-32
|
||||||
|
/build2
|
||||||
|
|
|
@ -436,22 +436,29 @@ void FGLRenderState::SetDepthRange(float min, float max)
|
||||||
glDepthRange(min, max);
|
glDepthRange(min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FGLRenderState::SetColorMask(bool r, bool g, bool b, bool a)
|
||||||
|
{
|
||||||
|
glColorMask(r, g, b, a);
|
||||||
|
}
|
||||||
|
|
||||||
void FGLRenderState::EnableDrawBufferAttachments(bool on)
|
void FGLRenderState::EnableDrawBufferAttachments(bool on)
|
||||||
{
|
{
|
||||||
EnableDrawBuffers(on ? GetPassDrawBufferCount() : 1);
|
EnableDrawBuffers(on ? GetPassDrawBufferCount() : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGLRenderState::SetStencil(int offs, int op, int flags)
|
void FGLRenderState::SetStencil(int offs, int op, int flags = -1)
|
||||||
{
|
{
|
||||||
static int op2gl[] = { GL_KEEP, GL_INCR, GL_DECR };
|
static int op2gl[] = { GL_KEEP, GL_INCR, GL_DECR };
|
||||||
|
|
||||||
glStencilFunc(GL_EQUAL, screen->stencilValue + offs, ~0); // draw sky into stencil
|
glStencilFunc(GL_EQUAL, screen->stencilValue + offs, ~0); // draw sky into stencil
|
||||||
glStencilOp(GL_KEEP, GL_KEEP, op2gl[op]); // this stage doesn't modify the stencil
|
glStencilOp(GL_KEEP, GL_KEEP, op2gl[op]); // this stage doesn't modify the stencil
|
||||||
|
|
||||||
bool cmon = !(flags & SF_ColorMaskOff);
|
if (flags != -1)
|
||||||
bool cmalpha = cmon || (flags & SF_ColorMaskAlpha);
|
{
|
||||||
glColorMask(cmon, cmon, cmon, cmalpha); // don't write to the graphics buffer
|
bool cmon = !(flags & SF_ColorMaskOff);
|
||||||
glDepthMask(!(flags & SF_DepthMaskOff));
|
glColorMask(cmon, cmon, cmon, cmon); // don't write to the graphics buffer
|
||||||
|
glDepthMask(!(flags & SF_DepthMaskOff));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FGLRenderState::ToggleState(int state, bool on)
|
void FGLRenderState::ToggleState(int state, bool on)
|
||||||
|
|
|
@ -153,6 +153,7 @@ public:
|
||||||
void SetDepthMask(bool on) override;
|
void SetDepthMask(bool on) override;
|
||||||
void SetDepthFunc(int func) override;
|
void SetDepthFunc(int func) override;
|
||||||
void SetDepthRange(float min, float max) override;
|
void SetDepthRange(float min, float max) override;
|
||||||
|
void SetColorMask(bool r, bool g, bool b, bool a) override;
|
||||||
void EnableDrawBufferAttachments(bool on) override;
|
void EnableDrawBufferAttachments(bool on) override;
|
||||||
void SetStencil(int offs, int op, int flags) override;
|
void SetStencil(int offs, int op, int flags) override;
|
||||||
void SetCulling(int mode) override;
|
void SetCulling(int mode) override;
|
||||||
|
|
|
@ -667,10 +667,10 @@ void HWDrawInfo::AddSubsectorToPortal(FSectorPortalGroup *ptg, subsector_t *sub)
|
||||||
auto portal = FindPortal(ptg);
|
auto portal = FindPortal(ptg);
|
||||||
if (!portal)
|
if (!portal)
|
||||||
{
|
{
|
||||||
portal = new HWScenePortal(screen->mPortalState, new HWSectorStackPortal(ptg));
|
portal = new HWSectorStackPortal(screen->mPortalState, ptg);
|
||||||
Portals.Push(portal);
|
Portals.Push(portal);
|
||||||
}
|
}
|
||||||
auto ptl = static_cast<HWSectorStackPortal*>(static_cast<HWScenePortal*>(portal)->mScene);
|
auto ptl = static_cast<HWSectorStackPortal*>(portal);
|
||||||
ptl->AddSubsector(sub);
|
ptl->AddSubsector(sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,7 +144,7 @@ struct HWDrawInfo
|
||||||
HWDrawInfo * outer = nullptr;
|
HWDrawInfo * outer = nullptr;
|
||||||
int FullbrightFlags;
|
int FullbrightFlags;
|
||||||
std::atomic<int> spriteindex;
|
std::atomic<int> spriteindex;
|
||||||
HWScenePortalBase *mClipPortal;
|
HWPortal *mClipPortal;
|
||||||
HWPortal *mCurrentPortal;
|
HWPortal *mCurrentPortal;
|
||||||
//FRotator mAngles;
|
//FRotator mAngles;
|
||||||
Clipper *mClipper;
|
Clipper *mClipper;
|
||||||
|
|
|
@ -201,7 +201,7 @@ public:
|
||||||
//private:
|
//private:
|
||||||
|
|
||||||
void PutWall(HWDrawInfo *di, bool translucent);
|
void PutWall(HWDrawInfo *di, bool translucent);
|
||||||
void PutPortal(HWDrawInfo *di, int ptype);
|
void PutPortal(HWDrawInfo *di, int ptype, int plane);
|
||||||
void CheckTexturePosition(FTexCoordInfo *tci);
|
void CheckTexturePosition(FTexCoordInfo *tci);
|
||||||
|
|
||||||
void Put3DWall(HWDrawInfo *di, lightlist_t * lightlist, bool translucent);
|
void Put3DWall(HWDrawInfo *di, lightlist_t * lightlist, bool translucent);
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "c_dispatch.h"
|
#include "c_dispatch.h"
|
||||||
#include "portal.h"
|
|
||||||
#include "p_maputl.h"
|
#include "p_maputl.h"
|
||||||
#include "hw_portal.h"
|
#include "hw_portal.h"
|
||||||
#include "hw_clipper.h"
|
#include "hw_clipper.h"
|
||||||
|
@ -141,6 +140,14 @@ bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di
|
||||||
best = p;
|
best = p;
|
||||||
bestindex = i;
|
bestindex = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the portal area contains the current camera viewpoint, let's always use it because it's likely to give the largest area.
|
||||||
|
if (p->boundingBox.contains(outer_di->Viewpoint.Pos))
|
||||||
|
{
|
||||||
|
best = p;
|
||||||
|
bestindex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,13 +179,14 @@ void HWPortal::DrawPortalStencil(FRenderState &state, int pass)
|
||||||
if (mPrimIndices.Size() == 0)
|
if (mPrimIndices.Size() == 0)
|
||||||
{
|
{
|
||||||
mPrimIndices.Resize(2 * lines.Size());
|
mPrimIndices.Resize(2 * lines.Size());
|
||||||
|
|
||||||
for (unsigned int i = 0; i < lines.Size(); i++)
|
for (unsigned int i = 0; i < lines.Size(); i++)
|
||||||
{
|
{
|
||||||
mPrimIndices[i * 2] = lines[i].vertindex;
|
mPrimIndices[i * 2] = lines[i].vertindex;
|
||||||
mPrimIndices[i * 2 + 1] = lines[i].vertcount;
|
mPrimIndices[i * 2 + 1] = lines[i].vertcount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < mPrimIndices.Size(); i += 2)
|
for (unsigned int i = 0; i < mPrimIndices.Size(); i += 2)
|
||||||
{
|
{
|
||||||
state.Draw(DT_TriangleFan, mPrimIndices[i], mPrimIndices[i + 1], i == 0);
|
state.Draw(DT_TriangleFan, mPrimIndices[i], mPrimIndices[i + 1], i == 0);
|
||||||
|
@ -187,12 +195,32 @@ void HWPortal::DrawPortalStencil(FRenderState &state, int pass)
|
||||||
{
|
{
|
||||||
// The cap's depth handling needs special treatment so that it won't block further portal caps.
|
// The cap's depth handling needs special treatment so that it won't block further portal caps.
|
||||||
if (pass == STP_DepthRestore) state.SetDepthRange(1, 1);
|
if (pass == STP_DepthRestore) state.SetDepthRange(1, 1);
|
||||||
state.Draw(DT_TriangleFan, FFlatVertexBuffer::STENCILTOP_INDEX, 4);
|
|
||||||
state.Draw(DT_TriangleFan, FFlatVertexBuffer::STENCILBOTTOM_INDEX, 4);
|
if (planesused & (1 << sector_t::floor))
|
||||||
|
{
|
||||||
|
auto verts = screen->mVertexData->AllocVertices(4);
|
||||||
|
auto ptr = verts.first;
|
||||||
|
ptr[0].Set((float)boundingBox.left, -32767.f, (float)boundingBox.top, 0, 0);
|
||||||
|
ptr[1].Set((float)boundingBox.right, -32767.f, (float)boundingBox.top, 0, 0);
|
||||||
|
ptr[2].Set((float)boundingBox.left, -32767.f, (float)boundingBox.bottom, 0, 0);
|
||||||
|
ptr[3].Set((float)boundingBox.right, -32767.f, (float)boundingBox.bottom, 0, 0);
|
||||||
|
state.Draw(DT_TriangleStrip, verts.second, 4, false);
|
||||||
|
}
|
||||||
|
if (planesused & (1 << sector_t::ceiling))
|
||||||
|
{
|
||||||
|
auto verts = screen->mVertexData->AllocVertices(4);
|
||||||
|
auto ptr = verts.first;
|
||||||
|
ptr[0].Set((float)boundingBox.left, 32767.f, (float)boundingBox.top, 0, 0);
|
||||||
|
ptr[1].Set((float)boundingBox.right, 32767.f, (float)boundingBox.top, 0, 0);
|
||||||
|
ptr[2].Set((float)boundingBox.left, 32767.f, (float)boundingBox.bottom, 0, 0);
|
||||||
|
ptr[3].Set((float)boundingBox.right, 32767.f, (float)boundingBox.bottom, 0, 0);
|
||||||
|
state.Draw(DT_TriangleStrip, verts.second, 4, false);
|
||||||
|
}
|
||||||
if (pass == STP_DepthRestore) state.SetDepthRange(0, 1);
|
if (pass == STP_DepthRestore) state.SetDepthRange(0, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// Start
|
// Start
|
||||||
|
@ -204,53 +232,60 @@ void HWPortal::SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil
|
||||||
Clocker c(PortalAll);
|
Clocker c(PortalAll);
|
||||||
|
|
||||||
rendered_portals++;
|
rendered_portals++;
|
||||||
|
|
||||||
if (usestencil)
|
if (usestencil)
|
||||||
{
|
{
|
||||||
// Create stencil
|
// Create stencil
|
||||||
|
state.SetStencil(0, SOP_Increment); // create stencil, increment stencil of valid pixels
|
||||||
|
state.SetColorMask(false);
|
||||||
state.SetEffect(EFF_STENCIL);
|
state.SetEffect(EFF_STENCIL);
|
||||||
state.EnableTexture(false);
|
state.EnableTexture(false);
|
||||||
state.ResetColor();
|
state.ResetColor();
|
||||||
|
state.SetDepthFunc(DF_Less);
|
||||||
|
|
||||||
if (NeedDepthBuffer())
|
if (NeedDepthBuffer())
|
||||||
{
|
{
|
||||||
state.SetStencil(0, SOP_Increment, SF_ColorMaskOff | SF_DepthMaskOff);
|
state.SetDepthMask(false); // don't write to Z-buffer!
|
||||||
state.SetDepthFunc(DF_Less);
|
|
||||||
DrawPortalStencil(state, STP_Stencil);
|
DrawPortalStencil(state, STP_Stencil);
|
||||||
|
|
||||||
// Clear Z-buffer
|
// Clear Z-buffer
|
||||||
state.SetStencil(1, SOP_Keep, SF_ColorMaskOff);
|
state.SetStencil(1, SOP_Keep); // draw sky into stencil. This stage doesn't modify the stencil.
|
||||||
|
state.SetDepthMask(true); // enable z-buffer again
|
||||||
state.SetDepthRange(1, 1);
|
state.SetDepthRange(1, 1);
|
||||||
state.SetDepthFunc(DF_Always);
|
state.SetDepthFunc(DF_Always);
|
||||||
DrawPortalStencil(state, STP_DepthClear);
|
DrawPortalStencil(state, STP_DepthClear);
|
||||||
|
|
||||||
// set normal drawing mode
|
// set normal drawing mode
|
||||||
state.EnableTexture(true);
|
state.EnableTexture(true);
|
||||||
state.SetStencil(1, SOP_Keep, SF_AllOn);
|
|
||||||
state.SetDepthRange(0, 1);
|
state.SetDepthRange(0, 1);
|
||||||
state.SetDepthFunc(DF_Less);
|
state.SetDepthFunc(DF_Less);
|
||||||
|
state.SetColorMask(true);
|
||||||
state.SetEffect(EFF_NONE);
|
state.SetEffect(EFF_NONE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// No z-buffer is needed therefore we can skip all the complicated stuff that is involved
|
// No z-buffer is needed therefore we can skip all the complicated stuff that is involved
|
||||||
// Note: We must draw the stencil with z-write enabled here because there is no second pass!
|
// Note: We must draw the stencil with z-write enabled here because there is no second pass!
|
||||||
state.SetStencil(0, SOP_Increment, SF_ColorMaskOff);
|
|
||||||
state.SetDepthFunc(DF_Less);
|
state.SetDepthMask(true);
|
||||||
DrawPortalStencil(state, STP_AllInOne);
|
DrawPortalStencil(state, STP_AllInOne);
|
||||||
|
state.SetStencil(1, SOP_Keep); // draw sky into stencil. This stage doesn't modify the stencil.
|
||||||
state.SetStencil(1, SOP_Keep, SF_DepthMaskOff);
|
|
||||||
state.EnableDepthTest(false);
|
|
||||||
state.EnableTexture(true);
|
state.EnableTexture(true);
|
||||||
|
state.SetColorMask(true);
|
||||||
state.SetEffect(EFF_NONE);
|
state.SetEffect(EFF_NONE);
|
||||||
|
state.EnableDepthTest(false);
|
||||||
|
state.SetDepthMask(false); // don't write to Z-buffer!
|
||||||
}
|
}
|
||||||
|
|
||||||
screen->stencilValue++;
|
screen->stencilValue++;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!NeedDepthBuffer())
|
if (!NeedDepthBuffer())
|
||||||
{
|
{
|
||||||
state.SetStencil(0, SOP_Keep, SF_DepthMaskOff);
|
state.SetDepthMask(false);
|
||||||
state.EnableDepthTest(false);
|
state.EnableDepthTest(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -259,6 +294,12 @@ void HWPortal::SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil
|
||||||
savedvisibility = di->Viewpoint.camera ? di->Viewpoint.camera->renderflags & RF_MAYBEINVISIBLE : ActorRenderFlags::FromInt(0);
|
savedvisibility = di->Viewpoint.camera ? di->Viewpoint.camera->renderflags & RF_MAYBEINVISIBLE : ActorRenderFlags::FromInt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// End
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
void HWPortal::RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestencil)
|
void HWPortal::RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestencil)
|
||||||
{
|
{
|
||||||
Clocker c(PortalAll);
|
Clocker c(PortalAll);
|
||||||
|
@ -268,53 +309,73 @@ void HWPortal::RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestenci
|
||||||
auto &vp = di->Viewpoint;
|
auto &vp = di->Viewpoint;
|
||||||
if (vp.camera != nullptr) vp.camera->renderflags = (vp.camera->renderflags & ~RF_MAYBEINVISIBLE) | savedvisibility;
|
if (vp.camera != nullptr) vp.camera->renderflags = (vp.camera->renderflags & ~RF_MAYBEINVISIBLE) | savedvisibility;
|
||||||
|
|
||||||
state.EnableDepthTest(true);
|
|
||||||
if (usestencil)
|
if (usestencil)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
state.SetColorMask(false); // no graphics
|
||||||
state.SetEffect(EFF_NONE);
|
state.SetEffect(EFF_NONE);
|
||||||
state.ResetColor();
|
state.ResetColor();
|
||||||
state.EnableTexture(false);
|
state.EnableTexture(false);
|
||||||
|
|
||||||
if (needdepth)
|
if (needdepth)
|
||||||
{
|
{
|
||||||
// first step: reset the depth buffer to max. depth
|
// first step: reset the depth buffer to max. depth
|
||||||
state.SetStencil(0, SOP_Keep, SF_ColorMaskOff);
|
|
||||||
state.SetDepthRange(1, 1); // always
|
state.SetDepthRange(1, 1); // always
|
||||||
state.SetDepthFunc(DF_Always); // write the farthest depth value
|
state.SetDepthFunc(DF_Always); // write the farthest depth value
|
||||||
DrawPortalStencil(state, STP_DepthClear);
|
DrawPortalStencil(state, STP_DepthClear);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state.EnableDepthTest(true);
|
||||||
|
}
|
||||||
|
|
||||||
// second step: restore the depth buffer to the previous values and reset the stencil
|
// second step: restore the depth buffer to the previous values and reset the stencil
|
||||||
state.SetStencil(0, SOP_Decrement, SF_ColorMaskOff);
|
|
||||||
state.SetDepthRange(0, 1);
|
|
||||||
state.SetDepthFunc(DF_LEqual);
|
state.SetDepthFunc(DF_LEqual);
|
||||||
|
state.SetDepthRange(0, 1);
|
||||||
|
state.SetStencil(0, SOP_Decrement);
|
||||||
DrawPortalStencil(state, STP_DepthRestore);
|
DrawPortalStencil(state, STP_DepthRestore);
|
||||||
|
state.SetDepthFunc(DF_Less);
|
||||||
|
|
||||||
|
|
||||||
state.EnableTexture(true);
|
state.EnableTexture(true);
|
||||||
state.SetEffect(EFF_NONE);
|
state.SetEffect(EFF_NONE);
|
||||||
|
state.SetColorMask(true);
|
||||||
screen->stencilValue--;
|
screen->stencilValue--;
|
||||||
|
|
||||||
|
// restore old stencil op.
|
||||||
|
state.SetStencil(0, SOP_Keep);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (needdepth)
|
||||||
|
{
|
||||||
|
state.Clear(CT_Depth);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state.EnableDepthTest(true);
|
||||||
|
state.SetDepthMask(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This draws a valid z-buffer into the stencil's contents to ensure it
|
||||||
|
// doesn't get overwritten by the level's geometry.
|
||||||
|
|
||||||
state.ResetColor();
|
state.ResetColor();
|
||||||
|
state.SetDepthFunc(DF_LEqual);
|
||||||
|
state.SetDepthRange(0, 1);
|
||||||
|
state.SetColorMask(0, 0, 0, 1); // mark portal in alpha channel but don't touch color
|
||||||
state.SetEffect(EFF_STENCIL);
|
state.SetEffect(EFF_STENCIL);
|
||||||
state.EnableTexture(false);
|
state.EnableTexture(false);
|
||||||
state.SetRenderStyle(STYLE_Source);
|
state.SetRenderStyle(STYLE_Source);
|
||||||
|
|
||||||
state.SetStencil(0, SOP_Keep, SF_ColorMaskOff | SF_ColorMaskAlpha); // SSAO needs the alpha channel as a marker.
|
|
||||||
if (needdepth) state.Clear(CT_Depth);
|
|
||||||
state.SetDepthRange(0, 1);
|
|
||||||
state.SetDepthFunc(DF_LEqual);
|
|
||||||
DrawPortalStencil(state, STP_DepthRestore);
|
DrawPortalStencil(state, STP_DepthRestore);
|
||||||
|
|
||||||
state.SetEffect(EFF_NONE);
|
state.SetEffect(EFF_NONE);
|
||||||
state.EnableTexture(true);
|
state.EnableTexture(true);
|
||||||
|
state.SetColorMask(true);
|
||||||
|
state.SetDepthFunc(DF_Less);
|
||||||
}
|
}
|
||||||
state.SetStencil(0, SOP_Keep, SF_AllOn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
@ -328,7 +389,6 @@ void HWScenePortalBase::ClearClipper(HWDrawInfo *di, Clipper *clipper)
|
||||||
|
|
||||||
clipper->Clear();
|
clipper->Clear();
|
||||||
|
|
||||||
auto &lines = mOwner->lines;
|
|
||||||
// Set the clipper to the minimal visible area
|
// Set the clipper to the minimal visible area
|
||||||
clipper->SafeAddClipRange(0, 0xffffffff);
|
clipper->SafeAddClipRange(0, 0xffffffff);
|
||||||
for (unsigned int i = 0; i < lines.Size(); i++)
|
for (unsigned int i = 0; i < lines.Size(); i++)
|
||||||
|
@ -409,7 +469,7 @@ int HWLinePortal::ClipPoint(const DVector2 &pos)
|
||||||
|
|
||||||
bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
|
bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
|
||||||
{
|
{
|
||||||
auto state = mOwner->mState;
|
auto state = mState;
|
||||||
if (state->renderdepth > r_mirror_recursions)
|
if (state->renderdepth > r_mirror_recursions)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -490,7 +550,7 @@ bool HWMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clippe
|
||||||
|
|
||||||
void HWMirrorPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate)
|
void HWMirrorPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate)
|
||||||
{
|
{
|
||||||
mOwner->mState->MirrorFlag--;
|
mState->MirrorFlag--;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *HWMirrorPortal::GetName() { return "Mirror"; }
|
const char *HWMirrorPortal::GetName() { return "Mirror"; }
|
||||||
|
@ -513,7 +573,7 @@ const char *HWMirrorPortal::GetName() { return "Mirror"; }
|
||||||
bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
|
bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
|
||||||
{
|
{
|
||||||
// TODO: Handle recursion more intelligently
|
// TODO: Handle recursion more intelligently
|
||||||
auto &state = mOwner->mState;
|
auto &state = mState;
|
||||||
if (state->renderdepth>r_mirror_recursions)
|
if (state->renderdepth>r_mirror_recursions)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -543,7 +603,6 @@ bool HWLineToLinePortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *cl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &lines = mOwner->lines;
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < lines.Size(); i++)
|
for (unsigned i = 0; i < lines.Size(); i++)
|
||||||
{
|
{
|
||||||
|
@ -589,10 +648,10 @@ const char *HWLineToLinePortal::GetName() { return "LineToLine"; }
|
||||||
|
|
||||||
bool HWSkyboxPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
|
bool HWSkyboxPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
|
||||||
{
|
{
|
||||||
auto state = mOwner->mState;
|
auto state = mState;
|
||||||
old_pm = state->PlaneMirrorMode;
|
old_pm = state->PlaneMirrorMode;
|
||||||
|
|
||||||
if (mOwner->mState->skyboxrecursion >= 3)
|
if (mState->skyboxrecursion >= 3)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -631,7 +690,7 @@ void HWSkyboxPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate)
|
||||||
{
|
{
|
||||||
rstate.SetDepthClamp(oldclamp);
|
rstate.SetDepthClamp(oldclamp);
|
||||||
|
|
||||||
auto state = mOwner->mState;
|
auto state = mState;
|
||||||
portal->mFlags &= ~PORTSF_INSKYBOX;
|
portal->mFlags &= ~PORTSF_INSKYBOX;
|
||||||
state->inskybox = false;
|
state->inskybox = false;
|
||||||
state->skyboxrecursion--;
|
state->skyboxrecursion--;
|
||||||
|
@ -699,7 +758,7 @@ void HWSectorStackPortal::SetupCoverage(HWDrawInfo *di)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
|
bool HWSectorStackPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
|
||||||
{
|
{
|
||||||
auto state = mOwner->mState;
|
auto state = mState;
|
||||||
FSectorPortalGroup *portal = origin;
|
FSectorPortalGroup *portal = origin;
|
||||||
auto &vp = di->Viewpoint;
|
auto &vp = di->Viewpoint;
|
||||||
|
|
||||||
|
@ -751,7 +810,7 @@ const char *HWSectorStackPortal::GetName() { return "Sectorstack"; }
|
||||||
|
|
||||||
bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
|
bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper)
|
||||||
{
|
{
|
||||||
auto state = mOwner->mState;
|
auto state = mState;
|
||||||
if (state->renderdepth > r_mirror_recursions)
|
if (state->renderdepth > r_mirror_recursions)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -781,7 +840,7 @@ bool HWPlaneMirrorPortal::Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *c
|
||||||
|
|
||||||
void HWPlaneMirrorPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate)
|
void HWPlaneMirrorPortal::Shutdown(HWDrawInfo *di, FRenderState &rstate)
|
||||||
{
|
{
|
||||||
auto state = mOwner->mState;
|
auto state = mState;
|
||||||
state->PlaneMirrorFlag--;
|
state->PlaneMirrorFlag--;
|
||||||
state->PlaneMirrorMode = old_pm;
|
state->PlaneMirrorMode = old_pm;
|
||||||
std::swap(screen->instack[sector_t::floor], screen->instack[sector_t::ceiling]);
|
std::swap(screen->instack[sector_t::floor], screen->instack[sector_t::ceiling]);
|
||||||
|
@ -800,8 +859,8 @@ const char *HWPlaneMirrorPortal::GetName() { return origin->fC() < 0? "Planemirr
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
HWHorizonPortal::HWHorizonPortal(FPortalSceneState *s, GLHorizonInfo * pt, FRenderViewpoint &vp, HWDrawInfo *di, bool local)
|
HWHorizonPortal::HWHorizonPortal(FPortalSceneState *s, GLHorizonInfo * pt, FRenderViewpoint &vp, bool local)
|
||||||
: HWPortal(s, local)
|
: HWPortal(s, local)
|
||||||
{
|
{
|
||||||
origin = pt;
|
origin = pt;
|
||||||
|
|
||||||
|
@ -960,7 +1019,7 @@ void HWEEHorizonPortal::DrawContents(HWDrawInfo *di, FRenderState &state)
|
||||||
{
|
{
|
||||||
horz.plane.Texheight = vp.Pos.Z + fabs(horz.plane.Texheight);
|
horz.plane.Texheight = vp.Pos.Z + fabs(horz.plane.Texheight);
|
||||||
}
|
}
|
||||||
HWHorizonPortal ceil(mState, &horz, di->Viewpoint, di, true);
|
HWHorizonPortal ceil(mState, &horz, di->Viewpoint, true);
|
||||||
ceil.DrawContents(di, state);
|
ceil.DrawContents(di, state);
|
||||||
}
|
}
|
||||||
if (sector->GetTexture(sector_t::floor) != skyflatnum)
|
if (sector->GetTexture(sector_t::floor) != skyflatnum)
|
||||||
|
@ -974,7 +1033,7 @@ void HWEEHorizonPortal::DrawContents(HWDrawInfo *di, FRenderState &state)
|
||||||
{
|
{
|
||||||
horz.plane.Texheight = vp.Pos.Z - fabs(horz.plane.Texheight);
|
horz.plane.Texheight = vp.Pos.Z - fabs(horz.plane.Texheight);
|
||||||
}
|
}
|
||||||
HWHorizonPortal floor(mState, &horz, di->Viewpoint, di, true);
|
HWHorizonPortal floor(mState, &horz, di->Viewpoint, true);
|
||||||
floor.DrawContents(di, state);
|
floor.DrawContents(di, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "portal.h"
|
#include "tarray.h"
|
||||||
|
#include "r_utility.h"
|
||||||
#include "actor.h"
|
#include "actor.h"
|
||||||
#include "hw_drawinfo.h"
|
#include "hwrenderer/scene/hw_drawinfo.h"
|
||||||
#include "hw_drawstructs.h"
|
#include "hwrenderer/scene/hw_drawstructs.h"
|
||||||
|
#include "hw_renderstate.h"
|
||||||
#include "hwrenderer/textures/hw_material.h"
|
#include "hwrenderer/textures/hw_material.h"
|
||||||
#include "hwrenderer/scene/hw_renderstate.h"
|
|
||||||
|
|
||||||
class FSkyVertexBuffer;
|
|
||||||
|
|
||||||
struct GLSkyInfo
|
struct GLSkyInfo
|
||||||
{
|
{
|
||||||
|
@ -61,12 +61,17 @@ class HWPortal
|
||||||
public:
|
public:
|
||||||
FPortalSceneState * mState;
|
FPortalSceneState * mState;
|
||||||
TArray<GLWall> lines;
|
TArray<GLWall> lines;
|
||||||
|
BoundingRect boundingBox;
|
||||||
|
int planesused = 0;
|
||||||
|
|
||||||
HWPortal(FPortalSceneState *s, bool local);
|
HWPortal(FPortalSceneState *s, bool local = false) : mState(s), boundingBox(false)
|
||||||
void SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil);
|
{
|
||||||
void RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestencil);
|
}
|
||||||
|
virtual ~HWPortal() {}
|
||||||
virtual ~HWPortal() {}
|
virtual int ClipSeg(seg_t *seg, const DVector3 &viewpos) { return PClip_Inside; }
|
||||||
|
virtual int ClipSubsector(subsector_t *sub) { return PClip_Inside; }
|
||||||
|
virtual int ClipPoint(const DVector2 &pos) { return PClip_Inside; }
|
||||||
|
virtual line_t *ClipLine() { return nullptr; }
|
||||||
virtual void * GetSource() const = 0; // GetSource MUST be implemented!
|
virtual void * GetSource() const = 0; // GetSource MUST be implemented!
|
||||||
virtual const char *GetName() = 0;
|
virtual const char *GetName() = 0;
|
||||||
virtual bool IsSky() { return false; }
|
virtual bool IsSky() { return false; }
|
||||||
|
@ -74,15 +79,20 @@ public:
|
||||||
virtual bool NeedDepthBuffer() { return true; }
|
virtual bool NeedDepthBuffer() { return true; }
|
||||||
virtual void DrawContents(HWDrawInfo *di, FRenderState &state) = 0;
|
virtual void DrawContents(HWDrawInfo *di, FRenderState &state) = 0;
|
||||||
virtual void RenderAttached(HWDrawInfo *di) {}
|
virtual void RenderAttached(HWDrawInfo *di) {}
|
||||||
|
void SetupStencil(HWDrawInfo *di, FRenderState &state, bool usestencil);
|
||||||
|
void RemoveStencil(HWDrawInfo *di, FRenderState &state, bool usestencil);
|
||||||
|
|
||||||
void AddLine(GLWall * l)
|
void AddLine(GLWall * l)
|
||||||
{
|
{
|
||||||
lines.Push(*l);
|
lines.Push(*l);
|
||||||
|
boundingBox.addVertex(l->glseg.x1, l->glseg.y1);
|
||||||
|
boundingBox.addVertex(l->glseg.x2, l->glseg.y2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct FPortalSceneState
|
struct FPortalSceneState
|
||||||
{
|
{
|
||||||
int MirrorFlag = 0;
|
int MirrorFlag = 0;
|
||||||
|
@ -116,37 +126,28 @@ struct FPortalSceneState
|
||||||
void RenderPortal(HWPortal *p, FRenderState &state, bool usestencil, HWDrawInfo *outer_di);
|
void RenderPortal(HWPortal *p, FRenderState &state, bool usestencil, HWDrawInfo *outer_di);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline HWPortal::HWPortal(FPortalSceneState *s, bool local) : mState(s)
|
|
||||||
{
|
class HWScenePortalBase : public HWPortal
|
||||||
//if (!local) s->portals.Push(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class HWScenePortalBase
|
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
HWPortal *mOwner;
|
HWScenePortalBase(FPortalSceneState *state) : HWPortal(state, false)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
HWScenePortalBase() {}
|
|
||||||
virtual ~HWScenePortalBase() {}
|
|
||||||
void SetOwner(HWPortal *p) { mOwner = p; }
|
|
||||||
void ClearClipper(HWDrawInfo *di, Clipper *clipper);
|
void ClearClipper(HWDrawInfo *di, Clipper *clipper);
|
||||||
|
|
||||||
virtual int ClipSeg(seg_t *seg, const DVector3 &viewpos) { return PClip_Inside; }
|
|
||||||
virtual int ClipSubsector(subsector_t *sub) { return PClip_Inside; }
|
|
||||||
virtual int ClipPoint(const DVector2 &pos) { return PClip_Inside; }
|
|
||||||
virtual line_t *ClipLine() { return nullptr; }
|
|
||||||
|
|
||||||
virtual bool IsSky() { return false; }
|
|
||||||
virtual bool NeedCap() { return false; }
|
|
||||||
virtual bool NeedDepthBuffer() { return true; }
|
virtual bool NeedDepthBuffer() { return true; }
|
||||||
virtual void * GetSource() const = 0; // GetSource MUST be implemented!
|
virtual void DrawContents(HWDrawInfo *di, FRenderState &state)
|
||||||
virtual const char *GetName() = 0;
|
{
|
||||||
|
if (Setup(di, state, di->mClipper))
|
||||||
|
{
|
||||||
|
di->DrawScene(di, DM_PORTAL);
|
||||||
|
Shutdown(di, state);
|
||||||
|
}
|
||||||
|
else state.ClearScreen();
|
||||||
|
}
|
||||||
virtual bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) = 0;
|
virtual bool Setup(HWDrawInfo *di, FRenderState &rstate, Clipper *clipper) = 0;
|
||||||
virtual void Shutdown(HWDrawInfo *di, FRenderState &rstate) {}
|
virtual void Shutdown(HWDrawInfo *di, FRenderState &rstate) {}
|
||||||
virtual void RenderAttached(HWDrawInfo *di) {}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HWLinePortal : public HWScenePortalBase
|
struct HWLinePortal : public HWScenePortalBase
|
||||||
|
@ -157,14 +158,14 @@ struct HWLinePortal : public HWScenePortalBase
|
||||||
|
|
||||||
angle_t angv1, angv2; // for quick comparisons with a line or subsector
|
angle_t angv1, angv2; // for quick comparisons with a line or subsector
|
||||||
|
|
||||||
HWLinePortal(line_t *line)
|
HWLinePortal(FPortalSceneState *state, line_t *line) : HWScenePortalBase(state)
|
||||||
{
|
{
|
||||||
v1 = line->v1;
|
v1 = line->v1;
|
||||||
v2 = line->v2;
|
v2 = line->v2;
|
||||||
CalcDelta();
|
CalcDelta();
|
||||||
}
|
}
|
||||||
|
|
||||||
HWLinePortal(FLinePortalSpan *line)
|
HWLinePortal(FPortalSceneState *state, FLinePortalSpan *line) : HWScenePortalBase(state)
|
||||||
{
|
{
|
||||||
if (line->lines[0]->mType != PORTT_LINKED || line->v1 == nullptr)
|
if (line->lines[0]->mType != PORTT_LINKED || line->v1 == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -212,8 +213,8 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
HWMirrorPortal(line_t * line)
|
HWMirrorPortal(FPortalSceneState *state, line_t * line)
|
||||||
: HWLinePortal(line)
|
: HWLinePortal(state, line)
|
||||||
{
|
{
|
||||||
linedef = line;
|
linedef = line;
|
||||||
}
|
}
|
||||||
|
@ -232,8 +233,8 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
HWLineToLinePortal(FLinePortalSpan *ll)
|
HWLineToLinePortal(FPortalSceneState *state, FLinePortalSpan *ll)
|
||||||
: HWLinePortal(ll)
|
: HWLinePortal(state, ll)
|
||||||
{
|
{
|
||||||
glport = ll;
|
glport = ll;
|
||||||
}
|
}
|
||||||
|
@ -256,7 +257,7 @@ protected:
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
HWSkyboxPortal(FSectorPortal * pt)
|
HWSkyboxPortal(FPortalSceneState *state, FSectorPortal * pt) : HWScenePortalBase(state)
|
||||||
{
|
{
|
||||||
portal = pt;
|
portal = pt;
|
||||||
}
|
}
|
||||||
|
@ -277,7 +278,7 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
HWSectorStackPortal(FSectorPortalGroup *pt)
|
HWSectorStackPortal(FPortalSceneState *state, FSectorPortalGroup *pt) : HWScenePortalBase(state)
|
||||||
{
|
{
|
||||||
origin = pt;
|
origin = pt;
|
||||||
}
|
}
|
||||||
|
@ -301,7 +302,7 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
HWPlaneMirrorPortal(secplane_t * pt)
|
HWPlaneMirrorPortal(FPortalSceneState *state, secplane_t * pt) : HWScenePortalBase(state)
|
||||||
{
|
{
|
||||||
origin = pt;
|
origin = pt;
|
||||||
}
|
}
|
||||||
|
@ -309,34 +310,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class HWScenePortal : public HWPortal
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HWScenePortalBase *mScene;
|
|
||||||
HWScenePortal(FPortalSceneState *state, HWScenePortalBase *handler) : HWPortal(state, false)
|
|
||||||
{
|
|
||||||
mScene = handler;
|
|
||||||
handler->SetOwner(this);
|
|
||||||
}
|
|
||||||
~HWScenePortal() { delete mScene; }
|
|
||||||
virtual void * GetSource() const { return mScene->GetSource(); }
|
|
||||||
virtual const char *GetName() { return mScene->GetName(); }
|
|
||||||
virtual bool IsSky() { return mScene->IsSky(); }
|
|
||||||
virtual bool NeedCap() { return true; }
|
|
||||||
virtual bool NeedDepthBuffer() { return true; }
|
|
||||||
virtual void DrawContents(HWDrawInfo *di, FRenderState &state)
|
|
||||||
{
|
|
||||||
if (mScene->Setup(di, state, di->mClipper))
|
|
||||||
{
|
|
||||||
di->DrawScene(di, DM_PORTAL);
|
|
||||||
mScene->Shutdown(di, state);
|
|
||||||
}
|
|
||||||
else state.ClearScreen();
|
|
||||||
}
|
|
||||||
virtual void RenderAttached(HWDrawInfo *di) { return mScene->RenderAttached(di); }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct HWHorizonPortal : public HWPortal
|
struct HWHorizonPortal : public HWPortal
|
||||||
{
|
{
|
||||||
GLHorizonInfo * origin;
|
GLHorizonInfo * origin;
|
||||||
|
@ -352,8 +325,8 @@ protected:
|
||||||
virtual const char *GetName();
|
virtual const char *GetName();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
HWHorizonPortal(FPortalSceneState *state, GLHorizonInfo * pt, FRenderViewpoint &vp, HWDrawInfo *di, bool local = false);
|
HWHorizonPortal(FPortalSceneState *state, GLHorizonInfo * pt, FRenderViewpoint &vp, bool local = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HWEEHorizonPortal : public HWPortal
|
struct HWEEHorizonPortal : public HWPortal
|
||||||
|
@ -369,7 +342,7 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
HWEEHorizonPortal(FPortalSceneState *state, FSectorPortal *pt, HWDrawInfo *di) : HWPortal(state, false)
|
HWEEHorizonPortal(FPortalSceneState *state, FSectorPortal *pt) : HWPortal(state)
|
||||||
{
|
{
|
||||||
portal = pt;
|
portal = pt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,6 @@ enum EStencilFlags
|
||||||
SF_AllOn = 0,
|
SF_AllOn = 0,
|
||||||
SF_ColorMaskOff = 1,
|
SF_ColorMaskOff = 1,
|
||||||
SF_DepthMaskOff = 2,
|
SF_DepthMaskOff = 2,
|
||||||
SF_ColorMaskAlpha = 4, // hack value for SSAO
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum EStencilOp
|
enum EStencilOp
|
||||||
|
@ -507,8 +506,9 @@ public:
|
||||||
virtual void SetDepthMask(bool on) = 0; // Used by decals and indirectly by portal setup.
|
virtual void SetDepthMask(bool on) = 0; // Used by decals and indirectly by portal setup.
|
||||||
virtual void SetDepthFunc(int func) = 0; // Used by models, portals and mirror surfaces.
|
virtual void SetDepthFunc(int func) = 0; // Used by models, portals and mirror surfaces.
|
||||||
virtual void SetDepthRange(float min, float max) = 0; // Used by portal setup.
|
virtual void SetDepthRange(float min, float max) = 0; // Used by portal setup.
|
||||||
|
virtual void SetColorMask(bool r, bool g, bool b, bool a) = 0; // Used by portals.
|
||||||
virtual void EnableDrawBufferAttachments(bool on) = 0; // Used by fog boundary drawer.
|
virtual void EnableDrawBufferAttachments(bool on) = 0; // Used by fog boundary drawer.
|
||||||
virtual void SetStencil(int offs, int op, int flags) = 0; // Used by portal setup and render hacks.
|
virtual void SetStencil(int offs, int op, int flags=-1) = 0; // Used by portal setup and render hacks.
|
||||||
virtual void SetCulling(int mode) = 0; // Used by model drawer only.
|
virtual void SetCulling(int mode) = 0; // Used by model drawer only.
|
||||||
virtual void EnableClipDistance(int num, bool state) = 0; // Use by sprite sorter for vertical splits.
|
virtual void EnableClipDistance(int num, bool state) = 0; // Use by sprite sorter for vertical splits.
|
||||||
virtual void Clear(int targets) = 0; // not used during normal rendering
|
virtual void Clear(int targets) = 0; // not used during normal rendering
|
||||||
|
@ -519,6 +519,10 @@ public:
|
||||||
virtual void EnableMultisampling(bool on) = 0; // only active for 2D
|
virtual void EnableMultisampling(bool on) = 0; // only active for 2D
|
||||||
virtual void EnableLineSmooth(bool on) = 0; // constant setting for each 2D drawer operation
|
virtual void EnableLineSmooth(bool on) = 0; // constant setting for each 2D drawer operation
|
||||||
|
|
||||||
|
void SetColorMask(bool on)
|
||||||
|
{
|
||||||
|
SetColorMask(on, on, on, on);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,7 @@ void GLWall::SkyPlane(HWDrawInfo *di, sector_t *sector, int plane, bool allowref
|
||||||
skyinfo.init(sector->sky, Colormap.FadeColor);
|
skyinfo.init(sector->sky, Colormap.FadeColor);
|
||||||
ptype = PORTALTYPE_SKY;
|
ptype = PORTALTYPE_SKY;
|
||||||
sky = &skyinfo;
|
sky = &skyinfo;
|
||||||
PutPortal(di, ptype);
|
PutPortal(di, ptype, plane);
|
||||||
}
|
}
|
||||||
else if (sportal != nullptr)
|
else if (sportal != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -162,7 +162,7 @@ void GLWall::SkyPlane(HWDrawInfo *di, sector_t *sector, int plane, bool allowref
|
||||||
}
|
}
|
||||||
if (ptype != -1)
|
if (ptype != -1)
|
||||||
{
|
{
|
||||||
PutPortal(di, ptype);
|
PutPortal(di, ptype, plane);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ void GLWall::SkyLine(HWDrawInfo *di, sector_t *fs, line_t *line)
|
||||||
ztop[1] = zceil[1];
|
ztop[1] = zceil[1];
|
||||||
zbottom[0] = zfloor[0];
|
zbottom[0] = zfloor[0];
|
||||||
zbottom[1] = zfloor[1];
|
zbottom[1] = zfloor[1];
|
||||||
PutPortal(di, ptype);
|
PutPortal(di, ptype, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -104,9 +104,9 @@ void HWSkyPortal::RenderBox(HWDrawInfo *di, FRenderState &state, FTextureID texn
|
||||||
state.mModelMatrix.loadIdentity();
|
state.mModelMatrix.loadIdentity();
|
||||||
|
|
||||||
if (!sky2)
|
if (!sky2)
|
||||||
state.mModelMatrix.rotate(-180.0f+x_offset, level.info->skyrotatevector.X, level.info->skyrotatevector.Z, level.info->skyrotatevector.Y);
|
state.mModelMatrix.rotate(-180.0f+x_offset, ::level.info->skyrotatevector.X, ::level.info->skyrotatevector.Z, ::level.info->skyrotatevector.Y);
|
||||||
else
|
else
|
||||||
state.mModelMatrix.rotate(-180.0f+x_offset, level.info->skyrotatevector2.X, level.info->skyrotatevector2.Z, level.info->skyrotatevector2.Y);
|
state.mModelMatrix.rotate(-180.0f+x_offset, ::level.info->skyrotatevector2.X, ::level.info->skyrotatevector2.Z, ::level.info->skyrotatevector2.Y);
|
||||||
|
|
||||||
if (sb->faces[5])
|
if (sb->faces[5])
|
||||||
{
|
{
|
||||||
|
|
|
@ -483,10 +483,10 @@ void GLWall::PutWall(HWDrawInfo *di, bool translucent)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void GLWall::PutPortal(HWDrawInfo *di, int ptype)
|
void GLWall::PutPortal(HWDrawInfo *di, int ptype, int plane)
|
||||||
{
|
{
|
||||||
auto pstate = screen->mPortalState;
|
auto pstate = screen->mPortalState;
|
||||||
HWPortal * portal;
|
HWPortal * portal = nullptr;
|
||||||
|
|
||||||
MakeVertices(di, false);
|
MakeVertices(di, false);
|
||||||
switch (ptype)
|
switch (ptype)
|
||||||
|
@ -498,7 +498,7 @@ void GLWall::PutPortal(HWDrawInfo *di, int ptype)
|
||||||
portal = di->FindPortal(horizon);
|
portal = di->FindPortal(horizon);
|
||||||
if (!portal)
|
if (!portal)
|
||||||
{
|
{
|
||||||
portal = new HWHorizonPortal(pstate, horizon, di->Viewpoint, di);
|
portal = new HWHorizonPortal(pstate, horizon, di->Viewpoint);
|
||||||
di->Portals.Push(portal);
|
di->Portals.Push(portal);
|
||||||
}
|
}
|
||||||
portal->AddLine(this);
|
portal->AddLine(this);
|
||||||
|
@ -509,10 +509,10 @@ void GLWall::PutPortal(HWDrawInfo *di, int ptype)
|
||||||
if (!portal)
|
if (!portal)
|
||||||
{
|
{
|
||||||
// either a regular skybox or an Eternity-style horizon
|
// either a regular skybox or an Eternity-style horizon
|
||||||
if (secportal->mType != PORTS_SKYVIEWPOINT) portal = new HWEEHorizonPortal(pstate, secportal, di);
|
if (secportal->mType != PORTS_SKYVIEWPOINT) portal = new HWEEHorizonPortal(pstate, secportal);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
portal = new HWScenePortal(pstate, new HWSkyboxPortal(secportal));
|
portal = new HWSkyboxPortal(pstate, secportal);
|
||||||
di->Portals.Push(portal);
|
di->Portals.Push(portal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -523,7 +523,7 @@ void GLWall::PutPortal(HWDrawInfo *di, int ptype)
|
||||||
portal = di->FindPortal(this->portal);
|
portal = di->FindPortal(this->portal);
|
||||||
if (!portal)
|
if (!portal)
|
||||||
{
|
{
|
||||||
portal = new HWScenePortal(pstate, new HWSectorStackPortal(this->portal));
|
portal = new HWSectorStackPortal(pstate, this->portal);
|
||||||
di->Portals.Push(portal);
|
di->Portals.Push(portal);
|
||||||
}
|
}
|
||||||
portal->AddLine(this);
|
portal->AddLine(this);
|
||||||
|
@ -532,12 +532,11 @@ void GLWall::PutPortal(HWDrawInfo *di, int ptype)
|
||||||
case PORTALTYPE_PLANEMIRROR:
|
case PORTALTYPE_PLANEMIRROR:
|
||||||
if (pstate->PlaneMirrorMode * planemirror->fC() <= 0)
|
if (pstate->PlaneMirrorMode * planemirror->fC() <= 0)
|
||||||
{
|
{
|
||||||
//@sync-portal
|
|
||||||
planemirror = pstate->UniquePlaneMirrors.Get(planemirror);
|
planemirror = pstate->UniquePlaneMirrors.Get(planemirror);
|
||||||
portal = di->FindPortal(planemirror);
|
portal = di->FindPortal(planemirror);
|
||||||
if (!portal)
|
if (!portal)
|
||||||
{
|
{
|
||||||
portal = new HWScenePortal(pstate, new HWPlaneMirrorPortal(planemirror));
|
portal = new HWPlaneMirrorPortal(pstate, planemirror);
|
||||||
di->Portals.Push(portal);
|
di->Portals.Push(portal);
|
||||||
}
|
}
|
||||||
portal->AddLine(this);
|
portal->AddLine(this);
|
||||||
|
@ -548,7 +547,7 @@ void GLWall::PutPortal(HWDrawInfo *di, int ptype)
|
||||||
portal = di->FindPortal(seg->linedef);
|
portal = di->FindPortal(seg->linedef);
|
||||||
if (!portal)
|
if (!portal)
|
||||||
{
|
{
|
||||||
portal = new HWScenePortal(pstate, new HWMirrorPortal(seg->linedef));
|
portal = new HWMirrorPortal(pstate, seg->linedef);
|
||||||
di->Portals.Push(portal);
|
di->Portals.Push(portal);
|
||||||
}
|
}
|
||||||
portal->AddLine(this);
|
portal->AddLine(this);
|
||||||
|
@ -570,7 +569,7 @@ void GLWall::PutPortal(HWDrawInfo *di, int ptype)
|
||||||
{
|
{
|
||||||
di->ProcessActorsInPortal(otherside->getPortal()->mGroup, di->in_area);
|
di->ProcessActorsInPortal(otherside->getPortal()->mGroup, di->in_area);
|
||||||
}
|
}
|
||||||
portal = new HWScenePortal(pstate, new HWLineToLinePortal(lineportal));
|
portal = new HWLineToLinePortal(pstate, lineportal);
|
||||||
di->Portals.Push(portal);
|
di->Portals.Push(portal);
|
||||||
}
|
}
|
||||||
portal->AddLine(this);
|
portal->AddLine(this);
|
||||||
|
@ -588,6 +587,11 @@ void GLWall::PutPortal(HWDrawInfo *di, int ptype)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
vertcount = 0;
|
vertcount = 0;
|
||||||
|
|
||||||
|
if (plane != -1 && portal)
|
||||||
|
{
|
||||||
|
portal->planesused |= (1<<plane);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -849,7 +853,7 @@ bool GLWall::DoHorizon(HWDrawInfo *di, seg_t * seg,sector_t * fs, vertex_t * v1,
|
||||||
|
|
||||||
if (di->isFullbrightScene()) hi.colormap.Clear();
|
if (di->isFullbrightScene()) hi.colormap.Clear();
|
||||||
horizon = &hi;
|
horizon = &hi;
|
||||||
PutPortal(di, PORTALTYPE_HORIZON);
|
PutPortal(di, PORTALTYPE_HORIZON, -1);
|
||||||
}
|
}
|
||||||
ztop[1] = ztop[0] = zbottom[0];
|
ztop[1] = ztop[0] = zbottom[0];
|
||||||
}
|
}
|
||||||
|
@ -878,7 +882,7 @@ bool GLWall::DoHorizon(HWDrawInfo *di, seg_t * seg,sector_t * fs, vertex_t * v1,
|
||||||
|
|
||||||
if (di->isFullbrightScene()) hi.colormap.Clear();
|
if (di->isFullbrightScene()) hi.colormap.Clear();
|
||||||
horizon = &hi;
|
horizon = &hi;
|
||||||
PutPortal(di, PORTALTYPE_HORIZON);
|
PutPortal(di, PORTALTYPE_HORIZON, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -1135,7 +1139,7 @@ void GLWall::DoTexture(HWDrawInfo *di, int _type,seg_t * seg, int peg,
|
||||||
|
|
||||||
if (seg->linedef->special == Line_Mirror && _type == RENDERWALL_M1S && gl_mirrors)
|
if (seg->linedef->special == Line_Mirror && _type == RENDERWALL_M1S && gl_mirrors)
|
||||||
{
|
{
|
||||||
PutPortal(di, PORTALTYPE_MIRROR);
|
PutPortal(di, PORTALTYPE_MIRROR, -1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1970,7 +1974,7 @@ void GLWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
|
||||||
ztop[1] = zceil[1];
|
ztop[1] = zceil[1];
|
||||||
zbottom[0] = zfloor[0];
|
zbottom[0] = zfloor[0];
|
||||||
zbottom[1] = zfloor[1];
|
zbottom[1] = zfloor[1];
|
||||||
PutPortal(di, PORTALTYPE_LINETOLINE);
|
PutPortal(di, PORTALTYPE_LINETOLINE, -1);
|
||||||
}
|
}
|
||||||
else if (seg->linedef->GetTransferredPortal())
|
else if (seg->linedef->GetTransferredPortal())
|
||||||
{
|
{
|
||||||
|
@ -2077,7 +2081,7 @@ void GLWall::Process(HWDrawInfo *di, seg_t *seg, sector_t * frontsector, sector_
|
||||||
ztop[1] = bch2;
|
ztop[1] = bch2;
|
||||||
zbottom[0] = bfh1;
|
zbottom[0] = bfh1;
|
||||||
zbottom[1] = bfh2;
|
zbottom[1] = bfh2;
|
||||||
PutPortal(di, PORTALTYPE_LINETOLINE);
|
PutPortal(di, PORTALTYPE_LINETOLINE, -1);
|
||||||
}
|
}
|
||||||
else if (backsector->e->XFloor.ffloors.Size() || frontsector->e->XFloor.ffloors.Size())
|
else if (backsector->e->XFloor.ffloors.Size() || frontsector->e->XFloor.ffloors.Size())
|
||||||
{
|
{
|
||||||
|
|
33
src/info.cpp
33
src/info.cpp
|
@ -118,6 +118,37 @@ void FState::SetAction(const char *name)
|
||||||
ActionFunc = FindVMFunction(RUNTIME_CLASS(AActor), name);
|
ActionFunc = FindVMFunction(RUNTIME_CLASS(AActor), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FState::CheckCallerType(AActor *self, AActor *stateowner)
|
||||||
|
{
|
||||||
|
auto CheckType = [=](AActor *check, PType *requiredType)
|
||||||
|
{
|
||||||
|
// This should really never happen. Any valid action function must have actor pointers here.
|
||||||
|
if (!requiredType->isObjectPointer())
|
||||||
|
{
|
||||||
|
ThrowAbortException(X_OTHER, "Bad function prototype in function call to %s", ActionFunc->PrintableName.GetChars());
|
||||||
|
}
|
||||||
|
auto cls = static_cast<PObjectPointer*>(requiredType)->PointedClass();
|
||||||
|
if (!check->IsKindOf(cls))
|
||||||
|
{
|
||||||
|
ThrowAbortException(X_OTHER, "Invalid class %s in function call to %s. %s expected", check->GetClass()->TypeName.GetChars(), ActionFunc->PrintableName.GetChars(), cls->TypeName.GetChars());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ActionFunc->ImplicitArgs >= 1)
|
||||||
|
{
|
||||||
|
auto argtypes = ActionFunc->Proto->ArgumentTypes;
|
||||||
|
|
||||||
|
CheckType(self, argtypes[0]);
|
||||||
|
|
||||||
|
if (ActionFunc->ImplicitArgs >= 2)
|
||||||
|
{
|
||||||
|
CheckType(stateowner, argtypes[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, FState **stateret)
|
bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, FState **stateret)
|
||||||
{
|
{
|
||||||
if (ActionFunc != nullptr)
|
if (ActionFunc != nullptr)
|
||||||
|
@ -140,6 +171,8 @@ bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info,
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
CheckCallerType(self, stateowner);
|
||||||
|
|
||||||
if (stateret == nullptr)
|
if (stateret == nullptr)
|
||||||
{
|
{
|
||||||
VMCall(ActionFunc, params, ActionFunc->ImplicitArgs, nullptr, 0);
|
VMCall(ActionFunc, params, ActionFunc->ImplicitArgs, nullptr, 0);
|
||||||
|
|
|
@ -175,10 +175,13 @@ public:
|
||||||
void ClearAction() { ActionFunc = NULL; }
|
void ClearAction() { ActionFunc = NULL; }
|
||||||
void SetAction(const char *name);
|
void SetAction(const char *name);
|
||||||
bool CallAction(AActor *self, AActor *stateowner, FStateParamInfo *stateinfo, FState **stateret);
|
bool CallAction(AActor *self, AActor *stateowner, FStateParamInfo *stateinfo, FState **stateret);
|
||||||
|
void CheckCallerType(AActor *self, AActor *stateowner);
|
||||||
|
|
||||||
static PClassActor *StaticFindStateOwner (const FState *state);
|
static PClassActor *StaticFindStateOwner (const FState *state);
|
||||||
static PClassActor *StaticFindStateOwner (const FState *state, PClassActor *info);
|
static PClassActor *StaticFindStateOwner (const FState *state, PClassActor *info);
|
||||||
static FString StaticGetStateName(const FState *state);
|
static FString StaticGetStateName(const FState *state);
|
||||||
static FRandom pr_statetics;
|
static FRandom pr_statetics;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FStateLabels;
|
struct FStateLabels;
|
||||||
|
|
|
@ -896,6 +896,8 @@ xx(DamageFunction)
|
||||||
xx(Length)
|
xx(Length)
|
||||||
xx(Unit)
|
xx(Unit)
|
||||||
xx(Size)
|
xx(Size)
|
||||||
|
xx(Push)
|
||||||
|
xx(Insert)
|
||||||
xx(Copy)
|
xx(Copy)
|
||||||
xx(Move)
|
xx(Move)
|
||||||
xx(Voidptr)
|
xx(Voidptr)
|
||||||
|
|
|
@ -169,6 +169,7 @@ bool AStateProvider::CallStateChain (AActor *actor, FState *state)
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
state->CheckCallerType(actor, this);
|
||||||
VMCall(state->ActionFunc, params, state->ActionFunc->ImplicitArgs, wantret, numret);
|
VMCall(state->ActionFunc, params, state->ActionFunc->ImplicitArgs, wantret, numret);
|
||||||
}
|
}
|
||||||
catch (CVMAbortException &err)
|
catch (CVMAbortException &err)
|
||||||
|
|
|
@ -249,7 +249,6 @@ struct FSectorPortal
|
||||||
//
|
//
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
struct GLSectorStackPortal;
|
|
||||||
struct FSectorPortalGroup
|
struct FSectorPortalGroup
|
||||||
{
|
{
|
||||||
DVector2 mDisplacement;
|
DVector2 mDisplacement;
|
||||||
|
@ -286,4 +285,4 @@ DVector2 P_GetOffsetPosition(double x, double y, double dx, double dy);
|
||||||
void InitPortalGroups();
|
void InitPortalGroups();
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -495,9 +495,9 @@ public:
|
||||||
auto §ion = sections[i];
|
auto §ion = sections[i];
|
||||||
auto &work = triangles[i];
|
auto &work = triangles[i];
|
||||||
|
|
||||||
BoundingRect bounds = { 1e32, 1e32, -1e32, -1e32 };
|
BoundingRect bounds(false);
|
||||||
BoundingRect loopBounds = { 1e32, 1e32, -1e32, -1e32 };
|
BoundingRect loopBounds(false);
|
||||||
BoundingRect outermostBounds = { 1e32, 1e32, -1e32, -1e32 };
|
BoundingRect outermostBounds(false);
|
||||||
unsigned outermoststart = ~0u;
|
unsigned outermoststart = ~0u;
|
||||||
unsigned loopstart = 0;
|
unsigned loopstart = 0;
|
||||||
bool ispolyorg = false;
|
bool ispolyorg = false;
|
||||||
|
@ -519,7 +519,7 @@ public:
|
||||||
outermoststart = loopstart;
|
outermoststart = loopstart;
|
||||||
loopstart = i + 1;
|
loopstart = i + 1;
|
||||||
}
|
}
|
||||||
loopBounds = { 1e32, 1e32, -1e32, -1e32 };
|
loopBounds.setEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
work.boundingLoopStart = outermoststart;
|
work.boundingLoopStart = outermoststart;
|
||||||
|
@ -716,7 +716,7 @@ public:
|
||||||
dest.subsectors.Set(&output.allSubsectors[numsubsectors], group.subsectors.Size());
|
dest.subsectors.Set(&output.allSubsectors[numsubsectors], group.subsectors.Size());
|
||||||
dest.vertexindex = -1;
|
dest.vertexindex = -1;
|
||||||
dest.vertexcount = 0;
|
dest.vertexcount = 0;
|
||||||
dest.bounds = {1e32, 1e32, -1e32, -1e32};
|
dest.bounds.setEmpty();
|
||||||
numsegments += group.segments.Size();
|
numsegments += group.segments.Size();
|
||||||
|
|
||||||
if (output.firstSectionForSectorPtr[dest.sector->Index()] == -1)
|
if (output.firstSectionForSectorPtr[dest.sector->Index()] == -1)
|
||||||
|
|
|
@ -25,12 +25,35 @@ struct BoundingRect
|
||||||
{
|
{
|
||||||
double left, top, right, bottom;
|
double left, top, right, bottom;
|
||||||
|
|
||||||
bool contains(const BoundingRect & other)
|
BoundingRect() = default;
|
||||||
|
BoundingRect(bool)
|
||||||
|
{
|
||||||
|
setEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setEmpty()
|
||||||
|
{
|
||||||
|
left = top = 1e38;
|
||||||
|
bottom = right = -1e38;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool contains(const BoundingRect & other) const
|
||||||
{
|
{
|
||||||
return left <= other.left && top <= other.top && right >= other.right && bottom >= other.bottom;
|
return left <= other.left && top <= other.top && right >= other.right && bottom >= other.bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool intersects(const BoundingRect & other)
|
bool contains(double x, double y) const
|
||||||
|
{
|
||||||
|
return left <= x && top <= y && right >= x && bottom >= y;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
bool contains(const T &vec) const
|
||||||
|
{
|
||||||
|
return left <= vec.X && top <= vec.Y && right >= vec.X && bottom >= vec.Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersects(const BoundingRect & other) const
|
||||||
{
|
{
|
||||||
return !(other.left > right ||
|
return !(other.left > right ||
|
||||||
other.right < left ||
|
other.right < left ||
|
||||||
|
@ -46,7 +69,7 @@ struct BoundingRect
|
||||||
if (other.bottom > bottom) bottom = other.bottom;
|
if (other.bottom > bottom) bottom = other.bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
double distanceTo(const BoundingRect &other)
|
double distanceTo(const BoundingRect &other) const
|
||||||
{
|
{
|
||||||
if (intersects(other)) return 0;
|
if (intersects(other)) return 0;
|
||||||
return std::max(std::min(fabs(left - other.right), fabs(right - other.left)),
|
return std::max(std::min(fabs(left - other.right), fabs(right - other.left)),
|
||||||
|
@ -61,10 +84,11 @@ struct BoundingRect
|
||||||
if (y > bottom) bottom = y;
|
if (y > bottom) bottom = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator == (const BoundingRect &other)
|
bool operator == (const BoundingRect &other) const
|
||||||
{
|
{
|
||||||
return left == other.left && top == other.top && right == other.right && bottom == other.bottom;
|
return left == other.left && top == other.top && right == other.right && bottom == other.bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8240,7 +8240,9 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
auto elementType = static_cast<PDynArray*>(Self->ValueType)->ElementType;
|
auto elementType = static_cast<PDynArray*>(Self->ValueType)->ElementType;
|
||||||
Self->ValueType = static_cast<PDynArray*>(Self->ValueType)->BackingType;
|
Self->ValueType = static_cast<PDynArray*>(Self->ValueType)->BackingType;
|
||||||
|
bool isDynArrayObj = elementType->isObjectPointer();
|
||||||
// this requires some added type checks for the passed types.
|
// this requires some added type checks for the passed types.
|
||||||
|
int idx = 0;
|
||||||
for (auto &a : ArgList)
|
for (auto &a : ArgList)
|
||||||
{
|
{
|
||||||
a = a->Resolve(ctx);
|
a = a->Resolve(ctx);
|
||||||
|
@ -8249,6 +8251,16 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
delete this;
|
delete this;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
if (isDynArrayObj && ((MethodName == NAME_Push && idx == 0) || (MethodName == NAME_Insert && idx == 1)))
|
||||||
|
{
|
||||||
|
// The DynArray_Obj declaration in dynarrays.txt doesn't support generics yet. Check the type here as if it did.
|
||||||
|
if (!static_cast<PObjectPointer*>(elementType)->PointedClass()->IsAncestorOf(static_cast<PObjectPointer*>(a->ValueType)->PointedClass()))
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Type mismatch in function argument");
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (a->IsDynamicArray())
|
if (a->IsDynamicArray())
|
||||||
{
|
{
|
||||||
// Copy and Move must turn their parameter into a pointer to the backing struct type.
|
// Copy and Move must turn their parameter into a pointer to the backing struct type.
|
||||||
|
@ -8288,6 +8300,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
idx++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue