diff --git a/README.md b/README.md index 9580200..96dae6d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ blender2minecraft ================= -A Blender Add-on to create Minecraft 3D-Models inside Blender+ +A Blender Add-on to create Minecraft 3D-Models inside Blender. Feel free to send pull requests. This add-on probably needs a lot of reworking, but I don't have the time to do it. (Warning: Code is pretty messy. I had very little python experience when I wrote it) diff --git a/blender2minecraft.py b/blender2minecraft.py index 0a8892c..fe445f3 100644 --- a/blender2minecraft.py +++ b/blender2minecraft.py @@ -1,7 +1,7 @@ bl_info = { "name": "Blender2Minecraft", "author": "freundTech", - "version": (0, 1), + "version": (0, 2), "blender": (2, 6, 9), "location": "File > Export > Export to Minecraft", "description": "Export Scene as Minecraft Blockmodel", @@ -11,37 +11,33 @@ "category": "Import-Export" } - import bpy from bpy import context import bmesh import os import math - +import json x = 0 y = 1 z = 2 -nl = os.linesep -tab = " " toRound = 2 - def getMaxMin(values, use): max = [None]*len(use) min = [None]*len(use) for u in range(0, len(use)): max[u] = float('-inf') min[u] = float('inf') - + for value in values: for u in range(0, len(use)): if value[use[u]] > max[u]: max[u] = value[use[u]] if value[use[u]] < min[u]: min[u] = value[use[u]] - + for u in range(0, len(use)): max[u] = round(max[u], toRound) min[u] = round(min[u], toRound) @@ -53,21 +49,21 @@ def getIndex(values, mask, toUse): return values.index(value) raise Exception("Value not found") -def rstr(num): - return str(round(num, toRound)) +def rval(num): + return round(num, toRound) def getDir(face): normals = [] for i in range(0, len(face.loops)): normals.append(list(face.loops[i].vert.normal)) - + top = 0 bottom = 0 north = 0 south = 0 east = 0 west = 0 - + for i in range(0, len(normals)): if normals[i][x] >= 0: east += 1 @@ -81,7 +77,7 @@ def getDir(face): top += 1 else: bottom += 1 - + if top == 4: return ["up", [x, y]] if bottom == 4: @@ -94,41 +90,46 @@ def getDir(face): return ["east", [y, z]] if west == 4: return ["west", [y, z]] - raise Exception("This should never happen") - + raise Exception("This should never happen") + class attrdict(dict): def __init__(self, *args, **kwargs): dict.__init__(self, *args, **kwargs) self.__dict__ = self -def write_to_file(context, filepath, include_textures, ambientocclusion, firsttrans, firstscale, firstrot, thirdtrans, thirdscale, thirdrot, invtrans, invscale, invrot): +def write_to_file(context, filepath, include_textures, ambientocclusion, minify, + firsttrans, firstscale, firstrot, + thirdtrans, thirdscale, thirdrot, + invtrans, invscale, invrot, + headtrans, headscale, headrot, + groundtrans, groundscale, groundrot, + fixedtrans, fixedscale, fixedrot): textures = [] particle = "" scene = context.scene objects = scene.objects + file = open(filepath,'w', encoding='utf-8') - file.write("{" + nl) - file.write(tab + "\"__comment\": \"This model was created with freundTech's Blender2Minecraft converter (BETA)\"," + nl) - - file.write(tab + "\"ambientocclusion\": " + str(ambientocclusion).lower() + "," + nl) - - file.write(tab + "\"elements\": [" + nl) - - firstObj = True - + + fileContent = {} + + fileContent["__comment"] = "This model was created with freundTech's Blender2Minecraft converter (BETA)" + fileContent["ambientocclusion"] = ambientocclusion + fileContent["elements"] = [] + if bpy.ops.object.mode_set.poll(): - bpy.ops.object.mode_set(mode='OBJECT') + bpy.ops.object.mode_set(mode='OBJECT') for obj in objects: if obj.type == 'MESH': - + data = obj.data bm = bmesh.new() bm.from_mesh(data) uv_layer = bm.loops.layers.uv.active - + if len(bm.faces) == 6: - box = [] + box = [] for i in range(0, len(obj.bound_box)): box.append([]) for j in range(0, len(obj.bound_box[i])): @@ -136,8 +137,7 @@ def write_to_file(context, filepath, include_textures, ambientocclusion, firsttr pos = obj.location scale = obj.scale #print(str(obj.bound_box[0][:]) + " " + str(obj.bound_box[1][:]) + " " + str(obj.bound_box[2][:]) + str(obj.bound_box[3][:]) + " " + str(obj.bound_box[4][:]) + " " + str(obj.bound_box[5][:]) + " " + str(obj.bound_box[6][:]) + " " + str(obj.bound_box[7][:]) + " ") - - + for co in box: for i in range(0, 3): co[i] *= scale[i] @@ -145,29 +145,26 @@ def write_to_file(context, filepath, include_textures, ambientocclusion, firsttr co[i] *= 16 co[x] += 8 co[y] = (co[y]) * -1 + 8 - + #print(nl + nl) #print(box[:][:]) toCoord, fromCoord = getMaxMin(box, [x, y, z]) print(toCoord) print(fromCoord) - - if firstObj: - firstObj = False - else: - file.write("," + nl) - + objname = [""] for c in obj.name: if c != '.': objname[len(objname)-1] += c else: objname.append("") - - file.write(tab + tab + "{ \"__comment\": \"" + objname[0] + "\"," + nl) - file.write(tab + tab + tab + "\"from\": [ " + rstr(fromCoord[x]) + ", " + rstr(fromCoord[z]) + ", " + rstr(fromCoord[y]) + " ]," + nl) - file.write(tab + tab + tab + "\"to\": [ " + rstr(toCoord[x]) + ", " + rstr(toCoord[z]) + ", " + rstr(toCoord[y]) + " ]," + nl) - + + item = {} + + item["__comment"] = objname[0] + item["from"] = [rval(fromCoord[x]), rval(fromCoord[z]), rval(fromCoord[y])] + item["to"] = [rval(toCoord[x]), rval(toCoord[z]), rval(toCoord[y])] + rotation = [round(math.degrees(a), 1) for a in obj.rotation_euler] notnull = 0 for i in range(0, len(rotation)): @@ -180,57 +177,52 @@ def write_to_file(context, filepath, include_textures, ambientocclusion, firsttr if notnull > 1: raise Exception("Only one Axis can be rotated at a time!") elif notnull == 1: - if rotation[axis] == -22.5 or rotation[axis] == 22.5 or rotation[axis] == -45 or rotation[axis] == 45: - file.write(tab + tab + tab + "\"rotation\": { \"origin\": [ " + rstr(pos[x]*16+8) + ", " + rstr(pos[z]*16) + ", " + rstr(pos[y]*16+8) + " ], \"axis\": \"") - + if rotation[axis] == -22.5 or rotation[axis] == 22.5 or rotation[axis] == -45 or rotation[axis] == 45: + item["rotation"] = { "origin": [rval(pos[x]*16+8), rval(pos[z]*16), rval(pos[y]*16+8)] } + + axisStr = "none" if axis == 0: - file.write("x") + axisStr = "x" elif axis == 1: - file.write("z") - rotation[axis] *= -1 + axisStr = "z" + rotation[axis] *= -1 elif axis == 2: - file.write("y") - file.write("\", \"angle\": " + str(rotation[axis])) + axisStr = "y" + item["rotation"]["axis"] = axisStr + item["rotation"]["angle"] = rotation[axis] + for n in objname: if n[0:8] == "rescale:": - file.write(", \"rescale\": " + n[8:]) - file.write(" }," + nl) + item["rotation"]["rescale"] = n[8:].lower() == "true" else: raise Exception("You can only rotate by 22.5, -22.5, 45 or -45 degrees!") - - - file.write(tab + tab + tab + "\"faces\": {" + nl) - - firstUv = True - + + item["faces"] = {} + for face in bm.faces: if len(face.loops) == 4: direction, toUse = getDir(face) - + try: uvs = [] for i in range(0, len(face.loops)): uvs.append([face.loops[i][uv_layer].uv[x] * 16, face.loops[i][uv_layer].uv[y] * 16]) except AttributeError: - uvs = [[16,16],[ 0,16],[ 0, 0],[16, 0]] - + uvs = [[16, 16], [0, 16], [0, 0], [16, 0]] + max, min = getMaxMin(uvs, [x, y]) - - - + if min[x] != max[x] and min[y] != max[y]: - + verts = [] for i in range(0, len(face.loops)): verts.append([face.loops[i].vert.co[x] * 16, face.loops[i].vert.co[y] * 16, face.loops[i].vert.co[z] * 16]) print(face.loops[i].vert.co) maxr, minr = getMaxMin(verts, toUse) - + print(maxr) print(minr) - - if direction == "south": bottom = minr elif direction == "east": @@ -243,7 +235,7 @@ def write_to_file(context, filepath, include_textures, ambientocclusion, firsttr bottom = [maxr[0], minr[1]] elif direction == "west": bottom = [maxr[0], minr[1]] - + print(bottom) print(verts) minI = getIndex(verts, bottom, toUse) @@ -255,15 +247,15 @@ def write_to_file(context, filepath, include_textures, ambientocclusion, firsttr minUv = list(uvs[minI]) for i in range(0, len(minUv)): minUv[i] = round(minUv[i], toRound) - + nextI = minI + 1 while nextI >= 4: nextI -= 4 - + nextUv = list(uvs[nextI]) for i in range(0, len(nextUv)): nextUv[i] = round(nextUv[i], toRound) - + if minUv == min and nextUv == [max[x], min[y]]: rot = 0 mirror = False @@ -297,147 +289,143 @@ def write_to_file(context, filepath, include_textures, ambientocclusion, firsttr print(rot) print(mirror) - + try: image = data.uv_textures.active.data[face.index].image except AttributeError: image = attrdict(name=["texture"], filepath="") - + name = [""] for c in image.name: if c != '.': name[len(name)-1] += c else: name.append("") - + path = [""] filepath = "" imagepath = bpy.path.abspath(image.filepath) imagepath = os.path.abspath(imagepath) - - path = imagepath.split(os.sep) + path = imagepath.split(os.sep) for dir in path: index = path.index(dir) if dir == "assets" and path[index+1] == "minecraft" and path[index+2] == "textures": for i in range(index+3, len(path)-1): filepath += path[i] - filepath += "/" - + filepath += "/" + for c in path[len(path)-1]: if c != '.': filepath += c else: break - - - + if not [name[0], filepath] in textures: textures.append([name[0], filepath]) - + print(name) - if firstUv: - firstUv = False - else: - file.write("," + nl) - + print(direction) print(minUv) print(nextUv) print(max) print(min) - file.write(tab + tab + tab + tab + "\"" + direction + "\": { ") - + s = max[y] - + max[y] = (min[y]- 8)*-1+8 min[y] = (s- 8)*-1+8 - - + + item["faces"][direction] = {} + if not mirror: - file.write("\"uv\": [ "+str(min[x])+", "+str(min[y])+", "+str(max[x])+", "+str(max[y])+" ], \"texture\": \"#" + name[0] + "\", \"rotation\": " + str(rot)) + item["faces"][direction]["uv"] = [min[x], min[y], max[x], max[y]] + item["faces"][direction]["texture"] = "#" + name[0] + item["faces"][direction]["rotation"] = rot else: - file.write("\"uv\": [ "+str(max[x])+", "+str(min[y])+", "+str(min[x])+", "+str(max[y])+" ], \"texture\": \"#" + name[0] + "\", \"rotation\": " + str(rot)) - + item["faces"][direction]["uv"] = [max[x], min[y], min[x], max[y]] + item["faces"][direction]["texture"] = "#" + name[0] + item["faces"][direction]["rotation"] = rot + for n in name: if n[0:9] == "cullface:": - file.write(", \"cullface\": \""+n[9:]+"\"") + item["faces"][direction]["cullface"] = n[9:] elif n[0:8] == "cullface": - file.write(", \"cullface\": \""+direction+"\"") + item["faces"][direction]["cullface"] = direction elif n[0:10] == "tintindex:": - file.write(", \"tintindex\": "+n[10:]) + item["faces"][direction]["tintindex"] = int(n[10:]) elif n[0:9] == "tintindex": - file.write(", \"tintindex\": 1") + item["faces"][direction]["tintindex"] = 1 elif n[0:8] == "particle": particle = filepath - file.write(" }") - print(rstr(max[x]) + nl) - print(rstr(min[x]) + nl) - print(rstr(max[y]) + nl) - print(rstr(min[y]) + nl + nl) - - else: print("Object \"" + data.name + "\" is not a cube!!!") #TODO - file.write(nl) - file.write(tab + tab + tab + "}" + nl) - file.write(tab + tab + "}") - + fileContent["elements"].append(item) + else: print("Object \"" + data.name + "\" is not a cube!") - - file.write(nl + tab + "]," + nl) + if include_textures: - file.write(tab + "\"textures\": {" + nl) - - + fileContent["textures"] = {} + for texture in textures: - file.write(tab + tab + "\"" + texture[0] + "\": " + "\"" + texture[1] + "\"," + nl) - + fileContent["textures"][texture[0]] = texture[1] + if particle != "": - file.write(tab + tab + "\"particle\": \"" + particle + "\"" + nl) - - file.write(tab + "}," + nl) - - file.write(tab + "\"display\": {" + nl) - file.write(tab + tab + "\"firstperson\": {" + nl) - file.write(tab + tab + tab + "\"rotation\": [ " + rstr(firstrot[x]) + ", " + rstr(firstrot[y]) + ", " + rstr(firstrot[z]) + " ]," + nl) - file.write(tab + tab + tab + "\"translation\": [ " + rstr(firsttrans[x]) + ", " + rstr(firsttrans[y]) + ", " + rstr(firsttrans[z]) + " ]," + nl) - file.write(tab + tab + tab + "\"scale\": [ " + rstr(firstscale[x]) + ", " + rstr(firstscale[y]) + ", " + rstr(firstscale[z]) + " ]" + nl) - file.write(tab + tab + "}," + nl) - - file.write(tab + tab + "\"thirdperson\": {" + nl) - file.write(tab + tab + tab + "\"rotation\": [ " + rstr(thirdrot[x]) + ", " + rstr(thirdrot[y]) + ", " + rstr(thirdrot[z]) + " ]," + nl) - file.write(tab + tab + tab + "\"translation\": [ " + rstr(thirdtrans[x]) + ", " + rstr(thirdtrans[y]) + ", " + rstr(thirdtrans[z]) + " ]," + nl) - file.write(tab + tab + tab + "\"scale\": [ " + rstr(thirdscale[x]) + ", " + rstr(thirdscale[y]) + ", " + rstr(thirdscale[z]) + " ]" + nl) - file.write(tab + tab + "}," + nl) - - file.write(tab + tab + "\"gui\": {" + nl) - file.write(tab + tab + tab + "\"rotation\": [ " + rstr(invrot[x]) + ", " + rstr(invrot[y]) + ", " + rstr(invrot[z]) + " ]," + nl) - file.write(tab + tab + tab + "\"translation\": [ " + rstr(invtrans[x]) + ", " + rstr(invtrans[y]) + ", " + rstr(invtrans[z]) + " ]," + nl) - file.write(tab + tab + tab + "\"scale\": [ " + rstr(invscale[x]) + ", " + rstr(invscale[y]) + ", " + rstr(invscale[z]) + " ]" + nl) - file.write(tab + tab + "}" + nl) - - file.write(tab + "}" + nl) - - file.write("}") - - file.close() - + fileContent["textures"]["particle"] = particle + + fileContent["display"] = { + "firstperson": { + "rotation": [rval(firstrot[x]), rval(firstrot[y]), rval(firstrot[z])], + "translation": [rval(firsttrans[x]), rval(firsttrans[y]), rval(firsttrans[z])], + "scale": [rval(firstscale[x]), rval(firstscale[y]), rval(firstscale[z])] + }, + "thirdperson": { + "rotation": [rval(thirdrot[x]), rval(thirdrot[y]), rval(thirdrot[z])], + "translation": [rval(thirdtrans[x]), rval(thirdtrans[y]), rval(thirdtrans[z])], + "scale": [rval(thirdscale[x]), rval(thirdscale[y]), rval(thirdscale[z])] + }, + "gui": { + "rotation": [rval(invrot[x]), rval(invrot[y]), rval(invrot[z])], + "translation": [rval(invtrans[x]), rval(invtrans[y]), rval(invtrans[z])], + "scale": [rval(invscale[x]), rval(invscale[y]), rval(invscale[z])] + }, + "head": { + "rotation": [rval(headrot[x]), rval(headrot[y]), rval(headrot[z])], + "translation": [rval(headtrans[x]), rval(headtrans[y]), rval(headtrans[z])], + "scale": [rval(headscale[x]), rval(headscale[y]), rval(headscale[z])] + }, + "ground": { + "rotation": [rval(groundrot[x]), rval(groundrot[y]), rval(groundrot[z])], + "translation": [rval(groundtrans[x]), rval(groundtrans[y]), rval(groundtrans[z])], + "scale": [rval(groundscale[x]), rval(groundscale[y]), rval(groundscale[z])] + }, + "fixed": { + "rotation": [rval(fixedrot[x]), rval(fixedrot[y]), rval(fixedrot[z])], + "translation": [rval(fixedtrans[x]), rval(fixedtrans[y]), rval(fixedtrans[z])], + "scale": [rval(fixedscale[x]), rval(fixedscale[y]), rval(fixedscale[z])] + } + } + + if(minify): + file.write(json.dumps(fileContent, separators=(',', ':'), sort_keys=False)) + else: + file.write(json.dumps(fileContent, indent=4, sort_keys=False)) + + file.close() return {'FINISHED'} - # ExportHelper is a helper class, defines filename and # invoke() function which calls the file selector. from bpy_extras.io_utils import ExportHelper from bpy.props import StringProperty, BoolProperty, EnumProperty, FloatProperty from bpy.types import Operator - class ExportBlockModel(Operator, ExportHelper): """This appears in the tooltip of the operator and in the generated docs""" bl_idname = "export_mc.blockmodel" # important since its how bpy.ops.import_test.some_data is constructed @@ -460,163 +448,19 @@ class ExportBlockModel(Operator, ExportHelper): description="Turns the Ambient Occlusion option on or off", default=True, ) - firsttransx = FloatProperty( - name="X", - description="Moves the Object in firstperson on the X axis", - default=0.0, - ) - firsttransy = FloatProperty( - name="Y", - description="Moves the Object in firstperson on the Y axis", - default=0.0, - ) - firsttransz = FloatProperty( - name="Z", - description="Moves the Object in firstperson on the Z axis", - default=0.0, - ) - firstrotx = FloatProperty( - name="X", - description="Rotates the Object in firstperson on the X axis", - default=0.0, - ) - firstroty = FloatProperty( - name="Y", - description="Rotates the Object in firstperson on the Y axis", - default=0.0, - ) - firstrotz = FloatProperty( - name="Z", - description="Rotates the Object in firstperson on the Z axis", - default=0.0, - ) - firstscalex = FloatProperty( - name="X", - description="Scales the Object in firstperson on the X axis", - default=1.0, - ) - firstscaley = FloatProperty( - name="Y", - description="Scales the Object in firstperson on the Y axis", - default=1.0, - ) - firstscalez = FloatProperty( - name="Z", - description="Scales the Object in firstperson on the Z axis", - default=1.0, - ) - thirdtransx = FloatProperty( - name="X", - description="Moves the Object in thirdperson on the X axis", - default=0.0, - ) - thirdtransy = FloatProperty( - name="Y", - description="Moves the Object in thirdperson on the Y axis", - default=0.0, - ) - thirdtransz = FloatProperty( - name="Z", - description="Moves the Object in thirdperson on the Z axis", - default=0.0, - ) - thirdrotx = FloatProperty( - name="X", - description="Rotates the Object in thirdperson on the X axis", - default=0.0, - ) - thirdroty = FloatProperty( - name="Y", - description="Rotates the Object in thirdperson on the Y axis", - default=0.0, - ) - thirdrotz = FloatProperty( - name="Z", - description="Rotates the Object in thirdperson on the Z axis", - default=0.0, - ) - thirdscalex = FloatProperty( - name="X", - description="Scales the Object in thirdperson on the X axis", - default=1.0, - ) - thirdscaley = FloatProperty( - name="Y", - description="Scales the Object in thirdperson on the Y axis", - default=1.0, - ) - thirdscalez = FloatProperty( - name="Z", - description="Scales the Object in thirdperson on the Z axis", - default=1.0, - ) - - invtransx = FloatProperty( - name="X", - description="Moves the Object in the Inventory on the X axis", - default=0.0, - ) - invtransy = FloatProperty( - name="Y", - description="Moves the Object in the Inventory on the Y axis", - default=0.0, - ) - invtransz = FloatProperty( - name="Z", - description="Moves the Object in the Inventory on the Z axis", - default=0.0, - ) - invrotx = FloatProperty( - name="X", - description="Rotates the Object in the Inventory on the X axis", - default=0.0, - ) - invroty = FloatProperty( - name="Y", - description="Rotates the Object in the Inventory on the Y axis", - default=0.0, - ) - invrotz = FloatProperty( - name="Z", - description="Rotates the Object in the Inventory on the Z axis", - default=0.0, - ) - invscalex = FloatProperty( - name="X", - description="Scales the Object in the Inventory on the X axis", - default=1.0, - ) - invscaley = FloatProperty( - name="Y", - description="Scales the Object in the Inventory on the Y axis", - default=1.0, - ) - invscalez = FloatProperty( - name="Z", - description="Scales the Object in the Inventory on the Z axis", - default=1.0, + minify = BoolProperty( + name="Minify Json", + description="Reduces size of exported .json by omitting redundant whitespaces", + default=True, ) -# randomoffset_x = BoolProperty( -# name="X", -# description="Use Random Offset on the X Axis", -# default=False, -# ) -# randomoffset_y = BoolProperty( -# name="Y", -# description="Use Random Offset on the X Axis", -# default=False, -# ) -# randomoffset_z = BoolProperty( -# name="Z", -# description="Use Random Offset on the X Axis", -# default=False, -# ) -# inverntory3drender = BoolProperty( -# name="Inventory 3D Rendering", -# description="Renders the Block 3D inside an inventory", -# default=True, -# ) - + + fpTransform = bpy.props.FloatVectorProperty(name = "First Person Transform", description = "Translation, Rotation and Scale of first person (in hand) rendering", size = 9, default=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0]) + tpTransform = bpy.props.FloatVectorProperty(name = "Third Person Transform", description = "Translation, Rotation and Scale of third person rendering", size = 9, default=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0]) + guiTransform = bpy.props.FloatVectorProperty(name = "GUI Transform", description = "Translation, Rotation and Scale in the GUI (Inventory)", size = 9, default=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0]) + headTransform = bpy.props.FloatVectorProperty(name = "Head Transform", description = "Translation, Rotation and Scale when equipped as helmet", size = 9, default=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0]) + groundTransform = bpy.props.FloatVectorProperty(name = "Ground Transform", description = "Translation, Rotation and Scale on the ground", size = 9, default=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0]) + fixedTransform = bpy.props.FloatVectorProperty(name = "Item Frame Transform", description = "Translation, Rotation and Scale in Item Frames", size = 9, default=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0]) + def draw(self, context): layout = self.layout @@ -626,75 +470,44 @@ def draw(self, context): layout.label(text="Textures:") row = layout.row() row.prop(self, "include_textures") - + layout.label(text="Ambient Occlusion:") row = layout.row() row.prop(self, "ambientocclusion") - - - layout.label() - layout.label(text="First Person:") - split = layout.split() - col = split.column(align=True) - col.label(text="Translate:") - col.prop(self, "firsttransx") - col.prop(self, "firsttransy") - col.prop(self, "firsttransz") - - col = split.column(align=True) - col.label(text="Rotate:") - col.prop(self, "firstrotx") - col.prop(self, "firstroty") - col.prop(self, "firstrotz") - - col = split.column(align=True) - col.label(text="Scale:") - col.prop(self, "firstscalex") - col.prop(self, "firstscaley") - col.prop(self, "firstscalez") - - layout.label() - layout.label(text="Third Person:") - split = layout.split() - col = split.column(align=True) - col.label(text="Translate:") - col.prop(self, "thirdtransx") - col.prop(self, "thirdtransy") - col.prop(self, "thirdtransz") - - col = split.column(align=True) - col.label(text="Rotate:") - col.prop(self, "thirdrotx") - col.prop(self, "thirdroty") - col.prop(self, "thirdrotz") - - col = split.column(align=True) - col.label(text="Scale:") - col.prop(self, "thirdscalex") - col.prop(self, "thirdscaley") - col.prop(self, "thirdscalez") - - - layout.label() - layout.label(text="Inventory:") - split = layout.split() - col = split.column(align=True) - col.label(text="Translate:") - col.prop(self, "invtransx") - col.prop(self, "invtransy") - col.prop(self, "invtransz") - - col = split.column(align=True) - col.label(text="Rotate:") - col.prop(self, "invrotx") - col.prop(self, "invroty") - col.prop(self, "invrotz") - - col = split.column(align=True) - col.label(text="Scale:") - col.prop(self, "invscalex") - col.prop(self, "invscaley") - col.prop(self, "invscalez") + + layout.label(text="Minify Json:") + row = layout.row() + row.prop(self, "minify") + + def createTransform(name, value): + layout.label() + layout.label(text=name) + split = layout.split() + col = split.column(align=True) + col.label(text="Translate:") + col.prop(self, value, index=0, text="X") + col.prop(self, value, index=1, text="Y") + col.prop(self, value, index=2, text="Z") + + col = split.column(align=True) + col.label(text="Rotate:") + col.prop(self, value, index=3, text="X") + col.prop(self, value, index=4, text="Y") + col.prop(self, value, index=5, text="Z") + + col = split.column(align=True) + col.label(text="Scale:") + col.prop(self, value, index=6, text="X") + col.prop(self, value, index=7, text="Y") + col.prop(self, value, index=8, text="Z") + + createTransform("First Person:", "fpTransform") + createTransform("Third Person:", "tpTransform") + createTransform("Inventory:", "guiTransform") + createTransform("Head:", "headTransform") + createTransform("Ground:", "groundTransform") + createTransform("Item Frame:", "fixedTransform") + # layout.label(text="NOTE: The following options don't work in 14w26b") # layout.label(text="They used to work in 14w21b. Hopefully they get readded.") # row = layout.row() @@ -703,39 +516,44 @@ def draw(self, context): # row.prop(self, "randomoffset_x") # row.prop(self, "randomoffset_y") # row.prop(self, "randomoffset_z") -# +# # layout.label(text="Inventory Rendering:") # row = layout.row() # row.prop(self, "inverntory3drender") def execute(self, context): - return write_to_file(context, self.filepath, self.include_textures, self.ambientocclusion, - [self.firsttransx, self.firsttransy, self.firsttransz], - [self.firstscalex, self.firstscaley, self.firstscalez], - [self.firstrotx, self.firstroty, self.firstrotz], - [self.thirdtransx, self.thirdtransy, self.thirdtransz], - [self.thirdscalex, self.thirdscaley, self.thirdscalez], - [self.thirdrotx, self.thirdroty, self.thirdrotz], - [self.invtransx, self.invtransy, self.invtransz], - [self.invscalex, self.invscaley, self.invscalez], - [self.invrotx, self.invroty, self.invrotz]) - + return write_to_file(context, self.filepath, self.include_textures, self.ambientocclusion, self.minify, + self.fpTransform[0:3], + self.fpTransform[6:9], + self.fpTransform[3:6], + self.tpTransform[0:3], + self.tpTransform[6:9], + self.tpTransform[3:6], + self.guiTransform[0:3], + self.guiTransform[6:9], + self.guiTransform[3:6], + self.headTransform[0:3], + self.headTransform[6:9], + self.headTransform[3:6], + self.groundTransform[0:3], + self.groundTransform[6:9], + self.groundTransform[3:6], + self.fixedTransform[0:3], + self.fixedTransform[6:9], + self.fixedTransform[3:6]) # Only needed if you want to add into a dynamic menu def menu_func_export(self, context): self.layout.operator(ExportBlockModel.bl_idname, text="Minecraft model (.json)") - def register(): bpy.utils.register_class(ExportBlockModel) bpy.types.INFO_MT_file_export.append(menu_func_export) - def unregister(): bpy.utils.unregister_class(ExportBlockModel) bpy.types.INFO_MT_file_export.remove(menu_func_export) - if __name__ == "__main__": register()