2010-11-20 10:37:14 +00:00
|
|
|
/* (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. */
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <base/math.h>
|
2008-08-14 17:19:13 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <engine/graphics.h>
|
2009-10-27 14:38:53 +00:00
|
|
|
|
2011-04-19 08:34:51 +00:00
|
|
|
#include "editor.h"
|
2010-05-29 07:25:38 +00:00
|
|
|
#include <game/client/render.h>
|
2008-01-12 12:27:55 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CLayerQuads::CLayerQuads()
|
2008-01-12 12:27:55 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Type = LAYERTYPE_QUADS;
|
2019-03-24 01:44:33 +00:00
|
|
|
m_aName[0] = '\0';
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Image = -1;
|
2008-01-12 12:27:55 +00:00
|
|
|
}
|
|
|
|
|
2022-08-17 23:07:16 +00:00
|
|
|
CLayerQuads::CLayerQuads(const CLayerQuads &Other) :
|
|
|
|
CLayer(Other)
|
|
|
|
{
|
|
|
|
m_Image = Other.m_Image;
|
|
|
|
m_vQuads = Other.m_vQuads;
|
|
|
|
}
|
|
|
|
|
2022-02-14 23:32:04 +00:00
|
|
|
CLayerQuads::~CLayerQuads() = default;
|
2008-01-12 12:27:55 +00:00
|
|
|
|
2018-08-19 17:05:42 +00:00
|
|
|
void CLayerQuads::Render(bool QuadPicker)
|
2008-01-12 12:27:55 +00:00
|
|
|
{
|
2012-08-12 10:41:50 +00:00
|
|
|
Graphics()->TextureClear();
|
2022-06-11 19:38:18 +00:00
|
|
|
if(m_Image >= 0 && (size_t)m_Image < m_pEditor->m_Map.m_vpImages.size())
|
|
|
|
Graphics()->TextureSet(m_pEditor->m_Map.m_vpImages[m_Image]->m_Texture);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2012-08-13 10:57:40 +00:00
|
|
|
Graphics()->BlendNone();
|
2022-07-10 19:22:50 +00:00
|
|
|
m_pEditor->RenderTools()->ForceRenderQuads(m_vQuads.data(), m_vQuads.size(), LAYERRENDERFLAG_OPAQUE, m_pEditor->EnvelopeEval, m_pEditor);
|
2012-08-13 10:57:40 +00:00
|
|
|
Graphics()->BlendNormal();
|
2022-07-10 19:22:50 +00:00
|
|
|
m_pEditor->RenderTools()->ForceRenderQuads(m_vQuads.data(), m_vQuads.size(), LAYERRENDERFLAG_TRANSPARENT, m_pEditor->EnvelopeEval, m_pEditor);
|
2008-01-12 12:27:55 +00:00
|
|
|
}
|
|
|
|
|
2019-03-28 12:41:07 +00:00
|
|
|
CQuad *CLayerQuads::NewQuad(int x, int y, int Width, int Height)
|
2008-01-12 12:27:55 +00:00
|
|
|
{
|
2011-03-21 23:31:42 +00:00
|
|
|
m_pEditor->m_Map.m_Modified = true;
|
|
|
|
|
2022-06-11 19:38:18 +00:00
|
|
|
m_vQuads.emplace_back();
|
2022-06-30 22:36:32 +00:00
|
|
|
CQuad *pQuad = &m_vQuads[m_vQuads.size() - 1];
|
2008-01-12 12:27:55 +00:00
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
pQuad->m_PosEnv = -1;
|
|
|
|
pQuad->m_ColorEnv = -1;
|
|
|
|
pQuad->m_PosEnvOffset = 0;
|
|
|
|
pQuad->m_ColorEnvOffset = 0;
|
2019-03-28 12:41:07 +00:00
|
|
|
|
|
|
|
Width /= 2;
|
|
|
|
Height /= 2;
|
2022-06-30 22:36:32 +00:00
|
|
|
pQuad->m_aPoints[0].x = i2fx(x - Width);
|
|
|
|
pQuad->m_aPoints[0].y = i2fx(y - Height);
|
|
|
|
pQuad->m_aPoints[1].x = i2fx(x + Width);
|
|
|
|
pQuad->m_aPoints[1].y = i2fx(y - Height);
|
|
|
|
pQuad->m_aPoints[2].x = i2fx(x - Width);
|
|
|
|
pQuad->m_aPoints[2].y = i2fx(y + Height);
|
|
|
|
pQuad->m_aPoints[3].x = i2fx(x + Width);
|
|
|
|
pQuad->m_aPoints[3].y = i2fx(y + Height);
|
|
|
|
|
|
|
|
pQuad->m_aPoints[4].x = i2fx(x); // pivot
|
|
|
|
pQuad->m_aPoints[4].y = i2fx(y);
|
|
|
|
|
|
|
|
pQuad->m_aTexcoords[0].x = i2fx(0);
|
|
|
|
pQuad->m_aTexcoords[0].y = i2fx(0);
|
|
|
|
|
|
|
|
pQuad->m_aTexcoords[1].x = i2fx(1);
|
|
|
|
pQuad->m_aTexcoords[1].y = i2fx(0);
|
|
|
|
|
|
|
|
pQuad->m_aTexcoords[2].x = i2fx(0);
|
|
|
|
pQuad->m_aTexcoords[2].y = i2fx(1);
|
|
|
|
|
|
|
|
pQuad->m_aTexcoords[3].x = i2fx(1);
|
|
|
|
pQuad->m_aTexcoords[3].y = i2fx(1);
|
|
|
|
|
|
|
|
pQuad->m_aColors[0].r = 255;
|
|
|
|
pQuad->m_aColors[0].g = 255;
|
|
|
|
pQuad->m_aColors[0].b = 255;
|
|
|
|
pQuad->m_aColors[0].a = 255;
|
|
|
|
pQuad->m_aColors[1].r = 255;
|
|
|
|
pQuad->m_aColors[1].g = 255;
|
|
|
|
pQuad->m_aColors[1].b = 255;
|
|
|
|
pQuad->m_aColors[1].a = 255;
|
|
|
|
pQuad->m_aColors[2].r = 255;
|
|
|
|
pQuad->m_aColors[2].g = 255;
|
|
|
|
pQuad->m_aColors[2].b = 255;
|
|
|
|
pQuad->m_aColors[2].a = 255;
|
|
|
|
pQuad->m_aColors[3].r = 255;
|
|
|
|
pQuad->m_aColors[3].g = 255;
|
|
|
|
pQuad->m_aColors[3].b = 255;
|
|
|
|
pQuad->m_aColors[3].a = 255;
|
|
|
|
|
|
|
|
return pQuad;
|
2008-01-12 12:27:55 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CLayerQuads::BrushSelecting(CUIRect Rect)
|
2008-01-12 12:27:55 +00:00
|
|
|
{
|
|
|
|
// draw selection rectangle
|
2010-05-29 07:25:38 +00:00
|
|
|
IGraphics::CLineItem Array[4] = {
|
2020-09-26 19:41:58 +00:00
|
|
|
IGraphics::CLineItem(Rect.x, Rect.y, Rect.x + Rect.w, Rect.y),
|
|
|
|
IGraphics::CLineItem(Rect.x + Rect.w, Rect.y, Rect.x + Rect.w, Rect.y + Rect.h),
|
|
|
|
IGraphics::CLineItem(Rect.x + Rect.w, Rect.y + Rect.h, Rect.x, Rect.y + Rect.h),
|
|
|
|
IGraphics::CLineItem(Rect.x, Rect.y + Rect.h, Rect.x, Rect.y)};
|
2012-08-12 10:41:50 +00:00
|
|
|
Graphics()->TextureClear();
|
2009-10-27 14:38:53 +00:00
|
|
|
Graphics()->LinesBegin();
|
2010-05-29 07:25:38 +00:00
|
|
|
Graphics()->LinesDraw(Array, 4);
|
2009-10-27 14:38:53 +00:00
|
|
|
Graphics()->LinesEnd();
|
2008-01-12 12:27:55 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int CLayerQuads::BrushGrab(CLayerGroup *pBrush, CUIRect Rect)
|
2008-01-12 12:27:55 +00:00
|
|
|
{
|
|
|
|
// create new layers
|
2010-05-29 07:25:38 +00:00
|
|
|
CLayerQuads *pGrabbed = new CLayerQuads();
|
|
|
|
pGrabbed->m_pEditor = m_pEditor;
|
|
|
|
pGrabbed->m_Image = m_Image;
|
|
|
|
pBrush->AddLayer(pGrabbed);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2008-01-12 12:27:55 +00:00
|
|
|
//dbg_msg("", "%f %f %f %f", rect.x, rect.y, rect.w, rect.h);
|
2022-06-11 19:38:18 +00:00
|
|
|
for(const auto &Quad : m_vQuads)
|
2008-01-12 12:27:55 +00:00
|
|
|
{
|
2022-05-24 09:24:33 +00:00
|
|
|
float px = fx2f(Quad.m_aPoints[4].x);
|
|
|
|
float py = fx2f(Quad.m_aPoints[4].y);
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
if(px > Rect.x && px < Rect.x + Rect.w && py > Rect.y && py < Rect.y + Rect.h)
|
2008-01-12 12:27:55 +00:00
|
|
|
{
|
2022-05-24 09:24:33 +00:00
|
|
|
CQuad n = Quad;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2020-10-26 14:14:07 +00:00
|
|
|
for(auto &Point : n.m_aPoints)
|
2008-01-12 12:27:55 +00:00
|
|
|
{
|
2020-10-26 14:14:07 +00:00
|
|
|
Point.x -= f2fx(Rect.x);
|
|
|
|
Point.y -= f2fx(Rect.y);
|
2008-01-12 12:27:55 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2022-06-11 19:38:18 +00:00
|
|
|
pGrabbed->m_vQuads.push_back(n);
|
2008-01-12 12:27:55 +00:00
|
|
|
}
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2022-06-11 19:38:18 +00:00
|
|
|
return pGrabbed->m_vQuads.empty() ? 0 : 1;
|
2008-01-12 12:27:55 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CLayerQuads::BrushPlace(CLayer *pBrush, float wx, float wy)
|
2008-01-12 12:27:55 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
CLayerQuads *pQuadLayer = (CLayerQuads *)pBrush;
|
|
|
|
for(const auto &Quad : pQuadLayer->m_vQuads)
|
2008-01-12 12:27:55 +00:00
|
|
|
{
|
2022-05-24 09:24:33 +00:00
|
|
|
CQuad n = Quad;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2020-10-26 14:14:07 +00:00
|
|
|
for(auto &Point : n.m_aPoints)
|
2008-01-12 12:27:55 +00:00
|
|
|
{
|
2020-10-26 14:14:07 +00:00
|
|
|
Point.x += f2fx(wx);
|
|
|
|
Point.y += f2fx(wy);
|
2008-01-12 12:27:55 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2022-06-11 19:38:18 +00:00
|
|
|
m_vQuads.push_back(n);
|
2008-01-12 12:27:55 +00:00
|
|
|
}
|
2011-03-21 23:31:42 +00:00
|
|
|
m_pEditor->m_Map.m_Modified = true;
|
2008-01-12 12:27:55 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CLayerQuads::BrushFlipX()
|
2008-01-12 12:27:55 +00:00
|
|
|
{
|
2022-06-11 19:38:18 +00:00
|
|
|
for(auto &Quad : m_vQuads)
|
2014-05-17 15:47:47 +00:00
|
|
|
{
|
2022-05-24 09:24:33 +00:00
|
|
|
std::swap(Quad.m_aPoints[0], Quad.m_aPoints[1]);
|
|
|
|
std::swap(Quad.m_aPoints[2], Quad.m_aPoints[3]);
|
2014-05-17 15:47:47 +00:00
|
|
|
}
|
|
|
|
m_pEditor->m_Map.m_Modified = true;
|
2008-01-12 12:27:55 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CLayerQuads::BrushFlipY()
|
2008-01-12 12:27:55 +00:00
|
|
|
{
|
2022-06-11 19:38:18 +00:00
|
|
|
for(auto &Quad : m_vQuads)
|
2014-05-17 15:47:47 +00:00
|
|
|
{
|
2022-05-24 09:24:33 +00:00
|
|
|
std::swap(Quad.m_aPoints[0], Quad.m_aPoints[2]);
|
|
|
|
std::swap(Quad.m_aPoints[1], Quad.m_aPoints[3]);
|
2014-05-17 15:47:47 +00:00
|
|
|
}
|
|
|
|
m_pEditor->m_Map.m_Modified = true;
|
2008-01-12 12:27:55 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void Rotate(vec2 *pCenter, vec2 *pPoint, float Rotation)
|
2008-02-05 19:11:34 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
float x = pPoint->x - pCenter->x;
|
|
|
|
float y = pPoint->y - pCenter->y;
|
2023-02-28 20:31:40 +00:00
|
|
|
pPoint->x = x * std::cos(Rotation) - y * std::sin(Rotation) + pCenter->x;
|
|
|
|
pPoint->y = x * std::sin(Rotation) + y * std::cos(Rotation) + pCenter->y;
|
2008-02-05 19:11:34 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CLayerQuads::BrushRotate(float Amount)
|
2008-02-05 19:11:34 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
vec2 Center;
|
|
|
|
GetSize(&Center.x, &Center.y);
|
|
|
|
Center.x /= 2;
|
|
|
|
Center.y /= 2;
|
2008-02-05 19:11:34 +00:00
|
|
|
|
2022-06-11 19:38:18 +00:00
|
|
|
for(auto &Quad : m_vQuads)
|
2008-02-05 19:11:34 +00:00
|
|
|
{
|
2022-05-24 09:24:33 +00:00
|
|
|
for(auto &Point : Quad.m_aPoints)
|
2008-02-05 19:11:34 +00:00
|
|
|
{
|
2020-10-26 14:14:07 +00:00
|
|
|
vec2 Pos(fx2f(Point.x), fx2f(Point.y));
|
2010-05-29 07:25:38 +00:00
|
|
|
Rotate(&Center, &Pos, Amount);
|
2020-10-26 14:14:07 +00:00
|
|
|
Point.x = f2fx(Pos.x);
|
|
|
|
Point.y = f2fx(Pos.y);
|
2008-02-05 19:11:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-30 22:36:32 +00:00
|
|
|
void CLayerQuads::GetSize(float *pWidth, float *pHeight)
|
2008-01-12 12:27:55 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
*pWidth = 0;
|
|
|
|
*pHeight = 0;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2022-06-11 19:38:18 +00:00
|
|
|
for(const auto &Quad : m_vQuads)
|
2008-01-12 12:27:55 +00:00
|
|
|
{
|
2022-05-24 09:24:33 +00:00
|
|
|
for(const auto &Point : Quad.m_aPoints)
|
2008-01-12 12:27:55 +00:00
|
|
|
{
|
2022-06-30 22:36:32 +00:00
|
|
|
*pWidth = maximum(*pWidth, fx2f(Point.x));
|
|
|
|
*pHeight = maximum(*pHeight, fx2f(Point.y));
|
2008-01-12 12:27:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int CLayerQuads::RenderProperties(CUIRect *pToolBox)
|
2008-01-12 12:27:55 +00:00
|
|
|
{
|
|
|
|
// layer props
|
2008-01-17 23:09:49 +00:00
|
|
|
enum
|
2008-01-12 12:27:55 +00:00
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
PROP_IMAGE = 0,
|
2008-01-17 23:09:49 +00:00
|
|
|
NUM_PROPS,
|
|
|
|
};
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CProperty aProps[] = {
|
2020-05-30 07:08:59 +00:00
|
|
|
{"Image", m_Image, PROPTYPE_IMAGE, -1, 0},
|
2022-06-13 16:28:13 +00:00
|
|
|
{nullptr},
|
2008-01-17 23:09:49 +00:00
|
|
|
};
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
static int s_aIds[NUM_PROPS] = {0};
|
|
|
|
int NewVal = 0;
|
2011-03-21 23:31:42 +00:00
|
|
|
int Prop = m_pEditor->DoProperties(pToolBox, aProps, s_aIds, &NewVal);
|
|
|
|
if(Prop != -1)
|
|
|
|
m_pEditor->m_Map.m_Modified = true;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
if(Prop == PROP_IMAGE)
|
2008-01-17 23:09:49 +00:00
|
|
|
{
|
2020-05-30 07:08:59 +00:00
|
|
|
if(NewVal >= 0)
|
2022-06-11 19:38:18 +00:00
|
|
|
m_Image = NewVal % m_pEditor->m_Map.m_vpImages.size();
|
2020-05-30 07:08:59 +00:00
|
|
|
else
|
|
|
|
m_Image = -1;
|
2008-01-17 23:09:49 +00:00
|
|
|
}
|
|
|
|
|
2008-01-13 22:03:32 +00:00
|
|
|
return 0;
|
2008-01-12 12:27:55 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CLayerQuads::ModifyImageIndex(INDEX_MODIFY_FUNC Func)
|
2008-01-19 12:32:08 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
Func(&m_Image);
|
2008-01-19 12:32:08 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
void CLayerQuads::ModifyEnvelopeIndex(INDEX_MODIFY_FUNC Func)
|
2008-01-19 12:32:08 +00:00
|
|
|
{
|
2022-06-11 19:38:18 +00:00
|
|
|
for(auto &Quad : m_vQuads)
|
2008-01-19 12:32:08 +00:00
|
|
|
{
|
2022-05-24 09:24:33 +00:00
|
|
|
Func(&Quad.m_PosEnv);
|
|
|
|
Func(&Quad.m_ColorEnv);
|
2008-01-19 12:32:08 +00:00
|
|
|
}
|
|
|
|
}
|
2022-08-17 23:07:16 +00:00
|
|
|
|
|
|
|
CLayer *CLayerQuads::Duplicate() const
|
|
|
|
{
|
|
|
|
return new CLayerQuads(*this);
|
|
|
|
}
|
2022-09-10 13:07:32 +00:00
|
|
|
|
|
|
|
int CLayerQuads::SwapQuads(int Index0, int Index1)
|
|
|
|
{
|
|
|
|
if(Index0 < 0 || Index0 >= (int)m_vQuads.size())
|
|
|
|
return Index0;
|
|
|
|
if(Index1 < 0 || Index1 >= (int)m_vQuads.size())
|
|
|
|
return Index0;
|
|
|
|
if(Index0 == Index1)
|
|
|
|
return Index0;
|
|
|
|
m_pEditor->m_Map.m_Modified = true;
|
|
|
|
std::swap(m_vQuads[Index0], m_vQuads[Index1]);
|
|
|
|
return Index1;
|
|
|
|
}
|