diff --git a/src/mcedit2/rendering/chunkmeshes/entity/models.py b/src/mcedit2/rendering/chunkmeshes/entity/models.py index af07a9d..878f7ca 100644 --- a/src/mcedit2/rendering/chunkmeshes/entity/models.py +++ b/src/mcedit2/rendering/chunkmeshes/entity/models.py @@ -11,6 +11,7 @@ from mcedit2.rendering.chunkmeshes.entity.biped import ModelZombie, ModelSkeleto ModelPigZombie from mcedit2.rendering.chunkmeshes.entity.chest import ModelChest, ModelLargeChest from mcedit2.rendering.chunkmeshes.entity.creeper import ModelCreeper +from mcedit2.rendering.chunkmeshes.entity.player import ModelPlayer from mcedit2.rendering.chunkmeshes.entity.quadruped import ModelPig, ModelCow, ModelSheep, \ ModelSheepWool from mcedit2.rendering.chunkmeshes.entity.shulker import ModelShulker @@ -168,6 +169,7 @@ def getTexture(entityID): model = models.get(entityID) return model.modelTexture +addModel(ModelPlayer()) addModel(ModelCreeper()) addModel(ModelZombie()) addModel(ModelSkeleton()) diff --git a/src/mcedit2/rendering/chunkmeshes/entity/player.py b/src/mcedit2/rendering/chunkmeshes/entity/player.py new file mode 100644 index 0000000..3cb5b3d --- /dev/null +++ b/src/mcedit2/rendering/chunkmeshes/entity/player.py @@ -0,0 +1,79 @@ +""" + player +""" +from __future__ import absolute_import, division, print_function, unicode_literals +import logging + +from mcedit2.rendering.chunkmeshes.entity.biped import ModelBiped +from mcedit2.rendering.chunkmeshes.entity.modelrenderer import ModelRenderer + +log = logging.getLogger(__name__) + + +class ModelPlayer(ModelBiped): + id = "MCEDIT_Player" + textureWidth = 64 + textureHeight = 64 + + def __init__(self, expandOffset=0.0, headOffset=0.0, smallArms=False): + super(ModelPlayer, self).__init__(expandOffset, headOffset) + + self.smallArms = smallArms + self.bipedCape = ModelRenderer(self, 0, 0) + # self.bipedCape.setTextureSize(64, 32) + self.bipedCape.addBox(-5.0, 0.0, -1.0, 10, 16, 1, expandOffset) + + if smallArms: + self.bipedLeftArm = ModelRenderer(self, 32, 48) + self.bipedLeftArm.addBox(-1.0, -2.0, -2.0, 3, 12, 4, expandOffset) + self.bipedLeftArm.setCenterPoint(5.0, 2.5, 0.0) + self.bipedRightArm = ModelRenderer(self, 40, 16) + self.bipedRightArm.addBox(-2.0, -2.0, -2.0, 3, 12, 4, expandOffset) + self.bipedRightArm.setCenterPoint(-5.0, 2.5, 0.0) + self.bipedLeftArmwear = ModelRenderer(self, 48, 48) + self.bipedLeftArmwear.addBox(-1.0, -2.0, -2.0, 3, 12, 4, expandOffset + 0.25) + self.bipedLeftArmwear.setCenterPoint(5.0, 2.5, 0.0) + self.bipedRightArmwear = ModelRenderer(self, 40, 32) + self.bipedRightArmwear.addBox(-2.0, -2.0, -2.0, 3, 12, 4, expandOffset + 0.25) + self.bipedRightArmwear.setCenterPoint(-5.0, 2.5, 10.0) + + else: + self.bipedLeftArm = ModelRenderer(self, 32, 48) + self.bipedLeftArm.addBox(-1.0, -2.0, -2.0, 4, 12, 4, expandOffset) + self.bipedLeftArm.setCenterPoint(5.0, 2.0, 0.0) + self.bipedLeftArmwear = ModelRenderer(self, 48, 48) + self.bipedLeftArmwear.addBox(-1.0, -2.0, -2.0, 4, 12, 4, expandOffset + 0.25) + self.bipedLeftArmwear.setCenterPoint(5.0, 2.0, 0.0) + self.bipedRightArmwear = ModelRenderer(self, 40, 32) + self.bipedRightArmwear.addBox(-3.0, -2.0, -2.0, 4, 12, 4, expandOffset + 0.25) + self.bipedRightArmwear.setCenterPoint(-5.0, 2.0, 10.0) + + self.bipedLeftLeg = ModelRenderer(self, 16, 48) + self.bipedLeftLeg.addBox(-2.0, 0.0, -2.0, 4, 12, 4, expandOffset) + self.bipedLeftLeg.setCenterPoint(1.9, 12.0, 0.0) + self.bipedLeftLegwear = ModelRenderer(self, 0, 48) + self.bipedLeftLegwear.addBox(-2.0, 0.0, -2.0, 4, 12, 4, expandOffset + 0.25) + self.bipedLeftLegwear.setCenterPoint(1.9, 12.0, 0.0) + self.bipedRightLegwear = ModelRenderer(self, 0, 32) + self.bipedRightLegwear.addBox(-2.0, 0.0, -2.0, 4, 12, 4, expandOffset + 0.25) + self.bipedRightLegwear.setCenterPoint(-1.9, 12.0, 0.0) + self.bipedBodyWear = ModelRenderer(self, 16, 32) + self.bipedBodyWear.addBox(-4.0, 0.0, -2.0, 8, 12, 4, expandOffset + 0.25) + self.bipedBodyWear.setCenterPoint(0.0, 0.0, 0.0) + + @property + def parts(self): + return [ + self.bipedHead, + self.bipedHeadwear, + self.bipedBody, + self.bipedBodyWear, + self.bipedRightArm, + self.bipedRightArmwear, + self.bipedLeftArm, + self.bipedLeftArmwear, + self.bipedRightLeg, + self.bipedRightLegwear, + self.bipedLeftLeg, + self.bipedLeftLegwear, + ] diff --git a/src/mcedit2/rendering/chunkmeshes/entitymesh.py b/src/mcedit2/rendering/chunkmeshes/entitymesh.py index f809b1b..301111c 100644 --- a/src/mcedit2/rendering/chunkmeshes/entitymesh.py +++ b/src/mcedit2/rendering/chunkmeshes/entitymesh.py @@ -396,7 +396,7 @@ class ItemFrameMesh(EntityMeshBase): } -def entityModelNode(ref, model, modelTex, chunk): +def entityModelNode(ref, model, modelTex=None, chunk=None, flip=False): modelVerts = numpy.array(model.vertices) modelVerts.shape = modelVerts.shape[0]//4, 4, modelVerts.shape[1] # scale down @@ -404,20 +404,26 @@ def entityModelNode(ref, model, modelTex, chunk): modelVerts[..., 1] = -modelVerts[..., 1] + 1.5 + 1/64. modelVerts[..., 0] = -modelVerts[..., 0] - vertexBuffer = QuadVertexArrayBuffer(len(modelVerts), lights=False, textures=True) + vertexBuffer = QuadVertexArrayBuffer(len(modelVerts), lights=False, textures=modelTex is not None) vertexBuffer.vertex[:] = modelVerts[..., :3] - vertexBuffer.texcoord[:] = modelVerts[..., 3:5] + if modelTex is not None: + vertexBuffer.texcoord[:] = modelVerts[..., 3:5] node = VertexNode([vertexBuffer]) + pos = ref.Position + if chunk is not None: + pos = pos - (chunk.cx << 4, 0, chunk.cz << 4) + + translate = Translate(pos) + node.addState(translate) + rotate = Rotate(ref.Rotation[0], (0., 1., 0.)) node.addState(rotate) - translate = Translate((ref.Position - (chunk.cx << 4, 0, chunk.cz << 4))) - node.addState(translate) - - bindTexture = BindTexture(modelTex, (1./model.texWidth, 1./model.texHeight, 1)) - node.addState(bindTexture) + if modelTex is not None: + bindTexture = BindTexture(modelTex, (1./model.texWidth, 1./model.texHeight * (-1 if flip else 1), 1)) + node.addState(bindTexture) return node @@ -501,6 +507,7 @@ def chestEntityModelNode(ref, model, modelTex, chunk, facing, largeX, largeZ): node.addState(bindTexture) return node + class TileEntityModelRenderer(ChunkMeshBase): layer = Layer.TileEntities diff --git a/src/mcedit2/rendering/players.py b/src/mcedit2/rendering/players.py new file mode 100644 index 0000000..a633a5b --- /dev/null +++ b/src/mcedit2/rendering/players.py @@ -0,0 +1,136 @@ +""" + playermesh +""" +from __future__ import absolute_import, division, print_function, unicode_literals +import logging +import os + +import numpy +from OpenGL import GL + +from mcedit2.rendering.chunkmeshes.entity.models import cookedModels +from mcedit2.rendering.chunkmeshes.entitymesh import entityModelNode +from mcedit2.rendering.scenegraph.misc import Enable +from mcedit2.rendering.scenegraph.scenenode import Node +from mcedit2.util import glutils +from mcedit2.util.load_png import loadPNGTexture, loadPNGFile +from mcedit2.util.player_server import PlayerDataCache + +log = logging.getLogger(__name__) + + +class PlayerNode(Node): + def __init__(self, playerRef): + super(PlayerNode, self).__init__() + self.playerRef = playerRef + self.entityNode = None + + def _callback(result, error): + if result: + self.texturePath = result['texturePath'] + else: + self.texturePath = None + if error: + log.info("Error getting player info: %s", error) + + PlayerDataCache.getPlayerInfo(playerRef.UUID, _callback) + + _texturePath = None + + @property + def texturePath(self): + return self._texturePath + + @texturePath.setter + def texturePath(self, value): + self._texturePath = value + if value is not None: + log.info("Got texture path: %s", value) + w, h, modelImage = loadPNGFile(value) + # modelTex = loadPNGTexture(value) + if h == 32: + w, h, modelImage = fixupTextureImage(modelImage) + + tex = glutils.Texture(name=os.path.basename(value), image=modelImage.ravel(), + width=w, height=h) + + if self.entityNode: + self.removeChild(self.entityNode) + + self.entityNode = entityModelNode(self.playerRef, cookedModels['MCEDIT_Player'], tex) + self.entityNode.addState(Enable(GL.GL_ALPHA_TEST)) + self.addChild(self.entityNode) + else: + log.info("Did not get texture path.") + + +def fixupTextureImage(modelImage): + w = 64 + h = 64 + oh, ow, b = modelImage.shape + + newImage = numpy.zeros((h, w, b), dtype='uint8') + newImage[:oh, :ow, :] = modelImage[::-1] + #newImage = newImage[::-1, :, :] + + def drawImage(x1, y1, x2, y2, sx1, sy1, sx2, sy2): + def _slice(a, b): + if a > b: + return slice(a-1, b-1, -1) + else: + return slice(a, b) + newImage[_slice(y1, y2), _slice(x1, x2)] = newImage[_slice(sy1, sy2), _slice(sx1, sx2)] + + drawImage(24, 48, 20, 52, 4, 16, 8, 20) + drawImage(28, 48, 24, 52, 8, 16, 12, 20) + drawImage(20, 52, 16, 64, 8, 20, 12, 32) + drawImage(24, 52, 20, 64, 4, 20, 8, 32) + drawImage(28, 52, 24, 64, 0, 20, 4, 32) + drawImage(32, 52, 28, 64, 12, 20, 16, 32) + drawImage(40, 48, 36, 52, 44, 16, 48, 20) + drawImage(44, 48, 40, 52, 48, 16, 52, 20) + drawImage(36, 52, 32, 64, 48, 20, 52, 32) + drawImage(40, 52, 36, 64, 44, 20, 48, 32) + drawImage(44, 52, 40, 64, 40, 20, 44, 32) + drawImage(48, 52, 44, 64, 52, 20, 56, 32) + + #newImage = newImage[::-1, :, :] + # } + # + # graphics.dispose(); + # this.imageData = ((DataBufferInt)bufferedimage.getRaster().getDataBuffer()).getData(); + # this.setAreaOpaque(0, 0, 32, 16); + # this.setAreaTransparent(32, 0, 64, 32); + # this.setAreaOpaque(0, 16, 64, 32); + # this.setAreaTransparent(0, 32, 16, 48); + # this.setAreaTransparent(16, 32, 40, 48); + # this.setAreaTransparent(40, 32, 56, 48); + # this.setAreaTransparent(0, 48, 16, 64); + # this.setAreaOpaque(16, 48, 48, 64); + # this.setAreaTransparent(48, 48, 64, 64); + # return bufferedimage; + + return w, h, newImage + +class PlayersNode(Node): + def __init__(self, dimension): + """ + + Parameters + ---------- + dimension : mceditlib.worldeditor.WorldEditorDimension + """ + super(PlayersNode, self).__init__() + + playerNodes = [] + if not hasattr(dimension, 'worldEditor'): + # gross, dimension may be a MaskLevel + return + + for playerName in dimension.worldEditor.listPlayers(): + player = dimension.worldEditor.getPlayer(playerName) + if player.Dimension == dimension.dimNo: + playerNodes.append(PlayerNode(player)) + + for node in playerNodes: + self.addChild(node) diff --git a/src/mcedit2/rendering/worldscene.py b/src/mcedit2/rendering/worldscene.py index afabbd9..bfda613 100644 --- a/src/mcedit2/rendering/worldscene.py +++ b/src/mcedit2/rendering/worldscene.py @@ -11,6 +11,7 @@ import numpy from mcedit2.rendering.layers import Layer from mcedit2.rendering import chunkupdate +from mcedit2.rendering.players import PlayersNode from mcedit2.rendering.scenegraph import scenenode from mcedit2.rendering import renderstates from mcedit2.rendering.chunknode import ChunkNode, ChunkGroupNode @@ -229,6 +230,9 @@ class WorldScene(scenenode.Node): self.minlod = 0 self.bounds = bounds + self.playersNode = PlayersNode(dimension) + self.addChild(self.playersNode) + def setTextureAtlas(self, textureAtlas): if textureAtlas is not self.textureAtlas: self.textureAtlas = textureAtlas