]> git.localhorst.tv Git - blank.git/blob - src/app.cpp
control (some) application parameters via cmdline
[blank.git] / src / app.cpp
1 #include "app.hpp"
2
3 #include "geometry.hpp"
4
5 #include <iostream>
6 #include <stdexcept>
7
8
9 namespace blank {
10
11 Application::Application()
12 : init_sdl()
13 , init_img()
14 , init_gl()
15 , window()
16 , ctx(window.CreateContext())
17 , init_glew()
18 , program()
19 , cam()
20 , hud()
21 , world()
22 , controller(world.Player())
23 , outline()
24 , outline_visible(false)
25 , outline_transform(1.0f)
26 , running(false)
27 , place(false)
28 , remove(false)
29 , pick(false)
30 , remove_id(0)
31 , place_id(1) {
32         GLContext::EnableVSync();
33
34         world.Generate({ -4, -4, -4 }, { 5, 5, 5});
35
36         hud.Viewport(960, 600);
37         hud.Display(*world.BlockTypes()[place_id]);
38
39         glClearColor(0.0, 0.0, 0.0, 1.0);
40 }
41
42
43 void Application::RunN(size_t n) {
44         Uint32 last = SDL_GetTicks();
45         for (size_t i = 0; i < n; ++i) {
46                 Uint32 now = SDL_GetTicks();
47                 int delta = now - last;
48                 Loop(delta);
49                 last = now;
50         }
51 }
52
53 void Application::RunT(size_t t) {
54         Uint32 last = SDL_GetTicks();
55         Uint32 finish = last + t;
56         while (last < finish) {
57                 Uint32 now = SDL_GetTicks();
58                 int delta = now - last;
59                 Loop(delta);
60                 last = now;
61         }
62 }
63
64 void Application::RunS(size_t n, size_t t) {
65         for (size_t i = 0; i < n; ++i) {
66                 Loop(t);
67         }
68 }
69
70
71 void Application::Run() {
72         running = true;
73         Uint32 last = SDL_GetTicks();
74         window.GrabMouse();
75         while (running) {
76                 Uint32 now = SDL_GetTicks();
77                 int delta = now - last;
78                 Loop(delta);
79                 last = now;
80         }
81 }
82
83 void Application::Loop(int dt) {
84         HandleEvents();
85         Update(dt);
86         Render();
87 }
88
89
90 void Application::HandleEvents() {
91         SDL_Event event;
92         while (SDL_PollEvent(&event)) {
93                 switch (event.type) {
94                         case SDL_KEYDOWN:
95                         case SDL_KEYUP:
96                                 controller.HandleKeyboard(event.key);
97                                 break;
98                         case SDL_MOUSEBUTTONDOWN:
99                                 if (event.button.button == 1) {
100                                         // left
101                                         remove = true;
102                                 } else if (event.button.button == 2) {
103                                         // middle
104                                         pick = true;
105                                 } else if (event.button.button == 3) {
106                                         // right
107                                         place = true;
108                                 }
109                                 break;
110                         case SDL_MOUSEMOTION:
111                                 controller.HandleMouse(event.motion);
112                                 break;
113                         case SDL_QUIT:
114                                 running = false;
115                                 break;
116                         case SDL_WINDOWEVENT:
117                                 switch (event.window.event) {
118                                         case SDL_WINDOWEVENT_RESIZED:
119                                                 cam.Viewport(event.window.data1, event.window.data2);
120                                                 hud.Viewport(event.window.data1, event.window.data2);
121                                                 break;
122                                         default:
123                                                 break;
124                                 }
125                                 break;
126                         default:
127                                 break;
128                 }
129         }
130 }
131
132 void Application::Update(int dt) {
133         controller.Update(dt);
134         world.Update(dt);
135
136         Ray aim = controller.Aim();
137         Chunk *chunk;
138         int blkid;
139         float dist;
140         glm::vec3 normal;
141         if (world.Intersection(aim, glm::mat4(1.0f), &chunk, &blkid, &dist, &normal)) {
142                 glm::vec3 pos = Chunk::ToCoords(blkid);
143                 outline_visible = true;
144                 outline.Clear();
145                 chunk->Type(chunk->BlockAt(blkid)).FillOutlineModel(outline);
146                 outline_transform = glm::translate(chunk->Transform(world.Player().ChunkCoords()), pos);
147                 outline_transform = glm::scale(outline_transform, glm::vec3(1.0001f));
148         } else {
149                 outline_visible = false;
150         }
151
152         if (pick) {
153                 if (chunk) {
154                         place_id = chunk->BlockAt(blkid).type;
155                         hud.Display(*world.BlockTypes()[place_id]);
156                 }
157                 pick = false;
158         }
159         if (remove) {
160                 if (chunk) {
161                         chunk->BlockAt(blkid).type = remove_id;
162                         chunk->Invalidate();
163                 }
164                 remove = false;
165         }
166         if (place) {
167                 if (chunk) {
168                         Chunk *mod_chunk = chunk;
169                         glm::vec3 next_pos = Chunk::ToCoords(blkid) + normal;
170                         if (!Chunk::InBounds(next_pos)) {
171                                 mod_chunk = &world.Next(*chunk, normal);
172                                 next_pos -= normal * glm::vec3(Chunk::Extent());
173                         }
174                         mod_chunk->BlockAt(next_pos).type = place_id;
175                         mod_chunk->Invalidate();
176                 }
177                 place = false;
178         }
179 }
180
181 void Application::Render() {
182         GLContext::Clear();
183
184         program.Activate();
185
186         program.SetProjection(cam.Projection());
187         world.Render(program);
188
189         if (outline_visible) {
190                 program.SetM(outline_transform);
191                 outline.Draw();
192         }
193
194         hud.Render(program);
195
196         window.Flip();
197 }
198
199 }