const char* scale_scene_node(const char *node, point_t center, scalar_t factor[3] ) { scene_node_t *nodePtr; matrixgl_t matrix; if ( get_scene_node( node, &nodePtr ) != TCL_OK ) { return "No such node"; } make_translation_matrix( matrix, -center.x, -center.y, -center.z ); multiply_matrices( nodePtr->trans, nodePtr->trans, matrix ); make_translation_matrix( matrix, center.x, center.y, center.z ); multiply_matrices( nodePtr->invtrans, matrix, nodePtr->invtrans ); make_scaling_matrix( matrix, factor[0], factor[1], factor[2] ); multiply_matrices( nodePtr->trans, nodePtr->trans, matrix ); make_scaling_matrix( matrix, 1./factor[0], 1./factor[1], 1./factor[2] ); multiply_matrices( nodePtr->invtrans, matrix, nodePtr->invtrans ); make_translation_matrix( matrix, center.x, center.y, center.z ); multiply_matrices( nodePtr->trans, nodePtr->trans, matrix ); make_translation_matrix( matrix, -center.x, -center.y, -center.z ); multiply_matrices( nodePtr->invtrans, matrix, nodePtr->invtrans ); return NULL; }
void scale_scene_node(const std::string& node, const ppogl::Vec3d& center, const ppogl::Vec3d& factor) { SceneNode *nodePtr; if(get_scene_node(node, &nodePtr)!=true){ PP_WARNING("No such node"); return; } pp::Matrix matrix; matrix.makeTranslation( -center.x(), -center.y(), -center.z() ); nodePtr->trans=nodePtr->trans*matrix; matrix.makeTranslation( center.x(), center.y(), center.z() ); nodePtr->invtrans=matrix*nodePtr->invtrans; matrix.makeScaling( factor.values[0], factor.values[1], factor.values[2] ); nodePtr->trans=nodePtr->trans*matrix; matrix.makeScaling( 1./factor.values[0], 1./factor.values[1], 1./factor.values[2] ); nodePtr->invtrans=matrix*nodePtr->invtrans; matrix.makeTranslation( center.x(), center.y(), center.z() ); nodePtr->trans=nodePtr->trans*matrix; matrix.makeTranslation( -center.x(), -center.y(), -center.z() ); nodePtr->invtrans=matrix*nodePtr->invtrans; }
void SceneTreeEditor::_node_visibility_changed(Node *p_node) { if (p_node != get_scene_node() && !p_node->get_owner()) { return; } TreeItem *item = p_node ? _find(tree->get_root(), p_node->get_path()) : NULL; if (!item) { return; } int idx = item->get_button_by_id(0, BUTTON_VISIBILITY); ERR_FAIL_COND(idx == -1); bool visible = false; if (p_node->is_class("CanvasItem")) { visible = p_node->call("is_visible"); CanvasItemEditor::get_singleton()->get_viewport_control()->update(); } else if (p_node->is_class("Spatial")) { visible = p_node->call("is_visible"); } if (visible) item->set_button(0, idx, get_icon("GuiVisibilityVisible", "EditorIcons")); else item->set_button(0, idx, get_icon("GuiVisibilityHidden", "EditorIcons")); _update_visibility_color(p_node, item); }
void SceneTreeEditor::_node_visibility_changed(Node *p_node) { if (p_node!=get_scene_node() && !p_node->get_owner()) { return; } TreeItem* item=p_node?_find(tree->get_root(),p_node->get_path()):NULL; if (!item) { return; } int idx=item->get_button_by_id(0,BUTTON_VISIBILITY); ERR_FAIL_COND(idx==-1); bool visible=false; if (p_node->is_type("CanvasItem")) { visible = !p_node->call("is_hidden"); } else if (p_node->is_type("Spatial")) { visible = !p_node->call("is_hidden"); } if (!visible) item->set_button(0,idx,get_icon("Hidden","EditorIcons")); else item->set_button(0,idx,get_icon("Visible","EditorIcons")); }
void SceneTreeEditor::_update_tree() { if (!is_inside_tree()) { tree_dirty = false; return; } updating_tree = true; tree->clear(); if (get_scene_node()) { _add_nodes(get_scene_node(), NULL); last_hash = hash_djb2_one_64(0); _compute_hash(get_scene_node(), last_hash); } updating_tree = false; tree_dirty = false; }
Variant SceneTreeEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) { if (!can_rename) return Variant(); //not editable tree Vector<Node *> selected; Vector<Ref<Texture> > icons; TreeItem *next = tree->get_next_selected(NULL); while (next) { NodePath np = next->get_metadata(0); Node *n = get_node(np); if (n) { // Only allow selection if not part of an instanced scene. if (!n->get_owner() || n->get_owner() == get_scene_node() || n->get_owner()->get_filename() == String()) { selected.push_back(n); icons.push_back(next->get_icon(0)); } } next = tree->get_next_selected(next); } if (selected.empty()) return Variant(); VBoxContainer *vb = memnew(VBoxContainer); Array objs; int list_max = 10; float opacity_step = 1.0f / list_max; float opacity_item = 1.0f; for (int i = 0; i < selected.size(); i++) { if (i < list_max) { HBoxContainer *hb = memnew(HBoxContainer); TextureRect *tf = memnew(TextureRect); tf->set_texture(icons[i]); hb->add_child(tf); Label *label = memnew(Label(selected[i]->get_name())); hb->add_child(label); vb->add_child(hb); hb->set_modulate(Color(1, 1, 1, opacity_item)); opacity_item -= opacity_step; } NodePath p = selected[i]->get_path(); objs.push_back(p); } set_drag_preview(vb); Dictionary drag_data; drag_data["type"] = "nodes"; drag_data["nodes"] = objs; tree->set_drop_mode_flags(Tree::DROP_MODE_INBETWEEN | Tree::DROP_MODE_ON_ITEM); emit_signal("nodes_dragged"); return drag_data; }
void SEObjectBase::set_visible(bool _visible) { Entity* entity = get_entity(); SceneNode *node = get_scene_node(); if(_visible) node->attachObject(entity); else node->detachObject(entity); }
void draw_scene_graph(const std::string& node) { SceneNode *nodePtr; if(get_scene_node( node, &nodePtr ) != true){ PP_ERROR( "draw_scene_graph: No such node: " << node); } traverse_dag( nodePtr, &g_hier_default_material ); }
void SceneTreeEditor::_test_update_tree() { pending_test_update=false; if (!is_inside_tree()) return; if(tree_dirty) return; // don't even bother uint64_t hash = hash_djb2_one_64(0); if (get_scene_node()) _compute_hash(get_scene_node(),hash); //test hash if (hash==last_hash) return; // did not change MessageQueue::get_singleton()->push_call(this,"_update_tree"); tree_dirty=true; }
void draw_scene_graph(const char *node ) { scene_node_t *nodePtr; if ( get_scene_node( node, &nodePtr ) != TCL_OK ) { handle_error( 1, "draw_scene_graph: No such node `%s'", node ); } traverse_dag( nodePtr, &g_hier_default_material ); }
void transform_scene_node(const std::string& node, const pp::Matrix& mat, const pp::Matrix& invmat ) { SceneNode *nodePtr; if(get_scene_node(node, &nodePtr)!=true){ PP_WARNING("No such node"); return; } nodePtr->trans=nodePtr->trans*mat; nodePtr->invtrans=invmat*nodePtr->invtrans; }
void reset_scene_node(const std::string& node) { SceneNode *nodePtr; if(get_scene_node( node, &nodePtr )!= true){ // node doesn't exist return; } nodePtr->trans.makeIdentity(); nodePtr->invtrans.makeIdentity(); }
const char* reset_scene_node( const char *node ) { scene_node_t *nodePtr; if ( get_scene_node( node, &nodePtr ) != TCL_OK ) { return "No such node"; } make_identity_matrix( nodePtr->trans ); make_identity_matrix( nodePtr->invtrans ); return NULL; }
const char* transform_scene_node(const char *node, matrixgl_t mat, matrixgl_t invmat ) { scene_node_t *nodePtr; if ( get_scene_node( node, &nodePtr ) != TCL_OK ) { return "No such node"; } multiply_matrices( nodePtr->trans, nodePtr->trans, mat ); multiply_matrices( nodePtr->invtrans, invmat, nodePtr->invtrans ); return NULL; }
bool_t collide(const char *node, polyhedron_t ph ) { scene_node_t *nodePtr; matrixgl_t mat, invmat; make_identity_matrix( mat ); make_identity_matrix( invmat ); if ( get_scene_node( node, &nodePtr ) != TCL_OK ) { handle_error( 1, "draw_scene_graph: No such node `%s'", node ); } return check_polyhedron_collision_with_dag( nodePtr, mat, invmat, ph ); }
bool collide(const std::string& node, const ppogl::Polyhedron& ph) { SceneNode *nodePtr; if(get_scene_node(node, &nodePtr) != true){ PP_ERROR( "draw_scene_graph: No such node: " << node ); } pp::Matrix mat, invmat; mat.makeIdentity(); invmat.makeIdentity(); return check_polyhedron_collision_with_dag( nodePtr, mat, invmat, ph ); }
const char* rotate_scene_node( const char *node, char axis, scalar_t angle ) { scene_node_t *nodePtr; matrixgl_t rotMatrix; if ( get_scene_node( node, &nodePtr ) != TCL_OK ) { return "No such node"; } make_rotation_matrix( rotMatrix, angle, axis ); multiply_matrices( nodePtr->trans, nodePtr->trans, rotMatrix ); make_rotation_matrix( rotMatrix, -angle, axis ); multiply_matrices( nodePtr->invtrans, rotMatrix, nodePtr->invtrans ); return NULL; }
const char* translate_scene_node(const char *node, vector_t vec ) { scene_node_t *nodePtr; matrixgl_t xlateMatrix; if ( get_scene_node( node, &nodePtr ) != TCL_OK ) { return "No such node"; } make_translation_matrix( xlateMatrix, vec.x, vec.y, vec.z ); multiply_matrices( nodePtr->trans, nodePtr->trans, xlateMatrix ); make_translation_matrix( xlateMatrix, -vec.x, -vec.y, -vec.z ); multiply_matrices( nodePtr->invtrans, xlateMatrix, nodePtr->invtrans ); return NULL; }
void translate_scene_node(const std::string& node, const ppogl::Vec3d& vec ) { SceneNode *nodePtr; if(get_scene_node( node, &nodePtr ) != true){ PP_WARNING("No such node"); return; } pp::Matrix xlateMatrix; xlateMatrix.makeTranslation( vec.x(), vec.y(), vec.z() ); nodePtr->trans=nodePtr->trans*xlateMatrix; xlateMatrix.makeTranslation( -vec.x(), -vec.y(), -vec.z() ); nodePtr->invtrans=xlateMatrix*nodePtr->invtrans; }
void rotate_scene_node(const std::string& node, ppogl::Axis axis, double angle ) { SceneNode *nodePtr; if(get_scene_node( node, &nodePtr )!= true){ PP_WARNING("No such node"); return; } pp::Matrix rotMatrix; rotMatrix.makeRotation( angle, axis ); nodePtr->trans=nodePtr->trans*rotMatrix; rotMatrix.makeRotation( -angle, axis ); nodePtr->invtrans=rotMatrix*nodePtr->invtrans; }
const char* set_scene_node_material(const char *node,const char *mat ) { material_t *matPtr; scene_node_t *nodePtr; if ( get_scene_node( node, &nodePtr ) != TCL_OK ) { return "No such node"; } if ( get_material( mat, &matPtr ) != TCL_OK ) { return "No such material"; } nodePtr->mat = matPtr; return NULL; }
const char* set_scene_node_shadow_state(const char *node, const char *state ) { scene_node_t *nodePtr; if ( get_scene_node( node, &nodePtr ) != TCL_OK ) { return "No such node"; } if ( strcmp( state, "off" ) == 0 ) { nodePtr->render_shadow = False; } else if ( strcmp ( state, "on" ) == 0 ) { nodePtr->render_shadow = True; } else { return "Shadow state must be 'on' or 'off'"; } return NULL; }
void set_scene_node_material(const std::string& node, const std::string& mat) { SceneNode *nodePtr; if(get_scene_node(node, &nodePtr) != true){ PP_WARNING("No such node"); return; } ppogl::Material *matPtr; if(get_material( mat, &matPtr ) != true){ PP_WARNING("No such material"); return; } nodePtr->mat = matPtr; }
void set_scene_node_shadow_state(const std::string& node, const std::string& state) { SceneNode *nodePtr; if(get_scene_node(node, &nodePtr) != true){ PP_WARNING("No such node"); return; } if(state=="off"){ nodePtr->renderShadow = false; }else if(state=="on"){ nodePtr->renderShadow = true; } else { PP_WARNING("Shadow state must be 'on' or 'off'"); return; } }
/** Creates a new node, add the node to the hash table, and inserts the node into the DAG. Default values are given to all fields except the type-specific ones (geom, param). */ std::string create_scene_node(const std::string& parent_name, const std::string& child_name, SceneNode **node ) { SceneNode *parent; if(get_scene_node(parent_name, &parent) != true){ return "Parent node does not exist"; } SceneNode* child = new SceneNode; PP_CHECK_ALLOC(child); // Initialize node child->parent = parent; child->next = NULL; child->child = NULL; child->mat = NULL; child->renderShadow = true; child->trans.makeIdentity(); child->invtrans.makeIdentity(); if(add_scene_node(parent_name, child_name, child ) != true){ delete child; return "Child already exists"; } // Add node to parent's children if ( parent != NULL ) { if ( parent->child == NULL ) { parent->child = child; } else { for (parent = parent->child; parent->next != NULL; parent = parent->next) {/* do nothing */} parent->next = child; } } *node = child; return ""; }
/* Creates a new node, add the node to the hash table, and inserts the node into the DAG. Default values are given to all fields except the type-specific ones (geom, param). */ char* create_scene_node( const char *parent_name, const char *child_name, scene_node_t **node ) { scene_node_t *parent, *child; if ( get_scene_node( parent_name, &parent ) != TCL_OK ) { return "Parent node does not exist"; } /* Create node */ child = (scene_node_t *)malloc( sizeof( scene_node_t ) ); /* Initialize node */ child->parent = parent; child->next = NULL; child->child = NULL; child->mat = NULL; child->render_shadow = True; child->eye = False; make_identity_matrix( child->trans ); make_identity_matrix( child->invtrans ); if ( add_scene_node( parent_name, child_name, child ) != TCL_OK ) { free( child ); return "Child already exists"; } /* Add node to parent's children */ if ( parent != NULL ) { if ( parent->child == NULL ) { parent->child = child; } else { for (parent = parent->child; parent->next != NULL; parent = parent->next) {/* do nothing */} parent->next = child; } } *node = child; return NULL; }
point_t get_tux_view_pt( player_data_t *plyr ) { matrixgl_t trans; char *tux_root_node_name; scene_node_t *tux_root_node; make_identity_matrix( trans ); tux_root_node_name = get_tux_root_node(); if ( get_scene_node( tux_root_node_name, &tux_root_node ) != TCL_OK ) { check_assertion(0, "couldn't load tux's root node" ); } traverse_dag_for_view_point( tux_root_node, trans ); tux_view_pt = move_point( tux_view_pt, scale_vector( 0.2, plyr->plane_nml ) ); return tux_view_pt; }
const char* set_scene_node_eye(const char *node, const char *which_eye ) { scene_node_t *nodePtr; if ( get_scene_node( node, &nodePtr ) != TCL_OK ) { return "No such node"; } if ( strcmp( which_eye, "right" ) == 0 ) { nodePtr->eye = True; nodePtr->which_eye = TuxRightEye; } else if ( strcmp ( which_eye, "left" ) == 0 ) { nodePtr->eye = True; nodePtr->which_eye = TuxLeftEye; } else { return "'eye' must be right or left"; } return NULL; }
bool SceneTreeEditor::_add_nodes(Node *p_node,TreeItem *p_parent) { if (!p_node) return false; // only owned nodes are editable, since nodes can create their own (manually owned) child nodes, // which the editor needs not to know about. bool part_of_subscene=false; if (!display_foreign && p_node->get_owner()!=get_scene_node() && p_node!=get_scene_node()) { if ((show_enabled_subscene || can_open_instance) && p_node->get_owner() && (get_scene_node()->is_editable_instance(p_node->get_owner()))) { part_of_subscene=true; //allow } else { return false; } } else { part_of_subscene = p_node!=get_scene_node() && get_scene_node()->get_scene_inherited_state().is_valid() && get_scene_node()->get_scene_inherited_state()->find_node_by_path(get_scene_node()->get_path_to(p_node))>=0; } TreeItem *item = tree->create_item(p_parent); item->set_text(0, p_node->get_name() ); if (can_rename && !part_of_subscene /*(p_node->get_owner() == get_scene_node() || p_node==get_scene_node())*/) item->set_editable(0, true); item->set_selectable(0,true); if (can_rename) { #ifdef ENABLE_DEPRECATED if (p_node->has_meta("_editor_collapsed")) { //remove previous way of storing folding, which did not get along with scene inheritance and instancing if ((bool)p_node->get_meta("_editor_collapsed")) p_node->set_display_folded(true); p_node->set_meta("_editor_collapsed",Variant()); } #endif bool collapsed = p_node->is_displayed_folded(); if (collapsed) item->set_collapsed(true); } Ref<Texture> icon; if (p_node->has_meta("_editor_icon")) icon=p_node->get_meta("_editor_icon"); else icon=get_icon( (has_icon(p_node->get_type(),"EditorIcons")?p_node->get_type():String("Object")),"EditorIcons"); item->set_icon(0, icon ); item->set_metadata( 0,p_node->get_path() ); if (part_of_subscene) { //item->set_selectable(0,marked_selectable); item->set_custom_color(0,Color(0.8,0.4,0.20)); } else if (marked.has(p_node)) { item->set_selectable(0,marked_selectable); item->set_custom_color(0,Color(0.8,0.1,0.10)); } else if (!marked_selectable && !marked_children_selectable) { Node *node=p_node; while(node) { if (marked.has(node)) { item->set_selectable(0,false); item->set_custom_color(0,Color(0.8,0.1,0.10)); break; } node=node->get_parent(); } } if (can_rename) { //should be can edit.. String warning = p_node->get_configuration_warning(); if (warning!=String()) { item->add_button(0,get_icon("NodeWarning","EditorIcons"),BUTTON_WARNING); } bool has_connections = p_node->has_persistent_signal_connections(); bool has_groups = p_node->has_persistent_groups(); if (has_connections && has_groups) { item->add_button(0,get_icon("ConnectionAndGroups","EditorIcons"),BUTTON_SIGNALS); } else if (has_connections) { item->add_button(0,get_icon("Connect","EditorIcons"),BUTTON_SIGNALS); } else if (has_groups) { item->add_button(0,get_icon("Groups","EditorIcons"),BUTTON_GROUPS); } } if (p_node==get_scene_node() && p_node->get_scene_inherited_state().is_valid()) { item->add_button(0,get_icon("InstanceOptions","EditorIcons"),BUTTON_SUBSCENE); item->set_tooltip(0,TTR("Inherits:")+" "+p_node->get_scene_inherited_state()->get_path()+"\n"+TTR("Type:")+" "+p_node->get_type()); } else if (p_node!=get_scene_node() && p_node->get_filename()!="" && can_open_instance) { item->add_button(0,get_icon("InstanceOptions","EditorIcons"),BUTTON_SUBSCENE); item->set_tooltip(0,TTR("Instance:")+" "+p_node->get_filename()+"\n"+TTR("Type:")+" "+p_node->get_type()); } else { item->set_tooltip(0,String(p_node->get_name())+"\n"+TTR("Type:")+" "+p_node->get_type()); } if (can_open_instance) { if (!p_node->is_connected("script_changed",this,"_node_script_changed")) p_node->connect("script_changed",this,"_node_script_changed",varray(p_node)); if (!p_node->get_script().is_null()) { item->add_button(0,get_icon("Script","EditorIcons"),BUTTON_SCRIPT); } if (p_node->is_type("CanvasItem")) { bool is_locked = p_node->has_meta("_edit_lock_");//_edit_group_ if (is_locked) item->add_button(0,get_icon("Lock", "EditorIcons"), BUTTON_LOCK); bool is_grouped = p_node->has_meta("_edit_group_"); if (is_grouped) item->add_button(0,get_icon("Group", "EditorIcons"), BUTTON_GROUP); bool h = p_node->call("is_hidden"); if (h) item->add_button(0,get_icon("Hidden","EditorIcons"),BUTTON_VISIBILITY); else item->add_button(0,get_icon("Visible","EditorIcons"),BUTTON_VISIBILITY); if (!p_node->is_connected("visibility_changed",this,"_node_visibility_changed")) p_node->connect("visibility_changed",this,"_node_visibility_changed",varray(p_node)); } else if (p_node->is_type("Spatial")) { bool h = p_node->call("is_hidden"); if (h) item->add_button(0,get_icon("Hidden","EditorIcons"),BUTTON_VISIBILITY); else item->add_button(0,get_icon("Visible","EditorIcons"),BUTTON_VISIBILITY); if (!p_node->is_connected("visibility_changed",this,"_node_visibility_changed")) p_node->connect("visibility_changed",this,"_node_visibility_changed",varray(p_node)); } } if (editor_selection) { if (editor_selection->is_selected(p_node)) { item->select(0); } } if (selected==p_node) { if (!editor_selection) item->select(0); item->set_as_cursor(0); } bool keep= (filter.is_subsequence_ofi(String(p_node->get_name()))); for (int i=0;i<p_node->get_child_count();i++) { bool child_keep = _add_nodes(p_node->get_child(i),item); keep = keep || child_keep; } if (!keep) { memdelete(item); return false; } else { return true; } }
void SceneTreeEditor::_cell_button_pressed(Object *p_item,int p_column,int p_id) { TreeItem *item=p_item->cast_to<TreeItem>(); ERR_FAIL_COND(!item); NodePath np = item->get_metadata(0); Node *n=get_node(np); ERR_FAIL_COND(!n); if (p_id==BUTTON_SUBSCENE) { //open scene request Rect2 item_rect = tree->get_item_rect(item,0); item_rect.pos.y-=tree->get_scroll().y; item_rect.pos+=tree->get_global_pos(); if (n==get_scene_node()) { inheritance_menu->set_pos(item_rect.pos+Vector2(0,item_rect.size.y)); inheritance_menu->set_size(Vector2(item_rect.size.x,0)); inheritance_menu->popup(); instance_node=n->get_instance_ID(); } else { instance_menu->set_pos(item_rect.pos+Vector2(0,item_rect.size.y)); instance_menu->set_size(Vector2(item_rect.size.x,0)); if (EditorNode::get_singleton()->get_edited_scene()->is_editable_instance(n)) instance_menu->set_item_checked(0,true); else instance_menu->set_item_checked(0,false); if (n->get_owner()==get_scene_node()) { instance_menu->set_item_checked(1,n->get_scene_instance_load_placeholder()); instance_menu->set_item_disabled(1,false); } else { instance_menu->set_item_checked(1,false); instance_menu->set_item_disabled(1,true); } instance_menu->popup(); instance_node=n->get_instance_ID(); } //emit_signal("open",n->get_filename()); } else if (p_id==BUTTON_SCRIPT) { RefPtr script=n->get_script(); if (!script.is_null()) emit_signal("open_script",script); } else if (p_id==BUTTON_VISIBILITY) { if (n->is_type("Spatial")) { Spatial *ci = n->cast_to<Spatial>(); if (!ci->is_visible() && ci->get_parent_spatial() && !ci->get_parent_spatial()->is_visible()) { error->set_text(TTR("This item cannot be made visible because the parent is hidden. Unhide the parent first.")); error->popup_centered_minsize(); return; } bool v = !bool(n->call("is_hidden")); undo_redo->create_action(TTR("Toggle Spatial Visible")); undo_redo->add_do_method(n,"_set_visible_",!v); undo_redo->add_undo_method(n,"_set_visible_",v); undo_redo->commit_action(); } else if (n->is_type("CanvasItem")) { CanvasItem *ci = n->cast_to<CanvasItem>(); if (!ci->is_visible() && ci->get_parent_item() && !ci->get_parent_item()->is_visible()) { error->set_text(TTR("This item cannot be made visible because the parent is hidden. Unhide the parent first.")); error->popup_centered_minsize(); return; } bool v = !bool(n->call("is_hidden")); undo_redo->create_action(TTR("Toggle CanvasItem Visible")); undo_redo->add_do_method(n,v?"hide":"show"); undo_redo->add_undo_method(n,v?"show":"hide"); undo_redo->commit_action(); } } else if (p_id==BUTTON_LOCK) { if (n->is_type("CanvasItem")) { n->set_meta("_edit_lock_", Variant()); _update_tree(); emit_signal("node_changed"); } } else if (p_id==BUTTON_GROUP) { if (n->is_type("CanvasItem")) { n->set_meta("_edit_group_", Variant()); _update_tree(); emit_signal("node_changed"); } } else if (p_id==BUTTON_WARNING) { String config_err = n->get_configuration_warning(); if (config_err==String()) return; config_err=config_err.word_wrap(80); warning->set_text(config_err); warning->popup_centered_minsize(); } else if (p_id==BUTTON_SIGNALS) { editor_selection->clear(); editor_selection->add_node(n); set_selected(n); NodeDock::singleton->get_parent()->call("set_current_tab",NodeDock::singleton->get_index()); NodeDock::singleton->show_connections(); } else if (p_id==BUTTON_GROUPS) { editor_selection->clear(); editor_selection->add_node(n); set_selected(n); NodeDock::singleton->get_parent()->call("set_current_tab",NodeDock::singleton->get_index()); NodeDock::singleton->show_groups(); } }