2 #include <msp/gl/meshbuilder.h>
3 #include <msp/input/keys.h>
5 #include "terraintool.h"
11 TerrainTool::TerrainTool(Designer &d, Input::Keyboard &k, Input::Mouse &m, Terrain &t):
14 marker((GL::VERTEX3, GL::COLOR4_UBYTE)),
16 marker_orientation(0),
20 designer.get_layout_3d().get_scene().add(*this);
25 TerrainTool::~TerrainTool()
27 designer.get_layout_3d().get_scene().remove(*this);
30 void TerrainTool::update_marker()
33 GL::MeshBuilder bld(marker);
35 float ts = terrain.get_type().get_tile_size();
36 bld.matrix() *= GL::Matrix::translation(edit_size/2*-ts, edit_size/2*-ts, 0);
39 bld.begin(GL::TRIANGLE_STRIP);
42 bld.vertex(0, ts/2, ts/4);
43 bld.vertex(0, ts/2, -ts/4);
44 bld.vertex(0, 0, ts/4);
45 bld.vertex(0, 0, -ts/4);
46 bld.vertex(ts/2, 0, ts/4);
47 bld.vertex(ts/2, 0, -ts/4);
51 bld.vertex(0, 0, ts/4);
52 bld.vertex(0, 0, -ts/4);
53 bld.vertex(edit_size*ts, 0, ts/4);
54 bld.vertex(edit_size*ts, 0, -ts/4);
55 bld.vertex(edit_size*ts, edit_size*ts, ts/4);
56 bld.vertex(edit_size*ts, edit_size*ts, -ts/4);
57 bld.vertex(0, edit_size*ts, ts/4);
58 bld.vertex(0, edit_size*ts, -ts/4);
66 bld.begin(GL::TRIANGLE_STRIP);
67 bld.vertex(-ts/2, 0, ts/4);
68 bld.vertex(-ts/2, 0, -ts/4);
69 bld.vertex((edit_size+0.5)*ts, 0, ts/4);
70 bld.vertex((edit_size+0.5)*ts, 0, -ts/4);
72 bld.begin(GL::TRIANGLE_STRIP);
73 bld.vertex(0, -ts/2, ts/4);
74 bld.vertex(0, -ts/2, -ts/4);
75 bld.vertex(0, (edit_size+0.5)*ts, ts/4);
76 bld.vertex(0, (edit_size+0.5)*ts, -ts/4);
80 bld.begin(GL::TRIANGLE_STRIP);
81 bld.vertex(-ts/2, edit_size*ts, ts/4);
82 bld.vertex(-ts/2, edit_size*ts, -ts/4);
83 bld.vertex((edit_size+0.5)*ts, edit_size*ts, ts/4);
84 bld.vertex((edit_size+0.5)*ts, edit_size*ts, -ts/4);
86 bld.begin(GL::TRIANGLE_STRIP);
87 bld.vertex(edit_size*ts, -ts/2, ts/4);
88 bld.vertex(edit_size*ts, -ts/2, -ts/4);
89 bld.vertex(edit_size*ts, (edit_size+0.5)*ts, ts/4);
90 bld.vertex(edit_size*ts, (edit_size+0.5)*ts, -ts/4);
96 void TerrainTool::key_press(unsigned key)
98 if(key==Input::KEY_PLUS)
103 else if(key==Input::KEY_MINUS)
113 bool shift_was_held = shift_held;
114 Tool::key_press(key);
115 if(shift_held!=shift_was_held)
120 void TerrainTool::key_release(unsigned key)
122 bool shift_was_held = shift_held;
123 Tool::key_release(key);
124 if(shift_held!=shift_was_held)
128 void TerrainTool::button_press(unsigned btn)
133 drag_start = pointer.y;
137 void TerrainTool::button_release(unsigned btn)
143 void TerrainTool::pointer_motion()
147 float d = (pointer.y-drag_start)*20;
151 float elev = terrain.get_node_elevation(highlight_node);
152 float eg = terrain.get_type().get_elevation_granularity();
155 terrain.set_node_elevation(highlight_node, elev, !shift_held);
158 unsigned bx = highlight_node.x-edit_size/2;
159 unsigned by = highlight_node.y-edit_size/2;
162 bx += highlight_node.i%2;
163 by += highlight_node.i/2;
166 // TODO make it possible to adjust the area without flattening it
167 for(unsigned y=0; y<edit_size; ++y)
168 for(unsigned x=0; x<edit_size; ++x)
169 for(unsigned i=0; i<4; ++i)
171 Terrain::NodeCoordinates c(bx+x, by+y, i);
172 if(c.x<terrain.get_width() && c.y<terrain.get_height())
173 terrain.set_node_elevation(c, elev, !shift_held);
177 marker_position = terrain.get_node_position(highlight_node);
178 drag_start = pointer.y;
183 Ray ray = designer.get_view().create_ray(pointer.x, pointer.y);
184 highlight_node = terrain.get_closest_node(ray);
185 marker_position = terrain.get_node_position(highlight_node);
186 marker_orientation = highlight_node.i^(highlight_node.i>>1);
190 void TerrainTool::render(GL::Renderer &renderer, const GL::Tag &tag) const
195 GL::Renderer::Push push(renderer);
197 renderer.matrix_stack() *= GL::Matrix::translation(marker_position);
198 renderer.matrix_stack() *= GL::Matrix::rotation(Angle::from_turns(marker_orientation*0.25), 0, 0, 1);
199 marker.draw(renderer);