void AnimationTreeEditor::_edit_filters() { filter_dialog->popup_centered_ratio(); filter->clear(); Set<String> npb; _find_paths_for_filter(edited_node,npb); TreeItem *root = filter->create_item(); filter->set_hide_root(true); Map<String,TreeItem*> pm; Node *base = anim_tree->get_node( anim_tree->get_base_path() ); for(Set<String>::Element *E=npb.front();E;E=E->next()) { TreeItem *parent=root; String descr=E->get(); if (base) { NodePath np = E->get(); if (np.get_property()!=StringName()) { Node *n = base->get_node(np); Skeleton *s = n->cast_to<Skeleton>(); if (s) { String skelbase = E->get().substr(0,E->get().find(":")); int bidx = s->find_bone(np.get_property()); if (bidx!=-1) { int bparent = s->get_bone_parent(bidx); // if (bparent!=-1) { String bpn = skelbase+":"+s->get_bone_name(bparent); if (pm.has(bpn)) { parent=pm[bpn]; descr=np.get_property(); } } else { if (pm.has(skelbase)) { parent=pm[skelbase]; } } } } } } TreeItem *it = filter->create_item(parent); it->set_cell_mode(0,TreeItem::CELL_MODE_CHECK); it->set_text(0,descr); it->set_metadata(0,NodePath(E->get())); it->set_editable(0,true); if (anim_tree->node_get_type(edited_node)==AnimationTreePlayer::NODE_ONESHOT) { it->set_checked(0, anim_tree->oneshot_node_is_path_filtered(edited_node,E->get())); } else if (anim_tree->node_get_type(edited_node)==AnimationTreePlayer::NODE_BLEND2) { it->set_checked(0, anim_tree->blend2_node_is_path_filtered(edited_node,E->get())); } pm[E->get()]=it; } }
void EditorPropertyRootMotion::_node_assign() { NodePath current = get_edited_object()->get(get_edited_property()); AnimationTree *atree = Object::cast_to<AnimationTree>(get_edited_object()); if (!atree->has_node(atree->get_animation_player())) { EditorNode::get_singleton()->show_warning(TTR("AnimationTree has no path set to an AnimationPlayer")); return; } AnimationPlayer *player = Object::cast_to<AnimationPlayer>(atree->get_node(atree->get_animation_player())); if (!player) { EditorNode::get_singleton()->show_warning(TTR("Path to AnimationPlayer is invalid")); return; } Node *base = player->get_node(player->get_root()); if (!base) { EditorNode::get_singleton()->show_warning(TTR("Animation player has no valid root node path, so unable to retrieve track names.")); return; } Set<String> paths; { List<StringName> animations; player->get_animation_list(&animations); for (List<StringName>::Element *E = animations.front(); E; E = E->next()) { Ref<Animation> anim = player->get_animation(E->get()); for (int i = 0; i < anim->get_track_count(); i++) { paths.insert(anim->track_get_path(i)); } } } filters->clear(); TreeItem *root = filters->create_item(); Map<String, TreeItem *> parenthood; for (Set<String>::Element *E = paths.front(); E; E = E->next()) { NodePath path = E->get(); TreeItem *ti = NULL; String accum; for (int i = 0; i < path.get_name_count(); i++) { String name = path.get_name(i); if (accum != String()) { accum += "/"; } accum += name; if (!parenthood.has(accum)) { if (ti) { ti = filters->create_item(ti); } else { ti = filters->create_item(root); } parenthood[accum] = ti; ti->set_text(0, name); ti->set_selectable(0, false); ti->set_editable(0, false); if (base->has_node(accum)) { Node *node = base->get_node(accum); if (has_icon(node->get_class(), "EditorIcons")) { ti->set_icon(0, get_icon(node->get_class(), "EditorIcons")); } else { ti->set_icon(0, get_icon("Node", "EditorIcons")); } } } else { ti = parenthood[accum]; } } Node *node = NULL; if (base->has_node(accum)) { node = base->get_node(accum); } if (!node) continue; //no node, cant edit if (path.get_subname_count()) { String concat = path.get_concatenated_subnames(); Skeleton *skeleton = Object::cast_to<Skeleton>(node); if (skeleton && skeleton->find_bone(concat) != -1) { //path in skeleton String bone = concat; int idx = skeleton->find_bone(bone); List<String> bone_path; while (idx != -1) { bone_path.push_front(skeleton->get_bone_name(idx)); idx = skeleton->get_bone_parent(idx); } accum += ":"; for (List<String>::Element *F = bone_path.front(); F; F = F->next()) { if (F != bone_path.front()) { accum += "/"; } accum += F->get(); if (!parenthood.has(accum)) { ti = filters->create_item(ti); parenthood[accum] = ti; ti->set_text(0, F->get()); ti->set_selectable(0, true); ti->set_editable(0, false); ti->set_icon(0, get_icon("BoneAttachment", "EditorIcons")); ti->set_metadata(0, accum); } else { ti = parenthood[accum]; } } ti->set_selectable(0, true); ti->set_text(0, concat); ti->set_icon(0, get_icon("BoneAttachment", "EditorIcons")); ti->set_metadata(0, path); if (path == current) { ti->select(0); } } else { //just a property ti = filters->create_item(ti); ti->set_text(0, concat); ti->set_selectable(0, true); ti->set_metadata(0, path); if (path == current) { ti->select(0); } } } else { if (ti) { //just a node, likely call or animation track ti->set_selectable(0, true); ti->set_metadata(0, path); if (path == current) { ti->select(0); } } } } filters->ensure_cursor_is_visible(); filter_dialog->popup_centered_ratio(); }
bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &anode) { if (updating || _filter_edit != anode) return false; NodePath player_path = anode->get_tree()->get_animation_player(); if (!anode->get_tree()->has_node(player_path)) { EditorNode::get_singleton()->show_warning(TTR("No animation player set, so unable to retrieve track names.")); return false; } AnimationPlayer *player = Object::cast_to<AnimationPlayer>(anode->get_tree()->get_node(player_path)); if (!player) { EditorNode::get_singleton()->show_warning(TTR("Player path set is invalid, so unable to retrieve track names.")); return false; } Node *base = player->get_node(player->get_root()); if (!base) { EditorNode::get_singleton()->show_warning(TTR("Animation player has no valid root node path, so unable to retrieve track names.")); return false; } updating = true; Set<String> paths; { List<StringName> animations; player->get_animation_list(&animations); for (List<StringName>::Element *E = animations.front(); E; E = E->next()) { Ref<Animation> anim = player->get_animation(E->get()); for (int i = 0; i < anim->get_track_count(); i++) { paths.insert(anim->track_get_path(i)); } } } filter_enabled->set_pressed(anode->is_filter_enabled()); filters->clear(); TreeItem *root = filters->create_item(); Map<String, TreeItem *> parenthood; for (Set<String>::Element *E = paths.front(); E; E = E->next()) { NodePath path = E->get(); TreeItem *ti = NULL; String accum; for (int i = 0; i < path.get_name_count(); i++) { String name = path.get_name(i); if (accum != String()) { accum += "/"; } accum += name; if (!parenthood.has(accum)) { if (ti) { ti = filters->create_item(ti); } else { ti = filters->create_item(root); } parenthood[accum] = ti; ti->set_text(0, name); ti->set_selectable(0, false); ti->set_editable(0, false); if (base->has_node(accum)) { Node *node = base->get_node(accum); if (has_icon(node->get_class(), "EditorIcons")) { ti->set_icon(0, get_icon(node->get_class(), "EditorIcons")); } else { ti->set_icon(0, get_icon("Node", "EditorIcons")); } } } else { ti = parenthood[accum]; } } Node *node = NULL; if (base->has_node(accum)) { node = base->get_node(accum); } if (!node) continue; //no node, cant edit if (path.get_subname_count()) { String concat = path.get_concatenated_subnames(); Skeleton *skeleton = Object::cast_to<Skeleton>(node); if (skeleton && skeleton->find_bone(concat) != -1) { //path in skeleton String bone = concat; int idx = skeleton->find_bone(bone); List<String> bone_path; while (idx != -1) { bone_path.push_front(skeleton->get_bone_name(idx)); idx = skeleton->get_bone_parent(idx); } accum += ":"; for (List<String>::Element *F = bone_path.front(); F; F = F->next()) { if (F != bone_path.front()) { accum += "/"; } accum += F->get(); if (!parenthood.has(accum)) { ti = filters->create_item(ti); parenthood[accum] = ti; ti->set_text(0, F->get()); ti->set_selectable(0, false); ti->set_editable(0, false); ti->set_icon(0, get_icon("BoneAttachment", "EditorIcons")); } else { ti = parenthood[accum]; } } ti->set_editable(0, true); ti->set_selectable(0, true); ti->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); ti->set_text(0, concat); ti->set_checked(0, anode->is_path_filtered(path)); ti->set_icon(0, get_icon("BoneAttachment", "EditorIcons")); ti->set_metadata(0, path); } else { //just a property ti = filters->create_item(ti); ti->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); ti->set_text(0, concat); ti->set_editable(0, true); ti->set_selectable(0, true); ti->set_checked(0, anode->is_path_filtered(path)); ti->set_metadata(0, path); } } else { if (ti) { //just a node, likely call or animation track ti->set_editable(0, true); ti->set_selectable(0, true); ti->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); ti->set_checked(0, anode->is_path_filtered(path)); ti->set_metadata(0, path); } } } updating = false; return true; }
Error EditorSceneImporterFBXConv::_parse_animations(State& state) { AnimationPlayer *ap = memnew( AnimationPlayer ); state.scene->add_child(ap); ap->set_owner(state.scene); for(int i=0;i<state.animations.size();i++) { Dictionary anim = state.animations[i]; ERR_CONTINUE(!anim.has("id")); Ref<Animation> an = memnew( Animation ); an->set_name(_id(anim["id"])); if (anim.has("bones")) { Array bone_tracks = anim["bones"]; for(int j=0;j<bone_tracks.size();j++) { Dictionary bone_track=bone_tracks[j]; String bone = bone_track["boneId"]; if (!bone_track.has("keyframes")) continue; if (!state.bones.has(bone)) continue; Skeleton *sk = state.bones[bone].skeleton; if (!sk) continue; int bone_idx=sk->find_bone(bone); if (bone_idx==-1) continue; String path = state.scene->get_path_to(sk); path+=":"+bone; an->add_track(Animation::TYPE_TRANSFORM); int tidx = an->get_track_count()-1; an->track_set_path(tidx,path); Dictionary parent_xform_dict; Dictionary xform_dict; if (state.bones.has(bone)) { xform_dict=state.bones[bone].node; } Array parent_keyframes; if (sk->get_bone_parent(bone_idx)!=-1) { String parent_name = sk->get_bone_name(sk->get_bone_parent(bone_idx)); if (state.bones.has(parent_name)) { parent_xform_dict=state.bones[parent_name].node; } print_line("parent for "+bone+"? "+parent_name+" XFD: "+String(Variant(parent_xform_dict))); for(int k=0;k<bone_tracks.size();k++) { Dictionary d = bone_tracks[k]; if (d["boneId"]==parent_name) { parent_keyframes=d["keyframes"]; print_line("found keyframes"); break; } } } print_line("BONE XFD "+String(Variant(xform_dict))); Array keyframes=bone_track["keyframes"]; for(int k=0;k<keyframes.size();k++) { Dictionary key=keyframes[k]; Transform xform=_get_transform_mixed(key,xform_dict); float time = key["keytime"]; time=time/1000.0; #if 0 if (parent_keyframes.size()) { //localize print_line(itos(k)+" localizate for: "+bone); float prev_kt=-1; float kt; int idx=0; for(int l=0;l<parent_keyframes.size();l++) { Dictionary d=parent_keyframes[l]; kt=d["keytime"]; kt=kt/1000.0; if (kt>time) break; prev_kt=kt; idx++; } Transform t; if (idx==0) { t=_get_transform_mixed(parent_keyframes[0],parent_xform_dict); } else if (idx==parent_keyframes.size()){ t=_get_transform_mixed(parent_keyframes[idx-1],parent_xform_dict); } else { t=_get_transform_mixed(parent_keyframes[idx-1],parent_xform_dict); float d = (time-prev_kt)/(kt-prev_kt); if (d>0) { Transform t2=_get_transform_mixed(parent_keyframes[idx],parent_xform_dict); t=t.interpolate_with(t2,d); } else { print_line("exact: "+rtos(kt)); } } xform = t.affine_inverse() * xform; //localize } else if (!parent_xform_dict.empty()) { Transform t = _get_transform(parent_xform_dict); xform = t.affine_inverse() * xform; //localize } #endif xform = sk->get_bone_rest(bone_idx).affine_inverse() * xform; Quat q = xform.basis; q.normalize(); Vector3 s = xform.basis.get_scale(); Vector3 l = xform.origin; an->transform_track_insert_key(tidx,time,l,q,s); } } } ap->add_animation(_id(anim["id"]),an); } return OK; }