0ad/source/tools/atlas/GameInterface/Handlers/Elevation.cpp

85 lines
1.9 KiB
C++

#include "precompiled.h"
#include "MessageHandler.h"
#include "../CommandProc.h"
#include "graphics/Terrain.h"
#include "ps/Game.h"
namespace AtlasMessage {
BEGIN_COMMAND(AlterElevation)
// TODO: much more efficient version of this, and without the memory leaks
u16* OldTerrain;
u16* NewTerrain;
void Construct()
{
OldTerrain = NewTerrain = NULL;
}
void Destruct()
{
delete OldTerrain;
delete NewTerrain;
}
void Do()
{
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
int verts = terrain->GetVerticesPerSide()*terrain->GetVerticesPerSide();
OldTerrain = new u16[verts];
memcpy(OldTerrain, terrain->GetHeightMap(), verts*sizeof(u16));
int amount = (int)d->amount;
// debug_printf("%d\n", amount);
// If the thing's being updated very fast, 'amount' is often very
// 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;
}
CVector3D vec;
d->pos.GetWorldSpace(vec);
uint32_t x, z;
terrain->CalcFromPosition(vec, x, z);
terrain->RaiseVertex(x, z, amount);
terrain->MakeDirty(x, z, x, z);
}
void Undo()
{
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
}
void Redo()
{
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
terrain->SetHeightMap(NewTerrain); // CTerrain duplicates the data
}
void MergeWithSelf(cAlterElevation* prev)
{
std::swap(prev->NewTerrain, NewTerrain);
}
END_COMMAND(AlterElevation);
}