2005-07-03 18:25:48 +02:00
|
|
|
#include "precompiled.h"
|
|
|
|
|
|
|
|
#include "MessageHandler.h"
|
|
|
|
|
2005-08-20 17:44:50 +02:00
|
|
|
#include "../CommandProc.h"
|
|
|
|
|
2005-07-03 18:25:48 +02:00
|
|
|
#include "graphics/Terrain.h"
|
|
|
|
#include "ps/Game.h"
|
|
|
|
|
2005-10-04 04:50:59 +02:00
|
|
|
#include "../Brushes.h"
|
|
|
|
|
2005-07-03 18:25:48 +02:00
|
|
|
namespace AtlasMessage {
|
|
|
|
|
2005-09-13 05:57:34 +02:00
|
|
|
|
2005-08-20 17:44:50 +02:00
|
|
|
BEGIN_COMMAND(AlterElevation)
|
2005-07-03 18:25:48 +02:00
|
|
|
|
2005-08-20 17:44:50 +02:00
|
|
|
// TODO: much more efficient version of this, and without the memory leaks
|
|
|
|
u16* OldTerrain;
|
|
|
|
u16* NewTerrain;
|
2005-07-03 18:25:48 +02:00
|
|
|
|
2005-08-20 17:44:50 +02:00
|
|
|
void Construct()
|
|
|
|
{
|
|
|
|
OldTerrain = NewTerrain = NULL;
|
|
|
|
}
|
|
|
|
void Destruct()
|
|
|
|
{
|
|
|
|
delete OldTerrain;
|
|
|
|
delete NewTerrain;
|
|
|
|
}
|
2005-07-03 18:25:48 +02:00
|
|
|
|
2005-09-13 05:57:34 +02:00
|
|
|
void Do()
|
|
|
|
{
|
2005-07-03 18:25:48 +02:00
|
|
|
|
2005-08-20 17:44:50 +02:00
|
|
|
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
|
2005-07-03 18:25:48 +02:00
|
|
|
|
2005-08-20 17:44:50 +02:00
|
|
|
int verts = terrain->GetVerticesPerSide()*terrain->GetVerticesPerSide();
|
|
|
|
OldTerrain = new u16[verts];
|
|
|
|
memcpy(OldTerrain, terrain->GetHeightMap(), verts*sizeof(u16));
|
|
|
|
|
2005-09-13 05:57:34 +02:00
|
|
|
int amount = (int)d->amount;
|
|
|
|
|
2005-09-30 02:59:42 +02:00
|
|
|
// If the framerate is very high, 'amount' is often very
|
2005-09-13 05:57:34 +02:00
|
|
|
// small (even zero) so the integer truncation is significant
|
|
|
|
static float roundingError = 0.0;
|
|
|
|
roundingError += d->amount - (float)amount;
|
|
|
|
if (roundingError >= 1.f)
|
|
|
|
{
|
|
|
|
amount += (int)roundingError;
|
|
|
|
roundingError -= (float)(int)roundingError;
|
|
|
|
}
|
|
|
|
|
2005-10-04 04:50:59 +02:00
|
|
|
int x0, y0;
|
|
|
|
d->pos.GetWorldSpace(g_CurrentBrush.m_Centre);
|
|
|
|
g_CurrentBrush.GetBottomRight(x0, y0);
|
|
|
|
for (int dy = 0; dy < g_CurrentBrush.m_H; ++dy)
|
|
|
|
for (int dx = 0; dx < g_CurrentBrush.m_W; ++dx)
|
2005-10-08 05:55:21 +02:00
|
|
|
{
|
|
|
|
// TODO: proper variable raise amount (store floats in terrain delta array?)
|
|
|
|
float b = g_CurrentBrush.Get(dx, dy);
|
|
|
|
if (b)
|
|
|
|
terrain->RaiseVertex(x0+dx, y0+dy, amount*b);
|
|
|
|
}
|
|
|
|
|
|
|
|
terrain->MakeDirty(x0, y0, x0+g_CurrentBrush.m_W, y0+g_CurrentBrush.m_H);
|
2005-08-20 17:44:50 +02:00
|
|
|
}
|
|
|
|
|
2005-09-13 05:57:34 +02:00
|
|
|
void Undo()
|
|
|
|
{
|
2005-08-20 17:44:50 +02:00
|
|
|
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
|
|
|
|
if (! NewTerrain)
|
|
|
|
{
|
|
|
|
int verts = terrain->GetVerticesPerSide()*terrain->GetVerticesPerSide();
|
|
|
|
NewTerrain = new u16[verts];
|
|
|
|
memcpy(NewTerrain, terrain->GetHeightMap(), verts*sizeof(u16));
|
|
|
|
}
|
|
|
|
terrain->SetHeightMap(OldTerrain); // CTerrain duplicates the data
|
|
|
|
}
|
|
|
|
|
2005-09-13 05:57:34 +02:00
|
|
|
void Redo()
|
|
|
|
{
|
2005-08-20 17:44:50 +02:00
|
|
|
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
|
|
|
|
terrain->SetHeightMap(NewTerrain); // CTerrain duplicates the data
|
|
|
|
}
|
|
|
|
|
2005-09-13 05:57:34 +02:00
|
|
|
void MergeWithSelf(cAlterElevation* prev)
|
|
|
|
{
|
2005-08-20 19:37:48 +02:00
|
|
|
std::swap(prev->NewTerrain, NewTerrain);
|
2005-08-20 17:44:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
END_COMMAND(AlterElevation);
|
2005-07-03 18:25:48 +02:00
|
|
|
|
|
|
|
}
|