140 lines
4.5 KiB
C++
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;
|
|
}
|