add animation export option

refactor test scenes, able to run different configuration
This commit is contained in:
Jason0214
2018-08-10 15:50:50 -07:00
parent 82290bb1e0
commit 1f1b15ce39
71 changed files with 98 additions and 40 deletions

2
.gitignore vendored
View File

@@ -2,7 +2,7 @@
__pycache__
*.blend[0-9]
tests/godot_project/exports/*.escn
tests/godot_project/exports/*
.import
*.import

View File

@@ -82,7 +82,7 @@ class ExportGodot(bpy.types.Operator, ExportHelper):
description="Export only selected objects (and visible in active "
"layers if that applies).",
default=False,
)
)
use_exclude_ctrl_bone = BoolProperty(
name="Exclude Control Bones",
description="Do not export control bones (bone.use_deform = false)",
@@ -90,28 +90,47 @@ class ExportGodot(bpy.types.Operator, ExportHelper):
)
use_export_animation = BoolProperty(
name="Export Animation",
description="Export all the animation actions (include those "
"in nla_tracks), notice if an animated object has "
"an ancestor also has animated, its animation would "
"go into the ancetor's AnimationPlayer",
description="Export all the animation actions (include actions "
"in nla_tracks), note that by default blender animation "
"is exported as actions, so every node would have their "
"own AnimationPlayer hold their actions",
default=True,
)
use_seperate_animation_player = BoolProperty(
name="Seperate AnimationPlayer For Each Object",
description="Create a seperate AnimationPlayer node for every"
"blender object which has animtion data",
default=False,
)
use_mesh_modifiers = BoolProperty(
name="Apply Modifiers",
description="Apply modifiers to mesh objects (on a copy!).",
default=True,
)
)
use_active_layers = BoolProperty(
name="Active Layers",
description="Export only objects on the active layers.",
default=True,
)
animation_modes = EnumProperty(
name="Animation Modes",
description="Configuration of how blender animation data being "
"exported to godot AnimationPlayer as well as the "
"placement of AnimationPlayers in the node tree.",
default="ACTIONS",
items=(
(
"ACTIONS", "Animation as Actions",
"Each animated node would have their own AnimationPlayer"
),
(
"SCENE_ANIMATION", "Scene Animation",
"All the animations of the whole scene would be placed "
"into one AnimationPlayer at scene root"
),
(
"SQUASHED_ACTIONS", "Animation as Actions with Squash",
"Animation is exported as actions of nodes, but instead "
"of having an individual AnimationPlayer for each node, "
"this configuration would squash children nodes' actions "
"to their parents"
)
)
)
material_search_paths = EnumProperty(
name="Material Search Paths",
description="Search for existing godot materials with names that match"

View File

@@ -229,12 +229,26 @@ def transform_frames_to_keys(frame_list, value_list, interp):
def get_animation_player(escn_file, export_settings, godot_node):
"""Get a AnimationPlayer node, if not existed, a new
one will be created and returned"""
"""Get a AnimationPlayer node, its return value depends
on animation exporting settings"""
animation_player = None
# the parent of AnimationPlayer
animation_base = None
# looking for a existed AnimationPlayer
if not export_settings['use_seperate_animation_player']:
if export_settings['animation_modes'] == 'ACTIONS':
animation_base = godot_node
elif export_settings['animation_modes'] == 'SCENE_ANIMATION':
node_ptr = godot_node
while node_ptr.parent is not None:
node_ptr = node_ptr.parent
scene_root = node_ptr
animation_base = scene_root
for child in scene_root.children:
if child.get_type() == 'AnimationPlayer':
animation_player = child
break
else: # export_settings['animation_modes'] == 'SQUASHED_ACTIONS':
animation_base = godot_node
node_ptr = godot_node
while node_ptr is not None:
for child in node_ptr.children:
@@ -248,7 +262,7 @@ def get_animation_player(escn_file, export_settings, godot_node):
if animation_player is None:
animation_player = AnimationPlayer(
name='AnimationPlayer',
parent=godot_node,
parent=animation_base,
)
escn_file.add_node(animation_player)

View File

@@ -2,34 +2,56 @@ import bpy
import os
import sys
import traceback
import json
sys.path = [os.getcwd()] + sys.path # Ensure exporter from this folder
from io_scene_godot import export_godot
TEST_SCENE_DIR = os.path.join(os.getcwd(), "tests/test_scenes")
EXPORTED_DIR = os.path.join(os.getcwd(), "tests/godot_project/exports")
def export_escn(out_file):
def export_escn(out_file, config):
"""Fake the export operator call"""
import io_scene_godot
io_scene_godot.export(out_file, {})
io_scene_godot.export(out_file, config)
def main():
target_dir = os.path.join(os.getcwd(), "tests/test_scenes")
for file_name in os.listdir(target_dir):
full_path = os.path.join(target_dir, file_name)
if full_path.endswith(".blend"):
print("Exporting {}".format(full_path))
bpy.ops.wm.open_mainfile(filepath=full_path)
dir_queue = list()
dir_queue.append('.')
while dir_queue:
dir_relpath = dir_queue.pop(0)
out_path, blend_name = os.path.split(full_path)
out_path = os.path.join(
out_path,
'../godot_project/exports/',
blend_name.replace('.blend', '.escn')
)
print(out_path)
export_escn(out_path)
print("Exported")
# read config file if present, otherwise use default
src_dir_path = os.path.join(TEST_SCENE_DIR, dir_relpath)
if os.path.exists(os.path.join(src_dir_path, "config.json")):
with open(os.path.join(src_dir_path, "config.json")) as config_file:
config = json.load(config_file)
else:
config = {}
# create exported to directory
exported_dir_path = os.path.join(EXPORTED_DIR, dir_relpath)
if not os.path.exists(exported_dir_path):
os.makedirs(exported_dir_path)
for item in os.listdir(os.path.join(TEST_SCENE_DIR, dir_relpath)):
item_abspath = os.path.join(TEST_SCENE_DIR, dir_relpath, item)
if os.path.isdir(item_abspath):
# push dir into queue for later traversal
dir_queue.append(os.path.join(dir_relpath, item))
elif item_abspath.endswith('blend'):
# export blend file
print("---------")
print("Exporting {}".format(os.path.abspath(item_abspath)))
bpy.ops.wm.open_mainfile(filepath=item_abspath)
out_path = os.path.join(
EXPORTED_DIR,
dir_relpath,
item.replace('.blend', '.escn')
)
export_escn(out_path, config)
print("Exported to {}".format(os.path.abspath(out_path)))
def run_with_abort(function):

View File

@@ -1,5 +1,5 @@
[gd_scene load_steps=1 format=2]
[ext_resource id=1 path="../uv_tester_material.tres" type="SpatialMaterial"]
[ext_resource id=1 path="../../uv_tester_material.tres" type="SpatialMaterial"]
[sub_resource id=1 type="ArrayMesh"]

View File

@@ -0,0 +1,3 @@
{
"animation_modes": "SCENE_ANIMATION"
}