ddnet/src/game/editor/layer_quads.cpp

284 lines
6.5 KiB
C++
Raw Normal View History

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>
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;
m_aName[0] = '\0';
2010-05-29 07:25:38 +00:00
m_Image = -1;
2008-01-12 12:27:55 +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
{
Graphics()->TextureClear();
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);
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);
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
}
CQuad *CLayerQuads::NewQuad(int x, int y, int Width, int Height)
2008-01-12 12:27:55 +00:00
{
Autosave copy of current editor map periodically to `auto` folder A copy of the map currently open in the editor is saved every 10 minutes to the `maps/auto` folder (interval configurable, see below). The automatically saved map uses the filename of the original map with an additional timestamp. Per map name 10 autosaves are kept in the `auto` folder before old autosaves will be deleted (number configurable, see below). Add config variable `ed_autosave_interval` (0 - 240, default 10) to configure the interval in minutes at which a copy of the current editor map is automatically saved to the 'auto' folder. Add config variable `ed_autosave_max` (0 - 1000, default 10) to configure the maximum number of autosaves that are kept per map name (0 = no limit). Autosaving will not take place in the 5 seconds immediately after the map was last modified by the user, to avoid interrupting the user with the autosave. This will only delay autosaving for up to 1 minute though, so autosaves are not prevented entirely, should the user continuously edit the map. When the editor is reopened after being closed for more than 10 seconds, the autosave timer will be adjusted to compensate for the time that was not spent on editing in the editor. When the map is saved manually by the user the autosave file is also updated, if it's outdated by at least half of the configured autosave interval. This ensures that autosaves are always available as a periodic backup of the map. When a copy of the current map is saved, this does not update the autosave and will also no longer reset the modified state. The modified state should reflect whether changes have been made that are not saved to the current map file. As saving a copy does not update the current file, the modified state should not be reset in this case. Closes #6693.
2023-06-23 15:39:05 +00:00
m_pEditor->m_Map.OnModify();
m_vQuads.emplace_back();
CQuad *pQuad = &m_vQuads[m_vQuads.size() - 1];
2008-01-12 12:27:55 +00:00
pQuad->m_PosEnv = -1;
pQuad->m_ColorEnv = -1;
pQuad->m_PosEnvOffset = 0;
pQuad->m_ColorEnvOffset = 0;
Width /= 2;
Height /= 2;
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] = {
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)};
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);
2008-01-12 12:27:55 +00:00
//dbg_msg("", "%f %f %f %f", rect.x, rect.y, rect.w, rect.h);
for(const auto &Quad : m_vQuads)
2008-01-12 12:27:55 +00:00
{
float px = fx2f(Quad.m_aPoints[4].x);
float py = fx2f(Quad.m_aPoints[4].y);
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
{
CQuad n = Quad;
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
}
pGrabbed->m_vQuads.push_back(n);
2008-01-12 12:27:55 +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
{
CLayerQuads *pQuadLayer = (CLayerQuads *)pBrush;
for(const auto &Quad : pQuadLayer->m_vQuads)
2008-01-12 12:27:55 +00:00
{
CQuad n = Quad;
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
}
m_vQuads.push_back(n);
2008-01-12 12:27:55 +00:00
}
Autosave copy of current editor map periodically to `auto` folder A copy of the map currently open in the editor is saved every 10 minutes to the `maps/auto` folder (interval configurable, see below). The automatically saved map uses the filename of the original map with an additional timestamp. Per map name 10 autosaves are kept in the `auto` folder before old autosaves will be deleted (number configurable, see below). Add config variable `ed_autosave_interval` (0 - 240, default 10) to configure the interval in minutes at which a copy of the current editor map is automatically saved to the 'auto' folder. Add config variable `ed_autosave_max` (0 - 1000, default 10) to configure the maximum number of autosaves that are kept per map name (0 = no limit). Autosaving will not take place in the 5 seconds immediately after the map was last modified by the user, to avoid interrupting the user with the autosave. This will only delay autosaving for up to 1 minute though, so autosaves are not prevented entirely, should the user continuously edit the map. When the editor is reopened after being closed for more than 10 seconds, the autosave timer will be adjusted to compensate for the time that was not spent on editing in the editor. When the map is saved manually by the user the autosave file is also updated, if it's outdated by at least half of the configured autosave interval. This ensures that autosaves are always available as a periodic backup of the map. When a copy of the current map is saved, this does not update the autosave and will also no longer reset the modified state. The modified state should reflect whether changes have been made that are not saved to the current map file. As saving a copy does not update the current file, the modified state should not be reset in this case. Closes #6693.
2023-06-23 15:39:05 +00:00
m_pEditor->m_Map.OnModify();
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
{
for(auto &Quad : m_vQuads)
{
std::swap(Quad.m_aPoints[0], Quad.m_aPoints[1]);
std::swap(Quad.m_aPoints[2], Quad.m_aPoints[3]);
}
Autosave copy of current editor map periodically to `auto` folder A copy of the map currently open in the editor is saved every 10 minutes to the `maps/auto` folder (interval configurable, see below). The automatically saved map uses the filename of the original map with an additional timestamp. Per map name 10 autosaves are kept in the `auto` folder before old autosaves will be deleted (number configurable, see below). Add config variable `ed_autosave_interval` (0 - 240, default 10) to configure the interval in minutes at which a copy of the current editor map is automatically saved to the 'auto' folder. Add config variable `ed_autosave_max` (0 - 1000, default 10) to configure the maximum number of autosaves that are kept per map name (0 = no limit). Autosaving will not take place in the 5 seconds immediately after the map was last modified by the user, to avoid interrupting the user with the autosave. This will only delay autosaving for up to 1 minute though, so autosaves are not prevented entirely, should the user continuously edit the map. When the editor is reopened after being closed for more than 10 seconds, the autosave timer will be adjusted to compensate for the time that was not spent on editing in the editor. When the map is saved manually by the user the autosave file is also updated, if it's outdated by at least half of the configured autosave interval. This ensures that autosaves are always available as a periodic backup of the map. When a copy of the current map is saved, this does not update the autosave and will also no longer reset the modified state. The modified state should reflect whether changes have been made that are not saved to the current map file. As saving a copy does not update the current file, the modified state should not be reset in this case. Closes #6693.
2023-06-23 15:39:05 +00:00
m_pEditor->m_Map.OnModify();
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
{
for(auto &Quad : m_vQuads)
{
std::swap(Quad.m_aPoints[0], Quad.m_aPoints[2]);
std::swap(Quad.m_aPoints[1], Quad.m_aPoints[3]);
}
Autosave copy of current editor map periodically to `auto` folder A copy of the map currently open in the editor is saved every 10 minutes to the `maps/auto` folder (interval configurable, see below). The automatically saved map uses the filename of the original map with an additional timestamp. Per map name 10 autosaves are kept in the `auto` folder before old autosaves will be deleted (number configurable, see below). Add config variable `ed_autosave_interval` (0 - 240, default 10) to configure the interval in minutes at which a copy of the current editor map is automatically saved to the 'auto' folder. Add config variable `ed_autosave_max` (0 - 1000, default 10) to configure the maximum number of autosaves that are kept per map name (0 = no limit). Autosaving will not take place in the 5 seconds immediately after the map was last modified by the user, to avoid interrupting the user with the autosave. This will only delay autosaving for up to 1 minute though, so autosaves are not prevented entirely, should the user continuously edit the map. When the editor is reopened after being closed for more than 10 seconds, the autosave timer will be adjusted to compensate for the time that was not spent on editing in the editor. When the map is saved manually by the user the autosave file is also updated, if it's outdated by at least half of the configured autosave interval. This ensures that autosaves are always available as a periodic backup of the map. When a copy of the current map is saved, this does not update the autosave and will also no longer reset the modified state. The modified state should reflect whether changes have been made that are not saved to the current map file. As saving a copy does not update the current file, the modified state should not be reset in this case. Closes #6693.
2023-06-23 15:39:05 +00:00
m_pEditor->m_Map.OnModify();
2008-01-12 12:27:55 +00:00
}
2010-05-29 07:25:38 +00:00
void Rotate(vec2 *pCenter, vec2 *pPoint, float Rotation)
{
2010-05-29 07:25:38 +00:00
float x = pPoint->x - pCenter->x;
float y = pPoint->y - pCenter->y;
pPoint->x = x * std::cos(Rotation) - y * std::sin(Rotation) + pCenter->x;
pPoint->y = x * std::sin(Rotation) + y * std::cos(Rotation) + pCenter->y;
}
2010-05-29 07:25:38 +00:00
void CLayerQuads::BrushRotate(float Amount)
{
2010-05-29 07:25:38 +00:00
vec2 Center;
GetSize(&Center.x, &Center.y);
Center.x /= 2;
Center.y /= 2;
for(auto &Quad : m_vQuads)
{
for(auto &Point : Quad.m_aPoints)
{
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);
}
}
}
void CLayerQuads::GetSize(float *pWidth, float *pHeight)
2008-01-12 12:27:55 +00:00
{
*pWidth = 0;
*pHeight = 0;
for(const auto &Quad : m_vQuads)
2008-01-12 12:27:55 +00:00
{
for(const auto &Point : Quad.m_aPoints)
2008-01-12 12:27:55 +00:00
{
*pWidth = maximum(*pWidth, fx2f(Point.x));
*pHeight = maximum(*pHeight, fx2f(Point.y));
2008-01-12 12:27:55 +00:00
}
}
}
CUI::EPopupMenuFunctionResult CLayerQuads::RenderProperties(CUIRect *pToolBox)
2008-01-12 12:27:55 +00:00
{
2008-01-17 23:09:49 +00:00
enum
2008-01-12 12:27:55 +00:00
{
PROP_IMAGE = 0,
2008-01-17 23:09:49 +00:00
NUM_PROPS,
};
2010-05-29 07:25:38 +00:00
CProperty aProps[] = {
{"Image", m_Image, PROPTYPE_IMAGE, -1, 0},
{nullptr},
2008-01-17 23:09:49 +00:00
};
2010-05-29 07:25:38 +00:00
static int s_aIds[NUM_PROPS] = {0};
int NewVal = 0;
int Prop = m_pEditor->DoProperties(pToolBox, aProps, s_aIds, &NewVal);
if(Prop != -1)
{
Autosave copy of current editor map periodically to `auto` folder A copy of the map currently open in the editor is saved every 10 minutes to the `maps/auto` folder (interval configurable, see below). The automatically saved map uses the filename of the original map with an additional timestamp. Per map name 10 autosaves are kept in the `auto` folder before old autosaves will be deleted (number configurable, see below). Add config variable `ed_autosave_interval` (0 - 240, default 10) to configure the interval in minutes at which a copy of the current editor map is automatically saved to the 'auto' folder. Add config variable `ed_autosave_max` (0 - 1000, default 10) to configure the maximum number of autosaves that are kept per map name (0 = no limit). Autosaving will not take place in the 5 seconds immediately after the map was last modified by the user, to avoid interrupting the user with the autosave. This will only delay autosaving for up to 1 minute though, so autosaves are not prevented entirely, should the user continuously edit the map. When the editor is reopened after being closed for more than 10 seconds, the autosave timer will be adjusted to compensate for the time that was not spent on editing in the editor. When the map is saved manually by the user the autosave file is also updated, if it's outdated by at least half of the configured autosave interval. This ensures that autosaves are always available as a periodic backup of the map. When a copy of the current map is saved, this does not update the autosave and will also no longer reset the modified state. The modified state should reflect whether changes have been made that are not saved to the current map file. As saving a copy does not update the current file, the modified state should not be reset in this case. Closes #6693.
2023-06-23 15:39:05 +00:00
m_pEditor->m_Map.OnModify();
}
2010-05-29 07:25:38 +00:00
if(Prop == PROP_IMAGE)
2008-01-17 23:09:49 +00:00
{
if(NewVal >= 0)
m_Image = NewVal % m_pEditor->m_Map.m_vpImages.size();
else
m_Image = -1;
2008-01-17 23:09:49 +00:00
}
return CUI::POPUP_KEEP_OPEN;
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
{
for(auto &Quad : m_vQuads)
2008-01-19 12:32:08 +00:00
{
Func(&Quad.m_PosEnv);
Func(&Quad.m_ColorEnv);
2008-01-19 12:32:08 +00:00
}
}
CLayer *CLayerQuads::Duplicate() const
{
return new CLayerQuads(*this);
}
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;
Autosave copy of current editor map periodically to `auto` folder A copy of the map currently open in the editor is saved every 10 minutes to the `maps/auto` folder (interval configurable, see below). The automatically saved map uses the filename of the original map with an additional timestamp. Per map name 10 autosaves are kept in the `auto` folder before old autosaves will be deleted (number configurable, see below). Add config variable `ed_autosave_interval` (0 - 240, default 10) to configure the interval in minutes at which a copy of the current editor map is automatically saved to the 'auto' folder. Add config variable `ed_autosave_max` (0 - 1000, default 10) to configure the maximum number of autosaves that are kept per map name (0 = no limit). Autosaving will not take place in the 5 seconds immediately after the map was last modified by the user, to avoid interrupting the user with the autosave. This will only delay autosaving for up to 1 minute though, so autosaves are not prevented entirely, should the user continuously edit the map. When the editor is reopened after being closed for more than 10 seconds, the autosave timer will be adjusted to compensate for the time that was not spent on editing in the editor. When the map is saved manually by the user the autosave file is also updated, if it's outdated by at least half of the configured autosave interval. This ensures that autosaves are always available as a periodic backup of the map. When a copy of the current map is saved, this does not update the autosave and will also no longer reset the modified state. The modified state should reflect whether changes have been made that are not saved to the current map file. As saving a copy does not update the current file, the modified state should not be reset in this case. Closes #6693.
2023-06-23 15:39:05 +00:00
m_pEditor->m_Map.OnModify();
std::swap(m_vQuads[Index0], m_vQuads[Index1]);
return Index1;
}