forked from Kolyah35/minecraft-pe-0.6.1
FIXED: support 64x32 + 64x64 skins with fallback for failed skin URL
This commit is contained in:
@@ -73,50 +73,20 @@ public:
|
|||||||
: filename_;
|
: filename_;
|
||||||
std::ifstream source(filename.c_str(), std::ios::binary);
|
std::ifstream source(filename.c_str(), std::ios::binary);
|
||||||
|
|
||||||
if (source) {
|
if (!source) {
|
||||||
png_structp pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
if (!pngPtr)
|
|
||||||
return out;
|
|
||||||
|
|
||||||
png_infop infoPtr = png_create_info_struct(pngPtr);
|
|
||||||
|
|
||||||
if (!infoPtr) {
|
|
||||||
png_destroy_read_struct(&pngPtr, NULL, NULL);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hack to get around the broken libpng for windows
|
|
||||||
png_set_read_fn(pngPtr,(void*)&source, png_funcReadFile);
|
|
||||||
|
|
||||||
png_read_info(pngPtr, infoPtr);
|
|
||||||
|
|
||||||
// Set up the texdata properties
|
|
||||||
out.w = png_get_image_width(pngPtr, infoPtr);
|
|
||||||
out.h = png_get_image_height(pngPtr, infoPtr);
|
|
||||||
|
|
||||||
png_bytep* rowPtrs = new png_bytep[out.h];
|
|
||||||
out.data = new unsigned char[4 * out.w * out.h];
|
|
||||||
out.memoryHandledExternally = false;
|
|
||||||
|
|
||||||
int rowStrideBytes = 4 * out.w;
|
|
||||||
for (int i = 0; i < out.h; i++) {
|
|
||||||
rowPtrs[i] = (png_bytep)&out.data[i*rowStrideBytes];
|
|
||||||
}
|
|
||||||
png_read_image(pngPtr, rowPtrs);
|
|
||||||
|
|
||||||
// Teardown and return
|
|
||||||
png_destroy_read_struct(&pngPtr, &infoPtr,(png_infopp)0);
|
|
||||||
delete[] (png_bytep)rowPtrs;
|
|
||||||
source.close();
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOGI("Couldn't find file: %s\n", filename.c_str());
|
LOGI("Couldn't find file: %s\n", filename.c_str());
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned char> fileData((std::istreambuf_iterator<char>(source)), std::istreambuf_iterator<char>());
|
||||||
|
source.close();
|
||||||
|
|
||||||
|
if (fileData.empty()) {
|
||||||
|
LOGI("Couldn't read file: %s\n", filename.c_str());
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadTextureFromMemory(fileData.data(), fileData.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureData loadTextureFromMemory(const unsigned char* data, size_t size) override {
|
TextureData loadTextureFromMemory(const unsigned char* data, size_t size) override {
|
||||||
|
|||||||
@@ -263,7 +263,8 @@ static void* fetchSkinForPlayer(void* param) {
|
|||||||
std::vector<unsigned char> skinData;
|
std::vector<unsigned char> skinData;
|
||||||
if (!HttpClient::download(skinUrl, skinData) || skinData.empty()) {
|
if (!HttpClient::download(skinUrl, skinData) || skinData.empty()) {
|
||||||
LOGW("[Skin] download failed for %s\n", skinUrl.c_str());
|
LOGW("[Skin] download failed for %s\n", skinUrl.c_str());
|
||||||
return NULL;
|
player->setTextureName("mob/char.png");
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save to cache
|
// Save to cache
|
||||||
|
|||||||
@@ -19,12 +19,13 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
void additionalRendering(Mob* mob, float a);
|
void additionalRendering(Mob* mob, float a);
|
||||||
|
|
||||||
private:
|
|
||||||
HumanoidModel* humanoidModel;
|
HumanoidModel* humanoidModel;
|
||||||
|
|
||||||
// Last rotation values for cape smoothing (reduces jitter)
|
// Last rotation values for cape smoothing (reduces jitter)
|
||||||
float lastCapeXRot;
|
float lastCapeXRot;
|
||||||
float lastCapeZRot;
|
float lastCapeZRot;
|
||||||
|
private:
|
||||||
|
// i guess ill keep this just in case seomthing breaks
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*NET_MINECRAFT_CLIENT_RENDERER_ENTITY__HumanoidMobRenderer_H__*/
|
#endif /*NET_MINECRAFT_CLIENT_RENDERER_ENTITY__HumanoidMobRenderer_H__*/
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
void setArmor(Model* armor);
|
void setArmor(Model* armor);
|
||||||
Model* getArmor();
|
Model* getArmor();
|
||||||
|
Model* model; // allows derived renderers to swap models dynamically for skin formats
|
||||||
private:
|
private:
|
||||||
Model* model;
|
|
||||||
Model* armor;
|
Model* armor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "PlayerRenderer.h"
|
#include "PlayerRenderer.h"
|
||||||
#include "EntityRenderDispatcher.h"
|
#include "EntityRenderDispatcher.h"
|
||||||
|
#include "../Textures.h"
|
||||||
#include "../../../world/entity/player/Player.h"
|
#include "../../../world/entity/player/Player.h"
|
||||||
#include "../../../world/level/Level.h"
|
#include "../../../world/level/Level.h"
|
||||||
#include "../../../world/item/ArmorItem.h"
|
#include "../../../world/item/ArmorItem.h"
|
||||||
@@ -14,12 +15,22 @@ static const std::string armorFilenames[10] = {
|
|||||||
|
|
||||||
PlayerRenderer::PlayerRenderer( HumanoidModel* humanoidModel, float shadow )
|
PlayerRenderer::PlayerRenderer( HumanoidModel* humanoidModel, float shadow )
|
||||||
: super(humanoidModel, shadow),
|
: super(humanoidModel, shadow),
|
||||||
|
playerModel64(humanoidModel),
|
||||||
|
playerModel32(new HumanoidModel(0, 0, 64, 32)),
|
||||||
armorParts1(new HumanoidModel(1.0f, 0, 64, 64)),
|
armorParts1(new HumanoidModel(1.0f, 0, 64, 64)),
|
||||||
armorParts2(new HumanoidModel(0.5f, 0, 64, 64))
|
armorParts2(new HumanoidModel(0.5f, 0, 64, 64))
|
||||||
{
|
{
|
||||||
|
// default to legacy skin path until we know the exact texture size
|
||||||
|
model = playerModel32;
|
||||||
|
humanoidModel = playerModel32;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerRenderer::~PlayerRenderer() {
|
PlayerRenderer::~PlayerRenderer() {
|
||||||
|
// prevent MobRenderer destructor from deleting model pointers we manage manually
|
||||||
|
model = nullptr;
|
||||||
|
|
||||||
|
delete playerModel32;
|
||||||
|
delete playerModel64;
|
||||||
delete armorParts1;
|
delete armorParts1;
|
||||||
delete armorParts2;
|
delete armorParts2;
|
||||||
}
|
}
|
||||||
@@ -43,6 +54,15 @@ void PlayerRenderer::setupRotations( Entity* mob, float bob, float bodyRot, floa
|
|||||||
super::setupRotations(mob, bob, bodyRot, a);
|
super::setupRotations(mob, bob, bodyRot, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PlayerRenderer::isModernPlayerSkin(Mob* mob) {
|
||||||
|
const std::string texName = mob->getTexture();
|
||||||
|
TextureId texId = entityRenderDispatcher->textures->loadTexture(texName);
|
||||||
|
if (!Textures::isTextureIdValid(texId))
|
||||||
|
return false;
|
||||||
|
const TextureData* texData = entityRenderDispatcher->textures->getTemporaryTextureData(texId);
|
||||||
|
return texData && texData->w == 64 && texData->h == 64;
|
||||||
|
}
|
||||||
|
|
||||||
void PlayerRenderer::renderName( Mob* mob, float x, float y, float z ){
|
void PlayerRenderer::renderName( Mob* mob, float x, float y, float z ){
|
||||||
//@todo: figure out how to handle HideGUI
|
//@todo: figure out how to handle HideGUI
|
||||||
if (mob != entityRenderDispatcher->cameraEntity && mob->level->adventureSettings.showNameTags) {
|
if (mob != entityRenderDispatcher->cameraEntity && mob->level->adventureSettings.showNameTags) {
|
||||||
@@ -50,6 +70,20 @@ void PlayerRenderer::renderName( Mob* mob, float x, float y, float z ){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PlayerRenderer::render(Entity* mob_, float x, float y, float z, float rot, float a) {
|
||||||
|
Mob* mob = (Mob*) mob_;
|
||||||
|
HumanoidModel* desired = isModernPlayerSkin(mob) ? playerModel64 : playerModel32;
|
||||||
|
if (model != desired || humanoidModel != desired) {
|
||||||
|
model = desired;
|
||||||
|
humanoidModel = desired;
|
||||||
|
}
|
||||||
|
// LOGI("[PlayerRenderer] %s: skin=%s, modelTex=%dx%d, desired=%s\n",
|
||||||
|
// ((Player*)mob)->name.c_str(), mob->getTexture().c_str(),
|
||||||
|
// humanoidModel->texWidth, humanoidModel->texHeight,
|
||||||
|
// (desired == playerModel64 ? "64" : "32"));
|
||||||
|
HumanoidMobRenderer::render(mob_, x, y, z, rot, a);
|
||||||
|
}
|
||||||
|
|
||||||
int PlayerRenderer::prepareArmor(Mob* mob, int layer, float a) {
|
int PlayerRenderer::prepareArmor(Mob* mob, int layer, float a) {
|
||||||
Player* player = (Player*) mob;
|
Player* player = (Player*) mob;
|
||||||
|
|
||||||
@@ -80,8 +114,11 @@ int PlayerRenderer::prepareArmor(Mob* mob, int layer, float a) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PlayerRenderer::onGraphicsReset() {
|
void PlayerRenderer::onGraphicsReset() {
|
||||||
super::onGraphicsReset();
|
if (playerModel32) playerModel32->onGraphicsReset();
|
||||||
|
if (playerModel64) playerModel64->onGraphicsReset();
|
||||||
|
|
||||||
if (armorParts1) armorParts1->onGraphicsReset();
|
if (armorParts1) armorParts1->onGraphicsReset();
|
||||||
if (armorParts2) armorParts2->onGraphicsReset();
|
if (armorParts2) armorParts2->onGraphicsReset();
|
||||||
|
|
||||||
|
super::onGraphicsReset();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ public:
|
|||||||
~PlayerRenderer();
|
~PlayerRenderer();
|
||||||
|
|
||||||
virtual int prepareArmor(Mob* mob, int layer, float a);
|
virtual int prepareArmor(Mob* mob, int layer, float a);
|
||||||
|
bool isModernPlayerSkin(Mob* mob);
|
||||||
|
virtual void render(Entity* mob, float x, float y, float z, float rot, float a);
|
||||||
|
|
||||||
virtual void setupPosition(Entity* mob, float x, float y, float z);
|
virtual void setupPosition(Entity* mob, float x, float y, float z);
|
||||||
virtual void setupRotations(Entity* mob, float bob, float bodyRot, float a);
|
virtual void setupRotations(Entity* mob, float bob, float bodyRot, float a);
|
||||||
@@ -18,6 +20,8 @@ public:
|
|||||||
virtual void renderName(Mob* mob, float x, float y, float z);
|
virtual void renderName(Mob* mob, float x, float y, float z);
|
||||||
virtual void onGraphicsReset();
|
virtual void onGraphicsReset();
|
||||||
private:
|
private:
|
||||||
|
HumanoidModel* playerModel32;
|
||||||
|
HumanoidModel* playerModel64;
|
||||||
HumanoidModel* armorParts1;
|
HumanoidModel* armorParts1;
|
||||||
HumanoidModel* armorParts2;
|
HumanoidModel* armorParts2;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user