mirror of
https://github.com/ddnet/ddnet.git
synced 2024-09-21 18:14:19 +00:00
f31e081bd4
OK, maybe not actually remove because it is kept for fallback when the new method isn't available. The whole gametype parsing business had the same downsides as user agent parsing on the web, hence I removed it while keeping behavior the same. This allows servers to explicitly opt in or out of certain bug workarounds and other client behavior. This increases the complexity of different configurations that are available in the client (which is a bad thing).
1981 lines
67 KiB
C++
1981 lines
67 KiB
C++
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
|
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
|
#include <engine/graphics.h>
|
|
#include <engine/keys.h>
|
|
#include <engine/demo.h>
|
|
#include <engine/serverbrowser.h>
|
|
#include <engine/shared/config.h>
|
|
#include <engine/storage.h>
|
|
|
|
#include <game/layers.h>
|
|
#include <game/client/gameclient.h>
|
|
#include <game/client/component.h>
|
|
#include <game/client/render.h>
|
|
|
|
#include <game/client/components/camera.h>
|
|
#include <game/client/components/mapimages.h>
|
|
|
|
#include <game/generated/client_data.h>
|
|
|
|
#include "maplayers.h"
|
|
|
|
CMapLayers::CMapLayers(int t)
|
|
{
|
|
m_Type = t;
|
|
m_pLayers = 0;
|
|
m_CurrentLocalTick = 0;
|
|
m_LastLocalTick = 0;
|
|
m_EnvelopeUpdate = false;
|
|
}
|
|
|
|
void CMapLayers::OnInit()
|
|
{
|
|
m_pLayers = Layers();
|
|
m_pImages = m_pClient->m_pMapimages;
|
|
}
|
|
|
|
void CMapLayers::EnvelopeUpdate()
|
|
{
|
|
if(Client()->State() == IClient::STATE_DEMOPLAYBACK)
|
|
{
|
|
const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo();
|
|
m_CurrentLocalTick = pInfo->m_CurrentTick;
|
|
m_LastLocalTick = pInfo->m_CurrentTick;
|
|
m_EnvelopeUpdate = true;
|
|
}
|
|
}
|
|
|
|
|
|
void CMapLayers::MapScreenToGroup(float CenterX, float CenterY, CMapItemGroup *pGroup, float Zoom)
|
|
{
|
|
float Points[4];
|
|
RenderTools()->MapscreenToWorld(CenterX, CenterY, pGroup->m_ParallaxX, pGroup->m_ParallaxY,
|
|
pGroup->m_OffsetX, pGroup->m_OffsetY, Graphics()->ScreenAspect(), Zoom, Points);
|
|
Graphics()->MapScreen(Points[0], Points[1], Points[2], Points[3]);
|
|
}
|
|
|
|
void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void *pUser)
|
|
{
|
|
CMapLayers *pThis = (CMapLayers *)pUser;
|
|
pChannels[0] = 0;
|
|
pChannels[1] = 0;
|
|
pChannels[2] = 0;
|
|
pChannels[3] = 0;
|
|
|
|
CEnvPoint *pPoints = 0;
|
|
|
|
{
|
|
int Start, Num;
|
|
pThis->m_pLayers->Map()->GetType(MAPITEMTYPE_ENVPOINTS, &Start, &Num);
|
|
if(Num)
|
|
pPoints = (CEnvPoint *)pThis->m_pLayers->Map()->GetItem(Start, 0, 0);
|
|
}
|
|
|
|
int Start, Num;
|
|
pThis->m_pLayers->Map()->GetType(MAPITEMTYPE_ENVELOPE, &Start, &Num);
|
|
|
|
if(Env >= Num)
|
|
return;
|
|
|
|
CMapItemEnvelope *pItem = (CMapItemEnvelope *)pThis->m_pLayers->Map()->GetItem(Start+Env, 0, 0);
|
|
|
|
static float s_Time = 0.0f;
|
|
static float s_LastLocalTime = pThis->Client()->LocalTime();
|
|
if(pThis->Client()->State() == IClient::STATE_DEMOPLAYBACK)
|
|
{
|
|
const IDemoPlayer::CInfo *pInfo = pThis->DemoPlayer()->BaseInfo();
|
|
|
|
if(!pInfo->m_Paused || pThis->m_EnvelopeUpdate)
|
|
{
|
|
if(pThis->m_CurrentLocalTick != pInfo->m_CurrentTick)
|
|
{
|
|
pThis->m_LastLocalTick = pThis->m_CurrentLocalTick;
|
|
pThis->m_CurrentLocalTick = pInfo->m_CurrentTick;
|
|
}
|
|
|
|
s_Time = mix(pThis->m_LastLocalTick / (float)pThis->Client()->GameTickSpeed(),
|
|
pThis->m_CurrentLocalTick / (float)pThis->Client()->GameTickSpeed(),
|
|
pThis->Client()->IntraGameTick());
|
|
}
|
|
|
|
pThis->RenderTools()->RenderEvalEnvelope(pPoints+pItem->m_StartPoint, pItem->m_NumPoints, 4, s_Time+TimeOffset, pChannels);
|
|
}
|
|
else
|
|
{
|
|
if(pThis->m_pClient->m_Snap.m_pGameInfoObj) // && !(pThis->m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED))
|
|
{
|
|
if(pItem->m_Version < 2 || pItem->m_Synchronized)
|
|
{
|
|
s_Time = mix((pThis->Client()->PrevGameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(),
|
|
(pThis->Client()->GameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(),
|
|
pThis->Client()->IntraGameTick());
|
|
}
|
|
else
|
|
s_Time += pThis->Client()->LocalTime()-s_LastLocalTime;
|
|
}
|
|
pThis->RenderTools()->RenderEvalEnvelope(pPoints+pItem->m_StartPoint, pItem->m_NumPoints, 4, s_Time+TimeOffset, pChannels);
|
|
s_LastLocalTime = pThis->Client()->LocalTime();
|
|
}
|
|
}
|
|
|
|
struct STmpTile
|
|
{
|
|
vec2 m_TopLeft;
|
|
vec2 m_TopRight;
|
|
vec2 m_BottomRight;
|
|
vec2 m_BottomLeft;
|
|
};
|
|
struct STmpTileTexCoord
|
|
{
|
|
STmpTileTexCoord()
|
|
{
|
|
m_TexCoordTopLeftRightOrBottom[0] = m_TexCoordTopLeftRightOrBottom[1] = 0;
|
|
m_TexCoordBottomLeftRightOrBottom[0] = 0; m_TexCoordBottomLeftRightOrBottom[1] = 1;
|
|
m_TexCoordTopRightRightOrBottom[0] = 1; m_TexCoordTopRightRightOrBottom[1] = 0;
|
|
m_TexCoordBottomRightRightOrBottom[0] = m_TexCoordBottomRightRightOrBottom[1] = 1;
|
|
}
|
|
unsigned char m_TexCoordTopLeft[2];
|
|
unsigned char m_TexCoordTopLeftRightOrBottom[2];
|
|
unsigned char m_TexCoordTopRight[2];
|
|
unsigned char m_TexCoordTopRightRightOrBottom[2];
|
|
unsigned char m_TexCoordBottomRight[2];
|
|
unsigned char m_TexCoordBottomRightRightOrBottom[2];
|
|
unsigned char m_TexCoordBottomLeft[2];
|
|
unsigned char m_TexCoordBottomLeftRightOrBottom[2];
|
|
};
|
|
|
|
void FillTmpTileSpeedup(STmpTile* pTmpTile, STmpTileTexCoord* pTmpTex, unsigned char Flags, unsigned char Index, int x, int y, int Scale, CMapItemGroup* pGroup, short AngleRotate)
|
|
{
|
|
if(pTmpTex)
|
|
{
|
|
unsigned char x0 = 0;
|
|
unsigned char y0 = 0;
|
|
unsigned char x1 = 16;
|
|
unsigned char y1 = 0;
|
|
unsigned char x2 = 16;
|
|
unsigned char y2 = 16;
|
|
unsigned char x3 = 0;
|
|
unsigned char y3 = 16;
|
|
|
|
unsigned char bx0 = 0;
|
|
unsigned char by0 = 0;
|
|
unsigned char bx1 = 1;
|
|
unsigned char by1 = 0;
|
|
unsigned char bx2 = 1;
|
|
unsigned char by2 = 1;
|
|
unsigned char bx3 = 0;
|
|
unsigned char by3 = 1;
|
|
|
|
pTmpTex->m_TexCoordTopLeft[0] = x0;
|
|
pTmpTex->m_TexCoordTopLeft[1] = y0;
|
|
pTmpTex->m_TexCoordBottomLeft[0] = x3;
|
|
pTmpTex->m_TexCoordBottomLeft[1] = y3;
|
|
pTmpTex->m_TexCoordTopRight[0] = x1;
|
|
pTmpTex->m_TexCoordTopRight[1] = y1;
|
|
pTmpTex->m_TexCoordBottomRight[0] = x2;
|
|
pTmpTex->m_TexCoordBottomRight[1] = y2;
|
|
|
|
pTmpTex->m_TexCoordTopLeftRightOrBottom[0] = bx0;
|
|
pTmpTex->m_TexCoordTopLeftRightOrBottom[1] = by0;
|
|
pTmpTex->m_TexCoordBottomLeftRightOrBottom[0] = bx3;
|
|
pTmpTex->m_TexCoordBottomLeftRightOrBottom[1] = by3;
|
|
pTmpTex->m_TexCoordTopRightRightOrBottom[0] = bx1;
|
|
pTmpTex->m_TexCoordTopRightRightOrBottom[1] = by1;
|
|
pTmpTex->m_TexCoordBottomRightRightOrBottom[0] = bx2;
|
|
pTmpTex->m_TexCoordBottomRightRightOrBottom[1] = by2;
|
|
}
|
|
|
|
//same as in rotate from Graphics()
|
|
float Angle = (float)AngleRotate*(3.14159265f/180.0f);
|
|
float c = cosf(Angle);
|
|
float s = sinf(Angle);
|
|
float xR, yR;
|
|
int i;
|
|
|
|
int ScaleSmaller = 2;
|
|
pTmpTile->m_TopLeft.x = x*Scale + ScaleSmaller;
|
|
pTmpTile->m_TopLeft.y = y*Scale + ScaleSmaller;
|
|
pTmpTile->m_BottomLeft.x = x*Scale + ScaleSmaller;
|
|
pTmpTile->m_BottomLeft.y = y*Scale + Scale - ScaleSmaller;
|
|
pTmpTile->m_TopRight.x = x*Scale + Scale - ScaleSmaller;
|
|
pTmpTile->m_TopRight.y = y*Scale + ScaleSmaller;
|
|
pTmpTile->m_BottomRight.x = x*Scale + Scale - ScaleSmaller;
|
|
pTmpTile->m_BottomRight.y = y*Scale + Scale - ScaleSmaller;
|
|
|
|
float* pTmpTileVertices = (float*)pTmpTile;
|
|
|
|
vec2 Center;
|
|
Center.x = pTmpTile->m_TopLeft.x + (Scale-ScaleSmaller)/2.f;
|
|
Center.y = pTmpTile->m_TopLeft.y + (Scale-ScaleSmaller)/2.f;
|
|
|
|
for(i = 0; i < 4; i++)
|
|
{
|
|
xR = pTmpTileVertices[i*2] - Center.x;
|
|
yR = pTmpTileVertices[i*2+1] - Center.y;
|
|
pTmpTileVertices[i*2] = xR * c - yR * s + Center.x;
|
|
pTmpTileVertices[i*2+1] = xR * s + yR * c + Center.y;
|
|
}
|
|
}
|
|
|
|
void FillTmpTile(STmpTile* pTmpTile, STmpTileTexCoord* pTmpTex, unsigned char Flags, unsigned char Index, int x, int y, int Scale, CMapItemGroup* pGroup)
|
|
{
|
|
if(pTmpTex)
|
|
{
|
|
unsigned char tx = Index%16;
|
|
unsigned char ty = Index/16;
|
|
unsigned char x0 = tx;
|
|
unsigned char y0 = ty;
|
|
unsigned char x1 = tx+1;
|
|
unsigned char y1 = ty;
|
|
unsigned char x2 = tx+1;
|
|
unsigned char y2 = ty+1;
|
|
unsigned char x3 = tx;
|
|
unsigned char y3 = ty+1;
|
|
|
|
unsigned char bx0 = 0;
|
|
unsigned char by0 = 0;
|
|
unsigned char bx1 = 1;
|
|
unsigned char by1 = 0;
|
|
unsigned char bx2 = 1;
|
|
unsigned char by2 = 1;
|
|
unsigned char bx3 = 0;
|
|
unsigned char by3 = 1;
|
|
|
|
|
|
|
|
if(Flags&TILEFLAG_VFLIP)
|
|
{
|
|
x0 = x2;
|
|
x1 = x3;
|
|
x2 = x3;
|
|
x3 = x0;
|
|
|
|
bx0 = bx2;
|
|
bx1 = bx3;
|
|
bx2 = bx3;
|
|
bx3 = bx0;
|
|
}
|
|
|
|
if(Flags&TILEFLAG_HFLIP)
|
|
{
|
|
y0 = y3;
|
|
y2 = y1;
|
|
y3 = y1;
|
|
y1 = y0;
|
|
|
|
by0 = by3;
|
|
by2 = by1;
|
|
by3 = by1;
|
|
by1 = by0;
|
|
}
|
|
|
|
if(Flags&TILEFLAG_ROTATE)
|
|
{
|
|
unsigned char Tmp = x0;
|
|
x0 = x3;
|
|
x3 = x2;
|
|
x2 = x1;
|
|
x1 = Tmp;
|
|
Tmp = y0;
|
|
y0 = y3;
|
|
y3 = y2;
|
|
y2 = y1;
|
|
y1 = Tmp;
|
|
|
|
Tmp = bx0;
|
|
bx0 = bx3;
|
|
bx3 = bx2;
|
|
bx2 = bx1;
|
|
bx1 = Tmp;
|
|
Tmp = by0;
|
|
by0 = by3;
|
|
by3 = by2;
|
|
by2 = by1;
|
|
by1 = Tmp;
|
|
}
|
|
|
|
pTmpTex->m_TexCoordTopLeft[0] = x0;
|
|
pTmpTex->m_TexCoordTopLeft[1] = y0;
|
|
pTmpTex->m_TexCoordBottomLeft[0] = x3;
|
|
pTmpTex->m_TexCoordBottomLeft[1] = y3;
|
|
pTmpTex->m_TexCoordTopRight[0] = x1;
|
|
pTmpTex->m_TexCoordTopRight[1] = y1;
|
|
pTmpTex->m_TexCoordBottomRight[0] = x2;
|
|
pTmpTex->m_TexCoordBottomRight[1] = y2;
|
|
|
|
pTmpTex->m_TexCoordTopLeftRightOrBottom[0] = bx0;
|
|
pTmpTex->m_TexCoordTopLeftRightOrBottom[1] = by0;
|
|
pTmpTex->m_TexCoordBottomLeftRightOrBottom[0] = bx3;
|
|
pTmpTex->m_TexCoordBottomLeftRightOrBottom[1] = by3;
|
|
pTmpTex->m_TexCoordTopRightRightOrBottom[0] = bx1;
|
|
pTmpTex->m_TexCoordTopRightRightOrBottom[1] = by1;
|
|
pTmpTex->m_TexCoordBottomRightRightOrBottom[0] = bx2;
|
|
pTmpTex->m_TexCoordBottomRightRightOrBottom[1] = by2;
|
|
}
|
|
|
|
pTmpTile->m_TopLeft.x = x*Scale;
|
|
pTmpTile->m_TopLeft.y = y*Scale;
|
|
pTmpTile->m_BottomLeft.x = x*Scale;
|
|
pTmpTile->m_BottomLeft.y = y*Scale + Scale;
|
|
pTmpTile->m_TopRight.x = x*Scale + Scale;
|
|
pTmpTile->m_TopRight.y = y*Scale;
|
|
pTmpTile->m_BottomRight.x = x*Scale + Scale;
|
|
pTmpTile->m_BottomRight.y = y*Scale + Scale;
|
|
}
|
|
|
|
bool CMapLayers::STileLayerVisuals::Init(unsigned int Width, unsigned int Height)
|
|
{
|
|
m_Width = Width;
|
|
m_Height = Height;
|
|
if(Width == 0 || Height == 0)
|
|
return false;
|
|
|
|
m_TilesOfLayer = new CMapLayers::STileLayerVisuals::STileVisual[Height*Width];
|
|
|
|
if(Width > 2)
|
|
{
|
|
m_BorderTop = new CMapLayers::STileLayerVisuals::STileVisual[Width-2];
|
|
m_BorderBottom = new CMapLayers::STileLayerVisuals::STileVisual[Width-2];
|
|
}
|
|
if(Height > 2)
|
|
{
|
|
m_BorderLeft = new CMapLayers::STileLayerVisuals::STileVisual[Height-2];
|
|
m_BorderRight = new CMapLayers::STileLayerVisuals::STileVisual[Height-2];
|
|
}
|
|
return true;
|
|
}
|
|
|
|
CMapLayers::STileLayerVisuals::~STileLayerVisuals()
|
|
{
|
|
if(m_TilesOfLayer)
|
|
{
|
|
delete[] m_TilesOfLayer;
|
|
}
|
|
|
|
if(m_BorderTop)
|
|
delete[] m_BorderTop;
|
|
if(m_BorderBottom)
|
|
delete[] m_BorderBottom;
|
|
if(m_BorderLeft)
|
|
delete[] m_BorderLeft;
|
|
if(m_BorderRight)
|
|
delete[] m_BorderRight;
|
|
|
|
m_TilesOfLayer = NULL;
|
|
m_BorderTop = NULL;
|
|
m_BorderBottom = NULL;
|
|
m_BorderLeft = NULL;
|
|
m_BorderRight = NULL;
|
|
}
|
|
|
|
bool AddTile(std::vector<STmpTile>& TmpTiles, std::vector<STmpTileTexCoord>& TmpTileTexCoords, unsigned char Index, unsigned char Flags, int x, int y, CMapItemGroup* pGroup, bool DoTextureCoords, bool FillSpeedup = false, int AngleRotate = -1)
|
|
{
|
|
if(Index)
|
|
{
|
|
TmpTiles.push_back(STmpTile());
|
|
STmpTile& Tile = TmpTiles.back();
|
|
STmpTileTexCoord* pTileTex = NULL;
|
|
if(DoTextureCoords)
|
|
{
|
|
TmpTileTexCoords.push_back(STmpTileTexCoord());
|
|
STmpTileTexCoord& TileTex = TmpTileTexCoords.back();
|
|
pTileTex = &TileTex;
|
|
}
|
|
if(FillSpeedup)
|
|
FillTmpTileSpeedup(&Tile, pTileTex, Flags, 0, x, y, 32.f, pGroup, AngleRotate);
|
|
else
|
|
FillTmpTile(&Tile, pTileTex, Flags, Index, x, y, 32.f, pGroup);
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
struct STmpQuadVertexTextured
|
|
{
|
|
float m_X, m_Y, m_CenterX, m_CenterY;
|
|
float m_U, m_V;
|
|
unsigned char m_R, m_G, m_B, m_A;
|
|
};
|
|
|
|
struct STmpQuadVertex
|
|
{
|
|
float m_X, m_Y, m_CenterX, m_CenterY;
|
|
unsigned char m_R, m_G, m_B, m_A;
|
|
};
|
|
|
|
struct STmpQuad
|
|
{
|
|
STmpQuadVertex m_aVertices[4];
|
|
};
|
|
|
|
struct STmpQuadTextured
|
|
{
|
|
STmpQuadVertexTextured m_aVertices[4];
|
|
};
|
|
|
|
void mem_copy_special(void *pDest, void *pSource, size_t Size, size_t Count, size_t Steps)
|
|
{
|
|
size_t CurStep = 0;
|
|
for(size_t i = 0; i < Count; ++i)
|
|
{
|
|
mem_copy(((char*)pDest) + CurStep + i * Size, ((char*)pSource) + i * Size, Size);
|
|
CurStep += Steps;
|
|
}
|
|
}
|
|
|
|
void CMapLayers::OnMapLoad()
|
|
{
|
|
if(!Graphics()->IsBufferingEnabled())
|
|
return;
|
|
//clear everything and destroy all buffers
|
|
if(m_TileLayerVisuals.size() != 0)
|
|
{
|
|
int s = m_TileLayerVisuals.size();
|
|
for(int i = 0; i < s; ++i)
|
|
{
|
|
Graphics()->DeleteBufferContainer(m_TileLayerVisuals[i]->m_BufferContainerIndex, true);
|
|
delete m_TileLayerVisuals[i];
|
|
}
|
|
m_TileLayerVisuals.clear();
|
|
}
|
|
if(m_QuadLayerVisuals.size() != 0)
|
|
{
|
|
int s = m_QuadLayerVisuals.size();
|
|
for(int i = 0; i < s; ++i)
|
|
{
|
|
Graphics()->DeleteBufferContainer(m_QuadLayerVisuals[i]->m_BufferContainerIndex, true);
|
|
delete m_QuadLayerVisuals[i];
|
|
}
|
|
m_QuadLayerVisuals.clear();
|
|
}
|
|
|
|
bool PassedGameLayer = false;
|
|
//prepare all visuals for all tile layers
|
|
std::vector<STmpTile> tmpTiles;
|
|
std::vector<STmpTileTexCoord> tmpTileTexCoords;
|
|
std::vector<STmpTile> tmpBorderTopTiles;
|
|
std::vector<STmpTileTexCoord> tmpBorderTopTilesTexCoords;
|
|
std::vector<STmpTile> tmpBorderLeftTiles;
|
|
std::vector<STmpTileTexCoord> tmpBorderLeftTilesTexCoords;
|
|
std::vector<STmpTile> tmpBorderRightTiles;
|
|
std::vector<STmpTileTexCoord> tmpBorderRightTilesTexCoords;
|
|
std::vector<STmpTile> tmpBorderBottomTiles;
|
|
std::vector<STmpTileTexCoord> tmpBorderBottomTilesTexCoords;
|
|
std::vector<STmpTile> tmpBorderCorners;
|
|
std::vector<STmpTileTexCoord> tmpBorderCornersTexCoords;
|
|
|
|
std::vector<STmpQuad> tmpQuads;
|
|
std::vector<STmpQuadTextured> tmpQuadsTextured;
|
|
|
|
for(int g = 0; g < m_pLayers->NumGroups(); g++)
|
|
{
|
|
CMapItemGroup *pGroup = m_pLayers->GetGroup(g);
|
|
if(!pGroup)
|
|
{
|
|
dbg_msg("maplayers", "error group was null, group number = %d, total groups = %d", g, m_pLayers->NumGroups());
|
|
dbg_msg("maplayers", "this is here to prevent a crash but the source of this is unknown, please report this for it to get fixed");
|
|
dbg_msg("maplayers", "we need mapname and crc and the map that caused this if possible, and anymore info you think is relevant");
|
|
continue;
|
|
}
|
|
|
|
for(int l = 0; l < pGroup->m_NumLayers; l++)
|
|
{
|
|
CMapItemLayer *pLayer = m_pLayers->GetLayer(pGroup->m_StartLayer+l);
|
|
bool IsFrontLayer = false;
|
|
bool IsSwitchLayer = false;
|
|
bool IsTeleLayer = false;
|
|
bool IsSpeedupLayer = false;
|
|
bool IsTuneLayer = false;
|
|
bool IsGameLayer = false;
|
|
bool IsEntityLayer = false;
|
|
|
|
if(pLayer == (CMapItemLayer*)m_pLayers->GameLayer())
|
|
{
|
|
IsGameLayer = true;
|
|
IsEntityLayer = true;
|
|
PassedGameLayer = true;
|
|
}
|
|
|
|
if(pLayer == (CMapItemLayer*)m_pLayers->FrontLayer())
|
|
IsEntityLayer = IsFrontLayer = true;
|
|
|
|
if(pLayer == (CMapItemLayer*)m_pLayers->SwitchLayer())
|
|
IsEntityLayer = IsSwitchLayer = true;
|
|
|
|
if(pLayer == (CMapItemLayer*)m_pLayers->TeleLayer())
|
|
IsEntityLayer = IsTeleLayer = true;
|
|
|
|
if(pLayer == (CMapItemLayer*)m_pLayers->SpeedupLayer())
|
|
IsEntityLayer = IsSpeedupLayer = true;
|
|
|
|
if(pLayer == (CMapItemLayer*)m_pLayers->TuneLayer())
|
|
IsEntityLayer = IsTuneLayer = true;
|
|
|
|
if(m_Type <= TYPE_BACKGROUND_FORCE)
|
|
{
|
|
if(PassedGameLayer)
|
|
return;
|
|
}
|
|
else if(m_Type == TYPE_FOREGROUND)
|
|
{
|
|
if(!PassedGameLayer)
|
|
continue;
|
|
}
|
|
|
|
if(pLayer->m_Type == LAYERTYPE_TILES)
|
|
{
|
|
bool DoTextureCoords = false;
|
|
CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer;
|
|
if(pTMap->m_Image == -1)
|
|
{
|
|
if(IsEntityLayer)
|
|
DoTextureCoords = true;
|
|
}
|
|
else
|
|
DoTextureCoords = true;
|
|
|
|
|
|
int DataIndex = 0;
|
|
unsigned int TileSize = 0;
|
|
int OverlayCount = 0;
|
|
if(IsFrontLayer)
|
|
{
|
|
DataIndex = pTMap->m_Front;
|
|
TileSize = sizeof(CTile);
|
|
}
|
|
else if(IsSwitchLayer)
|
|
{
|
|
DataIndex = pTMap->m_Switch;
|
|
TileSize = sizeof(CSwitchTile);
|
|
OverlayCount = 2;
|
|
}
|
|
else if(IsTeleLayer)
|
|
{
|
|
DataIndex = pTMap->m_Tele;
|
|
TileSize = sizeof(CTeleTile);
|
|
OverlayCount = 1;
|
|
}
|
|
else if(IsSpeedupLayer)
|
|
{
|
|
DataIndex = pTMap->m_Speedup;
|
|
TileSize = sizeof(CSpeedupTile);
|
|
OverlayCount = 2;
|
|
}
|
|
else if(IsTuneLayer)
|
|
{
|
|
DataIndex = pTMap->m_Tune;
|
|
TileSize = sizeof(CTuneTile);
|
|
}
|
|
else
|
|
{
|
|
DataIndex = pTMap->m_Data;
|
|
TileSize = sizeof(CTile);
|
|
}
|
|
unsigned int Size = m_pLayers->Map()->GetDataSize(DataIndex);
|
|
void* pTiles = m_pLayers->Map()->GetData(DataIndex);
|
|
|
|
if(Size >= pTMap->m_Width*pTMap->m_Height*TileSize)
|
|
{
|
|
int CurOverlay = 0;
|
|
while(CurOverlay < OverlayCount + 1)
|
|
{
|
|
// We can later just count the tile layers to get the idx in the vector
|
|
m_TileLayerVisuals.push_back(new STileLayerVisuals());
|
|
STileLayerVisuals& Visuals = *m_TileLayerVisuals.back();
|
|
if(!Visuals.Init(pTMap->m_Width, pTMap->m_Height))
|
|
{
|
|
++CurOverlay;
|
|
continue;
|
|
}
|
|
Visuals.m_IsTextured = DoTextureCoords;
|
|
|
|
tmpTiles.clear();
|
|
tmpTileTexCoords.clear();
|
|
|
|
tmpBorderTopTiles.clear();
|
|
tmpBorderLeftTiles.clear();
|
|
tmpBorderRightTiles.clear();
|
|
tmpBorderBottomTiles.clear();
|
|
tmpBorderCorners.clear();
|
|
tmpBorderTopTilesTexCoords.clear();
|
|
tmpBorderLeftTilesTexCoords.clear();
|
|
tmpBorderRightTilesTexCoords.clear();
|
|
tmpBorderBottomTilesTexCoords.clear();
|
|
tmpBorderCornersTexCoords.clear();
|
|
|
|
int x = 0;
|
|
int y = 0;
|
|
for(y = 0; y < pTMap->m_Height; ++y)
|
|
{
|
|
for(x = 0; x < pTMap->m_Width; ++x)
|
|
{
|
|
|
|
unsigned char Index = 0;
|
|
unsigned char Flags = 0;
|
|
int AngleRotate = -1;
|
|
if(IsEntityLayer)
|
|
{
|
|
if(IsGameLayer)
|
|
{
|
|
Index = ((CTile*)pTiles)[y*pTMap->m_Width+x].m_Index;
|
|
Flags = ((CTile*)pTiles)[y*pTMap->m_Width+x].m_Flags;
|
|
if(GameClient()->m_GameInfo.m_EntitiesDDNet && !IsValidGameTile(Index))
|
|
Index = 0;
|
|
}
|
|
if(IsFrontLayer)
|
|
{
|
|
Index = ((CTile*)pTiles)[y*pTMap->m_Width+x].m_Index;
|
|
Flags = ((CTile*)pTiles)[y*pTMap->m_Width+x].m_Flags;
|
|
if(!IsValidFrontTile(Index))
|
|
Index = 0;
|
|
}
|
|
if(IsSwitchLayer)
|
|
{
|
|
Flags = 0;
|
|
Index = ((CSwitchTile*)pTiles)[y*pTMap->m_Width+x].m_Type;
|
|
if(!IsValidSwitchTile(Index))
|
|
Index = 0;
|
|
else if(CurOverlay == 0)
|
|
{
|
|
Flags = ((CSwitchTile*)pTiles)[y*pTMap->m_Width+x].m_Flags;
|
|
if(Index == TILE_SWITCHTIMEDOPEN) Index = 8;
|
|
}
|
|
else if(CurOverlay == 1)
|
|
Index = ((CSwitchTile*)pTiles)[y*pTMap->m_Width+x].m_Number;
|
|
else if(CurOverlay == 2)
|
|
Index = ((CSwitchTile*)pTiles)[y*pTMap->m_Width+x].m_Delay;
|
|
}
|
|
if(IsTeleLayer)
|
|
{
|
|
Index = ((CTeleTile*)pTiles)[y*pTMap->m_Width+x].m_Type;
|
|
Flags = 0;
|
|
if(!IsValidTeleTile(Index))
|
|
Index = 0;
|
|
else if(CurOverlay == 1)
|
|
{
|
|
if(Index != TILE_TELECHECKIN && Index != TILE_TELECHECKINEVIL)
|
|
Index = ((CTeleTile*)pTiles)[y*pTMap->m_Width+x].m_Number;
|
|
else Index = 0;
|
|
}
|
|
}
|
|
if(IsSpeedupLayer)
|
|
{
|
|
Index = ((CSpeedupTile*)pTiles)[y*pTMap->m_Width+x].m_Type;
|
|
Flags = 0;
|
|
AngleRotate = ((CSpeedupTile*)pTiles)[y*pTMap->m_Width + x].m_Angle;
|
|
if(!IsValidSpeedupTile(Index) || ((CSpeedupTile*)pTiles)[y*pTMap->m_Width+x].m_Force == 0)
|
|
Index = 0;
|
|
else if(CurOverlay == 1)
|
|
Index = ((CSpeedupTile*)pTiles)[y*pTMap->m_Width+x].m_Force;
|
|
else if(CurOverlay == 2)
|
|
Index = ((CSpeedupTile*)pTiles)[y*pTMap->m_Width+x].m_MaxSpeed;
|
|
}
|
|
if(IsTuneLayer)
|
|
{
|
|
Index = ((CTuneTile*)pTiles)[y*pTMap->m_Width+x].m_Type;
|
|
if(!IsValidTuneTile(Index))
|
|
Index = 0;
|
|
Flags = 0;
|
|
}
|
|
} else
|
|
{
|
|
Index = ((CTile*)pTiles)[y*pTMap->m_Width+x].m_Index;
|
|
Flags = ((CTile*)pTiles)[y*pTMap->m_Width+x].m_Flags;
|
|
}
|
|
|
|
//the amount of tiles handled before this tile
|
|
int TilesHandledCount = tmpTiles.size();
|
|
Visuals.m_TilesOfLayer[y*pTMap->m_Width + x].SetIndexBufferByteOffset((offset_ptr32)(TilesHandledCount*6*sizeof(unsigned int)));
|
|
|
|
bool AddAsSpeedup = false;
|
|
if(IsSpeedupLayer && CurOverlay == 0)
|
|
AddAsSpeedup = true;
|
|
|
|
if(AddTile(tmpTiles, tmpTileTexCoords, Index, Flags, x, y, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate))
|
|
Visuals.m_TilesOfLayer[y*pTMap->m_Width + x].Draw(true);
|
|
|
|
//do the border tiles
|
|
if(x == 0)
|
|
{
|
|
if(y == 0)
|
|
{
|
|
Visuals.m_BorderTopLeft.SetIndexBufferByteOffset((offset_ptr32)(tmpBorderCorners.size()*6*sizeof(unsigned int)));
|
|
if(AddTile(tmpBorderCorners, tmpBorderCornersTexCoords, Index, Flags, x, y, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate))
|
|
Visuals.m_BorderTopLeft.Draw(true);
|
|
}
|
|
else if(y == pTMap->m_Height - 1)
|
|
{
|
|
Visuals.m_BorderBottomLeft.SetIndexBufferByteOffset((offset_ptr32)(tmpBorderCorners.size()*6*sizeof(unsigned int)));
|
|
if(AddTile(tmpBorderCorners, tmpBorderCornersTexCoords, Index, Flags, x, y, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate))
|
|
Visuals.m_BorderBottomLeft.Draw(true);
|
|
|
|
}
|
|
else
|
|
{
|
|
Visuals.m_BorderLeft[y-1].SetIndexBufferByteOffset((offset_ptr32)(tmpBorderLeftTiles.size()*6*sizeof(unsigned int)));
|
|
if(AddTile(tmpBorderLeftTiles, tmpBorderLeftTilesTexCoords, Index, Flags, x, y, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate))
|
|
Visuals.m_BorderLeft[y-1].Draw(true);
|
|
}
|
|
}
|
|
else if(x == pTMap->m_Width - 1)
|
|
{
|
|
if(y == 0)
|
|
{
|
|
Visuals.m_BorderTopRight.SetIndexBufferByteOffset((offset_ptr32)(tmpBorderCorners.size()*6*sizeof(unsigned int)));
|
|
if(AddTile(tmpBorderCorners, tmpBorderCornersTexCoords, Index, Flags, x, y, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate))
|
|
Visuals.m_BorderTopRight.Draw(true);
|
|
|
|
}
|
|
else if(y == pTMap->m_Height - 1)
|
|
{
|
|
Visuals.m_BorderBottomRight.SetIndexBufferByteOffset((offset_ptr32)(tmpBorderCorners.size()*6*sizeof(unsigned int)));
|
|
if(AddTile(tmpBorderCorners, tmpBorderCornersTexCoords, Index, Flags, x, y, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate))
|
|
Visuals.m_BorderBottomRight.Draw(true);
|
|
|
|
}
|
|
else
|
|
{
|
|
Visuals.m_BorderRight[y-1].SetIndexBufferByteOffset((offset_ptr32)(tmpBorderRightTiles.size()*6*sizeof(unsigned int)));
|
|
if(AddTile(tmpBorderRightTiles, tmpBorderRightTilesTexCoords, Index, Flags, x, y, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate))
|
|
Visuals.m_BorderRight[y-1].Draw(true);
|
|
}
|
|
}
|
|
else if(y == 0)
|
|
{
|
|
if(x > 0 && x < pTMap->m_Width - 1)
|
|
{
|
|
Visuals.m_BorderTop[x-1].SetIndexBufferByteOffset((offset_ptr32)(tmpBorderTopTiles.size()*6*sizeof(unsigned int)));
|
|
if(AddTile(tmpBorderTopTiles, tmpBorderTopTilesTexCoords, Index, Flags, x, y, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate))
|
|
Visuals.m_BorderTop[x-1].Draw(true);
|
|
}
|
|
}
|
|
else if(y == pTMap->m_Height - 1)
|
|
{
|
|
if(x > 0 && x < pTMap->m_Width - 1)
|
|
{
|
|
Visuals.m_BorderBottom[x-1].SetIndexBufferByteOffset((offset_ptr32)(tmpBorderBottomTiles.size()*6*sizeof(unsigned int)));
|
|
if(AddTile(tmpBorderBottomTiles, tmpBorderBottomTilesTexCoords, Index, Flags, x, y, pGroup, DoTextureCoords, AddAsSpeedup, AngleRotate))
|
|
Visuals.m_BorderBottom[x-1].Draw(true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//append one kill tile to the gamelayer
|
|
if(IsGameLayer)
|
|
{
|
|
Visuals.m_BorderKillTile.SetIndexBufferByteOffset((offset_ptr32)(tmpTiles.size() * 6 * sizeof(unsigned int)));
|
|
if(AddTile(tmpTiles, tmpTileTexCoords, TILE_DEATH, 0, 0, 0, pGroup, DoTextureCoords))
|
|
Visuals.m_BorderKillTile.Draw(true);
|
|
}
|
|
|
|
//add the border corners, then the borders and fix their byte offsets
|
|
int TilesHandledCount = tmpTiles.size();
|
|
Visuals.m_BorderTopLeft.AddIndexBufferByteOffset(TilesHandledCount*6*sizeof(unsigned int));
|
|
Visuals.m_BorderTopRight.AddIndexBufferByteOffset(TilesHandledCount*6*sizeof(unsigned int));
|
|
Visuals.m_BorderBottomLeft.AddIndexBufferByteOffset(TilesHandledCount*6*sizeof(unsigned int));
|
|
Visuals.m_BorderBottomRight.AddIndexBufferByteOffset(TilesHandledCount*6*sizeof(unsigned int));
|
|
//add the Corners to the tiles
|
|
tmpTiles.insert(tmpTiles.end(), tmpBorderCorners.begin(), tmpBorderCorners.end());
|
|
tmpTileTexCoords.insert(tmpTileTexCoords.end(), tmpBorderCornersTexCoords.begin(), tmpBorderCornersTexCoords.end());
|
|
|
|
//now the borders
|
|
TilesHandledCount = tmpTiles.size();
|
|
if(pTMap->m_Width > 2)
|
|
{
|
|
for(int i = 0; i < pTMap->m_Width-2; ++i)
|
|
{
|
|
Visuals.m_BorderTop[i].AddIndexBufferByteOffset(TilesHandledCount * 6 * sizeof(unsigned int));
|
|
}
|
|
}
|
|
tmpTiles.insert(tmpTiles.end(), tmpBorderTopTiles.begin(), tmpBorderTopTiles.end());
|
|
tmpTileTexCoords.insert(tmpTileTexCoords.end(), tmpBorderTopTilesTexCoords.begin(), tmpBorderTopTilesTexCoords.end());
|
|
|
|
TilesHandledCount = tmpTiles.size();
|
|
if(pTMap->m_Width > 2)
|
|
{
|
|
for(int i = 0; i < pTMap->m_Width-2; ++i)
|
|
{
|
|
Visuals.m_BorderBottom[i].AddIndexBufferByteOffset(TilesHandledCount * 6 * sizeof(unsigned int));
|
|
}
|
|
}
|
|
tmpTiles.insert(tmpTiles.end(), tmpBorderBottomTiles.begin(), tmpBorderBottomTiles.end());
|
|
tmpTileTexCoords.insert(tmpTileTexCoords.end(), tmpBorderBottomTilesTexCoords.begin(), tmpBorderBottomTilesTexCoords.end());
|
|
|
|
TilesHandledCount = tmpTiles.size();
|
|
if(pTMap->m_Height > 2)
|
|
{
|
|
for(int i = 0; i < pTMap->m_Height-2; ++i)
|
|
{
|
|
Visuals.m_BorderLeft[i].AddIndexBufferByteOffset(TilesHandledCount * 6 * sizeof(unsigned int));
|
|
}
|
|
}
|
|
tmpTiles.insert(tmpTiles.end(), tmpBorderLeftTiles.begin(), tmpBorderLeftTiles.end());
|
|
tmpTileTexCoords.insert(tmpTileTexCoords.end(), tmpBorderLeftTilesTexCoords.begin(), tmpBorderLeftTilesTexCoords.end());
|
|
|
|
TilesHandledCount = tmpTiles.size();
|
|
if(pTMap->m_Height > 2)
|
|
{
|
|
for(int i = 0; i < pTMap->m_Height-2; ++i)
|
|
{
|
|
Visuals.m_BorderRight[i].AddIndexBufferByteOffset(TilesHandledCount * 6 * sizeof(unsigned int));
|
|
}
|
|
}
|
|
tmpTiles.insert(tmpTiles.end(), tmpBorderRightTiles.begin(), tmpBorderRightTiles.end());
|
|
tmpTileTexCoords.insert(tmpTileTexCoords.end(), tmpBorderRightTilesTexCoords.begin(), tmpBorderRightTilesTexCoords.end());
|
|
|
|
//setup params
|
|
float* pTmpTiles = (tmpTiles.size() == 0) ? NULL : (float*)&tmpTiles[0];
|
|
unsigned char* pTmpTileTexCoords = (tmpTileTexCoords.size() == 0) ? NULL : (unsigned char*)&tmpTileTexCoords[0];
|
|
|
|
size_t UploadDataSize = tmpTileTexCoords.size() * sizeof(STmpTileTexCoord) + tmpTiles.size() * sizeof(STmpTile);
|
|
char* pUploadData = new char[UploadDataSize];
|
|
|
|
mem_copy_special(pUploadData, pTmpTiles, sizeof(vec2), tmpTiles.size() * 4, (DoTextureCoords ? (sizeof(unsigned char) * 2 * 2) : 0));
|
|
if(DoTextureCoords)
|
|
{
|
|
mem_copy_special(pUploadData + sizeof(vec2), pTmpTileTexCoords, sizeof(unsigned char) * 2 * 2, tmpTiles.size() * 4, (DoTextureCoords ? (sizeof(vec2)) : 0));
|
|
}
|
|
|
|
// first create the buffer object
|
|
int BufferObjectIndex = Graphics()->CreateBufferObject(UploadDataSize, pUploadData);
|
|
delete[] pUploadData;
|
|
|
|
// then create the buffer container
|
|
SBufferContainerInfo ContainerInfo;
|
|
ContainerInfo.m_Stride = (DoTextureCoords ? (sizeof(float) * 2 + sizeof(unsigned char) * 2 * 2) : 0);
|
|
ContainerInfo.m_Attributes.push_back(SBufferContainerInfo::SAttribute());
|
|
SBufferContainerInfo::SAttribute* pAttr = &ContainerInfo.m_Attributes.back();
|
|
pAttr->m_DataTypeCount = 2;
|
|
pAttr->m_Type = GRAPHICS_TYPE_FLOAT;
|
|
pAttr->m_Normalized = false;
|
|
pAttr->m_pOffset = 0;
|
|
pAttr->m_FuncType = 0;
|
|
pAttr->m_VertBufferBindingIndex = BufferObjectIndex;
|
|
if(DoTextureCoords)
|
|
{
|
|
ContainerInfo.m_Attributes.push_back(SBufferContainerInfo::SAttribute());
|
|
pAttr = &ContainerInfo.m_Attributes.back();
|
|
pAttr->m_DataTypeCount = 2;
|
|
pAttr->m_Type = GRAPHICS_TYPE_UNSIGNED_BYTE;
|
|
pAttr->m_Normalized = false;
|
|
pAttr->m_pOffset = (void*)(sizeof(vec2));
|
|
pAttr->m_FuncType = 0;
|
|
pAttr->m_VertBufferBindingIndex = BufferObjectIndex;
|
|
|
|
ContainerInfo.m_Attributes.push_back(SBufferContainerInfo::SAttribute());
|
|
pAttr = &ContainerInfo.m_Attributes.back();
|
|
pAttr->m_DataTypeCount = 2;
|
|
pAttr->m_Type = GRAPHICS_TYPE_UNSIGNED_BYTE;
|
|
pAttr->m_Normalized = false;
|
|
pAttr->m_pOffset = (void*)(sizeof(vec2) + sizeof(unsigned char) * 2);
|
|
pAttr->m_FuncType = 1;
|
|
pAttr->m_VertBufferBindingIndex = BufferObjectIndex;
|
|
}
|
|
|
|
Visuals.m_BufferContainerIndex = Graphics()->CreateBufferContainer(&ContainerInfo);
|
|
// and finally inform the backend how many indices are required
|
|
Graphics()->IndicesNumRequiredNotify(tmpTiles.size() * 6);
|
|
|
|
++CurOverlay;
|
|
}
|
|
}
|
|
}
|
|
else if(pLayer->m_Type == LAYERTYPE_QUADS)
|
|
{
|
|
CMapItemLayerQuads *pQLayer = (CMapItemLayerQuads *)pLayer;
|
|
|
|
m_QuadLayerVisuals.push_back(new SQuadLayerVisuals());
|
|
SQuadLayerVisuals* pQLayerVisuals = m_QuadLayerVisuals.back();
|
|
|
|
bool Textured = (pQLayer->m_Image == -1 ? false : true);
|
|
|
|
tmpQuads.clear();
|
|
tmpQuadsTextured.clear();
|
|
|
|
if(Textured)
|
|
tmpQuadsTextured.resize(pQLayer->m_NumQuads);
|
|
else
|
|
tmpQuads.resize(pQLayer->m_NumQuads);
|
|
|
|
CQuad *pQuads = (CQuad *)m_pLayers->Map()->GetDataSwapped(pQLayer->m_Data);
|
|
for(int i = 0; i < pQLayer->m_NumQuads; ++i)
|
|
{
|
|
CQuad *q = &pQuads[i];
|
|
for(int j = 0; j < 4; ++j)
|
|
{
|
|
int QuadIDX = j;
|
|
if(j == 2)
|
|
QuadIDX = 3;
|
|
else if(j == 3)
|
|
QuadIDX = 2;
|
|
if(!Textured)
|
|
{
|
|
// ignore the conversion for the position coordinates
|
|
tmpQuads[i].m_aVertices[j].m_X = (q->m_aPoints[QuadIDX].x);
|
|
tmpQuads[i].m_aVertices[j].m_Y = (q->m_aPoints[QuadIDX].y);
|
|
tmpQuads[i].m_aVertices[j].m_CenterX = (q->m_aPoints[4].x);
|
|
tmpQuads[i].m_aVertices[j].m_CenterY = (q->m_aPoints[4].y);
|
|
tmpQuads[i].m_aVertices[j].m_R = (unsigned char)q->m_aColors[QuadIDX].r;
|
|
tmpQuads[i].m_aVertices[j].m_G = (unsigned char)q->m_aColors[QuadIDX].g;
|
|
tmpQuads[i].m_aVertices[j].m_B = (unsigned char)q->m_aColors[QuadIDX].b;
|
|
tmpQuads[i].m_aVertices[j].m_A = (unsigned char)q->m_aColors[QuadIDX].a;
|
|
}
|
|
else
|
|
{
|
|
// ignore the conversion for the position coordinates
|
|
tmpQuadsTextured[i].m_aVertices[j].m_X = (q->m_aPoints[QuadIDX].x);
|
|
tmpQuadsTextured[i].m_aVertices[j].m_Y = (q->m_aPoints[QuadIDX].y);
|
|
tmpQuadsTextured[i].m_aVertices[j].m_CenterX = (q->m_aPoints[4].x);
|
|
tmpQuadsTextured[i].m_aVertices[j].m_CenterY = (q->m_aPoints[4].y);
|
|
tmpQuadsTextured[i].m_aVertices[j].m_U = fx2f(q->m_aTexcoords[QuadIDX].x);
|
|
tmpQuadsTextured[i].m_aVertices[j].m_V = fx2f(q->m_aTexcoords[QuadIDX].y);
|
|
tmpQuadsTextured[i].m_aVertices[j].m_R = (unsigned char)q->m_aColors[QuadIDX].r;
|
|
tmpQuadsTextured[i].m_aVertices[j].m_G = (unsigned char)q->m_aColors[QuadIDX].g;
|
|
tmpQuadsTextured[i].m_aVertices[j].m_B = (unsigned char)q->m_aColors[QuadIDX].b;
|
|
tmpQuadsTextured[i].m_aVertices[j].m_A = (unsigned char)q->m_aColors[QuadIDX].a;
|
|
}
|
|
}
|
|
}
|
|
|
|
size_t UploadDataSize = 0;
|
|
if(Textured)
|
|
UploadDataSize = tmpQuadsTextured.size() * sizeof(STmpQuadTextured);
|
|
else
|
|
UploadDataSize = tmpQuads.size() * sizeof(STmpQuad);
|
|
|
|
if(UploadDataSize > 0) {
|
|
void* pUploadData = NULL;
|
|
if(Textured)
|
|
pUploadData = &tmpQuadsTextured[0];
|
|
else
|
|
pUploadData = &tmpQuads[0];
|
|
// create the buffer object
|
|
int BufferObjectIndex = Graphics()->CreateBufferObject(UploadDataSize, pUploadData);
|
|
// then create the buffer container
|
|
SBufferContainerInfo ContainerInfo;
|
|
ContainerInfo.m_Stride = (Textured ? (sizeof(STmpQuadTextured) / 4) : (sizeof(STmpQuad) / 4));
|
|
ContainerInfo.m_Attributes.push_back(SBufferContainerInfo::SAttribute());
|
|
SBufferContainerInfo::SAttribute* pAttr = &ContainerInfo.m_Attributes.back();
|
|
pAttr->m_DataTypeCount = 4;
|
|
pAttr->m_Type = GRAPHICS_TYPE_FLOAT;
|
|
pAttr->m_Normalized = false;
|
|
pAttr->m_pOffset = 0;
|
|
pAttr->m_FuncType = 0;
|
|
pAttr->m_VertBufferBindingIndex = BufferObjectIndex;
|
|
if(Textured)
|
|
{
|
|
ContainerInfo.m_Attributes.push_back(SBufferContainerInfo::SAttribute());
|
|
pAttr = &ContainerInfo.m_Attributes.back();
|
|
pAttr->m_DataTypeCount = 2;
|
|
pAttr->m_Type = GRAPHICS_TYPE_FLOAT;
|
|
pAttr->m_Normalized = false;
|
|
pAttr->m_pOffset = (void*)(sizeof(float) * 4);
|
|
pAttr->m_FuncType = 0;
|
|
pAttr->m_VertBufferBindingIndex = BufferObjectIndex;
|
|
}
|
|
ContainerInfo.m_Attributes.push_back(SBufferContainerInfo::SAttribute());
|
|
pAttr = &ContainerInfo.m_Attributes.back();
|
|
pAttr->m_DataTypeCount = 4;
|
|
pAttr->m_Type = GRAPHICS_TYPE_UNSIGNED_BYTE;
|
|
pAttr->m_Normalized = true;
|
|
pAttr->m_pOffset = (void*)(sizeof(float) * 4 + (Textured ? (sizeof(float) * 2) : 0));
|
|
pAttr->m_FuncType = 0;
|
|
pAttr->m_VertBufferBindingIndex = BufferObjectIndex;
|
|
|
|
pQLayerVisuals->m_BufferContainerIndex = Graphics()->CreateBufferContainer(&ContainerInfo);
|
|
// and finally inform the backend how many indices are required
|
|
Graphics()->IndicesNumRequiredNotify(pQLayer->m_NumQuads * 6);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMapLayers::RenderTileLayer(int LayerIndex, ColorRGBA* pColor, CMapItemLayerTilemap* pTileLayer, CMapItemGroup* pGroup)
|
|
{
|
|
STileLayerVisuals& Visuals = *m_TileLayerVisuals[LayerIndex];
|
|
if(Visuals.m_BufferContainerIndex == -1)
|
|
return; //no visuals were created
|
|
|
|
float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
|
|
Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1);
|
|
|
|
float r=1, g=1, b=1, a=1;
|
|
if(pTileLayer->m_ColorEnv >= 0)
|
|
{
|
|
float aChannels[4];
|
|
EnvelopeEval(pTileLayer->m_ColorEnvOffset/1000.0f, pTileLayer->m_ColorEnv, aChannels, this);
|
|
r = aChannels[0];
|
|
g = aChannels[1];
|
|
b = aChannels[2];
|
|
a = aChannels[3];
|
|
}
|
|
|
|
int BorderX0, BorderY0, BorderX1, BorderY1;
|
|
bool DrawBorder = false;
|
|
|
|
int Y0 = BorderY0 = (int)floorf((ScreenY0)/32);
|
|
int X0 = BorderX0 = (int)floorf((ScreenX0)/32);
|
|
int Y1 = BorderY1 = (int)floorf((ScreenY1)/32);
|
|
int X1 = BorderX1 = (int)floorf((ScreenX1)/32);
|
|
|
|
if(X0 <= 0)
|
|
{
|
|
X0 = 0;
|
|
DrawBorder = true;
|
|
}
|
|
if(Y0 <= 0)
|
|
{
|
|
Y0 = 0;
|
|
DrawBorder = true;
|
|
}
|
|
if(X1 >= pTileLayer->m_Width - 1)
|
|
{
|
|
X1 = pTileLayer->m_Width - 1;
|
|
DrawBorder = true;
|
|
}
|
|
if(Y1 >= pTileLayer->m_Height - 1)
|
|
{
|
|
Y1 = pTileLayer->m_Height - 1;
|
|
DrawBorder = true;
|
|
}
|
|
|
|
bool DrawLayer = true;
|
|
if(X1 < 0)
|
|
DrawLayer = false;
|
|
if(Y1 < 0)
|
|
DrawLayer = false;
|
|
if(X0 >= pTileLayer->m_Width)
|
|
DrawLayer = false;
|
|
if(Y0 >= pTileLayer->m_Height)
|
|
DrawLayer = false;
|
|
|
|
if(DrawLayer)
|
|
{
|
|
//create the indice buffers we want to draw -- reuse them
|
|
static std::vector<char*> s_IndexOffsets;
|
|
static std::vector<unsigned int> s_DrawCounts;
|
|
|
|
s_IndexOffsets.clear();
|
|
s_DrawCounts.clear();
|
|
|
|
unsigned long long Reserve = absolute(Y1 - Y0) + 1;
|
|
s_IndexOffsets.reserve(Reserve);
|
|
s_DrawCounts.reserve(Reserve);
|
|
|
|
for(int y = Y0; y <= Y1; ++y)
|
|
{
|
|
if(X0 > X1)
|
|
continue;
|
|
|
|
dbg_assert(Visuals.m_TilesOfLayer[y*pTileLayer->m_Width + X1].IndexBufferByteOffset() >= Visuals.m_TilesOfLayer[y*pTileLayer->m_Width + X0].IndexBufferByteOffset(), "Tile count wrong.");
|
|
|
|
unsigned int NumVertices = ((Visuals.m_TilesOfLayer[y*pTileLayer->m_Width + X1].IndexBufferByteOffset() - Visuals.m_TilesOfLayer[y*pTileLayer->m_Width + X0].IndexBufferByteOffset()) / sizeof(unsigned int)) + (Visuals.m_TilesOfLayer[y*pTileLayer->m_Width + X1].DoDraw() ? 6lu : 0lu);
|
|
|
|
if(NumVertices)
|
|
{
|
|
s_IndexOffsets.push_back((offset_ptr_size)Visuals.m_TilesOfLayer[y*pTileLayer->m_Width + X0].IndexBufferByteOffset());
|
|
s_DrawCounts.push_back(NumVertices);
|
|
}
|
|
}
|
|
|
|
pColor->x *= r;
|
|
pColor->y *= g;
|
|
pColor->z *= b;
|
|
pColor->w *= a;
|
|
|
|
int DrawCount = s_IndexOffsets.size();
|
|
if(DrawCount != 0)
|
|
{
|
|
Graphics()->RenderTileLayer(Visuals.m_BufferContainerIndex, (float*)pColor, &s_IndexOffsets[0], &s_DrawCounts[0], DrawCount);
|
|
}
|
|
}
|
|
|
|
if(DrawBorder)
|
|
RenderTileBorder(LayerIndex, pColor, pTileLayer, pGroup, BorderX0, BorderY0, BorderX1, BorderY1, (int)(-floorf((-ScreenX1) / 32.f)) - BorderX0, (int)(-floorf((-ScreenY1) / 32.f)) - BorderY0);
|
|
}
|
|
|
|
void CMapLayers::RenderTileBorderCornerTiles(int WidthOffsetToOrigin, int HeightOffsetToOrigin, int TileCountWidth, int TileCountHeight, int BufferContainerIndex, float* pColor, offset_ptr_size IndexBufferOffset, float* pOffset, float* pDir)
|
|
{
|
|
// if border is still in range of the original corner, it doesn't needs to be redrawn
|
|
bool CornerVisible = (WidthOffsetToOrigin - 1 < TileCountWidth) && (HeightOffsetToOrigin - 1 < TileCountHeight);
|
|
|
|
int CountX = minimum(WidthOffsetToOrigin, TileCountWidth);
|
|
int CountY = minimum(HeightOffsetToOrigin, TileCountHeight);
|
|
|
|
int Count = (CountX * CountY) - (CornerVisible ? 1 : 0); // Don't draw the corner again
|
|
|
|
Graphics()->RenderBorderTiles(BufferContainerIndex, pColor, IndexBufferOffset, pOffset, pDir, CountX, Count);
|
|
}
|
|
|
|
void CMapLayers::RenderTileBorder(int LayerIndex, ColorRGBA* pColor, CMapItemLayerTilemap* pTileLayer, CMapItemGroup* pGroup, int BorderX0, int BorderY0, int BorderX1, int BorderY1, int ScreenWidthTileCount, int ScreenHeightTileCount)
|
|
{
|
|
STileLayerVisuals& Visuals = *m_TileLayerVisuals[LayerIndex];
|
|
|
|
int Y0 = BorderY0;
|
|
int X0 = BorderX0;
|
|
int Y1 = BorderY1;
|
|
int X1 = BorderX1;
|
|
|
|
int CountWidth = ScreenWidthTileCount;
|
|
int CountHeight = ScreenHeightTileCount;
|
|
|
|
if(X0 < 1)
|
|
X0 = 1;
|
|
if(Y0 < 1)
|
|
Y0 = 1;
|
|
if(X1 >= pTileLayer->m_Width - 1)
|
|
X1 = pTileLayer->m_Width - 2;
|
|
if(Y1 >= pTileLayer->m_Height - 1)
|
|
Y1 = pTileLayer->m_Height - 2;
|
|
|
|
if(BorderX0 <= 0)
|
|
{
|
|
// Draw corners on left side
|
|
if(BorderY0 <= 0)
|
|
{
|
|
if(Visuals.m_BorderTopLeft.DoDraw())
|
|
{
|
|
vec2 Offset;
|
|
Offset.x = BorderX0 * 32.f;
|
|
Offset.y = BorderY0 * 32.f;
|
|
vec2 Dir;
|
|
Dir.x = 32.f;
|
|
Dir.y = 32.f;
|
|
|
|
RenderTileBorderCornerTiles(absolute(BorderX0) + 1, absolute(BorderY0) + 1, CountWidth, CountHeight, Visuals.m_BufferContainerIndex, (float*)pColor, (offset_ptr_size)Visuals.m_BorderTopLeft.IndexBufferByteOffset(), (float*)&Offset, (float*)&Dir);
|
|
}
|
|
}
|
|
if(BorderY1 >= pTileLayer->m_Height - 1)
|
|
{
|
|
if(Visuals.m_BorderBottomLeft.DoDraw())
|
|
{
|
|
vec2 Offset;
|
|
Offset.x = BorderX0 * 32.f;
|
|
Offset.y = (BorderY1 - (pTileLayer->m_Height - 1)) * 32.f;
|
|
vec2 Dir;
|
|
Dir.x = 32.f;
|
|
Dir.y = -32.f;
|
|
|
|
RenderTileBorderCornerTiles(absolute(BorderX0) + 1, (BorderY1 - (pTileLayer->m_Height - 1)) + 1, CountWidth, CountHeight, Visuals.m_BufferContainerIndex, (float*)pColor, (offset_ptr_size)Visuals.m_BorderBottomLeft.IndexBufferByteOffset(), (float*)&Offset, (float*)&Dir);
|
|
}
|
|
}
|
|
}
|
|
if(BorderX0 < 0)
|
|
{
|
|
// Draw left border
|
|
if(Y0 < pTileLayer->m_Height - 1 && Y1 > 0)
|
|
{
|
|
unsigned int DrawNum = ((Visuals.m_BorderLeft[Y1 - 1].IndexBufferByteOffset() - Visuals.m_BorderLeft[Y0 - 1].IndexBufferByteOffset()) / sizeof(unsigned int)) + (Visuals.m_BorderLeft[Y1 - 1].DoDraw() ? 6lu : 0lu);
|
|
offset_ptr_size pOffset = (offset_ptr_size)Visuals.m_BorderLeft[Y0-1].IndexBufferByteOffset();
|
|
vec2 Offset;
|
|
Offset.x = 32.f * BorderX0;
|
|
Offset.y = 0.f;
|
|
vec2 Dir;
|
|
Dir.x = 32.f;
|
|
Dir.y = 0.f;
|
|
Graphics()->RenderBorderTileLines(Visuals.m_BufferContainerIndex, (float*)pColor, pOffset, (float*)&Offset, (float*)&Dir, DrawNum, minimum(absolute(BorderX0), CountWidth));
|
|
}
|
|
}
|
|
|
|
if(BorderX1 >= pTileLayer->m_Width - 1)
|
|
{
|
|
// Draw corners on right side
|
|
if(BorderY0 <= 0)
|
|
{
|
|
if(Visuals.m_BorderTopRight.DoDraw())
|
|
{
|
|
vec2 Offset;
|
|
Offset.x = (BorderX1 - (pTileLayer->m_Width - 1)) * 32.f;
|
|
Offset.y = BorderY0 * 32.f;
|
|
vec2 Dir;
|
|
Dir.x = -32.f;
|
|
Dir.y = 32.f;
|
|
|
|
RenderTileBorderCornerTiles((BorderX1 - (pTileLayer->m_Width - 1)) + 1, absolute(BorderY0) + 1, CountWidth, CountHeight, Visuals.m_BufferContainerIndex, (float*)pColor, (offset_ptr_size)Visuals.m_BorderTopRight.IndexBufferByteOffset(), (float*)&Offset, (float*)&Dir);
|
|
}
|
|
}
|
|
if(BorderY1 >= pTileLayer->m_Height - 1)
|
|
{
|
|
if(Visuals.m_BorderBottomRight.DoDraw())
|
|
{
|
|
vec2 Offset;
|
|
Offset.x = (BorderX1 - (pTileLayer->m_Width - 1)) * 32.f;
|
|
Offset.y = (BorderY1 - (pTileLayer->m_Height - 1)) * 32.f;
|
|
vec2 Dir;
|
|
Dir.x = -32.f;
|
|
Dir.y = -32.f;
|
|
|
|
RenderTileBorderCornerTiles((BorderX1 - (pTileLayer->m_Width - 1)) + 1, (BorderY1 - (pTileLayer->m_Height - 1)) + 1, CountWidth, CountHeight, Visuals.m_BufferContainerIndex, (float*)pColor, (offset_ptr_size)Visuals.m_BorderBottomRight.IndexBufferByteOffset(), (float*)&Offset, (float*)&Dir);
|
|
}
|
|
}
|
|
}
|
|
if(BorderX1 > pTileLayer->m_Width - 1)
|
|
{
|
|
// Draw right border
|
|
if(Y0 < pTileLayer->m_Height - 1 && Y1 > 0)
|
|
{
|
|
unsigned int DrawNum = ((Visuals.m_BorderRight[Y1 - 1].IndexBufferByteOffset() - Visuals.m_BorderRight[Y0 - 1].IndexBufferByteOffset()) / sizeof(unsigned int)) + (Visuals.m_BorderRight[Y1 - 1].DoDraw() ? 6lu : 0lu);
|
|
offset_ptr_size pOffset = (offset_ptr_size)Visuals.m_BorderRight[Y0-1].IndexBufferByteOffset();
|
|
vec2 Offset;
|
|
Offset.x = 32.f * (BorderX1 - (pTileLayer->m_Width - 1));
|
|
Offset.y = 0.f;
|
|
vec2 Dir;
|
|
Dir.x = -32.f;
|
|
Dir.y = 0.f;
|
|
Graphics()->RenderBorderTileLines(Visuals.m_BufferContainerIndex, (float*)pColor, pOffset, (float*)&Offset, (float*)&Dir, DrawNum, minimum((BorderX1 - (pTileLayer->m_Width - 1)), CountWidth));
|
|
}
|
|
}
|
|
if(BorderY0 < 0)
|
|
{
|
|
// Draw top border
|
|
if(X0 < pTileLayer->m_Width - 1 && X1 > 0)
|
|
{
|
|
unsigned int DrawNum = ((Visuals.m_BorderTop[X1 - 1].IndexBufferByteOffset() - Visuals.m_BorderTop[X0 - 1].IndexBufferByteOffset()) / sizeof(unsigned int)) + (Visuals.m_BorderTop[X1 - 1].DoDraw() ? 6lu : 0lu);
|
|
offset_ptr_size pOffset = (offset_ptr_size)Visuals.m_BorderTop[X0-1].IndexBufferByteOffset();
|
|
vec2 Offset;
|
|
Offset.x = 0.f;
|
|
Offset.y = 32.f * BorderY0;
|
|
vec2 Dir;
|
|
Dir.x = 0.f;
|
|
Dir.y = 32.f;
|
|
Graphics()->RenderBorderTileLines(Visuals.m_BufferContainerIndex, (float*)pColor, pOffset, (float*)&Offset, (float*)&Dir, DrawNum, minimum(absolute(BorderY0), CountHeight));
|
|
}
|
|
}
|
|
if(BorderY1 >= pTileLayer->m_Height)
|
|
{
|
|
// Draw bottom border
|
|
if(X0 < pTileLayer->m_Width - 1 && X1 > 0)
|
|
{
|
|
unsigned int DrawNum = ((Visuals.m_BorderBottom[X1 - 1].IndexBufferByteOffset() - Visuals.m_BorderBottom[X0 - 1].IndexBufferByteOffset()) / sizeof(unsigned int)) + (Visuals.m_BorderBottom[X1 - 1].DoDraw() ? 6lu : 0lu);
|
|
offset_ptr_size pOffset = (offset_ptr_size)Visuals.m_BorderBottom[X0-1].IndexBufferByteOffset();
|
|
vec2 Offset;
|
|
Offset.x = 0.f;
|
|
Offset.y = 32.f * (BorderY1 - (pTileLayer->m_Height - 1));
|
|
vec2 Dir;
|
|
Dir.x = 0.f;
|
|
Dir.y = -32.f;
|
|
Graphics()->RenderBorderTileLines(Visuals.m_BufferContainerIndex, (float*)pColor, pOffset, (float*)&Offset, (float*)&Dir, DrawNum, minimum((BorderY1 - (pTileLayer->m_Height - 1)), CountHeight));
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMapLayers::RenderKillTileBorder(int LayerIndex, ColorRGBA* pColor, CMapItemLayerTilemap* pTileLayer, CMapItemGroup* pGroup)
|
|
{
|
|
STileLayerVisuals& Visuals = *m_TileLayerVisuals[LayerIndex];
|
|
if(Visuals.m_BufferContainerIndex == -1) return; //no visuals were created
|
|
|
|
float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
|
|
Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1);
|
|
|
|
bool DrawBorder = false;
|
|
|
|
int BorderY0 = (int)(ScreenY0/32)-1;
|
|
int BorderX0 = (int)(ScreenX0/32)-1;
|
|
int BorderY1 = (int)(ScreenY1/32)+1;
|
|
int BorderX1 = (int)(ScreenX1/32)+1;
|
|
|
|
if(BorderX0 < -201)
|
|
DrawBorder = true;
|
|
if(BorderY0 < -201)
|
|
DrawBorder = true;
|
|
if(BorderX1 >= pTileLayer->m_Width + 201)
|
|
DrawBorder = true;
|
|
if(BorderY1 >= pTileLayer->m_Height + 201)
|
|
DrawBorder = true;
|
|
|
|
if(!DrawBorder)
|
|
return;
|
|
if(!Visuals.m_BorderKillTile.DoDraw())
|
|
return;
|
|
|
|
if(BorderX0 < -300)
|
|
BorderX0 = -300;
|
|
if(BorderY0 < -300)
|
|
BorderY0 = -300;
|
|
if(BorderX1 >= pTileLayer->m_Width + 300)
|
|
BorderX1 = pTileLayer->m_Width + 299;
|
|
if(BorderY1 >= pTileLayer->m_Height + 300)
|
|
BorderY1 = pTileLayer->m_Height + 299;
|
|
|
|
if(BorderX1 < -300)
|
|
BorderX1 = -300;
|
|
if(BorderY1 < -300)
|
|
BorderY1 = -300;
|
|
if(BorderX0 >= pTileLayer->m_Width + 300)
|
|
BorderX0 = pTileLayer->m_Width + 299;
|
|
if(BorderY0 >= pTileLayer->m_Height + 300)
|
|
BorderY0 = pTileLayer->m_Height + 299;
|
|
|
|
// Draw left kill tile border
|
|
if(BorderX0 < -201)
|
|
{
|
|
vec2 Offset;
|
|
Offset.x = BorderX0 * 32.f;
|
|
Offset.y = BorderY0 * 32.f;
|
|
vec2 Dir;
|
|
Dir.x = 32.f;
|
|
Dir.y = 32.f;
|
|
|
|
int Count = (absolute(BorderX0) - 201) * (BorderY1 - BorderY0);
|
|
|
|
Graphics()->RenderBorderTiles(Visuals.m_BufferContainerIndex, (float*)pColor, (offset_ptr_size)Visuals.m_BorderKillTile.IndexBufferByteOffset(), (float*)&Offset, (float*)&Dir, (absolute(BorderX0) - 201), Count);
|
|
}
|
|
// Draw top kill tile border
|
|
if(BorderY0 < -201)
|
|
{
|
|
vec2 Offset;
|
|
int OffX0 = (BorderX0 < -201 ? -201 : BorderX0);
|
|
int OffX1 = (BorderX1 >= pTileLayer->m_Width + 201 ? pTileLayer->m_Width + 201 : BorderX1);
|
|
Offset.x = OffX0 * 32.f;
|
|
Offset.y = BorderY0 * 32.f;
|
|
vec2 Dir;
|
|
Dir.x = 32.f;
|
|
Dir.y = 32.f;
|
|
|
|
int Count = (OffX1 - OffX0) * (absolute(BorderY0)-201);
|
|
|
|
Graphics()->RenderBorderTiles(Visuals.m_BufferContainerIndex, (float*)pColor, (offset_ptr_size)Visuals.m_BorderKillTile.IndexBufferByteOffset(), (float*)&Offset, (float*)&Dir, (OffX1 - OffX0), Count);
|
|
}
|
|
if(BorderX1 >= pTileLayer->m_Width + 201)
|
|
{
|
|
vec2 Offset;
|
|
Offset.x = (pTileLayer->m_Width + 201) * 32.f;
|
|
Offset.y = BorderY0 * 32.f;
|
|
vec2 Dir;
|
|
Dir.x = 32.f;
|
|
Dir.y = 32.f;
|
|
|
|
int Count = (BorderX1 - (pTileLayer->m_Width + 201)) * (BorderY1 - BorderY0);
|
|
|
|
Graphics()->RenderBorderTiles(Visuals.m_BufferContainerIndex, (float*)pColor, (offset_ptr_size)Visuals.m_BorderKillTile.IndexBufferByteOffset(), (float*)&Offset, (float*)&Dir, (BorderX1 - (pTileLayer->m_Width + 201)), Count);
|
|
}
|
|
if(BorderY1 >= pTileLayer->m_Height + 201)
|
|
{
|
|
vec2 Offset;
|
|
int OffX0 = (BorderX0 < -201 ? -201 : BorderX0);
|
|
int OffX1 = (BorderX1 >= pTileLayer->m_Width + 201 ? pTileLayer->m_Width + 201 : BorderX1);
|
|
Offset.x = OffX0 * 32.f;
|
|
Offset.y = (pTileLayer->m_Height + 201) * 32.f;
|
|
vec2 Dir;
|
|
Dir.x = 32.f;
|
|
Dir.y = 32.f;
|
|
|
|
int Count = (OffX1 - OffX0) * (BorderY1-(pTileLayer->m_Height + 201));
|
|
|
|
Graphics()->RenderBorderTiles(Visuals.m_BufferContainerIndex, (float*)pColor, (offset_ptr_size)Visuals.m_BorderKillTile.IndexBufferByteOffset(), (float*)&Offset, (float*)&Dir, (OffX1 - OffX0), Count);
|
|
}
|
|
}
|
|
|
|
void CMapLayers::RenderQuadLayer(int LayerIndex, CMapItemLayerQuads* pQuadLayer, CMapItemGroup* pGroup, bool Force)
|
|
{
|
|
SQuadLayerVisuals& Visuals = *m_QuadLayerVisuals[LayerIndex];
|
|
if(Visuals.m_BufferContainerIndex == -1)
|
|
return; //no visuals were created
|
|
|
|
if(!Force && (!g_Config.m_ClShowQuads || g_Config.m_ClOverlayEntities == 100))
|
|
return;
|
|
|
|
CQuad *pQuads = (CQuad *)m_pLayers->Map()->GetDataSwapped(pQuadLayer->m_Data);
|
|
|
|
static std::vector<SQuadRenderInfo> s_QuadRenderInfo;
|
|
|
|
s_QuadRenderInfo.resize(pQuadLayer->m_NumQuads);
|
|
for(int i = 0; i < pQuadLayer->m_NumQuads; ++i)
|
|
{
|
|
CQuad *q = &pQuads[i];
|
|
|
|
float aColor[4];
|
|
aColor[0] = aColor[1] = aColor[2] = aColor[3] = 1.f;
|
|
if(q->m_ColorEnv >= 0)
|
|
{
|
|
EnvelopeEval(q->m_ColorEnvOffset / 1000.0f, q->m_ColorEnv, aColor, this);
|
|
}
|
|
|
|
float OffsetX = 0;
|
|
float OffsetY = 0;
|
|
float Rot = 0;
|
|
|
|
if(q->m_PosEnv >= 0)
|
|
{
|
|
float aChannels[4];
|
|
EnvelopeEval(q->m_PosEnvOffset / 1000.0f, q->m_PosEnv, aChannels, this);
|
|
OffsetX = aChannels[0];
|
|
OffsetY = aChannels[1];
|
|
Rot = aChannels[2] / 180.0f*pi;
|
|
}
|
|
|
|
SQuadRenderInfo& QInfo = s_QuadRenderInfo[i];
|
|
mem_copy(QInfo.m_aColor, aColor, sizeof(aColor));
|
|
QInfo.m_aOffsets[0] = OffsetX;
|
|
QInfo.m_aOffsets[1] = OffsetY;
|
|
QInfo.m_Rotation = Rot;
|
|
}
|
|
Graphics()->RenderQuadLayer(Visuals.m_BufferContainerIndex, &s_QuadRenderInfo[0], pQuadLayer->m_NumQuads);
|
|
}
|
|
|
|
void CMapLayers::LayersOfGroupCount(CMapItemGroup* pGroup, int& TileLayerCount, int& QuadLayerCount, bool& PassedGameLayer)
|
|
{
|
|
int TileLayerCounter = 0;
|
|
int QuadLayerCounter = 0;
|
|
for(int l = 0; l < pGroup->m_NumLayers; l++)
|
|
{
|
|
CMapItemLayer *pLayer = m_pLayers->GetLayer(pGroup->m_StartLayer+l);
|
|
bool IsFrontLayer = false;
|
|
bool IsSwitchLayer = false;
|
|
bool IsTeleLayer = false;
|
|
bool IsSpeedupLayer = false;
|
|
bool IsTuneLayer = false;
|
|
|
|
if(pLayer == (CMapItemLayer*)m_pLayers->GameLayer())
|
|
{
|
|
PassedGameLayer = true;
|
|
}
|
|
|
|
if(pLayer == (CMapItemLayer*)m_pLayers->FrontLayer())
|
|
IsFrontLayer = true;
|
|
|
|
if(pLayer == (CMapItemLayer*)m_pLayers->SwitchLayer())
|
|
IsSwitchLayer = true;
|
|
|
|
if(pLayer == (CMapItemLayer*)m_pLayers->TeleLayer())
|
|
IsTeleLayer = true;
|
|
|
|
if(pLayer == (CMapItemLayer*)m_pLayers->SpeedupLayer())
|
|
IsSpeedupLayer = true;
|
|
|
|
if(pLayer == (CMapItemLayer*)m_pLayers->TuneLayer())
|
|
IsTuneLayer = true;
|
|
|
|
|
|
if(m_Type <= TYPE_BACKGROUND_FORCE)
|
|
{
|
|
if(PassedGameLayer)
|
|
break;
|
|
}
|
|
else if(m_Type == TYPE_FOREGROUND)
|
|
{
|
|
if(!PassedGameLayer)
|
|
continue;
|
|
}
|
|
|
|
if(pLayer->m_Type == LAYERTYPE_TILES)
|
|
{
|
|
CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer;
|
|
int DataIndex = 0;
|
|
unsigned int TileSize = 0;
|
|
int TileLayerAndOverlayCount = 0;
|
|
if(IsFrontLayer)
|
|
{
|
|
DataIndex = pTMap->m_Front;
|
|
TileSize = sizeof(CTile);
|
|
TileLayerAndOverlayCount = 1;
|
|
}
|
|
else if(IsSwitchLayer)
|
|
{
|
|
DataIndex = pTMap->m_Switch;
|
|
TileSize = sizeof(CSwitchTile);
|
|
TileLayerAndOverlayCount = 3;
|
|
}
|
|
else if(IsTeleLayer)
|
|
{
|
|
DataIndex = pTMap->m_Tele;
|
|
TileSize = sizeof(CTeleTile);
|
|
TileLayerAndOverlayCount = 2;
|
|
}
|
|
else if(IsSpeedupLayer)
|
|
{
|
|
DataIndex = pTMap->m_Speedup;
|
|
TileSize = sizeof(CSpeedupTile);
|
|
TileLayerAndOverlayCount = 3;
|
|
}
|
|
else if(IsTuneLayer)
|
|
{
|
|
DataIndex = pTMap->m_Tune;
|
|
TileSize = sizeof(CTuneTile);
|
|
TileLayerAndOverlayCount = 1;
|
|
}
|
|
else
|
|
{
|
|
DataIndex = pTMap->m_Data;
|
|
TileSize = sizeof(CTile);
|
|
TileLayerAndOverlayCount = 1;
|
|
}
|
|
|
|
unsigned int Size = m_pLayers->Map()->GetDataSize(DataIndex);
|
|
if(Size >= pTMap->m_Width*pTMap->m_Height*TileSize)
|
|
{
|
|
TileLayerCounter += TileLayerAndOverlayCount;
|
|
}
|
|
}
|
|
else if(pLayer->m_Type == LAYERTYPE_QUADS)
|
|
{
|
|
++QuadLayerCounter;
|
|
}
|
|
}
|
|
|
|
TileLayerCount += TileLayerCounter;
|
|
QuadLayerCount += QuadLayerCounter;
|
|
}
|
|
|
|
void CMapLayers::OnRender()
|
|
{
|
|
if(Client()->State() != IClient::STATE_ONLINE && Client()->State() != IClient::STATE_DEMOPLAYBACK)
|
|
return;
|
|
|
|
CUIRect Screen;
|
|
Graphics()->GetScreen(&Screen.x, &Screen.y, &Screen.w, &Screen.h);
|
|
|
|
vec2 Center = m_pClient->m_pCamera->m_Center;
|
|
|
|
bool PassedGameLayer = false;
|
|
int TileLayerCounter = 0;
|
|
int QuadLayerCounter = 0;
|
|
|
|
for(int g = 0; g < m_pLayers->NumGroups(); g++)
|
|
{
|
|
CMapItemGroup *pGroup = m_pLayers->GetGroup(g);
|
|
|
|
if(!pGroup)
|
|
{
|
|
dbg_msg("maplayers", "error group was null, group number = %d, total groups = %d", g, m_pLayers->NumGroups());
|
|
dbg_msg("maplayers", "this is here to prevent a crash but the source of this is unknown, please report this for it to get fixed");
|
|
dbg_msg("maplayers", "we need mapname and crc and the map that caused this if possible, and anymore info you think is relevant");
|
|
continue;
|
|
}
|
|
|
|
if(!g_Config.m_GfxNoclip && pGroup->m_Version >= 2 && pGroup->m_UseClipping)
|
|
{
|
|
// set clipping
|
|
float Points[4];
|
|
MapScreenToGroup(Center.x, Center.y, m_pLayers->GameGroup(), m_pClient->m_pCamera->m_Zoom);
|
|
Graphics()->GetScreen(&Points[0], &Points[1], &Points[2], &Points[3]);
|
|
float x0 = (pGroup->m_ClipX - Points[0]) / (Points[2]-Points[0]);
|
|
float y0 = (pGroup->m_ClipY - Points[1]) / (Points[3]-Points[1]);
|
|
float x1 = ((pGroup->m_ClipX+pGroup->m_ClipW) - Points[0]) / (Points[2]-Points[0]);
|
|
float y1 = ((pGroup->m_ClipY+pGroup->m_ClipH) - Points[1]) / (Points[3]-Points[1]);
|
|
|
|
if(x1 < 0.0f || x0 > 1.0f || y1 < 0.0f || y0 > 1.0f)
|
|
{
|
|
//check tile layer count of this group
|
|
LayersOfGroupCount(pGroup, TileLayerCounter, QuadLayerCounter, PassedGameLayer);
|
|
continue;
|
|
}
|
|
|
|
Graphics()->ClipEnable((int)(x0*Graphics()->ScreenWidth()), (int)(y0*Graphics()->ScreenHeight()),
|
|
(int)((x1-x0)*Graphics()->ScreenWidth()), (int)((y1-y0)*Graphics()->ScreenHeight()));
|
|
}
|
|
|
|
if(!g_Config.m_ClZoomBackgroundLayers && !pGroup->m_ParallaxX && !pGroup->m_ParallaxY)
|
|
{
|
|
MapScreenToGroup(Center.x, Center.y, pGroup, 1.0);
|
|
} else
|
|
MapScreenToGroup(Center.x, Center.y, pGroup, m_pClient->m_pCamera->m_Zoom);
|
|
|
|
for(int l = 0; l < pGroup->m_NumLayers; l++)
|
|
{
|
|
CMapItemLayer *pLayer = m_pLayers->GetLayer(pGroup->m_StartLayer+l);
|
|
bool Render = false;
|
|
bool IsGameLayer = false;
|
|
bool IsFrontLayer = false;
|
|
bool IsSwitchLayer = false;
|
|
bool IsTeleLayer = false;
|
|
bool IsSpeedupLayer = false;
|
|
bool IsTuneLayer = false;
|
|
bool IsEntityLayer = false;
|
|
|
|
if(pLayer == (CMapItemLayer*)m_pLayers->GameLayer())
|
|
{
|
|
IsEntityLayer = IsGameLayer = true;
|
|
PassedGameLayer = true;
|
|
}
|
|
|
|
if(pLayer == (CMapItemLayer*)m_pLayers->FrontLayer())
|
|
IsEntityLayer = IsFrontLayer = true;
|
|
|
|
if(pLayer == (CMapItemLayer*)m_pLayers->SwitchLayer())
|
|
IsEntityLayer = IsSwitchLayer = true;
|
|
|
|
if(pLayer == (CMapItemLayer*)m_pLayers->TeleLayer())
|
|
IsEntityLayer = IsTeleLayer = true;
|
|
|
|
if(pLayer == (CMapItemLayer*)m_pLayers->SpeedupLayer())
|
|
IsEntityLayer = IsSpeedupLayer = true;
|
|
|
|
if(pLayer == (CMapItemLayer*)m_pLayers->TuneLayer())
|
|
IsEntityLayer = IsTuneLayer = true;
|
|
|
|
if(m_Type == -1)
|
|
Render = true;
|
|
else if(m_Type <= TYPE_BACKGROUND_FORCE)
|
|
{
|
|
if(PassedGameLayer)
|
|
return;
|
|
Render = true;
|
|
|
|
if(m_Type == TYPE_BACKGROUND_FORCE)
|
|
{
|
|
if(pLayer->m_Type == LAYERTYPE_TILES && !g_Config.m_ClBackgroundShowTilesLayers)
|
|
continue;
|
|
}
|
|
}
|
|
else // TYPE_FOREGROUND
|
|
{
|
|
if(PassedGameLayer && !IsGameLayer)
|
|
Render = true;
|
|
}
|
|
|
|
if(Render && pLayer->m_Type == LAYERTYPE_TILES && Input()->KeyIsPressed(KEY_LCTRL) && Input()->KeyIsPressed(KEY_LSHIFT) && Input()->KeyPress(KEY_KP_0))
|
|
{
|
|
CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer;
|
|
CTile *pTiles = (CTile *)m_pLayers->Map()->GetData(pTMap->m_Data);
|
|
CServerInfo CurrentServerInfo;
|
|
Client()->GetServerInfo(&CurrentServerInfo);
|
|
char aFilename[256];
|
|
str_format(aFilename, sizeof(aFilename), "dumps/tilelayer_dump_%s-%d-%d-%dx%d.txt", CurrentServerInfo.m_aMap, g, l, pTMap->m_Width, pTMap->m_Height);
|
|
IOHANDLE File = Storage()->OpenFile(aFilename, IOFLAG_WRITE, IStorage::TYPE_SAVE);
|
|
if(File)
|
|
{
|
|
for(int y = 0; y < pTMap->m_Height; y++)
|
|
{
|
|
for(int x = 0; x < pTMap->m_Width; x++)
|
|
io_write(File, &(pTiles[y*pTMap->m_Width + x].m_Index), sizeof(pTiles[y*pTMap->m_Width + x].m_Index));
|
|
io_write_newline(File);
|
|
}
|
|
io_close(File);
|
|
}
|
|
}
|
|
|
|
if((Render || IsGameLayer) && pLayer->m_Type == LAYERTYPE_TILES)
|
|
{
|
|
CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer;
|
|
int DataIndex = 0;
|
|
unsigned int TileSize = 0;
|
|
int TileLayerAndOverlayCount = 0;
|
|
if(IsFrontLayer)
|
|
{
|
|
DataIndex = pTMap->m_Front;
|
|
TileSize = sizeof(CTile);
|
|
TileLayerAndOverlayCount = 1;
|
|
}
|
|
else if(IsSwitchLayer)
|
|
{
|
|
DataIndex = pTMap->m_Switch;
|
|
TileSize = sizeof(CSwitchTile);
|
|
TileLayerAndOverlayCount = 3;
|
|
}
|
|
else if(IsTeleLayer)
|
|
{
|
|
DataIndex = pTMap->m_Tele;
|
|
TileSize = sizeof(CTeleTile);
|
|
TileLayerAndOverlayCount = 2;
|
|
}
|
|
else if(IsSpeedupLayer)
|
|
{
|
|
DataIndex = pTMap->m_Speedup;
|
|
TileSize = sizeof(CSpeedupTile);
|
|
TileLayerAndOverlayCount = 3;
|
|
}
|
|
else if(IsTuneLayer)
|
|
{
|
|
DataIndex = pTMap->m_Tune;
|
|
TileSize = sizeof(CTuneTile);
|
|
TileLayerAndOverlayCount = 1;
|
|
}
|
|
else
|
|
{
|
|
DataIndex = pTMap->m_Data;
|
|
TileSize = sizeof(CTile);
|
|
TileLayerAndOverlayCount = 1;
|
|
}
|
|
|
|
unsigned int Size = m_pLayers->Map()->GetDataSize(DataIndex);
|
|
if(Size >= pTMap->m_Width*pTMap->m_Height*TileSize)
|
|
{
|
|
TileLayerCounter += TileLayerAndOverlayCount;
|
|
}
|
|
}
|
|
else if(Render && pLayer->m_Type == LAYERTYPE_QUADS)
|
|
{
|
|
++QuadLayerCounter;
|
|
}
|
|
|
|
// skip rendering if detail layers if not wanted, or is entity layer and we are a background map
|
|
if((pLayer->m_Flags&LAYERFLAG_DETAIL && !g_Config.m_GfxHighDetail && !IsGameLayer) || (m_Type == TYPE_BACKGROUND_FORCE && IsEntityLayer))
|
|
continue;
|
|
|
|
if((Render && g_Config.m_ClOverlayEntities < 100 && !IsGameLayer && !IsFrontLayer && !IsSwitchLayer && !IsTeleLayer && !IsSpeedupLayer && !IsTuneLayer) || (g_Config.m_ClOverlayEntities && IsGameLayer) || (m_Type == TYPE_BACKGROUND_FORCE))
|
|
{
|
|
if(pLayer->m_Type == LAYERTYPE_TILES)
|
|
{
|
|
CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer;
|
|
if(pTMap->m_Image == -1)
|
|
{
|
|
if(!IsGameLayer)
|
|
Graphics()->TextureSet(-1);
|
|
else
|
|
Graphics()->TextureSet(m_pImages->GetEntities());
|
|
}
|
|
else
|
|
Graphics()->TextureSet(m_pImages->Get(pTMap->m_Image));
|
|
|
|
CTile *pTiles = (CTile *)m_pLayers->Map()->GetData(pTMap->m_Data);
|
|
unsigned int Size = m_pLayers->Map()->GetDataSize(pTMap->m_Data);
|
|
|
|
if(Size >= pTMap->m_Width*pTMap->m_Height*sizeof(CTile))
|
|
{
|
|
ColorRGBA Color = ColorRGBA(pTMap->m_Color.r/255.0f, pTMap->m_Color.g/255.0f, pTMap->m_Color.b/255.0f, pTMap->m_Color.a/255.0f);
|
|
if(IsGameLayer && g_Config.m_ClOverlayEntities)
|
|
Color = ColorRGBA(pTMap->m_Color.r/255.0f, pTMap->m_Color.g/255.0f, pTMap->m_Color.b/255.0f, pTMap->m_Color.a/255.0f*g_Config.m_ClOverlayEntities/100.0f);
|
|
else if(!IsGameLayer && g_Config.m_ClOverlayEntities && !(m_Type == TYPE_BACKGROUND_FORCE))
|
|
Color = ColorRGBA(pTMap->m_Color.r/255.0f, pTMap->m_Color.g/255.0f, pTMap->m_Color.b/255.0f, pTMap->m_Color.a/255.0f*(100-g_Config.m_ClOverlayEntities)/100.0f);
|
|
if(!Graphics()->IsBufferingEnabled())
|
|
{
|
|
Graphics()->BlendNone();
|
|
RenderTools()->RenderTilemap(pTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_OPAQUE,
|
|
EnvelopeEval, this, pTMap->m_ColorEnv, pTMap->m_ColorEnvOffset);
|
|
|
|
Graphics()->BlendNormal();
|
|
|
|
// draw kill tiles outside the entity clipping rectangle
|
|
if(IsGameLayer)
|
|
{
|
|
// slow blinking to hint that it's not a part of the map
|
|
double Seconds = time_get()/(double)time_freq();
|
|
ColorRGBA ColorHint = ColorRGBA(1.0f, 1.0f, 1.0f, 0.3f + 0.7f*(1.0+sin(2.0f*pi*Seconds/3.f))/2.0f);
|
|
|
|
RenderTools()->RenderTileRectangle(-201, -201, pTMap->m_Width+402, pTMap->m_Height+402,
|
|
0, TILE_DEATH, // display air inside, death outside
|
|
32.0f, Color.v4()*ColorHint.v4(), TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_TRANSPARENT,
|
|
EnvelopeEval, this, pTMap->m_ColorEnv, pTMap->m_ColorEnvOffset);
|
|
}
|
|
|
|
RenderTools()->RenderTilemap(pTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_TRANSPARENT,
|
|
EnvelopeEval, this, pTMap->m_ColorEnv, pTMap->m_ColorEnvOffset);
|
|
} else
|
|
{
|
|
Graphics()->BlendNormal();
|
|
// draw kill tiles outside the entity clipping rectangle
|
|
if(IsGameLayer)
|
|
{
|
|
// slow blinking to hint that it's not a part of the map
|
|
double Seconds = time_get() / (double)time_freq();
|
|
ColorRGBA ColorHint = ColorRGBA(1.0f, 1.0f, 1.0f, 0.3f + 0.7f*(1.0 + sin(2.0f*pi*Seconds / 3.f)) / 2.0f);
|
|
|
|
ColorRGBA ColorKill(Color.x*ColorHint.x,Color.y*ColorHint.y,Color.z*ColorHint.z,Color.w*ColorHint.w);
|
|
RenderKillTileBorder(TileLayerCounter-1, &ColorKill, pTMap, pGroup);
|
|
}
|
|
RenderTileLayer(TileLayerCounter-1, &Color, pTMap, pGroup);
|
|
}
|
|
}
|
|
}
|
|
else if(pLayer->m_Type == LAYERTYPE_QUADS)
|
|
{
|
|
CMapItemLayerQuads *pQLayer = (CMapItemLayerQuads *)pLayer;
|
|
if(pQLayer->m_Image == -1)
|
|
Graphics()->TextureSet(-1);
|
|
else
|
|
Graphics()->TextureSet(m_pImages->Get(pQLayer->m_Image));
|
|
|
|
CQuad *pQuads = (CQuad *)m_pLayers->Map()->GetDataSwapped(pQLayer->m_Data);
|
|
if(m_Type == TYPE_BACKGROUND_FORCE)
|
|
{
|
|
if(g_Config.m_ClShowQuads)
|
|
{
|
|
if(!Graphics()->IsBufferingEnabled())
|
|
{
|
|
//Graphics()->BlendNone();
|
|
//RenderTools()->ForceRenderQuads(pQuads, pQLayer->m_NumQuads, LAYERRENDERFLAG_OPAQUE, EnvelopeEval, this, 1.f);
|
|
Graphics()->BlendNormal();
|
|
RenderTools()->ForceRenderQuads(pQuads, pQLayer->m_NumQuads, LAYERRENDERFLAG_TRANSPARENT, EnvelopeEval, this, 1.f);
|
|
}
|
|
else
|
|
{
|
|
RenderQuadLayer(QuadLayerCounter-1, pQLayer, pGroup, true);
|
|
}
|
|
}
|
|
} else
|
|
{
|
|
if(!Graphics()->IsBufferingEnabled())
|
|
{
|
|
//Graphics()->BlendNone();
|
|
//RenderTools()->RenderQuads(pQuads, pQLayer->m_NumQuads, LAYERRENDERFLAG_OPAQUE, EnvelopeEval, this);
|
|
Graphics()->BlendNormal();
|
|
RenderTools()->RenderQuads(pQuads, pQLayer->m_NumQuads, LAYERRENDERFLAG_TRANSPARENT, EnvelopeEval, this);
|
|
}
|
|
else
|
|
{
|
|
RenderQuadLayer(QuadLayerCounter-1, pQLayer, pGroup, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if(Render && g_Config.m_ClOverlayEntities && IsFrontLayer)
|
|
{
|
|
CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer;
|
|
Graphics()->TextureSet(m_pImages->GetEntities());
|
|
|
|
CTile *pFrontTiles = (CTile *)m_pLayers->Map()->GetData(pTMap->m_Front);
|
|
unsigned int Size = m_pLayers->Map()->GetDataSize(pTMap->m_Front);
|
|
|
|
if(Size >= pTMap->m_Width*pTMap->m_Height*sizeof(CTile))
|
|
{
|
|
ColorRGBA Color = ColorRGBA(pTMap->m_Color.r/255.0f, pTMap->m_Color.g/255.0f, pTMap->m_Color.b/255.0f, pTMap->m_Color.a/255.0f*g_Config.m_ClOverlayEntities/100.0f);
|
|
if(!Graphics()->IsBufferingEnabled())
|
|
{
|
|
Graphics()->BlendNone();
|
|
RenderTools()->RenderTilemap(pFrontTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_OPAQUE,
|
|
EnvelopeEval, this, pTMap->m_ColorEnv, pTMap->m_ColorEnvOffset);
|
|
Graphics()->BlendNormal();
|
|
RenderTools()->RenderTilemap(pFrontTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_TRANSPARENT,
|
|
EnvelopeEval, this, pTMap->m_ColorEnv, pTMap->m_ColorEnvOffset);
|
|
}
|
|
else
|
|
{
|
|
Graphics()->BlendNormal();
|
|
RenderTileLayer(TileLayerCounter-1, &Color, pTMap, pGroup);
|
|
}
|
|
}
|
|
}
|
|
else if(Render && g_Config.m_ClOverlayEntities && IsSwitchLayer)
|
|
{
|
|
CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer;
|
|
Graphics()->TextureSet(m_pImages->GetEntities());
|
|
|
|
CSwitchTile *pSwitchTiles = (CSwitchTile *)m_pLayers->Map()->GetData(pTMap->m_Switch);
|
|
unsigned int Size = m_pLayers->Map()->GetDataSize(pTMap->m_Switch);
|
|
|
|
if(Size >= pTMap->m_Width*pTMap->m_Height*sizeof(CSwitchTile))
|
|
{
|
|
ColorRGBA Color = ColorRGBA(pTMap->m_Color.r/255.0f, pTMap->m_Color.g/255.0f, pTMap->m_Color.b/255.0f, pTMap->m_Color.a/255.0f*g_Config.m_ClOverlayEntities/100.0f);
|
|
if(!Graphics()->IsBufferingEnabled())
|
|
{
|
|
Graphics()->BlendNone();
|
|
RenderTools()->RenderSwitchmap(pSwitchTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_OPAQUE);
|
|
Graphics()->BlendNormal();
|
|
RenderTools()->RenderSwitchmap(pSwitchTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_TRANSPARENT);
|
|
RenderTools()->RenderSwitchOverlay(pSwitchTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, g_Config.m_ClOverlayEntities/100.0f);
|
|
}
|
|
else
|
|
{
|
|
Graphics()->BlendNormal();
|
|
RenderTileLayer(TileLayerCounter-3, &Color, pTMap, pGroup);
|
|
if(g_Config.m_ClTextEntities)
|
|
{
|
|
Graphics()->TextureSet(m_pImages->GetOverlayBottom());
|
|
RenderTileLayer(TileLayerCounter-2, &Color, pTMap, pGroup);
|
|
Graphics()->TextureSet(m_pImages->GetOverlayTop());
|
|
RenderTileLayer(TileLayerCounter-1, &Color, pTMap, pGroup);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if(Render && g_Config.m_ClOverlayEntities && IsTeleLayer)
|
|
{
|
|
CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer;
|
|
Graphics()->TextureSet(m_pImages->GetEntities());
|
|
|
|
CTeleTile *pTeleTiles = (CTeleTile *)m_pLayers->Map()->GetData(pTMap->m_Tele);
|
|
unsigned int Size = m_pLayers->Map()->GetDataSize(pTMap->m_Tele);
|
|
|
|
if(Size >= pTMap->m_Width*pTMap->m_Height*sizeof(CTeleTile))
|
|
{
|
|
ColorRGBA Color = ColorRGBA(pTMap->m_Color.r/255.0f, pTMap->m_Color.g/255.0f, pTMap->m_Color.b/255.0f, pTMap->m_Color.a/255.0f*g_Config.m_ClOverlayEntities/100.0f);
|
|
if(!Graphics()->IsBufferingEnabled())
|
|
{
|
|
Graphics()->BlendNone();
|
|
RenderTools()->RenderTelemap(pTeleTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_OPAQUE);
|
|
Graphics()->BlendNormal();
|
|
RenderTools()->RenderTelemap(pTeleTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_TRANSPARENT);
|
|
RenderTools()->RenderTeleOverlay(pTeleTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, g_Config.m_ClOverlayEntities/100.0f);
|
|
}
|
|
else
|
|
{
|
|
Graphics()->BlendNormal();
|
|
RenderTileLayer(TileLayerCounter-2, &Color, pTMap, pGroup);
|
|
if(g_Config.m_ClTextEntities)
|
|
{
|
|
Graphics()->TextureSet(m_pImages->GetOverlayCenter());
|
|
RenderTileLayer(TileLayerCounter-1, &Color, pTMap, pGroup);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if(Render && g_Config.m_ClOverlayEntities && IsSpeedupLayer)
|
|
{
|
|
CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer;
|
|
Graphics()->TextureSet(m_pImages->GetEntities());
|
|
|
|
CSpeedupTile *pSpeedupTiles = (CSpeedupTile *)m_pLayers->Map()->GetData(pTMap->m_Speedup);
|
|
unsigned int Size = m_pLayers->Map()->GetDataSize(pTMap->m_Speedup);
|
|
|
|
if(Size >= pTMap->m_Width*pTMap->m_Height*sizeof(CSpeedupTile))
|
|
{
|
|
ColorRGBA Color = ColorRGBA(pTMap->m_Color.r/255.0f, pTMap->m_Color.g/255.0f, pTMap->m_Color.b/255.0f, pTMap->m_Color.a/255.0f*g_Config.m_ClOverlayEntities/100.0f);
|
|
if(!Graphics()->IsBufferingEnabled())
|
|
{
|
|
Graphics()->BlendNone();
|
|
RenderTools()->RenderSpeedupmap(pSpeedupTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_OPAQUE);
|
|
Graphics()->BlendNormal();
|
|
RenderTools()->RenderSpeedupmap(pSpeedupTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_TRANSPARENT);
|
|
RenderTools()->RenderSpeedupOverlay(pSpeedupTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, g_Config.m_ClOverlayEntities/100.0f);
|
|
}
|
|
else
|
|
{
|
|
Graphics()->BlendNormal();
|
|
|
|
// draw arrow -- clamp to the edge of the arrow image
|
|
Graphics()->WrapClamp();
|
|
Graphics()->TextureSet(g_pData->m_aImages[IMAGE_SPEEDUP_ARROW].m_Id);
|
|
RenderTileLayer(TileLayerCounter-3, &Color, pTMap, pGroup);
|
|
Graphics()->WrapNormal();
|
|
if(g_Config.m_ClTextEntities)
|
|
{
|
|
Graphics()->TextureSet(m_pImages->GetOverlayBottom());
|
|
RenderTileLayer(TileLayerCounter-2, &Color, pTMap, pGroup);
|
|
Graphics()->TextureSet(m_pImages->GetOverlayTop());
|
|
RenderTileLayer(TileLayerCounter-1, &Color, pTMap, pGroup);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if(Render && g_Config.m_ClOverlayEntities && IsTuneLayer)
|
|
{
|
|
CMapItemLayerTilemap *pTMap = (CMapItemLayerTilemap *)pLayer;
|
|
Graphics()->TextureSet(m_pImages->GetEntities());
|
|
|
|
CTuneTile *pTuneTiles = (CTuneTile *)m_pLayers->Map()->GetData(pTMap->m_Tune);
|
|
unsigned int Size = m_pLayers->Map()->GetDataSize(pTMap->m_Tune);
|
|
|
|
if(Size >= pTMap->m_Width*pTMap->m_Height*sizeof(CTuneTile))
|
|
{
|
|
ColorRGBA Color = ColorRGBA(pTMap->m_Color.r/255.0f, pTMap->m_Color.g/255.0f, pTMap->m_Color.b/255.0f, pTMap->m_Color.a/255.0f*g_Config.m_ClOverlayEntities/100.0f);
|
|
if(!Graphics()->IsBufferingEnabled())
|
|
{
|
|
Graphics()->BlendNone();
|
|
RenderTools()->RenderTunemap(pTuneTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_OPAQUE);
|
|
Graphics()->BlendNormal();
|
|
RenderTools()->RenderTunemap(pTuneTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, Color, TILERENDERFLAG_EXTEND|LAYERRENDERFLAG_TRANSPARENT);
|
|
//RenderTools()->RenderTuneOverlay(pTuneTiles, pTMap->m_Width, pTMap->m_Height, 32.0f, g_Config.m_ClOverlayEntities/100.0f);
|
|
}
|
|
else
|
|
{
|
|
Graphics()->BlendNormal();
|
|
RenderTileLayer(TileLayerCounter-1, &Color, pTMap, pGroup);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(!g_Config.m_GfxNoclip)
|
|
Graphics()->ClipDisable();
|
|
}
|
|
|
|
if(!g_Config.m_GfxNoclip)
|
|
Graphics()->ClipDisable();
|
|
|
|
// reset the screen like it was before
|
|
Graphics()->MapScreen(Screen.x, Screen.y, Screen.w, Screen.h);
|
|
}
|