mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2025-02-18 01:21:32 +00:00
Merge branch 'master' into modern
This commit is contained in:
commit
124fe63d00
22 changed files with 464 additions and 166 deletions
|
@ -2364,16 +2364,17 @@ void Net_DoCommand (int type, uint8_t **stream, int player)
|
||||||
spawned->flags &= ~MF_FRIENDLY;
|
spawned->flags &= ~MF_FRIENDLY;
|
||||||
spawned->health = spawned->SpawnHealth();
|
spawned->health = spawned->SpawnHealth();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (type >= DEM_SUMMON2 && type <= DEM_SUMMONFOE2)
|
if (type >= DEM_SUMMON2 && type <= DEM_SUMMONFOE2)
|
||||||
{
|
{
|
||||||
spawned->Angles.Yaw = source->Angles.Yaw - angle;
|
spawned->Angles.Yaw = source->Angles.Yaw - angle;
|
||||||
spawned->tid = tid;
|
spawned->tid = tid;
|
||||||
spawned->special = special;
|
spawned->special = special;
|
||||||
for(i = 0; i < 5; i++) {
|
for(i = 0; i < 5; i++) {
|
||||||
spawned->args[i] = args[i];
|
spawned->args[i] = args[i];
|
||||||
|
}
|
||||||
|
if(tid) spawned->AddToHash();
|
||||||
}
|
}
|
||||||
if(tid) spawned->AddToHash();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,17 +106,17 @@ void G_VerifySkill();
|
||||||
|
|
||||||
CUSTOM_CVAR(Bool, gl_brightfog, false, CVAR_ARCHIVE | CVAR_NOINITCALL)
|
CUSTOM_CVAR(Bool, gl_brightfog, false, CVAR_ARCHIVE | CVAR_NOINITCALL)
|
||||||
{
|
{
|
||||||
if (level.info->brightfog == -1) level.brightfog = self;
|
if (level.info == nullptr || level.info->brightfog == -1) level.brightfog = self;
|
||||||
}
|
}
|
||||||
|
|
||||||
CUSTOM_CVAR(Bool, gl_lightadditivesurfaces, false, CVAR_ARCHIVE | CVAR_NOINITCALL)
|
CUSTOM_CVAR(Bool, gl_lightadditivesurfaces, false, CVAR_ARCHIVE | CVAR_NOINITCALL)
|
||||||
{
|
{
|
||||||
if (level.info->lightadditivesurfaces == -1) level.lightadditivesurfaces = self;
|
if (level.info == nullptr || level.info->lightadditivesurfaces == -1) level.lightadditivesurfaces = self;
|
||||||
}
|
}
|
||||||
|
|
||||||
CUSTOM_CVAR(Bool, gl_notexturefill, false, CVAR_NOINITCALL)
|
CUSTOM_CVAR(Bool, gl_notexturefill, false, CVAR_NOINITCALL)
|
||||||
{
|
{
|
||||||
if (level.info->notexturefill == -1) level.notexturefill = self;
|
if (level.info == nullptr || level.info->notexturefill == -1) level.notexturefill = self;
|
||||||
}
|
}
|
||||||
|
|
||||||
CUSTOM_CVAR(Int, gl_lightmode, 3, CVAR_ARCHIVE | CVAR_NOINITCALL)
|
CUSTOM_CVAR(Int, gl_lightmode, 3, CVAR_ARCHIVE | CVAR_NOINITCALL)
|
||||||
|
|
|
@ -112,7 +112,7 @@ void GLWall::ProcessDecal(HWDrawInfo *di, DBaseDecal *decal, const FVector3 &nor
|
||||||
zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling);
|
zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FMaterial *tex = FMaterial::ValidateTexture(texture, true);
|
FMaterial *tex = FMaterial::ValidateTexture(texture, false);
|
||||||
|
|
||||||
// now clip the decal to the actual polygon
|
// now clip the decal to the actual polygon
|
||||||
|
|
||||||
|
|
|
@ -737,6 +737,15 @@ int P_Thing_CheckProximity(AActor *self, PClass *classname, double distance, int
|
||||||
else if (classname != mo->GetClass())
|
else if (classname != mo->GetClass())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (mo->IsKindOf(RUNTIME_CLASS(AInventory)))
|
||||||
|
{
|
||||||
|
// Skip owned item because its position could remain unchanged since attachment to owner
|
||||||
|
// Most likely it is the last location of this item in the world before pick up
|
||||||
|
AInventory *const inventory = static_cast<AInventory*>(mo);
|
||||||
|
if (inventory != nullptr && inventory->Owner != nullptr)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// [MC]Make sure it's in range and respect the desire for Z or not. The function forces it to use
|
// [MC]Make sure it's in range and respect the desire for Z or not. The function forces it to use
|
||||||
// Z later for ensuring CLOSEST and FARTHEST flags are respected perfectly.
|
// Z later for ensuring CLOSEST and FARTHEST flags are respected perfectly.
|
||||||
// Ripped from sphere checking in A_RadiusGive (along with a number of things).
|
// Ripped from sphere checking in A_RadiusGive (along with a number of things).
|
||||||
|
|
|
@ -148,8 +148,6 @@ void RenderPolyScene::RenderSubsector(PolyRenderThread *thread, subsector_t *sub
|
||||||
sector_t *frontsector = sub->sector;
|
sector_t *frontsector = sub->sector;
|
||||||
frontsector->MoreFlags |= SECMF_DRAWN;
|
frontsector->MoreFlags |= SECMF_DRAWN;
|
||||||
|
|
||||||
bool mainBSP = sub->polys == nullptr;
|
|
||||||
|
|
||||||
if (sub->polys)
|
if (sub->polys)
|
||||||
{
|
{
|
||||||
if (sub->BSP == nullptr || sub->BSP->bDirty)
|
if (sub->BSP == nullptr || sub->BSP->bDirty)
|
||||||
|
@ -172,35 +170,27 @@ void RenderPolyScene::RenderSubsector(PolyRenderThread *thread, subsector_t *sub
|
||||||
{
|
{
|
||||||
RenderPolyNode(thread, &sub->BSP->Nodes.Last(), subsectorDepth, frontsector);
|
RenderPolyNode(thread, &sub->BSP->Nodes.Last(), subsectorDepth, frontsector);
|
||||||
}
|
}
|
||||||
|
|
||||||
Render3DFloorPlane::RenderPlanes(thread, sub, CurrentViewpoint->StencilValue, subsectorDepth, thread->TranslucentObjects);
|
|
||||||
RenderPolyPlane::RenderPlanes(thread, sub, CurrentViewpoint->StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, thread->SectorPortals, CurrentViewpoint->SectorPortalsStart);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
PolyTransferHeights fakeflat(sub);
|
||||||
|
|
||||||
|
Render3DFloorPlane::RenderPlanes(thread, sub, CurrentViewpoint->StencilValue, subsectorDepth, thread->TranslucentObjects);
|
||||||
|
RenderPolyPlane::RenderPlanes(thread, fakeflat, CurrentViewpoint->StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, thread->SectorPortals, CurrentViewpoint->SectorPortalsStart);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < sub->numlines; i++)
|
||||||
{
|
{
|
||||||
PolyTransferHeights fakeflat(sub);
|
if (Cull.IsLineSegVisible(subsectorDepth, i))
|
||||||
|
|
||||||
Render3DFloorPlane::RenderPlanes(thread, sub, CurrentViewpoint->StencilValue, subsectorDepth, thread->TranslucentObjects);
|
|
||||||
RenderPolyPlane::RenderPlanes(thread, fakeflat, CurrentViewpoint->StencilValue, Cull.MaxCeilingHeight, Cull.MinFloorHeight, thread->SectorPortals, CurrentViewpoint->SectorPortalsStart);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < sub->numlines; i++)
|
|
||||||
{
|
{
|
||||||
if (Cull.IsLineSegVisible(subsectorDepth, i))
|
seg_t *line = &sub->firstline[i];
|
||||||
{
|
RenderLine(thread, sub, line, fakeflat.FrontSector, subsectorDepth);
|
||||||
seg_t *line = &sub->firstline[i];
|
|
||||||
RenderLine(thread, sub, line, fakeflat.FrontSector, subsectorDepth);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mainBSP)
|
int subsectorIndex = sub->Index();
|
||||||
|
for (int i = ParticlesInSubsec[subsectorIndex]; i != NO_PARTICLE; i = Particles[i].snext)
|
||||||
{
|
{
|
||||||
int subsectorIndex = sub->Index();
|
particle_t *particle = Particles + i;
|
||||||
for (int i = ParticlesInSubsec[subsectorIndex]; i != NO_PARTICLE; i = Particles[i].snext)
|
thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject<PolyTranslucentParticle>(particle, sub, subsectorDepth, CurrentViewpoint->StencilValue));
|
||||||
{
|
|
||||||
particle_t *particle = Particles + i;
|
|
||||||
thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject<PolyTranslucentParticle>(particle, sub, subsectorDepth, CurrentViewpoint->StencilValue));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -372,7 +372,7 @@ FTexture *RenderPolySprite::GetSpriteTexture(AActor *thing, /*out*/ bool &flipX)
|
||||||
void RenderPolySprite::SetDynlight(AActor *thing, PolyDrawArgs &args)
|
void RenderPolySprite::SetDynlight(AActor *thing, PolyDrawArgs &args)
|
||||||
{
|
{
|
||||||
bool fullbrightSprite = ((thing->renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT));
|
bool fullbrightSprite = ((thing->renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT));
|
||||||
if (fullbrightSprite)
|
if (fullbrightSprite || !r_dynlights)
|
||||||
{
|
{
|
||||||
args.SetDynLightColor(0);
|
args.SetDynLightColor(0);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -35,9 +35,6 @@
|
||||||
|
|
||||||
#import <Carbon/Carbon.h>
|
#import <Carbon/Carbon.h>
|
||||||
|
|
||||||
// Avoid collision between DObject class and Objective-C
|
|
||||||
#define Class ObjectClass
|
|
||||||
|
|
||||||
#include "c_console.h"
|
#include "c_console.h"
|
||||||
#include "c_cvars.h"
|
#include "c_cvars.h"
|
||||||
#include "c_dispatch.h"
|
#include "c_dispatch.h"
|
||||||
|
@ -49,8 +46,6 @@
|
||||||
#include "v_video.h"
|
#include "v_video.h"
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
|
|
||||||
#undef Class
|
|
||||||
|
|
||||||
|
|
||||||
EXTERN_CVAR(Int, m_use_mouse)
|
EXTERN_CVAR(Int, m_use_mouse)
|
||||||
|
|
||||||
|
|
|
@ -36,9 +36,6 @@
|
||||||
|
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
|
|
||||||
// Avoid collision between DObject class and Objective-C
|
|
||||||
#define Class ObjectClass
|
|
||||||
|
|
||||||
#include "c_console.h"
|
#include "c_console.h"
|
||||||
#include "c_cvars.h"
|
#include "c_cvars.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
|
@ -48,8 +45,6 @@
|
||||||
#include "st_console.h"
|
#include "st_console.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
#undef Class
|
|
||||||
|
|
||||||
|
|
||||||
#define ZD_UNUSED(VARIABLE) ((void)(VARIABLE))
|
#define ZD_UNUSED(VARIABLE) ((void)(VARIABLE))
|
||||||
|
|
||||||
|
|
|
@ -35,9 +35,6 @@
|
||||||
|
|
||||||
#include "i_common.h"
|
#include "i_common.h"
|
||||||
|
|
||||||
// Avoid collision between DObject class and Objective-C
|
|
||||||
#define Class ObjectClass
|
|
||||||
|
|
||||||
#include "bitmap.h"
|
#include "bitmap.h"
|
||||||
#include "c_dispatch.h"
|
#include "c_dispatch.h"
|
||||||
#include "doomstat.h"
|
#include "doomstat.h"
|
||||||
|
@ -54,8 +51,6 @@
|
||||||
#include "gl/system/gl_framebuffer.h"
|
#include "gl/system/gl_framebuffer.h"
|
||||||
#include "gl/textures/gl_samplers.h"
|
#include "gl/textures/gl_samplers.h"
|
||||||
|
|
||||||
#undef Class
|
|
||||||
|
|
||||||
|
|
||||||
@implementation NSWindow(ExitAppOnClose)
|
@implementation NSWindow(ExitAppOnClose)
|
||||||
|
|
||||||
|
|
|
@ -33,9 +33,6 @@
|
||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Avoid collision between DObject class and Objective-C
|
|
||||||
#define Class ObjectClass
|
|
||||||
|
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
#include "d_main.h"
|
#include "d_main.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
@ -44,8 +41,6 @@
|
||||||
#include "m_misc.h"
|
#include "m_misc.h"
|
||||||
#include "gameconfigfile.h"
|
#include "gameconfigfile.h"
|
||||||
|
|
||||||
#undef Class
|
|
||||||
|
|
||||||
#include <Cocoa/Cocoa.h>
|
#include <Cocoa/Cocoa.h>
|
||||||
#include <wordexp.h>
|
#include <wordexp.h>
|
||||||
|
|
||||||
|
|
|
@ -28,11 +28,11 @@ float unpackuvert( uint32_t n, int c )
|
||||||
{
|
{
|
||||||
switch( c )
|
switch( c )
|
||||||
{
|
{
|
||||||
case 2:
|
case 0:
|
||||||
return ((int16_t)((n&0x7ff)<<5))/128.f;
|
return ((int16_t)((n&0x7ff)<<5))/128.f;
|
||||||
case 1:
|
case 1:
|
||||||
return ((int16_t)(((n>>11)&0x7ff)<<5))/128.f;
|
return ((int16_t)(((n>>11)&0x7ff)<<5))/128.f;
|
||||||
case 0:
|
case 2:
|
||||||
return ((int16_t)(((n>>22)&0x3ff)<<6))/128.f;
|
return ((int16_t)(((n>>22)&0x3ff)<<6))/128.f;
|
||||||
default:
|
default:
|
||||||
return 0.f;
|
return 0.f;
|
||||||
|
@ -41,66 +41,74 @@ float unpackuvert( uint32_t n, int c )
|
||||||
|
|
||||||
bool FUE1Model::Load( const char *filename, int lumpnum, const char *buffer, int length )
|
bool FUE1Model::Load( const char *filename, int lumpnum, const char *buffer, int length )
|
||||||
{
|
{
|
||||||
mLumpNum = lumpnum;
|
|
||||||
int lumpnum2;
|
int lumpnum2;
|
||||||
FMemLump lump2;
|
|
||||||
const char *buffer2;
|
|
||||||
FString realfilename = Wads.GetLumpFullName(lumpnum);
|
FString realfilename = Wads.GetLumpFullName(lumpnum);
|
||||||
if ( (size_t)realfilename.IndexOf("_d.3d") == realfilename.Len()-5 )
|
if ( (size_t)realfilename.IndexOf("_d.3d") == realfilename.Len()-5 )
|
||||||
{
|
{
|
||||||
realfilename.Substitute("_d.3d","_a.3d");
|
realfilename.Substitute("_d.3d","_a.3d");
|
||||||
lumpnum2 = Wads.CheckNumForFullName(realfilename);
|
lumpnum2 = Wads.CheckNumForFullName(realfilename);
|
||||||
lump2 = Wads.ReadLump(lumpnum2);
|
mDataLump = lumpnum;
|
||||||
buffer2 = (char*)lump2.GetMem();
|
mAnivLump = lumpnum2;
|
||||||
// map structures
|
|
||||||
dhead = (d3dhead*)(buffer);
|
|
||||||
dpolys = (d3dpoly*)(buffer+sizeof(d3dhead));
|
|
||||||
ahead = (a3dhead*)(buffer2);
|
|
||||||
averts = (uint32_t*)(buffer2+sizeof(a3dhead));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
realfilename.Substitute("_a.3d","_d.3d");
|
realfilename.Substitute("_a.3d","_d.3d");
|
||||||
lumpnum2 = Wads.CheckNumForFullName(realfilename);
|
lumpnum2 = Wads.CheckNumForFullName(realfilename);
|
||||||
lump2 = Wads.ReadLump(lumpnum2);
|
mAnivLump = lumpnum;
|
||||||
buffer2 = (char*)lump2.GetMem();
|
mDataLump = lumpnum2;
|
||||||
// map structures
|
|
||||||
dhead = (d3dhead*)(buffer2);
|
|
||||||
dpolys = (d3dpoly*)(buffer2+sizeof(d3dhead));
|
|
||||||
ahead = (a3dhead*)(buffer);
|
|
||||||
averts = (uint32_t*)(buffer+sizeof(a3dhead));
|
|
||||||
}
|
}
|
||||||
// set counters
|
|
||||||
numVerts = dhead->numverts;
|
|
||||||
numFrames = ahead->numframes;
|
|
||||||
numPolys = dhead->numpolys;
|
|
||||||
numGroups = 0;
|
|
||||||
groupIndices.Reset();
|
|
||||||
uint8_t used[256] = {0};
|
|
||||||
for ( int i=0; i<numPolys; i++ )
|
|
||||||
used[dpolys[i].texnum] = 1;
|
|
||||||
for ( int i=0; i<256; i++ )
|
|
||||||
{
|
|
||||||
if ( !used[i] ) continue;
|
|
||||||
groupIndices.Push(i);
|
|
||||||
numGroups++;
|
|
||||||
}
|
|
||||||
LoadGeometry();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FUE1Model::LoadGeometry()
|
void FUE1Model::LoadGeometry()
|
||||||
{
|
{
|
||||||
|
FMemLump lump, lump2;
|
||||||
|
const char *buffer, *buffer2;
|
||||||
|
lump = Wads.ReadLump(mDataLump);
|
||||||
|
buffer = (char*)lump.GetMem();
|
||||||
|
lump2 = Wads.ReadLump(mAnivLump);
|
||||||
|
buffer2 = (char*)lump2.GetMem();
|
||||||
|
// map structures
|
||||||
|
dhead = (d3dhead*)(buffer);
|
||||||
|
dpolys = (d3dpoly*)(buffer+sizeof(d3dhead));
|
||||||
|
ahead = (a3dhead*)(buffer2);
|
||||||
|
// detect deus ex format
|
||||||
|
if ( (ahead->framesize/dhead->numverts) == 8 )
|
||||||
|
{
|
||||||
|
averts = NULL;
|
||||||
|
dxverts = (dxvert*)(buffer2+sizeof(a3dhead));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
averts = (uint32_t*)(buffer2+sizeof(a3dhead));
|
||||||
|
dxverts = NULL;
|
||||||
|
}
|
||||||
|
weaponPoly = -1;
|
||||||
|
// set counters
|
||||||
|
numVerts = dhead->numverts;
|
||||||
|
numFrames = ahead->numframes;
|
||||||
|
numPolys = dhead->numpolys;
|
||||||
|
numGroups = 0;
|
||||||
// populate vertex arrays
|
// populate vertex arrays
|
||||||
for ( int i=0; i<numFrames; i++ )
|
for ( int i=0; i<numFrames; i++ )
|
||||||
{
|
{
|
||||||
for ( int j=0; j<numVerts; j++ )
|
for ( int j=0; j<numVerts; j++ )
|
||||||
{
|
{
|
||||||
UE1Vertex Vert;
|
UE1Vertex Vert;
|
||||||
// unpack position
|
if ( dxverts != NULL )
|
||||||
Vert.Pos = FVector3(unpackuvert(averts[j+i*numVerts],2),
|
{
|
||||||
unpackuvert(averts[j+i*numVerts],0),
|
// convert padded XYZ16
|
||||||
-unpackuvert(averts[j+i*numVerts],1));
|
Vert.Pos = FVector3(dxverts[j+i*numVerts].x,
|
||||||
|
dxverts[j+i*numVerts].z,
|
||||||
|
-dxverts[j+i*numVerts].y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// convert packed XY11Z10
|
||||||
|
Vert.Pos = FVector3(unpackuvert(averts[j+i*numVerts],0),
|
||||||
|
unpackuvert(averts[j+i*numVerts],2),
|
||||||
|
-unpackuvert(averts[j+i*numVerts],1));
|
||||||
|
}
|
||||||
// push vertex (without normals, will be calculated later)
|
// push vertex (without normals, will be calculated later)
|
||||||
verts.Push(Vert);
|
verts.Push(Vert);
|
||||||
}
|
}
|
||||||
|
@ -115,7 +123,11 @@ void FUE1Model::LoadGeometry()
|
||||||
// unpack coords
|
// unpack coords
|
||||||
for ( int j=0; j<3; j++ )
|
for ( int j=0; j<3; j++ )
|
||||||
Poly.C[j] = FVector2(dpolys[i].uv[j][0]/255.f,dpolys[i].uv[j][1]/255.f);
|
Poly.C[j] = FVector2(dpolys[i].uv[j][0]/255.f,dpolys[i].uv[j][1]/255.f);
|
||||||
Poly.texNum = dpolys[i].texnum;
|
// compute facet normal
|
||||||
|
FVector3 dir[2];
|
||||||
|
dir[0] = verts[Poly.V[1]].Pos-verts[Poly.V[0]].Pos;
|
||||||
|
dir[1] = verts[Poly.V[2]].Pos-verts[Poly.V[0]].Pos;
|
||||||
|
Poly.Normal = dir[0]^dir[1];
|
||||||
// push
|
// push
|
||||||
polys.Push(Poly);
|
polys.Push(Poly);
|
||||||
}
|
}
|
||||||
|
@ -130,37 +142,61 @@ void FUE1Model::LoadGeometry()
|
||||||
for ( int k=0; k<numPolys; k++ )
|
for ( int k=0; k<numPolys; k++ )
|
||||||
{
|
{
|
||||||
if ( (polys[k].V[0] != j) && (polys[k].V[1] != j) && (polys[k].V[2] != j) ) continue;
|
if ( (polys[k].V[0] != j) && (polys[k].V[1] != j) && (polys[k].V[2] != j) ) continue;
|
||||||
FVector3 vert[3], dir[2], norm;
|
nsum += polys[k].Normal;
|
||||||
// compute facet normal
|
|
||||||
for ( int l=0; l<3; l++ )
|
|
||||||
vert[l] = verts[polys[k].V[l]+numVerts*i].Pos;
|
|
||||||
dir[0] = vert[1]-vert[0];
|
|
||||||
dir[1] = vert[2]-vert[0];
|
|
||||||
norm = dir[0]^dir[1];
|
|
||||||
nsum += norm.Unit();
|
|
||||||
}
|
}
|
||||||
verts[j+numVerts*i].Normal = nsum.Unit();
|
verts[j+numVerts*i].Normal = nsum.Unit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// populate skin groups
|
// populate poly groups (subdivided by texture number and type)
|
||||||
for ( int i=0; i<numGroups; i++ )
|
// this method minimizes searches in the group list as much as possible
|
||||||
|
// while still doing a single pass through the poly list
|
||||||
|
int curgroup = -1;
|
||||||
|
UE1Group Group;
|
||||||
|
for ( int i=0; i<numPolys; i++ )
|
||||||
{
|
{
|
||||||
UE1Group Group;
|
// while we're at it, look for the weapon triangle
|
||||||
Group.numPolys = 0;
|
if ( dpolys[i].type&PT_WeaponTriangle ) weaponPoly = i;
|
||||||
for ( int j=0; j<numPolys; j++ )
|
if ( curgroup == -1 )
|
||||||
{
|
{
|
||||||
if ( polys[j].texNum != groupIndices[i] )
|
// no group, create it
|
||||||
continue;
|
Group.P.Reset();
|
||||||
Group.P.Push(j);
|
Group.numPolys = 0;
|
||||||
Group.numPolys++;
|
Group.texNum = dpolys[i].texnum;
|
||||||
|
Group.type = dpolys[i].type;
|
||||||
|
groups.Push(Group);
|
||||||
|
curgroup = numGroups++;
|
||||||
}
|
}
|
||||||
groups.Push(Group);
|
else if ( (dpolys[i].texnum != groups[curgroup].texNum) || (dpolys[i].type != groups[curgroup].type) )
|
||||||
|
{
|
||||||
|
// different attributes than last time
|
||||||
|
// search for existing group with new attributes, create one if not found
|
||||||
|
curgroup = -1;
|
||||||
|
for ( int j=0; j<numGroups; j++ )
|
||||||
|
{
|
||||||
|
if ( (groups[j].texNum != dpolys[i].texnum) || (groups[j].type != dpolys[i].type) ) continue;
|
||||||
|
curgroup = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// counter the increment that will happen after continuing this loop
|
||||||
|
// otherwise it'll be skipped over
|
||||||
|
i--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
groups[curgroup].P.Push(i);
|
||||||
|
groups[curgroup].numPolys++;
|
||||||
}
|
}
|
||||||
// ... and it's finally done
|
// ... and it's finally done
|
||||||
|
mDataLoaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FUE1Model::UnloadGeometry()
|
void FUE1Model::UnloadGeometry()
|
||||||
{
|
{
|
||||||
|
mDataLoaded = false;
|
||||||
|
weaponPoly = -1;
|
||||||
|
numVerts = 0;
|
||||||
|
numFrames = 0;
|
||||||
|
numPolys = 0;
|
||||||
|
numGroups = 0;
|
||||||
verts.Reset();
|
verts.Reset();
|
||||||
polys.Reset();
|
polys.Reset();
|
||||||
for ( int i=0; i<numGroups; i++ )
|
for ( int i=0; i<numGroups; i++ )
|
||||||
|
@ -184,17 +220,25 @@ void FUE1Model::RenderFrame( FModelRenderer *renderer, FTexture *skin, int frame
|
||||||
for ( int i=0; i<numGroups; i++ )
|
for ( int i=0; i<numGroups; i++ )
|
||||||
{
|
{
|
||||||
vsize = groups[i].numPolys*3;
|
vsize = groups[i].numPolys*3;
|
||||||
|
if ( groups[i].type&PT_WeaponTriangle )
|
||||||
|
{
|
||||||
|
// weapon triangle should never be drawn, it only exists to calculate attachment position and orientation
|
||||||
|
vofs += vsize;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
FTexture *sskin = skin;
|
FTexture *sskin = skin;
|
||||||
if ( !sskin )
|
if ( !sskin )
|
||||||
{
|
{
|
||||||
if ( curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].isValid() )
|
if ( curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][groups[i].texNum].isValid() )
|
||||||
sskin = TexMan(curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i]);
|
sskin = TexMan(curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][groups[i].texNum]);
|
||||||
if ( !sskin )
|
if ( !sskin )
|
||||||
{
|
{
|
||||||
vofs += vsize;
|
vofs += vsize;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// TODO: Handle per-group render styles and other flags once functions for it are implemented
|
||||||
|
// Future note: poly renderstyles should always be enforced unless the actor itself has a style other than Normal
|
||||||
renderer->SetMaterial(sskin,false,translation);
|
renderer->SetMaterial(sskin,false,translation);
|
||||||
GetVertexBuffer(renderer)->SetupFrame(renderer,vofs+frame*fsize,vofs+frame2*fsize,vsize);
|
GetVertexBuffer(renderer)->SetupFrame(renderer,vofs+frame*fsize,vofs+frame2*fsize,vsize);
|
||||||
renderer->DrawArrays(0,vsize);
|
renderer->DrawArrays(0,vsize);
|
||||||
|
@ -207,6 +251,8 @@ void FUE1Model::BuildVertexBuffer( FModelRenderer *renderer )
|
||||||
{
|
{
|
||||||
if (GetVertexBuffer(renderer))
|
if (GetVertexBuffer(renderer))
|
||||||
return;
|
return;
|
||||||
|
if ( !mDataLoaded )
|
||||||
|
LoadGeometry();
|
||||||
int vsize = 0;
|
int vsize = 0;
|
||||||
for ( int i=0; i<numGroups; i++ )
|
for ( int i=0; i<numGroups; i++ )
|
||||||
vsize += groups[i].numPolys*3;
|
vsize += groups[i].numPolys*3;
|
||||||
|
@ -227,7 +273,13 @@ void FUE1Model::BuildVertexBuffer( FModelRenderer *renderer )
|
||||||
FVector2 C = polys[groups[j].P[k]].C[l];
|
FVector2 C = polys[groups[j].P[k]].C[l];
|
||||||
FModelVertex *vert = &vptr[vidx++];
|
FModelVertex *vert = &vptr[vidx++];
|
||||||
vert->Set(V.Pos.X,V.Pos.Y,V.Pos.Z,C.X,C.Y);
|
vert->Set(V.Pos.X,V.Pos.Y,V.Pos.Z,C.X,C.Y);
|
||||||
vert->SetNormal(V.Normal.X,V.Normal.Y,V.Normal.Z);
|
if ( groups[j].type&PT_Curvy ) // use facet normal
|
||||||
|
{
|
||||||
|
vert->SetNormal(polys[groups[j].P[k]].Normal.X,
|
||||||
|
polys[groups[j].P[k]].Normal.Y,
|
||||||
|
polys[groups[j].P[k]].Normal.Z);
|
||||||
|
}
|
||||||
|
else vert->SetNormal(V.Normal.X,V.Normal.Y,V.Normal.Z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,8 +290,8 @@ void FUE1Model::BuildVertexBuffer( FModelRenderer *renderer )
|
||||||
void FUE1Model::AddSkins( uint8_t *hitlist )
|
void FUE1Model::AddSkins( uint8_t *hitlist )
|
||||||
{
|
{
|
||||||
for ( int i=0; i<numGroups; i++ )
|
for ( int i=0; i<numGroups; i++ )
|
||||||
if ( curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].isValid() )
|
if ( curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][groups[i].texNum].isValid() )
|
||||||
hitlist[curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][i].GetIndex()] |= FTextureManager::HIT_Flat;
|
hitlist[curSpriteMDLFrame->surfaceskinIDs[curMDLIndex][groups[i].texNum].GetIndex()] |= FTextureManager::HIT_Flat;
|
||||||
}
|
}
|
||||||
|
|
||||||
FUE1Model::~FUE1Model()
|
FUE1Model::~FUE1Model()
|
||||||
|
|
|
@ -5,6 +5,23 @@
|
||||||
class FUE1Model : public FModel
|
class FUE1Model : public FModel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum EPolyType
|
||||||
|
{
|
||||||
|
PT_Normal = 0, // normal renderstyle
|
||||||
|
PT_TwoSided = 1, // like normal, but don't cull backfaces
|
||||||
|
PT_Translucent = 2, // additive blending
|
||||||
|
PT_Masked = 3, // draw with alpha testing
|
||||||
|
PT_Modulated = 4, // overlay-like blending (rgb values below 128 darken, 128 is unchanged, and above 128 lighten)
|
||||||
|
// types mask
|
||||||
|
PT_Type = 7,
|
||||||
|
// flags
|
||||||
|
PT_WeaponTriangle = 0x08, // this poly is used for positioning a weapon attachment and should not be drawn
|
||||||
|
PT_Unlit = 0x10, // this poly is fullbright
|
||||||
|
PT_Curvy = 0x20, // this poly uses the facet normal
|
||||||
|
PT_EnvironmentMap = 0x40, // vertex UVs are remapped to their view-space X and Z normals, fake cubemap look
|
||||||
|
PT_NoSmooth = 0x80 // this poly forcibly uses nearest filtering
|
||||||
|
};
|
||||||
|
|
||||||
bool Load(const char * fn, int lumpnum, const char * buffer, int length) override;
|
bool Load(const char * fn, int lumpnum, const char * buffer, int length) override;
|
||||||
int FindFrame(const char * name) override;
|
int FindFrame(const char * name) override;
|
||||||
void RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame, int frame2, double inter, int translation=0) override;
|
void RenderFrame(FModelRenderer *renderer, FTexture * skin, int frame, int frame2, double inter, int translation=0) override;
|
||||||
|
@ -14,7 +31,9 @@ public:
|
||||||
void UnloadGeometry();
|
void UnloadGeometry();
|
||||||
FUE1Model()
|
FUE1Model()
|
||||||
{
|
{
|
||||||
mLumpNum = -1;
|
mDataLump = -1;
|
||||||
|
mAnivLump = -1;
|
||||||
|
mDataLoaded = false;
|
||||||
dhead = NULL;
|
dhead = NULL;
|
||||||
dpolys = NULL;
|
dpolys = NULL;
|
||||||
ahead = NULL;
|
ahead = NULL;
|
||||||
|
@ -27,7 +46,8 @@ public:
|
||||||
~FUE1Model();
|
~FUE1Model();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int mLumpNum;
|
int mDataLump, mAnivLump;
|
||||||
|
bool mDataLoaded;
|
||||||
|
|
||||||
// raw data structures
|
// raw data structures
|
||||||
struct d3dhead
|
struct d3dhead
|
||||||
|
@ -54,6 +74,11 @@ private:
|
||||||
d3dpoly * dpolys;
|
d3dpoly * dpolys;
|
||||||
a3dhead * ahead;
|
a3dhead * ahead;
|
||||||
uint32_t * averts;
|
uint32_t * averts;
|
||||||
|
struct dxvert
|
||||||
|
{
|
||||||
|
int16_t x, y, z, pad;
|
||||||
|
};
|
||||||
|
dxvert * dxverts;
|
||||||
|
|
||||||
// converted data structures
|
// converted data structures
|
||||||
struct UE1Vertex
|
struct UE1Vertex
|
||||||
|
@ -64,21 +89,21 @@ private:
|
||||||
{
|
{
|
||||||
int V[3];
|
int V[3];
|
||||||
FVector2 C[3];
|
FVector2 C[3];
|
||||||
int texNum;
|
FVector3 Normal;
|
||||||
};
|
};
|
||||||
struct UE1Group
|
struct UE1Group
|
||||||
{
|
{
|
||||||
TArray<int> P;
|
TArray<int> P;
|
||||||
int numPolys;
|
int numPolys, texNum, type;
|
||||||
};
|
};
|
||||||
|
|
||||||
int numVerts;
|
int numVerts;
|
||||||
int numFrames;
|
int numFrames;
|
||||||
int numPolys;
|
int numPolys;
|
||||||
int numGroups;
|
int numGroups;
|
||||||
|
int weaponPoly; // for future model attachment support, unused for now
|
||||||
|
|
||||||
TArray<UE1Vertex> verts;
|
TArray<UE1Vertex> verts;
|
||||||
TArray<UE1Poly> polys;
|
TArray<UE1Poly> polys;
|
||||||
TArray<UE1Group> groups;
|
TArray<UE1Group> groups;
|
||||||
TArray<int> groupIndices;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -2524,6 +2524,11 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
|
||||||
}
|
}
|
||||||
else if (p->Default != nullptr)
|
else if (p->Default != nullptr)
|
||||||
{
|
{
|
||||||
|
if (flags & VARF_Out)
|
||||||
|
{
|
||||||
|
Error(p, "Out parameters cannot have default values");
|
||||||
|
}
|
||||||
|
|
||||||
flags |= VARF_Optional;
|
flags |= VARF_Optional;
|
||||||
hasoptionals = true;
|
hasoptionals = true;
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@ static bool CheckIfRaw(FileReader & data)
|
||||||
}
|
}
|
||||||
else if (ofs >= 64000-1) // Need one byte for an empty column
|
else if (ofs >= 64000-1) // Need one byte for an empty column
|
||||||
{
|
{
|
||||||
free (foo);
|
M_Free (foo);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -108,14 +108,14 @@ static bool CheckIfRaw(FileReader & data)
|
||||||
{
|
{
|
||||||
if (foo2[ofs] == 255)
|
if (foo2[ofs] == 255)
|
||||||
{
|
{
|
||||||
free (foo);
|
M_Free (foo);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
ofs += foo2[ofs+1] + 4;
|
ofs += foo2[ofs+1] + 4;
|
||||||
}
|
}
|
||||||
if (ofs >= 64000)
|
if (ofs >= 64000)
|
||||||
{
|
{
|
||||||
free (foo);
|
M_Free (foo);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,9 +31,51 @@
|
||||||
#include "r_utility.h"
|
#include "r_utility.h"
|
||||||
#include "v_video.h"
|
#include "v_video.h"
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
|
#include "vm.h"
|
||||||
|
|
||||||
EXTERN_CVAR(Float, transsouls)
|
EXTERN_CVAR(Float, transsouls)
|
||||||
|
|
||||||
|
IMPLEMENT_CLASS(DShape2D, false, false)
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(DShape2D, Clear)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(DShape2D);
|
||||||
|
PARAM_INT(which);
|
||||||
|
if ( which&C_Verts ) self->mVertices.Clear();
|
||||||
|
if ( which&C_Coords ) self->mCoords.Clear();
|
||||||
|
if ( which&C_Indices ) self->mIndices.Clear();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(DShape2D, PushVertex)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(DShape2D);
|
||||||
|
PARAM_FLOAT(x);
|
||||||
|
PARAM_FLOAT(y);
|
||||||
|
self->mVertices.Push(DVector2(x,y));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(DShape2D, PushCoord)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(DShape2D);
|
||||||
|
PARAM_FLOAT(u);
|
||||||
|
PARAM_FLOAT(v);
|
||||||
|
self->mCoords.Push(DVector2(u,v));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(DShape2D, PushTriangle)
|
||||||
|
{
|
||||||
|
PARAM_SELF_PROLOGUE(DShape2D);
|
||||||
|
PARAM_INT(a);
|
||||||
|
PARAM_INT(b);
|
||||||
|
PARAM_INT(c);
|
||||||
|
self->mIndices.Push(a);
|
||||||
|
self->mIndices.Push(b);
|
||||||
|
self->mIndices.Push(c);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -318,6 +360,61 @@ void F2DDrawer::AddTexture(FTexture *img, DrawParms &parms)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
void F2DDrawer::AddShape( FTexture *img, DShape2D *shape, DrawParms &parms )
|
||||||
|
{
|
||||||
|
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.mTranslation = 0;
|
||||||
|
SetStyle(img, parms, vertexcolor, dg);
|
||||||
|
|
||||||
|
if (!img->bHasCanvas && parms.remap != nullptr && !parms.remap->Inactive)
|
||||||
|
dg.mTranslation = parms.remap;
|
||||||
|
|
||||||
|
double minx = 16383, miny = 16383, maxx = -16384, maxy = -16384;
|
||||||
|
for ( int i=0; i<dg.mVertCount; i++ )
|
||||||
|
{
|
||||||
|
if ( shape->mVertices[i].X < minx ) minx = shape->mVertices[i].X;
|
||||||
|
if ( shape->mVertices[i].Y < miny ) miny = shape->mVertices[i].Y;
|
||||||
|
if ( shape->mVertices[i].X > maxx ) maxx = shape->mVertices[i].X;
|
||||||
|
if ( shape->mVertices[i].Y > maxy ) maxy = shape->mVertices[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; i<dg.mVertCount; i++ )
|
||||||
|
ptr[i].Set(shape->mVertices[i].X, shape->mVertices[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; i<int(shape->mIndices.Size()); i+=3 )
|
||||||
|
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,
|
void F2DDrawer::AddPoly(FTexture *texture, FVector2 *points, int npoints,
|
||||||
double originx, double originy, double scalex, double scaley,
|
double originx, double originy, double scalex, double scaley,
|
||||||
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel)
|
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel)
|
||||||
|
|
|
@ -9,6 +9,25 @@
|
||||||
|
|
||||||
struct DrawParms;
|
struct DrawParms;
|
||||||
|
|
||||||
|
// 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:
|
||||||
|
TArray<int> mIndices;
|
||||||
|
TArray<DVector2> mVertices;
|
||||||
|
TArray<DVector2> mCoords;
|
||||||
|
};
|
||||||
|
|
||||||
class F2DDrawer
|
class F2DDrawer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -117,6 +136,7 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void AddTexture(FTexture *img, DrawParms &parms);
|
void AddTexture(FTexture *img, DrawParms &parms);
|
||||||
|
void AddShape(FTexture *img, DShape2D *shape, DrawParms &parms);
|
||||||
void AddPoly(FTexture *texture, FVector2 *points, int npoints,
|
void AddPoly(FTexture *texture, FVector2 *points, int npoints,
|
||||||
double originx, double originy, double scalex, double scaley,
|
double originx, double originy, double scalex, double scaley,
|
||||||
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel);
|
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel);
|
||||||
|
|
|
@ -190,6 +190,50 @@ void DFrameBuffer::DrawTextureParms(FTexture *img, DrawParms &parms)
|
||||||
m2DDrawer.AddTexture(img, parms);
|
m2DDrawer.AddTexture(img, parms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// ZScript arbitrary textured shape drawing functions
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void DFrameBuffer::DrawShape(FTexture *img, DShape2D *shape, int tags_first, ...)
|
||||||
|
{
|
||||||
|
Va_List tags;
|
||||||
|
va_start(tags.list, tags_first);
|
||||||
|
DrawParms parms;
|
||||||
|
|
||||||
|
bool res = ParseDrawTextureTags(img, 0, 0, tags_first, tags, &parms, false);
|
||||||
|
va_end(tags.list);
|
||||||
|
if (!res) return;
|
||||||
|
m2DDrawer.AddShape(img, shape, parms);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DFrameBuffer::DrawShape(FTexture *img, DShape2D *shape, VMVa_List &args)
|
||||||
|
{
|
||||||
|
DrawParms parms;
|
||||||
|
uint32_t tag = ListGetInt(args);
|
||||||
|
|
||||||
|
bool res = ParseDrawTextureTags(img, 0, 0, tag, args, &parms, false);
|
||||||
|
if (!res) return;
|
||||||
|
m2DDrawer.AddShape(img, shape, parms);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(_Screen, DrawShape)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
PARAM_INT(texid);
|
||||||
|
PARAM_BOOL(animate);
|
||||||
|
PARAM_POINTER(shape, DShape2D);
|
||||||
|
|
||||||
|
if (!screen->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function");
|
||||||
|
|
||||||
|
FTexture *tex = animate ? TexMan(FSetTextureID(texid)) : TexMan[FSetTextureID(texid)];
|
||||||
|
VMVa_List args = { param + 3, 0, numparam - 3 };
|
||||||
|
|
||||||
|
screen->DrawShape(tex, shape, args);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// Clipping rect
|
// Clipping rect
|
||||||
|
@ -1451,7 +1495,11 @@ void DFrameBuffer::DrawBlend(sector_t * viewsector)
|
||||||
V_AddBlend(player->BlendR, player->BlendG, player->BlendB, player->BlendA, blend);
|
V_AddBlend(player->BlendR, player->BlendG, player->BlendB, player->BlendA, blend);
|
||||||
}
|
}
|
||||||
|
|
||||||
screen->Dim(PalEntry(255, uint8_t(blend[0] * 255), uint8_t(blend[1] * 255), uint8_t(blend[2] * 255)), blend[3], 0, 0, screen->GetWidth(), screen->GetHeight());
|
const float br = clamp(blend[0] * 255.f, 0.f, 255.f);
|
||||||
|
const float bg = clamp(blend[1] * 255.f, 0.f, 255.f);
|
||||||
|
const float bb = clamp(blend[2] * 255.f, 0.f, 255.f);
|
||||||
|
const PalEntry bcolor(255, uint8_t(br), uint8_t(bg), uint8_t(bb));
|
||||||
|
screen->Dim(bcolor, blend[3], 0, 0, screen->GetWidth(), screen->GetHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -492,6 +492,8 @@ public:
|
||||||
bool SetTextureParms(DrawParms *parms, FTexture *img, double x, double y) const;
|
bool SetTextureParms(DrawParms *parms, FTexture *img, double x, double y) const;
|
||||||
void DrawTexture(FTexture *img, double x, double y, int tags, ...);
|
void DrawTexture(FTexture *img, double x, double y, int tags, ...);
|
||||||
void DrawTexture(FTexture *img, double x, double y, VMVa_List &);
|
void DrawTexture(FTexture *img, double x, double y, VMVa_List &);
|
||||||
|
void DrawShape(FTexture *img, DShape2D *shape, int tags, ...);
|
||||||
|
void DrawShape(FTexture *img, DShape2D *shape, VMVa_List &);
|
||||||
void FillBorder(FTexture *img); // Fills the border around a 4:3 part of the screen on non-4:3 displays
|
void FillBorder(FTexture *img); // Fills the border around a 4:3 part of the screen on non-4:3 displays
|
||||||
void VirtualToRealCoords(double &x, double &y, double &w, double &h, double vwidth, double vheight, bool vbottom = false, bool handleaspect = true) const;
|
void VirtualToRealCoords(double &x, double &y, double &w, double &h, double vwidth, double vheight, bool vbottom = false, bool handleaspect = true) const;
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ vec3 ProcessMaterial(vec3 material, vec3 color);
|
||||||
|
|
||||||
float grayscale(vec4 color)
|
float grayscale(vec4 color)
|
||||||
{
|
{
|
||||||
return dot(color.rgb, vec3(0.4, 0.56, 0.14));
|
return dot(color.rgb, vec3(0.3, 0.56, 0.14));
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
|
@ -165,6 +165,21 @@ enum DrawTextureTags
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Shape2D : Object native
|
||||||
|
{
|
||||||
|
enum EClearWhich
|
||||||
|
{
|
||||||
|
C_Verts = 1,
|
||||||
|
C_Coords = 2,
|
||||||
|
C_Indices = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
native void Clear( int which = C_Verts|C_Coords|C_Indices );
|
||||||
|
native void PushVertex( Vector2 v );
|
||||||
|
native void PushCoord( Vector2 c );
|
||||||
|
native void PushTriangle( int a, int b, int c );
|
||||||
|
}
|
||||||
|
|
||||||
struct Screen native
|
struct Screen native
|
||||||
{
|
{
|
||||||
native static Color PaletteColor(int index);
|
native static Color PaletteColor(int index);
|
||||||
|
@ -174,6 +189,7 @@ struct Screen native
|
||||||
native static void Dim(Color col, double amount, int x, int y, int w, int h);
|
native static void Dim(Color col, double amount, int x, int y, int w, int h);
|
||||||
|
|
||||||
native static vararg void DrawTexture(TextureID tex, bool animate, double x, double y, ...);
|
native static vararg void DrawTexture(TextureID tex, bool animate, double x, double y, ...);
|
||||||
|
native static vararg void DrawShape(TextureID tex, bool animate, Shape2D s, ...);
|
||||||
native static vararg void DrawChar(Font font, int normalcolor, double x, double y, int character, ...);
|
native static vararg void DrawChar(Font font, int normalcolor, double x, double y, int character, ...);
|
||||||
native static vararg void DrawText(Font font, int normalcolor, double x, double y, String text, ...);
|
native static vararg void DrawText(Font font, int normalcolor, double x, double y, String text, ...);
|
||||||
native static void DrawLine(int x0, int y0, int x1, int y1, Color color);
|
native static void DrawLine(int x0, int y0, int x1, int y1, Color color);
|
||||||
|
|
|
@ -135,6 +135,26 @@ class LevelCompatibility play
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case '0F898F0688AECD42F2CD102FAE06F271': // TNT: Evilution MAP07
|
||||||
|
{
|
||||||
|
// Dropping onto the outdoor lava now also raises the
|
||||||
|
// triangle sectors.
|
||||||
|
SetLineSpecial(320, Floor_RaiseToNearest, 16, 32);
|
||||||
|
SetLineActivation(320, SPAC_Cross);
|
||||||
|
SetLineSpecial(959, Floor_RaiseToNearest, 16, 32);
|
||||||
|
SetLineActivation(959, SPAC_Cross);
|
||||||
|
SetLineSpecial(960, Floor_RaiseToNearest, 16, 32);
|
||||||
|
SetLineActivation(960, SPAC_Cross);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '1E785E841A5247B6223C042EC712EBB3': // TNT: Evilution MAP08
|
||||||
|
{
|
||||||
|
// Missing texture when lowering sector to red keycard
|
||||||
|
SetWallTexture(480, Line.back, Side.Bottom, "METAL2");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 'DFC18B92BF3E8142B8684ECD8BD2EF06': // TNT: Evilution map15
|
case 'DFC18B92BF3E8142B8684ECD8BD2EF06': // TNT: Evilution map15
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,18 +27,16 @@ class RandomSpawner : Actor
|
||||||
|
|
||||||
return GetDefaultByType(pclass).bIsMonster;
|
return GetDefaultByType(pclass).bIsMonster;
|
||||||
}
|
}
|
||||||
|
|
||||||
// To handle "RandomSpawning" missiles, the code has to be split in two parts.
|
// Override this to decide what to spawn in some other way.
|
||||||
// If the following code is not done in BeginPlay, missiles will use the
|
// Return the class name, or 'None' to spawn nothing, or 'Unknown' to spawn an error marker.
|
||||||
// random spawner's velocity (0...) instead of their own.
|
virtual Name ChooseSpawn()
|
||||||
override void BeginPlay()
|
|
||||||
{
|
{
|
||||||
DropItem di; // di will be our drop item list iterator
|
DropItem di; // di will be our drop item list iterator
|
||||||
DropItem drop; // while drop stays as the reference point.
|
DropItem drop; // while drop stays as the reference point.
|
||||||
int n = 0;
|
int n = 0;
|
||||||
bool nomonsters = sv_nomonsters || level.nomonsters;
|
bool nomonsters = sv_nomonsters || level.nomonsters;
|
||||||
|
|
||||||
Super.BeginPlay();
|
|
||||||
drop = di = GetDropItems();
|
drop = di = GetDropItems();
|
||||||
if (di != null)
|
if (di != null)
|
||||||
{
|
{
|
||||||
|
@ -57,8 +55,7 @@ class RandomSpawner : Actor
|
||||||
}
|
}
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
{ // Nothing left to spawn. They must have all been monsters, and monsters are disabled.
|
{ // Nothing left to spawn. They must have all been monsters, and monsters are disabled.
|
||||||
Destroy();
|
return 'None';
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// Then we reset the iterator to the start position...
|
// Then we reset the iterator to the start position...
|
||||||
di = drop;
|
di = drop;
|
||||||
|
@ -83,40 +80,69 @@ class RandomSpawner : Actor
|
||||||
di = di.Next;
|
di = di.Next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// So now we can spawn the dropped item.
|
if (di == null)
|
||||||
if (di == null || bouncecount >= MAX_RANDOMSPAWNERS_RECURSION) // Prevents infinite recursions
|
|
||||||
{
|
{
|
||||||
Spawn("Unknown", Pos, NO_REPLACE); // Show that there's a problem.
|
return 'Unknown';
|
||||||
Destroy();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else if (random[randomspawn]() <= di.Probability) // prob 255 = always spawn, prob 0 = almost never spawn.
|
else if (random[randomspawn]() <= di.Probability) // prob 255 = always spawn, prob 0 = almost never spawn.
|
||||||
{
|
{
|
||||||
// Handle replacement here so as to get the proper speed and flags for missiles
|
return di.Name;
|
||||||
Class<Actor> cls = di.Name;
|
}
|
||||||
if (cls != null)
|
else
|
||||||
|
{
|
||||||
|
return 'None';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 'None';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// To handle "RandomSpawning" missiles, the code has to be split in two parts.
|
||||||
|
// If the following code is not done in BeginPlay, missiles will use the
|
||||||
|
// random spawner's velocity (0...) instead of their own.
|
||||||
|
override void BeginPlay()
|
||||||
|
{
|
||||||
|
Super.BeginPlay();
|
||||||
|
let s = ChooseSpawn();
|
||||||
|
|
||||||
|
if (s == 'Unknown') // Spawn error markers immediately.
|
||||||
|
{
|
||||||
|
Spawn(s, Pos, NO_REPLACE);
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
else if (s == 'None') // ChooseSpawn chose to spawn nothing.
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// So now we can spawn the dropped item.
|
||||||
|
// Handle replacement here so as to get the proper speed and flags for missiles
|
||||||
|
Class<Actor> cls = s;
|
||||||
|
if (cls != null)
|
||||||
|
{
|
||||||
|
Class<Actor> rep = GetReplacement(cls);
|
||||||
|
if (rep != null)
|
||||||
{
|
{
|
||||||
Class<Actor> rep = GetReplacement(cls);
|
cls = rep;
|
||||||
if (rep != null)
|
|
||||||
{
|
|
||||||
cls = rep;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (cls != null)
|
|
||||||
{
|
|
||||||
Species = Name(cls);
|
|
||||||
readonly<Actor> defmobj = GetDefaultByType(cls);
|
|
||||||
Speed = defmobj.Speed;
|
|
||||||
bMissile |= defmobj.bMissile;
|
|
||||||
bSeekerMissile |= defmobj.bSeekerMissile;
|
|
||||||
bSpectral |= defmobj.bSpectral;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
A_Log(TEXTCOLOR_RED .. "Unknown item class ".. di.Name .." to drop from a random spawner\n");
|
|
||||||
Species = 'None';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (cls != null)
|
||||||
|
{
|
||||||
|
Species = Name(cls);
|
||||||
|
readonly<Actor> defmobj = GetDefaultByType(cls);
|
||||||
|
Speed = defmobj.Speed;
|
||||||
|
bMissile |= defmobj.bMissile;
|
||||||
|
bSeekerMissile |= defmobj.bSeekerMissile;
|
||||||
|
bSpectral |= defmobj.bSpectral;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
A_Log(TEXTCOLOR_RED .. "Unknown item class ".. s .." to drop from a random spawner\n");
|
||||||
|
Species = 'None';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +154,13 @@ class RandomSpawner : Actor
|
||||||
{
|
{
|
||||||
Super.PostBeginPlay();
|
Super.PostBeginPlay();
|
||||||
|
|
||||||
|
if (bouncecount >= MAX_RANDOMSPAWNERS_RECURSION) // Prevents infinite recursions
|
||||||
|
{
|
||||||
|
Spawn("Unknown", Pos, NO_REPLACE); // Show that there's a problem.
|
||||||
|
Destroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Actor newmobj = null;
|
Actor newmobj = null;
|
||||||
bool boss = false;
|
bool boss = false;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue