+#include <cmath>
+#include <msp/gl/meshbuilder.h>
+#include <msp/input/keys.h>
+#include "designer.h"
+#include "terraintool.h"
+
+using namespace std;
+using namespace Msp;
+using namespace R2C2;
+
+TerrainTool::TerrainTool(Designer &d, Input::Keyboard &k, Input::Mouse &m, Terrain &t):
+ Tool(d, k, m),
+ terrain(t),
+ marker((GL::VERTEX3, GL::COLOR4_UBYTE)),
+ dragging(false),
+ drag_start(0)
+{
+ designer.get_layout_3d().get_scene().add(*this);
+
+ float ts = terrain.get_type().get_tile_size();
+ GL::MeshBuilder bld(marker);
+ bld.begin(GL::TRIANGLE_STRIP);
+ bld.vertex(-ts/2, 0, -ts/4);
+ bld.vertex(ts/2, 0, -ts/4);
+ bld.vertex(-ts/2, 0, ts/4);
+ bld.vertex(ts/2, 0, ts/4);
+ bld.end();
+ bld.begin(GL::TRIANGLE_STRIP);
+ bld.vertex(0, -ts/2, -ts/4);
+ bld.vertex(0, ts/2, -ts/4);
+ bld.vertex(0, -ts/2, ts/4);
+ bld.vertex(0, ts/2, ts/4);
+ bld.end();
+}
+
+TerrainTool::~TerrainTool()
+{
+ designer.get_layout_3d().get_scene().remove(*this);
+}
+
+void TerrainTool::button_press(unsigned btn)
+{
+ if(btn==1)
+ {
+ dragging = true;
+ drag_start = pointer.y;
+ }
+}
+
+void TerrainTool::button_release(unsigned btn)
+{
+ if(btn==1)
+ dragging = false;
+}
+
+void TerrainTool::pointer_motion()
+{
+ if(dragging)
+ {
+ float d = (pointer.y-drag_start)*20;
+
+ if(abs(d)>1)
+ {
+ float elev = terrain.get_node_elevation(highlight_node);
+ float eg = terrain.get_type().get_elevation_granularity();
+ elev += eg*d;
+ terrain.set_node_elevation(highlight_node, elev, true);
+ marker_position = terrain.get_node_position(highlight_node);
+
+ drag_start = pointer.y;
+ }
+ }
+ else
+ {
+ Ray ray = designer.get_view().create_ray(pointer.x, pointer.y);
+ highlight_node = terrain.get_closest_node(ray);
+ marker_position = terrain.get_node_position(highlight_node);
+ }
+}
+
+void TerrainTool::render(GL::Renderer &renderer, const GL::Tag &tag) const
+{
+ if(tag.id)
+ return;
+
+ GL::Renderer::Push push(renderer);
+
+ renderer.matrix_stack() *= GL::Matrix::translation(marker_position);
+ marker.draw(renderer);
+}