]> git.localhorst.tv Git - blank.git/blob - src/interface.cpp
00c291df605e7b799c820947ed09d5ca58ff439b
[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(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 , move_velocity(0.005f)
24 , pitch_sensitivity(-0.0025f)
25 , yaw_sensitivity(-0.001f)
26 , remove(0)
27 , selection(1)
28 , front(false)
29 , back(false)
30 , left(false)
31 , right(false)
32 , up(false)
33 , down(false) {
34         hud.Viewport(960, 600);
35         hud.Display(selection);
36 }
37
38
39 void Interface::Handle(const SDL_KeyboardEvent &event) {
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                 case SDLK_p:
76                         if (event.state == SDL_PRESSED) {
77                                 PrintSelectionInfo();
78                         }
79         }
80 }
81
82 void Interface::FaceBlock() {
83         selection.SetFace(Block::Face((selection.GetFace() + 1) % Block::FACE_COUNT));
84         hud.Display(selection);
85 }
86
87 void Interface::TurnBlock() {
88         selection.SetTurn(Block::Turn((selection.GetTurn() + 1) % Block::TURN_COUNT));
89         hud.Display(selection);
90 }
91
92 void Interface::PrintBlockInfo() {
93         std::cout << std::endl;
94         if (!aim_chunk) {
95                 std::cout << "not looking at any block" << std::endl;
96                 return;
97         }
98         std::cout << "looking at block " << aim_block
99                 << " " << Chunk::ToCoords(aim_block)
100                 << " of chunk " << aim_chunk->Position()
101                 << std::endl;
102         Print(aim_chunk->BlockAt(aim_block));
103 }
104
105 void Interface::PrintSelectionInfo() {
106         std::cout << std::endl;
107         Print(selection);
108 }
109
110 void Interface::Print(const Block &block) {
111         std::cout << "type: " << block.type
112                 << ", face: " << block.GetFace()
113                 << ", turn: " << block.GetTurn()
114                 << std::endl;
115 }
116
117
118 void Interface::Handle(const SDL_MouseMotionEvent &event) {
119         ctrl.RotateYaw(event.xrel * yaw_sensitivity);
120         ctrl.RotatePitch(event.yrel * pitch_sensitivity);
121 }
122
123 void Interface::Handle(const SDL_MouseButtonEvent &event) {
124         if (event.state != SDL_PRESSED) return;
125
126         if (event.button == 1) {
127                 RemoveBlock();
128         } else if (event.button == 2) {
129                 PickBlock();
130         } else if (event.button == 3) {
131                 PlaceBlock();
132         }
133 }
134
135 void Interface::PickBlock() {
136         if (!aim_chunk) return;
137         selection = aim_chunk->BlockAt(aim_block);
138         hud.Display(selection);
139 }
140
141 void Interface::PlaceBlock() {
142         if (!aim_chunk) return;
143         Chunk *mod_chunk = aim_chunk;
144         glm::vec3 next_pos = Chunk::ToCoords(aim_block) + aim_normal;
145         if (!Chunk::InBounds(next_pos)) {
146                 mod_chunk = &world.Next(*aim_chunk, aim_normal);
147                 next_pos -= aim_normal * glm::vec3(Chunk::Extent());
148         }
149         mod_chunk->BlockAt(next_pos) = selection;
150         mod_chunk->Invalidate();
151 }
152
153 void Interface::RemoveBlock() {
154         if (!aim_chunk) return;
155         aim_chunk->BlockAt(aim_block) = remove;
156         aim_chunk->Invalidate();
157 }
158
159
160 void Interface::Handle(const SDL_MouseWheelEvent &event) {
161         if (event.y < 0) {
162                 SelectNext();
163         } else if (event.y > 0) {
164                 SelectPrevious();
165         }
166 }
167
168 void Interface::SelectNext() {
169         ++selection.type;
170         if (size_t(selection.type) >= world.BlockTypes().Size()) {
171                 selection.type = 1;
172         }
173         hud.Display(selection);
174 }
175
176 void Interface::SelectPrevious() {
177         --selection.type;
178         if (selection.type <= 0) {
179                 selection.type = world.BlockTypes().Size() - 1;
180         }
181         hud.Display(selection);
182 }
183
184 void Interface::Handle(const SDL_WindowEvent &event) {
185         if (event.event == SDL_WINDOWEVENT_RESIZED) {
186                 hud.Viewport(event.data1, event.data2);
187         }
188 }
189
190
191 void Interface::Update(int dt) {
192         glm::vec3 vel;
193         if (right && !left) {
194                 vel.x = move_velocity;
195         } else if (left && !right) {
196                 vel.x = -move_velocity;
197         }
198         if (up && !down) {
199                 vel.y = move_velocity;
200         } else if (down && !up) {
201                 vel.y = -move_velocity;
202         }
203         if (back && !front) {
204                 vel.z = move_velocity;
205         } else if (front && !back) {
206                 vel.z = -move_velocity;
207         }
208         ctrl.Velocity(vel);
209         ctrl.Update(dt);
210
211         Ray aim = ctrl.Aim();
212         float dist;
213         if (world.Intersection(aim, glm::mat4(1.0f), &aim_chunk, &aim_block, &dist, &aim_normal)) {
214                 outline.Clear();
215                 aim_chunk->Type(aim_chunk->BlockAt(aim_block)).FillOutlineModel(outline);
216                 outline_transform = glm::scale(glm::mat4(1.0f), glm::vec3(1.0002f));
217                 outline_transform = aim_chunk->Transform(world.Player().ChunkCoords());
218                 outline_transform *= aim_chunk->ToTransform(aim_block);
219         } else {
220                 aim_chunk = nullptr;
221         }
222
223 }
224
225
226 void Interface::Render(DirectionalLighting &program) {
227         if (aim_chunk) {
228                 program.SetM(outline_transform);
229                 outline.Draw();
230         }
231
232         hud.Render(program);
233 }
234
235 }