2021-03-01 20:05:38 +01:00
|
|
|
# bpy. app. debug = True
|
2020-12-27 17:13:58 +01:00
|
|
|
|
|
|
|
bl_info = {
|
|
|
|
"name": "PSX TMesh exporter",
|
|
|
|
"author": "Schnappy, TheDukeOfZill",
|
|
|
|
"blender": (2,7,9),
|
2021-04-03 14:14:01 +02:00
|
|
|
"version": (0,0,4),
|
2020-12-27 17:13:58 +01:00
|
|
|
"location": "File > Import-Export",
|
|
|
|
"description": "Export psx data format",
|
|
|
|
"category": "Import-Export"
|
|
|
|
}
|
2021-03-01 20:05:38 +01:00
|
|
|
|
|
|
|
import os
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2020-12-27 17:13:58 +01:00
|
|
|
import bpy
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-12 11:21:18 +01:00
|
|
|
import bmesh
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
import unicodedata
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
import subprocess
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
from math import radians, degrees, floor, cos, sin, sqrt, ceil
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-12 11:21:18 +01:00
|
|
|
from mathutils import Vector
|
2021-02-19 18:00:42 +01:00
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
from collections import defaultdict
|
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
from bpy.props import (CollectionProperty,
|
|
|
|
StringProperty,
|
|
|
|
BoolProperty,
|
|
|
|
EnumProperty,
|
2021-04-15 18:10:34 +02:00
|
|
|
FloatProperty,
|
|
|
|
IntProperty
|
2021-02-19 18:00:42 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
from bpy_extras.io_utils import (ExportHelper,
|
2021-03-24 11:33:09 +01:00
|
|
|
axis_conversion)
|
|
|
|
|
|
|
|
from bpy_extras.object_utils import world_to_camera_view
|
2021-04-08 17:24:17 +02:00
|
|
|
|
|
|
|
from re import sub
|
|
|
|
|
2020-12-27 17:13:58 +01:00
|
|
|
class ExportMyFormat(bpy.types.Operator, ExportHelper):
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2020-12-27 17:13:58 +01:00
|
|
|
bl_idname = "export_psx.c";
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
bl_label = "PSX compatible scene exporter";
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2020-12-27 17:13:58 +01:00
|
|
|
bl_options = {'PRESET'};
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2020-12-27 17:13:58 +01:00
|
|
|
filename_ext = ".c";
|
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
exp_Triangulate = BoolProperty(
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
name="Triangulate meshes ( Destructive ! )",
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
description="Triangulate meshes (destructive ! Do not use your original file)",
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
default=False,
|
|
|
|
)
|
|
|
|
|
|
|
|
exp_Scale = FloatProperty(
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
name="Scale",
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
description="Scale of exported mesh.",
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
min=1, max=1000,
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
default=65,
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
)
|
2021-04-15 18:10:34 +02:00
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
|
|
|
|
exp_Precalc = BoolProperty(
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
name="Use precalculated BGs",
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
description="Render backgrounds and converts them to TIMs",
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
default=False,
|
|
|
|
)
|
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
# ~ exp_ShowPortals = BoolProperty(
|
|
|
|
|
|
|
|
# ~ name="Render Portals in precalculated BGs",
|
|
|
|
|
|
|
|
# ~ description="Useful for debugging",
|
|
|
|
|
|
|
|
# ~ default=False,
|
|
|
|
# ~ )
|
|
|
|
|
2021-04-03 14:14:01 +02:00
|
|
|
exp_useIMforTIM = BoolProperty(
|
2021-04-02 22:33:28 +02:00
|
|
|
|
|
|
|
name = "Use ImageMagick",
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
description = "Use installed Image Magick's convert tool to convert PNGs to 8/4bpp",
|
2021-04-02 22:33:28 +02:00
|
|
|
|
|
|
|
default = False
|
|
|
|
)
|
|
|
|
|
2021-04-03 14:14:01 +02:00
|
|
|
exp_TIMbpp = BoolProperty(
|
|
|
|
|
|
|
|
name = "Use 4bpp TIMs",
|
|
|
|
|
|
|
|
description = "Converts rendered backgrounds to 4bpp TIMs instead of the default 8bpp",
|
|
|
|
|
|
|
|
default = False
|
|
|
|
)
|
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
exp_LvlNbr = IntProperty(
|
|
|
|
|
|
|
|
name="Level number",
|
|
|
|
|
|
|
|
description="That nimber is used in the symbols name.",
|
|
|
|
|
|
|
|
min=1, max=10,
|
|
|
|
|
|
|
|
default=0,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
2021-04-02 22:33:28 +02:00
|
|
|
|
2020-12-27 17:13:58 +01:00
|
|
|
def execute(self, context):
|
2021-04-04 23:32:34 +02:00
|
|
|
|
|
|
|
### Globals declaration
|
|
|
|
|
|
|
|
global nextTpage, freeTpage
|
|
|
|
|
|
|
|
global nextClutSlot, freeClutSlot
|
|
|
|
|
|
|
|
global tpageY
|
|
|
|
|
|
|
|
global TIMbpp
|
|
|
|
|
|
|
|
### Functions
|
2021-03-12 11:21:18 +01:00
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
def triangulate_object(obj):
|
|
|
|
|
|
|
|
# Triangulate an object's mesh
|
|
|
|
# Source : https://blender.stackexchange.com/questions/45698/triangulate-mesh-in-python/45722#45722
|
|
|
|
|
2020-12-30 22:09:12 +01:00
|
|
|
me = obj.data
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2020-12-30 22:09:12 +01:00
|
|
|
# Get a BMesh representation
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2020-12-30 22:09:12 +01:00
|
|
|
bm = bmesh.new()
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2020-12-30 22:09:12 +01:00
|
|
|
bm.from_mesh(me)
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2020-12-30 22:09:12 +01:00
|
|
|
bmesh.ops.triangulate(bm, faces=bm.faces[:], quad_method=0, ngon_method=0)
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2020-12-30 22:09:12 +01:00
|
|
|
# Finish up, write the bmesh back to the mesh
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2020-12-30 22:09:12 +01:00
|
|
|
bm.to_mesh(me)
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2020-12-30 22:09:12 +01:00
|
|
|
bm.free()
|
2020-12-29 15:01:44 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
def CleanName(strName):
|
2021-03-12 13:06:21 +01:00
|
|
|
|
|
|
|
# Removes specials characters, dots ans space from string
|
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
name = strName.replace(' ','_')
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
name = name.replace('.','_')
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
name = unicodedata.normalize('NFKD',name).encode('ASCII', 'ignore').decode()
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
return name
|
2021-03-12 12:13:08 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
def isInFrame(scene, cam, target):
|
|
|
|
|
2021-04-03 14:14:01 +02:00
|
|
|
# Checks if an object is in view frame
|
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
position = world_to_camera_view(scene, cam, target.location)
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
|
|
|
(position.x < 0 or position.x > 1 ) or
|
|
|
|
|
|
|
|
(position.y < 0 or position.y > 1 ) or
|
|
|
|
|
|
|
|
(position.z < 0 )
|
|
|
|
|
|
|
|
) :
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
def isInPlane(plane, obj):
|
2021-03-18 16:34:43 +01:00
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# Checks if 'obj' has its coordinates contained between the plane's coordinate.
|
2021-04-08 17:24:17 +02:00
|
|
|
# Obj is a dict
|
2021-03-18 16:34:43 +01:00
|
|
|
# If 'obj' is contained, returns 1.
|
|
|
|
# If 'obj' is partly contained, returns which side (S == 2, W == 4, N == 8, E == 6) it's overlapping.
|
2021-03-12 13:06:21 +01:00
|
|
|
# If 'obj' is not contained in 'plane', returns 0.
|
|
|
|
|
|
|
|
if (
|
2021-03-18 16:34:43 +01:00
|
|
|
(plane.get('x1') <= obj.get('x1') and plane.get('x2') >= obj.get('x2') ) and
|
|
|
|
(plane.get('y1') <= obj.get('y1') and plane.get('y2') >= obj.get('y2') )
|
2021-03-12 13:06:21 +01:00
|
|
|
):
|
|
|
|
|
|
|
|
return 1
|
|
|
|
|
|
|
|
# Overlap on the West side of the plane
|
|
|
|
if (
|
2021-03-18 16:34:43 +01:00
|
|
|
( plane.get('x1') >= obj.get('x1') and plane.get('x1') <= obj.get('x2') ) and
|
|
|
|
( plane.get('y1') <= obj.get('y2') and plane.get('y2') >= obj.get('y1') )
|
2021-03-12 13:06:21 +01:00
|
|
|
):
|
|
|
|
|
|
|
|
return 4
|
|
|
|
|
|
|
|
# Overlap on the East side of the plane
|
|
|
|
if (
|
2021-03-18 16:34:43 +01:00
|
|
|
( plane.get('x2') <= obj.get('x2') and plane.get('x2') >= obj.get('x1') ) and
|
|
|
|
( plane.get('y1') <= obj.get('y2') and plane.get('y2') >= obj.get('y1') )
|
2021-03-12 13:06:21 +01:00
|
|
|
):
|
|
|
|
|
|
|
|
return 6
|
|
|
|
|
|
|
|
# Overlap on the North side of the plane
|
|
|
|
if (
|
2021-03-18 16:34:43 +01:00
|
|
|
( plane.get('y2') <= obj.get('y2') and plane.get('y2') >= obj.get('y1') ) and
|
|
|
|
( plane.get('x1') <= obj.get('x1') and plane.get('x2') >= obj.get('x2') )
|
2021-03-12 13:06:21 +01:00
|
|
|
):
|
|
|
|
|
|
|
|
return 8
|
|
|
|
|
|
|
|
# Overlap on the South side of the plane
|
|
|
|
if (
|
2021-03-18 16:34:43 +01:00
|
|
|
( plane.get('y1') >= obj.get('y1') and plane.get('y1') <= obj.get('y2') ) and
|
|
|
|
( plane.get('x1') <= obj.get('x1') and plane.get('x2') >= obj.get('x2') )
|
2021-03-12 13:06:21 +01:00
|
|
|
):
|
|
|
|
|
|
|
|
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 == 'N':
|
|
|
|
|
|
|
|
return [ LvlPlanes[plane]['x1'], LvlPlanes[plane]['y2'], LvlPlanes[plane]['x2'], LvlPlanes[plane]['y2'] ]
|
2021-03-18 16:34:43 +01:00
|
|
|
|
|
|
|
if side == 'S':
|
|
|
|
|
|
|
|
return [ LvlPlanes[plane]['x1'], LvlPlanes[plane]['y1'], LvlPlanes[plane]['x2'], LvlPlanes[plane]['y1'] ]
|
2021-03-12 13:06:21 +01:00
|
|
|
|
|
|
|
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 )
|
|
|
|
|
2021-04-03 14:14:01 +02:00
|
|
|
# Rounding to avoid false positives
|
2021-03-12 13:06:21 +01:00
|
|
|
|
|
|
|
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) ):
|
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
return "connected"
|
2021-03-12 13:06:21 +01:00
|
|
|
|
|
|
|
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"
|
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
def objVertLtoW(target):
|
|
|
|
|
2021-04-03 14:14:01 +02:00
|
|
|
# Converts an object's vertices coordinates from local to global
|
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
worldPos = []
|
|
|
|
|
|
|
|
mw = target.matrix_world
|
|
|
|
|
|
|
|
mesh = bpy.data.meshes[ target.name ]
|
|
|
|
|
|
|
|
for vertex in mesh.vertices:
|
|
|
|
|
|
|
|
worldPos.append( mw * vertex.co * scale )
|
|
|
|
|
|
|
|
return worldPos
|
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
def objVertWtoS(scene, cam, target, toScale = 1):
|
2021-04-03 14:14:01 +02:00
|
|
|
|
|
|
|
# Converts an object's vertices coordinates from local to screen coordinates
|
2021-03-31 20:28:02 +02:00
|
|
|
|
|
|
|
screenPos = []
|
|
|
|
|
|
|
|
# Get objects world matrix
|
|
|
|
|
|
|
|
mw = target.matrix_world
|
|
|
|
|
|
|
|
# Get object's mesh
|
|
|
|
|
|
|
|
mesh = bpy.data.meshes[ target.name ]
|
|
|
|
|
|
|
|
# For each vertex in mesh, get screen coordinates
|
|
|
|
|
|
|
|
for vertex in mesh.vertices:
|
|
|
|
|
|
|
|
# Get meshes world coordinates
|
|
|
|
|
|
|
|
screenPos.append( world_to_camera_view( scene, cam, ( mw * vertex.co ) ) )
|
|
|
|
|
|
|
|
if toScale:
|
|
|
|
|
|
|
|
# Get current scene rsolution
|
|
|
|
|
|
|
|
resX = scene.render.resolution_x
|
|
|
|
|
|
|
|
resY = scene.render.resolution_y
|
|
|
|
|
|
|
|
# Scale values
|
|
|
|
|
|
|
|
for vector in screenPos:
|
|
|
|
|
|
|
|
# ~ vector.x = int( resX * vector.x ) < 0 ? 0 : int( resX * vector.x ) > 320 ? 320 : int( resX * vector.x )
|
|
|
|
|
|
|
|
vector.x = max ( 0, min ( resX, int( resX * vector.x ) ) )
|
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
vector.y = resY - max ( 0, min ( resY, int( resY * vector.y ) ) )
|
2021-03-31 20:28:02 +02:00
|
|
|
|
|
|
|
vector.z = int( vector.z )
|
|
|
|
|
|
|
|
return screenPos
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
def convertBGtoTIM( filePathWithExt, colors = 256, bpp = 8, timX = 640, timY = 0, clutX = 0, clutY = 480, transparency = 'alpha'):
|
2021-04-03 14:14:01 +02:00
|
|
|
|
|
|
|
# By default, converts a RGB to 8bpp, 256 colors indexed PNG, then to a 8bpp TIM image
|
|
|
|
|
|
|
|
filePathWithoutExt = filePathWithExt[ : filePathWithExt.rfind('.') ]
|
|
|
|
|
|
|
|
# For windows users, add '.exe' to the command
|
|
|
|
|
|
|
|
exe = ""
|
|
|
|
|
|
|
|
if os.name == 'nt':
|
|
|
|
|
|
|
|
exe = ".exe"
|
|
|
|
|
|
|
|
# 8bpp TIM needs < 256 colors
|
|
|
|
|
|
|
|
if bpp == 8:
|
|
|
|
|
|
|
|
# Clamp number of colors to 256
|
|
|
|
|
|
|
|
colors = min( 256, colors )
|
|
|
|
|
|
|
|
elif bpp == 4:
|
|
|
|
|
|
|
|
# 4bpp TIM needs < 16 colors
|
|
|
|
|
|
|
|
# Clamp number of colors to 16
|
|
|
|
|
|
|
|
colors = min( 16, colors )
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
if transparency == "alpha":
|
|
|
|
|
|
|
|
transpMethod = "-usealpha"
|
|
|
|
|
|
|
|
elif transparency == "black":
|
|
|
|
|
|
|
|
transpMethod = "-b"
|
|
|
|
|
|
|
|
elif transparency == "nonblack":
|
|
|
|
|
|
|
|
transpMethod = "-t"
|
|
|
|
|
2021-04-03 14:14:01 +02:00
|
|
|
# Quantization of colors with pngquant ( https://pngquant.org/ )
|
|
|
|
|
|
|
|
subprocess.call( [ "pngquant" + exe, str( colors ), filePathWithExt, "-o", filePathWithExt, "--force" ] )
|
|
|
|
|
|
|
|
# Image magick's convert can be used alternatively ( https://imagemagick.org/ )
|
|
|
|
|
|
|
|
if self.exp_useIMforTIM :
|
|
|
|
|
|
|
|
# ImageMagick alternative
|
|
|
|
|
|
|
|
subprocess.call( [ "convert" + exe, filePathWithExt, "-colors", str( colors ), filePathWithExt ] )
|
|
|
|
|
|
|
|
# Convert to tim with img2tim ( https://github.com/Lameguy64/img2tim )
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
subprocess.call( [ "img2tim" + exe, transpMethod, "-bpp", str( bpp ), "-org", str( timX ), str( timY ), "-plt" , str( clutX ), str( clutY ),"-o", filePathWithoutExt + ".tim", filePathWithExt ] )
|
|
|
|
|
|
|
|
def VramIsFull( size ):
|
|
|
|
|
|
|
|
# Returns True if not enough space in Vram for image
|
|
|
|
|
|
|
|
# Transpose bpp to bitshift value
|
|
|
|
|
|
|
|
global nextTpage, freeTpage
|
|
|
|
|
|
|
|
global nextClutSlot, freeClutSlot
|
|
|
|
|
|
|
|
global tpageY
|
|
|
|
|
|
|
|
if TIMbpp == 8:
|
|
|
|
|
|
|
|
shift = 1
|
|
|
|
|
|
|
|
elif TIMbpp == 4:
|
|
|
|
|
|
|
|
shift = 2
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
shift = 0
|
|
|
|
|
|
|
|
# Get image width in vram
|
|
|
|
|
|
|
|
if not size:
|
|
|
|
|
|
|
|
imageWidth = size[0] >> shift
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
imageWidth = size >> shift
|
|
|
|
|
|
|
|
# Divide by cell width ( 64 pixels )
|
|
|
|
|
|
|
|
imageWidthInTPage = ceil( imageWidth / 64 )
|
|
|
|
|
|
|
|
if ( tpageY == 0 and
|
|
|
|
|
|
|
|
nextTpage + ( imageWidthInTPage * 64 ) < 1024 and
|
|
|
|
|
|
|
|
freeTpage - imageWidthInTPage > 0
|
|
|
|
|
|
|
|
) :
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
elif ( tpageY == 256 and
|
|
|
|
|
|
|
|
nextTpage + ( imageWidthInTPage * 64 ) < 960 and
|
|
|
|
|
|
|
|
freeTpage - imageWidthInTPage > 1
|
|
|
|
|
|
|
|
) :
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
def setNextTimPos( image ):
|
|
|
|
|
|
|
|
# Sets nextTpage, freeTpage, tpageY, nextClutSlot, freeClutSlot to next free space in Vram
|
|
|
|
|
|
|
|
|
|
|
|
# Transpose bpp to bitshift value
|
|
|
|
|
|
|
|
global nextTpage, freeTpage
|
|
|
|
|
|
|
|
global nextClutSlot, freeClutSlot
|
|
|
|
|
|
|
|
global tpageY
|
|
|
|
|
|
|
|
if TIMbpp == 8:
|
|
|
|
|
|
|
|
shift = 1
|
|
|
|
|
|
|
|
elif TIMbpp == 4:
|
|
|
|
|
|
|
|
shift = 2
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
shift = 0
|
|
|
|
|
|
|
|
# Get image width in vram
|
|
|
|
|
|
|
|
imageWidth = image.size[0] >> shift
|
|
|
|
|
|
|
|
# Divide by cell width ( 64 pixels )
|
|
|
|
|
|
|
|
imageWidthInTPage = ceil( imageWidth / 64 )
|
|
|
|
|
|
|
|
if ( tpageY == 0 and
|
|
|
|
|
|
|
|
nextTpage + ( imageWidthInTPage * 64 ) < 1024 and
|
|
|
|
|
|
|
|
freeTpage - imageWidthInTPage > 0
|
|
|
|
|
|
|
|
) :
|
|
|
|
|
|
|
|
nextTpage += imageWidthInTPage * 64
|
|
|
|
|
|
|
|
freeTpage -= imageWidthInTPage
|
|
|
|
|
|
|
|
nextClutSlot += 1
|
|
|
|
|
|
|
|
freeClutSlot -= 1
|
|
|
|
|
|
|
|
|
|
|
|
elif ( tpageY == 256 and
|
|
|
|
|
|
|
|
nextTpage + ( imageWidthInTPage * 64 ) < 960 and
|
|
|
|
|
|
|
|
freeTpage - imageWidthInTPage > 1
|
|
|
|
|
|
|
|
) :
|
|
|
|
|
|
|
|
nextTpage += imageWidthInTPage * 64
|
|
|
|
|
|
|
|
freeTpage -= imageWidthInTPage
|
|
|
|
|
|
|
|
nextClutSlot += 1
|
|
|
|
|
|
|
|
freeClutSlot -= 1
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
tpageY = 256
|
|
|
|
|
|
|
|
nextTpage = 320
|
|
|
|
|
|
|
|
nextClutSlot += 1
|
|
|
|
|
|
|
|
freeClutSlot -= 1
|
|
|
|
|
|
|
|
### VRam Layout
|
|
|
|
|
|
|
|
nextTpage = 320
|
|
|
|
|
|
|
|
nextClutSlot = 480
|
|
|
|
|
|
|
|
freeTpage = 21
|
|
|
|
|
|
|
|
freeClutSlot = 32
|
|
|
|
|
|
|
|
tpageY = 0
|
|
|
|
|
|
|
|
# Set TIMs default bpp value
|
2021-04-03 14:14:01 +02:00
|
|
|
|
|
|
|
TIMbpp = 8
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
TIMshift = 1
|
|
|
|
|
2021-04-03 14:14:01 +02:00
|
|
|
if self.exp_TIMbpp:
|
|
|
|
|
|
|
|
TIMbpp = 4
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
TIMshift = 2
|
|
|
|
|
2020-12-29 15:01:44 +01:00
|
|
|
# Leave edit mode to avoid errors
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2020-12-29 15:53:47 +01:00
|
|
|
bpy.ops.object.mode_set(mode='OBJECT')
|
2020-12-30 22:09:12 +01:00
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# If set, triangulate objects of type mesh
|
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
if self.exp_Triangulate:
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
for o in range(len(bpy.data.objects)):
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
if bpy.data.objects[o].type == 'MESH':
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
triangulate_object(bpy.data.objects[o])
|
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# Set Scale
|
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
scale = self.exp_Scale
|
2020-12-30 22:09:12 +01:00
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# Get working directory path
|
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
filepath = bpy.data.filepath
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
folder = os.path.dirname(bpy.path.abspath(filepath))
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
dirpath = os.path.join(folder, "TIM")
|
|
|
|
|
2021-03-24 11:33:09 +01:00
|
|
|
### Export pre-calculated backgrounds and construct a list of visible objects for each camera angle
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
camAngles = []
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-12 11:21:18 +01:00
|
|
|
defaultCam = 'NULL'
|
|
|
|
|
2021-03-24 11:33:09 +01:00
|
|
|
# List of Rigid/Static bodies to ray a cast upon
|
|
|
|
|
|
|
|
rayTargets = []
|
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# If using precalculated BG, render and export them to ./TIM/
|
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
if self.exp_Precalc:
|
2021-04-02 12:41:32 +02:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
# Set rendering resolution
|
|
|
|
|
|
|
|
bpy.context.scene.render.resolution_x = 320
|
|
|
|
|
|
|
|
bpy.context.scene.render.resolution_y = 240
|
|
|
|
|
|
|
|
# Get BGs TIM size depending on mode
|
|
|
|
|
|
|
|
timSize = bpy.context.scene.render.resolution_x >> TIMshift
|
|
|
|
|
|
|
|
timSizeInCell = ceil( timSize / 64 )
|
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# Create folder if it doesn't exist
|
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
os.makedirs(dirpath, exist_ok = 1)
|
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# Set file format config
|
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
bpy.context.scene.render.image_settings.file_format = 'PNG'
|
2021-04-02 22:33:28 +02:00
|
|
|
|
|
|
|
# ~ bpy.context.scene.render.image_settings.quality = 100
|
|
|
|
|
|
|
|
# ~ bpy.context.scene.render.image_settings.compression = 0
|
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
bpy.context.scene.render.image_settings.color_depth = '8'
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
bpy.context.scene.render.image_settings.color_mode = 'RGB'
|
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# Get active cam
|
|
|
|
|
2021-03-24 11:33:09 +01:00
|
|
|
scene = bpy.context.scene
|
|
|
|
|
|
|
|
cam = scene.camera
|
2021-03-01 20:05:38 +01:00
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# Find default cam, and cameras in camPath
|
2021-03-01 20:05:38 +01:00
|
|
|
|
|
|
|
for o in bpy.data.objects:
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-12 11:21:18 +01:00
|
|
|
if o.type == 'CAMERA' and o.data.get('isDefault'):
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-12 11:21:18 +01:00
|
|
|
defaultCam = o.name
|
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
if o.type == 'CAMERA' and o.name.startswith("camPath"):
|
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
filepath = folder + os.sep + "TIM" + os.sep
|
|
|
|
|
|
|
|
filename = "bg_" + CleanName(o.name)
|
|
|
|
|
|
|
|
fileext = "." + str(bpy.context.scene.render.image_settings.file_format).lower()
|
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# Set camera as active
|
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
bpy.context.scene.camera = o
|
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# Render and save image
|
2021-03-01 20:05:38 +01:00
|
|
|
|
|
|
|
bpy.ops.render.render()
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
bpy.data.images["Render Result"].save_render( filepath + filename + fileext )
|
|
|
|
|
2021-04-03 14:14:01 +02:00
|
|
|
# Convert PNG to TIM
|
2021-04-02 12:41:32 +02:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
if not VramIsFull( bpy.context.scene.render.resolution_x ):
|
2021-03-01 20:05:38 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
convertBGtoTIM( filepath + filename + fileext , bpp = TIMbpp, timX = nextTpage, timY = tpageY, clutY = nextClutSlot )
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
tpageY = 256
|
|
|
|
|
|
|
|
nextTpage = 320
|
|
|
|
|
|
|
|
if not VramIsFull( bpy.context.scene.render.resolution_x ):
|
|
|
|
|
|
|
|
convertBGtoTIM( filepath + filename + fileext , bpp = TIMbpp, timX = nextTpage, timY = tpageY, clutY = nextClutSlot )
|
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# Add camera object to camAngles
|
2021-03-01 20:05:38 +01:00
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
camAngles.append(o)
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
# Notify layout change to vars
|
|
|
|
|
|
|
|
nextTpage += timSizeInCell * 64
|
|
|
|
|
|
|
|
freeTpage -= timSizeInCell
|
2021-03-24 11:33:09 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
nextClutSlot += 1
|
|
|
|
|
|
|
|
freeClutSlot -= 1
|
|
|
|
|
2021-04-10 18:34:11 +02:00
|
|
|
### Start writing output files
|
|
|
|
|
|
|
|
# Stolen from Lameguy64 : https://github.com/Lameguy64/Blender-RSD-Plugin/blob/b3b6fd4475aed4ca38587ca83d34000f60b68a47/io_export_rsd.py#L68
|
|
|
|
|
|
|
|
filepath = self.filepath
|
|
|
|
|
|
|
|
filepath = filepath.replace(self.filename_ext, "") # Quick fix to get around the aforementioned 'bugfix'
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
# TODO : add option to export scenes as levels
|
|
|
|
|
|
|
|
# ~ if self.exp_UseScenesAsLevels:
|
|
|
|
|
|
|
|
# ~ fileName = cleanName(bpy.data.scenes[0].name)
|
|
|
|
|
|
|
|
# ~ else:
|
|
|
|
|
|
|
|
# For now, use .blender file name
|
|
|
|
|
|
|
|
# ~ fileName = bpy.path.basename(filepath)
|
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
lvlNbr = self.exp_LvlNbr
|
|
|
|
|
|
|
|
fileName = 'level' + str( lvlNbr )
|
2021-04-13 16:49:26 +02:00
|
|
|
|
2021-04-12 14:50:44 +02:00
|
|
|
# We're writing a few files:
|
|
|
|
# - custom_types.h contains the 'engine' 's specific struct definitions
|
|
|
|
# - level.h contains the forward declaration of the level's variables
|
|
|
|
# - level.c contains the initialization and data of those variables
|
2021-04-10 18:34:11 +02:00
|
|
|
|
2021-04-12 14:50:44 +02:00
|
|
|
# 'custom_types.h' goes in project's root
|
2021-04-10 18:34:11 +02:00
|
|
|
|
2021-04-12 14:50:44 +02:00
|
|
|
custom_types_h = folder + os.sep + 'custom_types.h'
|
2021-04-10 18:34:11 +02:00
|
|
|
|
2021-04-12 14:50:44 +02:00
|
|
|
# Levels files go in ./levels/
|
|
|
|
|
|
|
|
# If ./levels does not exist, create it
|
|
|
|
|
|
|
|
if not os.path.exists(folder + os.sep + 'levels'):
|
|
|
|
|
|
|
|
os.mkdir(folder + os.sep + 'levels')
|
|
|
|
|
|
|
|
levels_folder = folder + os.sep + 'levels' + os.sep
|
|
|
|
|
|
|
|
# TODO : dynamic filenaming
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_h = levels_folder + fileName + '.h'
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_c = levels_folder + fileName + '.c'
|
2021-04-10 18:34:11 +02:00
|
|
|
|
2021-04-12 14:50:44 +02:00
|
|
|
### Custom types Header (custom_types.h)
|
2021-03-12 13:06:21 +01:00
|
|
|
|
|
|
|
# Open file
|
|
|
|
|
2021-04-12 14:50:44 +02:00
|
|
|
h = open(os.path.normpath(custom_types_h),"w+")
|
2020-12-30 11:23:36 +01:00
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
## Add C structures definitions
|
|
|
|
|
2021-04-10 18:34:11 +02:00
|
|
|
h.write(
|
|
|
|
|
2021-04-12 14:50:44 +02:00
|
|
|
"#pragma once\n" +
|
|
|
|
|
2021-04-10 18:34:11 +02:00
|
|
|
"#include <sys/types.h>\n" +
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-10 18:34:11 +02:00
|
|
|
"#include <libgte.h>\n" +
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-10 18:34:11 +02:00
|
|
|
"#include <libgpu.h>\n\n"
|
|
|
|
|
|
|
|
)
|
|
|
|
|
2021-03-16 16:18:05 +01:00
|
|
|
# Partial declaration of structures to avoid inter-dependencies issues
|
|
|
|
|
2021-04-10 18:34:11 +02:00
|
|
|
h.write("struct BODY;\n" +
|
2021-03-16 16:18:05 +01:00
|
|
|
"struct VANIM;\n" +
|
|
|
|
"struct PRIM;\n" +
|
|
|
|
"struct MESH;\n" +
|
|
|
|
"struct CAMPOS;\n" +
|
|
|
|
"struct CAMPATH;\n" +
|
|
|
|
"struct CAMANGLE;\n" +
|
|
|
|
"struct SIBLINGS;\n" +
|
|
|
|
"struct CHILDREN;\n" +
|
2021-03-31 20:28:02 +02:00
|
|
|
"struct NODE;\n" +
|
|
|
|
"struct QUAD;\n" +
|
|
|
|
"\n")
|
2021-03-16 16:18:05 +01:00
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# BODY
|
|
|
|
|
2021-04-10 18:34:11 +02:00
|
|
|
h.write("typedef struct BODY {\n" +
|
2021-02-19 18:00:42 +01:00
|
|
|
"\tVECTOR gForce;\n" +
|
2021-01-14 17:22:44 +01:00
|
|
|
"\tVECTOR position;\n" +
|
|
|
|
"\tSVECTOR velocity;\n" +
|
2021-03-01 20:05:38 +01:00
|
|
|
"\tint mass;\n" +
|
2021-02-19 18:00:42 +01:00
|
|
|
"\tint invMass;\n" +
|
2021-01-14 17:22:44 +01:00
|
|
|
"\tVECTOR min; \n" +
|
|
|
|
"\tVECTOR max; \n" +
|
2021-02-19 18:00:42 +01:00
|
|
|
"\tint restitution; \n" +
|
2021-03-22 20:26:41 +01:00
|
|
|
# ~ "\tstruct NODE * curNode; \n" +
|
2021-01-14 17:22:44 +01:00
|
|
|
"\t} BODY;\n\n")
|
2021-03-12 12:13:08 +01:00
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# VANIM
|
|
|
|
|
2021-04-10 18:34:11 +02:00
|
|
|
h.write("typedef struct VANIM { \n" +
|
2021-02-02 12:15:11 +01:00
|
|
|
"\tint nframes; // number of frames e.g 20\n" +
|
|
|
|
"\tint nvert; // number of vertices e.g 21\n" +
|
2021-03-01 20:05:38 +01:00
|
|
|
"\tint cursor; // anim cursor\n" +
|
|
|
|
"\tint lerpCursor; // anim cursor\n" +
|
|
|
|
"\tint dir; // playback direction (1 or -1)\n" +
|
|
|
|
"\tint interpolate; // use lerp to interpolate keyframes\n" +
|
2021-02-02 12:15:11 +01:00
|
|
|
"\tSVECTOR data[]; // vertex pos as SVECTORs e.g 20 * 21 SVECTORS\n" +
|
2021-02-19 18:00:42 +01:00
|
|
|
# ~ "\tSVECTOR normals[]; // vertex pos as SVECTORs e.g 20 * 21 SVECTORS\n" +
|
2021-02-02 12:15:11 +01:00
|
|
|
"\t} VANIM;\n\n")
|
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# PRIM
|
|
|
|
|
2021-04-10 18:34:11 +02:00
|
|
|
h.write("typedef struct PRIM {\n" +
|
2021-02-19 18:00:42 +01:00
|
|
|
"\tVECTOR order;\n" +
|
2021-03-31 20:28:02 +02:00
|
|
|
"\tint code; // Same as POL3/POL4 codes : Code (F3 = 1, FT3 = 2, G3 = 3,\n// GT3 = 4) Code (F4 = 5, FT4 = 6, G4 = 7, GT4 = 8)\n" +
|
2021-02-19 18:00:42 +01:00
|
|
|
"\t} PRIM;\n\n")
|
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# MESH
|
|
|
|
|
2021-04-10 18:34:11 +02:00
|
|
|
h.write("typedef struct MESH { \n"+
|
2021-01-04 18:28:27 +01:00
|
|
|
"\tTMESH * tmesh;\n" +
|
2021-02-19 18:00:42 +01:00
|
|
|
"\tPRIM * index;\n" +
|
2021-01-04 18:28:27 +01:00
|
|
|
"\tTIM_IMAGE * tim; \n" +
|
2021-03-01 20:05:38 +01:00
|
|
|
"\tunsigned long * tim_data;\n"+
|
2021-04-15 18:10:34 +02:00
|
|
|
"\tMATRIX mat;\n" +
|
|
|
|
"\tVECTOR pos;\n" +
|
|
|
|
"\tSVECTOR rot;\n" +
|
|
|
|
"\tshort isRigidBody;\n" +
|
|
|
|
"\tshort isStaticBody;\n" +
|
|
|
|
"\tshort isPrism;\n" +
|
|
|
|
"\tshort isAnim;\n" +
|
|
|
|
"\tshort isActor;\n" +
|
|
|
|
"\tshort isLevel;\n" +
|
|
|
|
"\tshort isBG;\n" +
|
|
|
|
"\tshort isSprite;\n" +
|
|
|
|
"\tlong p;\n" +
|
|
|
|
"\tlong OTz;\n" +
|
|
|
|
"\tBODY * body;\n" +
|
|
|
|
"\tVANIM * anim;\n" +
|
2021-03-22 20:26:41 +01:00
|
|
|
"\tstruct NODE * node;\n" +
|
2021-04-15 18:10:34 +02:00
|
|
|
"\tVECTOR pos2D;\n" +
|
2020-12-30 11:23:36 +01:00
|
|
|
"\t} MESH;\n\n")
|
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
#QUAD
|
|
|
|
|
2021-04-10 18:34:11 +02:00
|
|
|
h.write("typedef struct QUAD {\n" +
|
2021-03-31 20:28:02 +02:00
|
|
|
"\tVECTOR v0, v1;\n" +
|
|
|
|
"\tVECTOR v2, v3;\n" +
|
|
|
|
"\t} QUAD;\n\n")
|
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# CAMPOS
|
|
|
|
|
2021-04-10 18:34:11 +02:00
|
|
|
h.write("typedef struct CAMPOS {\n" +
|
2021-02-02 12:15:11 +01:00
|
|
|
"\tVECTOR pos;\n" +
|
|
|
|
"\tSVECTOR rot;\n" +
|
|
|
|
"\t} CAMPOS;\n\n" +
|
2021-03-31 20:28:02 +02:00
|
|
|
"\n// Blender cam ~= PSX cam with these settings : \n" +
|
|
|
|
"// NTSC - 320x240, PAL 320x256, pixel ratio 1:1,\n" +
|
|
|
|
"// cam focal length : perspective 90° ( 16 mm ))\n" +
|
|
|
|
"// With a FOV of 1/2, camera focal length is ~= 16 mm / 90°\n" +
|
|
|
|
"// Lower values mean wider angle\n\n")
|
2021-03-01 20:05:38 +01:00
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# CAMANGLE
|
|
|
|
|
2021-04-10 18:34:11 +02:00
|
|
|
h.write("typedef struct CAMANGLE {\n" +
|
2021-03-01 20:05:38 +01:00
|
|
|
"\tCAMPOS * campos;\n" +
|
|
|
|
"\tTIM_IMAGE * BGtim;\n" +
|
|
|
|
"\tunsigned long * tim_data;\n" +
|
2021-03-31 20:28:02 +02:00
|
|
|
"\tQUAD bw, fw;\n" +
|
2021-03-24 11:33:09 +01:00
|
|
|
"\tint index;\n" +
|
|
|
|
"\tMESH * objects[];\n" +
|
2021-03-01 20:05:38 +01:00
|
|
|
"\t} CAMANGLE;\n\n")
|
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# CAMPATH
|
|
|
|
|
2021-04-10 18:34:11 +02:00
|
|
|
h.write("typedef struct CAMPATH {\n" +
|
2021-03-01 20:05:38 +01:00
|
|
|
"\tshort len, cursor, pos;\n" +
|
2021-02-02 12:15:11 +01:00
|
|
|
"\tVECTOR points[];\n" +
|
|
|
|
"\t} CAMPATH;\n\n")
|
|
|
|
|
2021-03-16 16:18:05 +01:00
|
|
|
# SIBLINGS
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-04-10 18:34:11 +02:00
|
|
|
h.write("typedef struct SIBLINGS {\n" +
|
2021-03-15 12:44:15 +01:00
|
|
|
"\tint index;\n" +
|
2021-03-16 16:18:05 +01:00
|
|
|
"\tstruct NODE * list[];\n" +
|
|
|
|
"\t} SIBLINGS ;\n\n")
|
2021-03-15 12:44:15 +01:00
|
|
|
|
2021-03-16 16:18:05 +01:00
|
|
|
# CHILDREN
|
2021-03-15 12:44:15 +01:00
|
|
|
|
2021-04-10 18:34:11 +02:00
|
|
|
h.write("typedef struct CHILDREN {\n" +
|
2021-03-15 12:44:15 +01:00
|
|
|
"\tint index;\n" +
|
2021-03-16 16:18:05 +01:00
|
|
|
"\tMESH * list[];\n" +
|
|
|
|
"\t} CHILDREN ;\n\n")
|
2021-03-15 12:44:15 +01:00
|
|
|
|
|
|
|
# NODE
|
|
|
|
|
2021-04-10 18:34:11 +02:00
|
|
|
h.write("typedef struct NODE {\n" +
|
2021-03-16 16:18:05 +01:00
|
|
|
"\tMESH * plane;\n" +
|
|
|
|
"\tSIBLINGS * siblings;\n" +
|
|
|
|
"\tCHILDREN * objects;\n" +
|
2021-03-18 19:21:40 +01:00
|
|
|
"\tCHILDREN * rigidbodies;\n" +
|
2021-03-12 12:13:08 +01:00
|
|
|
"\t} NODE;\n\n")
|
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# LEVEL
|
|
|
|
|
|
|
|
h.write("typedef struct LEVEL {\n" +
|
|
|
|
"\tMATRIX * cmat;\n" +
|
|
|
|
"\tMATRIX * lgtmat;\n" +
|
|
|
|
"\tMESH ** meshes;\n" +
|
|
|
|
"\tint * meshes_length;\n" +
|
|
|
|
"\tMESH * actorPtr;\n" +
|
|
|
|
"\tMESH * levelPtr;\n" +
|
|
|
|
"\tMESH * propPtr;\n" +
|
|
|
|
"\tCAMANGLE * camPtr;\n" +
|
|
|
|
"\tCAMPATH * camPath;\n" +
|
|
|
|
"\tCAMANGLE ** camAngles;\n" +
|
|
|
|
"\tNODE * curNode;\n" +
|
|
|
|
"\tMESH * meshPlan; // This one is temporary\n" +
|
|
|
|
"\t} LEVEL;\n")
|
|
|
|
|
2021-04-10 18:34:11 +02:00
|
|
|
h.close()
|
|
|
|
|
2021-04-12 14:50:44 +02:00
|
|
|
## Level Data (level.c)
|
2021-04-10 18:34:11 +02:00
|
|
|
|
2021-04-12 14:50:44 +02:00
|
|
|
# Store every variable name in a list so that we can populate the level.h file later
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols = []
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
level_symbols.append("LEVEL " + fileName)
|
|
|
|
|
2021-04-12 14:50:44 +02:00
|
|
|
f = open(os.path.normpath(level_c),"w+")
|
2021-04-10 18:34:11 +02:00
|
|
|
|
|
|
|
f.write(
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
'#include "' + fileName + '.h"\n\n' +
|
|
|
|
|
|
|
|
"NODE_DECLARATION\n"
|
|
|
|
|
2021-04-10 18:34:11 +02:00
|
|
|
)
|
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
## Camera setup
|
|
|
|
|
|
|
|
# List of points defining the camera path
|
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
camPathPoints = []
|
2021-03-12 13:06:21 +01:00
|
|
|
|
|
|
|
# Define first mesh. Will be used as default if no properties are found in meshes
|
2021-02-19 18:00:42 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
first_mesh = CleanName( bpy.data.meshes[ 0 ].name )
|
2021-02-02 12:15:11 +01:00
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# Set camera position and rotation in the scene
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
for o in range( len( bpy.data.objects ) ):
|
2021-03-24 11:33:09 +01:00
|
|
|
|
|
|
|
# Add objects of type MESH with a Rigidbody or StaticBody flag set to a list
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
if bpy.data.objects[ o ].type == 'MESH':
|
2021-03-25 10:50:54 +01:00
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
if (
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
bpy.data.objects[ o ].data.get('isRigidBody') or
|
2021-04-02 12:41:32 +02:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
bpy.data.objects[ o ].data.get('isStaticBody')
|
2021-04-02 12:41:32 +02:00
|
|
|
|
|
|
|
#or bpy.data.objects[o].data.get('isPortal')
|
|
|
|
|
|
|
|
):
|
2021-03-24 11:33:09 +01:00
|
|
|
|
2021-03-25 10:50:54 +01:00
|
|
|
rayTargets.append(bpy.data.objects[o])
|
2021-03-24 11:33:09 +01:00
|
|
|
|
|
|
|
# Set object of type CAMERA with isDefault flag as default camera
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
if bpy.data.objects[o].type == 'CAMERA' and bpy.data.objects[o].data.get('isDefault'):
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
defaultCam = bpy.data.objects[o].name
|
2021-03-24 11:33:09 +01:00
|
|
|
|
|
|
|
# Declare each blender camera as a CAMPOS
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
if bpy.data.objects[o].type == 'CAMERA':
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("CAMPOS " + fileName + "_camPos_" + CleanName( bpy.data.objects[ o ].name ) + " = {\n" +
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
"\t{ " + str( round( -bpy.data.objects[o].location.x * scale ) ) +
|
|
|
|
|
|
|
|
"," + str( round( bpy.data.objects[o].location.z * scale ) ) +
|
|
|
|
|
|
|
|
"," + str( round( -bpy.data.objects[o].location.y * scale ) ) + " },\n" +
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
"\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" +
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
"};\n\n")
|
2021-03-01 20:05:38 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "CAMPOS " + fileName + "_camPos_" + CleanName( bpy.data.objects[ o ].name ) )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# Find camera path points and append them to camPathPoints[]
|
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
if bpy.data.objects[o].type == 'CAMERA' :
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-04-08 17:24:17 +02:00
|
|
|
if ( bpy.data.objects[ o ].name.startswith( "camPath" )
|
2021-04-04 23:32:34 +02:00
|
|
|
|
2021-04-08 17:24:17 +02:00
|
|
|
and not bpy.data.objects[ o ].data.get( 'exclude' )
|
2021-04-04 23:32:34 +02:00
|
|
|
|
|
|
|
) :
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
camPathPoints.append(bpy.data.objects[o].name)
|
2021-03-25 10:50:54 +01:00
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# Write the CAMPATH structure
|
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
if camPathPoints:
|
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# Populate with points found above
|
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
# ~ camPathPoints = list(reversed(camPathPoints))
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
for point in range(len(camPathPoints)):
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
if point == 0:
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("CAMPATH " + fileName + "_camPath = {\n" +
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
"\t" + str( len( camPathPoints ) ) + ",\n" +
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
"\t0,\n" +
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
"\t0,\n" +
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
"\t{\n")
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "CAMPATH " + fileName + "_camPath" )
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
f.write( "\t\t{ " + str( round( -bpy.data.objects[ camPathPoints[ point ] ].location.x * scale ) ) +
|
|
|
|
|
|
|
|
"," + str( round( bpy.data.objects[ camPathPoints[ point ] ].location.z * scale ) ) +
|
|
|
|
|
|
|
|
"," + str( round( -bpy.data.objects[ camPathPoints[ point ] ].location.y * scale ) ) +
|
|
|
|
|
|
|
|
" }" )
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
if point != len( camPathPoints ) - 1:
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
f.write(",\n")
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
f.write("\n\t}\n};\n\n")
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
else:
|
2021-03-12 13:06:21 +01:00
|
|
|
|
|
|
|
# If no camera path points are found, use default
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("CAMPATH " + fileName + "_camPath = {\n" +
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
"\t0,\n" +
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
"\t0,\n" +
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
"\t0\n" +
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-04-12 14:50:44 +02:00
|
|
|
"};\n\n" )
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "CAMPATH " + fileName + "_camPath" )
|
2021-02-02 12:15:11 +01:00
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
## Lighting setup
|
|
|
|
|
|
|
|
# Light sources will be similar to Blender's sunlamp
|
|
|
|
# A maximum of 3 light sources will be used
|
|
|
|
|
|
|
|
# LLM : Local Light Matrix
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
if len( bpy.data.lamps ) is not None:
|
2021-02-02 12:15:11 +01:00
|
|
|
|
|
|
|
# ~ f.write( "static MATRIX lgtmat = {\n" +
|
|
|
|
# ~ "\t 4096, 4096, 4096,\n" +
|
|
|
|
# ~ "\t -4096, 4096, 4096,\n" +
|
|
|
|
# ~ "\t -4096, 4096, -4096\n" +
|
|
|
|
# ~ "};\n")
|
|
|
|
|
|
|
|
cnt = 0
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
pad = 3 - len( bpy.data.lamps )
|
2021-02-02 12:15:11 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write( "MATRIX " + fileName + "_lgtmat = {\n")
|
2021-02-02 12:15:11 +01:00
|
|
|
|
|
|
|
for l in range(len(bpy.data.lamps)):
|
2021-03-12 13:06:21 +01:00
|
|
|
|
|
|
|
# Lightsource energy
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
energy = int( bpy.data.lamps[ l ].energy * 4096 )
|
2021-02-02 12:15:11 +01:00
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# Get lightsource's world orientation
|
2021-02-02 12:15:11 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
lightdir = bpy.data.objects[ bpy.data.lamps[ l ].name ].matrix_world * Vector( ( 0, 0, -1, 0 ) )
|
2021-02-02 12:15:11 +01:00
|
|
|
|
|
|
|
f.write(
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
"\t" + str( int( lightdir.x * energy ) ) + "," +
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
"\t" + str( int( -lightdir.z * energy ) ) + "," +
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
"\t" + str( int( lightdir.y * energy ) )
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
)
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
if l != len( bpy.data.lamps ) - 1:
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
f.write(",\n")
|
2021-02-19 18:00:42 +01:00
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# If less than 3 light sources exist in blender, fill the matrix with 0s.
|
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
if pad:
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
f.write(",\n")
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
while cnt < pad:
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
f.write("\t0,0,0")
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
if cnt != pad:
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
f.write(",\n")
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
cnt += 1
|
|
|
|
|
|
|
|
f.write("\n\t};\n\n")
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "MATRIX " + fileName + "_lgtmat" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
# LCM : Local Color Matrix
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write( "MATRIX " + fileName + "_cmat = {\n")
|
2021-02-02 12:15:11 +01:00
|
|
|
|
|
|
|
LCM = []
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
for l in bpy.data.lamps:
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
LCM.append( str( int( l.color.r * 4096 ) if l.color.r else 0 ) )
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
LCM.append( str( int( l.color.g * 4096 ) if l.color.g else 0 ) )
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
LCM.append( str( int( l.color.b * 4096 ) if l.color.b else 0 ) )
|
2021-02-02 12:15:11 +01:00
|
|
|
|
|
|
|
if len(LCM) < 9:
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
while len(LCM) < 9:
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
LCM.append('0')
|
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# Write LC matrix
|
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
f.write(
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
"\t" + LCM[ 0 ] + "," + LCM[ 3 ] + "," + LCM[ 6 ] + ",\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
"\t" + LCM[ 1 ] + "," + LCM[ 4 ] + "," + LCM[ 7 ] + ",\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
"\t" + LCM[ 2 ] + "," + LCM[ 5 ] + "," + LCM[ 8 ] + "\n" )
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-02-02 12:15:11 +01:00
|
|
|
f.write("\t};\n\n")
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "MATRIX " + fileName + "_cmat" )
|
2021-03-12 13:06:21 +01:00
|
|
|
|
|
|
|
## Meshes
|
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
actorPtr = first_mesh
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
levelPtr = first_mesh
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-02-19 18:00:42 +01:00
|
|
|
propPtr = first_mesh
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-03-12 12:13:08 +01:00
|
|
|
nodePtr = first_mesh
|
2021-02-19 18:00:42 +01:00
|
|
|
|
2021-03-12 11:21:18 +01:00
|
|
|
timList = []
|
|
|
|
|
2020-12-27 17:13:58 +01:00
|
|
|
for m in bpy.data.meshes:
|
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
if not m.get('isPortal') :
|
|
|
|
|
|
|
|
# Store vertices coordinates by axis to find max/min coordinates
|
|
|
|
|
|
|
|
Xvals = []
|
|
|
|
|
|
|
|
Yvals = []
|
|
|
|
|
|
|
|
Zvals = []
|
|
|
|
|
|
|
|
cleanName = CleanName(m.name)
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
# Write vertices vectors
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write( "SVECTOR " + fileName + "_model" + cleanName + "_mesh[] = {\n" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "SVECTOR " + "model" + cleanName + "_mesh[]" )
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
for i in range( len( m.vertices ) ):
|
2021-03-31 20:28:02 +02:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
v = m.vertices[ i ].co
|
2021-03-31 20:28:02 +02:00
|
|
|
|
|
|
|
# Append vertex coords to lists
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
Xvals.append( v.x )
|
2021-03-31 20:28:02 +02:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
Yvals.append( v.y )
|
2021-03-31 20:28:02 +02:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
Zvals.append( -v.z )
|
2021-03-31 20:28:02 +02:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
f.write("\t{ " + str( round( v.x * scale ) ) +
|
|
|
|
|
|
|
|
"," + str( round( -v.z * scale ) ) +
|
|
|
|
|
|
|
|
"," + str( round( v.y * scale ) ) + " }" )
|
2021-03-31 20:28:02 +02:00
|
|
|
|
|
|
|
if i != len(m.vertices) - 1:
|
|
|
|
|
|
|
|
f.write(",")
|
|
|
|
|
|
|
|
f.write("\n")
|
|
|
|
|
|
|
|
f.write("};\n\n")
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
# Write normals vectors
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("SVECTOR " + fileName + "_model"+cleanName+"_normal[] = {\n")
|
2021-01-14 17:22:44 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "SVECTOR " + fileName + "_model"+cleanName+"_normal[]" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
for i in range(len(m.vertices)):
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
poly = m.vertices[i]
|
2021-01-14 17:22:44 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
f.write( "\t"+ str( round( -poly.normal.x * 4096 ) ) +
|
|
|
|
|
|
|
|
"," + str( round( poly.normal.z * 4096 ) ) +
|
|
|
|
|
|
|
|
"," + str( round( -poly.normal.y * 4096 ) ) + ", 0" )
|
2021-01-14 17:22:44 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
if i != len(m.vertices) - 1:
|
2021-03-01 20:05:38 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
f.write(",")
|
|
|
|
|
|
|
|
f.write("\n")
|
|
|
|
|
|
|
|
f.write("};\n\n")
|
|
|
|
|
2021-04-03 15:23:30 +02:00
|
|
|
# Write UV textures coordinates
|
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
if len(m.uv_textures) != None:
|
|
|
|
|
|
|
|
for t in range(len(m.uv_textures)):
|
|
|
|
|
|
|
|
if m.uv_textures[t].data[0].image != None:
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("SVECTOR " + fileName + "_model"+cleanName+"_uv[] = {\n")
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "SVECTOR " + fileName + "_model"+cleanName+"_uv[]")
|
2021-03-31 20:28:02 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
# Clamp values to 0-255 to avoid tpage overflow
|
|
|
|
|
|
|
|
f.write("\t" + str( max( 0, min( round( ux ) , 255 ) ) ) +
|
|
|
|
|
|
|
|
"," + str( max( 0, min( round( tex_height - uy ) , 255 ) ) ) +
|
|
|
|
|
|
|
|
", 0, 0" )
|
2021-03-31 20:28:02 +02:00
|
|
|
|
|
|
|
if i != len(uv_layer) - 1:
|
|
|
|
|
|
|
|
f.write(",")
|
|
|
|
|
|
|
|
f.write("\n")
|
|
|
|
|
|
|
|
f.write("};\n\n")
|
|
|
|
|
|
|
|
# Save UV texture to a file in ./TIM
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
# It will have to be converted to a tim file
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
if texture_image.filepath == '':
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
os.makedirs(dirpath, exist_ok = 1)
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
texture_image.filepath_raw = folder + os.sep + "TIM" + os.sep + CleanName(texture_image.name) + "." + texture_image.file_format
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
texture_image.save()
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
# Write vertex colors vectors
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("CVECTOR " + fileName + "_model" + cleanName + "_color[] = {\n" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "CVECTOR " + fileName + "_model" + cleanName + "_color[]" )
|
2021-03-31 20:28:02 +02:00
|
|
|
|
|
|
|
# If vertex colors exist, use them
|
2021-02-19 18:00:42 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
if len(m.vertex_colors) != 0:
|
2021-02-19 18:00:42 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
colors = m.vertex_colors[0].data
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
for i in range(len(colors)):
|
2021-02-02 12:15:11 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
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" )
|
2021-02-19 18:00:42 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
if i != len(colors) - 1:
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
f.write(",")
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
f.write("\n")
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
# If no vertex colors, default to 2 whites, 1 grey
|
2021-03-25 16:53:04 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
else:
|
|
|
|
|
|
|
|
for i in range(len(m.polygons) * 3):
|
|
|
|
|
|
|
|
if i % 3 == 0:
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("\t80, 80, 80, 0" )
|
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
else:
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("\t128, 128, 128, 0" )
|
2021-03-31 20:28:02 +02:00
|
|
|
|
|
|
|
if i != (len(m.polygons) * 3) - 1:
|
|
|
|
|
|
|
|
f.write(",")
|
|
|
|
|
|
|
|
f.write("\n")
|
|
|
|
|
|
|
|
f.write("};\n\n")
|
|
|
|
|
|
|
|
# Write polygons index + type
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write( "PRIM " + fileName + "_model" + cleanName + "_index[] = {\n" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "PRIM " + fileName + "_model" + cleanName + "_index[]" )
|
2021-03-31 20:28:02 +02:00
|
|
|
|
|
|
|
for i in range(len(m.polygons)):
|
|
|
|
|
|
|
|
poly = m.polygons[i]
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
f.write( "\t" + str( poly.vertices[ 0 ] ) + "," + str( poly.vertices[ 1 ] ) + "," + str( poly.vertices[ 2 ] ) )
|
2021-03-25 16:53:04 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
if len(poly.vertices) > 3:
|
|
|
|
|
|
|
|
f.write("," + str(poly.vertices[3]) + ",8")
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
f.write(",0,4")
|
2021-03-25 16:53:04 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
if i != len(m.polygons) - 1:
|
2021-03-25 16:53:04 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
f.write(",")
|
2021-02-02 12:15:11 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
f.write("\n")
|
2021-02-02 12:15:11 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
f.write("};\n\n")
|
2021-02-02 12:15:11 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
# Get object's custom properties
|
2021-02-02 12:15:11 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
chkProp = {
|
|
|
|
|
|
|
|
'isAnim':0,
|
|
|
|
|
|
|
|
'isRigidBody':0,
|
|
|
|
|
|
|
|
'isStaticBody':0,
|
|
|
|
|
|
|
|
'isPrism':0,
|
|
|
|
|
|
|
|
'isActor':0,
|
|
|
|
|
|
|
|
'isLevel':0,
|
|
|
|
|
|
|
|
'isBG':0,
|
|
|
|
|
|
|
|
'isSprite':0,
|
|
|
|
|
|
|
|
'mass': 1,
|
|
|
|
|
|
|
|
'restitution': 0,
|
|
|
|
|
|
|
|
'lerp': 0
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for prop in chkProp:
|
|
|
|
|
|
|
|
if m.get(prop) is not None:
|
|
|
|
|
|
|
|
chkProp[prop] = m[prop]
|
|
|
|
|
|
|
|
# put isBG back to 0 if using precalculated BGs
|
|
|
|
|
|
|
|
if not self.exp_Precalc:
|
|
|
|
|
|
|
|
chkProp['isBG'] = 0;
|
|
|
|
|
|
|
|
if m.get('isActor'):
|
|
|
|
|
|
|
|
actorPtr = m.name
|
|
|
|
|
|
|
|
if m.get('isLevel'):
|
|
|
|
|
|
|
|
levelPtr = cleanName
|
|
|
|
|
|
|
|
if m.get('isProp'):
|
|
|
|
|
|
|
|
propPtr = cleanName
|
|
|
|
|
|
|
|
## 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:
|
2021-02-02 12:15:11 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
# Write vertex pos
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
o = bpy.data.objects[m.name]
|
2021-02-02 12:15:11 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
# If an action exists with the same name as the object, use that
|
|
|
|
|
|
|
|
if m.name in bpy.data.actions:
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
frame_start = int(bpy.data.actions[m.name].frame_range[0])
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
frame_end = int(bpy.data.actions[m.name].frame_range[1])
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
else:
|
|
|
|
|
|
|
|
# Use scene's Start/End frames
|
|
|
|
|
|
|
|
frame_start = int( bpy.context.scene.frame_start )
|
|
|
|
|
|
|
|
frame_end = int( bpy.context.scene.frame_end )
|
|
|
|
|
|
|
|
nFrame = frame_end - frame_start
|
|
|
|
|
|
|
|
c = 0;
|
|
|
|
|
|
|
|
tmp_meshes = []
|
|
|
|
|
|
|
|
for i in range(frame_start, frame_end):
|
|
|
|
|
|
|
|
bpy.context.scene.frame_set(i)
|
|
|
|
|
|
|
|
bpy.context.scene.update()
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
nm = o.to_mesh(bpy.context.scene, True, 'PREVIEW')
|
|
|
|
|
|
|
|
if i == frame_start :
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("VANIM " + fileName + "_model"+cleanName+"_anim = {\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
"\t" + str(nFrame) + ",\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
"\t" + str(len(nm.vertices)) + ",\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
"\t0,\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
"\t0,\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
"\t1,\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
"\t" + str(chkProp['lerp']) + ",\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
"\t{\n"
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
)
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "VANIM " + fileName + "_model"+cleanName+"_anim" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
for v in range(len(nm.vertices)):
|
|
|
|
|
|
|
|
if v == 0:
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
f.write("\t\t//Frame %d\n" % i)
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
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)) + " }")
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
if c != len(nm.vertices) * (nFrame) * 3 - 3:
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
f.write(",\n")
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
if v == len(nm.vertices) - 1:
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
f.write("\n")
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
c += 3;
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
tmp_meshes.append(nm)
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
f.write("\n\t}\n};\n")
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
# Remove meshe's working copies
|
|
|
|
|
|
|
|
for nm in tmp_meshes:
|
|
|
|
|
|
|
|
bpy.data.meshes.remove(nm)
|
|
|
|
|
|
|
|
# bpy.data.objects[bpy.data.meshes[0].name].active_shape_key.value : access shape_key
|
2021-02-19 18:00:42 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
## Mesh world transform setup
|
|
|
|
|
|
|
|
# Write object matrix, rot and pos vectors
|
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
f.write(
|
|
|
|
|
|
|
|
# ~ "MATRIX " + fileName + "_model"+cleanName+"_matrix = {0};\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ "VECTOR " + fileName + "_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" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ "SVECTOR " + fileName + "_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" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ "short " + fileName + "_model"+cleanName+"_isRigidBody = " + str(int(chkProp['isRigidBody'])) + ";\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ "short " + fileName + "_model"+cleanName+"_isStaticBody = " + str(int(chkProp['isStaticBody'])) + ";\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ "short " + fileName + "_model"+cleanName+"_isPrism = " + str(int(chkProp['isPrism'])) + ";\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ "short " + fileName + "_model"+cleanName+"_isAnim = " + str(int(chkProp['isAnim'])) + ";\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ "short " + fileName + "_model"+cleanName+"_isActor = " + str(int(chkProp['isActor'])) + ";\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ "short " + fileName + "_model"+cleanName+"_isLevel = " + str(int(chkProp['isLevel'])) + ";\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ "short " + fileName + "_model"+cleanName+"_isBG = " + str(int(chkProp['isBG'])) + ";\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ "short " + fileName + "_model"+cleanName+"_isSprite = " + str(int(chkProp['isSprite'])) + ";\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ "long " + fileName + "_model"+cleanName+"_p = 0;\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ "long " + fileName + "_model"+cleanName+"_OTz = 0;\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
"BODY " + fileName + "_model"+cleanName+"_body = {\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
"\t{0, 0, 0, 0},\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
"\t" + 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" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
"\t"+ 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)) + ", 0,\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
"\t" + str(int(chkProp['mass'])) + ",\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
"\tONE/" + str(int(chkProp['mass'])) + ",\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
# write min and max values of AABBs on each axis
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
"\t" + str(round(min(Xvals) * scale)) + "," + str(round(min(Zvals) * scale)) + "," + str(round(min(Yvals) * scale)) + ", 0,\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
"\t" + str(round(max(Xvals) * scale)) + "," + str(round(max(Zvals) * scale)) + "," + str(round(max(Yvals) * scale)) + ", 0,\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
"\t" + str(int(chkProp['restitution'])) + ",\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
# ~ "\tNULL\n" +
|
2021-04-03 14:14:01 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
"\t};\n\n")
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ level_symbols.append( "MATRIX " + fileName + "_model"+cleanName+"_matrix" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ level_symbols.append( "VECTOR " + fileName + "_model"+cleanName+"_pos" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ level_symbols.append( "SVECTOR " + fileName + "_model"+cleanName+"_rot" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ level_symbols.append( "short " + fileName + "_model"+cleanName+"_isRigidBody" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ level_symbols.append( "short " + fileName + "_model"+cleanName+"_isStaticBody" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ level_symbols.append( "short " + fileName + "_model"+cleanName+"_isPrism" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ level_symbols.append( "short " + fileName + "_model"+cleanName+"_isAnim" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ level_symbols.append( "short " + fileName + "_model"+cleanName+"_isActor" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ level_symbols.append( "short " + fileName + "_model"+cleanName+"_isLevel" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ level_symbols.append( "short " + fileName + "_model"+cleanName+"_isBG" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ level_symbols.append( "short " + fileName + "_model"+cleanName+"_isSprite" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ level_symbols.append( "long " + fileName + "_model"+cleanName+"_p" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# ~ level_symbols.append( "long " + fileName + "_model"+cleanName+"_OTz" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "BODY " + fileName + "_model"+cleanName+"_body" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
# Write TMESH struct
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write( "TMESH " + fileName + "_model" + cleanName + " = {\n" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write( "\t" + fileName + "_model" + cleanName + "_mesh,\n" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write( "\t" + fileName + "_model" + cleanName + "_normal,\n" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "TMESH " + fileName + "_model" + cleanName )
|
2021-03-31 20:28:02 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
# ~ level_symbols.append( "model" + cleanName + "_mesh" )
|
2021-03-31 20:28:02 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
# ~ level_symbols.append( "model" + cleanName + "_normal" )
|
2021-03-31 20:28:02 +02:00
|
|
|
|
|
|
|
if len(m.uv_textures) != None:
|
|
|
|
|
|
|
|
for t in range(len(m.uv_textures)):
|
|
|
|
|
|
|
|
if m.uv_textures[0].data[0].image != None:
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("\t" + fileName + "_model"+cleanName+"_uv,\n")
|
2021-03-31 20:28:02 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
# ~ level_symbols.append( "model" + cleanName + "_uv" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
else:
|
|
|
|
|
|
|
|
f.write("\t0,\n")
|
|
|
|
else:
|
|
|
|
|
|
|
|
f.write("\t0,\n")
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write( "\t" + fileName + "_model" + cleanName + "_color, \n" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
# ~ level_symbols.append( "model" + cleanName + "_color" )
|
2021-03-31 20:28:02 +02:00
|
|
|
|
|
|
|
# According to libgte.h, TMESH.len should be # of vertices. Meh...
|
|
|
|
|
2021-04-12 14:50:44 +02:00
|
|
|
f.write( "\t" + str( len ( m.polygons ) ) + "\n" )
|
2021-03-31 20:28:02 +02:00
|
|
|
|
2021-04-12 14:50:44 +02:00
|
|
|
f.write( "};\n\n" )
|
2021-03-31 20:28:02 +02:00
|
|
|
|
|
|
|
# Write texture binary name and declare TIM_IMAGE
|
|
|
|
# By default, loads the file from the ./TIM folder
|
|
|
|
|
|
|
|
if len(m.uv_textures) != None:
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
for t in range(len(m.uv_textures)):
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
if m.uv_textures[0].data[0].image != None:
|
|
|
|
|
|
|
|
tex_name = texture_image.name
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
prefix = str.partition(tex_name, ".")[0].replace('-','_')
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
prefix = CleanName(prefix)
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
# Add Tex name to list if it's not in there already
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
if prefix in timList:
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
break
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
else:
|
|
|
|
|
2021-04-03 14:14:01 +02:00
|
|
|
# Convert PNG to TIM
|
|
|
|
|
|
|
|
# If filename contains a dot, remove extension
|
|
|
|
|
|
|
|
if tex_name.find('.') != -1:
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
tex_name = tex_name[ : tex_name.rfind( '.' ) ]
|
2021-04-03 14:14:01 +02:00
|
|
|
|
|
|
|
# TODO : Add a way to arrange TIM's VM layout to avoid overlapping
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
filePathWithExt = folder + os.sep + "TIM" + os.sep + CleanName( tex_name ) + "." + texture_image.file_format.lower()
|
|
|
|
|
|
|
|
if not VramIsFull( bpy.context.scene.render.resolution_x ):
|
|
|
|
|
|
|
|
convertBGtoTIM( filePathWithExt, bpp = TIMbpp, timX = nextTpage, timY = tpageY, clutY = nextClutSlot )
|
|
|
|
|
|
|
|
setNextTimPos( texture_image )
|
|
|
|
|
|
|
|
elif VramIsFull( bpy.context.scene.render.resolution_x ) and tpageY == 0:
|
|
|
|
|
|
|
|
tpageY = 256
|
|
|
|
|
|
|
|
nextTpage = 320
|
|
|
|
|
|
|
|
if not VramIsFull( bpy.context.scene.render.resolution_x ):
|
|
|
|
|
|
|
|
convertBGtoTIM( filePathWithExt, bpp = TIMbpp, timX = nextTpage, timY = tpageY, clutY = nextClutSlot )
|
|
|
|
|
|
|
|
setNextTimPos( texture_image )
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
self.report({'ERROR'}, "Not enough space in VRam !")
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
self.report({'ERROR'}, "Not enough space in VRam !")
|
|
|
|
|
2021-04-07 18:03:47 +02:00
|
|
|
# ~ print( str(freeTpage) + " : " + str(nextTpage) + " : " + str(nextClutSlot) + " : " + str(freeClutSlot) )
|
2021-04-03 14:14:01 +02:00
|
|
|
|
|
|
|
# Write corresponding TIM declaration
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("extern unsigned long " + "_binary_TIM_" + prefix + "_tim_start[];\n")
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("extern unsigned long " + "_binary_TIM_" + prefix + "_tim_end[];\n")
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("extern unsigned long " + "_binary_TIM_" + prefix + "_tim_length;\n\n")
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-04-14 15:57:07 +02:00
|
|
|
f.write("TIM_IMAGE " + fileName + "_tim_" + prefix + ";\n\n")
|
2021-03-31 20:28:02 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "unsigned long " + "_binary_TIM_" + prefix + "_tim_start[]" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "unsigned long " + "_binary_TIM_" + prefix + "_tim_end[]" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "unsigned long " + "_binary_TIM_" + prefix + "_tim_length" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-14 15:57:07 +02:00
|
|
|
level_symbols.append( "TIM_IMAGE " + fileName + "_tim_" + prefix )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
timList.append(prefix)
|
2021-03-12 11:21:18 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
# ~ f.write("NODE_DECLARATION\n")
|
2021-04-08 17:24:17 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write( "MESH " + fileName + "_mesh" + cleanName + " = {\n" )
|
2021-03-31 20:28:02 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("\t&" + fileName + "_model"+ cleanName +",\n")
|
2021-03-31 20:28:02 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("\t" + fileName + "_model" + cleanName + "_index,\n")
|
2021-03-31 20:28:02 +02:00
|
|
|
|
|
|
|
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
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
prefix = str.partition(tex_name, ".")[0].replace('-','_')
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
prefix = CleanName(prefix)
|
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
f.write("\t&" + fileName + "_tim_"+ prefix + ",\n")
|
2021-03-31 20:28:02 +02:00
|
|
|
|
|
|
|
f.write("\t_binary_TIM_" + prefix + "_tim_start,\n")
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
f.write("\t0,\n" +
|
|
|
|
|
|
|
|
"\t0,\n")
|
|
|
|
else:
|
|
|
|
|
|
|
|
f.write("\t0,\n" +
|
|
|
|
|
|
|
|
"\t0,\n")
|
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
f.write(
|
|
|
|
|
|
|
|
"\t{0},\n" +
|
|
|
|
|
|
|
|
"\t{" + 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" +
|
|
|
|
|
|
|
|
"\t{"+ 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" +
|
|
|
|
|
|
|
|
"\t" + str( int( chkProp[ 'isRigidBody' ] ) ) + ",\n" +
|
|
|
|
|
|
|
|
"\t" + str(int(chkProp['isStaticBody'])) + ",\n" +
|
|
|
|
|
|
|
|
"\t" + str(int(chkProp['isPrism'])) + ",\n" +
|
|
|
|
|
|
|
|
"\t" + str(int(chkProp['isAnim'])) + ",\n" +
|
|
|
|
|
|
|
|
"\t" + str(int(chkProp['isActor'])) + ",\n" +
|
|
|
|
|
|
|
|
"\t" + str(int(chkProp['isLevel'])) + ",\n" +
|
|
|
|
|
|
|
|
"\t" + str(int(chkProp['isBG'])) + ",\n" +
|
|
|
|
|
|
|
|
"\t" + str(int(chkProp['isSprite'])) + ",\n" +
|
|
|
|
|
|
|
|
"\t0,\n" +
|
|
|
|
|
|
|
|
"\t0,\n" +
|
|
|
|
|
|
|
|
"\t&" + fileName + "_model"+cleanName+"_body,\n"
|
|
|
|
|
|
|
|
)
|
2021-03-12 11:21:18 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
if m.get("isAnim") is not None and m["isAnim"] != 0:
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("\t&" + fileName + "_model"+cleanName+"_anim,\n")
|
2021-03-31 20:28:02 +02:00
|
|
|
else:
|
|
|
|
|
|
|
|
f.write("\t0,\n")
|
|
|
|
|
|
|
|
|
|
|
|
f.write(
|
2021-04-08 17:24:17 +02:00
|
|
|
|
|
|
|
"\t" + "subs_" + m.name + ",\n" +
|
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
"\t0" +
|
2021-04-08 17:24:17 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
"\n};\n\n"
|
|
|
|
)
|
2021-04-13 16:49:26 +02:00
|
|
|
|
|
|
|
level_symbols.append( "MESH " + fileName + "_mesh" + cleanName )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
# Remove portals from mesh list as we don't want them to be exported
|
|
|
|
|
|
|
|
meshList = list(bpy.data.meshes)
|
|
|
|
|
|
|
|
portalList = []
|
|
|
|
|
|
|
|
for mesh in meshList:
|
|
|
|
|
|
|
|
if mesh.get('isPortal'):
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
meshList = [i for i in meshList if i != mesh]
|
|
|
|
|
|
|
|
# Nasty way of removing all occurrences of the mesh
|
|
|
|
# ~ try:
|
|
|
|
# ~ while True:
|
|
|
|
# ~ meshList.remove(mesh)
|
|
|
|
# ~ except ValueError:
|
|
|
|
# ~ pass
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
portalList.append( bpy.data.objects[mesh.name] )
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("MESH * " + fileName + "_meshes[" + str( len(meshList ) ) + "] = {\n")
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
for k in range(len(meshList)):
|
2021-03-12 11:21:18 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
cleanName = CleanName(meshList[k].name)
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("\t&" + fileName + "_mesh" + cleanName)
|
2021-03-12 11:21:18 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
if k != len(meshList) - 1:
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2020-12-30 11:23:36 +01:00
|
|
|
f.write(",\n")
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("\n}; \n\n")
|
|
|
|
|
|
|
|
f.write("int " + fileName + "_meshes_length = " + str( len( meshList ) ) + ";\n\n")
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "MESH * " + fileName + "_meshes[" + str(len(meshList)) + "]")
|
|
|
|
|
|
|
|
level_symbols.append( "int " + fileName + "_meshes_length" )
|
2021-03-01 20:05:38 +01:00
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# If camAngles is empty, use default camera, and do not include pre-calculated backgrounds
|
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
if not camAngles:
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("CAMANGLE " + fileName + "_camAngle_" + CleanName(defaultCam) + " = {\n" +
|
2021-03-24 11:33:09 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
"\t&" + fileName + "_camPos_" + CleanName(defaultCam) + ",\n" +
|
2021-03-24 11:33:09 +01:00
|
|
|
|
2021-04-08 17:24:17 +02:00
|
|
|
"\t0,\n\t 0,\n\t { 0 },\n\t { 0 },\n\t 0,\n\t 0\n" +
|
2021-03-24 11:33:09 +01:00
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
"};\n\n")
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "CAMANGLE " + fileName + "_camAngle_" + CleanName(defaultCam) )
|
2021-03-01 20:05:38 +01:00
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# If camAngles is populated, use backgrounds and camera angles
|
|
|
|
|
2021-03-24 11:33:09 +01:00
|
|
|
for camera in camAngles:
|
|
|
|
|
2021-03-25 10:50:54 +01:00
|
|
|
# Get current scene
|
|
|
|
|
2021-03-24 11:33:09 +01:00
|
|
|
scene = bpy.context.scene
|
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
# List of portals
|
|
|
|
|
|
|
|
visiblePortal = []
|
|
|
|
|
|
|
|
for portal in portalList:
|
|
|
|
|
|
|
|
if isInFrame(scene, camera, portal):
|
|
|
|
|
|
|
|
# Get normalized direction vector between camera and portal
|
|
|
|
|
|
|
|
dirToTarget = portal.location - camera.location
|
|
|
|
|
|
|
|
dirToTarget.normalize()
|
|
|
|
|
|
|
|
# Cast a ray from camera to body to determine visibility
|
|
|
|
|
|
|
|
result, location, normal, index, hitObject, matrix = scene.ray_cast( camera.location, dirToTarget )
|
|
|
|
|
|
|
|
# If hitObject is portal, nothing is obstructing it's visibility
|
|
|
|
|
|
|
|
if hitObject is not None:
|
|
|
|
|
|
|
|
if hitObject in portalList:
|
|
|
|
|
|
|
|
if hitObject == portal:
|
|
|
|
|
|
|
|
visiblePortal.append(hitObject)
|
|
|
|
|
|
|
|
# If more than one portal is visible, only keep the two closest ones
|
|
|
|
|
|
|
|
if len( visiblePortal ) > 2:
|
|
|
|
|
|
|
|
# Store the tested portals distance to camera
|
|
|
|
|
|
|
|
testDict = {}
|
|
|
|
|
|
|
|
for tested in visiblePortal:
|
|
|
|
|
|
|
|
# Get distance between cam and tested portal
|
|
|
|
|
|
|
|
distToTested = sqrt( ( tested.location - camera.location ) * ( tested.location - camera.location ) )
|
|
|
|
|
|
|
|
# Store distance
|
|
|
|
|
|
|
|
testDict[distToTested] = tested
|
|
|
|
|
|
|
|
# If dictionary has more than 2 portals, remove the farthest ones
|
|
|
|
|
|
|
|
while len( testDict ) > 2:
|
|
|
|
|
|
|
|
del testDict[max(testDict)]
|
|
|
|
|
|
|
|
# Reset visible portal
|
|
|
|
|
|
|
|
visiblePortal.clear()
|
|
|
|
|
|
|
|
# Get the portals stored in the dict and store them in the list
|
|
|
|
|
|
|
|
for Dportal in testDict:
|
|
|
|
|
|
|
|
visiblePortal.append(testDict[Dportal])
|
|
|
|
|
|
|
|
# Revert to find original order back
|
|
|
|
|
|
|
|
visiblePortal.reverse()
|
|
|
|
|
2021-03-24 11:33:09 +01:00
|
|
|
# List of target found visible
|
|
|
|
|
|
|
|
visibleTarget = []
|
|
|
|
|
|
|
|
for target in rayTargets:
|
|
|
|
|
|
|
|
# Chech object is in view frame
|
|
|
|
|
2021-04-03 14:14:01 +02:00
|
|
|
if isInFrame(scene, camera, target):
|
2021-03-25 10:50:54 +01:00
|
|
|
|
2021-03-24 11:33:09 +01:00
|
|
|
# Get normalized direction vector between camera and object
|
|
|
|
|
|
|
|
dirToTarget = target.location - camera.location
|
|
|
|
|
|
|
|
dirToTarget.normalize()
|
|
|
|
|
|
|
|
# Cast ray from camera to object
|
2021-03-31 20:28:02 +02:00
|
|
|
# Unpack results into several variables.
|
2021-03-24 11:33:09 +01:00
|
|
|
# We're only interested in 'hitObject' though
|
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
result, hitLocation, normal, index, hitObject, matrix = scene.ray_cast( camera.location, dirToTarget )
|
2021-03-24 11:33:09 +01:00
|
|
|
|
|
|
|
# If hitObject is the same as target, nothing is obstructing it's visibility
|
|
|
|
|
|
|
|
if hitObject is not None:
|
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
# If hit object is a portal, cast a new ray from hit location to target
|
|
|
|
|
|
|
|
if hitObject.data.get('isPortal'):
|
|
|
|
|
|
|
|
# Find out if we're left or right of portal
|
|
|
|
|
2021-04-02 12:53:55 +02:00
|
|
|
# Get vertices world coordinates
|
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
v0 = hitObject.matrix_world * hitObject.data.vertices[0].co
|
2021-04-02 12:53:55 +02:00
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
v1 = hitObject.matrix_world * hitObject.data.vertices[1].co
|
|
|
|
|
2021-04-02 12:53:55 +02:00
|
|
|
# Check side :
|
|
|
|
# 'back' : portal in on the right of the cam, cam is on left of portal
|
|
|
|
# 'front' : portal in on the left of the cam, cam is on right of portal
|
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
side = checkLine(v0.x, v0.y, v1.x, v1.y , camera.location.x, camera.location.y, camera.location.x, camera.location.y )
|
|
|
|
|
|
|
|
if side == 'front':
|
|
|
|
|
2021-04-02 12:53:55 +02:00
|
|
|
# we're on the right of the portal, origin.x must be > hitLocation.x
|
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
offset = [ 1.001, 0.999, 0.999 ]
|
|
|
|
|
|
|
|
else :
|
|
|
|
|
2021-04-02 12:53:55 +02:00
|
|
|
# we're on the left of the portal, origin.x must be < hitLocation.x
|
2021-04-02 12:41:32 +02:00
|
|
|
|
2021-04-02 12:53:55 +02:00
|
|
|
offset = [ 0.999, 1.001, 1.001 ]
|
|
|
|
|
|
|
|
# Add offset to hitLocation, so that the new ray won't hit the same portal
|
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
origin = Vector( ( hitLocation.x * offset[0], hitLocation.y * offset[1], hitLocation.z * offset[2] ) )
|
|
|
|
|
|
|
|
result, hitLocationPort, normal, index, hitObjectPort, matrix = scene.ray_cast( origin , dirToTarget )
|
|
|
|
|
|
|
|
if hitObjectPort is not None:
|
|
|
|
|
|
|
|
if hitObjectPort in rayTargets:
|
|
|
|
|
|
|
|
visibleTarget.append(target)
|
|
|
|
|
2021-04-02 12:53:55 +02:00
|
|
|
# If hitObject is not a portal, just add it
|
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
elif hitObject in rayTargets:
|
2021-03-25 10:50:54 +01:00
|
|
|
|
2021-03-24 11:33:09 +01:00
|
|
|
visibleTarget.append(target)
|
2021-04-02 12:41:32 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
if bpy.data.objects[ actorPtr ] not in visibleTarget:
|
|
|
|
|
|
|
|
visibleTarget.append( bpy.data.objects[ actorPtr ] )
|
|
|
|
|
2021-04-02 15:37:38 +02:00
|
|
|
# If visiblePortal length is under 2, this means there's only one portal
|
|
|
|
|
|
|
|
# Empty strings to be populated depending on portal position (left/right of screen)
|
|
|
|
|
|
|
|
before = ''
|
|
|
|
|
|
|
|
after = ''
|
|
|
|
|
|
|
|
if len( visiblePortal ) < 2 :
|
|
|
|
|
|
|
|
# Find wich side of screen the portal is on. left side : portal == bw, right side : portal == fw
|
|
|
|
|
|
|
|
screenCenterX = int( scene.render.resolution_x / 2 )
|
|
|
|
|
|
|
|
screenY = int( scene.render.resolution_y )
|
|
|
|
|
|
|
|
# Get vertices screen coordinates
|
|
|
|
|
|
|
|
s = objVertWtoS(scene, camera, visiblePortal[0])
|
|
|
|
|
|
|
|
# Check line
|
|
|
|
|
|
|
|
side = checkLine(
|
|
|
|
screenCenterX, 0, screenCenterX, screenY,
|
|
|
|
|
|
|
|
s[1].x,
|
|
|
|
|
|
|
|
s[1].y,
|
|
|
|
|
|
|
|
s[3].x,
|
|
|
|
|
|
|
|
s[3].y
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# If front == right of screen : fw
|
|
|
|
|
|
|
|
if side == "front":
|
|
|
|
|
|
|
|
before = "\t{\n\t\t{ 0, 0, 0, 0 },\n\t\t{ 0, 0, 0, 0 },\n\t\t{ 0, 0, 0, 0 },\n\t\t{ 0, 0, 0, 0 }\n\t},\n"
|
|
|
|
|
|
|
|
# If back == left of screen : bw
|
|
|
|
|
|
|
|
else :
|
|
|
|
|
|
|
|
after = "\t{\n\t\t{ 0, 0, 0, 0 },\n\t\t{ 0, 0, 0, 0 },\n\t\t{ 0, 0, 0, 0 },\n\t\t{ 0, 0, 0, 0 }\n\t},\n"
|
|
|
|
|
2021-03-24 11:33:09 +01:00
|
|
|
prefix = CleanName(camera.name)
|
2021-03-01 20:05:38 +01:00
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# Include Tim data
|
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
f.write("extern unsigned long "+"_binary_TIM_bg_" + prefix + "_tim_start[];\n")
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
f.write("extern unsigned long "+"_binary_TIM_bg_" + prefix + "_tim_end[];\n")
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
f.write("extern unsigned long "+"_binary_TIM_bg_" + prefix + "_tim_length;\n\n")
|
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# Write corresponding TIM_IMAGE struct
|
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
f.write("TIM_IMAGE tim_bg_" + prefix + ";\n\n")
|
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# Write corresponding CamAngle struct
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("CAMANGLE " + fileName + "_camAngle_" + prefix + " = {\n" +
|
2021-03-24 11:33:09 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
"\t&" + fileName + "_camPos_" + prefix + ",\n" +
|
2021-03-24 11:33:09 +01:00
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
"\t&tim_bg_" + prefix + ",\n" +
|
2021-03-24 11:33:09 +01:00
|
|
|
|
|
|
|
"\t_binary_TIM_bg_" + prefix + "_tim_start,\n" +
|
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
"\t// Write quad NW, NE, SE, SW\n")
|
|
|
|
|
2021-04-02 15:37:38 +02:00
|
|
|
f.write( before )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
# Feed to level_symbols
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "unsigned long "+"_binary_TIM_bg_" + prefix + "_tim_start[]")
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "unsigned long "+"_binary_TIM_bg_" + prefix + "_tim_end[]")
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "unsigned long "+"_binary_TIM_bg_" + prefix + "_tim_length")
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "TIM_IMAGE tim_bg_" + prefix )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "CAMANGLE " + fileName + "_camAngle_" + prefix )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
for portal in visiblePortal:
|
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
w = objVertLtoW(portal)
|
2021-03-31 20:28:02 +02:00
|
|
|
|
2021-04-02 15:37:38 +02:00
|
|
|
# ~ f.write("\t// " + str(portal) + "\n" )
|
2021-03-31 20:28:02 +02:00
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
# Write portal'vertices world coordinates NW, NE, SE, SW
|
2021-03-31 20:28:02 +02:00
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
f.write("\t{\n\t\t" +
|
2021-03-31 20:28:02 +02:00
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
"{ " + str( int (w[3].x ) ) + ", " + str( int (w[3].y ) ) + ", " + str( int (w[3].z ) ) + ", 0 },\n\t\t" +
|
|
|
|
|
|
|
|
"{ " + str( int (w[2].x ) ) + ", " + str( int (w[2].y ) ) + ", " + str( int (w[2].z ) ) + ", 0 },\n\t\t" +
|
|
|
|
|
|
|
|
"{ " + str( int (w[0].x ) ) + ", " + str( int (w[0].y ) ) + ", " + str( int (w[0].z ) ) + ", 0 },\n\t\t" +
|
2021-03-31 20:28:02 +02:00
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
"{ " + str( int (w[1].x ) ) + ", " + str( int (w[1].y ) ) + ", " + str( int (w[1].z ) ) + ", 0 }\n" +
|
2021-03-31 20:28:02 +02:00
|
|
|
|
|
|
|
"\t},\n" )
|
2021-04-02 12:41:32 +02:00
|
|
|
|
2021-04-02 15:37:38 +02:00
|
|
|
f.write( after )
|
|
|
|
|
2021-04-02 12:41:32 +02:00
|
|
|
# UNUSED : Screen coords
|
|
|
|
|
|
|
|
# ~ s = objVertWtoS( scene, camera, portal )
|
|
|
|
|
|
|
|
# ~ f.write("\t{\n\t\t" +
|
|
|
|
|
|
|
|
# ~ "{ " + str( int (s[3].x ) ) + ", " + str( int (s[3].y ) ) + ", " + str( int (s[3].z ) ) + ", 0 },\n\t\t" +
|
|
|
|
|
|
|
|
# ~ "{ " + str( int (s[2].x ) ) + ", " + str( int (s[2].y ) ) + ", " + str( int (s[2].z ) ) + ", 0 },\n\t\t" +
|
|
|
|
|
|
|
|
# ~ "{ " + str( int (s[0].x ) ) + ", " + str( int (s[0].y ) ) + ", " + str( int (s[0].z ) ) + ", 0 },\n\t\t" +
|
|
|
|
|
|
|
|
# ~ "{ " + str( int (s[1].x ) ) + ", " + str( int (s[1].y ) ) + ", " + str( int (s[1].z ) ) + ", 0 }\n" +
|
|
|
|
|
|
|
|
# ~ "\t},\n" )
|
2021-03-31 20:28:02 +02:00
|
|
|
|
|
|
|
f.write("\t" + str( len( visibleTarget ) ) + ",\n" +
|
2021-03-24 11:33:09 +01:00
|
|
|
|
|
|
|
"\t{\n")
|
|
|
|
|
|
|
|
for target in range( len( visibleTarget ) ) :
|
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
f.write( "\t\t&" + fileName + "_mesh" + CleanName(visibleTarget[target].name) )
|
2021-03-24 11:33:09 +01:00
|
|
|
|
|
|
|
if target < len(visibleTarget) - 1:
|
|
|
|
|
|
|
|
f.write(",\n")
|
|
|
|
|
|
|
|
f.write("\n\t}\n" +
|
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
"};\n\n")
|
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# Write camera angles in an array for loops
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("CAMANGLE * " + fileName + "_camAngles[" + str(len(camAngles)) + "] = {\n")
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-24 11:33:09 +01:00
|
|
|
for camera in camAngles:
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-24 11:33:09 +01:00
|
|
|
prefix = CleanName(camera.name)
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("\t&" + fileName + "_camAngle_" + prefix + ",\n")
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-01 20:05:38 +01:00
|
|
|
f.write("};\n\n")
|
2020-12-30 11:23:36 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
# Feed to level_symbols
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "CAMANGLE * " + fileName + "_camAngles[" + str(len(camAngles)) + "]" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
## Spatial Partitioning
|
|
|
|
|
2021-03-16 11:58:00 +01:00
|
|
|
# Planes in the level - dict of strings
|
2021-03-15 12:44:15 +01:00
|
|
|
|
|
|
|
LvlPlanes = {}
|
|
|
|
|
2021-03-16 11:58:00 +01:00
|
|
|
# Objects in the level - dict of strings
|
2021-03-15 12:44:15 +01:00
|
|
|
|
|
|
|
LvlObjects = {}
|
|
|
|
|
|
|
|
# Link objects to their respective plane
|
|
|
|
|
2021-03-16 11:58:00 +01:00
|
|
|
PlanesObjects = defaultdict(dict)
|
2021-03-18 16:34:43 +01:00
|
|
|
|
2021-03-18 19:21:40 +01:00
|
|
|
PlanesRigidBodies = defaultdict(dict)
|
|
|
|
|
2021-03-18 16:34:43 +01:00
|
|
|
# List of objects that can travel ( actor , moveable props...)
|
|
|
|
|
|
|
|
Moveables = []
|
2021-03-15 12:44:15 +01:00
|
|
|
|
2021-04-08 17:24:17 +02:00
|
|
|
# Store starting plane for moveables
|
|
|
|
|
|
|
|
PropPlane = defaultdict(dict)
|
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
# Store XY1, XY2 values
|
|
|
|
|
|
|
|
Xvalues = []
|
|
|
|
|
|
|
|
Yvalues = []
|
|
|
|
|
|
|
|
# Find planes and objects bounding boxes
|
|
|
|
|
|
|
|
# Planes first
|
|
|
|
|
|
|
|
for o in bpy.data.objects:
|
|
|
|
|
|
|
|
# Only loop through meshes
|
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
if o.type == 'MESH' and not o.data.get('isPortal'):
|
2021-03-15 12:44:15 +01:00
|
|
|
|
|
|
|
# Get Level planes coordinates
|
|
|
|
|
|
|
|
if o.data.get('isLevel'):
|
|
|
|
|
|
|
|
# World matrix is used to convert local to global coordinates
|
|
|
|
|
|
|
|
mw = o.matrix_world
|
|
|
|
|
|
|
|
for v in bpy.data.objects[o.name].data.vertices:
|
|
|
|
|
|
|
|
# Convert local to global coords
|
|
|
|
|
|
|
|
Xvalues.append( (mw * v.co).x )
|
|
|
|
|
|
|
|
Yvalues.append( (mw * v.co).y )
|
|
|
|
|
|
|
|
LvlPlanes[o.name] = {'x1' : min(Xvalues),
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
'y1' : min(Yvalues),
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
'x2' : max(Xvalues),
|
2021-03-23 14:33:38 +01:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
'y2' : max(Yvalues)}
|
|
|
|
|
|
|
|
# Clear X/Y lists for next iteration
|
|
|
|
|
|
|
|
Xvalues = []
|
|
|
|
|
|
|
|
Yvalues = []
|
|
|
|
|
2021-03-16 11:58:00 +01:00
|
|
|
# For each object not a plane, get its coordinates
|
2021-03-15 12:44:15 +01:00
|
|
|
|
2021-03-16 11:58:00 +01:00
|
|
|
if not o.data.get('isLevel'):
|
2021-03-15 12:44:15 +01:00
|
|
|
|
|
|
|
# World matrix is used to convert local to global coordinates
|
|
|
|
|
|
|
|
mw = o.matrix_world
|
2021-03-16 11:58:00 +01:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
for v in bpy.data.objects[o.name].data.vertices:
|
|
|
|
|
|
|
|
# Convert local to global coords
|
|
|
|
|
|
|
|
Xvalues.append( (mw * v.co).x )
|
|
|
|
|
|
|
|
Yvalues.append( (mw * v.co).y )
|
|
|
|
|
|
|
|
LvlObjects[o.name] = {'x1' : min(Xvalues),
|
2021-04-02 12:41:32 +02:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
'y1' : min(Yvalues),
|
2021-04-02 12:41:32 +02:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
'x2' : max(Xvalues),
|
2021-04-02 12:41:32 +02:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
'y2' : max(Yvalues)}
|
|
|
|
|
|
|
|
# Clear X/Y lists for next iteration
|
|
|
|
|
|
|
|
Xvalues = []
|
|
|
|
|
|
|
|
Yvalues = []
|
2021-03-18 16:34:43 +01:00
|
|
|
|
|
|
|
# Add objects that can travel to the
|
|
|
|
|
|
|
|
if o.data.get("isRigidBody"):
|
|
|
|
|
2021-04-08 17:24:17 +02:00
|
|
|
Moveables.append(o)
|
2021-03-15 12:44:15 +01:00
|
|
|
|
2021-03-16 16:18:05 +01:00
|
|
|
# Declare LvlPlanes nodes to avoid declaration dependency issues
|
|
|
|
|
2021-04-08 17:24:17 +02:00
|
|
|
# ~ for k in LvlPlanes.keys():
|
2021-03-16 16:18:05 +01:00
|
|
|
|
2021-04-08 17:24:17 +02:00
|
|
|
# ~ f.write("NODE node" + CleanName(k) + ";\n\n")
|
2021-03-16 16:18:05 +01:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
# Sides of the plane to check
|
|
|
|
|
|
|
|
checkSides = [
|
|
|
|
['N','S'],
|
2021-04-08 17:24:17 +02:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
['S','N'],
|
2021-04-08 17:24:17 +02:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
['W','E'],
|
2021-04-08 17:24:17 +02:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
['E','W']
|
2021-04-08 17:24:17 +02:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
]
|
|
|
|
|
|
|
|
# Generate a dict :
|
|
|
|
|
|
|
|
# ~ {
|
|
|
|
# ~ 'S' : []
|
|
|
|
# ~ 'N' : [] list of planes connected to this plane, and side they're on
|
|
|
|
# ~ 'W' : []
|
|
|
|
# ~ 'E' : []
|
|
|
|
# ~ 'objects' : [] list of objects on this plane
|
|
|
|
# ~ ''
|
|
|
|
# ~ }
|
|
|
|
|
2021-04-07 18:03:47 +02:00
|
|
|
overlappingObject = []
|
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
for p in LvlPlanes:
|
|
|
|
|
|
|
|
# Find objects on plane
|
|
|
|
|
|
|
|
for o in LvlObjects:
|
|
|
|
|
2021-04-07 18:03:47 +02:00
|
|
|
# If object is overlapping between several planes
|
|
|
|
|
|
|
|
if isInPlane(LvlPlanes[p], LvlObjects[o]) > 1:
|
|
|
|
|
|
|
|
# Object not actor
|
|
|
|
|
|
|
|
if o != actorPtr:
|
|
|
|
|
|
|
|
# Object not in list
|
|
|
|
|
|
|
|
if o not in overlappingObject:
|
|
|
|
|
|
|
|
overlappingObject.append(o)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
overlappingObject.remove(o)
|
|
|
|
|
|
|
|
# Add this object to the plane's list
|
|
|
|
|
|
|
|
if 'objects' in PlanesObjects[p]:
|
|
|
|
|
|
|
|
PlanesObjects[p]['objects'].append(o)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
PlanesObjects[p] = { 'objects' : [o] }
|
|
|
|
|
2021-03-16 11:58:00 +01:00
|
|
|
# If object is above plane
|
2021-03-15 12:44:15 +01:00
|
|
|
|
2021-03-18 16:34:43 +01:00
|
|
|
if isInPlane(LvlPlanes[p], LvlObjects[o]) == 1:
|
2021-03-15 12:44:15 +01:00
|
|
|
|
2021-03-22 20:26:41 +01:00
|
|
|
# Add all objects but the actor
|
2021-03-16 11:58:00 +01:00
|
|
|
|
2021-03-22 20:26:41 +01:00
|
|
|
if o != actorPtr:
|
2021-03-16 11:58:00 +01:00
|
|
|
|
2021-03-22 20:26:41 +01:00
|
|
|
# Add this object to the plane's list
|
|
|
|
|
|
|
|
if 'objects' in PlanesObjects[p]:
|
|
|
|
|
|
|
|
PlanesObjects[p]['objects'].append(o)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
PlanesObjects[p] = { 'objects' : [o] }
|
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
else:
|
2021-03-22 20:26:41 +01:00
|
|
|
|
|
|
|
# If actor is on this plane, use it as starting node
|
2021-04-07 18:03:47 +02:00
|
|
|
|
2021-03-24 11:33:09 +01:00
|
|
|
levelPtr = p
|
2021-04-07 18:03:47 +02:00
|
|
|
|
2021-03-22 20:26:41 +01:00
|
|
|
nodePtr = p
|
2021-04-07 18:03:47 +02:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
# Add moveable objects in every plane
|
2021-03-18 16:34:43 +01:00
|
|
|
|
|
|
|
for moveable in Moveables:
|
|
|
|
|
2021-04-08 17:24:17 +02:00
|
|
|
# If moveable is not actor
|
|
|
|
|
|
|
|
if moveable.data.get( 'isProp' ):
|
|
|
|
|
|
|
|
# If is in current plane, add it to the list
|
|
|
|
|
|
|
|
if isInPlane( LvlPlanes[ p ], LvlObjects[ moveable.name ] ) :
|
|
|
|
|
|
|
|
PropPlane[moveable] = p
|
|
|
|
|
2021-03-18 19:21:40 +01:00
|
|
|
if 'rigidbodies' in PlanesRigidBodies[p]:
|
2021-03-18 16:34:43 +01:00
|
|
|
|
2021-04-08 17:24:17 +02:00
|
|
|
if moveable.name not in PlanesRigidBodies[p]['rigidbodies']:
|
2021-03-18 16:34:43 +01:00
|
|
|
|
2021-04-08 17:24:17 +02:00
|
|
|
PlanesRigidBodies[ p ][ 'rigidbodies' ].append(CleanName( moveable.name ) )
|
2021-03-18 16:34:43 +01:00
|
|
|
else:
|
|
|
|
|
2021-04-08 17:24:17 +02:00
|
|
|
PlanesRigidBodies[p] = { 'rigidbodies' : [ CleanName(moveable.name) ] }
|
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
# Find surrounding planes
|
|
|
|
|
|
|
|
for op in LvlPlanes:
|
|
|
|
|
|
|
|
# Loop on other planes
|
|
|
|
|
|
|
|
if op is not p:
|
|
|
|
|
|
|
|
# Check each side
|
|
|
|
|
|
|
|
for s in checkSides:
|
|
|
|
|
|
|
|
# If connected ('connected') plane exists...
|
|
|
|
|
|
|
|
if checkLine(
|
|
|
|
|
|
|
|
getSepLine(p, s[0])[0],
|
2021-04-04 23:32:34 +02:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
getSepLine(p, s[0])[1],
|
2021-04-04 23:32:34 +02:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
getSepLine(p, s[0])[2],
|
2021-04-04 23:32:34 +02:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
getSepLine(p, s[0])[3],
|
|
|
|
|
|
|
|
getSepLine(op, s[1])[0],
|
2021-04-04 23:32:34 +02:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
getSepLine(op, s[1])[1],
|
2021-04-04 23:32:34 +02:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
getSepLine(op, s[1])[2],
|
2021-04-04 23:32:34 +02:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
getSepLine(op, s[1])[3]
|
|
|
|
|
2021-03-18 16:34:43 +01:00
|
|
|
) == 'connected' and (
|
|
|
|
|
|
|
|
isInPlane( LvlPlanes[p], LvlPlanes[op] )
|
|
|
|
|
|
|
|
):
|
2021-03-15 12:44:15 +01:00
|
|
|
|
|
|
|
# ... add it to the list
|
|
|
|
|
|
|
|
if 'siblings' not in PlanesObjects[p]:
|
|
|
|
|
|
|
|
PlanesObjects[p]['siblings'] = {}
|
|
|
|
|
|
|
|
# If more than one plane is connected on the same side of the plane,
|
|
|
|
# add it to the corresponding list
|
|
|
|
|
|
|
|
if s[0] in PlanesObjects[p]['siblings']:
|
|
|
|
|
|
|
|
PlanesObjects[p]['siblings'][s[0]].append(op)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
PlanesObjects[p]['siblings'][s[0]] = [op]
|
2021-04-08 17:24:17 +02:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
pName = CleanName(p)
|
|
|
|
|
2021-03-16 16:18:05 +01:00
|
|
|
# Write SIBLINGS structure
|
2021-03-15 12:44:15 +01:00
|
|
|
|
2021-03-16 11:58:00 +01:00
|
|
|
nSiblings = 0
|
|
|
|
|
2021-03-18 16:34:43 +01:00
|
|
|
if 'siblings' in PlanesObjects[p]:
|
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
if 'S' in PlanesObjects[ p ][ 'siblings' ]:
|
2021-03-16 11:58:00 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
nSiblings += len( PlanesObjects[ p ][ 'siblings' ][ 'S' ] )
|
2021-03-16 11:58:00 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
if 'N' in PlanesObjects[ p ][ 'siblings' ]:
|
2021-03-18 16:34:43 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
nSiblings += len( PlanesObjects[ p ][ 'siblings' ][ 'N' ] )
|
2021-03-18 16:34:43 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
if 'E' in PlanesObjects[ p ][ 'siblings' ]:
|
2021-03-18 16:34:43 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
nSiblings += len( PlanesObjects[ p ][ 'siblings' ][ 'E' ] )
|
2021-03-18 16:34:43 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
if 'W' in PlanesObjects[ p ][ 'siblings' ]:
|
2021-03-18 16:34:43 +01:00
|
|
|
|
2021-04-04 23:32:34 +02:00
|
|
|
nSiblings += len( PlanesObjects[ p ][ 'siblings' ][ 'W' ] )
|
2021-03-16 11:58:00 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("SIBLINGS " + fileName + "_node" + pName + "_siblings = {\n" +
|
2021-04-08 17:24:17 +02:00
|
|
|
|
2021-03-16 11:58:00 +01:00
|
|
|
"\t" + str(nSiblings) + ",\n" +
|
2021-04-08 17:24:17 +02:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
"\t{\n")
|
|
|
|
|
2021-03-15 15:02:26 +01:00
|
|
|
if 'siblings' in PlanesObjects[p]:
|
2021-03-15 12:44:15 +01:00
|
|
|
|
2021-03-18 16:34:43 +01:00
|
|
|
i = 0
|
|
|
|
|
2021-03-15 15:02:26 +01:00
|
|
|
for side in PlanesObjects[p]['siblings']:
|
2021-03-18 16:34:43 +01:00
|
|
|
|
2021-03-15 15:02:26 +01:00
|
|
|
for sibling in PlanesObjects[p]['siblings'][side]:
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("\t\t&" + fileName + "_node" + CleanName(sibling) )
|
2021-03-18 16:34:43 +01:00
|
|
|
|
|
|
|
if i < ( nSiblings - 1 ) :
|
|
|
|
|
|
|
|
f.write(",")
|
|
|
|
|
|
|
|
i += 1
|
|
|
|
|
|
|
|
f.write("\n")
|
|
|
|
|
2021-03-15 15:02:26 +01:00
|
|
|
else:
|
2021-03-18 19:21:40 +01:00
|
|
|
f.write("\t\t0\n")
|
2021-03-15 15:02:26 +01:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
f.write("\t}\n" +
|
2021-04-08 17:24:17 +02:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
"};\n\n")
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
# Feed to level_symbols
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "SIBLINGS " + fileName + "_node" + pName + "_siblings" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-03-18 19:21:40 +01:00
|
|
|
# Write CHILDREN static objects structure
|
2021-03-15 12:44:15 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("CHILDREN " + fileName + "_node" + pName + "_objects = {\n")
|
2021-03-15 12:44:15 +01:00
|
|
|
|
2021-03-15 15:02:26 +01:00
|
|
|
if 'objects' in PlanesObjects[p]:
|
2021-03-15 12:44:15 +01:00
|
|
|
|
2021-03-15 15:02:26 +01:00
|
|
|
f.write("\t" + str(len(PlanesObjects[p]['objects'])) + ",\n" +
|
|
|
|
"\t{\n")
|
2021-03-18 16:34:43 +01:00
|
|
|
|
|
|
|
i = 0
|
|
|
|
|
2021-03-15 15:02:26 +01:00
|
|
|
for obj in PlanesObjects[p]['objects']:
|
2021-03-15 12:44:15 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write( "\t\t&" + fileName + "_mesh" + CleanName(obj))
|
2021-03-18 16:34:43 +01:00
|
|
|
|
|
|
|
if i < len(PlanesObjects[p]['objects']) - 1:
|
|
|
|
|
|
|
|
f.write(",")
|
|
|
|
|
|
|
|
i += 1
|
|
|
|
|
|
|
|
f.write("\n")
|
2021-03-15 15:02:26 +01:00
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
f.write("\t0,\n" +
|
2021-03-18 16:34:43 +01:00
|
|
|
"\t{\n\t\t0\n")
|
2021-03-15 15:02:26 +01:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
f.write("\t}\n" +
|
|
|
|
"};\n\n")
|
2021-03-18 19:21:40 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
# Feed to level_symbols
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "CHILDREN " + fileName + "_node" + pName + "_objects" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-03-18 19:21:40 +01:00
|
|
|
# Write CHILDREN rigidbodies structure
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("CHILDREN " + fileName + "_node" + pName + "_rigidbodies = {\n")
|
2021-03-18 19:21:40 +01:00
|
|
|
|
|
|
|
if 'rigidbodies' in PlanesRigidBodies[p]:
|
|
|
|
|
|
|
|
f.write("\t" + str(len(PlanesRigidBodies[p]['rigidbodies'])) + ",\n" +
|
|
|
|
"\t{\n")
|
|
|
|
|
|
|
|
i = 0
|
|
|
|
|
|
|
|
for obj in PlanesRigidBodies[p]['rigidbodies']:
|
2021-03-15 12:44:15 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write( "\t\t&" + fileName + "_mesh" + CleanName(obj))
|
2021-03-18 19:21:40 +01:00
|
|
|
|
|
|
|
if i < len(PlanesRigidBodies[p]['rigidbodies']) - 1:
|
|
|
|
|
|
|
|
f.write(",")
|
|
|
|
|
|
|
|
i += 1
|
|
|
|
|
|
|
|
f.write("\n")
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
f.write("\t0,\n" +
|
|
|
|
"\t{\n\t\t0\n")
|
|
|
|
|
|
|
|
f.write("\t}\n" +
|
|
|
|
"};\n\n")
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
# Feed to level_symbols
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "CHILDREN " + fileName + "_node" + pName + "_rigidbodies" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
# Write NODE structure
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write( "NODE " + fileName + "_node" + pName + " = {\n" +
|
2021-04-08 17:24:17 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
"\t&" + fileName + "_mesh" + pName + ",\n" +
|
2021-04-08 17:24:17 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
"\t&" + fileName + "_node" + pName + "_siblings,\n" +
|
2021-04-08 17:24:17 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
"\t&" + fileName + "_node" + pName + "_objects,\n" +
|
2021-04-08 17:24:17 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
"\t&" + fileName + "_node" + pName + "_rigidbodies\n" +
|
2021-04-08 17:24:17 +02:00
|
|
|
|
2021-03-15 12:44:15 +01:00
|
|
|
"};\n\n" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
# Feed to level_symbols
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "NODE " + fileName + "_node" + pName )
|
2021-04-08 17:24:17 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("MESH * " + fileName + "_actorPtr = &" + fileName + "_mesh" + CleanName(actorPtr) + ";\n")
|
2021-03-24 11:33:09 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("MESH * " + fileName + "_levelPtr = &" + fileName + "_mesh" + CleanName(levelPtr) + ";\n")
|
2021-03-24 11:33:09 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("MESH * " + fileName + "_propPtr = &" + fileName + "_mesh" + propPtr + ";\n\n")
|
2021-03-24 11:33:09 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("CAMANGLE * " + fileName + "_camPtr = &" + fileName + "_camAngle_" + CleanName(defaultCam) + ";\n\n")
|
2021-03-24 11:33:09 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
f.write("NODE * " + fileName + "_curNode = &" + fileName + "_node" + CleanName(nodePtr) + ";\n\n")
|
2021-03-12 12:13:08 +01:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
# Feed to level_symbols
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "MESH * " + fileName + "_actorPtr" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "MESH * " + fileName + "_levelPtr" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "MESH * " + fileName + "_propPtr" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "CAMANGLE * " + fileName + "_camPtr" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "NODE * " + fileName + "_curNode" )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-15 18:10:34 +02:00
|
|
|
# Write LEVEL struct
|
|
|
|
|
|
|
|
f.write(
|
|
|
|
|
|
|
|
"LEVEL " + fileName + " = {\n" +
|
|
|
|
|
|
|
|
"\t&" + fileName + "_cmat,\n" +
|
|
|
|
|
|
|
|
"\t&" + fileName + "_lgtmat,\n" +
|
|
|
|
|
|
|
|
"\t&" + fileName + "_meshes,\n" +
|
|
|
|
|
|
|
|
"\t&" + fileName + "_meshes_length,\n" +
|
|
|
|
|
|
|
|
"\t&" + fileName + "_mesh" + CleanName(actorPtr)+ ",\n" +
|
|
|
|
|
|
|
|
"\t&" + fileName + "_mesh" + CleanName(levelPtr)+ ",\n" +
|
|
|
|
|
|
|
|
"\t&" + fileName + "_mesh" + propPtr + ",\n" +
|
|
|
|
|
|
|
|
"\t&" + fileName + "_camAngle_" + CleanName(defaultCam) + ",\n" +
|
|
|
|
|
|
|
|
"\t&" + fileName + "_camPath,\n" +
|
|
|
|
|
|
|
|
"\t&" + fileName + "_camAngles,\n" +
|
|
|
|
|
|
|
|
"\t&" + fileName + "_node" + CleanName(nodePtr) + ",\n" +
|
|
|
|
|
|
|
|
"\t&" + fileName + "_meshPlan\n" +
|
|
|
|
|
|
|
|
"};\n\n")
|
|
|
|
|
2021-03-12 13:06:21 +01:00
|
|
|
# Set default camera back in Blender
|
|
|
|
|
2021-03-12 11:21:18 +01:00
|
|
|
if defaultCam != 'NULL':
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-03-31 20:28:02 +02:00
|
|
|
bpy.context.scene.camera = bpy.data.objects[ defaultCam ]
|
2021-03-12 11:21:18 +01:00
|
|
|
|
2020-12-27 17:13:58 +01:00
|
|
|
f.close()
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2021-04-08 17:24:17 +02:00
|
|
|
|
|
|
|
# Using a UGLY method here , sorry !
|
|
|
|
# We're re-opening the file we just closed to substracts some values that were not available
|
|
|
|
# Fill in node in MESH structs
|
|
|
|
|
|
|
|
# Get the file content
|
|
|
|
|
2021-04-12 14:50:44 +02:00
|
|
|
f = open(os.path.normpath(level_c),"r")
|
2021-04-08 17:24:17 +02:00
|
|
|
|
|
|
|
filedata = f.read()
|
|
|
|
|
|
|
|
f.close()
|
|
|
|
|
|
|
|
# Declare LvlPlanes nodes to avoid declaration dependency issues
|
|
|
|
|
|
|
|
# Constuct and store the new string
|
|
|
|
|
|
|
|
Node_declaration = ''
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
|
|
|
|
|
2021-04-08 17:24:17 +02:00
|
|
|
for k in LvlPlanes.keys():
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
Node_declaration += "NODE " + fileName + "_node" + CleanName(k) + ";\n\n"
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
level_symbols.append( "NODE " + fileName + "_node" + CleanName(k) )
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
# Do the substitution only once
|
|
|
|
|
|
|
|
newdata = filedata.replace("NODE_DECLARATION\n", Node_declaration, 1)
|
2021-04-08 17:24:17 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
newdata = filedata.replace("NODE_DECLARATION\n", "")
|
2021-04-08 17:24:17 +02:00
|
|
|
|
|
|
|
# Now substitute mesh name for corresponding plane's NODE
|
|
|
|
|
|
|
|
for moveable in PropPlane:
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
newdata = newdata.replace("subs_" + moveable.name, "&" + fileName + "_node" + PropPlane[moveable])
|
2021-04-08 17:24:17 +02:00
|
|
|
|
|
|
|
# Subsitute mesh name with 0 in the other MESH structs
|
|
|
|
|
|
|
|
newdata = sub("(?m)^\tsubs_.*$", "\t0,", newdata )
|
|
|
|
|
|
|
|
# Open and write file
|
|
|
|
|
2021-04-12 14:50:44 +02:00
|
|
|
f = open(os.path.normpath(level_c),"w")
|
2021-04-08 17:24:17 +02:00
|
|
|
|
2021-04-12 14:50:44 +02:00
|
|
|
f.write( newdata )
|
2021-04-08 17:24:17 +02:00
|
|
|
|
|
|
|
f.close()
|
|
|
|
|
2021-04-12 14:50:44 +02:00
|
|
|
|
|
|
|
## Level forward declarations (level.h)
|
|
|
|
|
|
|
|
h = open(os.path.normpath(level_h),"w+")
|
|
|
|
|
|
|
|
h.write(
|
|
|
|
|
|
|
|
'#pragma once\n\n' +
|
|
|
|
|
|
|
|
'#include "../custom_types.h"\n\n'
|
|
|
|
|
|
|
|
)
|
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
for symbol in level_symbols:
|
2021-04-12 14:50:44 +02:00
|
|
|
|
2021-04-13 16:49:26 +02:00
|
|
|
h.write( "extern " + symbol + ";\n\n")
|
2021-04-12 14:50:44 +02:00
|
|
|
|
|
|
|
h.close()
|
|
|
|
|
2020-12-27 17:13:58 +01:00
|
|
|
return {'FINISHED'};
|
|
|
|
|
|
|
|
def menu_func(self, context):
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2020-12-27 17:13:58 +01:00
|
|
|
self.layout.operator(ExportMyFormat.bl_idname, text="PSX Format(.c)");
|
|
|
|
|
|
|
|
def register():
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2020-12-27 17:13:58 +01:00
|
|
|
bpy.utils.register_module(__name__);
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2020-12-27 17:13:58 +01:00
|
|
|
bpy.types.INFO_MT_file_export.append(menu_func);
|
|
|
|
|
|
|
|
def unregister():
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2020-12-27 17:13:58 +01:00
|
|
|
bpy.utils.unregister_module(__name__);
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2020-12-27 17:13:58 +01:00
|
|
|
bpy.types.INFO_MT_file_export.remove(menu_func);
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2021-03-12 13:06:21 +01:00
|
|
|
|
2020-12-27 17:13:58 +01:00
|
|
|
register()
|