#!BPY ################ #author: Daniel Jungmann (dsj at gmx dot net) #version: 3.0 ################ """ Name: 'Eternal-Lands files (.e3d)' Blender: 245 Group: 'Export' Tip: 'Export to Eternal-Lands 3d object files.' """ import Blender from Blender import NMesh, Object, Mesh from Blender import Draw, BGL from Blender.BGL import * from Blender.Draw import * from Blender.Window import * from Blender.Image import * from Blender.Mathutils import Vector import sys, struct, string from types import * from math import * import os from os import path import md5 import gzip path = Blender.Get('uscriptsdir') if not path: path = Blender.Get('scriptsdir') if not path: path = Blender.Get('filename') sys.path.append(path) import el3d from el3d import * from el3d.optimizer import * from el3d.el3d_file_obj import * do_compress = 0 has_extra_uv = 0 has_color = 0 first_uv = 0 second_uv = 0 alpha_uv = 0 do_check = 0 size = [0.01, 0.5] uv_range = [0.0, 1.0] EVENT_NOEVENT = 1 EVENT_EXPORT = 2 EVENT_CANCEL = 3 EVENT_DO_CHECK = 4 EVENT_SAVE_COLOR = 5 EVENT_DO_COMPRESS = 6 EVENT_EXTRA_UV = 7 EVENT_FIRST_UV = 8 EVENT_SECOND_UV = 9 EVENT_ALPHA_UV = 9 EVENT_TRANSPARENT_BASE = 11 material_count = 0 material_dict = {} material_options = [] material_names = [] default_uv_layer = "UVTex" extra_uv_layer = "" alpha_uv_layer = "" layer_list = [] uv_menu = Create(1) extra_uv_menu = Create(1) default_filename = "" clear_options = 1 def save_el3d(filename): global do_compress, has_extra_uv, do_check, has_color, uv_range, size global material_dict, material_count, material_options, material_names global default_uv_layer, extra_uv_layer, alpha_uv_layer if (filename.find(".e3d", -4) <= 0): if (do_compress): if (filename.find(".e3d.gz", -7) <= 0): filename += ".e3d.gz" else: filename += ".e3d" elif (do_compress): filename += ".gz" save_obj = el3d_file() print "Starting e3d export to file: ", filename #get the currently selected data structures for mesh_object in Blender.Object.GetSelected(): if (mesh_object.getType() == "Mesh"): #get access to the mesh data mesh = mesh_object.getData(False, True) break #convert quads to tris mesh.quadToTriangle(1) for i in range(0, material_count): save_obj.add_material(Blender.sys.basename(material_names[i][0]), Blender.sys.basename(material_names[i][1]), material_options[i]) for face in mesh.faces: if (len(layer_list) > 1): cur_layer = mesh.activeUVLayer mesh.activeUVLayer = default_uv_layer material_name_1 = face.image.getFilename() mesh.activeUVLayer = extra_uv_layer material_name_2 = face.image.getFilename() mesh.activeUVLayer = cur_layer material_dict_name = material_name_1 + material_name_2 else: material_dict_name = face.image.getFilename() if (material_dict[material_dict_name] != i): continue for j in range(0, 3): co = mesh.verts[face.v[j].index].co uv = face.uv[j] if (has_color): col = face.col[j] color = [int(col.r), int(col.g), int(col.b), int(col.a)] else: color = [0] * 4 if (has_extra_uv): mesh.activeUVLayer = extra_uv_layer face = mesh.faces[i] extra_uv = face.uv mesh.activeUVLayer = default_uv_layer else: extra_uv = [0] * 2 save_obj.add_face_corner(co[0], co[1], co[2], uv[0], uv[1], extra_uv[0], extra_uv[1], color) ret = save_obj.save(filename, do_compress, has_extra_uv, do_check, has_color, uv_range, size) if (ret.count("uv")): print "UV coordinates of file:", infile, "are out of range", uv_range if (ret.count("size")): print "Error with triangle side size of file:\t", infile print "Done e3d export to file: ", filename def fill_mat(mesh): global material_dict, material_count, material_options, material_names global default_uv_layer, extra_uv_layer, alpha_uv_layer, layer_list, uv_menu global clear_options material_count = 0 material_dict = {} material_names = [] if (clear_options): material_options = [] for face in mesh.faces: try: if (len(layer_list) > 1): cur_layer = mesh.activeUVLayer mesh.activeUVLayer = default_uv_layer if (not face.image): return False material_name_1 = face.image.getFilename() mesh.activeUVLayer = extra_uv_layer if (not face.image): return False material_name_2 = face.image.getFilename() mesh.activeUVLayer = cur_layer material_name = [material_name_1, material_name_2] material_dict_name = material_name_1 + material_name_2 else: if (not face.image): return False material_name = [face.image.getFilename(), ""] material_dict_name = face.image.getFilename() except ValueError: return False if not material_dict.has_key(material_dict_name): material_dict[material_dict_name] = material_count if (clear_options): material_options.append(0) material_names.append(material_name) material_count += 1 clear_options = 0 return True def draw(): global do_compress, has_extra_uv, first_uv, second_uv, alpha_uv, do_check global material_dict, material_count, material_options, material_names global default_uv_layer, extra_uv_layer, alpha_uv_layer, layer_list, uv_menu global extra_uv_menu, default_filename, has_color global EVENT_NOEVENT, EVENT_CANCEL, EVENT_EXPORT, EVENT_DO_CHECK, EVENT_SAVE_COLOR global EVENT_DO_COMPRESS, EVENT_EXTRA_UV, EVENT_ALPHA_UV global EVENT_TRANSPARENT_BASE, EVENT_FIRST_UV glClear(GL_COLOR_BUFFER_BIT) size = list(Blender.Window.GetAreaSize()) #get the currently selected data structures for mesh_object in Blender.Object.GetSelected(): if (mesh_object.getType() == "Mesh"): #get access to the mesh data mesh = mesh_object.getData(False, True) default_filename = mesh_object.name + ".e3d" if (do_compress): default_filename += ".gz" break layer_list = mesh.getUVLayerNames() if (len(layer_list) > 0): default_uv_layer = layer_list[first_uv] extra_uv_layer = layer_list[second_uv] alpha_uv_layer = layer_list[alpha_uv] if (not fill_mat(mesh)): PupMenu("Error: Not all faces have images!") Exit() return menu_string = "" for i in range (0, len(layer_list)): menu_string += "| " + layer_list[i] + " %x" + str(i) if (len(layer_list) > 1): if size[0] < 450: size[0] = 450 else: if size[0] < 230: size[0] = 230 columns = (size[0] - 10) / 220 rows = (material_count + columns - 1) / columns columns = min(columns, material_count) rows = max(rows, 1) if (size[1] < (270 + rows * 30)): size[1] = 270 + rows * 30 # 10 px border rect = [10, 10, size[0] - 11, size[1] - 11] middle = (rect[0] + rect[2]) / 2 string = "EL Exporter Options" glRasterPos2i(middle - (GetStringWidth(string, "large") / 2), \ rect[3] - 9) Text(string, "large") glRasterPos2i(middle - (GetStringWidth(string, "large") / 2) + 1, \ rect[3] - 9) Text(string, "large") rect[3] -= 16 if (len(layer_list) > 1): pos = middle - 215 else: pos = middle - 105 rect[3] -= 30 Toggle("GZip Compression", EVENT_DO_COMPRESS, pos, rect[3], 210, 25, \ do_compress) if (len(layer_list) > 1): glRasterPos2i(pos + 220, rect[3] + 9) Text("First UV coordinates", "large") rect[3] -= 30 Toggle("Save extra uv's", EVENT_EXTRA_UV, pos, rect[3], \ 210, 25, has_extra_uv) uv_menu = Menu("First UV coordinates %t" + menu_string, \ EVENT_FIRST_UV, pos + 220, rect[3], 210, 25, first_uv) rect[3] -= 30 Toggle("Check", EVENT_DO_CHECK, pos, rect[3], 210, 25, do_check) if (len(layer_list) > 1): glRasterPos2i(pos + 220, rect[3] + 9) Text("Second UV coordinates", "large") rect[3] -= 30 if (mesh.vertexColors): Toggle("Save colors", EVENT_SAVE_COLOR, pos, rect[3], 210, 25, has_color) if (len(layer_list) > 1): extra_uv_menu = Menu("Second UV coordinates %t" + \ menu_string, EVENT_SECOND_UV, pos + 220, rect[3], \ 210, 25, second_uv) if (len(layer_list) > 2): rect[3] -= 30 glRasterPos2i(pos + 220, rect[3] + 9) Text("Alpha UV coordinates", "large") rect[3] -= 30 alpha_uv_menu = Menu("Alpha UV coordinates %t" + \ menu_string, EVENT_ALPHA_UV, pos + 220, rect[3], \ 210, 25, alpha_uv) rect[3] -= 10 string = "Transparent Materials" glRasterPos2i(middle - (GetStringWidth(string, "large") / 2), \ rect[3] - 9) Text(string, "large") glRasterPos2i(middle - (GetStringWidth(string, "large") / 2) + 1, \ rect[3] - 9) Text(string, "large") rect[3] -= 16 i = 0 start_pos = middle - columns * 110 + 5 if (columns > 0): for string in material_names: if ((i % columns) == 0): pos = start_pos rect[3] -= 30 Toggle(Blender.sys.basename(string[0]), \ EVENT_TRANSPARENT_BASE + i, pos, rect[3], \ 210, 25, material_options[i]) pos += 220 i += 1 Button("Export", EVENT_EXPORT, middle + 005, rect[1], 100, 50) Button("Cancel", EVENT_CANCEL, middle - 105, rect[1], 100, 50) def event(evt, val): if (evt == QKEY and not val): Exit() def bevent(evt): global do_compress, has_extra_uv, first_uv, do_check, has_color global second_uv, alpha_uv, material_dict, material_count, material_options global material_names, default_uv_layer, extra_uv_layer, uv_menu global extra_uv_menu, alpha_uv_menu, default_filename global EVENT_NOEVENT, EVENT_CANCEL, EVENT_EXPORT, EVENT_DO_CHECK, EVENT_SAVE_COLOR global EVENT_DO_COMPRESS, EVENT_EXTRA_UV, EVENT_ALPHA_UV global EVENT_TRANSPARENT_BASE, EVENT_FIRST_UV, EVENT_SECOND_UV global clear_options if (evt == EVENT_EXPORT): if (has_extra_uv and (first_uv == second_uv)): PupMenu("Warning: First and second texture " + \ "coordinates are the same layer! " + \ "Second texture coordinates disabled.") Blender.Window.FileSelector(save_el3d, "Export e3dx", default_filename) Redraw(1) elif (evt == EVENT_DO_COMPRESS): do_compress = 1 - do_compress Redraw(1) elif (evt == EVENT_DO_CHECK): do_check = 1 - do_check Redraw(1) elif (evt == EVENT_SAVE_COLOR): has_color = 1 - has_color Redraw(1) elif (evt == EVENT_EXTRA_UV): has_extra_uv = 1 - has_extra_uv Redraw(1) elif (evt == EVENT_FIRST_UV): if (first_uv != uv_menu.val): clear_options = 1 first_uv = uv_menu.val Redraw(1) elif (evt == EVENT_SECOND_UV): second_uv = extra_uv_menu.val Redraw(1) elif (evt == EVENT_ALPHA_UV): alpha_uv = alpha_uv_menu.val Redraw(1) elif ((evt >= EVENT_TRANSPARENT_BASE) and (evt < \ (EVENT_TRANSPARENT_BASE + material_count))): i = evt - EVENT_TRANSPARENT_BASE material_options[i] = 1 - material_options[i] Redraw(1) elif (evt == EVENT_CANCEL): Exit() def register_exporter(): for mesh_object in Blender.Object.GetSelected(): if (mesh_object.getType() == "Mesh"): #get access to the mesh data Register(draw, event, bevent) return PupMenu("Fatal Error: You must select a mesh to output as e3d!") register_exporter()