2
0
Fork 0

Fixes for gltf export.

* Fix null crashes.
* Bake tracks
* Add some error messages.
4.0
K. S. Ernest (iFire) Lee 2023-02-03 18:06:29 +07:00
parent 929333fe26
commit dbc1e94695
2 changed files with 276 additions and 95 deletions

@ -4894,13 +4894,11 @@ Error GLTFDocument::_serialize_animations(Ref<GLTFState> p_state) {
return OK; return OK;
} }
for (int32_t player_i = 0; player_i < p_state->animation_players.size(); player_i++) { for (int32_t player_i = 0; player_i < p_state->animation_players.size(); player_i++) {
List<StringName> animation_names;
AnimationPlayer *animation_player = p_state->animation_players[player_i]; AnimationPlayer *animation_player = p_state->animation_players[player_i];
animation_player->get_animation_list(&animation_names); List<StringName> animations;
if (animation_names.size()) { animation_player->get_animation_list(&animations);
for (int animation_name_i = 0; animation_name_i < animation_names.size(); animation_name_i++) { for (StringName animation_name : animations) {
_convert_animation(p_state, animation_player, animation_names[animation_name_i]); _convert_animation(p_state, animation_player, animation_name);
}
} }
} }
Array animations; Array animations;
@ -6028,7 +6026,7 @@ void GLTFDocument::_import_animation(Ref<GLTFState> p_state, AnimationPlayer *p_
Node *root = p_animation_player->get_parent(); Node *root = p_animation_player->get_parent();
ERR_FAIL_COND(root == nullptr); ERR_FAIL_COND(root == nullptr);
HashMap<GLTFNodeIndex, Node *>::Iterator node_element = p_state->scene_nodes.find(node_index); HashMap<GLTFNodeIndex, Node *>::Iterator node_element = p_state->scene_nodes.find(node_index);
ERR_CONTINUE_MSG(!node_element, vformat("Unable to find node %d for animation", node_index)); ERR_CONTINUE_MSG(!node_element, vformat("Unable to find node %d for animation.", node_index));
node_path = root->get_path_to(node_element->value); node_path = root->get_path_to(node_element->value);
HashMap<GLTFNodeIndex, ImporterMeshInstance3D *>::Iterator mesh_instance_element = p_state->scene_mesh_instances.find(node_index); HashMap<GLTFNodeIndex, ImporterMeshInstance3D *>::Iterator mesh_instance_element = p_state->scene_mesh_instances.find(node_index);
if (mesh_instance_element) { if (mesh_instance_element) {
@ -6450,7 +6448,32 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
for (int32_t key_i = 0; key_i < key_count; key_i++) { for (int32_t key_i = 0; key_i < key_count; key_i++) {
times.write[key_i] = p_animation->track_get_key_time(p_track_i, key_i); times.write[key_i] = p_animation->track_get_key_time(p_track_i, key_i);
} }
double anim_end = p_animation->get_length();
if (track_type == Animation::TYPE_SCALE_3D) { if (track_type == Animation::TYPE_SCALE_3D) {
if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) {
gltf_interpolation = GLTFAnimation::INTERP_LINEAR;
p_track.scale_track.times.clear();
p_track.scale_track.values.clear();
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
const double increment = 1.0 / BAKE_FPS;
double time = 0.0;
bool last = false;
while (true) {
Vector3 scale;
Error err = p_animation->scale_track_interpolate(p_track_i, time, &scale);
ERR_CONTINUE(err != OK);
p_track.scale_track.values.push_back(scale);
p_track.scale_track.times.push_back(time);
if (last) {
break;
}
time += increment;
if (time >= anim_end) {
last = true;
time = anim_end;
}
}
} else {
p_track.scale_track.times = times; p_track.scale_track.times = times;
p_track.scale_track.interpolation = gltf_interpolation; p_track.scale_track.interpolation = gltf_interpolation;
p_track.scale_track.values.resize(key_count); p_track.scale_track.values.resize(key_count);
@ -6460,7 +6483,32 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
ERR_CONTINUE(err != OK); ERR_CONTINUE(err != OK);
p_track.scale_track.values.write[key_i] = scale; p_track.scale_track.values.write[key_i] = scale;
} }
}
} else if (track_type == Animation::TYPE_POSITION_3D) { } else if (track_type == Animation::TYPE_POSITION_3D) {
if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) {
gltf_interpolation = GLTFAnimation::INTERP_LINEAR;
p_track.position_track.times.clear();
p_track.position_track.values.clear();
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
const double increment = 1.0 / BAKE_FPS;
double time = 0.0;
bool last = false;
while (true) {
Vector3 scale;
Error err = p_animation->position_track_interpolate(p_track_i, time, &scale);
ERR_CONTINUE(err != OK);
p_track.position_track.values.push_back(scale);
p_track.position_track.times.push_back(time);
if (last) {
break;
}
time += increment;
if (time >= anim_end) {
last = true;
time = anim_end;
}
}
} else {
p_track.position_track.times = times; p_track.position_track.times = times;
p_track.position_track.values.resize(key_count); p_track.position_track.values.resize(key_count);
p_track.position_track.interpolation = gltf_interpolation; p_track.position_track.interpolation = gltf_interpolation;
@ -6470,39 +6518,110 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
ERR_CONTINUE(err != OK); ERR_CONTINUE(err != OK);
p_track.position_track.values.write[key_i] = position; p_track.position_track.values.write[key_i] = position;
} }
}
} else if (track_type == Animation::TYPE_ROTATION_3D) { } else if (track_type == Animation::TYPE_ROTATION_3D) {
if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) {
gltf_interpolation = GLTFAnimation::INTERP_LINEAR;
p_track.rotation_track.times.clear();
p_track.rotation_track.values.clear();
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
const double increment = 1.0 / BAKE_FPS;
double time = 0.0;
bool last = false;
while (true) {
Quaternion rotation;
Error err = p_animation->rotation_track_interpolate(p_track_i, time, &rotation);
ERR_CONTINUE(err != OK);
p_track.rotation_track.values.push_back(rotation);
p_track.rotation_track.times.push_back(time);
if (last) {
break;
}
time += increment;
if (time >= anim_end) {
last = true;
time = anim_end;
}
}
} else {
p_track.rotation_track.times = times; p_track.rotation_track.times = times;
p_track.rotation_track.interpolation = gltf_interpolation;
p_track.rotation_track.values.resize(key_count); p_track.rotation_track.values.resize(key_count);
p_track.rotation_track.interpolation = gltf_interpolation;
for (int32_t key_i = 0; key_i < key_count; key_i++) { for (int32_t key_i = 0; key_i < key_count; key_i++) {
Quaternion rotation; Quaternion rotation;
Error err = p_animation->rotation_track_get_key(p_track_i, key_i, &rotation); Error err = p_animation->rotation_track_get_key(p_track_i, key_i, &rotation);
ERR_CONTINUE(err != OK); ERR_CONTINUE(err != OK);
p_track.rotation_track.values.write[key_i] = rotation; p_track.rotation_track.values.write[key_i] = rotation;
} }
}
} else if (track_type == Animation::TYPE_VALUE) { } else if (track_type == Animation::TYPE_VALUE) {
if (path.contains(":position")) { if (path.contains(":position")) {
p_track.position_track.times = times;
p_track.position_track.interpolation = gltf_interpolation; p_track.position_track.interpolation = gltf_interpolation;
p_track.position_track.times = times;
p_track.position_track.values.resize(key_count); p_track.position_track.values.resize(key_count);
p_track.position_track.interpolation = gltf_interpolation;
if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) {
gltf_interpolation = GLTFAnimation::INTERP_LINEAR;
p_track.position_track.times.clear();
p_track.position_track.values.clear();
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
const double increment = 1.0 / BAKE_FPS;
double time = 0.0;
bool last = false;
while (true) {
Vector3 position;
Error err = p_animation->position_track_interpolate(p_track_i, time, &position);
ERR_CONTINUE(err != OK);
p_track.position_track.values.push_back(position);
p_track.position_track.times.push_back(time);
if (last) {
break;
}
time += increment;
if (time >= anim_end) {
last = true;
time = anim_end;
}
}
} else {
for (int32_t key_i = 0; key_i < key_count; key_i++) { for (int32_t key_i = 0; key_i < key_count; key_i++) {
Vector3 position = p_animation->track_get_key_value(p_track_i, key_i); Vector3 position = p_animation->track_get_key_value(p_track_i, key_i);
p_track.position_track.values.write[key_i] = position; p_track.position_track.values.write[key_i] = position;
} }
}
} else if (path.contains(":rotation")) { } else if (path.contains(":rotation")) {
p_track.rotation_track.times = times;
p_track.rotation_track.interpolation = gltf_interpolation; p_track.rotation_track.interpolation = gltf_interpolation;
p_track.rotation_track.times = times;
p_track.rotation_track.values.resize(key_count); p_track.rotation_track.values.resize(key_count);
p_track.rotation_track.interpolation = gltf_interpolation; if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) {
gltf_interpolation = GLTFAnimation::INTERP_LINEAR;
p_track.rotation_track.times.clear();
p_track.rotation_track.values.clear();
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
const double increment = 1.0 / BAKE_FPS;
double time = 0.0;
bool last = false;
while (true) {
Quaternion rotation;
Error err = p_animation->rotation_track_interpolate(p_track_i, time, &rotation);
ERR_CONTINUE(err != OK);
p_track.rotation_track.values.push_back(rotation);
p_track.rotation_track.times.push_back(time);
if (last) {
break;
}
time += increment;
if (time >= anim_end) {
last = true;
time = anim_end;
}
}
} else {
for (int32_t key_i = 0; key_i < key_count; key_i++) { for (int32_t key_i = 0; key_i < key_count; key_i++) {
Vector3 rotation_radian = p_animation->track_get_key_value(p_track_i, key_i); Vector3 rotation_radian = p_animation->track_get_key_value(p_track_i, key_i);
p_track.rotation_track.values.write[key_i] = Quaternion::from_euler(rotation_radian); p_track.rotation_track.values.write[key_i] = Quaternion::from_euler(rotation_radian);
} }
}
} else if (path.contains(":scale")) { } else if (path.contains(":scale")) {
p_track.scale_track.times = times; p_track.scale_track.times = times;
p_track.scale_track.interpolation = gltf_interpolation; p_track.scale_track.interpolation = gltf_interpolation;
@ -6510,68 +6629,115 @@ GLTFAnimation::Track GLTFDocument::_convert_animation_track(Ref<GLTFState> p_sta
p_track.scale_track.values.resize(key_count); p_track.scale_track.values.resize(key_count);
p_track.scale_track.interpolation = gltf_interpolation; p_track.scale_track.interpolation = gltf_interpolation;
if (gltf_interpolation == GLTFAnimation::INTERP_CUBIC_SPLINE) {
gltf_interpolation = GLTFAnimation::INTERP_LINEAR;
p_track.scale_track.times.clear();
p_track.scale_track.values.clear();
// CATMULLROMSPLINE or CUBIC_SPLINE have to be baked, apologies.
const double increment = 1.0 / BAKE_FPS;
double time = 0.0;
bool last = false;
while (true) {
Vector3 scale;
Error err = p_animation->scale_track_interpolate(p_track_i, time, &scale);
ERR_CONTINUE(err != OK);
p_track.scale_track.values.push_back(scale);
p_track.scale_track.times.push_back(time);
if (last) {
break;
}
time += increment;
if (time >= anim_end) {
last = true;
time = anim_end;
}
}
} else {
for (int32_t key_i = 0; key_i < key_count; key_i++) { for (int32_t key_i = 0; key_i < key_count; key_i++) {
Vector3 scale_track = p_animation->track_get_key_value(p_track_i, key_i); Vector3 scale_track = p_animation->track_get_key_value(p_track_i, key_i);
p_track.scale_track.values.write[key_i] = scale_track; p_track.scale_track.values.write[key_i] = scale_track;
} }
} }
}
} else if (track_type == Animation::TYPE_BEZIER) { } else if (track_type == Animation::TYPE_BEZIER) {
if (path.contains("/scale")) { const int32_t keys = anim_end * BAKE_FPS;
const int32_t keys = p_animation->track_get_key_time(p_track_i, key_count - 1) * BAKE_FPS; if (path.contains(":scale")) {
if (!p_track.scale_track.times.size()) { if (!p_track.scale_track.times.size()) {
p_track.scale_track.interpolation = gltf_interpolation;
Vector<real_t> new_times; Vector<real_t> new_times;
new_times.resize(keys); new_times.resize(keys);
for (int32_t key_i = 0; key_i < keys; key_i++) { for (int32_t key_i = 0; key_i < keys; key_i++) {
new_times.write[key_i] = key_i / BAKE_FPS; new_times.write[key_i] = key_i / BAKE_FPS;
} }
p_track.scale_track.times = new_times; p_track.scale_track.times = new_times;
p_track.scale_track.interpolation = gltf_interpolation;
p_track.scale_track.values.resize(keys); p_track.scale_track.values.resize(keys);
for (int32_t key_i = 0; key_i < keys; key_i++) { for (int32_t key_i = 0; key_i < keys; key_i++) {
p_track.scale_track.values.write[key_i] = Vector3(1.0f, 1.0f, 1.0f); p_track.scale_track.values.write[key_i] = Vector3(1.0f, 1.0f, 1.0f);
} }
p_track.scale_track.interpolation = gltf_interpolation;
}
for (int32_t key_i = 0; key_i < keys; key_i++) { for (int32_t key_i = 0; key_i < keys; key_i++) {
Vector3 bezier_track = p_track.scale_track.values[key_i]; Vector3 bezier_track = p_track.scale_track.values[key_i];
if (path.contains("/scale:x")) { if (path.contains(":scale:x")) {
bezier_track.x = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS); bezier_track.x = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
} else if (path.contains("/scale:y")) { } else if (path.contains(":scale:y")) {
bezier_track.y = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS); bezier_track.y = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
} else if (path.contains("/scale:z")) { } else if (path.contains(":scale:z")) {
bezier_track.z = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS); bezier_track.z = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
} }
p_track.scale_track.values.write[key_i] = bezier_track; p_track.scale_track.values.write[key_i] = bezier_track;
} }
} else if (path.contains("/position")) { }
const int32_t keys = p_animation->track_get_key_time(p_track_i, key_count - 1) * BAKE_FPS; } else if (path.contains(":position")) {
if (!p_track.position_track.times.size()) { if (!p_track.position_track.times.size()) {
p_track.position_track.interpolation = gltf_interpolation;
Vector<real_t> new_times; Vector<real_t> new_times;
new_times.resize(keys); new_times.resize(keys);
for (int32_t key_i = 0; key_i < keys; key_i++) { for (int32_t key_i = 0; key_i < keys; key_i++) {
new_times.write[key_i] = key_i / BAKE_FPS; new_times.write[key_i] = key_i / BAKE_FPS;
} }
p_track.position_track.times = new_times; p_track.position_track.times = new_times;
p_track.position_track.interpolation = gltf_interpolation;
p_track.position_track.values.resize(keys); p_track.position_track.values.resize(keys);
p_track.position_track.interpolation = gltf_interpolation;
} }
for (int32_t key_i = 0; key_i < keys; key_i++) { for (int32_t key_i = 0; key_i < keys; key_i++) {
Vector3 bezier_track = p_track.position_track.values[key_i]; Vector3 bezier_track = p_track.position_track.values[key_i];
if (path.contains("/position:x")) { if (path.contains(":position:x")) {
bezier_track.x = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS); bezier_track.x = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
} else if (path.contains("/position:y")) { } else if (path.contains(":position:y")) {
bezier_track.y = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS); bezier_track.y = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
} else if (path.contains("/position:z")) { } else if (path.contains(":position:z")) {
bezier_track.z = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS); bezier_track.z = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
} }
p_track.position_track.values.write[key_i] = bezier_track; p_track.position_track.values.write[key_i] = bezier_track;
} }
} else if (path.contains(":rotation")) {
if (!p_track.rotation_track.times.size()) {
p_track.rotation_track.interpolation = gltf_interpolation;
Vector<real_t> new_times;
new_times.resize(keys);
for (int32_t key_i = 0; key_i < keys; key_i++) {
new_times.write[key_i] = key_i / BAKE_FPS;
}
p_track.rotation_track.times = new_times;
p_track.rotation_track.values.resize(keys);
}
for (int32_t key_i = 0; key_i < keys; key_i++) {
Quaternion bezier_track = p_track.rotation_track.values[key_i];
if (path.contains(":rotation:x")) {
bezier_track.x = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
} else if (path.contains(":rotation:y")) {
bezier_track.y = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
} else if (path.contains(":rotation:z")) {
bezier_track.z = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
} else if (path.contains(":rotation:w")) {
bezier_track.w = p_animation->bezier_track_interpolate(p_track_i, key_i / BAKE_FPS);
}
p_track.rotation_track.values.write[key_i] = bezier_track;
}
} }
} }
return p_track; return p_track;
@ -6582,16 +6748,18 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p
Ref<GLTFAnimation> gltf_animation; Ref<GLTFAnimation> gltf_animation;
gltf_animation.instantiate(); gltf_animation.instantiate();
gltf_animation->set_name(_gen_unique_name(p_state, p_animation_track_name)); gltf_animation->set_name(_gen_unique_name(p_state, p_animation_track_name));
for (int32_t track_i = 0; track_i < animation->get_track_count(); track_i++) { for (int32_t track_i = 0; track_i < animation->get_track_count(); track_i++) {
if (!animation->track_is_enabled(track_i)) { if (!animation->track_is_enabled(track_i)) {
continue; continue;
} }
String orig_track_path = animation->track_get_path(track_i); String final_track_path = animation->track_get_path(track_i);
if (String(orig_track_path).contains(":position")) { Node *animation_base_node = p_animation_player->get_parent();
const Vector<String> node_suffix = String(orig_track_path).split(":position"); ERR_CONTINUE_MSG(!animation_base_node, "Cannot get the parent of the animation player.");
if (String(final_track_path).contains(":position")) {
const Vector<String> node_suffix = String(final_track_path).split(":position");
const NodePath path = node_suffix[0]; const NodePath path = node_suffix[0];
const Node *node = p_animation_player->get_parent()->get_node_or_null(path); const Node *node = animation_base_node->get_node_or_null(path);
ERR_CONTINUE_MSG(!node, "Cannot get the node from a position path.");
for (const KeyValue<GLTFNodeIndex, Node *> &position_scene_node_i : p_state->scene_nodes) { for (const KeyValue<GLTFNodeIndex, Node *> &position_scene_node_i : p_state->scene_nodes) {
if (position_scene_node_i.value == node) { if (position_scene_node_i.value == node) {
GLTFNodeIndex node_index = position_scene_node_i.key; GLTFNodeIndex node_index = position_scene_node_i.key;
@ -6604,10 +6772,11 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p
gltf_animation->get_tracks().insert(node_index, track); gltf_animation->get_tracks().insert(node_index, track);
} }
} }
} else if (String(orig_track_path).contains(":rotation_degrees")) { } else if (String(final_track_path).contains(":rotation_degrees")) {
const Vector<String> node_suffix = String(orig_track_path).split(":rotation_degrees"); const Vector<String> node_suffix = String(final_track_path).split(":rotation_degrees");
const NodePath path = node_suffix[0]; const NodePath path = node_suffix[0];
const Node *node = p_animation_player->get_parent()->get_node_or_null(path); const Node *node = animation_base_node->get_node_or_null(path);
ERR_CONTINUE_MSG(!node, "Cannot get the node from a rotation degrees path.");
for (const KeyValue<GLTFNodeIndex, Node *> &rotation_degree_scene_node_i : p_state->scene_nodes) { for (const KeyValue<GLTFNodeIndex, Node *> &rotation_degree_scene_node_i : p_state->scene_nodes) {
if (rotation_degree_scene_node_i.value == node) { if (rotation_degree_scene_node_i.value == node) {
GLTFNodeIndex node_index = rotation_degree_scene_node_i.key; GLTFNodeIndex node_index = rotation_degree_scene_node_i.key;
@ -6620,10 +6789,11 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p
gltf_animation->get_tracks().insert(node_index, track); gltf_animation->get_tracks().insert(node_index, track);
} }
} }
} else if (String(orig_track_path).contains(":scale")) { } else if (String(final_track_path).contains(":scale")) {
const Vector<String> node_suffix = String(orig_track_path).split(":scale"); const Vector<String> node_suffix = String(final_track_path).split(":scale");
const NodePath path = node_suffix[0]; const NodePath path = node_suffix[0];
const Node *node = p_animation_player->get_parent()->get_node_or_null(path); const Node *node = animation_base_node->get_node_or_null(path);
ERR_CONTINUE_MSG(!node, "Cannot get the node from a scale path.");
for (const KeyValue<GLTFNodeIndex, Node *> &scale_scene_node_i : p_state->scene_nodes) { for (const KeyValue<GLTFNodeIndex, Node *> &scale_scene_node_i : p_state->scene_nodes) {
if (scale_scene_node_i.value == node) { if (scale_scene_node_i.value == node) {
GLTFNodeIndex node_index = scale_scene_node_i.key; GLTFNodeIndex node_index = scale_scene_node_i.key;
@ -6636,10 +6806,11 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p
gltf_animation->get_tracks().insert(node_index, track); gltf_animation->get_tracks().insert(node_index, track);
} }
} }
} else if (String(orig_track_path).contains(":transform")) { } else if (String(final_track_path).contains(":transform")) {
const Vector<String> node_suffix = String(orig_track_path).split(":transform"); const Vector<String> node_suffix = String(final_track_path).split(":transform");
const NodePath path = node_suffix[0]; const NodePath path = node_suffix[0];
const Node *node = p_animation_player->get_parent()->get_node_or_null(path); const Node *node = animation_base_node->get_node_or_null(path);
ERR_CONTINUE_MSG(!node, "Cannot get the node from a transform path.");
for (const KeyValue<GLTFNodeIndex, Node *> &transform_track_i : p_state->scene_nodes) { for (const KeyValue<GLTFNodeIndex, Node *> &transform_track_i : p_state->scene_nodes) {
if (transform_track_i.value == node) { if (transform_track_i.value == node) {
GLTFAnimation::Track track; GLTFAnimation::Track track;
@ -6647,12 +6818,16 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p
gltf_animation->get_tracks().insert(transform_track_i.key, track); gltf_animation->get_tracks().insert(transform_track_i.key, track);
} }
} }
} else if (String(orig_track_path).contains(":") && animation->track_get_type(track_i) == Animation::TYPE_BLEND_SHAPE) { } else if (String(final_track_path).contains(":") && animation->track_get_type(track_i) == Animation::TYPE_BLEND_SHAPE) {
const Vector<String> node_suffix = String(orig_track_path).split(":"); const Vector<String> node_suffix = String(final_track_path).split(":");
const NodePath path = node_suffix[0]; const NodePath path = node_suffix[0];
const String suffix = node_suffix[1]; const String suffix = node_suffix[1];
Node *node = p_animation_player->get_parent()->get_node_or_null(path); Node *node = animation_base_node->get_node_or_null(path);
ERR_CONTINUE_MSG(!node, "Cannot get the node from a blend shape path.");
MeshInstance3D *mi = cast_to<MeshInstance3D>(node); MeshInstance3D *mi = cast_to<MeshInstance3D>(node);
if (!mi) {
continue;
}
Ref<Mesh> mesh = mi->get_mesh(); Ref<Mesh> mesh = mi->get_mesh();
ERR_CONTINUE(mesh.is_null()); ERR_CONTINUE(mesh.is_null());
int32_t mesh_index = -1; int32_t mesh_index = -1;
@ -6703,14 +6878,20 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p
} }
tracks[mesh_index] = track; tracks[mesh_index] = track;
} }
} else if (String(orig_track_path).contains(":")) { } else if (String(final_track_path).contains(":")) {
//Process skeleton //Process skeleton
const Vector<String> node_suffix = String(orig_track_path).split(":"); const Vector<String> node_suffix = String(final_track_path).split(":");
const String node = node_suffix[0]; const String node = node_suffix[0];
const NodePath node_path = node; const NodePath node_path = node;
const String suffix = node_suffix[1]; const String suffix = node_suffix[1];
Node *godot_node = p_animation_player->get_parent()->get_node_or_null(node_path); Node *godot_node = animation_base_node->get_node_or_null(node_path);
Skeleton3D *skeleton = nullptr; if (!godot_node) {
continue;
}
Skeleton3D *skeleton = cast_to<Skeleton3D>(animation_base_node->get_node_or_null(node));
if (!skeleton) {
continue;
}
GLTFSkeletonIndex skeleton_gltf_i = -1; GLTFSkeletonIndex skeleton_gltf_i = -1;
for (GLTFSkeletonIndex skeleton_i = 0; skeleton_i < p_state->skeletons.size(); skeleton_i++) { for (GLTFSkeletonIndex skeleton_i = 0; skeleton_i < p_state->skeletons.size(); skeleton_i++) {
if (p_state->skeletons[skeleton_i]->godot_skeleton == cast_to<Skeleton3D>(godot_node)) { if (p_state->skeletons[skeleton_i]->godot_skeleton == cast_to<Skeleton3D>(godot_node)) {
@ -6719,7 +6900,7 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p
ERR_CONTINUE(!skeleton); ERR_CONTINUE(!skeleton);
Ref<GLTFSkeleton> skeleton_gltf = p_state->skeletons[skeleton_gltf_i]; Ref<GLTFSkeleton> skeleton_gltf = p_state->skeletons[skeleton_gltf_i];
int32_t bone = skeleton->find_bone(suffix); int32_t bone = skeleton->find_bone(suffix);
ERR_CONTINUE(bone == -1); ERR_CONTINUE_MSG(bone == -1, vformat("Cannot find the bone %s.", suffix));
if (!skeleton_gltf->godot_bone_node.has(bone)) { if (!skeleton_gltf->godot_bone_node.has(bone)) {
continue; continue;
} }
@ -6733,9 +6914,10 @@ void GLTFDocument::_convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p
gltf_animation->get_tracks()[node_i] = track; gltf_animation->get_tracks()[node_i] = track;
} }
} }
} else if (!String(orig_track_path).contains(":")) { } else if (!String(final_track_path).contains(":")) {
ERR_CONTINUE(!p_animation_player->get_parent()); ERR_CONTINUE(!animation_base_node);
Node *godot_node = p_animation_player->get_parent()->get_node_or_null(orig_track_path); Node *godot_node = animation_base_node->get_node_or_null(final_track_path);
ERR_CONTINUE_MSG(!godot_node, vformat("Cannot get the node from a skeleton path %s.", final_track_path));
for (const KeyValue<GLTFNodeIndex, Node *> &scene_node_i : p_state->scene_nodes) { for (const KeyValue<GLTFNodeIndex, Node *> &scene_node_i : p_state->scene_nodes) {
if (scene_node_i.value == godot_node) { if (scene_node_i.value == godot_node) {
GLTFNodeIndex node_i = scene_node_i.key; GLTFNodeIndex node_i = scene_node_i.key;

@ -364,8 +364,7 @@ public:
Ref<GLTFNode> p_gltf_node); Ref<GLTFNode> p_gltf_node);
GLTFMeshIndex _convert_mesh_to_gltf(Ref<GLTFState> p_state, GLTFMeshIndex _convert_mesh_to_gltf(Ref<GLTFState> p_state,
MeshInstance3D *p_mesh_instance); MeshInstance3D *p_mesh_instance);
void _convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p_animation_player, void _convert_animation(Ref<GLTFState> p_state, AnimationPlayer *p_animation_player, String p_animation_track_name);
String p_animation_track_name);
Error _serialize(Ref<GLTFState> p_state, const String &p_path); Error _serialize(Ref<GLTFState> p_state, const String &p_path);
Error _parse(Ref<GLTFState> p_state, String p_path, Ref<FileAccess> p_file); Error _parse(Ref<GLTFState> p_state, String p_path, Ref<FileAccess> p_file);
}; };