fixed recursive build script
[carveJwlIkooP6JGAAIwe30JlM.git] / blender_export.py
index edb758fa64c60ff84c5c9f87c97c3fa19a755f97..86b65410919ff61854517a805ca73b096bafa84a 100644 (file)
@@ -1,3 +1,7 @@
+#
+# Copyright (C) 2021-2022 Mt.ZERO Software, Harry Godden - All Rights Reserved
+#
+
 import bpy, math, gpu
 import cProfile
 from ctypes import *
@@ -132,8 +136,7 @@ class classtype_route_node(Structure):
 
 class classtype_route(Structure):
    _pack_ = 1
-   _fields_ = [("pstr_name",c_uint32),
-               ("id_start",c_uint32),
+   _fields_ = [("id_start",c_uint32),
                ("colour",c_float*3)]
 
 class classtype_skin(Structure):
@@ -154,6 +157,8 @@ class classtype_bone(Structure):
                ("ik_target",c_uint32),
                ("ik_pole",c_uint32),
                ("collider",c_uint32),
+               ("use_limits",c_uint32),
+               ("angle_limits",(c_float*3)*2),
                ("hitbox",(c_float*3)*2)]
 
 # Exporter
@@ -203,6 +208,9 @@ def write_model(collection_name):
    def emplace_material( mat ):
       nonlocal material_cache, material_buffer
 
+      if mat == None:
+         return 0
+
       if mat.name in material_cache:
          return material_cache[mat.name]
 
@@ -393,7 +401,9 @@ def write_model(collection_name):
          can_use_cache = True
 
          for mod in obj.modifiers:
-            if mod.type == 'DATA_TRANSFER' or mod.type == 'SHRINKWRAP':
+            if mod.type == 'DATA_TRANSFER' or mod.type == 'SHRINKWRAP' or \
+               mod.type == 'BOOLEAN' or mod.type == 'CURVE' or \
+               mod.type == 'ARRAY':
                can_use_cache = False
 
             if mod.type == 'ARMATURE':
@@ -469,7 +479,11 @@ def write_model(collection_name):
                   # WEight groups
                   #
                   if armature_def:
-                     weight_groups = sorted( data.vertices[vi].groups, key = \
+                     src_groups = [_ for _ in data.vertices[vi].groups \
+                                 if obj.vertex_groups[_.group].name in \
+                                    armature_def['bones']]
+
+                     weight_groups = sorted( src_groups, key = \
                                              lambda a: a.weight, reverse=True )
                      tot = 0.0
                      for ml in range(3):
@@ -651,12 +665,25 @@ def write_model(collection_name):
                         for pb in armature.pose.bones:
                            if pb.name == bone_name:
                               rb = armature.data.bones[ bone_name ]
-
-                              loc, rot, sca = pb.matrix_basis.decompose()
+                              
+                              # relative bone matrix
+                              if rb.parent is not None:
+                                 offset_mtx = rb.parent.matrix_local
+                                 offset_mtx = offset_mtx.inverted_safe() @ \
+                                              rb.matrix_local
+
+                                 inv_parent = pb.parent.matrix @ offset_mtx
+                                 inv_parent.invert_safe()
+                                 fpm = inv_parent @ pb.matrix 
+                              else:
+                                 bone_mtx = rb.matrix.to_4x4()
+                                 local_inv = rb.matrix_local.inverted_safe()
+                                 fpm = bone_mtx @ local_inv @ pb.matrix
+
+                              loc, rot, sca = fpm.decompose()
 
                               # local position
-                              vp = rb.matrix @ loc
-                              final_pos = Vector(( vp[0], vp[2], -vp[1] ))
+                              final_pos = Vector(( loc[0], loc[2], -loc[1] ))
 
                               # rotation
                               lc_m = pb.matrix_channel.to_3x3()
@@ -725,6 +752,23 @@ def write_model(collection_name):
             bone.hitbox[1][1] = 0.0
             bone.hitbox[1][2] = 0.0
 
+         if obj.cv_data.con0:
+            bone.use_limits = 1 
+            bone.angle_limits[0][0] =  obj.cv_data.mins[0]
+            bone.angle_limits[0][1] =  obj.cv_data.mins[2]
+            bone.angle_limits[0][2] = -obj.cv_data.maxs[1]
+            bone.angle_limits[1][0] =  obj.cv_data.maxs[0]
+            bone.angle_limits[1][1] =  obj.cv_data.maxs[2]
+            bone.angle_limits[1][2] = -obj.cv_data.mins[1]
+         else:
+            bone.use_limits = 0
+            bone.angle_limits[0][0] = 0.0
+            bone.angle_limits[0][1] = 0.0
+            bone.angle_limits[0][2] = 0.0
+            bone.angle_limits[1][0] = 0.0
+            bone.angle_limits[1][1] = 0.0
+            bone.angle_limits[1][2] = 0.0
+
          bone.deform = node_def['deform']
          entdata_buffer += [bone]
 
@@ -814,7 +858,6 @@ def write_model(collection_name):
          node.classtype = 9
          entdata_length += sizeof( classtype_route )
          r = classtype_route()
-         r.pstr_name = emplace_string("not-implemented")
          r.colour[0] = obj.cv_data.colour[0]
          r.colour[1] = obj.cv_data.colour[1]
          r.colour[2] = obj.cv_data.colour[2]
@@ -992,7 +1035,7 @@ def cv_draw():
    for obj in bpy.context.collection.objects:
       if obj.type == 'ARMATURE':
          for bone in obj.data.bones:
-            if bone.cv_data.collider:
+            if bone.cv_data.collider and obj.data.pose_position == 'REST':
                c = bone.head_local
                a = bone.cv_data.v0
                b = bone.cv_data.v1
@@ -1317,17 +1360,10 @@ class CV_BONE_SETTINGS(bpy.types.PropertyGroup):
    v0: bpy.props.FloatVectorProperty(name="v0",size=3)
    v1: bpy.props.FloatVectorProperty(name="v1",size=3)
 
+   con0: bpy.props.BoolProperty(name="Constriant 0",default=False)
    mins: bpy.props.FloatVectorProperty(name="mins",size=3)
    maxs: bpy.props.FloatVectorProperty(name="maxs",size=3)
 
-   con0: bpy.props.BoolProperty(name="Constriant 0",default=False)
-   c0: bpy.props.FloatVectorProperty(name="dir",size=3)
-   s0: bpy.props.FloatVectorProperty(name="limits",size=3)
-
-   con1: bpy.props.BoolProperty(name="Constriant 1",default=False)
-   c1: bpy.props.FloatVectorProperty(name="dir",size=3)
-   s1: bpy.props.FloatVectorProperty(name="limits",size=3)
-
 class CV_BONE_PANEL(bpy.types.Panel):
    bl_label="Bone Config"
    bl_idname="SCENE_PT_cv_bone"
@@ -1347,16 +1383,9 @@ class CV_BONE_PANEL(bpy.types.Panel):
       _.layout.prop( bone.cv_data, "v1" )
 
       _.layout.label( text="Angle Limits" )
+      _.layout.prop( bone.cv_data, "con0" )
       _.layout.prop( bone.cv_data, "mins" )
       _.layout.prop( bone.cv_data, "maxs" )
-      
-      _.layout.prop( bone.cv_data, "con0" )
-      _.layout.prop( bone.cv_data, "c0" )
-      _.layout.prop( bone.cv_data, "s0" )
-
-      _.layout.prop( bone.cv_data, "con1" )
-      _.layout.prop( bone.cv_data, "c1" )
-      _.layout.prop( bone.cv_data, "s1" )
 
 class CV_SCENE_SETTINGS(bpy.types.PropertyGroup):
    use_hidden: bpy.props.BoolProperty( name="use hidden", default=False )