X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fui%2Fui.cpp;h=0c89a2f3a554ab6c0347ed669bdd71d801dea22a;hb=551573ecb04969696f916aeb5485658e298a7f6b;hp=4775999310d1bb6b2bdd44998725597a6011539e;hpb=2c2c02796e9df82d0cda12b59aad638d40b4e8b4;p=blank.git diff --git a/src/ui/ui.cpp b/src/ui/ui.cpp index 4775999..0c89a2f 100644 --- a/src/ui/ui.cpp +++ b/src/ui/ui.cpp @@ -2,16 +2,19 @@ #include "Interface.hpp" #include "../app/Assets.hpp" +#include "../app/Environment.hpp" +#include "../app/FrameCounter.hpp" #include "../app/init.hpp" -#include "../graphics/BlendedSprite.hpp" -#include "../graphics/DirectionalLighting.hpp" +#include "../audio/Audio.hpp" #include "../graphics/Font.hpp" +#include "../graphics/Viewport.hpp" #include "../model/shapes.hpp" #include "../world/World.hpp" #include #include #include +#include #include #include @@ -25,40 +28,31 @@ HUD::HUD(const BlockTypeRegistry &types, const Font &font) , block_buf() , block_transform(1.0f) , block_label() -, label_sprite() -, label_transform(1.0f) -, label_color{0xFF, 0xFF, 0xFF, 0xFF} , block_visible(false) -, crosshair() -, crosshair_transform(1.0f) -, near(100.0f) -, far(-100.0f) -, projection(glm::ortho(0.0f, 1.0f, 1.0f, 0.0f, near, far)) -, view(1.0f) { +, crosshair() { block_transform = glm::translate(block_transform, glm::vec3(50.0f, 50.0f, 0.0f)); block_transform = glm::scale(block_transform, glm::vec3(50.0f)); block_transform = glm::rotate(block_transform, 3.5f, glm::vec3(1.0f, 0.0f, 0.0f)); block_transform = glm::rotate(block_transform, 0.35f, glm::vec3(0.0f, 1.0f, 0.0f)); - crosshair.vertices = std::vector({ + OutlineModel::Buffer buf; + buf.vertices = std::vector({ { -10.0f, 0.0f, 0.0f }, { 10.0f, 0.0f, 0.0f }, { 0.0f, -10.0f, 0.0f }, { 0.0f, 10.0f, 0.0f }, }); - crosshair.indices = std::vector({ + buf.indices = std::vector({ 0, 1, 2, 3 }); - crosshair.colors.resize(4, { 10.0f, 10.0f, 10.0f }); - crosshair.Invalidate(); -} - - -void HUD::Viewport(float width, float height) noexcept { - Viewport(0, 0, width, height); -} - -void HUD::Viewport(float x, float y, float width, float height) noexcept { - projection = glm::ortho(x, width, height, y, near, far); - crosshair_transform = glm::translate(glm::vec3(width * 0.5f, height * 0.5f, 0.0f)); + buf.colors.resize(4, { 10.0f, 10.0f, 10.0f }); + crosshair.Update(buf); + + block_label.Position( + glm::vec3(50.0f, 85.0f, 0.0f), + Gravity::NORTH_WEST, + Gravity::NORTH + ); + block_label.Foreground(glm::vec4(1.0f)); + block_label.Background(glm::vec4(0.5f)); } @@ -66,50 +60,45 @@ void HUD::Display(const Block &b) { const BlockType &type = types.Get(b.type); block_buf.Clear(); - type.FillModel(block_buf, b.Transform()); + type.FillEntityModel(block_buf, b.Transform()); block.Update(block_buf); - font.Render(type.label.c_str(), label_color, block_label); - glm::vec2 size(font.TextSize(type.label.c_str())); - label_sprite.LoadRect(size.x, size.y); - label_transform = glm::translate(glm::vec3( - std::max(5.0f, 50.0f - std::round(size.x * 0.5f)), - 70.0f + size.y, - 0.75f - )); + block_label.Set(font, type.label); block_visible = type.visible; } -void HUD::Render(DirectionalLighting &world_prog, BlendedSprite &sprite_prog) noexcept { - world_prog.Activate(); +void HUD::Render(Viewport &viewport) noexcept { + viewport.ClearDepth(); + + DirectionalLighting &world_prog = viewport.HUDProgram(); world_prog.SetLightDirection({ 1.0f, 3.0f, 5.0f }); // disable distance fog world_prog.SetFogDensity(0.0f); - GLContext::ClearDepthBuffer(); - GLContext::EnableInvertBlending(); - world_prog.SetMVP(crosshair_transform, view, projection); + viewport.EnableInvertBlending(); + viewport.SetCursor(glm::vec3(0.0f), Gravity::CENTER); + world_prog.SetM(viewport.Cursor()); crosshair.Draw(); if (block_visible) { - GLContext::DisableBlending(); + viewport.DisableBlending(); world_prog.SetM(block_transform); block.Draw(); - - sprite_prog.Activate(); - sprite_prog.SetMVP(label_transform, view, projection); - sprite_prog.SetTexture(block_label); - label_sprite.Draw(); + block_label.Render(viewport); } } -Interface::Interface(const Config &config, const Assets &assets, World &world) -: world(world) +Interface::Interface( + const Config &config, + Environment &env, + World &world) +: env(env) +, world(world) , ctrl(world.Player()) -, font(assets.LoadFont("DejaVuSans", 16)) +, font(env.assets.LoadFont("DejaVuSans", 16)) , hud(world.BlockTypes(), font) , aim{{ 0, 0, 0 }, { 0, 0, -1 }} , aim_chunk(nullptr) @@ -117,14 +106,29 @@ Interface::Interface(const Config &config, const Assets &assets, World &world) , aim_normal() , outline() , outline_transform(1.0f) +, counter_text() +, messages(font) +, msg_timer(5000) , config(config) , place_timer(256) , remove_timer(256) , remove(0) , selection(1) +, place_sound(env.assets.LoadSound("thump")) +, remove_sound(env.assets.LoadSound("plop")) , fwd(0) , rev(0) { - hud.Viewport(960, 600); + counter_text.Hide(); + counter_text.Position(glm::vec3(-25.0f, 25.0f, 0.0f), Gravity::NORTH_EAST); + counter_text.Foreground(glm::vec4(1.0f)); + counter_text.Background(glm::vec4(0.5f)); + position_text.Hide(); + position_text.Position(glm::vec3(-25.0f, 25.0f + font.LineSkip(), 0.0f), Gravity::NORTH_EAST); + position_text.Foreground(glm::vec4(1.0f)); + position_text.Background(glm::vec4(0.5f)); + messages.Position(glm::vec3(25.0f, -25.0f, 0.0f), Gravity::SOUTH_WEST); + messages.Foreground(glm::vec4(1.0f)); + messages.Background(glm::vec4(0.5f)); hud.Display(selection); } @@ -175,6 +179,16 @@ void Interface::HandlePress(const SDL_KeyboardEvent &event) { case SDLK_p: PrintSelectionInfo(); break; + + case SDLK_F1: + ToggleVisual(); + break; + case SDLK_F3: + ToggleDebug(); + break; + case SDLK_F4: + ToggleAudio(); + break; } } @@ -215,61 +229,83 @@ void Interface::TurnBlock() { void Interface::ToggleCollision() { ctrl.Controlled().WorldCollidable(!ctrl.Controlled().WorldCollidable()); - std::cout << "collision " << (ctrl.Controlled().WorldCollidable() ? "on" : "off") << std::endl; + if (ctrl.Controlled().WorldCollidable()) { + PostMessage("collision on"); + } else { + PostMessage("collision off"); + } } void Interface::PrintBlockInfo() { std::cout << std::endl; if (!aim_chunk) { - std::cout << "not looking at any block" << std::endl; + PostMessage("not looking at any block"); Ray aim = ctrl.Aim(); - std::cout << "aim ray: " << aim.orig << ", " << aim.dir << std::endl; + std::stringstream s; + s << "aim ray: " << aim.orig << ", " << aim.dir; + PostMessage(s.str()); return; } - std::cout << "looking at block " << aim_block + std::stringstream s; + s << "looking at block " << aim_block << " " << Chunk::ToCoords(aim_block) << " of chunk " << aim_chunk->Position() - << std::endl; + ; + PostMessage(s.str()); Print(aim_chunk->BlockAt(aim_block)); } void Interface::PrintChunkInfo() { std::cout << std::endl; if (!aim_chunk) { - std::cout << "not looking at any block" << std::endl; + PostMessage("not looking at any block"); return; } - std::cout << "looking at chunk " - << aim_chunk->Position() - << std::endl; + std::stringstream s; + s << "looking at chunk " << aim_chunk->Position(); + PostMessage(s.str()); - std::cout << " neighbors:" << std::endl; + PostMessage(" neighbors:"); if (aim_chunk->HasNeighbor(Block::FACE_LEFT)) { - std::cout << " left " << aim_chunk->GetNeighbor(Block::FACE_LEFT).Position() << std::endl; + s.str(""); + s << " left " << aim_chunk->GetNeighbor(Block::FACE_LEFT).Position(); + PostMessage(s.str()); } if (aim_chunk->HasNeighbor(Block::FACE_RIGHT)) { - std::cout << " right " << aim_chunk->GetNeighbor(Block::FACE_RIGHT).Position() << std::endl; + s.str(""); + s << " right " << aim_chunk->GetNeighbor(Block::FACE_RIGHT).Position(); + PostMessage(s.str()); } if (aim_chunk->HasNeighbor(Block::FACE_UP)) { - std::cout << " up " << aim_chunk->GetNeighbor(Block::FACE_UP).Position() << std::endl; + s.str(""); + s << " up " << aim_chunk->GetNeighbor(Block::FACE_UP).Position(); + PostMessage(s.str()); } if (aim_chunk->HasNeighbor(Block::FACE_DOWN)) { - std::cout << " down " << aim_chunk->GetNeighbor(Block::FACE_DOWN).Position() << std::endl; + s.str(""); + s << " down " << aim_chunk->GetNeighbor(Block::FACE_DOWN).Position(); + PostMessage(s.str()); } if (aim_chunk->HasNeighbor(Block::FACE_FRONT)) { - std::cout << " front " << aim_chunk->GetNeighbor(Block::FACE_FRONT).Position() << std::endl; + s.str(""); + s << " front " << aim_chunk->GetNeighbor(Block::FACE_FRONT).Position(); + PostMessage(s.str()); } if (aim_chunk->HasNeighbor(Block::FACE_BACK)) { - std::cout << " back " << aim_chunk->GetNeighbor(Block::FACE_BACK).Position() << std::endl; + s.str(""); + s << " back " << aim_chunk->GetNeighbor(Block::FACE_BACK).Position(); + PostMessage(s.str()); } std::cout << std::endl; } void Interface::PrintLightInfo() { - std::cout + std::stringstream s; + s << "light level " << world.PlayerChunk().GetLight(world.Player().Position()) << " at position " << world.Player().Position() - << std::endl; + ; + PostMessage(s.str()); } void Interface::PrintSelectionInfo() { @@ -278,10 +314,54 @@ void Interface::PrintSelectionInfo() { } void Interface::Print(const Block &block) { - std::cout << "type: " << block.type + std::stringstream s; + s << "type: " << block.type << ", face: " << block.GetFace() << ", turn: " << block.GetTurn() - << std::endl; + ; + PostMessage(s.str()); +} + +void Interface::ToggleAudio() { + config.audio_disabled = !config.audio_disabled; + if (config.audio_disabled) { + PostMessage("audio off"); + } else { + PostMessage("audio on"); + } +} + +void Interface::ToggleVisual() { + config.visual_disabled = !config.visual_disabled; + if (config.visual_disabled) { + PostMessage("visual off"); + } else { + PostMessage("visual on"); + } +} + +void Interface::ToggleDebug() { + counter_text.Toggle(); + position_text.Toggle(); + if (counter_text.Visible()) { + UpdateCounter(); + UpdatePosition(); + } +} + +void Interface::UpdateCounter() { + std::stringstream s; + s << std::setprecision(3) << + "avg: " << env.counter.Average().running << "ms, " + "peak: " << env.counter.Peak().running << "ms"; + std::string text = s.str(); + counter_text.Set(font, text); +} + +void Interface::UpdatePosition() { + std::stringstream s; + s << std::setprecision(3) << "pos: " << ctrl.Controlled().AbsolutePosition(); + position_text.Set(font, s.str()); } @@ -330,13 +410,25 @@ void Interface::PlaceBlock() { next_pos -= aim_normal * glm::vec3(Chunk::Extent()); } mod_chunk->SetBlock(next_pos, selection); - mod_chunk->Invalidate(); + + if (config.audio_disabled) return; + const Entity &player = ctrl.Controlled(); + env.audio.Play( + place_sound, + mod_chunk->ToSceneCoords(player.ChunkCoords(), next_pos) + ); } void Interface::RemoveBlock() noexcept { if (!aim_chunk) return; aim_chunk->SetBlock(aim_block, remove); - aim_chunk->Invalidate(); + + if (config.audio_disabled) return; + const Entity &player = ctrl.Controlled(); + env.audio.Play( + remove_sound, + aim_chunk->ToSceneCoords(player.ChunkCoords(), Chunk::ToCoords(aim_block)) + ); } @@ -366,10 +458,12 @@ void Interface::SelectPrevious() { hud.Display(selection); } -void Interface::Handle(const SDL_WindowEvent &event) noexcept { - if (event.event == SDL_WINDOWEVENT_RESIZED) { - hud.Viewport(event.data1, event.data2); - } + +void Interface::PostMessage(const char *msg) { + messages.PushLine(msg); + msg_timer.Reset(); + msg_timer.Start(); + std::cout << msg << std::endl; } @@ -377,12 +471,17 @@ void Interface::Update(int dt) { ctrl.Velocity(glm::vec3(fwd - rev) * config.move_velocity); ctrl.Update(dt); + msg_timer.Update(dt); place_timer.Update(dt); remove_timer.Update(dt); aim = ctrl.Aim(); CheckAim(); + if (msg_timer.HitOnce()) { + msg_timer.Stop(); + } + if (remove_timer.Hit()) { RemoveBlock(); CheckAim(); @@ -392,13 +491,27 @@ void Interface::Update(int dt) { PlaceBlock(); CheckAim(); } + + if (counter_text.Visible() && env.counter.Changed()) { + UpdateCounter(); + } + if (position_text.Visible()) { + UpdatePosition(); + } +} + +namespace { + +OutlineModel::Buffer outl_buf; + } void Interface::CheckAim() { float dist; if (world.Intersection(aim, glm::mat4(1.0f), aim_chunk, aim_block, dist, aim_normal)) { - outline.Clear(); - aim_chunk->Type(aim_chunk->BlockAt(aim_block)).FillOutlineModel(outline); + outl_buf.Clear(); + aim_chunk->Type(aim_chunk->BlockAt(aim_block)).FillOutlineModel(outl_buf); + outline.Update(outl_buf); outline_transform = glm::scale(glm::vec3(1.0002f)); outline_transform *= aim_chunk->Transform(world.Player().ChunkCoords()); outline_transform *= aim_chunk->ToTransform(Chunk::ToPos(aim_block), aim_block); @@ -408,16 +521,27 @@ void Interface::CheckAim() { } -void Interface::Render(DirectionalLighting &world_prog, BlendedSprite &sprite_prog) noexcept { +void Interface::Render(Viewport &viewport) noexcept { if (config.visual_disabled) return; if (aim_chunk) { - world_prog.Activate(); + DirectionalLighting &world_prog = viewport.EntityProgram(); world_prog.SetM(outline_transform); outline.Draw(); } - hud.Render(world_prog, sprite_prog); + if (counter_text.Visible()) { + counter_text.Render(viewport); + } + if (position_text.Visible()) { + position_text.Render(viewport); + } + + if (msg_timer.Running()) { + messages.Render(viewport); + } + + hud.Render(viewport); } }