def __gather_node(channels: typing.Tuple[bpy.types.FCurve],
                  blender_object: bpy.types.Object,
                  export_settings,
                  bake_bone: typing.Union[str, None],
                  driver_obj
                  ) -> gltf2_io.Node:

    if driver_obj is not None:
        return gltf2_blender_gather_nodes.gather_node(driver_obj,
            driver_obj.library.name if driver_obj.library else None,
            None, None, export_settings)

    if blender_object.type == "ARMATURE":
        # TODO: get joint from fcurve data_path and gather_joint

        if bake_bone is not None:
            blender_bone = blender_object.pose.bones[bake_bone]
        else:
            blender_bone = blender_object.path_resolve(channels[0].data_path.rsplit('.', 1)[0])

        if isinstance(blender_bone, bpy.types.PoseBone):
            if export_settings["gltf_def_bones"] is False:
                obj = blender_object.proxy if blender_object.proxy else blender_object
                return gltf2_blender_gather_joints.gather_joint(obj, blender_bone, export_settings)
            else:
                bones, _, _ = gltf2_blender_gather_skins.get_bone_tree(None, blender_object)
                if blender_bone.name in [b.name for b in bones]:
                    obj = blender_object.proxy if blender_object.proxy else blender_object
                    return gltf2_blender_gather_joints.gather_jointb(obj, blender_bone, export_settings)

    return gltf2_blender_gather_nodes.gather_node(blender_object,
        blender_object.library.name if blender_object.library else None,
        None, None, export_settings)
def __gather_scene(blender_scene, export_settings):
    scene = gltf2_io.Scene(
        extensions=None,
        extras=__gather_extras(blender_scene, export_settings),
        name=blender_scene.name,
        nodes=[]
    )


    vtree = gltf2_blender_gather_tree.VExportTree(export_settings)
    vtree.construct(blender_scene)
    vtree.search_missing_armature() # In case armature are no parented correctly

    export_user_extensions('vtree_before_filter_hook', export_settings, vtree)

    # Now, we can filter tree if needed
    vtree.filter()

    export_user_extensions('vtree_after_filter_hook', export_settings, vtree)

    export_settings['vtree'] = vtree

    for r in [vtree.nodes[r] for r in vtree.roots]:
        node = gltf2_blender_gather_nodes.gather_node(
            r, export_settings)
        if node is not None:
            scene.nodes.append(node)

    export_user_extensions('gather_scene_hook', export_settings, scene, blender_scene)

    return scene
Example #3
0
def __gather_animations(blender_scene, export_settings):
    animations = []
    for blender_object in blender_scene.objects:
        # First check if this object is exported or not. Do not export animation of not exported object
        obj_node = gltf2_blender_gather_nodes.gather_node(blender_object, blender_scene, export_settings)
        if obj_node is not None:
            animations += gltf2_blender_gather_animations.gather_animations(blender_object, export_settings)
    return animations
def __gather_node(channels: typing.Tuple[bpy.types.FCurve],
                  blender_object: bpy.types.Object,
                  export_settings
                  ) -> gltf2_io.Node:
    if blender_object.type == "ARMATURE":
        # TODO: get joint from fcurve data_path and gather_joint
        blender_bone = blender_object.path_resolve(channels[0].data_path.rsplit('.', 1)[0])
        return gltf2_blender_gather_joints.gather_joint(blender_bone, export_settings)

    return gltf2_blender_gather_nodes.gather_node(blender_object, export_settings)
Example #5
0
def __gather_scene(blender_scene, export_settings):
    scene = gltf2_io.Scene(
        extensions=None,
        extras=__gather_extras(blender_scene, export_settings),
        name=None,
        nodes=[]
    )
    for _blender_object in [obj for obj in blender_scene.objects if obj.proxy is None]:
        if _blender_object.type == "ARMATURE": # extract the root bone from the armature
            armature = _blender_object
            blender_object = _blender_object.proxy if _blender_object.proxy else _blender_object
            for bone in blender_object.pose.bones: # sometimes there can be more than one bone at root level
                if bone.parent is None:
                    joint = gltf2_blender_gather_joints.gather_joint(blender_object, bone, export_settings)
                    if joint is not None:
                        scene.nodes.append(joint)
        elif _blender_object.type == "MESH":
            if _blender_object.parent is None: # skip if the object is not a child
                continue
            if _blender_object.parent.parent is None: # add skinned meshes and meshes with a parent bone to the scene
                blender_object = _blender_object.proxy if _blender_object.proxy else _blender_object
                modifiers = {m.type: m for m in blender_object.modifiers}
                if ("ARMATURE" not in modifiers or modifiers["ARMATURE"].object is None) and not blender_object.parent_bone == "": # for some reason the value for no parent bone is an empty string instead of None
                    continue
                node = gltf2_blender_gather_nodes.gather_node(
                    blender_object,
                    blender_object.library.name if blender_object.library else None,
                    blender_scene, None, export_settings)
                if node is not None:
                    scene.nodes.append(node)
        elif _blender_object.type == "EMPTY": # in rare cases where there is more than one root bone, if there is an empty that is a direct child of an armature and has no parent bone, we export it 
            if _blender_object.parent_bone == "" and _blender_object.parent.parent is None:
                blender_object = _blender_object.proxy if _blender_object.proxy else _blender_object
                node = gltf2_blender_gather_nodes.gather_node(
                    blender_object,
                    blender_object.library.name if blender_object.library else None,
                    blender_scene, None, export_settings)
                if node is not None:
                    scene.nodes.append(node)

    export_user_extensions('gather_scene_hook', export_settings, scene, blender_scene)

    return scene
def __gather_node(channels: typing.Tuple[bpy.types.FCurve],
                  blender_object: bpy.types.Object,
                  export_settings
                  ) -> gltf2_io.Node:
    if blender_object.type == "ARMATURE":
        # TODO: get joint from fcurve data_path and gather_joint
        blender_bone = blender_object.path_resolve(channels[0].data_path.rsplit('.', 1)[0])
        if isinstance(blender_bone, bpy.types.PoseBone):
            return gltf2_blender_gather_joints.gather_joint(blender_bone, export_settings)

    return gltf2_blender_gather_nodes.gather_node(blender_object, export_settings)
def gather_node_property(export_settings, blender_object, target,
                         property_name, property_definition, hubs_config):
    blender_object = getattr(target, property_name)

    if blender_object:
        return gltf2_blender_gather_nodes.gather_node(
            blender_object,
            blender_object.library.name if blender_object.library else None,
            blender_object.users_scene[0], None, export_settings)
    else:
        return None
Example #8
0
def __gather_animations(blender_scene, anim_scene, export_settings):
    for _blender_object in blender_scene.objects:

        blender_object = _blender_object.proxy if _blender_object.proxy else _blender_object

        # First check if this object is exported or not. Do not export animation of not exported object
        obj_node = gltf2_blender_gather_nodes.gather_node(blender_object,
            blender_object.library.name if blender_object.library else None,
            blender_scene, None, export_settings)

    animations = gltf2_blender_gather_animations.gather_animations(anim_scene, export_settings)
    return animations
Example #9
0
def gather_node_property(export_settings, blender_object, target,
                         property_name, property_definition, hubs_config):
    blender_object = getattr(target, property_name)

    if blender_object:
        node = gltf2_blender_gather_nodes.gather_node(
            blender_object,
            blender_object.library.name if blender_object.library else None,
            blender_object.users_scene[0], None, export_settings)

        return {"__mhc_link_type": "node", "index": node}
    else:
        return None
Example #10
0
def __gather_scene(blender_scene, export_settings):
    scene = gltf2_io.Scene(
        extensions=None,
        extras=__gather_extras(blender_scene, export_settings),
        name=blender_scene.name,
        nodes=[]
    )

    for blender_object in blender_scene.objects:
        if blender_object.parent is None:
            node = gltf2_blender_gather_nodes.gather_node(blender_object, blender_scene, export_settings)
            if node is not None:
                scene.nodes.append(node)

    return scene
def __gather_scene(blender_scene, export_settings):
    scene = gltf2_io.Scene(
        extensions=None,
        extras=__gather_extras(blender_scene, export_settings),
        name=blender_scene.name,
        nodes=[]
    )

    for blender_object in blender_scene.objects:
        if blender_object.parent is None:
            node = gltf2_blender_gather_nodes.gather_node(blender_object, export_settings)
            if node is not None:
                scene.nodes.append(node)

    return scene
def __gather_node(channels: typing.Tuple[bpy.types.FCurve],
                  blender_object: bpy.types.Object,
                  export_settings,
                  bake_bone: typing.Union[str, None]
                  ) -> gltf2_io.Node:
    if blender_object.type == "ARMATURE":
        # TODO: get joint from fcurve data_path and gather_joint

        if bake_bone is not None:
            blender_bone = blender_object.pose.bones[bake_bone]
        else:
            blender_bone = blender_object.path_resolve(channels[0].data_path.rsplit('.', 1)[0])

        if isinstance(blender_bone, bpy.types.PoseBone):
            return gltf2_blender_gather_joints.gather_joint(blender_bone, export_settings)

    return gltf2_blender_gather_nodes.gather_node(blender_object, None, export_settings)
def __gather_scene(blender_scene, export_settings):
    scene = gltf2_io.Scene(extensions=None,
                           extras=None,
                           name=blender_scene.name,
                           nodes=[])

    for blender_object in blender_scene.objects:
        if blender_object.parent is None:
            node = gltf2_blender_gather_nodes.gather_node(
                blender_object, export_settings)
            if node is not None:
                scene.nodes.append(node)

    # TODO: materials, textures, images
    # TODO: animations
    # TODO: lights
    # TODO: asset?

    return scene
Example #14
0
def __gather_animations(blender_scene, export_settings):
    animations = []
    for blender_object in blender_scene.objects:
        # First check if this object is exported or not. Do not export animation of not exported object
        obj_node = gltf2_blender_gather_nodes.gather_node(
            blender_object, blender_scene, export_settings)
        if obj_node is not None:
            animations += gltf2_blender_gather_animations.gather_animations(
                blender_object, export_settings)

    # if none of those two actions have been selected,
    # let's merge indivudual animations into one single with multiple channels
    all_actions = export_settings['gltf_all_actions']
    nla_strips = export_settings['gltf_nla_strips']
    if not all_actions and not nla_strips:
        scene_animation = __merge_animations(blender_scene, animations,
                                             export_settings)
        animations = []
        animations.append(scene_animation)

    return animations
def __gather_scene(blender_scene, export_settings):
    scene = gltf2_io.Scene(
        extensions=None,
        extras=__gather_extras(blender_scene, export_settings),
        name=blender_scene.name,
        nodes=[]
    )

    for _blender_object in [obj for obj in blender_scene.objects if obj.proxy is None]:
        if _blender_object.parent is None:
            blender_object = _blender_object.proxy if _blender_object.proxy else _blender_object
            node = gltf2_blender_gather_nodes.gather_node(
                blender_object,
                blender_object.library.name if blender_object.library else None,
                blender_scene, None, export_settings)
            if node is not None:
                scene.nodes.append(node)

    export_user_extensions('gather_scene_hook', export_settings, scene, blender_scene)

    return scene
def __gather_materials(blender_scene, export_settings):
    materials = []

    for _blender_object in blender_scene.objects:
        blender_object = _blender_object.proxy if _blender_object.proxy else _blender_object

        # Check if this object is exclude from view layer
        node = gltf2_blender_gather_nodes.gather_node(
                blender_object,
                blender_object.library.name if blender_object.library else None,
                blender_scene, None, export_settings)
        if node is None:
            continue

        for slot in blender_object.material_slots:
            # Check if this slot as assigned material
            if slot.material is None:
                continue

            double_sided = not slot.material.use_backface_culling
            materials.append(gltf2_blender_gather_materials.gather_material(slot.material, double_sided, export_settings))

    return materials
def __gather_animations(blender_scene, export_settings):
    animations = []
    merged_tracks = {}

    for _blender_object in blender_scene.objects:

        blender_object = _blender_object.proxy if _blender_object.proxy else _blender_object

        # First check if this object is exported or not. Do not export animation of not exported object
        obj_node = gltf2_blender_gather_nodes.gather_node(
            blender_object,
            blender_object.library.name if blender_object.library else None,
            blender_scene, None, export_settings)
        if obj_node is not None:
            # Check was done on armature, but use here the _proxy object, because this is where the animation is
            animations_, merged_tracks = gltf2_blender_gather_animations.gather_animations(
                _blender_object, merged_tracks, len(animations),
                export_settings)
            animations += animations_

    if export_settings['gltf_nla_strips'] is False:
        # Fake an animation with all animations of the scene
        merged_tracks = {}
        merged_tracks['Animation'] = []
        for idx, animation in enumerate(animations):
            merged_tracks['Animation'].append(idx)

    to_delete_idx = []
    for merged_anim_track in merged_tracks.keys():
        if len(merged_tracks[merged_anim_track]) < 2:

            # There is only 1 animation in the track
            # If name of the track is not a default name, use this name for action
            if len(merged_tracks[merged_anim_track]) != 0:
                animations[merged_tracks[merged_anim_track]
                           [0]].name = merged_anim_track

            continue

        base_animation_idx = None
        offset_sampler = 0

        for idx, anim_idx in enumerate(merged_tracks[merged_anim_track]):
            if idx == 0:
                base_animation_idx = anim_idx
                animations[anim_idx].name = merged_anim_track
                already_animated = []
                for channel in animations[anim_idx].channels:
                    already_animated.append(
                        (channel.target.node, channel.target.path))
                continue

            to_delete_idx.append(anim_idx)

            # Merging extras
            # Warning, some values can be overwritten if present in multiple merged animations
            if animations[anim_idx].extras is not None:
                for k in animations[anim_idx].extras.keys():
                    if animations[base_animation_idx].extras is None:
                        animations[base_animation_idx].extras = {}
                    animations[base_animation_idx].extras[k] = animations[
                        anim_idx].extras[k]

            offset_sampler = len(animations[base_animation_idx].samplers)
            for sampler in animations[anim_idx].samplers:
                animations[base_animation_idx].samplers.append(sampler)

            for channel in animations[anim_idx].channels:
                if (channel.target.node,
                        channel.target.path) in already_animated:
                    print_console(
                        "WARNING",
                        "Some strips have same channel animation ({}), on node {} !"
                        .format(channel.target.path, channel.target.node.name))
                    continue
                animations[base_animation_idx].channels.append(channel)
                animations[base_animation_idx].channels[
                    -1].sampler = animations[base_animation_idx].channels[
                        -1].sampler + offset_sampler
                already_animated.append(
                    (channel.target.node, channel.target.path))

    new_animations = []
    if len(to_delete_idx) != 0:
        for idx, animation in enumerate(animations):
            if idx in to_delete_idx:
                continue
            new_animations.append(animation)
    else:
        new_animations = animations

    return new_animations
def __gather_animations(blender_scene, export_settings):
    animations = []
    merged_tracks = {}

    for blender_object in blender_scene.objects:
        # First check if this object is exported or not. Do not export animation of not exported object
        obj_node = gltf2_blender_gather_nodes.gather_node(
            blender_object, blender_scene, export_settings)
        if obj_node is not None:
            animations_, merged_tracks = gltf2_blender_gather_animations.gather_animations(
                blender_object, merged_tracks, len(animations),
                export_settings)
            animations += animations_

    if export_settings['gltf_nla_strips'] is False:
        # Fake an animation witha all animations of the scene
        merged_tracks = {}
        merged_tracks['Animation'] = []
        for idx, animation in enumerate(animations):
            merged_tracks['Animation'].append(idx)

    to_delete_idx = []
    for merged_anim_track in merged_tracks.keys():
        if len(merged_tracks[merged_anim_track]) < 2:
            continue

        base_animation_idx = None
        offset_sampler = 0

        for idx, anim_idx in enumerate(merged_tracks[merged_anim_track]):
            if idx == 0:
                base_animation_idx = anim_idx
                animations[anim_idx].name = merged_anim_track
                already_animated = []
                for channel in animations[anim_idx].channels:
                    already_animated.append(
                        (channel.target.node, channel.target.path))
                continue

            to_delete_idx.append(anim_idx)

            offset_sampler = len(animations[base_animation_idx].samplers)
            for sampler in animations[anim_idx].samplers:
                animations[base_animation_idx].samplers.append(sampler)

            for channel in animations[anim_idx].channels:
                if (channel.target.node,
                        channel.target.path) in already_animated:
                    print_console(
                        "WARNING",
                        "Some strips have same channel animation ({}), on node {} !"
                        .format(channel.target.path, channel.target.node.name))
                    continue
                animations[base_animation_idx].channels.append(channel)
                animations[base_animation_idx].channels[
                    -1].sampler = animations[base_animation_idx].channels[
                        -1].sampler + offset_sampler
                already_animated.append(
                    (channel.target.node, channel.target.path))

    new_animations = []
    if len(to_delete_idx) != 0:
        for idx, animation in enumerate(animations):
            if idx in to_delete_idx:
                continue
            new_animations.append(animation)
    else:
        new_animations = animations

    return new_animations
def __gather_node(action_group: bpy.types.ActionGroup,
                  blender_object: bpy.types.Object,
                  export_settings) -> gltf2_io.Node:
    return gltf2_blender_gather_nodes.gather_node(blender_object,
                                                  export_settings)