void SceneTreeDock::_node_prerenamed(Node* p_node, const String& p_new_name) { List<Pair<NodePath,NodePath> > path_renames; Vector<StringName> base_path; Node *n = p_node->get_parent(); while(n) { base_path.push_back(n->get_name()); n=n->get_parent(); } base_path.invert(); Vector<StringName> new_base_path=base_path; base_path.push_back(p_node->get_name()); new_base_path.push_back(p_new_name); Pair<NodePath,NodePath> npp; npp.first = NodePath(base_path,true); npp.second = NodePath(new_base_path,true); path_renames.push_back(npp); for(int i=0;i<p_node->get_child_count();i++) _fill_path_renames(base_path,new_base_path,p_node->get_child(i),&path_renames); perform_node_renames(NULL,&path_renames); }
void SceneTreeDock::_delete_confirm() { List<Node*> remove_list = editor_selection->get_selected_node_list(); if (remove_list.empty()) return; if (editor->get_editor_plugin_over()) editor->get_editor_plugin_over()->make_visible(false); editor_data->get_undo_redo().create_action("Remove Node(s)"); bool entire_scene=false; for(List<Node*>::Element *E=remove_list.front();E;E=E->next()) { if (E->get()==edited_scene) { entire_scene=true; } } if (entire_scene) { editor_data->get_undo_redo().add_do_method(editor,"set_edited_scene",(Object*)NULL); editor_data->get_undo_redo().add_undo_method(editor,"set_edited_scene",edited_scene); editor_data->get_undo_redo().add_undo_method(edited_scene,"set_owner",edited_scene->get_owner()); editor_data->get_undo_redo().add_undo_reference(edited_scene); } else { remove_list.sort_custom<Node::Comparator>(); //sort nodes to keep positions List<Pair<NodePath,NodePath> > path_renames; //delete from animation for(List<Node*>::Element *E=remove_list.front();E;E=E->next()) { Node *n = E->get(); if (!n->is_inside_scene() || !n->get_parent()) continue; fill_path_renames(n,NULL,&path_renames); } perform_node_renames(NULL,&path_renames); //delete for read for(List<Node*>::Element *E=remove_list.front();E;E=E->next()) { Node *n = E->get(); if (!n->is_inside_scene() || !n->get_parent()) continue; List<Node*> owned; n->get_owned_by(n->get_owner(),&owned); Array owners; for(List<Node*>::Element *E=owned.front();E;E=E->next()) { owners.push_back(E->get()); } editor_data->get_undo_redo().add_do_method(n->get_parent(),"remove_child",n); editor_data->get_undo_redo().add_undo_method(n->get_parent(),"add_child",n); editor_data->get_undo_redo().add_undo_method(n->get_parent(),"move_child",n,n->get_index()); if (editor->get_animation_editor()->get_root()==n) editor_data->get_undo_redo().add_undo_method(editor->get_animation_editor(),"set_root",n); editor_data->get_undo_redo().add_undo_method(this,"_set_owners",edited_scene,owners); //editor_data->get_undo_redo().add_undo_method(n,"set_owner",n->get_owner()); editor_data->get_undo_redo().add_undo_reference(n); } } editor_data->get_undo_redo().commit_action(); _update_tool_buttons(); }
void SceneTreeDock::_node_reparent(NodePath p_path,bool p_node_only) { Node *node = scene_tree->get_selected(); ERR_FAIL_COND(!node); ERR_FAIL_COND(node==edited_scene); Node *new_parent = scene_root->get_node(p_path); ERR_FAIL_COND(!new_parent); Node *validate=new_parent; while(validate) { if (editor_selection->is_selected(validate)) { ERR_EXPLAIN("Selection changed at some point.. can't reparent"); ERR_FAIL(); return; } validate=validate->get_parent(); } //ok all valid List<Node*> selection = editor_selection->get_selected_node_list(); if (selection.empty()) return; //nothing to reparent //sort by tree order, so re-adding is easy selection.sort_custom<Node::Comparator>(); editor_data->get_undo_redo().create_action("Reparent Node"); List<Pair<NodePath,NodePath> > path_renames; for(List<Node*>::Element *E=selection.front();E;E=E->next()) { //no undo for now, sorry Node *node = E->get(); fill_path_renames(node,new_parent,&path_renames); List<Node*> owned; node->get_owned_by(node->get_owner(),&owned); Array owners; for(List<Node*>::Element *E=owned.front();E;E=E->next()) { owners.push_back(E->get()); } editor_data->get_undo_redo().add_do_method(node->get_parent(),"remove_child",node); editor_data->get_undo_redo().add_do_method(new_parent,"add_child",node); editor_data->get_undo_redo().add_do_method(this,"_set_owners",edited_scene,owners); if (editor->get_animation_editor()->get_root()==node) editor_data->get_undo_redo().add_do_method(editor->get_animation_editor(),"set_root",node); editor_data->get_undo_redo().add_undo_method(new_parent,"remove_child",node); } //add and move in a second step.. (so old order is preserved) for(List<Node*>::Element *E=selection.front();E;E=E->next()) { Node *node = E->get(); List<Node*> owned; node->get_owned_by(node->get_owner(),&owned); Array owners; for(List<Node*>::Element *E=owned.front();E;E=E->next()) { owners.push_back(E->get()); } int child_pos = node->get_position_in_parent(); editor_data->get_undo_redo().add_undo_method(node->get_parent(),"add_child",node); editor_data->get_undo_redo().add_undo_method(node->get_parent(),"move_child",node,child_pos); editor_data->get_undo_redo().add_undo_method(this,"_set_owners",edited_scene,owners); if (editor->get_animation_editor()->get_root()==node) editor_data->get_undo_redo().add_undo_method(editor->get_animation_editor(),"set_root",node); } perform_node_renames(NULL,&path_renames); editor_data->get_undo_redo().commit_action(); //node->set_owner(owner); }
void SceneTreeDock::perform_node_renames(Node* p_base,List<Pair<NodePath,NodePath> > *p_renames, Map<Ref<Animation>, Set<int> > *r_rem_anims) { Map<Ref<Animation>, Set<int> > rem_anims; if (!r_rem_anims) r_rem_anims=&rem_anims; if (!bool(EDITOR_DEF("animation/autorename_animation_tracks",true))) return; if (!p_base) { p_base=edited_scene; } if (!p_base) return; if (p_base->cast_to<AnimationPlayer>()) { AnimationPlayer *ap=p_base->cast_to<AnimationPlayer>(); List<StringName> anims; ap->get_animation_list(&anims); Node *root = ap->get_node(ap->get_root()); if (root) { NodePath root_path=root->get_path(); NodePath new_root_path=root_path; for(List<Pair<NodePath,NodePath> >::Element* E=p_renames->front();E;E=E->next()) { if (E->get().first==root_path) { new_root_path=E->get().second; break; } } if (new_root_path!=NodePath()) { //will not be erased for(List<StringName>::Element *E=anims.front();E;E=E->next()) { Ref<Animation> anim=ap->get_animation(E->get()); if (!r_rem_anims->has(anim)) { r_rem_anims->insert(anim,Set<int>()); Set<int> &ran = r_rem_anims->find(anim)->get(); for(int i=0;i<anim->get_track_count();i++) ran.insert(i); } Set<int> &ran = r_rem_anims->find(anim)->get(); if (anim.is_null()) continue; for(int i=0;i<anim->get_track_count();i++) { NodePath track_np=anim->track_get_path(i); Node *n = root->get_node(track_np); if (!n) { continue; } NodePath old_np = n->get_path(); if (!ran.has(i)) continue; //channel was removed for(List<Pair<NodePath,NodePath> >::Element* E=p_renames->front();E;E=E->next()) { if (E->get().first==old_np) { if (E->get().second==NodePath()) { //will be erased int idx=0; Set<int>::Element *EI=ran.front(); ERR_FAIL_COND(!EI); //bug while(EI->get()!=i) { idx++; EI=EI->next(); ERR_FAIL_COND(!EI); //another bug } editor_data->get_undo_redo().add_do_method(anim.ptr(),"remove_track",idx); editor_data->get_undo_redo().add_undo_method(anim.ptr(),"add_track",anim->track_get_type(i),idx); editor_data->get_undo_redo().add_undo_method(anim.ptr(),"track_set_path",idx,track_np); editor_data->get_undo_redo().add_undo_method(anim.ptr(),"track_set_interpolation_type",idx,anim->track_get_interpolation_type(i)); for(int j=0;j<anim->track_get_key_count(i);j++) { editor_data->get_undo_redo().add_undo_method(anim.ptr(),"track_insert_key",idx,anim->track_get_key_time(i,j),anim->track_get_key_value(i,j),anim->track_get_key_transition(i,j)); } ran.erase(i); //byebye channel } else { //will be renamed NodePath rel_path = new_root_path.rel_path_to(E->get().second); NodePath new_path = NodePath( rel_path.get_names(), track_np.get_subnames(), false, track_np.get_property() ); if (new_path==track_np) continue; //bleh editor_data->get_undo_redo().add_do_method(anim.ptr(),"track_set_path",i,new_path); editor_data->get_undo_redo().add_undo_method(anim.ptr(),"track_set_path",i,track_np); } } } } } } } } for(int i=0;i<p_base->get_child_count();i++) perform_node_renames(p_base->get_child(i),p_renames,r_rem_anims); }
void SceneTreeDock::_node_reparent(NodePath p_path,bool p_keep_global_xform) { Node *node = scene_tree->get_selected(); ERR_FAIL_COND(!node); ERR_FAIL_COND(node==edited_scene); Node *new_parent = scene_root->get_node(p_path); ERR_FAIL_COND(!new_parent); Node *validate=new_parent; while(validate) { if (editor_selection->is_selected(validate)) { ERR_EXPLAIN("Selection changed at some point.. can't reparent"); ERR_FAIL(); return; } validate=validate->get_parent(); } //ok all valid List<Node*> selection = editor_selection->get_selected_node_list(); if (selection.empty()) return; //nothing to reparent //sort by tree order, so re-adding is easy selection.sort_custom<Node::Comparator>(); editor_data->get_undo_redo().create_action("Reparent Node"); List<Pair<NodePath,NodePath> > path_renames; for(List<Node*>::Element *E=selection.front();E;E=E->next()) { //no undo for now, sorry Node *node = E->get(); fill_path_renames(node,new_parent,&path_renames); List<Node*> owned; node->get_owned_by(node->get_owner(),&owned); Array owners; for(List<Node*>::Element *E=owned.front();E;E=E->next()) { owners.push_back(E->get()); } editor_data->get_undo_redo().add_do_method(node->get_parent(),"remove_child",node); editor_data->get_undo_redo().add_do_method(new_parent,"add_child",node); ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger(); String new_name = new_parent->validate_child_name(node->get_name()); editor_data->get_undo_redo().add_do_method(sed,"live_debug_reparent_node",edited_scene->get_path_to(node),edited_scene->get_path_to(new_parent),new_name,-1); editor_data->get_undo_redo().add_undo_method(sed,"live_debug_reparent_node",NodePath(String(edited_scene->get_path_to(new_parent))+"/"+new_name),edited_scene->get_path_to(node->get_parent()),node->get_name(),node->get_index()); if (p_keep_global_xform) { if (node->cast_to<Node2D>()) editor_data->get_undo_redo().add_do_method(node,"set_global_transform",node->cast_to<Node2D>()->get_global_transform()); if (node->cast_to<Spatial>()) editor_data->get_undo_redo().add_do_method(node,"set_global_transform",node->cast_to<Spatial>()->get_global_transform()); if (node->cast_to<Control>()) { bool can_do_it=false; Control *c=node->cast_to<Control>(); if (c->get_parent()->cast_to<Container>()) can_do_it=false; for(int i=0;i<4;i++) { if (c->get_anchor(Margin(i))!=ANCHOR_BEGIN) can_do_it=false; } editor_data->get_undo_redo().add_do_method(node,"set_global_pos",node->cast_to<Control>()->get_global_pos()); } } editor_data->get_undo_redo().add_do_method(this,"_set_owners",edited_scene,owners); if (AnimationPlayerEditor::singleton->get_key_editor()->get_root()==node) editor_data->get_undo_redo().add_do_method(AnimationPlayerEditor::singleton->get_key_editor(),"set_root",node); editor_data->get_undo_redo().add_undo_method(new_parent,"remove_child",node); } //add and move in a second step.. (so old order is preserved) for(List<Node*>::Element *E=selection.front();E;E=E->next()) { Node *node = E->get(); List<Node*> owned; node->get_owned_by(node->get_owner(),&owned); Array owners; for(List<Node*>::Element *E=owned.front();E;E=E->next()) { owners.push_back(E->get()); } int child_pos = node->get_position_in_parent(); editor_data->get_undo_redo().add_undo_method(node->get_parent(),"add_child",node); editor_data->get_undo_redo().add_undo_method(node->get_parent(),"move_child",node,child_pos); editor_data->get_undo_redo().add_undo_method(this,"_set_owners",edited_scene,owners); if (AnimationPlayerEditor::singleton->get_key_editor()->get_root()==node) editor_data->get_undo_redo().add_undo_method(AnimationPlayerEditor::singleton->get_key_editor(),"set_root",node); if (p_keep_global_xform) { if (node->cast_to<Node2D>()) editor_data->get_undo_redo().add_undo_method(node,"set_transform",node->cast_to<Node2D>()->get_transform()); if (node->cast_to<Spatial>()) editor_data->get_undo_redo().add_undo_method(node,"set_transform",node->cast_to<Spatial>()->get_transform()); if (node->cast_to<Control>()) { bool can_do_it=false; Control *c=node->cast_to<Control>(); if (c->get_parent()->cast_to<Container>()) can_do_it=false; for(int i=0;i<4;i++) { if (c->get_anchor(Margin(i))!=ANCHOR_BEGIN) can_do_it=false; } editor_data->get_undo_redo().add_undo_method(node,"set_pos",node->cast_to<Control>()->get_pos()); } } } perform_node_renames(NULL,&path_renames); editor_data->get_undo_redo().commit_action(); //node->set_owner(owner); }