1
0
Fork 0
Univerxel/src/core/world/EdittableChunk.cpp

113 lines
3.2 KiB
C++

#include "EdittableChunk.hpp"
#include <algorithm>
#include <Tracy.hpp>
#include "core/geometry/math.hpp"
using namespace world;
EdittableChunk::EdittableChunk(owner<ChunkEdits*> edits, std::istream& str): world::Chunk(str), edits(edits) { }
EdittableChunk::EdittableChunk(owner<ChunkEdits*> edits, Voxel v): world::Chunk(v), edits(edits) { }
EdittableChunk::EdittableChunk(owner<ChunkEdits*> 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<Faces> 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<world::chunk_voxel_idx> 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 {};
}
}