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