diff --git a/src/audio/audio.cpp b/src/audio/audio.cpp index e8fd96e14..cfc84ce00 100644 --- a/src/audio/audio.cpp +++ b/src/audio/audio.cpp @@ -190,6 +190,10 @@ void audio::initialize( audio::get_channel(channel.name)->setVolume(value * value); }, true)); } + objects_keeper.keepAlive(settings.acousticEffects.observe([=](auto value) { + if (value) return; + backend->setAcoustics(audio::Acoustics {}); + }, true)); if (inputEnabled) { ::input_device = backend->openInputDevice("", 44100, 1, 16); diff --git a/src/coders/vec3.cpp b/src/coders/vec3.cpp index 974b9a633..e00bdd662 100644 --- a/src/coders/vec3.cpp +++ b/src/coders/vec3.cpp @@ -23,6 +23,10 @@ enum AttributeType { COLOR }; +enum MaterialFlag { + SHADELESS = 1 +}; + struct VertexAttribute { AttributeType type; int flags; @@ -62,7 +66,7 @@ static VertexAttribute load_attribute(ByteReader& reader) { static model::Mesh build_mesh( const std::vector& attrs, const util::Buffer& indices, - const std::string& texture + const Material& material ) { const glm::vec3* coords = nullptr; const glm::vec2* uvs = nullptr; @@ -112,7 +116,11 @@ static model::Mesh build_mesh( } vertices.push_back(std::move(vertex)); } - return model::Mesh {texture, std::move(vertices)}; + return model::Mesh { + material.name, + std::move(vertices), + (material.flags & MaterialFlag::SHADELESS) == 0 + }; } static model::Mesh load_mesh( @@ -154,7 +162,7 @@ static model::Mesh load_mesh( return build_mesh( attributes, indices, - materials.at(materialId).name + materials.at(materialId) ); } diff --git a/src/devtools/stdin_cmd_reader.cpp b/src/devtools/stdin_cmd_reader.cpp index 8e4a48c22..90dc07e2b 100644 --- a/src/devtools/stdin_cmd_reader.cpp +++ b/src/devtools/stdin_cmd_reader.cpp @@ -4,6 +4,7 @@ #include "logic/CommandsInterpreter.hpp" #include "coders/json.hpp" #include "debug/Logger.hpp" +#include "util/platform.hpp" #include #include @@ -18,7 +19,12 @@ void cmd::start_stdin_cmd_reader(Engine& engine) { logger.info() << "reader thread started"; std::string line; - while (std::getline(std::cin, line)) { + while (true) { + if (!platform::stdin_has_data()) { + platform::sleep(10); + continue; + } + std::getline(std::cin, line); if (line.empty()) { continue; } diff --git a/src/graphics/render/BlockWrapsRenderer.cpp b/src/graphics/render/BlockWrapsRenderer.cpp index 24a7955b8..fb72d3347 100644 --- a/src/graphics/render/BlockWrapsRenderer.cpp +++ b/src/graphics/render/BlockWrapsRenderer.cpp @@ -8,18 +8,16 @@ #include "graphics/core/DrawContext.hpp" #include "graphics/render/MainBatch.hpp" #include "lighting/Lightmap.hpp" -#include "objects/Player.hpp" #include "voxels/Block.hpp" #include "voxels/Chunks.hpp" -#include "world/Level.hpp" #include BlockWrapsRenderer::BlockWrapsRenderer( - const Assets& assets, const Level& level, const Chunks& chunks + const Assets& assets, const Content& content, const Chunks& chunks ) : assets(assets), - level(level), + content(content), chunks(chunks), batch(std::make_unique(1024)) { } @@ -43,16 +41,14 @@ void BlockWrapsRenderer::draw(BlockWrapper& wrapper, const Texture* texture) { } const voxel* vox = chunks.get(wrapper.position); - if (vox == nullptr || vox->id == BLOCK_VOID) { + if (vox == nullptr || vox->id == BLOCK_AIR) { return; } // one frame can be invalid due to texture change but ok - const auto& def = - level.content.getIndices()->blocks.require(vox->id); + const auto& def = content.getIndices()->blocks.require(vox->id); if (wrapper.modelType != def.getModel(vox->state.userbits).type) { wrapper.dirtySides = 0xFF; - refreshWrapper(wrapper); } glm::vec4 light(1, 1, 1, 0); if (wrapper.emission < 1.0f) { @@ -95,6 +91,8 @@ void BlockWrapsRenderer::draw(BlockWrapper& wrapper, const Texture* texture) { } void BlockWrapsRenderer::refreshWrapper(BlockWrapper& wrapper) { + clearOrder(&wrapper); + for (int i = 0; i < 6; i++) { if ((wrapper.cullingBits & (1 << i)) == 0) { continue; @@ -104,15 +102,22 @@ void BlockWrapsRenderer::refreshWrapper(BlockWrapper& wrapper) { wrapper.texRegions[i] = texRegion; wrapper.uvRegions[i] = texRegion.region; - renderOrder.insert({texRegion.texture, &wrapper}); + auto range = renderOrder.equal_range(texRegion.texture); + auto it = + std::find_if(range.first, range.second, [&wrapper](auto& elem) { + return elem.second == &wrapper; + }); + if (it == range.second) { + renderOrder.emplace(texRegion.texture, &wrapper); + } } wrapper.dirtySides = 0x0; const voxel* vox = chunks.get(wrapper.position); - if (vox == nullptr || vox->id == BLOCK_VOID) { + if (vox == nullptr || vox->id == BLOCK_AIR) { return; } - const auto& def = level.content.getIndices()->blocks.require(vox->id); + const auto& def = content.getIndices()->blocks.require(vox->id); wrapper.modelType = def.getModel(vox->state.userbits).type; switch (wrapper.modelType) { case BlockModelType::AABB: { @@ -133,7 +138,7 @@ void BlockWrapsRenderer::refreshWrapper(BlockWrapper& wrapper) { } } -void BlockWrapsRenderer::draw(const DrawContext& pctx, const Player& player) { +void BlockWrapsRenderer::draw(const DrawContext& pctx) { auto ctx = pctx.sub(); auto& shader = assets.require("entity"); @@ -145,7 +150,6 @@ void BlockWrapsRenderer::draw(const DrawContext& pctx, const Player& player) { refreshWrapper(*wrapper); } } - for (const auto& [texture, wrapper] : renderOrder) { batch->setTexture(texture); draw(*wrapper, texture); @@ -181,15 +185,17 @@ void BlockWrapsRenderer::remove(u64id_t id) { if (found == wrappers.end()) { return; } - auto wrapper = std::move(found->second); + clearOrder(found->second.get()); wrappers.erase(id); +} +void BlockWrapsRenderer::clearOrder(const BlockWrapper* const wrapper) { auto it = renderOrder.begin(); while (it != renderOrder.end()) { - if (it->second == wrapper.get()) { + if (it->second == wrapper) { it = renderOrder.erase(it); } else { ++it; } } -} +} \ No newline at end of file diff --git a/src/graphics/render/BlockWrapsRenderer.hpp b/src/graphics/render/BlockWrapsRenderer.hpp index f19bf6b66..0f2ed8f7e 100644 --- a/src/graphics/render/BlockWrapsRenderer.hpp +++ b/src/graphics/render/BlockWrapsRenderer.hpp @@ -10,12 +10,9 @@ #include #include #include -#include class Assets; -class Player; -class Level; -struct voxel; +class Content; class Chunks; class Texture; class DrawContext; @@ -36,7 +33,7 @@ struct BlockWrapper { class BlockWrapsRenderer { const Assets& assets; - const Level& level; + const Content& content; const Chunks& chunks; std::unique_ptr batch; @@ -47,13 +44,14 @@ class BlockWrapsRenderer { void draw(BlockWrapper& wrapper, const Texture* texture); void refreshWrapper(BlockWrapper& wrapper); + void clearOrder(const BlockWrapper* const wrapper); public: BlockWrapsRenderer( - const Assets& assets, const Level& level, const Chunks& chunks + const Assets& assets, const Content& content, const Chunks& chunks ); ~BlockWrapsRenderer(); - void draw(const DrawContext& ctx, const Player& player); + void draw(const DrawContext& ctx); u64id_t add( const glm::ivec3& position, diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 4157eeb98..e1f683b96 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -94,9 +94,9 @@ WorldRenderer::WorldRenderer( assets, level, *player.chunks, engine.getSettings().graphics )), texts(std::make_unique(*batch3d, assets, *frustumCulling)), - blockWraps( - std::make_unique(assets, level, *player.chunks) - ) { + blockWraps(std::make_unique( + assets, level.content, *player.chunks + )) { auto& settings = engine.getSettings(); level.events->listen( LevelEventType::CHUNK_HIDDEN, @@ -214,7 +214,7 @@ void WorldRenderer::renderOpaque( setupWorldShader(shader, camera, settings, fogFactor); chunksRenderer->drawChunks(camera, shader); - blockWraps->draw(ctx, player); + blockWraps->draw(ctx); int cloudsQuality = settings.graphics.cloudsQuality.get(); if (cloudsQuality > 0) { diff --git a/src/logic/scripting/lua/libs/libblockwraps.cpp b/src/logic/scripting/lua/libs/libblockwraps.cpp index 5b28f7dbb..084dd6b8b 100644 --- a/src/logic/scripting/lua/libs/libblockwraps.cpp +++ b/src/logic/scripting/lua/libs/libblockwraps.cpp @@ -34,10 +34,14 @@ static int l_set_pos(lua::State* L) { static int l_set_texture(lua::State* L) { if (auto wrapper = renderer->blockWraps->get(lua::tointeger(L, 1))) { + const char* newTexture = lua::require_string(L, 2); + for (int i = 0; i < wrapper->textureFaces.size(); i++) { - wrapper->textureFaces[i] = lua::require_string(L, 2); + if (wrapper->textureFaces[i] != newTexture) { + wrapper->textureFaces[i] = newTexture; + wrapper->dirtySides = 0xFF; + } } - wrapper->dirtySides = 0xFF; } return 0; } @@ -52,7 +56,7 @@ static int l_set_faces(lua::State* L) { wrapper->dirtySides |= (1 << i); } } else { - auto texture = lua::require_string(L, 2 + i);; + auto texture = lua::require_string(L, 2 + i); if ((wrapper->cullingBits & (1 << i)) == 0x0 || wrapper->textureFaces[i] != texture) { wrapper->cullingBits |= (1 << i); @@ -73,7 +77,6 @@ static int l_set_tints(lua::State* L) { wrapper->tints[i] = lua::tovec3(L, 2 + i); } } - wrapper->dirtySides = 0xFF; } return 0; } diff --git a/src/util/platform.cpp b/src/util/platform.cpp index a7ba041db..f9ecf070d 100644 --- a/src/util/platform.cpp +++ b/src/util/platform.cpp @@ -14,8 +14,10 @@ #ifdef _WIN32 #include +#include #pragma comment(lib, "winmm.lib") #else +#include #include #endif @@ -290,3 +292,14 @@ void platform::new_engine_instance(const std::vector& args) { } #endif } + +bool platform::stdin_has_data() { +#ifdef _WIN32 + return _kbhit(); +#else + struct pollfd fds; + fds.fd = STDIN_FILENO; + fds.events = POLLIN; + return poll(&fds, 1, 0) == 1; +#endif +} \ No newline at end of file diff --git a/src/util/platform.hpp b/src/util/platform.hpp index 148c64c46..620178fc1 100644 --- a/src/util/platform.hpp +++ b/src/util/platform.hpp @@ -21,4 +21,6 @@ namespace platform { void new_engine_instance(const std::vector& args); /// @brief Open URL in web browser bool open_url(const std::string& url); + /// @brief Check if stdin has input + bool stdin_has_data(); }