Files
Re3D/src/types/texture.cpp
2024-07-17 13:52:24 -04:00

140 lines
4.5 KiB
C++

#include <ReTexture/rTexture.h>
#include <Redacted3D/types/texture.h>
#include <Redacted3D/engine/engine.h>
void Texture::load(Entity* entity, const std::string& file, bool storeOnTextureList) {
auto* texture = new RTexture(file, {RTextureFlag::INVERT_Y});
glGenTextures(1, &id);
glBindTexture(GL_TEXTURE_2D, id);
if (texture->format == RTextureFormat::RGBA)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->width, texture->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture->pixelData.data());
if (texture->format == RTextureFormat::RGB)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture->width, texture->height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture->pixelData.data());
delete texture;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
//If we can't load the missing texture
if (file == "assets/textures/missing.png" && id == 0)
engine->setError(ENGINE_ERROR_CODE::TEXTURE_NOT_FOUND, true);
if (id == 0)
engine->setError(ENGINE_ERROR_CODE::TEXTURE_NOT_FOUND, false),
load(entity, "assets/textures/missing.png", false);
usedBy.push_back(entity);
if (storeOnTextureList)
engine->world->textureList.push_back(new Texture(*this));
}
void Texture::erase() {
Texture::erase(this);
}
Texture::Texture(Entity* entity, const char *filePath, bool storeOnTextureList) {
load(entity, filePath, storeOnTextureList);
}
void Texture::erase(Texture* texture) const {
glDeleteTextures(1, &texture->id);
//If texture is being deleted while in use.
//It won't crash the program. But it'll cause the texture to be reloaded from disk unnecessarily.
if (!usedBy.empty())
engine->setError(ENGINE_ERROR_CODE::TEXTURE_ERASED_WHILE_IN_USE, false);
if (auto* t = dynamic_cast<MultiTexture*>(texture))
for (auto &m : t->multi)
glDeleteTextures(1, &m.id);
for (int i = 0; i < engine->world->textureList.size(); i++)
if (engine->world->textureList[i] == texture)
engine->world->textureList.erase(engine->world->textureList.begin() + i);
}
MultiTexture::MultiTexture(Entity* entity, const std::vector<std::string>& textures, bool storeOnTextureList) {
Texture base;
for (const auto& t : textures) {
if (id != 0)
multi.emplace_back(entity, t.c_str(), false);
else
base = Texture(entity, t.c_str(), false),
id = base.id,
usedBy = base.usedBy;
}
if (storeOnTextureList)
engine->world->textureList.push_back(new MultiTexture(*this));
if (multi.size() > 6)
engine->setError(ENGINE_ERROR_CODE::MULTI_TEXTURE_SIZE_EXCEEDS, false);
}
void MultiTexture::erase() {
Texture::erase(this);
}
MotionTexture::MotionTexture(Entity* entity, const std::vector<std::string>& textures, u16 msBetweenFrames, bool storeOnTextureList, bool doAnim) {
msDelay = msBetweenFrames;
this->doAnim = doAnim;
Texture base(entity, textures[0].c_str(), false);
std::vector<std::string> extra(textures.begin()+1, textures.end());
if(!extra.empty())
for (auto& t : extra)
motion.emplace_back(entity, t.c_str(), false);
id = base.id;
usedBy = base.usedBy;
if (storeOnTextureList)
engine->world->textureList.push_back(new MotionTexture(*this));
}
Texture* MotionTexture::current() {
//If animation is disabled.
if (!doAnim)
return this;
//If it's our first time getting the current texture
if (lastUpdate == std::chrono::high_resolution_clock::time_point()) {
lastUpdate = std::chrono::high_resolution_clock::now();
lastDisplayedIndex = 0;
return this;
}
auto now = std::chrono::high_resolution_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - lastUpdate).count();
if (elapsed >= msDelay) {
lastDisplayedIndex++;
if (lastDisplayedIndex > motion.size())
lastDisplayedIndex = 0;
lastUpdate = now;
}
if (lastDisplayedIndex == 0)
return this;
return &motion[lastDisplayedIndex - 1];
}
void MotionTexture::advance() {
lastDisplayedIndex++;
if (lastDisplayedIndex > motion.size())
lastDisplayedIndex = 0;
}
void MotionTexture::toggleAnim() {
doAnim = !doAnim;
}
Texture* MotionTexture::base() {
return this;
}