4jcraft/Minecraft.Client/Textures/Stitching/StitchedTexture.cpp
MatthewBeshay a0fdc643d1 Merge branch 'upstream-dev' into cleanup/nullptr-replacement
# Conflicts:
#	Minecraft.Client/Network/PlayerChunkMap.cpp
#	Minecraft.Client/Network/PlayerList.cpp
#	Minecraft.Client/Network/ServerChunkCache.cpp
#	Minecraft.Client/Platform/Common/Consoles_App.cpp
#	Minecraft.Client/Platform/Common/DLC/DLCManager.cpp
#	Minecraft.Client/Platform/Common/GameRules/LevelGenerationOptions.cpp
#	Minecraft.Client/Platform/Common/GameRules/LevelRuleset.cpp
#	Minecraft.Client/Platform/Common/Tutorial/Tutorial.cpp
#	Minecraft.Client/Platform/Common/Tutorial/TutorialTask.cpp
#	Minecraft.Client/Platform/Common/UI/IUIScene_CreativeMenu.cpp
#	Minecraft.Client/Platform/Common/UI/UIComponent_Panorama.cpp
#	Minecraft.Client/Platform/Common/UI/UIController.cpp
#	Minecraft.Client/Platform/Common/UI/UIController.h
#	Minecraft.Client/Platform/Extrax64Stubs.cpp
#	Minecraft.Client/Platform/Windows64/4JLibs/inc/4J_Input.h
#	Minecraft.Client/Platform/Windows64/4JLibs/inc/4J_Storage.h
#	Minecraft.Client/Player/EntityTracker.cpp
#	Minecraft.Client/Player/ServerPlayer.cpp
#	Minecraft.Client/Rendering/EntityRenderers/PlayerRenderer.cpp
#	Minecraft.Client/Textures/Packs/DLCTexturePack.cpp
#	Minecraft.Client/Textures/Stitching/StitchedTexture.cpp
#	Minecraft.Client/Textures/Stitching/TextureMap.cpp
#	Minecraft.Client/Textures/Textures.cpp
#	Minecraft.World/Blocks/NotGateTile.cpp
#	Minecraft.World/Blocks/PressurePlateTile.cpp
#	Minecraft.World/Blocks/TileEntities/PotionBrewing.cpp
#	Minecraft.World/Enchantments/EnchantmentHelper.cpp
#	Minecraft.World/Entities/HangingEntity.cpp
#	Minecraft.World/Entities/LeashFenceKnotEntity.cpp
#	Minecraft.World/Entities/LivingEntity.cpp
#	Minecraft.World/Entities/Mobs/Boat.cpp
#	Minecraft.World/Entities/Mobs/Minecart.cpp
#	Minecraft.World/Entities/Mobs/Witch.cpp
#	Minecraft.World/Entities/SyncedEntityData.cpp
#	Minecraft.World/Items/LeashItem.cpp
#	Minecraft.World/Items/PotionItem.cpp
#	Minecraft.World/Level/BaseMobSpawner.cpp
#	Minecraft.World/Level/CustomLevelSource.cpp
#	Minecraft.World/Level/Level.cpp
#	Minecraft.World/Level/Storage/DirectoryLevelStorage.cpp
#	Minecraft.World/Level/Storage/McRegionLevelStorage.cpp
#	Minecraft.World/Level/Storage/RegionFileCache.cpp
#	Minecraft.World/Player/Player.cpp
#	Minecraft.World/WorldGen/Biomes/BiomeCache.cpp
#	Minecraft.World/WorldGen/Features/RandomScatteredLargeFeature.cpp
#	Minecraft.World/WorldGen/Layers/BiomeOverrideLayer.cpp
2026-03-30 16:28:40 +11:00

286 lines
8.4 KiB
C++

#include "../../Platform/stdafx.h"
#include "../Texture.h"
#include "../../../Minecraft.World/Util/StringHelpers.h"
#include "../ClockTexture.h"
#include "../CompassTexture.h"
#include "StitchedTexture.h"
#include "../TextureManager.h"
StitchedTexture* StitchedTexture::create(const std::wstring& name) {
// TODO: Generalize?
if (name.compare(L"clock") == 0) {
return new ClockTexture();
} else if (name.compare(L"compass") == 0) {
return new CompassTexture();
} else {
return new StitchedTexture(name, name);
}
}
StitchedTexture::StitchedTexture(const std::wstring& name,
const std::wstring& filename)
: name(name) {
// 4J Initialisers
source = nullptr;
rotated = false;
x = 0;
y = 0;
width = 0;
height = 0;
u0 = 0.0f;
u1 = 0.0f;
v0 = 0.0f;
v1 = 0.0f;
widthTranslation = 0.0f;
heightTranslation = 0.0f;
frame = 0;
subFrame = 0;
frameOverride = nullptr;
flags = 0;
frames = nullptr;
m_fileName = filename;
}
void StitchedTexture::freeFrameTextures() {
if (frames != nullptr) {
for (auto it = frames->begin(); it != frames->end(); ++it) {
TextureManager::getInstance()->unregisterTexture(L"", *it);
delete *it;
}
delete frames;
frames = nullptr;
}
}
StitchedTexture::~StitchedTexture() {
if (frames != nullptr) {
for (auto it = frames->begin(); it != frames->end(); ++it) {
delete *it;
}
delete frames;
frames = nullptr;
}
if (frameOverride != nullptr) {
delete frameOverride;
frameOverride = nullptr;
}
}
void StitchedTexture::initUVs(float U0, float V0, float U1, float V1) {
u0 = U0;
u1 = U1;
v0 = V0;
v1 = V1;
}
void StitchedTexture::init(Texture* source, std::vector<Texture*>* frames,
int x, int y, int width, int height, bool rotated) {
this->source = source;
this->frames = frames;
frame = -1; // Force an update of animated textures
this->x = x;
this->y = y;
this->width = width;
this->height = height;
this->rotated = rotated;
float marginX = 0.0f; // 0.01f / source->getWidth();
float marginY = 0.0f; // 0.01f / source->getHeight();
this->u0 = x / (float)source->getWidth() + marginX;
this->u1 = (x + width) / (float)source->getWidth() - marginX;
this->v0 = y / (float)source->getHeight() + marginY;
this->v1 = (y + height) / (float)source->getHeight() - marginY;
#ifndef _CONTENT_PACKAGE
bool addBreakpoint = false;
if (addBreakpoint) {
printf("\nTreeTop\n");
printf("u0 = %f\n", u0);
printf("u1 = %f\n", u1);
printf("v0 = %f\n", v0);
printf("v1 = %f\n", v1);
printf("\n\n");
}
#endif
this->widthTranslation = width / (float)SharedConstants::WORLD_RESOLUTION;
this->heightTranslation = height / (float)SharedConstants::WORLD_RESOLUTION;
}
void StitchedTexture::replaceWith(StitchedTexture* texture) {
init(texture->source, texture->frames, texture->x, texture->y,
texture->width, texture->height, texture->rotated);
}
int StitchedTexture::getX() const { return x; }
int StitchedTexture::getY() const { return y; }
int StitchedTexture::getWidth() const { return width; }
int StitchedTexture::getHeight() const { return height; }
static const float UVAdjust = (1.0f / 16.0f) / 256.0f;
float StitchedTexture::getU0(bool adjust /*=false*/) const {
return adjust ? (u0 + UVAdjust) : u0;
}
float StitchedTexture::getU1(bool adjust /*=false*/) const {
return adjust ? (u1 - UVAdjust) : u1;
}
float StitchedTexture::getU(double offset, bool adjust /*=false*/) const {
float diff = getU1(adjust) - getU0(adjust);
return getU0(adjust) +
(diff * ((float)offset / SharedConstants::WORLD_RESOLUTION));
}
float StitchedTexture::getV0(bool adjust /*=false*/) const {
return adjust ? (v0 + UVAdjust) : v0;
}
float StitchedTexture::getV1(bool adjust /*=false*/) const {
return adjust ? (v1 - UVAdjust) : v1;
}
float StitchedTexture::getV(double offset, bool adjust /*=false*/) const {
float diff = getV1(adjust) - getV0(adjust);
return getV0(adjust) +
(diff * ((float)offset / SharedConstants::WORLD_RESOLUTION));
}
std::wstring StitchedTexture::getName() const { return name; }
int StitchedTexture::getSourceWidth() const { return source->getWidth(); }
int StitchedTexture::getSourceHeight() const { return source->getHeight(); }
void StitchedTexture::cycleFrames() {
if (frameOverride != nullptr) {
std::pair<int, int> current = frameOverride->at(frame);
subFrame++;
if (subFrame >= current.second) {
int oldFrame = current.first;
frame = (frame + 1) % frameOverride->size();
subFrame = 0;
current = frameOverride->at(frame);
int newFrame = current.first;
if (oldFrame != newFrame && newFrame >= 0 &&
newFrame < frames->size()) {
source->blit(x, y, frames->at(newFrame), rotated);
}
}
} else {
int oldFrame = frame;
frame = (frame + 1) % frames->size();
if (oldFrame != frame) {
source->blit(x, y, frames->at(this->frame), rotated);
}
}
}
Texture* StitchedTexture::getSource() { return source; }
Texture* StitchedTexture::getFrame(int i) { return frames->at(0); }
int StitchedTexture::getFrames() { return frames ? frames->size() : 0; }
/**
* Loads animation frames from a file with the syntax, <code>
* 0,1,2,3,
* 4*10,5*10,
* 4*10,3,2,1,
* 0
* </code> or similar
*
* @param bufferedReader
*/
void StitchedTexture::loadAnimationFrames(BufferedReader* bufferedReader) {
if (frameOverride != nullptr) {
delete frameOverride;
frameOverride = nullptr;
}
frame = 0;
subFrame = 0;
intPairVector* results = new intPairVector();
// try {
std::wstring line = bufferedReader->readLine();
while (!line.empty()) {
line = trimString(line);
if (line.length() > 0) {
std::vector<std::wstring> tokens = stringSplit(line, L',');
// for (String token : tokens)
for (auto it = tokens.begin(); it != tokens.end(); ++it) {
std::wstring token = *it;
int multiPos = token.find_first_of('*');
if (multiPos > 0) {
int frame = _fromString<int>(token.substr(0, multiPos));
int count = _fromString<int>(token.substr(multiPos + 1));
results->push_back(intPairVector::value_type(frame, count));
} else {
int tokenVal = _fromString<int>(token);
results->push_back(intPairVector::value_type(tokenVal, 1));
}
}
}
line = bufferedReader->readLine();
}
//} catch (Exception e) {
// System.err.println("Failed to read animation info for " + name + ": " +
// e.getMessage());
//}
if (!results->empty() &&
results->size() < (SharedConstants::TICKS_PER_SECOND * 30)) {
frameOverride = results;
} else {
delete results;
}
}
void StitchedTexture::loadAnimationFrames(const std::wstring& string) {
if (frameOverride != nullptr) {
delete frameOverride;
frameOverride = nullptr;
}
frame = 0;
subFrame = 0;
intPairVector* results = new intPairVector();
std::vector<std::wstring> tokens = stringSplit(trimString(string), L',');
// for (String token : tokens)
for (auto it = tokens.begin(); it != tokens.end(); ++it) {
std::wstring token = trimString(*it);
int multiPos = token.find_first_of('*');
if (multiPos > 0) {
int frame = _fromString<int>(token.substr(0, multiPos));
int count = _fromString<int>(token.substr(multiPos + 1));
results->push_back(intPairVector::value_type(frame, count));
} else if (!token.empty()) {
int tokenVal = _fromString<int>(token);
results->push_back(intPairVector::value_type(tokenVal, 1));
}
}
if (!results->empty() &&
results->size() < (SharedConstants::TICKS_PER_SECOND * 30)) {
frameOverride = results;
} else {
delete results;
}
}
void StitchedTexture::setFlags(int flags) { this->flags = flags; }
int StitchedTexture::getFlags() const { return this->flags; }
bool StitchedTexture::hasOwnData() { return true; }