Skip to content

Commit

Permalink
Add files
Browse files Browse the repository at this point in the history
  • Loading branch information
lifelandman committed Apr 10, 2023
1 parent a5dd9e6 commit ec27eb2
Show file tree
Hide file tree
Showing 3 changed files with 289 additions and 0 deletions.
29 changes: 29 additions & 0 deletions ZABEE main/__init__.py
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()
65 changes: 65 additions & 0 deletions ZABEE main/export.py
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
195 changes: 195 additions & 0 deletions ZABEE main/parse.py
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

0 comments on commit ec27eb2

Please sign in to comment.