]> git.localhorst.tv Git - blank.git/blobdiff - src/ui/ui.cpp
give unique IDs to entities
[blank.git] / src / ui / ui.cpp
index ef005f6dea778ec8f243a8087e7167c0368f59f1..2ec4d883d3e6f963dc047e85694a5bfb9bcec00d 100644 (file)
@@ -11,6 +11,7 @@
 #include "../graphics/Viewport.hpp"
 #include "../io/TokenStreamReader.hpp"
 #include "../model/shapes.hpp"
+#include "../world/BlockLookup.hpp"
 #include "../world/World.hpp"
 
 #include <algorithm>
@@ -58,6 +59,10 @@ HUD::HUD(const BlockTypeRegistry &types, const Font &font)
 }
 
 
+void HUD::DisplayNone() {
+       block_visible = false;
+}
+
 void HUD::Display(const Block &b) {
        const BlockType &type = types.Get(b.type);
 
@@ -97,29 +102,33 @@ void HUD::Render(Viewport &viewport) noexcept {
 Interface::Interface(
        const Config &config,
        Environment &env,
-       World &world)
+       World &world,
+       Entity &player)
 : env(env)
 , world(world)
-, ctrl(world.Player())
+// let's assume this succeeds and hope for the best for now
+, ctrl(player)
 , hud(world.BlockTypes(), env.assets.small_ui_font)
 , aim{{ 0, 0, 0 }, { 0, 0, -1 }}
-, aim_chunk(nullptr)
-, aim_block(0)
-, aim_normal()
+, aim_world()
+, aim_entity()
 , outline()
 , outline_transform(1.0f)
 , counter_text()
 , position_text()
 , orientation_text()
+, block_text()
+, last_block()
+, last_entity(nullptr)
 , messages(env.assets.small_ui_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"))
+, selection(0)
+, place_sound(env.loader.LoadSound("thump"))
+, remove_sound(env.loader.LoadSound("plop"))
 , fwd(0)
 , rev(0)
 , debug(false) {
@@ -132,10 +141,18 @@ Interface::Interface(
        orientation_text.Position(glm::vec3(-25.0f, 25.0f + 2 * env.assets.small_ui_font.LineSkip(), 0.0f), Gravity::NORTH_EAST);
        orientation_text.Foreground(glm::vec4(1.0f));
        orientation_text.Background(glm::vec4(0.5f));
+       block_text.Position(glm::vec3(-25.0f, 25.0f + 4 * env.assets.small_ui_font.LineSkip(), 0.0f), Gravity::NORTH_EAST);
+       block_text.Foreground(glm::vec4(1.0f));
+       block_text.Background(glm::vec4(0.5f));
+       block_text.Set(env.assets.small_ui_font, "Block: none");
+       entity_text.Position(glm::vec3(-25.0f, 25.0f + 4 * env.assets.small_ui_font.LineSkip(), 0.0f), Gravity::NORTH_EAST);
+       entity_text.Foreground(glm::vec4(1.0f));
+       entity_text.Background(glm::vec4(0.5f));
+       entity_text.Set(env.assets.small_ui_font, "Entity: none");
        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);
+       hud.DisplayNone();
 }
 
 
@@ -189,19 +206,6 @@ void Interface::HandlePress(const SDL_KeyboardEvent &event) {
                        ToggleCollision();
                        break;
 
-               case Keymap::PRINT_BLOCK:
-                       PrintBlockInfo();
-                       break;
-               case Keymap::PRINT_CHUNK:
-                       PrintChunkInfo();
-                       break;
-               case Keymap::PRINT_LIGHT:
-                       PrintLightInfo();
-                       break;
-               case Keymap::PRINT_SELECTION:
-                       PrintSelectionInfo();
-                       break;
-
                case Keymap::TOGGLE_VISUAL:
                        ToggleVisual();
                        break;
@@ -268,92 +272,6 @@ void Interface::ToggleCollision() {
        }
 }
 
-void Interface::PrintBlockInfo() {
-       std::cout << std::endl;
-       if (!aim_chunk) {
-               PostMessage("not looking at any block");
-               Ray aim = ctrl.Aim();
-               std::stringstream s;
-               s << "aim ray: " << aim.orig << ", " << aim.dir;
-               PostMessage(s.str());
-               return;
-       }
-       std::stringstream s;
-       s << "looking at block " << aim_block
-               << " " << Chunk::ToCoords(aim_block)
-               << " of chunk " << aim_chunk->Position()
-       ;
-       PostMessage(s.str());
-       Print(aim_chunk->BlockAt(aim_block));
-}
-
-void Interface::PrintChunkInfo() {
-       std::cout << std::endl;
-       if (!aim_chunk) {
-               PostMessage("not looking at any block");
-               return;
-       }
-       std::stringstream s;
-       s << "looking at chunk " << aim_chunk->Position();
-       PostMessage(s.str());
-
-       PostMessage("  neighbors:");
-       if (aim_chunk->HasNeighbor(Block::FACE_LEFT)) {
-               s.str("");
-               s << " left  " << aim_chunk->GetNeighbor(Block::FACE_LEFT).Position();
-               PostMessage(s.str());
-       }
-       if (aim_chunk->HasNeighbor(Block::FACE_RIGHT)) {
-               s.str("");
-               s << " right " << aim_chunk->GetNeighbor(Block::FACE_RIGHT).Position();
-               PostMessage(s.str());
-       }
-       if (aim_chunk->HasNeighbor(Block::FACE_UP)) {
-               s.str("");
-               s << " up    " << aim_chunk->GetNeighbor(Block::FACE_UP).Position();
-               PostMessage(s.str());
-       }
-       if (aim_chunk->HasNeighbor(Block::FACE_DOWN)) {
-               s.str("");
-               s << " down  " << aim_chunk->GetNeighbor(Block::FACE_DOWN).Position();
-               PostMessage(s.str());
-       }
-       if (aim_chunk->HasNeighbor(Block::FACE_FRONT)) {
-               s.str("");
-               s << " front " << aim_chunk->GetNeighbor(Block::FACE_FRONT).Position();
-               PostMessage(s.str());
-       }
-       if (aim_chunk->HasNeighbor(Block::FACE_BACK)) {
-               s.str("");
-               s << " back  " << aim_chunk->GetNeighbor(Block::FACE_BACK).Position();
-               PostMessage(s.str());
-       }
-       std::cout << std::endl;
-}
-
-void Interface::PrintLightInfo() {
-       std::stringstream s;
-       s
-               << "light level " << world.PlayerChunk().GetLight(world.Player().Position())
-               << " at position " << world.Player().Position()
-       ;
-       PostMessage(s.str());
-}
-
-void Interface::PrintSelectionInfo() {
-       std::cout << std::endl;
-       Print(selection);
-}
-
-void Interface::Print(const Block &block) {
-       std::stringstream s;
-       s << "type: " << block.type
-               << ", face: " << block.GetFace()
-               << ", turn: " << block.GetTurn()
-       ;
-       PostMessage(s.str());
-}
-
 void Interface::ToggleAudio() {
        config.audio_disabled = !config.audio_disabled;
        if (config.audio_disabled) {
@@ -378,6 +296,8 @@ void Interface::ToggleDebug() {
                UpdateCounter();
                UpdatePosition();
                UpdateOrientation();
+               UpdateBlockInfo();
+               UpdateEntityInfo();
        }
 }
 
@@ -403,6 +323,39 @@ void Interface::UpdateOrientation() {
        orientation_text.Set(env.assets.small_ui_font, s.str());
 }
 
+void Interface::UpdateBlockInfo() {
+       if (aim_world) {
+               const Block &block = aim_world.GetBlock();
+               if (last_block != block) {
+                       std::stringstream s;
+                       s << "Block: "
+                               << aim_world.GetType().label
+                               << ", face: " << block.GetFace()
+                               << ", turn: " << block.GetTurn();
+                       block_text.Set(env.assets.small_ui_font, s.str());
+                       last_block = block;
+               }
+       } else {
+               if (last_block != Block()) {
+                       std::stringstream s;
+                       s << "Block: none";
+                       block_text.Set(env.assets.small_ui_font, s.str());
+                       last_block = Block();
+               }
+       }
+}
+
+void Interface::UpdateEntityInfo() {
+       if (aim_entity) {
+               if (last_entity != aim_entity.entity) {
+                       std::stringstream s;
+                       s << "Entity: " << aim_entity.entity->Name();
+                       entity_text.Set(env.assets.small_ui_font, s.str());
+                       last_entity = aim_entity.entity;
+               }
+       }
+}
+
 
 void Interface::Handle(const SDL_MouseMotionEvent &event) {
        if (config.mouse_disabled) return;
@@ -435,38 +388,37 @@ void Interface::HandleRelease(const SDL_MouseButtonEvent &event) {
 }
 
 void Interface::PickBlock() {
-       if (!aim_chunk) return;
-       selection = aim_chunk->BlockAt(aim_block);
+       if (!aim_world) return;
+       selection = aim_world.GetBlock();
        hud.Display(selection);
 }
 
 void Interface::PlaceBlock() {
-       if (!aim_chunk) return;
-       Chunk *mod_chunk = aim_chunk;
-       glm::vec3 next_pos = Chunk::ToCoords(aim_block) + aim_normal;
-       if (!Chunk::InBounds(next_pos)) {
-               mod_chunk = &world.Next(*aim_chunk, aim_normal);
-               next_pos -= aim_normal * glm::vec3(Chunk::Extent());
+       if (!aim_world) return;
+
+       glm::vec3 next_pos = aim_world.BlockCoords() + aim_world.normal;
+       BlockLookup next_block(&aim_world.GetChunk(), next_pos);
+       if (next_block) {
        }
-       mod_chunk->SetBlock(next_pos, selection);
+       next_block.SetBlock(selection);
 
        if (config.audio_disabled) return;
        const Entity &player = ctrl.Controlled();
        env.audio.Play(
                place_sound,
-               mod_chunk->ToSceneCoords(player.ChunkCoords(), next_pos)
+               aim_world.GetChunk().ToSceneCoords(player.ChunkCoords(), next_pos)
        );
 }
 
 void Interface::RemoveBlock() noexcept {
-       if (!aim_chunk) return;
-       aim_chunk->SetBlock(aim_block, remove);
+       if (!aim_world) return;
+       aim_world.SetBlock(remove);
 
        if (config.audio_disabled) return;
        const Entity &player = ctrl.Controlled();
        env.audio.Play(
                remove_sound,
-               aim_chunk->ToSceneCoords(player.ChunkCoords(), Chunk::ToCoords(aim_block))
+               aim_world.GetChunk().ToSceneCoords(player.ChunkCoords(), aim_world.BlockCoords())
        );
 }
 
@@ -547,24 +499,43 @@ OutlineModel::Buffer outl_buf;
 }
 
 void Interface::CheckAim() {
-       float dist;
-       if (world.Intersection(aim, glm::mat4(1.0f), aim_chunk, aim_block, dist, aim_normal)) {
-               outl_buf.Clear();
-               aim_chunk->Type(aim_chunk->BlockAt(aim_block)).FillOutlineModel(outl_buf);
-               outline.Update(outl_buf);
-               outline_transform = aim_chunk->Transform(world.Player().ChunkCoords());
-               outline_transform *= aim_chunk->ToTransform(Chunk::ToPos(aim_block), aim_block);
-               outline_transform *= glm::scale(glm::vec3(1.005f));
-       } else {
-               aim_chunk = nullptr;
+       if (!world.Intersection(aim, glm::mat4(1.0f), ctrl.Controlled().ChunkCoords(), aim_world)) {
+               aim_world = WorldCollision();
+       }
+       if (!world.Intersection(aim, glm::mat4(1.0f), ctrl.Controlled(), aim_entity)) {
+               aim_entity = EntityCollision();
+       }
+       if (aim_world && aim_entity) {
+               // got both, pick the closest one
+               if (aim_world.depth < aim_entity.depth) {
+                       UpdateOutline();
+                       aim_entity = EntityCollision();
+               } else {
+                       aim_world = WorldCollision();
+               }
+       } else if (aim_world) {
+               UpdateOutline();
        }
+       if (debug) {
+               UpdateBlockInfo();
+               UpdateEntityInfo();
+       }
+}
+
+void Interface::UpdateOutline() {
+       outl_buf.Clear();
+       aim_world.GetType().FillOutlineModel(outl_buf);
+       outline.Update(outl_buf);
+       outline_transform = aim_world.GetChunk().Transform(Player().ChunkCoords());
+       outline_transform *= aim_world.BlockTransform();
+       outline_transform *= glm::scale(glm::vec3(1.005f));
 }
 
 
 void Interface::Render(Viewport &viewport) noexcept {
        if (config.visual_disabled) return;
 
-       if (aim_chunk) {
+       if (aim_world) {
                PlainColor &outline_prog = viewport.WorldOutlineProgram();
                outline_prog.SetM(outline_transform);
                outline.Draw();
@@ -574,6 +545,11 @@ void Interface::Render(Viewport &viewport) noexcept {
                counter_text.Render(viewport);
                position_text.Render(viewport);
                orientation_text.Render(viewport);
+               if (aim_world) {
+                       block_text.Render(viewport);
+               } else if (aim_entity) {
+                       entity_text.Render(viewport);
+               }
        }
 
        if (msg_timer.Running()) {
@@ -637,11 +613,6 @@ void Keymap::LoadDefault() {
        Map(SDL_SCANCODE_F3, TOGGLE_DEBUG);
        Map(SDL_SCANCODE_F4, TOGGLE_AUDIO);
 
-       Map(SDL_SCANCODE_B, PRINT_BLOCK);
-       Map(SDL_SCANCODE_C, PRINT_CHUNK);
-       Map(SDL_SCANCODE_L, PRINT_LIGHT);
-       Map(SDL_SCANCODE_P, PRINT_SELECTION);
-
        Map(SDL_SCANCODE_ESCAPE, EXIT);
 }
 
@@ -733,14 +704,6 @@ const char *Keymap::ActionToString(Action action) {
                        return "toggle_visual";
                case TOGGLE_DEBUG:
                        return "toggle_debug";
-               case PRINT_BLOCK:
-                       return "print_block";
-               case PRINT_CHUNK:
-                       return "print_chunk";
-               case PRINT_LIGHT:
-                       return "print_light";
-               case PRINT_SELECTION:
-                       return "print_selection";
                case EXIT:
                        return "exit";
        }
@@ -781,14 +744,6 @@ Keymap::Action Keymap::StringToAction(const std::string &str) {
                return TOGGLE_VISUAL;
        } else if (str == "toggle_debug") {
                return TOGGLE_DEBUG;
-       } else if (str == "print_block") {
-               return PRINT_BLOCK;
-       } else if (str == "print_chunk") {
-               return PRINT_CHUNK;
-       } else if (str == "print_light") {
-               return PRINT_LIGHT;
-       } else if (str == "print_selection") {
-               return PRINT_SELECTION;
        } else if (str == "exit") {
                return EXIT;
        } else {