2023-07-10 00:29:21 +00:00
|
|
|
#include "TileRender.h"
|
|
|
|
#include "RenderBase.h"
|
|
|
|
#include "Core.h"
|
|
|
|
#include "Tileset.h"
|
2023-07-11 20:30:28 +00:00
|
|
|
#include "RenderGrid.h"
|
|
|
|
#include "RenderObject.h"
|
|
|
|
|
2023-07-10 00:29:21 +00:00
|
|
|
|
|
|
|
TileRender::TileRender(const TileStorage& tiles)
|
2023-07-11 20:30:28 +00:00
|
|
|
: storage(tiles), renderBorders(false)
|
2023-07-10 00:29:21 +00:00
|
|
|
{
|
2023-07-13 22:19:33 +00:00
|
|
|
this->cull = false;
|
|
|
|
this->neverFollowCamera = true;
|
2023-07-10 00:29:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TileRender::~TileRender()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-07-11 20:30:28 +00:00
|
|
|
// shamelessly ripped from paint.net default palette
|
|
|
|
static const Vector s_tagColors[] =
|
|
|
|
{
|
|
|
|
/* 0 */ Vector(0.5f, 0.5f, 0.5f),
|
|
|
|
/* 1 */ Vector(1,0,0),
|
|
|
|
/* 2 */ Vector(1, 0.415686f, 0),
|
|
|
|
/* 3 */ Vector(1,0.847059f, 0),
|
|
|
|
/* 4 */ Vector(0.298039f,1,0),
|
|
|
|
/* 5 */ Vector(0,1,1),
|
|
|
|
/* 6 */ Vector(0,0.580392,1),
|
|
|
|
/* 7 */ Vector(0,0.149020f,1),
|
|
|
|
/* 8 */ Vector(0.282353f,0,1),
|
|
|
|
/* 9 */ Vector(0.698039f,0,1),
|
|
|
|
|
|
|
|
/* 10 */ Vector(1,0,1), // anything outside of the pretty range
|
|
|
|
};
|
|
|
|
|
|
|
|
static inline const Vector& getTagColor(int tag)
|
|
|
|
{
|
|
|
|
const unsigned idx = std::min<unsigned>(unsigned(tag), Countof(s_tagColors)-1);
|
|
|
|
return s_tagColors[idx];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-07-14 02:25:59 +00:00
|
|
|
static const float s_quadVerts[] =
|
|
|
|
{
|
|
|
|
-0.5f, +0.5f,
|
|
|
|
+0.5f, +0.5f,
|
|
|
|
+0.5f, -0.5f,
|
|
|
|
-0.5f, -0.5f,
|
|
|
|
};
|
2023-07-11 20:30:28 +00:00
|
|
|
|
2023-07-10 00:29:21 +00:00
|
|
|
void TileRender::onRender(const RenderState& rs) const
|
|
|
|
{
|
2023-07-14 02:25:59 +00:00
|
|
|
if(storage.tiles.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
|
|
|
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glVertexPointer(2, GL_FLOAT, 0, s_quadVerts);
|
|
|
|
|
|
|
|
RenderState rx(rs);
|
|
|
|
|
2023-07-10 00:29:21 +00:00
|
|
|
// prepare. get parallax scroll factors
|
|
|
|
const RenderObjectLayer& rl = core->renderObjectLayers[this->layer];
|
2023-07-11 20:30:28 +00:00
|
|
|
const Vector M = rl.followCameraMult; // affected by parallaxLock
|
2023-07-10 00:29:21 +00:00
|
|
|
const float F = rl.followCamera;
|
2023-07-13 22:19:33 +00:00
|
|
|
const bool parallax = rl.followCamera > 0;
|
2023-07-10 00:29:21 +00:00
|
|
|
|
|
|
|
// Formula from RenderObject::getFollowCameraPosition() and optimized for speed
|
|
|
|
const Vector C = core->screenCenter;
|
|
|
|
const Vector M1 = Vector(1,1) - M;
|
|
|
|
const Vector T = C * (1 - F);
|
|
|
|
|
|
|
|
unsigned lastTexRepeat = false;
|
|
|
|
unsigned lastTexId = 0;
|
2023-07-11 20:30:28 +00:00
|
|
|
|
2023-07-14 02:25:59 +00:00
|
|
|
const bool renderExtras = renderBorders || RenderObject::renderCollisionShape;
|
|
|
|
const TileEffectData *prevEff = ((TileEffectData*)NULL)+1; // initial value is different from anything else
|
|
|
|
const RenderGrid *grid = NULL;
|
|
|
|
const float *lastTexcoordBuf = NULL;
|
2023-07-10 00:29:21 +00:00
|
|
|
|
|
|
|
for(size_t i = 0; i < storage.tiles.size(); ++i)
|
|
|
|
{
|
|
|
|
const TileData& tile = storage.tiles[i];
|
2023-07-13 22:19:33 +00:00
|
|
|
if(tile.flags & (TILEFLAG_HIDDEN | TILEFLAG_EDITOR_HIDDEN))
|
2023-07-11 20:30:28 +00:00
|
|
|
continue;
|
|
|
|
|
2023-07-13 22:19:33 +00:00
|
|
|
Vector pos(tile.x, tile.y);
|
|
|
|
if(parallax)
|
|
|
|
{
|
|
|
|
const Vector tmp = T + (F * pos);
|
|
|
|
pos = pos * M1 + (tmp * M); // lerp, used to select whether to use original v or parallax-corrected v
|
|
|
|
}
|
2023-07-10 00:29:21 +00:00
|
|
|
|
2023-07-13 22:19:33 +00:00
|
|
|
const ElementTemplate * const et = tile.et;
|
2023-07-14 02:25:59 +00:00
|
|
|
const float sw = et->w * tile.scalex;
|
|
|
|
const float sh = et->h * tile.scaley;
|
2023-07-13 23:33:59 +00:00
|
|
|
|
|
|
|
// adapted from RenderObject::isOnScreen()
|
|
|
|
{
|
2023-07-14 02:25:59 +00:00
|
|
|
const float cullRadiusSqr = ((sw*sw + sh*sh) * core->invGlobalScaleSqr) + core->cullRadiusSqr;
|
2023-07-13 23:33:59 +00:00
|
|
|
if ((pos - core->cullCenter).getSquaredLength2D() >= cullRadiusSqr)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2023-07-13 22:19:33 +00:00
|
|
|
if(const Texture * const tex = et->tex.content())
|
2023-07-10 00:29:21 +00:00
|
|
|
{
|
|
|
|
unsigned texid = tex->gltexid;
|
|
|
|
unsigned rep = tile.flags & TILEFLAG_REPEAT;
|
|
|
|
if(texid != lastTexId || rep != lastTexRepeat)
|
|
|
|
{
|
|
|
|
lastTexId = texid;
|
|
|
|
lastTexRepeat = rep;
|
|
|
|
tex->apply(!!rep);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2023-07-11 20:30:28 +00:00
|
|
|
{
|
|
|
|
lastTexId = 0;
|
2023-07-10 00:29:21 +00:00
|
|
|
glBindTexture(GL_TEXTURE_2D, 0); // unlikely
|
2023-07-11 20:30:28 +00:00
|
|
|
}
|
2023-07-10 00:29:21 +00:00
|
|
|
|
|
|
|
glPushMatrix();
|
|
|
|
glTranslatef(pos.x, pos.y, pos.z);
|
|
|
|
|
|
|
|
glRotatef(tile.rotation, 0, 0, 1);
|
2023-07-14 02:25:59 +00:00
|
|
|
if(tile.flags & TILEFLAG_FH)
|
2023-07-10 00:29:21 +00:00
|
|
|
glRotatef(180, 0, 1, 0);
|
|
|
|
|
|
|
|
// this is only relevant in editor mode and is always 0 otherwise
|
2023-07-14 02:25:59 +00:00
|
|
|
//glTranslatef(tile.beforeScaleOffsetX, tile.beforeScaleOffsetY, 0);
|
2023-07-10 00:29:21 +00:00
|
|
|
|
2023-07-14 02:25:59 +00:00
|
|
|
glScalef(sw, sh, 1);
|
2023-07-10 00:29:21 +00:00
|
|
|
|
2023-07-11 20:30:28 +00:00
|
|
|
float alpha = rs.alpha;
|
|
|
|
const TileEffectData * const eff = tile.eff;
|
2023-07-14 02:25:59 +00:00
|
|
|
if(eff != prevEff) // effects between tiles are often shared so this works not only for NULL
|
2023-07-10 00:29:21 +00:00
|
|
|
{
|
2023-07-14 02:25:59 +00:00
|
|
|
prevEff = eff;
|
|
|
|
BlendType blend = BLEND_DEFAULT;
|
|
|
|
alpha = rs.alpha;
|
|
|
|
grid = NULL;
|
2023-07-11 20:30:28 +00:00
|
|
|
|
2023-07-14 02:25:59 +00:00
|
|
|
if(eff)
|
|
|
|
{
|
|
|
|
grid = eff->grid;
|
|
|
|
alpha *= eff->alpha.x;
|
|
|
|
blend = eff->blend;
|
|
|
|
}
|
2023-07-10 00:29:21 +00:00
|
|
|
|
2023-07-14 02:25:59 +00:00
|
|
|
rs.gpu.setBlend(blend);
|
|
|
|
glColor4f(rs.color.x, rs.color.y, rs.color.z, alpha);
|
|
|
|
}
|
2023-07-11 20:30:28 +00:00
|
|
|
|
|
|
|
if(!grid)
|
2023-07-10 00:29:21 +00:00
|
|
|
{
|
2023-07-14 03:21:16 +00:00
|
|
|
const float *tcbuf = (tile.flags & TILEFLAG_REPEAT)
|
|
|
|
? &tile.rep->texcoords[0]
|
|
|
|
: tile.et->texcoordQuadPtr;
|
2023-07-14 02:25:59 +00:00
|
|
|
assert(tcbuf);
|
|
|
|
if(lastTexcoordBuf != tcbuf)
|
2023-07-10 00:29:21 +00:00
|
|
|
{
|
2023-07-14 02:25:59 +00:00
|
|
|
lastTexcoordBuf = tcbuf;
|
|
|
|
glTexCoordPointer(2, GL_FLOAT, 0, tcbuf);
|
2023-07-10 00:29:21 +00:00
|
|
|
}
|
2023-07-14 02:25:59 +00:00
|
|
|
glDrawArrays(GL_QUADS, 0, 4);
|
2023-07-10 00:29:21 +00:00
|
|
|
}
|
2023-07-11 20:30:28 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
rx.alpha = alpha;
|
2023-07-14 03:21:16 +00:00
|
|
|
|
|
|
|
Vector upperLeftTextureCoordinates, lowerRightTextureCoordinates;
|
|
|
|
if(tile.flags & TILEFLAG_REPEAT)
|
|
|
|
{
|
|
|
|
upperLeftTextureCoordinates = Vector(tile.rep->tu1, tile.rep->tv1);
|
|
|
|
lowerRightTextureCoordinates = Vector(tile.rep->tu2, tile.rep->tv2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
upperLeftTextureCoordinates = Vector(et->tu1, et->tv1);
|
|
|
|
lowerRightTextureCoordinates = Vector(et->tu2, et->tv2);
|
|
|
|
}
|
|
|
|
|
2023-07-11 20:30:28 +00:00
|
|
|
grid->render(rx, upperLeftTextureCoordinates, lowerRightTextureCoordinates);
|
|
|
|
}
|
2023-07-10 00:29:21 +00:00
|
|
|
|
2023-07-14 02:25:59 +00:00
|
|
|
if(renderExtras)
|
2023-07-10 00:29:21 +00:00
|
|
|
{
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
2023-07-14 02:25:59 +00:00
|
|
|
lastTexId = 0;
|
|
|
|
prevEff = ((TileEffectData*)NULL)+1;
|
2023-07-10 00:29:21 +00:00
|
|
|
|
2023-07-14 02:25:59 +00:00
|
|
|
if(grid && RenderObject::renderCollisionShape)
|
|
|
|
{
|
|
|
|
grid->renderDebugPoints(rs);
|
|
|
|
}
|
2023-07-10 00:29:21 +00:00
|
|
|
|
2023-07-14 02:25:59 +00:00
|
|
|
if(renderBorders)
|
|
|
|
{
|
|
|
|
float c = (tile.flags & TILEFLAG_SELECTED) ? 1.0f : 0.5f;
|
|
|
|
Vector color(c,c,c);
|
|
|
|
color *= getTagColor(tile.tag);
|
|
|
|
|
|
|
|
glColor4f(color.x, color.y, color.z, 1.0f);
|
|
|
|
glPointSize(16);
|
|
|
|
glBegin(GL_POINTS);
|
|
|
|
glVertex2f(0,0);
|
|
|
|
glEnd();
|
|
|
|
|
|
|
|
glLineWidth(2);
|
|
|
|
glBegin(GL_LINE_STRIP);
|
|
|
|
glVertex2f(0.5f, 0.5f);
|
|
|
|
glVertex2f(0.5f, -0.5f);
|
|
|
|
glVertex2f(-0.5f, -0.5f);
|
|
|
|
glVertex2f(-0.5f, 0.5f);
|
|
|
|
glVertex2f(0.5f, 0.5f);
|
|
|
|
glEnd();
|
|
|
|
}
|
|
|
|
}
|
2023-07-10 00:29:21 +00:00
|
|
|
|
|
|
|
glPopMatrix();
|
|
|
|
}
|
|
|
|
|
2023-07-14 02:25:59 +00:00
|
|
|
glPopClientAttrib();
|
|
|
|
|
2023-07-10 00:29:21 +00:00
|
|
|
RenderObject::lastTextureApplied = lastTexId;
|
|
|
|
RenderObject::lastTextureRepeat = !!lastTexRepeat;
|
|
|
|
}
|
2023-07-13 22:19:33 +00:00
|
|
|
|
|
|
|
void TileRender::onUpdate(float dt)
|
|
|
|
{
|
|
|
|
//this->position = core->screenCenter;
|
|
|
|
}
|