summaryrefslogtreecommitdiff
path: root/editor
diff options
context:
space:
mode:
Diffstat (limited to 'editor')
-rw-r--r--editor/animation_track_editor.cpp48
-rw-r--r--editor/icons/KeyBlendShape.svg44
-rw-r--r--editor/icons/KeyTrackBlendShape.svg45
-rw-r--r--editor/import/editor_import_collada.cpp4
-rw-r--r--editor/import/resource_importer_scene.cpp145
-rw-r--r--editor/import/resource_importer_scene.h1
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp20
7 files changed, 244 insertions, 63 deletions
diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp
index 2ee7f0ffa5..7f118532c9 100644
--- a/editor/animation_track_editor.cpp
+++ b/editor/animation_track_editor.cpp
@@ -198,6 +198,7 @@ public:
}
} break;
+ case Animation::TYPE_BLEND_SHAPE:
case Animation::TYPE_VALUE: {
if (name == "value") {
Variant value = p_value;
@@ -438,6 +439,7 @@ public:
return true;
}
} break;
+ case Animation::TYPE_BLEND_SHAPE:
case Animation::TYPE_VALUE: {
if (name == "value") {
r_ret = animation->track_get_key_value(track, key);
@@ -551,6 +553,9 @@ public:
case Animation::TYPE_SCALE_3D: {
p_list->push_back(PropertyInfo(Variant::VECTOR3, "scale"));
} break;
+ case Animation::TYPE_BLEND_SHAPE: {
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "value"));
+ } break;
case Animation::TYPE_VALUE: {
Variant v = animation->track_get_key_value(track, key);
@@ -828,6 +833,7 @@ public:
undo_redo->add_undo_method(animation.ptr(), "track_set_key_value", track, key, old);
update_obj = true;
} break;
+ case Animation::TYPE_BLEND_SHAPE:
case Animation::TYPE_VALUE: {
if (name == "value") {
Variant value = p_value;
@@ -1054,6 +1060,7 @@ public:
}
} break;
+ case Animation::TYPE_BLEND_SHAPE:
case Animation::TYPE_VALUE: {
if (name == "value") {
r_ret = animation->track_get_key_value(track, key);
@@ -1206,6 +1213,9 @@ public:
case Animation::TYPE_SCALE_3D: {
p_list->push_back(PropertyInfo(Variant::VECTOR3, "scale"));
} break;
+ case Animation::TYPE_BLEND_SHAPE: {
+ p_list->push_back(PropertyInfo(Variant::FLOAT, "value"));
+ } break;
case Animation::TYPE_VALUE: {
if (same_key_type) {
Variant v = animation->track_get_key_value(first_track, first_key);
@@ -1404,6 +1414,7 @@ void AnimationTimelineEdit::_notification(int p_what) {
add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyXPosition"), SNAME("EditorIcons")), TTR("3D Position Track"));
add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyXRotation"), SNAME("EditorIcons")), TTR("3D Rotation Track"));
add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyXScale"), SNAME("EditorIcons")), TTR("3D Scale Track"));
+ add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyBlendShape"), SNAME("EditorIcons")), TTR("Blend Shape Track"));
add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyCall"), SNAME("EditorIcons")), TTR("Call Method Track"));
add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyBezier"), SNAME("EditorIcons")), TTR("Bezier Curve Track"));
add_track->get_popup()->add_icon_item(get_theme_icon(SNAME("KeyAudio"), SNAME("EditorIcons")), TTR("Audio Playback Track"));
@@ -1872,11 +1883,12 @@ void AnimationTrackEdit::_notification(int p_what) {
Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
Color color = get_theme_color(SNAME("font_color"), SNAME("Label"));
- Ref<Texture2D> type_icons[8] = {
+ Ref<Texture2D> type_icons[9] = {
get_theme_icon(SNAME("KeyValue"), SNAME("EditorIcons")),
get_theme_icon(SNAME("KeyTrackPosition"), SNAME("EditorIcons")),
get_theme_icon(SNAME("KeyTrackRotation"), SNAME("EditorIcons")),
get_theme_icon(SNAME("KeyTrackScale"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("KeyTrackBlendShape"), SNAME("EditorIcons")),
get_theme_icon(SNAME("KeyCall"), SNAME("EditorIcons")),
get_theme_icon(SNAME("KeyBezier"), SNAME("EditorIcons")),
get_theme_icon(SNAME("KeyAudio"), SNAME("EditorIcons")),
@@ -2067,7 +2079,7 @@ void AnimationTrackEdit::_notification(int p_what) {
interp_mode_rect.position.y = int(get_size().height - icon->get_height()) / 2;
interp_mode_rect.size = icon->get_size();
- if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D) {
+ if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D) {
draw_texture(icon, interp_mode_rect.position);
}
// Make it easier to click.
@@ -2077,7 +2089,7 @@ void AnimationTrackEdit::_notification(int p_what) {
ofs += icon->get_width() + hsep;
interp_mode_rect.size.x += hsep;
- if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D) {
+ if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D) {
draw_texture(down_icon, Vector2(ofs, int(get_size().height - down_icon->get_height()) / 2));
interp_mode_rect.size.x += down_icon->get_width();
} else {
@@ -2100,7 +2112,7 @@ void AnimationTrackEdit::_notification(int p_what) {
loop_mode_rect.position.y = int(get_size().height - icon->get_height()) / 2;
loop_mode_rect.size = icon->get_size();
- if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D) {
+ if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D) {
draw_texture(icon, loop_mode_rect.position);
}
@@ -2110,7 +2122,7 @@ void AnimationTrackEdit::_notification(int p_what) {
ofs += icon->get_width() + hsep;
loop_mode_rect.size.x += hsep;
- if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D) {
+ if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_BLEND_SHAPE || animation->track_get_type(track) == Animation::TYPE_POSITION_3D || animation->track_get_type(track) == Animation::TYPE_SCALE_3D || animation->track_get_type(track) == Animation::TYPE_ROTATION_3D) {
draw_texture(down_icon, Vector2(ofs, int(get_size().height - down_icon->get_height()) / 2));
loop_mode_rect.size.x += down_icon->get_width();
} else {
@@ -2330,11 +2342,12 @@ void AnimationTrackEdit::set_animation_and_track(const Ref<Animation> &p_animati
track = p_track;
update();
- Ref<Texture2D> type_icons[8] = {
+ Ref<Texture2D> type_icons[9] = {
get_theme_icon(SNAME("KeyValue"), SNAME("EditorIcons")),
get_theme_icon(SNAME("KeyXPosition"), SNAME("EditorIcons")),
get_theme_icon(SNAME("KeyXRotation"), SNAME("EditorIcons")),
get_theme_icon(SNAME("KeyXScale"), SNAME("EditorIcons")),
+ get_theme_icon(SNAME("KeyBlendShape"), SNAME("EditorIcons")),
get_theme_icon(SNAME("KeyCall"), SNAME("EditorIcons")),
get_theme_icon(SNAME("KeyBezier"), SNAME("EditorIcons")),
get_theme_icon(SNAME("KeyAudio"), SNAME("EditorIcons")),
@@ -2516,6 +2529,10 @@ String AnimationTrackEdit::get_tooltip(const Point2 &p_pos) const {
Vector3 t = animation->track_get_key_value(track, key_idx);
text += "Scale: " + String(t) + "\n";
} break;
+ case Animation::TYPE_BLEND_SHAPE: {
+ float t = animation->track_get_key_value(track, key_idx);
+ text += "Blend Shape: " + itos(t) + "\n";
+ } break;
case Animation::TYPE_VALUE: {
const Variant &v = animation->track_get_key_value(track, key_idx);
text += "Type: " + Variant::get_type_name(v.get_type()) + "\n";
@@ -3369,6 +3386,8 @@ static bool track_type_is_resettable(Animation::TrackType p_type) {
switch (p_type) {
case Animation::TYPE_VALUE:
[[fallthrough]];
+ case Animation::TYPE_BLEND_SHAPE:
+ [[fallthrough]];
case Animation::TYPE_BEZIER:
[[fallthrough]];
case Animation::TYPE_POSITION_3D:
@@ -4049,6 +4068,7 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD
case Animation::TYPE_POSITION_3D:
case Animation::TYPE_ROTATION_3D:
case Animation::TYPE_SCALE_3D:
+ case Animation::TYPE_BLEND_SHAPE:
case Animation::TYPE_VALUE: {
value = p_id.value;
@@ -4468,6 +4488,11 @@ void AnimationTrackEditor::_new_track_node_selected(NodePath p_path) {
ERR_FAIL_COND(!node);
NodePath path_to = root->get_path_to(node);
+ if (adding_track_type == Animation::TYPE_BLEND_SHAPE && !node->is_class("MeshInstance3D")) {
+ EditorNode::get_singleton()->show_warning(TTR("Blend Shape tracks only apply to MeshInstance3D nodes."));
+ return;
+ }
+
if ((adding_track_type == Animation::TYPE_POSITION_3D || adding_track_type == Animation::TYPE_ROTATION_3D || adding_track_type == Animation::TYPE_SCALE_3D) && !node->is_class("Node3D")) {
EditorNode::get_singleton()->show_warning(TTR("Position/Rotation/Scale 3D tracks only apply to 3D-based nodes."));
return;
@@ -4479,6 +4504,13 @@ void AnimationTrackEditor::_new_track_node_selected(NodePath p_path) {
prop_selector->set_type_filter(Vector<Variant::Type>());
prop_selector->select_property_from_instance(node);
} break;
+ case Animation::TYPE_BLEND_SHAPE: {
+ adding_track_path = path_to;
+ Vector<Variant::Type> filter;
+ filter.push_back(Variant::FLOAT);
+ prop_selector->set_type_filter(filter);
+ prop_selector->select_property_from_instance(node);
+ } break;
case Animation::TYPE_POSITION_3D:
case Animation::TYPE_ROTATION_3D:
case Animation::TYPE_SCALE_3D:
@@ -4710,6 +4742,7 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) {
undo_redo->commit_action();
} break;
+ case Animation::TYPE_BLEND_SHAPE:
case Animation::TYPE_VALUE: {
NodePath bp;
Variant value;
@@ -5388,6 +5421,9 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
case Animation::TYPE_SCALE_3D:
text += " (Scale)";
break;
+ case Animation::TYPE_BLEND_SHAPE:
+ text += " (BlendShape)";
+ break;
case Animation::TYPE_METHOD:
text += " (Methods)";
break;
diff --git a/editor/icons/KeyBlendShape.svg b/editor/icons/KeyBlendShape.svg
new file mode 100644
index 0000000000..42f7341942
--- /dev/null
+++ b/editor/icons/KeyBlendShape.svg
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ height="10"
+ viewBox="0 0 10 10"
+ width="10"
+ version="1.1"
+ id="svg80"
+ sodipodi:docname="KeyBlendShape.svg"
+ inkscape:version="1.1 (1:1.1+202106031931+af4d65493e)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs84" />
+ <sodipodi:namedview
+ id="namedview82"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ showgrid="false"
+ inkscape:zoom="84.4"
+ inkscape:cx="2.6599526"
+ inkscape:cy="5.0059242"
+ inkscape:window-width="1848"
+ inkscape:window-height="1016"
+ inkscape:window-x="72"
+ inkscape:window-y="27"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg80" />
+ <rect
+ fill="#3cf34e"
+ height="6.1027"
+ ry=".76286"
+ transform="matrix(.70710678 -.70710678 .70710678 .70710678 0 -1042.4)"
+ width="6.1027"
+ x="-740.13947"
+ y="741.10779"
+ id="rect78"
+ style="fill:#5ad5c4;fill-opacity:1" />
+</svg>
diff --git a/editor/icons/KeyTrackBlendShape.svg b/editor/icons/KeyTrackBlendShape.svg
new file mode 100644
index 0000000000..e82f0d6a6f
--- /dev/null
+++ b/editor/icons/KeyTrackBlendShape.svg
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ height="10"
+ viewBox="0 0 10 10"
+ width="10"
+ version="1.1"
+ id="svg12"
+ sodipodi:docname="KeyTrackBlendShape.svg"
+ inkscape:version="1.1 (1:1.1+202106031931+af4d65493e)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <defs
+ id="defs16" />
+ <sodipodi:namedview
+ id="namedview14"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ showgrid="false"
+ inkscape:zoom="29.839906"
+ inkscape:cx="-3.5690461"
+ inkscape:cy="9.0985541"
+ inkscape:window-width="1848"
+ inkscape:window-height="1016"
+ inkscape:window-x="72"
+ inkscape:window-y="27"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg12" />
+ <ellipse
+ style="fill:none;fill-opacity:0.401212;stroke:none;stroke-width:4.7811;stroke-linejoin:round"
+ id="path921"
+ cx="-0.88986981"
+ cy="6.0959954"
+ rx="1.2495773"
+ ry="1.0867468" />
+ <path
+ id="path1910"
+ style="color:#000000;fill:#5ad5c4;stroke-linejoin:round;-inkscape-stroke:none"
+ d="m 4.5230825,1.1341567 c -2.1310744,0.017055 -3.86718737,1.7635044 -3.86718737,3.8984375 0,1.8778511 1.34348597,3.4523891 3.11718737,3.8164061 L 3.95277,7.5794693 C 2.7929991,7.3095662 1.9351921,6.2780435 1.9351921,5.0325942 c 0,-1.4262775 1.123493,-2.5732858 2.5390622,-2.6152344 v 0.017578 h 0.2011719 l 0.1796875,-1.28125 H 4.5230825 v -0.011719 c 0,-0.00263 -2.64e-5,-0.00518 0,-0.00781 z m 1.6816406,0.019531 -0.1796875,1.28125 h 1.3085937 c 0.078866,0 0.1230469,0.044181 0.1230469,0.1230469 v 4.9882815 c 0,0.07887 -0.044181,0.121093 -0.1230469,0.121094 H 5.2887075 L 5.10902,8.9486103 h 2.2246093 c 0.7663818,0 1.4042969,-0.635962 1.4042969,-1.402344 V 2.5579848 c 0,-0.7663818 -0.637915,-1.4042969 -1.4042969,-1.4042969 z" />
+</svg>
diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp
index 52be03a1b1..ac8adedf2f 100644
--- a/editor/import/editor_import_collada.cpp
+++ b/editor/import/editor_import_collada.cpp
@@ -1710,7 +1710,7 @@ void ColladaImport::create_animation(int p_clip, bool p_import_value_tracks) {
NodeMap &nm = node_map[at.target];
String path = scene->get_path_to(nm.node);
- animation->add_track(Animation::TYPE_VALUE);
+ animation->add_track(Animation::TYPE_BLEND_SHAPE);
int track = animation->get_track_count() - 1;
path = path + ":" + at.param;
@@ -1732,7 +1732,7 @@ void ColladaImport::create_animation(int p_clip, bool p_import_value_tracks) {
WARN_PRINT("Collada: Unexpected amount of value keys: " + itos(data.size()));
}
- animation->track_insert_key(track, time, value);
+ animation->blend_shape_track_insert_key(track, time, value);
}
tracks_found = true;
diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp
index c393d7f5fc..319e5ee25f 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -1036,6 +1036,10 @@ void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_
} else if (default_anim->track_get_type(j) == Animation::TYPE_VALUE) {
Variant var = default_anim->value_track_interpolate(j, from);
new_anim->track_insert_key(dtrack, 0, var);
+ } else if (default_anim->track_get_type(j) == Animation::TYPE_BLEND_SHAPE) {
+ float interp;
+ default_anim->blend_shape_track_interpolate(j, from, &interp);
+ new_anim->blend_shape_track_insert_key(dtrack, 0, interp);
}
}
}
@@ -1055,6 +1059,10 @@ void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_
} else if (default_anim->track_get_type(j) == Animation::TYPE_VALUE) {
Variant var = default_anim->track_get_key_value(j, k);
new_anim->track_insert_key(dtrack, kt - from, var);
+ } else if (default_anim->track_get_type(j) == Animation::TYPE_BLEND_SHAPE) {
+ float interp;
+ default_anim->blend_shape_track_get_key(j, k, &interp);
+ new_anim->blend_shape_track_insert_key(dtrack, kt - from, interp);
}
}
@@ -1074,6 +1082,10 @@ void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_
} else if (default_anim->track_get_type(j) == Animation::TYPE_VALUE) {
Variant var = default_anim->value_track_interpolate(j, to);
new_anim->track_insert_key(dtrack, to - from, var);
+ } else if (default_anim->track_get_type(j) == Animation::TYPE_BLEND_SHAPE) {
+ float interp;
+ default_anim->blend_shape_track_interpolate(j, to, &interp);
+ new_anim->blend_shape_track_insert_key(dtrack, to - from, interp);
}
}
}
@@ -1105,6 +1117,12 @@ void ResourceImporterScene::_create_clips(AnimationPlayer *anim, const Array &p_
new_anim->track_insert_key(dtrack, 0, var);
Variant to_var = default_anim->value_track_interpolate(j, to);
new_anim->track_insert_key(dtrack, to - from, to_var);
+ } else if (default_anim->track_get_type(j) == Animation::TYPE_BLEND_SHAPE) {
+ float interp;
+ default_anim->blend_shape_track_interpolate(j, from, &interp);
+ new_anim->blend_shape_track_insert_key(dtrack, 0, interp);
+ default_anim->blend_shape_track_interpolate(j, to, &interp);
+ new_anim->blend_shape_track_insert_key(dtrack, to - from, interp);
}
}
}
@@ -1652,7 +1670,7 @@ void ResourceImporterScene::_optimize_track_usage(AnimationPlayer *p_player, Ani
ERR_FAIL_COND(parent == nullptr);
OrderedHashMap<NodePath, uint32_t> used_tracks[TRACK_CHANNEL_MAX];
bool tracks_to_add = false;
- static const Animation::TrackType track_types[TRACK_CHANNEL_MAX] = { Animation::TYPE_POSITION_3D, Animation::TYPE_ROTATION_3D, Animation::TYPE_SCALE_3D };
+ static const Animation::TrackType track_types[TRACK_CHANNEL_MAX] = { Animation::TYPE_POSITION_3D, Animation::TYPE_ROTATION_3D, Animation::TYPE_SCALE_3D, Animation::TYPE_BLEND_SHAPE };
for (const StringName &I : anims) {
Ref<Animation> anim = p_player->get_animation(I);
for (int i = 0; i < anim->get_track_count(); i++) {
@@ -1710,67 +1728,84 @@ void ResourceImporterScene::_optimize_track_usage(AnimationPlayer *p_player, Ani
NodePath path = J.key();
Node *n = parent->get_node(path);
- Skeleton3D *skel = Object::cast_to<Skeleton3D>(n);
- Node3D *n3d = Object::cast_to<Node3D>(n);
- Vector3 loc;
- Quaternion rot;
- Vector3 scale;
- if (skel && path.get_subname_count() > 0) {
- StringName bone = path.get_subname(0);
- int bone_idx = skel->find_bone(bone);
- if (bone_idx == -1) {
- continue;
+
+ if (j == TRACK_CHANNEL_BLEND_SHAPE) {
+ MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(n);
+ if (mi && path.get_subname_count() > 0) {
+ StringName bs = path.get_subname(0);
+ bool valid;
+ float value = mi->get(bs, &valid);
+ if (valid) {
+ int track_idx = anim->add_track(track_types[j]);
+ anim->track_set_path(track_idx, path);
+ anim->track_set_imported(track_idx, true);
+ anim->blend_shape_track_insert_key(track_idx, 0, value);
+ }
}
- skel->get_bone_pose(bone_idx);
- loc = skel->get_bone_pose_position(bone_idx);
- rot = skel->get_bone_pose_rotation(bone_idx);
- scale = skel->get_bone_pose_scale(bone_idx);
- } else if (n3d) {
- loc = n3d->get_position();
- rot = n3d->get_transform().basis.get_rotation_quaternion();
- scale = n3d->get_scale();
+
} else {
- continue;
- }
+ Skeleton3D *skel = Object::cast_to<Skeleton3D>(n);
+ Node3D *n3d = Object::cast_to<Node3D>(n);
+ Vector3 loc;
+ Quaternion rot;
+ Vector3 scale;
+ if (skel && path.get_subname_count() > 0) {
+ StringName bone = path.get_subname(0);
+ int bone_idx = skel->find_bone(bone);
+ if (bone_idx == -1) {
+ continue;
+ }
+ skel->get_bone_pose(bone_idx);
+ loc = skel->get_bone_pose_position(bone_idx);
+ rot = skel->get_bone_pose_rotation(bone_idx);
+ scale = skel->get_bone_pose_scale(bone_idx);
+ } else if (n3d) {
+ loc = n3d->get_position();
+ rot = n3d->get_transform().basis.get_rotation_quaternion();
+ scale = n3d->get_scale();
+ } else {
+ continue;
+ }
- // Ensure insertion keeps tracks together and ordered by type (loc/rot/scale)
- int insert_at_pos = -1;
- for (int k = 0; k < anim->get_track_count(); k++) {
- NodePath tpath = anim->track_get_path(k);
-
- if (path == tpath) {
- Animation::TrackType ttype = anim->track_get_type(k);
- if (insert_at_pos == -1) {
- // First insert, determine whether replacing or kicking back
- if (track_types[j] < ttype) {
- insert_at_pos = k;
- break; // No point in continuing.
- } else {
+ // Ensure insertion keeps tracks together and ordered by type (loc/rot/scale)
+ int insert_at_pos = -1;
+ for (int k = 0; k < anim->get_track_count(); k++) {
+ NodePath tpath = anim->track_get_path(k);
+
+ if (path == tpath) {
+ Animation::TrackType ttype = anim->track_get_type(k);
+ if (insert_at_pos == -1) {
+ // First insert, determine whether replacing or kicking back
+ if (track_types[j] < ttype) {
+ insert_at_pos = k;
+ break; // No point in continuing.
+ } else {
+ insert_at_pos = k + 1;
+ }
+ } else if (ttype < track_types[j]) {
+ // Kick back.
insert_at_pos = k + 1;
}
- } else if (ttype < track_types[j]) {
- // Kick back.
- insert_at_pos = k + 1;
+ } else if (insert_at_pos >= 0) {
+ break;
}
- } else if (insert_at_pos >= 0) {
- break;
}
- }
- int track_idx = anim->add_track(track_types[j], insert_at_pos);
-
- anim->track_set_path(track_idx, path);
- anim->track_set_imported(track_idx, true);
- switch (j) {
- case TRACK_CHANNEL_POSITION: {
- anim->position_track_insert_key(track_idx, 0, loc);
- } break;
- case TRACK_CHANNEL_ROTATION: {
- anim->rotation_track_insert_key(track_idx, 0, rot);
- } break;
- case TRACK_CHANNEL_SCALE: {
- anim->scale_track_insert_key(track_idx, 0, scale);
- } break;
- default: {
+ int track_idx = anim->add_track(track_types[j], insert_at_pos);
+
+ anim->track_set_path(track_idx, path);
+ anim->track_set_imported(track_idx, true);
+ switch (j) {
+ case TRACK_CHANNEL_POSITION: {
+ anim->position_track_insert_key(track_idx, 0, loc);
+ } break;
+ case TRACK_CHANNEL_ROTATION: {
+ anim->rotation_track_insert_key(track_idx, 0, rot);
+ } break;
+ case TRACK_CHANNEL_SCALE: {
+ anim->scale_track_insert_key(track_idx, 0, scale);
+ } break;
+ default: {
+ }
}
}
}
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
index fab602b8ff..e1e7046be5 100644
--- a/editor/import/resource_importer_scene.h
+++ b/editor/import/resource_importer_scene.h
@@ -207,6 +207,7 @@ class ResourceImporterScene : public ResourceImporter {
TRACK_CHANNEL_POSITION,
TRACK_CHANNEL_ROTATION,
TRACK_CHANNEL_SCALE,
+ TRACK_CHANNEL_BLEND_SHAPE,
TRACK_CHANNEL_MAX
};
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index cc94449f78..32a8bbf406 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -2226,6 +2226,21 @@ void Node3DEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (ED_IS_SHORTCUT("spatial_editor/right_view", p_event)) {
_menu_option(VIEW_RIGHT);
}
+ if (ED_IS_SHORTCUT("spatial_editor/orbit_view_down", p_event)) {
+ cursor.x_rot -= Math_PI / 12.0;
+ }
+ if (ED_IS_SHORTCUT("spatial_editor/orbit_view_up", p_event)) {
+ cursor.x_rot += Math_PI / 12.0;
+ }
+ if (ED_IS_SHORTCUT("spatial_editor/orbit_view_right", p_event)) {
+ cursor.y_rot -= Math_PI / 12.0;
+ }
+ if (ED_IS_SHORTCUT("spatial_editor/orbit_view_left", p_event)) {
+ cursor.y_rot += Math_PI / 12.0;
+ }
+ if (ED_IS_SHORTCUT("spatial_editor/orbit_view_180", p_event)) {
+ cursor.y_rot += Math_PI;
+ }
if (ED_IS_SHORTCUT("spatial_editor/focus_origin", p_event)) {
_menu_option(VIEW_CENTER_TO_ORIGIN);
}
@@ -7306,6 +7321,11 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) {
ED_SHORTCUT("spatial_editor/front_view", TTR("Front View"), KEY_KP_1);
ED_SHORTCUT("spatial_editor/left_view", TTR("Left View"), KEY_MASK_ALT + KEY_KP_3);
ED_SHORTCUT("spatial_editor/right_view", TTR("Right View"), KEY_KP_3);
+ ED_SHORTCUT("spatial_editor/orbit_view_down", TTR("Orbit View Down"), KEY_KP_2);
+ ED_SHORTCUT("spatial_editor/orbit_view_left", TTR("Orbit View Left"), KEY_KP_4);
+ ED_SHORTCUT("spatial_editor/orbit_view_right", TTR("Orbit View Right"), KEY_KP_6);
+ ED_SHORTCUT("spatial_editor/orbit_view_up", TTR("Orbit View Up"), KEY_KP_8);
+ ED_SHORTCUT("spatial_editor/orbit_view_180", TTR("Orbit View 180"), KEY_KP_9);
ED_SHORTCUT("spatial_editor/switch_perspective_orthogonal", TTR("Switch Perspective/Orthogonal View"), KEY_KP_5);
ED_SHORTCUT("spatial_editor/insert_anim_key", TTR("Insert Animation Key"), KEY_K);
ED_SHORTCUT("spatial_editor/focus_origin", TTR("Focus Origin"), KEY_O);