X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fui%2Fui.cpp;h=0f82139b2a7bd5350db9965e51d89ea1ea3c0843;hb=54f3f1260b95a924fcb40d9d6de3fa2e2c382f6f;hp=1e8a980112c0982fe69a6729849d37b75e50a959;hpb=b066e776622f96e906600a0c4a08de392bd03676;p=blank.git diff --git a/src/ui/ui.cpp b/src/ui/ui.cpp index 1e8a980..0f82139 100644 --- a/src/ui/ui.cpp +++ b/src/ui/ui.cpp @@ -12,10 +12,11 @@ #include "../app/FrameCounter.hpp" #include "../app/init.hpp" #include "../audio/Audio.hpp" +#include "../audio/SoundBank.hpp" #include "../graphics/Font.hpp" #include "../graphics/Viewport.hpp" #include "../io/TokenStreamReader.hpp" -#include "../model/shapes.hpp" +#include "../model/bounds.hpp" #include "../world/BlockLookup.hpp" #include "../world/World.hpp" #include "../world/WorldManipulator.hpp" @@ -32,47 +33,28 @@ namespace blank { -DirectInput::DirectInput(World &world, Player &player, WorldManipulator &manip) +PlayerController::PlayerController(World &world, Player &player) : world(world) , player(player) -, manip(manip) -, aim_world() -, aim_entity() , move_dir(0.0f) , pitch(0.0f) , yaw(0.0f) , dirty(true) -, active_slot(0) -, place_timer(256) -, remove_timer(256) { - -} - -void DirectInput::Update(int dt) { - dirty = true; // world has changed in the meantime - UpdatePlayer(); - - remove_timer.Update(dt); - if (remove_timer.Hit()) { - RemoveBlock(); - } +, aim_world() +, aim_entity() { - place_timer.Update(dt); - if (place_timer.Hit()) { - PlaceBlock(); - } } -void DirectInput::SetMovement(const glm::vec3 &m) { +void PlayerController::SetMovement(const glm::vec3 &m) noexcept { if (dot(m, m) > 1.0f) { move_dir = normalize(m); } else { move_dir = m; } - dirty = true; + Invalidate(); } -void DirectInput::TurnHead(float dp, float dy) { +void PlayerController::TurnHead(float dp, float dy) noexcept { pitch += dp; if (pitch > PI / 2) { pitch = PI / 2; @@ -85,9 +67,71 @@ void DirectInput::TurnHead(float dp, float dy) { } else if (yaw < -PI) { yaw += PI * 2; } + Invalidate(); +} + +void PlayerController::SelectInventory(int i) noexcept { + player.SetInventorySlot(i); +} + +int PlayerController::InventorySlot() const noexcept { + return player.GetInventorySlot(); +} + +void PlayerController::Invalidate() noexcept { dirty = true; } +void PlayerController::UpdatePlayer() noexcept { + constexpr float max_vel = 5.0f; // in m/s + if (dirty) { + player.GetEntity().Orientation(glm::quat(glm::vec3(0.0f, yaw, 0.0f))); + player.GetEntity().GetModel().EyesState().orientation = glm::quat(glm::vec3(pitch, 0.0f, 0.0f)); + player.GetEntity().TargetVelocity(glm::rotateY(move_dir * max_vel, yaw)); + + Ray aim = player.Aim(); + if (!world.Intersection(aim, glm::mat4(1.0f), player.GetEntity().ChunkCoords(), aim_world)) { + aim_world = WorldCollision(); + } + if (!world.Intersection(aim, glm::mat4(1.0f), player.GetEntity(), aim_entity)) { + aim_entity = EntityCollision(); + } + if (aim_world && aim_entity) { + // got both, pick the closest one + if (aim_world.depth < aim_entity.depth) { + aim_entity = EntityCollision(); + } else { + aim_world = WorldCollision(); + } + } + dirty = false; + } +} + + +DirectInput::DirectInput(World &world, Player &player, WorldManipulator &manip) +: PlayerController(world, player) +, manip(manip) +, place_timer(256) +, remove_timer(256) { + +} + +void DirectInput::Update(int dt) { + Invalidate(); // world has changed in the meantime + UpdatePlayer(); + + remove_timer.Update(dt); + if (remove_timer.Hit()) { + RemoveBlock(); + } + + place_timer.Update(dt); + if (place_timer.Hit()) { + PlaceBlock(); + } +} + void DirectInput::StartPrimaryAction() { if (!remove_timer.Running()) { RemoveBlock(); @@ -118,58 +162,29 @@ void DirectInput::StopTertiaryAction() { // nothing } -void DirectInput::SelectInventory(int) { -} - -void DirectInput::UpdatePlayer() { - constexpr float max_vel = 0.005f; - if (dirty) { - player.GetEntity().Orientation(glm::quat(glm::vec3(pitch, yaw, 0.0f))); - player.GetEntity().Velocity(glm::rotateY(move_dir * max_vel, yaw)); - - Ray aim = player.Aim(); - if (!world.Intersection(aim, glm::mat4(1.0f), player.GetEntity().ChunkCoords(), aim_world)) { - aim_world = WorldCollision(); - } - if (!world.Intersection(aim, glm::mat4(1.0f), player.GetEntity(), aim_entity)) { - aim_entity = EntityCollision(); - } - if (aim_world && aim_entity) { - // got both, pick the closest one - if (aim_world.depth < aim_entity.depth) { - aim_entity = EntityCollision(); - } else { - aim_world = WorldCollision(); - } - } - // TODO: update outline if applicable - dirty = false; - } -} - void DirectInput::PickBlock() { UpdatePlayer(); - if (!aim_world) return; - player.SetInventorySlot(aim_world.GetBlock().type - 1); + if (!BlockFocus()) return; + SelectInventory(BlockFocus().GetBlock().type - 1); } void DirectInput::PlaceBlock() { UpdatePlayer(); - if (!aim_world) return; + if (!BlockFocus()) return; - BlockLookup next_block(aim_world.chunk, aim_world.BlockPos(), Block::NormalFace(aim_world.normal)); + BlockLookup next_block(BlockFocus().chunk, BlockFocus().BlockPos(), Block::NormalFace(BlockFocus().normal)); if (!next_block) { return; } - manip.SetBlock(next_block.GetChunk(), next_block.GetBlockIndex(), Block(player.GetInventorySlot() + 1)); - dirty = true; + manip.SetBlock(next_block.GetChunk(), next_block.GetBlockIndex(), Block(InventorySlot() + 1)); + Invalidate(); } void DirectInput::RemoveBlock() { UpdatePlayer(); - if (!aim_world) return; - manip.SetBlock(aim_world.GetChunk(), aim_world.block, Block(0)); - dirty = true; + if (!BlockFocus()) return; + manip.SetBlock(BlockFocus().GetChunk(), BlockFocus().block, Block(0)); + Invalidate(); } @@ -197,8 +212,11 @@ HUD::HUD(Environment &env, Config &config, const Player &player) // message box , messages(env.assets.small_ui_font) , msg_timer(5000) +, msg_keep(false) // crosshair , crosshair() { + const float ls = env.assets.small_ui_font.LineSkip(); + // "inventory" block_transform = glm::translate(block_transform, glm::vec3(50.0f, 50.0f, 0.0f)); block_transform = glm::scale(block_transform, glm::vec3(50.0f)); @@ -216,42 +234,42 @@ HUD::HUD(Environment &env, Config &config, const Player &player) 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.Position(glm::vec3(-25.0f, 25.0f + env.assets.small_ui_font.LineSkip(), 0.0f), Gravity::NORTH_EAST); + position_text.Position(glm::vec3(-25.0f, 25.0f + ls, 0.0f), Gravity::NORTH_EAST); position_text.Foreground(glm::vec4(1.0f)); position_text.Background(glm::vec4(0.5f)); - orientation_text.Position(glm::vec3(-25.0f, 25.0f + 2 * env.assets.small_ui_font.LineSkip(), 0.0f), Gravity::NORTH_EAST); + orientation_text.Position(glm::vec3(-25.0f, 25.0f + 2 * ls, 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.Position(glm::vec3(-25.0f, 25.0f + 4 * ls, 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.Position(glm::vec3(-25.0f, 25.0f + 4 * ls, 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"); // message box - messages.Position(glm::vec3(25.0f, -25.0f, 0.0f), Gravity::SOUTH_WEST); + messages.Position(glm::vec3(25.0f, -25.0f - 2 * ls, 0.0f), Gravity::SOUTH_WEST); messages.Foreground(glm::vec4(1.0f)); messages.Background(glm::vec4(0.5f)); // crosshair - OutlineModel::Buffer buf; + PrimitiveMesh::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 }, }); - buf.indices = std::vector({ + buf.indices = std::vector({ 0, 1, 2, 3 }); - buf.colors.resize(4, { 10.0f, 10.0f, 10.0f }); + buf.colors.resize(4, { 10.0f, 10.0f, 10.0f, 1.0f }); crosshair.Update(buf); } namespace { -OutlineModel::Buffer outl_buf; +PrimitiveMesh::Buffer outl_buf; } @@ -259,7 +277,7 @@ void HUD::FocusBlock(const Chunk &chunk, int index) { const Block &block = chunk.BlockAt(index); const BlockType &type = chunk.Type(index); outl_buf.Clear(); - type.FillOutlineModel(outl_buf); + type.OutlinePrimitiveMesh(outl_buf); outline.Update(outl_buf); outline_transform = chunk.Transform(player.GetEntity().ChunkCoords()); outline_transform *= chunk.ToTransform(Chunk::ToPos(index), index); @@ -299,7 +317,7 @@ void HUD::DisplayNone() { void HUD::Display(const BlockType &type) { block_buf.Clear(); - type.FillEntityModel(block_buf); + type.FillEntityMesh(block_buf); block.Update(block_buf); block_label.Set(env.assets.small_ui_font, type.label); @@ -362,9 +380,9 @@ void HUD::Update(int dt) { void HUD::Render(Viewport &viewport) noexcept { // block focus if (outline_visible && config.video.world) { - PlainColor &outline_prog = viewport.WorldOutlineProgram(); + PlainColor &outline_prog = viewport.WorldColorProgram(); outline_prog.SetM(outline_transform); - outline.Draw(); + outline.DrawLines(); } // clear depth buffer so everything renders above the world @@ -385,16 +403,16 @@ void HUD::Render(Viewport &viewport) noexcept { } // message box - if (msg_timer.Running()) { + if (msg_keep || msg_timer.Running()) { messages.Render(viewport); } // crosshair - PlainColor &outline_prog = viewport.HUDOutlineProgram(); + PlainColor &outline_prog = viewport.HUDColorProgram(); viewport.EnableInvertBlending(); viewport.SetCursor(glm::vec3(0.0f), Gravity::CENTER); outline_prog.SetM(viewport.Cursor()); - crosshair.Draw(); + crosshair.DrawLines(); } // debug overlay @@ -411,22 +429,26 @@ void HUD::Render(Viewport &viewport) noexcept { } -InteractiveManipulator::InteractiveManipulator(Environment &env, Entity &player) +InteractiveManipulator::InteractiveManipulator(Audio &audio, const SoundBank &sounds, Entity &player) : player(player) -, audio(env.audio) -, place_sound(env.loader.LoadSound("thump")) -, remove_sound(env.loader.LoadSound("plop")) { +, audio(audio) +, sounds(sounds) { } void InteractiveManipulator::SetBlock(Chunk &chunk, int index, const Block &block) { + const BlockType &old_type = chunk.Type(index); chunk.SetBlock(index, block); + const BlockType &new_type = chunk.Type(index); glm::vec3 coords = chunk.ToSceneCoords(player.ChunkCoords(), Chunk::ToCoords(index)); - // TODO: get sound effect from block type - if (block.type == 0) { - audio.Play(remove_sound, coords); + if (new_type.id == 0) { + if (old_type.remove_sound >= 0) { + audio.Play(sounds[old_type.remove_sound], coords); + } } else { - audio.Play(place_sound, coords); + if (new_type.place_sound >= 0) { + audio.Play(sounds[new_type.place_sound], coords); + } } } @@ -636,6 +658,7 @@ void Interface::InvAbs(int s) { while (slot < 0) { slot += num_slots; } + player_ctrl.SelectInventory(slot); } void Interface::InvRel(int delta) {