pablodp606 / keymesh-addon

GNU General Public License v3.0
128 stars 13 forks source link

Question: Getting material names for each key frame (writing an exporter) #15

Open ncthbrt opened 3 years ago

ncthbrt commented 3 years ago

Hi there, also ccing in @AldrinMathew, this is not an issue so much as a question. I've been writing an exporter for keymesh for use in Unity, and I've stumbled into a problem where I'm trying to get the list of materials names used each keyframe. The problem seems to be that this list isn't updated with all the materials when I iterate across it in the exporter. I'm not entirely sure how to solve this or even why it's happenening. The output is also currently dependent on what frame is selected in the scrubber.

Below is some of my exporter code:

class KeyframeMeshObjExport(bpy.types.Operator, ExportHelper):
    bl_idname = "object.keyframe_mesh_obj"       
    bl_label = "Export Obj Sequence"
    bl_options = {'REGISTER'}   
    filename_ext = ".obj"

    @classmethod
    def poll(cls, context): 
        # It's a Keymesh scene
        for o in bpy.context.selected_objects: 
            if "km_datablock" and "km_id" in o:
                return True
        return False

    def execute(self, context):
        frame_end = -99999
        frame_start = 99999
        current_frame = bpy.context.scene.frame_current
        obs = list(bpy.context.selected_objects)

        objects = []

        framerate = 11 
        # Get length of the current action
        for o in obs:
            framerate = o.users_scene[0].render.fps
            this_end = o.users_scene[0].frame_end
            this_start = o.users_scene[0].frame_start
            if(this_end > frame_end): 
                frame_end = this_end
            if(this_start < frame_start): 
                frame_start = this_start

        file_path = Path(self.filepath)
        folder_path = file_path.parent        
        materials = {}

        bpy.ops.object.select_all(action='DESELECT')

        for o in obs:
            keyframes=[]
            o.select_set(True)
            object_material_slots={}        
            for i in range(frame_start, frame_end + 1): 
                bpy.context.scene.frame_current = i
                km_frame_handler(0)
                updateKeymesh(bpy.context.scene)
                dirty = False

                fcurves = o.animation_data.action.fcurves
                for fcurve in fcurves:
                    if fcurve.data_path != '["km_datablock"]':
                        continue                

                    for keyframe in fcurve.keyframe_points:
                        if i == int(keyframe.co.x):                            
                            dirty = True
                            break

                if dirty:        
                    frame_materials=[]                    
                    # The line in question that doesn't seem to be updating:
                    for mat in o.material_slots:
                        materials[mat.name] = True        
                        object_material_slots[mat.name] = True
                        frame_materials.append(mat.name)
                    keyframes.append({"frame":i, "materials": list(frame_materials) })
                    filename = str(Path(str(folder_path.absolute()) +"/" + re.sub(r'\.obj$',"_",file_path.name) + o.name + "_" + str(i) + ".obj").absolute())
                    bpy.ops.export_scene.obj(filepath=filename, use_materials=True, use_selection=True, use_blen_objects=True, group_by_object=True)

            o.select_set(False)

            objects.append({
                "name": o.name,
                "keyframes": list(keyframes),
                "materials": list(object_material_slots.keys())
            })        

        json_data_filename = str(Path(str(folder_path.absolute()) +"/" + file_path.name + ".objseq").absolute())

        with open(json_data_filename, 'w') as outfile:
            json.dump({ 
                "materials": list(materials.keys()), 
                "frame_start": frame_start,
                "frame_end": frame_end,
                "frame_rate": framerate,
                "objects": list(objects)
            }, outfile)

        bpy.context.scene.frame_current = current_frame
        km_frame_handler(0)

        return {'FINISHED'}

This is the output of this script in an example project I'm working on. There should be five materials in frame 63, but only three show up. The actual exported obj has space for 5 materials:

{
    "materials": [
        "EggMaterial",
        "GooMaterial",
        "PlantMaterial"
    ],
    "frame_start": 1,
    "frame_end": 80,
    "frame_rate": 24,
    "objects": [
        {
            "name": "Sphere",
            "keyframes": [
                {
                    "frame": 1,
                    "materials": [
                        "EggMaterial"
                    ]
                },
                {
                    "frame": 3,
                    "materials": [
                        "EggMaterial"
                    ]
                },
                {
                    "frame": 5,
                    "materials": [
                        "EggMaterial"
                    ]
                },
                {
                    "frame": 7,
                    "materials": [
                        "EggMaterial"
                    ]
                },
                {
                    "frame": 9,
                    "materials": [
                        "EggMaterial"
                    ]
                },
                {
                    "frame": 11,
                    "materials": [
                        "EggMaterial",
                        "GooMaterial"
                    ]
                },
                {
                    "frame": 13,
                    "materials": [
                        "EggMaterial",
                        "GooMaterial"
                    ]
                },
                {
                    "frame": 15,
                    "materials": [
                        "EggMaterial",
                        "GooMaterial"
                    ]
                },
                {
                    "frame": 17,
                    "materials": [
                        "EggMaterial",
                        "GooMaterial"
                    ]
                },
                {
                    "frame": 19,
                    "materials": [
                        "EggMaterial",
                        "GooMaterial"
                    ]
                },
                {
                    "frame": 21,
                    "materials": [
                        "EggMaterial",
                        "GooMaterial"
                    ]
                },
                {
                    "frame": 23,
                    "materials": [
                        "EggMaterial",
                        "GooMaterial"
                    ]
                },
                {
                    "frame": 25,
                    "materials": [
                        "EggMaterial",
                        "GooMaterial"
                    ]
                },
                {
                    "frame": 27,
                    "materials": [
                        "EggMaterial",
                        "GooMaterial"
                    ]
                },
                {
                    "frame": 29,
                    "materials": [
                        "EggMaterial",
                        "GooMaterial"
                    ]
                },
                {
                    "frame": 31,
                    "materials": [
                        "EggMaterial",
                        "GooMaterial"
                    ]
                },
                {
                    "frame": 51,
                    "materials": [
                        "EggMaterial",
                        "GooMaterial"
                    ]
                },
                {
                    "frame": 53,
                    "materials": [
                        "EggMaterial",
                        "GooMaterial"
                    ]
                },
                {
                    "frame": 55,
                    "materials": [
                        "EggMaterial",
                        "GooMaterial",
                        "PlantMaterial"
                    ]
                },
                {
                    "frame": 57,
                    "materials": [
                        "EggMaterial",
                        "GooMaterial",
                        "PlantMaterial"
                    ]
                },
                {
                    "frame": 59,
                    "materials": [
                        "EggMaterial",
                        "GooMaterial",
                        "PlantMaterial"
                    ]
                },
                {
                    "frame": 61,
                    "materials": [
                        "EggMaterial",
                        "GooMaterial",
                        "PlantMaterial"
                    ]
                },
                {
                    "frame": 63,
                    "materials": [
                        "EggMaterial",
                        "GooMaterial",
                        "PlantMaterial"
                    ]
                }
            ],
            "materials": [
                "EggMaterial",
                "GooMaterial",
                "PlantMaterial"
            ]
        }
    ]
}