finish cleanup

This commit is contained in:
ABelliqueux 2021-03-12 13:06:21 +01:00
parent 55af8e8406
commit c0ba209f87
1 changed files with 427 additions and 84 deletions

View File

@ -1,6 +1,4 @@
# bpy. app. debug = True
bl_info = {
"name": "PSX TMesh exporter",
@ -13,12 +11,19 @@ bl_info = {
}
import os
import bpy
import bmesh
import unicodedata
from math import radians, degrees, floor, cos, sin
from mathutils import Vector
from collections import defaultdict
from bpy.props import (CollectionProperty,
StringProperty,
BoolProperty,
@ -31,122 +36,282 @@ from bpy_extras.io_utils import (ExportHelper,
)
class ExportMyFormat(bpy.types.Operator, ExportHelper):
bl_idname = "export_psx.c";
bl_label = "PSX compatible scene exporter";
bl_options = {'PRESET'};
filename_ext = ".c";
exp_Triangulate = BoolProperty(
name="Triangulate meshes ( Destructive ! )",
description="Triangulate meshes (destructive ! Do not use your original file)",
default=False,
)
exp_Scale = FloatProperty(
name="Scale",
description="Scale of exported mesh.",
min=1, max=1000,
default=65,
)
exp_Precalc = BoolProperty(
name="Use precalculated BGs",
description="Set the BGs UV to black",
default=False,
)
def execute(self, context):
def triangulate_object(obj): # Stolen from here : https://blender.stackexchange.com/questions/45698/triangulate-mesh-in-python/45722#45722
def triangulate_object(obj):
# Triangulate an object's mesh
# Source : https://blender.stackexchange.com/questions/45698/triangulate-mesh-in-python/45722#45722
me = obj.data
# Get a BMesh representation
bm = bmesh.new()
bm.from_mesh(me)
bmesh.ops.triangulate(bm, faces=bm.faces[:], quad_method=0, ngon_method=0)
# Finish up, write the bmesh back to the mesh
bm.to_mesh(me)
bm.free()
# ~ return bm
def CleanName(strName):
# Removes specials characters, dots ans space from string
name = strName.replace(' ','_')
name = name.replace('.','_')
name = unicodedata.normalize('NFKD',name).encode('ASCII', 'ignore').decode()
return name
def isInPlane(plane, obj):
# Checks if 'obj' has its coordinates contained between the plane's coordinate.
# If 'obj' is partly contained, returns which side (S, W, N, E) it's overlapping.
# If 'obj' is not contained in 'plane', returns 0.
if (
(LvlPlanes[plane]['x1'] < LvlObjects[obj]['x1'] and LvlPlanes[plane]['x2'] > LvlObjects[obj]['x2']) and
(LvlPlanes[plane]['y1'] < LvlObjects[obj]['y1'] and LvlPlanes[plane]['y2'] > LvlObjects[obj]['y2'])
):
return 1
# Overlap on the West side of the plane
if (
( LvlPlanes[plane]['x1'] > LvlObjects[obj]['x1'] and LvlPlanes[plane]['x1'] < LvlObjects[obj]['x2'] ) and
( LvlPlanes[plane]['y1'] < LvlObjects[obj]['y1'] and LvlPlanes[plane]['y2'] > LvlObjects[obj]['y2'] )
):
return 4
# Overlap on the East side of the plane
if (
( LvlPlanes[plane]['x2'] < LvlObjects[obj]['x2'] and LvlPlanes[plane]['x2'] > LvlObjects[obj]['x1'] ) and
( LvlPlanes[plane]['y1'] < LvlObjects[obj]['y1'] and LvlPlanes[plane]['y2'] > LvlObjects[obj]['y2'] )
):
return 6
# Overlap on the North side of the plane
if (
( LvlPlanes[plane]['y2'] < LvlObjects[obj]['y2'] and LvlPlanes[plane]['y2'] > LvlObjects[obj]['y1'] ) and
( LvlPlanes[plane]['x1'] < LvlObjects[obj]['x1'] and LvlPlanes[plane]['x2'] > LvlObjects[obj]['x2'] )
):
return 8
# Overlap on the South side of the plane
if (
( LvlPlanes[plane]['y1'] > LvlObjects[obj]['y1'] and LvlPlanes[plane]['y1'] < LvlObjects[obj]['y2'] ) and
( LvlPlanes[plane]['x1'] < LvlObjects[obj]['x1'] and LvlPlanes[plane]['x2'] > LvlObjects[obj]['x2'] )
):
return 2
else:
return 0
def getSepLine(plane, side):
# Construct the line used for BSP generation from 'plane' 's coordinates, on specified side (S, W, N, E)
# Returns an array of 3 values
if side == 'S':
return [ LvlPlanes[plane]['x1'], LvlPlanes[plane]['y1'], LvlPlanes[plane]['x2'], LvlPlanes[plane]['y1'] ]
if side == 'N':
return [ LvlPlanes[plane]['x1'], LvlPlanes[plane]['y2'], LvlPlanes[plane]['x2'], LvlPlanes[plane]['y2'] ]
if side == 'W':
return [ LvlPlanes[plane]['x1'], LvlPlanes[plane]['y1'], LvlPlanes[plane]['x1'], LvlPlanes[plane]['y2'] ]
if side == 'E':
return [ LvlPlanes[plane]['x2'], LvlPlanes[plane]['y1'], LvlPlanes[plane]['x2'], LvlPlanes[plane]['y2'] ]
def checkLine(lineX1, lineY1 ,lineX2 ,lineY2, objX1, objY1, objX2, objY2):
# Returns wether object spanning from objXY1 to objXY2 is Back, Front, Same or Intersecting the line
# defined by points (lineXY1, lineXY2)
val1 = ( objX1 - lineX1 ) * ( lineY2-lineY1 ) - ( objY1 - lineY1 ) * ( lineX2 - lineX1 )
# rounding to avoid false positives
val1 = round(val1, 4)
val2 = ( objX2 - lineX1 ) * ( lineY2-lineY1 ) - ( objY2 - lineY1 ) * ( lineX2 - lineX1 )
val2 = round(val2, 4)
if ( (val1 > 0) and (val2 > 0) ):
return "front"
elif ( (val1 < 0) and (val2 < 0) ):
return "back"
elif ( (val1 == 0) and (val2 == 0) ):
return "same"
elif (
( (val1>0) and (val2==0) ) or
( (val1==0) and (val2>0) )
):
return "front"
elif (
( (val1<0) and (val2==0) ) or
( (val1==0) and (val2<0) )
):
return "back"
elif (
( (val1<0) and (val2>0) ) or
( (val1>0) and (val2<0) )
):
return "intersect"
# Leave edit mode to avoid errors
bpy.ops.object.mode_set(mode='OBJECT')
# triangulate objects of type mesh
# If set, triangulate objects of type mesh
if self.exp_Triangulate:
for o in range(len(bpy.data.objects)):
if bpy.data.objects[o].type == 'MESH':
triangulate_object(bpy.data.objects[o])
# ~ obj = bpy.data.objects[bpy.data.objects[o].name]
# ~ tm = obj.to_mesh(bpy.context.scene, False, 'PREVIEW')
# ~ work_meshes.append(tm)
# Set Scale
scale = self.exp_Scale
# get working directory path
# Get working directory path
filepath = bpy.data.filepath
folder = os.path.dirname(bpy.path.abspath(filepath))
dirpath = os.path.join(folder, "TIM")
### Export pre-calculated backgrounds
camAngles = []
defaultCam = 'NULL'
# if using precalculated BG, render and export them to ./TIM/
# If using precalculated BG, render and export them to ./TIM/
if self.exp_Precalc:
# create folder if !exist
# Create folder if it doesn't exist
os.makedirs(dirpath, exist_ok = 1)
# file format config
# Set file format config
bpy.context.scene.render.image_settings.file_format = 'PNG'
bpy.context.scene.render.image_settings.quality = 100
bpy.context.scene.render.image_settings.compression = 0
bpy.context.scene.render.image_settings.color_depth = '8'
# get current cam
# Get active cam
cam = bpy.context.scene.camera
# store cam location and rot for restoration later
# ~ originLoc = cam.location
# ~ originRot = cam.rotation_euler
# Find default cam, and cameras in camPath
for o in bpy.data.objects:
if o.type == 'CAMERA' and o.data.get('isDefault'):
defaultCam = o.name
if o.type == 'CAMERA' and o.name.startswith("camPath"):
# set cam as active - could be useful if multiple cam are present
# Set camera as active
bpy.context.scene.camera = o
# set cam Rot/Loc to empty rot/loc
# ~ cam.location = o.location
# ~ cam.rotation_euler = o.rotation_euler
# Render and save image
# apply 90degrees rotation on local X axis, as EMPTYs are pointing to -Z (bottom of the screen) by default
# ~ cam.rotation_euler.rotate_axis('X', radians(90))
# render and save image
bpy.ops.render.render()
bpy.data.images["Render Result"].save_render(folder + os.sep + "TIM" + os.sep + "bg_" + CleanName(o.name) + "." + str(bpy.context.scene.render.image_settings.file_format).lower())
# Add camera object to camAngles
camAngles.append(o)
# set cam back to original pos/rot
# ~ cam.location = originLoc
# ~ cam.rotation_euler = originRot
### Start writing output file
# Open file
f = open(os.path.normpath(self.filepath),"w+")
# write BODY struct def
## Add C structures definitions
# BODY
f.write("typedef struct {\n" +
"\tVECTOR gForce;\n" +
"\tVECTOR position;\n" +
@ -158,7 +323,8 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
"\tint restitution; \n" +
"\t} BODY;\n\n")
# VERTEX ANIM struct
# VANIM
f.write("typedef struct { \n" +
"\tint nframes; // number of frames e.g 20\n" +
"\tint nvert; // number of vertices e.g 21\n" +
@ -170,13 +336,15 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
# ~ "\tSVECTOR normals[]; // vertex pos as SVECTORs e.g 20 * 21 SVECTORS\n" +
"\t} VANIM;\n\n")
# PRIM struc
# PRIM
f.write("typedef struct {\n" +
"\tVECTOR order;\n" +
"\tint code; // Same as POL3/POL4 codes : Code (F3 = 1, FT3 = 2, G3 = 3, GT3 = 4) Code (F4 = 5, FT4 = 6, G4 = 7, GT4 = 8)\n" +
"\t} PRIM;\n\n")
# MESH struct
# MESH
f.write("typedef struct { \n"+
"\tTMESH * tmesh;\n" +
"\tPRIM * index;\n" +
@ -198,38 +366,49 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
"\tVANIM * anim;\n" +
"\t} MESH;\n\n")
# CAM POSITION struct
# CAMPOS
f.write("typedef struct {\n" +
"\tVECTOR pos;\n" +
"\tSVECTOR rot;\n" +
"\t} CAMPOS;\n\n" +
"\n// Blender cam ~= PSX cam with these settings : NTSC - 320x240, PAL 320x256, pixel ratio 1:1, cam focal length : perspective 90° ( 16 mm ))\n\n")
# CAM ANGLE
# CAMANGLE
f.write("typedef struct {\n" +
"\tCAMPOS * campos;\n" +
"\tTIM_IMAGE * BGtim;\n" +
"\tunsigned long * tim_data;\n" +
"\t} CAMANGLE;\n\n")
# CAM PATH struct
# CAMPATH
f.write("typedef struct {\n" +
"\tshort len, cursor, pos;\n" +
"\tVECTOR points[];\n" +
"\t} CAMPATH;\n\n")
# NODE struc
f.Write("typedef struct {\n" +
# NODE
f.write("typedef struct {\n" +
"\tMESH * curPlane;\n" +
"\tMESH * siblings[];" +
"\tMESH * objects[];" +
"\tMESH * siblings[];\n" +
"\tMESH * objects[];\n" +
"\t} NODE;\n\n")
## Camera setup
# List of points defining the camera path
camPathPoints = []
# Define first mesh. Will be used as default if no properties are found in meshes
first_mesh = CleanName(bpy.data.meshes[0].name)
# set camera position and rotation in the scene
# Set camera position and rotation in the scene
for o in range(len(bpy.data.objects)):
if bpy.data.objects[o].type == 'CAMERA' and bpy.data.objects[o].data.get('isDefault'):
defaultCam = bpy.data.objects[o].name
@ -239,13 +418,18 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
"\t{" + str(round(-(degrees(bpy.data.objects[o].rotation_euler.x)-90)/360 * 4096)) + "," + str(round(degrees(bpy.data.objects[o].rotation_euler.z)/360 * 4096)) + "," + str(round(-(degrees(bpy.data.objects[o].rotation_euler.y))/360 * 4096)) + "}\n" +
"};\n\n")
# find camStart and camEnd empties for camera trajectory
# Find camera path points and append them to camPathPoints[]
if bpy.data.objects[o].type == 'CAMERA' :
if bpy.data.objects[o].name.startswith("camPath") and not bpy.data.objects[o].data.get('isDefault'):
camPathPoints.append(bpy.data.objects[o].name)
# Write the CAMPATH structure
if camPathPoints:
# Populate with points found above
# ~ camPathPoints = list(reversed(camPathPoints))
for p in range(len(camPathPoints)):
@ -259,15 +443,24 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
if p != len(camPathPoints) - 1:
f.write(",\n")
f.write("\n\t}\n};\n\n")
else:
# If no camera path points are found, use default
f.write("CAMPATH camPath = {\n" +
"\t0,\n" +
"\t0,\n" +
"\t0\n" +
"};\n\n")
# Lights : max 3 sunlamp, no space coords
# LLM : Local Light Matrix
## Lighting setup
# Light sources will be similar to Blender's sunlamp
# A maximum of 3 light sources will be used
# LLM : Local Light Matrix
if len(bpy.data.lamps) is not None:
# ~ f.write( "static MATRIX lgtmat = {\n" +
@ -282,15 +475,15 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
f.write( "static MATRIX lgtmat = {\n")
for l in range(len(bpy.data.lamps)):
## intensity
# Lightsource energy
energy = int(bpy.data.lamps[l].energy * 4096)
# Euler based
# Get lightsource's world orientation
# get a direction vector from world matrix
lightdir = bpy.data.objects[bpy.data.lamps[l].name].matrix_world * Vector((0,0,-1,0))
f.write(
"\t" + str(int(lightdir.x * energy)) + "," +
"\t" + str(int(-lightdir.z * energy)) + "," +
@ -300,6 +493,8 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
if l != len(bpy.data.lamps) - 1:
f.write(",\n")
# If less than 3 light sources exist in blender, fill the matrix with 0s.
if pad:
f.write(",\n")
while cnt < pad:
@ -311,6 +506,7 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
f.write("\n\t};\n\n")
# LCM : Local Color Matrix
f.write( "static MATRIX cmat = {\n")
LCM = []
@ -323,12 +519,16 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
while len(LCM) < 9:
LCM.append('0')
# Write LC matrix
f.write(
"\t" + LCM[0] + "," + LCM[3] + "," + LCM[6] + ",\n" +
"\t" + LCM[1] + "," + LCM[4] + "," + LCM[7] + ",\n" +
"\t" + LCM[2] + "," + LCM[5] + "," + LCM[8] + "\n" )
f.write("\t};\n\n")
## Meshes
actorPtr = first_mesh
levelPtr = first_mesh
propPtr = first_mesh
@ -338,23 +538,24 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
for m in bpy.data.meshes:
# Write vertices vectors
# Store vertices coordinates by axis to find max/min coordinates
# AABB : Store vertices coordinates by axis
Xvals = []
Yvals = []
Zvals = []
# remove '.' from mesh name
cleanName = CleanName(m.name)
# ~ cleanName = m.name.replace('.','_')
# ~ cleanName = unicodedata.normalize('NFKD',cleanName).encode('ASCII', 'ignore').decode()
# Write vertices vectors
f.write("SVECTOR "+"model"+cleanName+"_mesh[] = {\n")
for i in range(len(m.vertices)):
v = m.vertices[i].co
# AABB : append vertices coords by axis
# Append vertex coords to lists
Xvals.append(v.x)
Yvals.append(v.y)
Zvals.append(-v.z)
@ -390,72 +591,124 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
if len(m.uv_textures) != None:
for t in range(len(m.uv_textures)):
if m.uv_textures[t].data[0].image != None:
f.write("SVECTOR "+"model"+cleanName+"_uv[] = {\n")
texture_image = m.uv_textures[t].data[0].image
tex_width = texture_image.size[0]
tex_height = texture_image.size[1]
uv_layer = m.uv_layers[0].data
for i in range(len(uv_layer)):
u = uv_layer[i].uv
ux = u.x * tex_width
uy = u.y * tex_height
# ~ if self.exp_Precalc and m.get('isBG'):
# ~ f.write("\t255, 255, 0, 0") # Clamp values to 0-255 to avoid tpage overflow
# ~ else:
f.write("\t"+str(max(0, min( round(ux) , 255 )))+","+str(max(0, min(round(tex_height - uy) , 255 )))+", 0, 0") # Clamp values to 0-255 to avoid tpage overflow
if i != len(uv_layer) - 1:
f.write(",")
f.write("\n")
f.write("};\n\n")
# save uv tex if needed - still have to convert them to tim...
# Save UV texture to a file in ./TIM
# It will have to be converted to a tim file
if texture_image.filepath == '':
os.makedirs(dirpath, exist_ok = 1)
texture_image.filepath_raw = folder + os.sep + "TIM" + os.sep + CleanName(texture_image.name) + "." + texture_image.file_format
texture_image.save()
# Write vertex colors vectors
f.write("CVECTOR "+"model"+cleanName+"_color[] = {\n")
f.write("CVECTOR "+"model"+cleanName+"_color[] = {\n")
# If vertex colors exist, use them
if len(m.vertex_colors) != 0:
colors = m.vertex_colors[0].data
for i in range(len(colors)):
f.write("\t"+str(int(colors[i].color.r*255))+","+str(int(colors[i].color.g*255))+","+str(int(colors[i].color.b*255))+", 0")
if i != len(colors) - 1:
f.write(",")
f.write("\n")
# If no vertex colors, default to 2 whites, 1 grey
else:
for i in range(len(m.polygons) * 3):
if i % 3 == 0:
f.write("\t80,80,80,0") # Let's add a bit more relief with a shade of grey
f.write("\t80,80,80,0")
else:
f.write("\t128,128,128,0")
if i != (len(m.polygons) * 3) - 1:
f.write(",")
f.write("\n")
f.write("};\n\n")
# Write polygons index + type
f.write("PRIM "+"model"+cleanName+"_index[] = {\n")
for i in range(len(m.polygons)):
poly = m.polygons[i]
f.write("\t"+str(poly.vertices[0])+","+str(poly.vertices[1])+","+str(poly.vertices[2]))
if len(poly.vertices) > 3:
f.write("," + str(poly.vertices[3]) + ",8")
else:
f.write(",0,4")
if i != len(m.polygons) - 1:
f.write(",")
f.write("\n")
f.write("};\n\n")
# get custom properties isRigidBody, isPrism, isAnim
# Get object's custom properties
chkProp = {
'isAnim':0,
'isRigidBody':0,
@ -488,16 +741,24 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
if m.get('isLevel'):
nodePtr = cleanName
# write vertex anim if isAnim != 0 # https://stackoverflow.com/questions/9138637/vertex-animation-exporter-for-blender
## Vertex animation
# write vertex anim if isAnim != 0
# Source : https://stackoverflow.com/questions/9138637/vertex-animation-exporter-for-blender
if m.get("isAnim") is not None and m["isAnim"] != 0:
#write vertex pos
# Write vertex pos
o = bpy.data.objects[m.name]
# ~ frame_start = bpy.context.scene.frame_start
frame_start = int(bpy.data.actions[m.name].frame_range[0])
# ~ frame_end = bpy.context.scene.frame_end
frame_end = int(bpy.data.actions[m.name].frame_range[1])
nFrame = frame_end - frame_start
@ -509,11 +770,13 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
for i in range(frame_start, frame_end):
bpy.context.scene.frame_set(i)
bpy.context.scene.update()
nm = o.to_mesh(bpy.context.scene, True, 'PREVIEW')
if i == 0 :
f.write("VANIM model"+cleanName+"_anim = {\n" +
"\t" + str(nFrame) + ",\n" +
"\t" + str(len(nm.vertices)) + ",\n" +
@ -523,28 +786,41 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
"\t" + str(chkProp['lerp']) + ",\n" +
"\t{\n"
)
for v in range(len(nm.vertices)):
if v == 0:
# ~ f.write("{\n")
f.write("\t\t//Frame %d\n" % i)
f.write("\t\t{ " + str(round(nm.vertices[v].co.x*scale)) + "," + str(round(-nm.vertices[v].co.z*scale)) + "," + str(round(nm.vertices[v].co.y*scale)) + " }")
if c != len(nm.vertices) * (nFrame) * 3 - 3:
f.write(",\n")
if v == len(nm.vertices) - 1:
f.write("\n")
c += 3;
# ~ if i != (frame_end - frame_start):
# ~ f.write(",")
tmp_meshes.append(nm)
# ~ tmp_meshes.remove(nm)
f.write("\n\t}\n};\n")
# Remove meshe's working copies
for nm in tmp_meshes:
bpy.data.meshes.remove(nm)
#Stuff # ~ bpy.data.objects[bpy.data.meshes[0].name].active_shape_key.value : access shape_key
# bpy.data.objects[bpy.data.meshes[0].name].active_shape_key.value : access shape_key
## Mesh world transform setup
# Write object matrix, rot and pos vectors
#write object matrix, rot and pos vectors
f.write("MATRIX model"+cleanName+"_matrix = {0};\n" +
"VECTOR model"+cleanName+"_pos = {"+ str(round(bpy.data.objects[m.name].location.x * scale)) + "," + str(round(-bpy.data.objects[m.name].location.z * scale)) + "," + str(round(bpy.data.objects[m.name].location.y * scale)) + ", 0};\n" +
"SVECTOR model"+cleanName+"_rot = {"+ str(round(degrees(bpy.data.objects[m.name].rotation_euler.x)/360 * 4096)) + "," + str(round(degrees(-bpy.data.objects[m.name].rotation_euler.z)/360 * 4096)) + "," + str(round(degrees(bpy.data.objects[m.name].rotation_euler.y)/360 * 4096)) + "};\n" +
@ -570,69 +846,104 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
"\t};\n\n")
# Write TMESH struct
f.write("TMESH "+"model"+cleanName+" = {\n")
f.write("\t"+"model"+cleanName+"_mesh, \n")
f.write("\t"+"model"+cleanName+"_normal,\n")
if len(m.uv_textures) != None:
for t in range(len(m.uv_textures)):
if m.uv_textures[0].data[0].image != None:
f.write("\t"+"model"+cleanName+"_uv,\n")
else:
f.write("\t0,\n")
else:
f.write("\t0,\n")
f.write("\t"+"model"+cleanName+"_color, \n")
# According to libgte.h, TMESH.len should be # of vertices. Meh...
f.write("\t"+str(len(m.polygons))+"\n")
f.write("};\n\n")
# write texture binary name and declare TIM_IMAGE
# by default, load the file from the TIM folder
# ~ if len(m.uv_textures) != 0:
# Write texture binary name and declare TIM_IMAGE
# By default, loads the file from the ./TIM folder
if len(m.uv_textures) != None:
for t in range(len(m.uv_textures)):
if m.uv_textures[0].data[0].image != None:
tex_name = texture_image.name
prefix = str.partition(tex_name, ".")[0].replace('-','_')
prefix = CleanName(prefix)
# add Tex name to array if !exist
# Add Tex name to list if it's not in there already
if prefix in timList:
break
else:
f.write("extern unsigned long "+"_binary_TIM_" + prefix + "_tim_start[];\n")
f.write("extern unsigned long "+"_binary_TIM_" + prefix + "_tim_end[];\n")
f.write("extern unsigned long "+"_binary_TIM_" + prefix + "_tim_length;\n\n")
f.write("TIM_IMAGE tim_" + prefix + ";\n\n")
timList.append(prefix)
f.write("MESH mesh"+cleanName+" = {\n")
f.write("\t&model"+ cleanName +",\n")
f.write("\tmodel" + cleanName + "_index,\n")
if len(m.uv_textures) != None:
for t in range(len(m.uv_textures)):
if m.uv_textures[0].data[0].image != None:
tex_name = texture_image.name
prefix = str.partition(tex_name, ".")[0].replace('-','_')
prefix = CleanName(prefix)
f.write("\t&tim_"+ prefix + ",\n")
f.write("\t_binary_TIM_" + prefix + "_tim_start,\n")
else:
f.write("\t0,\n" +
"\t0,\n")
else:
f.write("\t0,\n" +
"\t0,\n")
f.write("\t&model"+cleanName+"_matrix,\n" +
"\t&model"+cleanName+"_pos,\n" +
"\t&model"+cleanName+"_rot,\n" +
@ -646,83 +957,115 @@ class ExportMyFormat(bpy.types.Operator, ExportHelper):
"\t&model"+cleanName+"_p,\n" +
"\t&model"+cleanName+"_OTz,\n" +
"\t&model"+cleanName+"_body")
if m.get("isAnim") is not None and m["isAnim"] != 0:
f.write(",\n\t&model"+cleanName+"_anim\n")
else:
f.write("\n")
f.write("};\n\n")
f.write("MESH * meshes[" + str(len(bpy.data.meshes)) + "] = {\n")
for k in range(len(bpy.data.meshes)):
cleanName = CleanName(bpy.data.meshes[k].name)
f.write("\t&mesh" + cleanName)
if k != len(bpy.data.meshes) - 1:
f.write(",\n")
f.write("\n}; \n")
# nothing in camAngles, use default camera
# If camAngles is empty, use default camera, and do not include pre-calculated backgrounds
if not camAngles:
f.write("CAMANGLE camAngle_" + CleanName(defaultCam) + " = {\n" +
"\t&camPos_" + CleanName(defaultCam) + ",\n" +
"\t0,\n" +
"\t0\n" +
"};\n\n")
# cam angles is populated
# If camAngles is populated, use backgrounds and camera angles
for o in camAngles:
prefix = CleanName(o.name)
# include Tim data
# Include Tim data
f.write("extern unsigned long "+"_binary_TIM_bg_" + prefix + "_tim_start[];\n")
f.write("extern unsigned long "+"_binary_TIM_bg_" + prefix + "_tim_end[];\n")
f.write("extern unsigned long "+"_binary_TIM_bg_" + prefix + "_tim_length;\n\n")
# write corresponding TIM_IMAGE struct
# Write corresponding TIM_IMAGE struct
f.write("TIM_IMAGE tim_bg_" + prefix + ";\n\n")
# write corresponding CamAngle struct
# Write corresponding CamAngle struct
f.write("CAMANGLE camAngle_" + prefix + " = {\n" +
"\t&camPos_" + prefix + ",\n" +
"\t&tim_bg_" + prefix + ",\n" +
"\t_binary_TIM_bg_" + prefix + "_tim_start\n" +
"};\n\n")
# write cam angles array for loops
# Write camera angles in an array for loops
f.write("CAMANGLE * camAngles[" + str(len(camAngles)) + "] = {\n")
for o in camAngles:
prefix = CleanName(o.name)
f.write("\t&camAngle_" + prefix + ",\n")
f.write("};\n\n")
f.write("MESH * actorPtr = &mesh" + actorPtr + ";\n")
f.write("MESH * levelPtr = &mesh" + levelPtr + ";\n")
f.write("MESH * propPtr = &mesh" + propPtr + ";\n\n")
f.write("CAMANGLE * camPtr = &camAngle_" + CleanName(defaultCam) + ";\n\n")
f.write("NODE * curNode = &node_" + nodePtr + ";\n\n")
f.write("NODE * curNode = &node" + nodePtr + ";\n\n")
# set default cam back
# Set default camera back in Blender
if defaultCam != 'NULL':
bpy.context.scene.camera = bpy.data.objects[defaultCam]
f.close()
return {'FINISHED'};
def menu_func(self, context):
self.layout.operator(ExportMyFormat.bl_idname, text="PSX Format(.c)");
def register():
bpy.utils.register_module(__name__);
bpy.types.INFO_MT_file_export.append(menu_func);
def unregister():
bpy.utils.unregister_module(__name__);
bpy.types.INFO_MT_file_export.remove(menu_func);
if __name__ == "__main__":
register()