]> git.tdb.fi Git - r2c2.git/blob - source/designer/terraintool.cpp
Edit a single terrain node at a time if shift is held
[r2c2.git] / source / designer / terraintool.cpp
1 #include <cmath>
2 #include <msp/gl/meshbuilder.h>
3 #include <msp/input/keys.h>
4 #include "designer.h"
5 #include "terraintool.h"
6
7 using namespace std;
8 using namespace Msp;
9 using namespace R2C2;
10
11 TerrainTool::TerrainTool(Designer &d, Input::Keyboard &k, Input::Mouse &m, Terrain &t):
12         Tool(d, k, m),
13         terrain(t),
14         marker((GL::VERTEX3, GL::COLOR4_UBYTE)),
15         marker_orientation(0),
16         dragging(false),
17         drag_start(0)
18 {
19         designer.get_layout_3d().get_scene().add(*this);
20
21         update_marker();
22 }
23
24 TerrainTool::~TerrainTool()
25 {
26         designer.get_layout_3d().get_scene().remove(*this);
27 }
28
29 void TerrainTool::update_marker()
30 {
31         marker.clear();
32         GL::MeshBuilder bld(marker);
33
34         float ts = terrain.get_type().get_tile_size();
35         if(shift_held)
36         {
37                 bld.begin(GL::TRIANGLE_STRIP);
38                 bld.vertex(0, ts/2, ts/4);
39                 bld.vertex(0, ts/2, -ts/4);
40                 bld.vertex(0, 0, ts/4);
41                 bld.vertex(0, 0, -ts/4);
42                 bld.vertex(ts/2, 0, ts/4);
43                 bld.vertex(ts/2, 0, -ts/4);
44                 bld.end();
45         }
46         else
47         {
48                 bld.begin(GL::TRIANGLE_STRIP);
49                 bld.vertex(-ts/2, 0, ts/4);
50                 bld.vertex(-ts/2, 0, -ts/4);
51                 bld.vertex((edit_size+0.5)*ts, 0, ts/4);
52                 bld.vertex((edit_size+0.5)*ts, 0, -ts/4);
53                 bld.end();
54                 bld.begin(GL::TRIANGLE_STRIP);
55                 bld.vertex(0, -ts/2, ts/4);
56                 bld.vertex(0, -ts/2, -ts/4);
57                 bld.vertex(0, (edit_size+0.5)*ts, ts/4);
58                 bld.vertex(0, (edit_size+0.5)*ts, -ts/4);
59                 bld.end();
60         }
61 }
62
63 void TerrainTool::key_press(unsigned key)
64 {
65         bool shift_was_held = shift_held;
66         Tool::key_press(key);
67         if(shift_held!=shift_was_held)
68                 update_marker();
69 }
70
71 void TerrainTool::key_release(unsigned key)
72 {
73         bool shift_was_held = shift_held;
74         Tool::key_release(key);
75         if(shift_held!=shift_was_held)
76                 update_marker();
77 }
78
79 void TerrainTool::button_press(unsigned btn)
80 {
81         if(btn==1)
82         {
83                 dragging = true;
84                 drag_start = pointer.y;
85         }
86 }
87
88 void TerrainTool::button_release(unsigned btn)
89 {
90         if(btn==1)
91                 dragging = false;
92 }
93
94 void TerrainTool::pointer_motion()
95 {
96         if(dragging)
97         {
98                 float d = (pointer.y-drag_start)*20;
99
100                 if(abs(d)>1)
101                 {
102                         float elev = terrain.get_node_elevation(highlight_node);
103                         float eg = terrain.get_type().get_elevation_granularity();
104                         elev += eg*d;
105                         terrain.set_node_elevation(highlight_node, elev, !shift_held);
106                         marker_position = terrain.get_node_position(highlight_node);
107
108                         drag_start = pointer.y;
109                 }
110         }
111         else
112         {
113                 Ray ray = designer.get_view().create_ray(pointer.x, pointer.y);
114                 highlight_node = terrain.get_closest_node(ray);
115                 marker_position = terrain.get_node_position(highlight_node);
116                 marker_orientation = highlight_node.i^(highlight_node.i>>1);
117         }
118 }
119
120 void TerrainTool::render(GL::Renderer &renderer, const GL::Tag &tag) const
121 {
122         if(tag.id)
123                 return;
124
125         GL::Renderer::Push push(renderer);
126
127         renderer.matrix_stack() *= GL::Matrix::translation(marker_position);
128         renderer.matrix_stack() *= GL::Matrix::rotation(Angle::from_turns(marker_orientation*0.25), 0, 0, 1);
129         marker.draw(renderer);
130 }