#include "EdittableChunk.hpp" #include #include #include "core/geometry/math.hpp" using namespace world; EdittableChunk::EdittableChunk(owner edits, std::istream& str): world::Chunk(str), edits(edits) { } EdittableChunk::EdittableChunk(owner edits, Voxel v): world::Chunk(v), edits(edits) { } EdittableChunk::EdittableChunk(owner edits): world::Chunk(), edits(edits) { } EdittableChunk::~EdittableChunk() { } void EdittableChunk::set(chunk_voxel_idx idx, const Voxel& voxel) { if (!isHeavy()) { if (get(idx).value == voxel.value) return; flatten(); } voxels[idx] = voxel; } void EdittableChunk::setAt(const chunk_voxel_pos &pos, const Voxel& voxel) { return set(glm::toIdx(pos), voxel); } void EdittableChunk::flatten() { assert(isAllocated()); voxels.resize(CHUNK_SIZE, voxels.front()); } std::optional ChunkEdits::update(float deltaTime, bool animate) { //ZoneScopedN("Chunk"); for(auto it = edits.begin(); it != edits.end();) { it->second.delay -= deltaTime; if(it->second.delay <= 0 && animate) { invalidate(it->first); it = edits.erase(it); } else { ++it; } } if(upToDate) { return {}; } else { upToDate = true; return {toUpdate}; } } void ChunkEdits::invalidate(uint16_t idx) { invalidate( ((!getNeighborIdx(idx, Face::Up).has_value()) & Faces::Up) | ((!getNeighborIdx(idx, Face::Down).has_value()) & Faces::Down) | ((!getNeighborIdx(idx, Face::Left).has_value()) & Faces::Left) | ((!getNeighborIdx(idx, Face::Right).has_value()) & Faces::Right) | ((!getNeighborIdx(idx, Face::Forward).has_value()) & Faces::Forward) | ((!getNeighborIdx(idx, Face::Backward).has_value()) & Faces::Backward)); } void ChunkEdits::add(const Edit& edit) { edits.erase(edit.idx); if(edit.delay > 0) { edits.emplace(edit.idx, EditBody{edit.value, edit.delay}); } else { invalidate(edit.idx); } } void ChunkEdits::apply(const Edit& edit) { const auto prev = parent->get(edit.idx); if(prev.value != edit.value.value) { parent->set(edit.idx, edit.value); add(Edit{prev, edit.delay, edit.idx}); } } std::optional ChunkEdits::getNeighborIdx(chunk_voxel_idx idx, Face dir) { switch (dir) { case Face::Forward: if (idx % glm::IDX_LENGTH >= glm::IDX_LENGTH - 1) return {}; return idx + 1; case Face::Backward: if (idx % glm::IDX_LENGTH <= 0) return {}; return idx - 1; case Face::Up: if ((idx / glm::IDX_LENGTH) % glm::IDX_LENGTH >= glm::IDX_LENGTH - 1) return {}; return idx + glm::IDX_LENGTH; case Face::Down: if ((idx / glm::IDX_LENGTH) % glm::IDX_LENGTH <= 0) return {}; return idx - glm::IDX_LENGTH; case Face::Right: if (idx / glm::IDX_LENGTH2 >= glm::IDX_LENGTH - 1) return {}; return idx + glm::IDX_LENGTH2; case Face::Left: if (idx / glm::IDX_LENGTH2 <= 0) return {}; return idx - glm::IDX_LENGTH2; default: return {}; } }