]> git.localhorst.tv Git - blank.git/blob - src/interface.cpp
trying to fix the initial aiming issue
[blank.git] / src / interface.cpp
1 #include "interface.hpp"
2
3 #include "geometry.hpp"
4 #include "world.hpp"
5
6 #include <iostream>
7 #include <glm/glm.hpp>
8 #include <glm/gtc/matrix_transform.hpp>
9 #include <glm/gtx/io.hpp>
10
11
12 namespace blank {
13
14 Interface::Interface(const Config &config, World &world)
15 : world(world)
16 , ctrl(world.Player())
17 , hud(world.BlockTypes())
18 , aim_chunk(nullptr)
19 , aim_block(0)
20 , aim_normal()
21 , outline()
22 , outline_transform(1.0f)
23 , config(config)
24 , remove(0)
25 , selection(1)
26 , front(false)
27 , back(false)
28 , left(false)
29 , right(false)
30 , up(false)
31 , down(false) {
32         hud.Viewport(960, 600);
33         hud.Display(selection);
34 }
35
36
37 void Interface::Handle(const SDL_KeyboardEvent &event) {
38         if (config.keyboard_disabled) return;
39
40         switch (event.keysym.sym) {
41                 case SDLK_w:
42                         front = event.state == SDL_PRESSED;
43                         break;
44                 case SDLK_s:
45                         back = event.state == SDL_PRESSED;
46                         break;
47                 case SDLK_a:
48                         left = event.state == SDL_PRESSED;
49                         break;
50                 case SDLK_d:
51                         right = event.state == SDL_PRESSED;
52                         break;
53                 case SDLK_SPACE:
54                         up = event.state == SDL_PRESSED;
55                         break;
56                 case SDLK_LSHIFT:
57                         down = event.state == SDL_PRESSED;
58                         break;
59
60                 case SDLK_q:
61                         if (event.state == SDL_PRESSED) {
62                                 FaceBlock();
63                         }
64                         break;
65                 case SDLK_e:
66                         if (event.state == SDL_PRESSED) {
67                                 TurnBlock();
68                         }
69                         break;
70
71                 case SDLK_b:
72                         if (event.state == SDL_PRESSED) {
73                                 PrintBlockInfo();
74                         }
75                         break;
76                 case SDLK_c:
77                         if (event.state == SDL_PRESSED) {
78                                 PrintChunkInfo();
79                         }
80                         break;
81                 case SDLK_l:
82                         if (event.state == SDL_PRESSED) {
83                                 PrintLightInfo();
84                         }
85                         break;
86                 case SDLK_p:
87                         if (event.state == SDL_PRESSED) {
88                                 PrintSelectionInfo();
89                         }
90                         break;
91         }
92 }
93
94 void Interface::FaceBlock() {
95         selection.SetFace(Block::Face((selection.GetFace() + 1) % Block::FACE_COUNT));
96         hud.Display(selection);
97 }
98
99 void Interface::TurnBlock() {
100         selection.SetTurn(Block::Turn((selection.GetTurn() + 1) % Block::TURN_COUNT));
101         hud.Display(selection);
102 }
103
104 void Interface::PrintBlockInfo() {
105         std::cout << std::endl;
106         if (!aim_chunk) {
107                 std::cout << "not looking at any block" << std::endl;
108                 Ray aim = ctrl.Aim();
109                 std::cout << "aim ray: " << aim.orig << ", " << aim.dir << std::endl;
110                 return;
111         }
112         std::cout << "looking at block " << aim_block
113                 << " " << Chunk::ToCoords(aim_block)
114                 << " of chunk " << aim_chunk->Position()
115                 << std::endl;
116         Print(aim_chunk->BlockAt(aim_block));
117 }
118
119 void Interface::PrintChunkInfo() {
120         std::cout << std::endl;
121         if (!aim_chunk) {
122                 std::cout << "not looking at any block" << std::endl;
123                 return;
124         }
125         std::cout << "looking at chunk "
126                 << aim_chunk->Position()
127                 << std::endl;
128
129         std::cout << "  neighbors:" << std::endl;
130         if (aim_chunk->HasNeighbor(Block::FACE_LEFT)) {
131                 std::cout << " left  " << aim_chunk->GetNeighbor(Block::FACE_LEFT).Position() << std::endl;
132         }
133         if (aim_chunk->HasNeighbor(Block::FACE_RIGHT)) {
134                 std::cout << " right " << aim_chunk->GetNeighbor(Block::FACE_RIGHT).Position() << std::endl;
135         }
136         if (aim_chunk->HasNeighbor(Block::FACE_UP)) {
137                 std::cout << " up    " << aim_chunk->GetNeighbor(Block::FACE_UP).Position() << std::endl;
138         }
139         if (aim_chunk->HasNeighbor(Block::FACE_DOWN)) {
140                 std::cout << " down  " << aim_chunk->GetNeighbor(Block::FACE_DOWN).Position() << std::endl;
141         }
142         if (aim_chunk->HasNeighbor(Block::FACE_FRONT)) {
143                 std::cout << " front " << aim_chunk->GetNeighbor(Block::FACE_FRONT).Position() << std::endl;
144         }
145         if (aim_chunk->HasNeighbor(Block::FACE_BACK)) {
146                 std::cout << " back  " << aim_chunk->GetNeighbor(Block::FACE_BACK).Position() << std::endl;
147         }
148         std::cout << std::endl;
149 }
150
151 void Interface::PrintLightInfo() {
152         std::cout
153                 << "light level " << world.PlayerChunk().GetLight(world.Player().Position())
154                 << " at position " << world.Player().Position()
155                 << std::endl;
156 }
157
158 void Interface::PrintSelectionInfo() {
159         std::cout << std::endl;
160         Print(selection);
161 }
162
163 void Interface::Print(const Block &block) {
164         std::cout << "type: " << block.type
165                 << ", face: " << block.GetFace()
166                 << ", turn: " << block.GetTurn()
167                 << std::endl;
168 }
169
170
171 void Interface::Handle(const SDL_MouseMotionEvent &event) {
172         if (config.mouse_disabled) return;
173         ctrl.RotateYaw(event.xrel * config.yaw_sensitivity);
174         ctrl.RotatePitch(event.yrel * config.pitch_sensitivity);
175 }
176
177 void Interface::Handle(const SDL_MouseButtonEvent &event) {
178         if (config.mouse_disabled) return;
179
180         if (event.state != SDL_PRESSED) return;
181
182         if (event.button == 1) {
183                 RemoveBlock();
184         } else if (event.button == 2) {
185                 PickBlock();
186         } else if (event.button == 3) {
187                 PlaceBlock();
188         }
189 }
190
191 void Interface::PickBlock() {
192         if (!aim_chunk) return;
193         selection = aim_chunk->BlockAt(aim_block);
194         hud.Display(selection);
195 }
196
197 void Interface::PlaceBlock() {
198         if (!aim_chunk) return;
199         Chunk *mod_chunk = aim_chunk;
200         glm::vec3 next_pos = Chunk::ToCoords(aim_block) + aim_normal;
201         if (!Chunk::InBounds(next_pos)) {
202                 mod_chunk = &world.Next(*aim_chunk, aim_normal);
203                 next_pos -= aim_normal * glm::vec3(Chunk::Extent());
204         }
205         mod_chunk->SetBlock(next_pos, selection);
206         mod_chunk->Invalidate();
207 }
208
209 void Interface::RemoveBlock() {
210         if (!aim_chunk) return;
211         aim_chunk->SetBlock(aim_block, remove);
212         aim_chunk->Invalidate();
213 }
214
215
216 void Interface::Handle(const SDL_MouseWheelEvent &event) {
217         if (config.mouse_disabled) return;
218
219         if (event.y < 0) {
220                 SelectNext();
221         } else if (event.y > 0) {
222                 SelectPrevious();
223         }
224 }
225
226 void Interface::SelectNext() {
227         ++selection.type;
228         if (size_t(selection.type) >= world.BlockTypes().Size()) {
229                 selection.type = 1;
230         }
231         hud.Display(selection);
232 }
233
234 void Interface::SelectPrevious() {
235         --selection.type;
236         if (selection.type <= 0) {
237                 selection.type = world.BlockTypes().Size() - 1;
238         }
239         hud.Display(selection);
240 }
241
242 void Interface::Handle(const SDL_WindowEvent &event) {
243         if (event.event == SDL_WINDOWEVENT_RESIZED) {
244                 hud.Viewport(event.data1, event.data2);
245         }
246 }
247
248
249 void Interface::Update(int dt) {
250         glm::vec3 vel;
251         if (right && !left) {
252                 vel.x = config.move_velocity;
253         } else if (left && !right) {
254                 vel.x = -config.move_velocity;
255         }
256         if (up && !down) {
257                 vel.y = config.move_velocity;
258         } else if (down && !up) {
259                 vel.y = -config.move_velocity;
260         }
261         if (back && !front) {
262                 vel.z = config.move_velocity;
263         } else if (front && !back) {
264                 vel.z = -config.move_velocity;
265         }
266         ctrl.Velocity(vel);
267         ctrl.Update(dt);
268
269         Ray aim = ctrl.Aim();
270         float dist;
271         if (world.Intersection(aim, glm::mat4(1.0f), &aim_chunk, &aim_block, &dist, &aim_normal)) {
272                 outline.Clear();
273                 aim_chunk->Type(aim_chunk->BlockAt(aim_block)).FillOutlineModel(outline);
274                 outline_transform = glm::scale(glm::mat4(1.0f), glm::vec3(1.0002f));
275                 outline_transform = aim_chunk->Transform(world.Player().ChunkCoords());
276                 outline_transform *= aim_chunk->ToTransform(aim_block);
277         } else {
278                 aim_chunk = nullptr;
279         }
280
281 }
282
283
284 void Interface::Render(DirectionalLighting &program) {
285         if (config.visual_disabled) return;
286
287         if (aim_chunk) {
288                 program.SetM(outline_transform);
289                 outline.Draw();
290         }
291
292         hud.Render(program);
293 }
294
295 }