Merge pull request #51459 from TokageItLab/fix-animation-track-editor-insert-queue
Fixed behavior of insert track queue in `AnimationTrackEditor` is unstable
This commit is contained in:
commit
90fd6e960e
3 changed files with 157 additions and 174 deletions
|
@ -541,7 +541,7 @@ public:
|
|||
String hint_string;
|
||||
|
||||
if (v.get_type() == Variant::OBJECT) {
|
||||
//could actually check the object property if exists..? yes i will!
|
||||
// Could actually check the object property if exists..? Yes I will!
|
||||
Ref<Resource> res = v;
|
||||
if (res.is_valid()) {
|
||||
hint = PROPERTY_HINT_RESOURCE_TYPE;
|
||||
|
@ -1177,7 +1177,7 @@ public:
|
|||
String hint_string;
|
||||
|
||||
if (v.get_type() == Variant::OBJECT) {
|
||||
//could actually check the object property if exists..? yes i will!
|
||||
// Could actually check the object property if exists..? Yes I will!
|
||||
Ref<Resource> res = v;
|
||||
if (res.is_valid()) {
|
||||
hint = PROPERTY_HINT_RESOURCE_TYPE;
|
||||
|
@ -1388,7 +1388,7 @@ void AnimationTimelineEdit::_notification(int p_what) {
|
|||
|
||||
float l = animation->get_length();
|
||||
if (l <= 0) {
|
||||
l = 0.001; //avoid crashor
|
||||
l = 0.001; // Avoid crashor.
|
||||
}
|
||||
|
||||
Ref<Texture2D> hsize_icon = get_theme_icon(SNAME("Hsize"), SNAME("EditorIcons"));
|
||||
|
@ -1401,18 +1401,12 @@ void AnimationTimelineEdit::_notification(int p_what) {
|
|||
for (int i = 0; i < animation->get_track_count(); i++) {
|
||||
if (animation->track_get_key_count(i) > 0) {
|
||||
float beg = animation->track_get_key_time(i, 0);
|
||||
/*if (animation->track_get_type(i) == Animation::TYPE_BEZIER) {
|
||||
beg += animation->bezier_track_get_key_in_handle(i, 0).x;
|
||||
}* not worth it since they have no use */
|
||||
|
||||
if (beg < time_min) {
|
||||
time_min = beg;
|
||||
}
|
||||
|
||||
float end = animation->track_get_key_time(i, animation->track_get_key_count(i) - 1);
|
||||
/*if (animation->track_get_type(i) == Animation::TYPE_BEZIER) {
|
||||
end += animation->bezier_track_get_key_out_handle(i, animation->track_get_key_count(i) - 1).x;
|
||||
} not worth it since they have no use */
|
||||
|
||||
if (end > time_max) {
|
||||
time_max = end;
|
||||
|
@ -1422,8 +1416,6 @@ void AnimationTimelineEdit::_notification(int p_what) {
|
|||
|
||||
float extra = (zoomw / scale) * 0.5;
|
||||
|
||||
//if (time_min < -0.001)
|
||||
// time_min -= extra;
|
||||
time_max += extra;
|
||||
set_min(time_min);
|
||||
set_max(time_max);
|
||||
|
@ -1853,7 +1845,7 @@ void AnimationTrackEdit::_notification(int p_what) {
|
|||
{
|
||||
Ref<Texture2D> check = animation->track_is_enabled(track) ? get_theme_icon(SNAME("checked"), SNAME("CheckBox")) : get_theme_icon(SNAME("unchecked"), SNAME("CheckBox"));
|
||||
|
||||
int ofs = in_group ? check->get_width() : 0; //not the best reference for margin but..
|
||||
int ofs = in_group ? check->get_width() : 0; // Not the best reference for margin but..
|
||||
|
||||
check_rect = Rect2(Point2(ofs, int(get_size().height - check->get_height()) / 2), check->get_size());
|
||||
draw_texture(check, check_rect.position);
|
||||
|
@ -1971,7 +1963,7 @@ void AnimationTrackEdit::_notification(int p_what) {
|
|||
|
||||
ofs += hsep;
|
||||
{
|
||||
//callmode
|
||||
// Callmode.
|
||||
|
||||
Animation::UpdateMode update_mode;
|
||||
|
||||
|
@ -1990,7 +1982,7 @@ void AnimationTrackEdit::_notification(int p_what) {
|
|||
if (animation->track_get_type(track) == Animation::TYPE_VALUE) {
|
||||
draw_texture(update_icon, update_mode_rect.position);
|
||||
}
|
||||
//make it easier to click
|
||||
// Make it easier to click.
|
||||
update_mode_rect.position.y = 0;
|
||||
update_mode_rect.size.y = get_size().height;
|
||||
|
||||
|
@ -2019,7 +2011,7 @@ void AnimationTrackEdit::_notification(int p_what) {
|
|||
}
|
||||
|
||||
{
|
||||
//interp
|
||||
// Interp.
|
||||
|
||||
Animation::InterpolationType interp_mode = animation->track_get_interpolation_type(track);
|
||||
|
||||
|
@ -2032,7 +2024,7 @@ void AnimationTrackEdit::_notification(int p_what) {
|
|||
if (animation->track_get_type(track) == Animation::TYPE_VALUE || animation->track_get_type(track) == Animation::TYPE_TRANSFORM3D) {
|
||||
draw_texture(icon, interp_mode_rect.position);
|
||||
}
|
||||
//make it easier to click
|
||||
// Make it easier to click.
|
||||
interp_mode_rect.position.y = 0;
|
||||
interp_mode_rect.size.y = get_size().height;
|
||||
|
||||
|
@ -2052,7 +2044,7 @@ void AnimationTrackEdit::_notification(int p_what) {
|
|||
}
|
||||
|
||||
{
|
||||
//loop
|
||||
// Loop.
|
||||
|
||||
bool loop_wrap = animation->track_get_interpolation_loop_wrap(track);
|
||||
|
||||
|
@ -2085,7 +2077,7 @@ void AnimationTrackEdit::_notification(int p_what) {
|
|||
}
|
||||
|
||||
{
|
||||
//erase
|
||||
// Erase.
|
||||
|
||||
Ref<Texture2D> icon = get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"));
|
||||
|
||||
|
@ -2132,7 +2124,7 @@ Rect2 AnimationTrackEdit::get_key_rect(int p_index, float p_pixels_sec) {
|
|||
}
|
||||
Rect2 rect = Rect2(-type_icon->get_width() / 2, 0, type_icon->get_width(), get_size().height);
|
||||
|
||||
//make it a big easier to click
|
||||
// Make it a big easier to click.
|
||||
rect.position.x -= rect.size.x * 0.5;
|
||||
rect.size.x *= 2;
|
||||
return rect;
|
||||
|
@ -2221,7 +2213,7 @@ void AnimationTrackEdit::draw_key(int p_index, float p_pixels_sec, int p_x, bool
|
|||
draw_texture(icon_to_draw, ofs);
|
||||
}
|
||||
|
||||
//helper
|
||||
// Helper.
|
||||
void AnimationTrackEdit::draw_rect_clipped(const Rect2 &p_rect, const Color &p_color, bool p_filled) {
|
||||
int clip_left = timeline->get_name_limit();
|
||||
int clip_right = get_size().width - timeline->get_buttons_width();
|
||||
|
@ -2246,7 +2238,7 @@ void AnimationTrackEdit::draw_texture_region_clipped(const Ref<Texture2D> &p_tex
|
|||
int clip_left = timeline->get_name_limit();
|
||||
int clip_right = get_size().width - timeline->get_buttons_width();
|
||||
|
||||
//clip left and right
|
||||
// Clip left and right.
|
||||
if (clip_left > p_rect.position.x + p_rect.size.x) {
|
||||
return;
|
||||
}
|
||||
|
@ -2455,7 +2447,7 @@ String AnimationTrackEdit::get_tooltip(const Point2 &p_pos) const {
|
|||
key_distance = distance;
|
||||
}
|
||||
} else {
|
||||
//first one does it
|
||||
// First one does it.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -3001,7 +2993,7 @@ AnimationTrackEdit::AnimationTrackEdit() {
|
|||
play_position->set_anchors_and_offsets_preset(PRESET_WIDE);
|
||||
play_position->connect("draw", callable_mp(this, &AnimationTrackEdit::_play_position_draw));
|
||||
set_focus_mode(FOCUS_CLICK);
|
||||
set_mouse_filter(MOUSE_FILTER_PASS); //scroll has to work too for selection
|
||||
set_mouse_filter(MOUSE_FILTER_PASS); // Scroll has to work too for selection.
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
@ -3338,30 +3330,16 @@ static bool track_type_is_resettable(Animation::TrackType p_type) {
|
|||
}
|
||||
}
|
||||
|
||||
void AnimationTrackEditor::_query_insert(const InsertData &p_id) {
|
||||
if (insert_frame != Engine::get_singleton()->get_frames_drawn()) {
|
||||
//clear insert list for the frame if frame changed
|
||||
if (insert_confirm->is_visible()) {
|
||||
return; //do nothing
|
||||
}
|
||||
insert_data.clear();
|
||||
insert_query = false;
|
||||
}
|
||||
insert_frame = Engine::get_singleton()->get_frames_drawn();
|
||||
|
||||
for (const InsertData &E : insert_data) {
|
||||
//prevent insertion of multiple tracks
|
||||
if (E.path == p_id.path) {
|
||||
return; //already inserted a track for this on this frame
|
||||
}
|
||||
}
|
||||
|
||||
insert_data.push_back(p_id);
|
||||
void AnimationTrackEditor::make_insert_queue() {
|
||||
insert_data.clear();
|
||||
insert_queue = true;
|
||||
}
|
||||
|
||||
void AnimationTrackEditor::commit_insert_queue() {
|
||||
bool reset_allowed = true;
|
||||
AnimationPlayer *player = AnimationPlayerEditor::get_singleton()->get_player();
|
||||
if (player->has_animation("RESET") && player->get_animation("RESET") == animation) {
|
||||
// Avoid messing with the reset animation itself
|
||||
// Avoid messing with the reset animation itself.
|
||||
reset_allowed = false;
|
||||
} else {
|
||||
bool some_resettable = false;
|
||||
|
@ -3376,74 +3354,82 @@ void AnimationTrackEditor::_query_insert(const InsertData &p_id) {
|
|||
}
|
||||
}
|
||||
|
||||
if (p_id.track_idx == -1) {
|
||||
int num_tracks = 0;
|
||||
bool all_bezier = true;
|
||||
for (int i = 0; i < insert_data.size(); i++) {
|
||||
if (insert_data[i].type != Animation::TYPE_VALUE && insert_data[i].type != Animation::TYPE_BEZIER) {
|
||||
// Organize insert data.
|
||||
int num_tracks = 0;
|
||||
String last_track_query;
|
||||
bool all_bezier = true;
|
||||
for (int i = 0; i < insert_data.size(); i++) {
|
||||
if (insert_data[i].type != Animation::TYPE_VALUE && insert_data[i].type != Animation::TYPE_BEZIER) {
|
||||
all_bezier = false;
|
||||
}
|
||||
|
||||
if (insert_data[i].track_idx == -1) {
|
||||
++num_tracks;
|
||||
last_track_query = insert_data[i].query;
|
||||
}
|
||||
|
||||
if (insert_data[i].type != Animation::TYPE_VALUE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (insert_data[i].value.get_type()) {
|
||||
case Variant::INT:
|
||||
case Variant::FLOAT:
|
||||
case Variant::VECTOR2:
|
||||
case Variant::VECTOR3:
|
||||
case Variant::QUATERNION:
|
||||
case Variant::PLANE:
|
||||
case Variant::COLOR: {
|
||||
// Valid.
|
||||
} break;
|
||||
default: {
|
||||
all_bezier = false;
|
||||
}
|
||||
|
||||
if (insert_data[i].track_idx == -1) {
|
||||
++num_tracks;
|
||||
}
|
||||
|
||||
if (insert_data[i].type != Animation::TYPE_VALUE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (insert_data[i].value.get_type()) {
|
||||
case Variant::INT:
|
||||
case Variant::FLOAT:
|
||||
case Variant::VECTOR2:
|
||||
case Variant::VECTOR3:
|
||||
case Variant::QUATERNION:
|
||||
case Variant::PLANE:
|
||||
case Variant::COLOR: {
|
||||
// Valid.
|
||||
} break;
|
||||
default: {
|
||||
all_bezier = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bool(EDITOR_DEF("editors/animation/confirm_insert_track", true))) {
|
||||
//potential new key, does not exist
|
||||
if (num_tracks == 1) {
|
||||
// TRANSLATORS: %s will be replaced by a phrase describing the target of track.
|
||||
insert_confirm_text->set_text(vformat(TTR("Create new track for %s and insert key?"), p_id.query));
|
||||
} else {
|
||||
insert_confirm_text->set_text(vformat(TTR("Create %d new tracks and insert keys?"), num_tracks));
|
||||
}
|
||||
|
||||
insert_confirm_bezier->set_visible(all_bezier);
|
||||
insert_confirm_reset->set_visible(reset_allowed);
|
||||
|
||||
insert_confirm->get_ok_button()->set_text(TTR("Create"));
|
||||
insert_confirm->popup_centered();
|
||||
insert_query = true;
|
||||
if (bool(EDITOR_DEF("editors/animation/confirm_insert_track", true)) && num_tracks > 0) {
|
||||
// Potentially a new key, does not exist.
|
||||
if (num_tracks == 1) {
|
||||
// TRANSLATORS: %s will be replaced by a phrase describing the target of track.
|
||||
insert_confirm_text->set_text(vformat(TTR("Create new track for %s and insert key?"), last_track_query));
|
||||
} else {
|
||||
call_deferred(SNAME("_insert_delay"), reset_allowed && EDITOR_GET("editors/animation/default_create_reset_tracks"), all_bezier && EDITOR_GET("editors/animation/default_create_bezier_tracks"));
|
||||
insert_queue = true;
|
||||
insert_confirm_text->set_text(vformat(TTR("Create %d new tracks and insert keys?"), num_tracks));
|
||||
}
|
||||
|
||||
insert_confirm_bezier->set_visible(all_bezier);
|
||||
insert_confirm_reset->set_visible(reset_allowed);
|
||||
|
||||
insert_confirm->get_ok_button()->set_text(TTR("Create"));
|
||||
insert_confirm->popup_centered();
|
||||
} else {
|
||||
if (!insert_query && !insert_queue) {
|
||||
// Create Beziers wouldn't make sense in this case, where no tracks are being created
|
||||
call_deferred(SNAME("_insert_delay"), reset_allowed && EDITOR_GET("editors/animation/default_create_reset_tracks"), false);
|
||||
insert_queue = true;
|
||||
_insert_track(reset_allowed && EDITOR_GET("editors/animation/default_create_reset_tracks"), all_bezier && EDITOR_GET("editors/animation/default_create_bezier_tracks"));
|
||||
}
|
||||
|
||||
insert_queue = false;
|
||||
}
|
||||
|
||||
void AnimationTrackEditor::_query_insert(const InsertData &p_id) {
|
||||
if (!insert_queue) {
|
||||
insert_data.clear();
|
||||
}
|
||||
|
||||
for (const InsertData &E : insert_data) {
|
||||
// Prevent insertion of multiple tracks.
|
||||
if (E.path == p_id.path) {
|
||||
return; // Already inserted a track this frame.
|
||||
}
|
||||
}
|
||||
|
||||
insert_data.push_back(p_id);
|
||||
|
||||
// Without queue, commit immediately.
|
||||
if (!insert_queue) {
|
||||
commit_insert_queue();
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationTrackEditor::_insert_delay(bool p_create_reset, bool p_create_beziers) {
|
||||
if (insert_query) {
|
||||
//discard since it's entered into query mode
|
||||
insert_queue = false;
|
||||
return;
|
||||
}
|
||||
|
||||
void AnimationTrackEditor::_insert_track(bool p_create_reset, bool p_create_beziers) {
|
||||
undo_redo->create_action(TTR("Anim Insert"));
|
||||
|
||||
Ref<Animation> reset_anim;
|
||||
|
@ -3478,7 +3464,6 @@ void AnimationTrackEditor::_insert_delay(bool p_create_reset, bool p_create_bezi
|
|||
set_anim_pos(pos);
|
||||
emit_signal(SNAME("timeline_changed"), pos, true);
|
||||
}
|
||||
insert_queue = false;
|
||||
}
|
||||
|
||||
void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_sub, const Transform3D &p_xform) {
|
||||
|
@ -3490,7 +3475,7 @@ void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_
|
|||
}
|
||||
|
||||
ERR_FAIL_COND(!root);
|
||||
//let's build a node path
|
||||
// Let's build a node path.
|
||||
String path = root->get_path_to(p_node);
|
||||
if (p_sub != "") {
|
||||
path += ":" + p_sub;
|
||||
|
@ -3523,8 +3508,7 @@ void AnimationTrackEditor::insert_transform_key(Node3D *p_node, const String &p_
|
|||
id.query = vformat(TTR("node '%s'"), p_node->get_name());
|
||||
id.advance = false;
|
||||
|
||||
//dialog insert
|
||||
|
||||
// Dialog insert.
|
||||
_query_insert(id);
|
||||
}
|
||||
|
||||
|
@ -3556,12 +3540,12 @@ bool AnimationTrackEditor::has_transform_track(Node3D *p_node, const String &p_s
|
|||
void AnimationTrackEditor::_insert_animation_key(NodePath p_path, const Variant &p_value) {
|
||||
String path = p_path;
|
||||
|
||||
//animation property is a special case, always creates an animation track
|
||||
// Animation property is a special case, always creates an animation track.
|
||||
for (int i = 0; i < animation->get_track_count(); i++) {
|
||||
String np = animation->track_get_path(i);
|
||||
|
||||
if (path == np && animation->track_get_type(i) == Animation::TYPE_ANIMATION) {
|
||||
//exists
|
||||
// Exists.
|
||||
InsertData id;
|
||||
id.path = path;
|
||||
id.track_idx = i;
|
||||
|
@ -3570,7 +3554,7 @@ void AnimationTrackEditor::_insert_animation_key(NodePath p_path, const Variant
|
|||
// TRANSLATORS: This describes the target of new animation track, will be inserted into another string.
|
||||
id.query = TTR("animation");
|
||||
id.advance = false;
|
||||
//dialog insert
|
||||
// Dialog insert.
|
||||
_query_insert(id);
|
||||
return;
|
||||
}
|
||||
|
@ -3583,13 +3567,13 @@ void AnimationTrackEditor::_insert_animation_key(NodePath p_path, const Variant
|
|||
id.type = Animation::TYPE_ANIMATION;
|
||||
id.query = TTR("animation");
|
||||
id.advance = false;
|
||||
//dialog insert
|
||||
// Dialog insert.
|
||||
_query_insert(id);
|
||||
}
|
||||
|
||||
void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_property, const Variant &p_value, bool p_only_if_exists) {
|
||||
ERR_FAIL_COND(!root);
|
||||
//let's build a node path
|
||||
// Let's build a node path.
|
||||
|
||||
Node *node = p_node;
|
||||
|
||||
|
@ -3615,7 +3599,7 @@ void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_p
|
|||
|
||||
NodePath np = path;
|
||||
|
||||
//locate track
|
||||
// Locate track.
|
||||
|
||||
bool inserted = false;
|
||||
|
||||
|
@ -3633,14 +3617,14 @@ void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_p
|
|||
// TRANSLATORS: This describes the target of new animation track, will be inserted into another string.
|
||||
id.query = vformat(TTR("property '%s'"), p_property);
|
||||
id.advance = false;
|
||||
//dialog insert
|
||||
// Dialog insert.
|
||||
_query_insert(id);
|
||||
inserted = true;
|
||||
} else if (animation->track_get_type(i) == Animation::TYPE_BEZIER) {
|
||||
Variant value;
|
||||
String track_path = animation->track_get_path(i);
|
||||
if (track_path == np) {
|
||||
value = p_value; //all good
|
||||
value = p_value; // All good.
|
||||
} else {
|
||||
int sep = track_path.rfind(":");
|
||||
if (sep != -1) {
|
||||
|
@ -3663,7 +3647,7 @@ void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_p
|
|||
id.type = Animation::TYPE_BEZIER;
|
||||
id.query = vformat(TTR("property '%s'"), p_property);
|
||||
id.advance = false;
|
||||
//dialog insert
|
||||
// Dialog insert.
|
||||
_query_insert(id);
|
||||
inserted = true;
|
||||
}
|
||||
|
@ -3679,7 +3663,7 @@ void AnimationTrackEditor::insert_node_value_key(Node *p_node, const String &p_p
|
|||
id.type = Animation::TYPE_VALUE;
|
||||
id.query = vformat(TTR("property '%s'"), p_property);
|
||||
id.advance = false;
|
||||
//dialog insert
|
||||
// Dialog insert.
|
||||
_query_insert(id);
|
||||
}
|
||||
|
||||
|
@ -3687,7 +3671,7 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari
|
|||
EditorHistory *history = EditorNode::get_singleton()->get_editor_history();
|
||||
|
||||
ERR_FAIL_COND(!root);
|
||||
//let's build a node path
|
||||
// Let's build a node path.
|
||||
ERR_FAIL_COND(history->get_path_size() == 0);
|
||||
Object *obj = ObjectDB::get_instance(history->get_path_object(0));
|
||||
ERR_FAIL_COND(!Object::cast_to<Node>(obj));
|
||||
|
@ -3715,10 +3699,11 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari
|
|||
|
||||
NodePath np = path;
|
||||
|
||||
//locate track
|
||||
// Locate track.
|
||||
|
||||
bool inserted = false;
|
||||
|
||||
make_insert_queue();
|
||||
for (int i = 0; i < animation->get_track_count(); i++) {
|
||||
if (animation->track_get_type(i) == Animation::TYPE_VALUE) {
|
||||
if (animation->track_get_path(i) != np) {
|
||||
|
@ -3732,13 +3717,13 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari
|
|||
id.type = Animation::TYPE_VALUE;
|
||||
id.query = vformat(TTR("property '%s'"), p_property);
|
||||
id.advance = p_advance;
|
||||
//dialog insert
|
||||
// Dialog insert.
|
||||
_query_insert(id);
|
||||
inserted = true;
|
||||
} else if (animation->track_get_type(i) == Animation::TYPE_BEZIER) {
|
||||
Variant value;
|
||||
if (animation->track_get_path(i) == np) {
|
||||
value = p_value; //all good
|
||||
value = p_value; // All good.
|
||||
} else {
|
||||
String tpath = animation->track_get_path(i);
|
||||
int index = tpath.rfind(":");
|
||||
|
@ -3757,11 +3742,12 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari
|
|||
id.type = Animation::TYPE_BEZIER;
|
||||
id.query = vformat(TTR("property '%s'"), p_property);
|
||||
id.advance = p_advance;
|
||||
//dialog insert
|
||||
// Dialog insert.
|
||||
_query_insert(id);
|
||||
inserted = true;
|
||||
}
|
||||
}
|
||||
commit_insert_queue();
|
||||
|
||||
if (!inserted) {
|
||||
InsertData id;
|
||||
|
@ -3771,7 +3757,7 @@ void AnimationTrackEditor::insert_value_key(const String &p_property, const Vari
|
|||
id.type = Animation::TYPE_VALUE;
|
||||
id.query = vformat(TTR("property '%s'"), p_property);
|
||||
id.advance = p_advance;
|
||||
//dialog insert
|
||||
// Dialog insert.
|
||||
_query_insert(id);
|
||||
}
|
||||
}
|
||||
|
@ -3954,7 +3940,7 @@ AnimationTrackEditor::TrackIndices AnimationTrackEditor::_confirm_insert(InsertD
|
|||
animation->add_track(p_id.type);
|
||||
animation->track_set_path(animation->get_track_count() - 1, p_id.path);
|
||||
PropertyInfo h = _find_hint_for_track(animation->get_track_count() - 1, np);
|
||||
animation->remove_track(animation->get_track_count() - 1); //hack
|
||||
animation->remove_track(animation->get_track_count() - 1); // Hack.
|
||||
|
||||
if (h.type == Variant::FLOAT ||
|
||||
h.type == Variant::VECTOR2 ||
|
||||
|
@ -4103,7 +4089,7 @@ void AnimationTrackEditor::_update_tracks() {
|
|||
for (int i = 0; i < animation->get_track_count(); i++) {
|
||||
AnimationTrackEdit *track_edit = nullptr;
|
||||
|
||||
//find hint and info for plugin
|
||||
// Find hint and info for plugin.
|
||||
|
||||
if (use_filter) {
|
||||
NodePath path = animation->track_get_path(i);
|
||||
|
@ -4111,10 +4097,10 @@ void AnimationTrackEditor::_update_tracks() {
|
|||
if (root && root->has_node(path)) {
|
||||
Node *node = root->get_node(path);
|
||||
if (!node) {
|
||||
continue; // no node, no filter
|
||||
continue; // No node, no filter.
|
||||
}
|
||||
if (!EditorNode::get_singleton()->get_editor_selection()->is_selected(node)) {
|
||||
continue; //skip track due to not selected
|
||||
continue; // Skip track due to not selected.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4176,7 +4162,7 @@ void AnimationTrackEditor::_update_tracks() {
|
|||
}
|
||||
|
||||
if (track_edit == nullptr) {
|
||||
//no valid plugin_found
|
||||
// No valid plugin_found.
|
||||
track_edit = memnew(AnimationTrackEdit);
|
||||
}
|
||||
|
||||
|
@ -4251,11 +4237,11 @@ void AnimationTrackEditor::_update_tracks() {
|
|||
|
||||
void AnimationTrackEditor::_animation_changed() {
|
||||
if (animation_changing_awaiting_update) {
|
||||
return; //all will be updated, don't bother with anything
|
||||
return; // All will be updated, don't bother with anything.
|
||||
}
|
||||
|
||||
if (key_edit && key_edit->setting) {
|
||||
//if editing a key, just update the edited track, makes refresh less costly
|
||||
// If editing a key, just update the edited track, makes refresh less costly.
|
||||
if (key_edit->track < track_edits.size()) {
|
||||
if (animation->track_get_type(key_edit->track) == Animation::TYPE_BEZIER) {
|
||||
bezier_edit->update();
|
||||
|
@ -4309,7 +4295,7 @@ void AnimationTrackEditor::_animation_update() {
|
|||
}
|
||||
|
||||
if (track_edits.size() == animation->get_track_count()) {
|
||||
//check tracks are the same
|
||||
// Check tracks are the same.
|
||||
|
||||
for (int i = 0; i < track_edits.size(); i++) {
|
||||
if (track_edits[i]->get_path() != animation->track_get_path(i)) {
|
||||
|
@ -4503,12 +4489,12 @@ void AnimationTrackEditor::_new_track_property_selected(String p_name) {
|
|||
if (adding_track_type == Animation::TYPE_VALUE) {
|
||||
Animation::UpdateMode update_mode = Animation::UPDATE_DISCRETE;
|
||||
{
|
||||
//hack
|
||||
// Hack.
|
||||
NodePath np;
|
||||
animation->add_track(Animation::TYPE_VALUE);
|
||||
animation->track_set_path(animation->get_track_count() - 1, full_path);
|
||||
PropertyInfo h = _find_hint_for_track(animation->get_track_count() - 1, np);
|
||||
animation->remove_track(animation->get_track_count() - 1); //hack
|
||||
animation->remove_track(animation->get_track_count() - 1); // Hack.
|
||||
if (h.type == Variant::FLOAT ||
|
||||
h.type == Variant::VECTOR2 ||
|
||||
h.type == Variant::RECT2 ||
|
||||
|
@ -4536,12 +4522,12 @@ void AnimationTrackEditor::_new_track_property_selected(String p_name) {
|
|||
} else {
|
||||
Vector<String> subindices;
|
||||
{
|
||||
//hack
|
||||
// Hack.
|
||||
NodePath np;
|
||||
animation->add_track(Animation::TYPE_VALUE);
|
||||
animation->track_set_path(animation->get_track_count() - 1, full_path);
|
||||
PropertyInfo h = _find_hint_for_track(animation->get_track_count() - 1, np);
|
||||
animation->remove_track(animation->get_track_count() - 1); //hack
|
||||
animation->remove_track(animation->get_track_count() - 1); // Hack.
|
||||
bool valid;
|
||||
subindices = _get_bezier_subindices_for_type(h.type, &valid);
|
||||
if (!valid) {
|
||||
|
@ -4593,7 +4579,7 @@ void AnimationTrackEditor::_insert_key_from_track(float p_ofs, int p_track) {
|
|||
if (snap->is_pressed() && step->get_value() != 0) {
|
||||
p_ofs = snap_time(p_ofs);
|
||||
}
|
||||
while (animation->track_find_key(p_track, p_ofs, true) != -1) { //make sure insertion point is valid
|
||||
while (animation->track_find_key(p_track, p_ofs, true) != -1) { // Make sure insertion point is valid.
|
||||
p_ofs += 0.001;
|
||||
}
|
||||
|
||||
|
@ -4788,16 +4774,16 @@ struct _AnimMoveRestore {
|
|||
Variant key;
|
||||
float transition = 0;
|
||||
};
|
||||
//used for undo/redo
|
||||
// Used for undo/redo.
|
||||
|
||||
void AnimationTrackEditor::_clear_key_edit() {
|
||||
if (key_edit) {
|
||||
//if key edit is the object being inspected, remove it first
|
||||
// If key edit is the object being inspected, remove it first.
|
||||
if (EditorNode::get_singleton()->get_inspector()->get_edited_object() == key_edit) {
|
||||
EditorNode::get_singleton()->push_item(nullptr);
|
||||
}
|
||||
|
||||
//then actually delete it
|
||||
// Then actually delete it.
|
||||
memdelete(key_edit);
|
||||
key_edit = nullptr;
|
||||
}
|
||||
|
@ -4911,11 +4897,11 @@ void AnimationTrackEditor::_move_selection_commit() {
|
|||
List<_AnimMoveRestore> to_restore;
|
||||
|
||||
float motion = moving_selection_offset;
|
||||
// 1 - remove the keys
|
||||
// 1 - remove the keys.
|
||||
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
|
||||
undo_redo->add_do_method(animation.ptr(), "track_remove_key", E->key().track, E->key().key);
|
||||
}
|
||||
// 2 - remove overlapped keys
|
||||
// 2 - Remove overlapped keys.
|
||||
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
|
||||
float newtime = snap_time(E->get().pos + motion);
|
||||
int idx = animation->track_find_key(E->key().track, newtime, true);
|
||||
|
@ -4926,7 +4912,7 @@ void AnimationTrackEditor::_move_selection_commit() {
|
|||
sk.key = idx;
|
||||
sk.track = E->key().track;
|
||||
if (selection.has(sk)) {
|
||||
continue; //already in selection, don't save
|
||||
continue; // Already in selection, don't save.
|
||||
}
|
||||
|
||||
undo_redo->add_do_method(animation.ptr(), "track_remove_key_at_time", E->key().track, newtime);
|
||||
|
@ -4940,24 +4926,24 @@ void AnimationTrackEditor::_move_selection_commit() {
|
|||
to_restore.push_back(amr);
|
||||
}
|
||||
|
||||
// 3 - move the keys (re insert them)
|
||||
// 3 - Move the keys (Reinsert them).
|
||||
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
|
||||
float newpos = snap_time(E->get().pos + motion);
|
||||
undo_redo->add_do_method(animation.ptr(), "track_insert_key", E->key().track, newpos, animation->track_get_key_value(E->key().track, E->key().key), animation->track_get_key_transition(E->key().track, E->key().key));
|
||||
}
|
||||
|
||||
// 4 - (undo) remove inserted keys
|
||||
// 4 - (Undo) Remove inserted keys.
|
||||
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
|
||||
float newpos = snap_time(E->get().pos + motion);
|
||||
undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", E->key().track, newpos);
|
||||
}
|
||||
|
||||
// 5 - (undo) reinsert keys
|
||||
// 5 - (Undo) Reinsert keys.
|
||||
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
|
||||
undo_redo->add_undo_method(animation.ptr(), "track_insert_key", E->key().track, E->get().pos, animation->track_get_key_value(E->key().track, E->key().key), animation->track_get_key_transition(E->key().track, E->key().key));
|
||||
}
|
||||
|
||||
// 6 - (undo) reinsert overlapped keys
|
||||
// 6 - (Undo) Reinsert overlapped keys.
|
||||
for (_AnimMoveRestore &amr : to_restore) {
|
||||
undo_redo->add_undo_method(animation.ptr(), "track_insert_key", amr.track, amr.time, amr.key, amr.transition);
|
||||
}
|
||||
|
@ -4965,7 +4951,7 @@ void AnimationTrackEditor::_move_selection_commit() {
|
|||
undo_redo->add_do_method(this, "_clear_selection_for_anim", animation);
|
||||
undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
|
||||
|
||||
// 7 - reselect
|
||||
// 7 - Reselect.
|
||||
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
|
||||
float oldpos = E->get().pos;
|
||||
float newpos = snap_time(oldpos + motion);
|
||||
|
@ -5035,18 +5021,18 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) {
|
|||
box_select_rect = Rect2();
|
||||
} else if (box_selecting) {
|
||||
if (box_selection->is_visible_in_tree()) {
|
||||
//only if moved
|
||||
// Only if moved.
|
||||
for (int i = 0; i < track_edits.size(); i++) {
|
||||
Rect2 local_rect = box_select_rect;
|
||||
local_rect.position -= track_edits[i]->get_global_position();
|
||||
track_edits[i]->append_to_selection(local_rect, mb->is_command_pressed());
|
||||
}
|
||||
|
||||
if (_get_track_selected() == -1 && track_edits.size() > 0) { //minimal hack to make shortcuts work
|
||||
if (_get_track_selected() == -1 && track_edits.size() > 0) { // Minimal hack to make shortcuts work.
|
||||
track_edits[track_edits.size() - 1]->grab_focus();
|
||||
}
|
||||
} else {
|
||||
_clear_selection(); //clear it
|
||||
_clear_selection(); // Clear it.
|
||||
}
|
||||
|
||||
box_selection->hide();
|
||||
|
@ -5062,7 +5048,7 @@ void AnimationTrackEditor::_scroll_input(const Ref<InputEvent> &p_event) {
|
|||
|
||||
if (mm.is_valid() && box_selecting) {
|
||||
if (!(mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT)) {
|
||||
//no longer
|
||||
// No longer.
|
||||
box_selection->hide();
|
||||
box_selecting = false;
|
||||
return;
|
||||
|
@ -5102,16 +5088,16 @@ void AnimationTrackEditor::_cancel_bezier_edit() {
|
|||
}
|
||||
|
||||
void AnimationTrackEditor::_bezier_edit(int p_for_track) {
|
||||
_clear_selection(); //bezier probably wants to use a separate selection mode
|
||||
_clear_selection(); // Bezier probably wants to use a separate selection mode.
|
||||
bezier_edit->set_root(root);
|
||||
bezier_edit->set_animation_and_track(animation, p_for_track);
|
||||
scroll->hide();
|
||||
bezier_edit->show();
|
||||
//search everything within the track and curve- edit it
|
||||
// Search everything within the track and curve - edit it.
|
||||
}
|
||||
|
||||
void AnimationTrackEditor::_anim_duplicate_keys(bool transpose) {
|
||||
//duplicait!
|
||||
// Duplicait!
|
||||
if (selection.size() && animation.is_valid() && (!transpose || (_get_track_selected() >= 0 && _get_track_selected() < animation->get_track_count()))) {
|
||||
int top_track = 0x7FFFFFFF;
|
||||
float top_time = 1e10;
|
||||
|
@ -5169,7 +5155,7 @@ void AnimationTrackEditor::_anim_duplicate_keys(bool transpose) {
|
|||
|
||||
undo_redo->commit_action();
|
||||
|
||||
//reselect duplicated
|
||||
// Reselect duplicated.
|
||||
|
||||
Map<SelectedKey, KeyInfo> new_selection;
|
||||
for (const Pair<int, float> &E : new_selection_values) {
|
||||
|
@ -5281,7 +5267,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
|
|||
text += sn[j];
|
||||
}
|
||||
|
||||
path = NodePath(node->get_path().get_names(), path.get_subnames(), true); //store full path instead for copying
|
||||
path = NodePath(node->get_path().get_names(), path.get_subnames(), true); // Store full path instead for copying.
|
||||
} else {
|
||||
text = path;
|
||||
int sep = text.find(":");
|
||||
|
@ -5435,11 +5421,11 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
|
|||
|
||||
List<_AnimMoveRestore> to_restore;
|
||||
|
||||
// 1-remove the keys
|
||||
// 1 - Remove the keys.
|
||||
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
|
||||
undo_redo->add_do_method(animation.ptr(), "track_remove_key", E->key().track, E->key().key);
|
||||
}
|
||||
// 2- remove overlapped keys
|
||||
// 2 - Remove overlapped keys.
|
||||
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
|
||||
float newtime = (E->get().pos - from_t) * s + from_t;
|
||||
int idx = animation->track_find_key(E->key().track, newtime, true);
|
||||
|
@ -5450,7 +5436,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
|
|||
sk.key = idx;
|
||||
sk.track = E->key().track;
|
||||
if (selection.has(sk)) {
|
||||
continue; //already in selection, don't save
|
||||
continue; // Already in selection, don't save.
|
||||
}
|
||||
|
||||
undo_redo->add_do_method(animation.ptr(), "track_remove_key_at_time", E->key().track, newtime);
|
||||
|
@ -5465,24 +5451,24 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
|
|||
}
|
||||
|
||||
#define _NEW_POS(m_ofs) (((s > 0) ? m_ofs : from_t + (len - (m_ofs - from_t))) - pivot) * ABS(s) + from_t
|
||||
// 3-move the keys (re insert them)
|
||||
// 3 - Move the keys (re insert them).
|
||||
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
|
||||
float newpos = _NEW_POS(E->get().pos);
|
||||
undo_redo->add_do_method(animation.ptr(), "track_insert_key", E->key().track, newpos, animation->track_get_key_value(E->key().track, E->key().key), animation->track_get_key_transition(E->key().track, E->key().key));
|
||||
}
|
||||
|
||||
// 4-(undo) remove inserted keys
|
||||
// 4 - (Undo) Remove inserted keys.
|
||||
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
|
||||
float newpos = _NEW_POS(E->get().pos);
|
||||
undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_time", E->key().track, newpos);
|
||||
}
|
||||
|
||||
// 5-(undo) reinsert keys
|
||||
// 5 - (Undo) Reinsert keys.
|
||||
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
|
||||
undo_redo->add_undo_method(animation.ptr(), "track_insert_key", E->key().track, E->get().pos, animation->track_get_key_value(E->key().track, E->key().key), animation->track_get_key_transition(E->key().track, E->key().key));
|
||||
}
|
||||
|
||||
// 6-(undo) reinsert overlapped keys
|
||||
// 6 - (Undo) Reinsert overlapped keys.
|
||||
for (_AnimMoveRestore &amr : to_restore) {
|
||||
undo_redo->add_undo_method(animation.ptr(), "track_insert_key", amr.track, amr.time, amr.key, amr.transition);
|
||||
}
|
||||
|
@ -5490,7 +5476,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) {
|
|||
undo_redo->add_do_method(this, "_clear_selection_for_anim", animation);
|
||||
undo_redo->add_undo_method(this, "_clear_selection_for_anim", animation);
|
||||
|
||||
// 7-reselect
|
||||
// 7-reselect.
|
||||
for (Map<SelectedKey, KeyInfo>::Element *E = selection.back(); E; E = E->prev()) {
|
||||
float oldpos = E->get().pos;
|
||||
float newpos = _NEW_POS(oldpos);
|
||||
|
@ -5639,7 +5625,7 @@ bool AnimationTrackEditor::is_grouping_tracks() {
|
|||
|
||||
void AnimationTrackEditor::_selection_changed() {
|
||||
if (selected_filter->is_pressed()) {
|
||||
_update_tracks(); //needs updatin
|
||||
_update_tracks(); // Needs updatin.
|
||||
} else {
|
||||
for (int i = 0; i < track_edits.size(); i++) {
|
||||
track_edits[i]->update();
|
||||
|
@ -5708,7 +5694,6 @@ void AnimationTrackEditor::_bind_methods() {
|
|||
ClassDB::bind_method("_animation_update", &AnimationTrackEditor::_animation_update);
|
||||
ClassDB::bind_method("_track_grab_focus", &AnimationTrackEditor::_track_grab_focus);
|
||||
ClassDB::bind_method("_update_tracks", &AnimationTrackEditor::_update_tracks);
|
||||
ClassDB::bind_method("_insert_delay", &AnimationTrackEditor::_insert_delay);
|
||||
ClassDB::bind_method("_clear_selection_for_anim", &AnimationTrackEditor::_clear_selection_for_anim);
|
||||
ClassDB::bind_method("_select_at_anim", &AnimationTrackEditor::_select_at_anim);
|
||||
|
||||
|
@ -5794,7 +5779,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
|
|||
undo_redo = EditorNode::get_singleton()->get_undo_redo();
|
||||
|
||||
main_panel = memnew(PanelContainer);
|
||||
main_panel->set_focus_mode(FOCUS_ALL); // allow panel to have focus so that shortcuts work as expected.
|
||||
main_panel->set_focus_mode(FOCUS_ALL); // Allow panel to have focus so that shortcuts work as expected.
|
||||
add_child(main_panel);
|
||||
main_panel->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||
HBoxContainer *timeline_scroll = memnew(HBoxContainer);
|
||||
|
@ -5830,7 +5815,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
|
|||
scroll->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||
VScrollBar *sb = scroll->get_v_scrollbar();
|
||||
scroll->remove_child(sb);
|
||||
timeline_scroll->add_child(sb); //move here so timeline and tracks are always aligned
|
||||
timeline_scroll->add_child(sb); // Move here so timeline and tracks are always aligned.
|
||||
scroll->connect("gui_input", callable_mp(this, &AnimationTrackEditor::_scroll_input));
|
||||
|
||||
bezier_edit = memnew(AnimationBezierTrackEdit);
|
||||
|
@ -5871,7 +5856,7 @@ AnimationTrackEditor::AnimationTrackEditor() {
|
|||
|
||||
selected_filter = memnew(Button);
|
||||
selected_filter->set_flat(true);
|
||||
selected_filter->connect("pressed", callable_mp(this, &AnimationTrackEditor::_view_group_toggle)); //same function works the same
|
||||
selected_filter->connect("pressed", callable_mp(this, &AnimationTrackEditor::_view_group_toggle)); // Same function works the same.
|
||||
selected_filter->set_toggle_mode(true);
|
||||
selected_filter->set_tooltip(TTR("Only show tracks from nodes selected in tree."));
|
||||
|
||||
|
@ -5972,9 +5957,6 @@ AnimationTrackEditor::AnimationTrackEditor() {
|
|||
add_child(method_selector);
|
||||
method_selector->connect("selected", callable_mp(this, &AnimationTrackEditor::_add_method_key));
|
||||
|
||||
inserting = false;
|
||||
insert_query = false;
|
||||
insert_frame = 0;
|
||||
insert_queue = false;
|
||||
|
||||
insert_confirm = memnew(ConfirmationDialog);
|
||||
|
@ -6007,13 +5989,13 @@ AnimationTrackEditor::AnimationTrackEditor() {
|
|||
box_selection->connect("draw", callable_mp(this, &AnimationTrackEditor::_box_selection_draw));
|
||||
box_selecting = false;
|
||||
|
||||
//default plugins
|
||||
// Default Plugins.
|
||||
|
||||
Ref<AnimationTrackEditDefaultPlugin> def_plugin;
|
||||
def_plugin.instantiate();
|
||||
add_track_edit_plugin(def_plugin);
|
||||
|
||||
//dialogs
|
||||
// Dialogs.
|
||||
|
||||
optimize_dialog = memnew(ConfirmationDialog);
|
||||
add_child(optimize_dialog);
|
||||
|
|
|
@ -352,10 +352,7 @@ class AnimationTrackEditor : public VBoxContainer {
|
|||
CheckBox *insert_confirm_reset;
|
||||
ConfirmationDialog *insert_confirm;
|
||||
bool insert_queue;
|
||||
bool inserting;
|
||||
bool insert_query;
|
||||
List<InsertData> insert_data;
|
||||
uint64_t insert_frame;
|
||||
|
||||
void _query_insert(const InsertData &p_id);
|
||||
Ref<Animation> _create_and_get_reset_animation();
|
||||
|
@ -370,7 +367,7 @@ class AnimationTrackEditor : public VBoxContainer {
|
|||
}
|
||||
};
|
||||
TrackIndices _confirm_insert(InsertData p_id, TrackIndices p_next_tracks, bool p_create_reset, Ref<Animation> p_reset_anim, bool p_create_beziers);
|
||||
void _insert_delay(bool p_create_reset, bool p_create_beziers);
|
||||
void _insert_track(bool p_create_reset, bool p_create_beziers);
|
||||
|
||||
void _root_removed(Node *p_root);
|
||||
|
||||
|
@ -532,6 +529,8 @@ public:
|
|||
void insert_value_key(const String &p_property, const Variant &p_value, bool p_advance);
|
||||
void insert_transform_key(Node3D *p_node, const String &p_sub, const Transform3D &p_xform);
|
||||
bool has_transform_track(Node3D *p_node, const String &p_sub);
|
||||
void make_insert_queue();
|
||||
void commit_insert_queue();
|
||||
|
||||
void show_select_node_warning(bool p_show);
|
||||
|
||||
|
|
|
@ -434,6 +434,7 @@ void Skeleton3DEditor::insert_keys(bool p_all_bones) {
|
|||
String path = root->get_path_to(skeleton);
|
||||
|
||||
AnimationTrackEditor *te = AnimationPlayerEditor::get_singleton()->get_track_editor();
|
||||
te->make_insert_queue();
|
||||
for (int i = 0; i < bone_len; i++) {
|
||||
const String name = skeleton->get_bone_name(i);
|
||||
|
||||
|
@ -448,6 +449,7 @@ void Skeleton3DEditor::insert_keys(bool p_all_bones) {
|
|||
Transform3D tform = skeleton->get_bone_pose(i);
|
||||
te->insert_transform_key(skeleton, name, tform);
|
||||
}
|
||||
te->commit_insert_queue();
|
||||
}
|
||||
|
||||
void Skeleton3DEditor::pose_to_rest() {
|
||||
|
|
Loading…
Reference in a new issue