-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a5dd9e6
commit ec27eb2
Showing
3 changed files
with
289 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
|
||
bl_info = { | ||
"name": "ZABEE", | ||
"author": "Jackson \"Lifeland\" S.", | ||
"version": (0, 1), | ||
"blender": (3, 5, 0), | ||
"description": "", | ||
"warning": "", | ||
"location": "File > Export", | ||
"wiki_url": "", | ||
"category": "Export"} | ||
|
||
import bpy | ||
from . import export | ||
|
||
modules = [export] | ||
|
||
def register(): | ||
|
||
for module in modules: | ||
module.register() | ||
|
||
def unregister(): | ||
|
||
for module in modules: | ||
module.unregister() | ||
|
||
if __name__ == "__main__": | ||
register() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import bpy | ||
from . import parse | ||
|
||
def write_egg(context, filepath, egg_string): | ||
print("running write_egg...") | ||
f = open(filepath, 'w', encoding='utf-8') | ||
f.write(egg_string) | ||
f.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 | ||
from bpy.types import Operator | ||
|
||
|
||
class export_egg(Operator, ExportHelper): | ||
"""This function generates and exports an EGG file intended for use with panda3d.""" | ||
bl_idname = "export_egg.some_data" # important since its how bpy.ops.import_test.some_data is constructed | ||
bl_label = "Export Egg File" | ||
|
||
# ExportHelper mixin class uses this | ||
filename_ext = ".egg" | ||
|
||
filter_glob: StringProperty( | ||
default="*.egg", | ||
options={'HIDDEN'}, | ||
maxlen=255, # Max internal buffer length, longer would be clamped. | ||
) | ||
|
||
# List of operator properties, the attributes will be assigned | ||
# to the class instance from the operator settings before calling. | ||
imageDir: StringProperty( | ||
default="images\\", | ||
description="The path to this model's textures relative\nto the config file's model path" | ||
) | ||
|
||
def execute(self, context):##Put egg generating code here: | ||
egg_string = parse.write_egg_string(self.imageDir) | ||
return write_egg(context, self.filepath, egg_string) | ||
|
||
|
||
# Only needed if you want to add into a dynamic menu | ||
def menu_func_export(self, context): | ||
self.layout.operator(export_egg.bl_idname, text="Egg (Panda3D)") | ||
|
||
|
||
# Register and add to the "file selector" menu (required to use F3 search "Text Export Operator" for quick access). | ||
def register(): | ||
bpy.utils.register_class(export_egg) | ||
bpy.types.TOPBAR_MT_file_export.append(menu_func_export) | ||
|
||
|
||
def unregister(): | ||
bpy.utils.unregister_class(export_egg) | ||
bpy.types.TOPBAR_MT_file_export.remove(menu_func_export) | ||
|
||
|
||
if __name__ == "__main__": | ||
register() | ||
|
||
# test call |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
import bpy | ||
|
||
accepted_types = ('MESH') | ||
|
||
def process_mesh(mesh, name, mats, useTex, indent = 1):#should return egg string for this mesh without hierarchy indentation | ||
newliner = "\n" + (" "* indent) | ||
|
||
|
||
#create vertecies. | ||
#We have several duplicate verticies so the same point can coorispond to multiple uv coordinates. | ||
|
||
loop_id_lookup = {}#This is gonna be a dictionary where a loop id coorisponds to one of the vertexpool's verticies. | ||
#This is so when we're making polygons, we can look up verticie ids by loop, if need be. | ||
|
||
uv_match_check = {}#ex of what this will look like: {vert.id, {(uxx, uvy), eggvertid}} | ||
|
||
egg_data = newliner + "<VertexPool> " + name + "_pool {" | ||
|
||
idNum = 0 | ||
|
||
for loop in mesh.loops:#Generate verticies and lookup table(s) | ||
|
||
vertex_id = loop.vertex_index | ||
loop_id = loop.index | ||
uvLoop = mesh.uv_layers[0] | ||
uv_cor = uvLoop.uv[loop_id] | ||
|
||
vert = mesh.vertices[vertex_id] | ||
|
||
if vertex_id in uv_match_check: | ||
if uv_cor in uv_match_check[vertex_id]: | ||
loop_id_lookup[loop_id] = uv_match_check[vertex_id][uv_cor] | ||
continue | ||
|
||
egg_data += (newliner + " <Vertex> " + str(idNum) + ' { ' + str(vert.co[0]) + ' ' + str(vert.co[1]) + ' ' + str(vert.co[2]) | ||
+ newliner + " <Normal> { " + str(vert.normal[0]) + ' ' + str(vert.normal[1]) + ' ' + str(vert.normal[2]) + '}' + newliner | ||
+ " <UV> { " + str(uv_cor.vector.x) + ' ' + str(uv_cor.vector.y) + " }" | ||
) | ||
egg_data += '}' | ||
|
||
if not vertex_id in uv_match_check: | ||
uv_match_check[vertex_id] = {} | ||
|
||
uv_match_check[vertex_id][uv_cor] = vert | ||
loop_id_lookup[loop_id] = idNum | ||
idNum +=1#counter for how many vertices we've made | ||
|
||
|
||
egg_data += '\n}' | ||
|
||
idNum = 0 | ||
for poly in mesh.polygons: | ||
egg_data += newliner + "<Polygon> " + str(idNum) + " { " | ||
|
||
if useTex: | ||
egg_data += "<TRef> { " + mats[poly.material_index] + " }" + newliner | ||
|
||
egg_data += " <VertexRef> { " | ||
for loop in poly.loop_indices: | ||
egg_data += str(loop_id_lookup[loop]) + ' ' | ||
egg_data += "<ref> { " + name + "_pool }}}" | ||
|
||
idNum += 1 | ||
|
||
return egg_data | ||
|
||
|
||
|
||
def childProcess(objects, known_objects, known_names, texture_path, indent = 1): | ||
newliner = "\n" + (" "* indent) | ||
egg_string = "\n" | ||
|
||
for obj in objects: | ||
if not obj in known_objects: | ||
known_objects.append(obj) | ||
|
||
mats = [] | ||
|
||
name = obj.name.replace(" ", "_") | ||
nameinc = 0 | ||
nameTest = name | ||
while nameTest in known_names: | ||
nameinc += 1 | ||
nameTest = name + str(nameinc) | ||
if nameinc > 0: | ||
name = nameTest | ||
known_names.append(name) | ||
|
||
if obj.type in accepted_types: | ||
|
||
egg_string += (newliner + "<group> %s {\n" % name) | ||
|
||
child_addition = '' | ||
children = obj.children | ||
if len(children) > 0: | ||
child_addition = childProcess(children, known_objects, known_names, texture_path, indent + 1) | ||
if obj.type == "MESH": | ||
|
||
useTex = False | ||
#Add texture references, and calculate the slot data for materials | ||
picnum = len(obj.to_mesh().materials) | ||
if picnum != 0: | ||
useTex = True | ||
for i in range(picnum): | ||
mat = obj.to_mesh().materials[i] | ||
img_name = None | ||
for x in mat.node_tree.nodes: | ||
if x.bl_static_type=='TEX_IMAGE': | ||
img_name = x.image.name | ||
tex_name = img_name.replace(' ', '_') | ||
break | ||
|
||
if tex_name != None: | ||
mats.append(tex_name) | ||
egg_string += "\n<Texture> " + tex_name + " { " + texture_path + img_name + " }" | ||
|
||
egg_string += newliner | ||
|
||
#Process the mesh, and apply texture stuff in necissary | ||
new_addition = process_mesh(obj.to_mesh(), name, mats, useTex, indent) | ||
egg_string += new_addition | ||
|
||
egg_string += child_addition | ||
|
||
egg_string += newliner + "}" | ||
return egg_string | ||
|
||
|
||
######################## MAIN FUNCTION ##################################################### | ||
|
||
def write_egg_string(texture_path): | ||
known_objects = [] | ||
known_names = []#necissary so we can tell when we need to add an incrementing digit if multiple objects share a name. | ||
|
||
egg_string = "<CoordinateSystem> { Z-Up }\n\n" | ||
|
||
mats = [] | ||
|
||
for obj in bpy.data.objects: | ||
if not obj in known_objects: | ||
known_objects.append(obj) | ||
|
||
|
||
name = obj.name.replace(" ", "_") | ||
nameinc = 0 | ||
nameTest = name | ||
while nameTest in known_names: | ||
nameinc += 1 | ||
nameTest = name + str(nameinc) | ||
if nameinc > 0: | ||
name = nameTest | ||
known_names.append(name) | ||
|
||
if obj.type in accepted_types: | ||
|
||
|
||
|
||
egg_string += ("\n<group> %s {\n" % name) | ||
|
||
child_addition = '' | ||
children = obj.children | ||
if len(children) > 0: | ||
child_addition = childProcess(children, known_objects, known_names, texture_path) | ||
if obj.type == "MESH": | ||
|
||
useTex = False | ||
#Add texture references, and calculate the slot data for materials | ||
picnum = len(obj.to_mesh().materials) | ||
if picnum > 0: | ||
useTex = True | ||
for i in range(picnum): | ||
mat = obj.to_mesh().materials[i] | ||
img_name = None | ||
tex_name = None | ||
for x in mat.node_tree.nodes: | ||
if x.bl_static_type=='TEX_IMAGE':##THIS IS APPARENTLY DEPRICATED; and for some f*****g reason the only alternative I can find is as well. good luck, future me! | ||
img_name = x.image.name | ||
tex_name = img_name.replace(' ', '_') | ||
break | ||
|
||
if tex_name != None: | ||
mats.append(tex_name) | ||
egg_string += "\n<Texture> " + tex_name + " { " + texture_path + img_name + " }" | ||
|
||
egg_string += '\n' | ||
|
||
#Process the mesh, and apply texture stuff in necissary | ||
new_addition = process_mesh(obj.to_mesh(), name, mats, useTex) | ||
egg_string += new_addition | ||
|
||
egg_string += child_addition | ||
|
||
egg_string += "\n}" | ||
return egg_string | ||
|