]> git.localhorst.tv Git - blank.git/blob - src/interface.cpp
1f66b73e06ffc56afd1da35b1b502cafbdb0d193
[blank.git] / src / interface.cpp
1 #include "interface.hpp"
2
3 #include "geometry.hpp"
4 #include "world.hpp"
5
6 #include <glm/glm.hpp>
7 #include <glm/gtc/matrix_transform.hpp>
8
9
10 namespace blank {
11
12 Interface::Interface(World &world)
13 : world(world)
14 , ctrl(world.Player())
15 , hud(world.BlockTypes())
16 , aim_chunk(nullptr)
17 , aim_block(0)
18 , aim_normal()
19 , outline()
20 , outline_transform(1.0f)
21 , move_velocity(0.005f)
22 , pitch_sensitivity(-0.0025f)
23 , yaw_sensitivity(-0.001f)
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         switch (event.keysym.sym) {
39                 case SDLK_w:
40                         front = event.state == SDL_PRESSED;
41                         break;
42                 case SDLK_s:
43                         back = event.state == SDL_PRESSED;
44                         break;
45                 case SDLK_a:
46                         left = event.state == SDL_PRESSED;
47                         break;
48                 case SDLK_d:
49                         right = event.state == SDL_PRESSED;
50                         break;
51                 case SDLK_SPACE:
52                         up = event.state == SDL_PRESSED;
53                         break;
54                 case SDLK_LSHIFT:
55                         down = event.state == SDL_PRESSED;
56                         break;
57
58                 case SDLK_q:
59                         if (event.state == SDL_PRESSED) {
60                                 FaceBlock();
61                         }
62                         break;
63                 case SDLK_e:
64                         if (event.state == SDL_PRESSED) {
65                                 TurnBlock();
66                         }
67                         break;
68         }
69 }
70
71 void Interface::FaceBlock() {
72         selection.SetFace(Block::Face((selection.GetFace() + 1) % Block::FACE_COUNT));
73         hud.Display(selection);
74 }
75
76 void Interface::TurnBlock() {
77         selection.SetTurn(Block::Turn((selection.GetTurn() + 1) % Block::TURN_COUNT));
78         hud.Display(selection);
79 }
80
81
82 void Interface::Handle(const SDL_MouseMotionEvent &event) {
83         ctrl.RotateYaw(event.xrel * yaw_sensitivity);
84         ctrl.RotatePitch(event.yrel * pitch_sensitivity);
85 }
86
87 void Interface::Handle(const SDL_MouseButtonEvent &event) {
88         if (event.state != SDL_PRESSED) return;
89
90         if (event.button == 1) {
91                 RemoveBlock();
92         } else if (event.button == 2) {
93                 PickBlock();
94         } else if (event.button == 3) {
95                 PlaceBlock();
96         }
97 }
98
99 void Interface::PickBlock() {
100         if (!aim_chunk) return;
101         selection = aim_chunk->BlockAt(aim_block);
102         hud.Display(selection);
103 }
104
105 void Interface::PlaceBlock() {
106         if (!aim_chunk) return;
107         Chunk *mod_chunk = aim_chunk;
108         glm::vec3 next_pos = Chunk::ToCoords(aim_block) + aim_normal;
109         if (!Chunk::InBounds(next_pos)) {
110                 mod_chunk = &world.Next(*aim_chunk, aim_normal);
111                 next_pos -= aim_normal * glm::vec3(Chunk::Extent());
112         }
113         mod_chunk->BlockAt(next_pos) = selection;
114         mod_chunk->Invalidate();
115 }
116
117 void Interface::RemoveBlock() {
118         if (!aim_chunk) return;
119         aim_chunk->BlockAt(aim_block) = remove;
120         aim_chunk->Invalidate();
121 }
122
123
124 void Interface::Handle(const SDL_MouseWheelEvent &event) {
125         if (event.y < 0) {
126                 SelectNext();
127         } else if (event.y > 0) {
128                 SelectPrevious();
129         }
130 }
131
132 void Interface::SelectNext() {
133         ++selection.type;
134         if (size_t(selection.type) >= world.BlockTypes().Size()) {
135                 selection.type = 1;
136         }
137         hud.Display(selection);
138 }
139
140 void Interface::SelectPrevious() {
141         --selection.type;
142         if (selection.type <= 0) {
143                 selection.type = world.BlockTypes().Size() - 1;
144         }
145         hud.Display(selection);
146 }
147
148 void Interface::Handle(const SDL_WindowEvent &event) {
149         if (event.event == SDL_WINDOWEVENT_RESIZED) {
150                 hud.Viewport(event.data1, event.data2);
151         }
152 }
153
154
155 void Interface::Update(int dt) {
156         glm::vec3 vel;
157         if (right && !left) {
158                 vel.x = move_velocity;
159         } else if (left && !right) {
160                 vel.x = -move_velocity;
161         }
162         if (up && !down) {
163                 vel.y = move_velocity;
164         } else if (down && !up) {
165                 vel.y = -move_velocity;
166         }
167         if (back && !front) {
168                 vel.z = move_velocity;
169         } else if (front && !back) {
170                 vel.z = -move_velocity;
171         }
172         ctrl.Velocity(vel);
173         ctrl.Update(dt);
174
175         Ray aim = ctrl.Aim();
176         float dist;
177         if (world.Intersection(aim, glm::mat4(1.0f), &aim_chunk, &aim_block, &dist, &aim_normal)) {
178                 outline.Clear();
179                 aim_chunk->Type(aim_chunk->BlockAt(aim_block)).FillOutlineModel(outline);
180                 outline_transform = glm::scale(glm::mat4(1.0f), glm::vec3(1.0002f));
181                 outline_transform = aim_chunk->Transform(world.Player().ChunkCoords());
182                 outline_transform *= aim_chunk->ToTransform(aim_block);
183         } else {
184                 aim_chunk = nullptr;
185         }
186
187 }
188
189
190 void Interface::Render(DirectionalLighting &program) {
191         if (aim_chunk) {
192                 program.SetM(outline_transform);
193                 outline.Draw();
194         }
195
196         hud.Render(program);
197 }
198
199 }