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