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 GIProbe::_find_meshes(Node *p_at_node,Baker *p_baker){ MeshInstance *mi = p_at_node->cast_to<MeshInstance>(); if (mi && mi->get_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT)) { Ref<Mesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { Rect3 aabb = mesh->get_aabb(); Transform xf = get_global_transform().affine_inverse() * mi->get_global_transform(); if (Rect3(-extents,extents*2).intersects(xf.xform(aabb))) { Baker::PlotMesh pm; pm.local_xform=xf; pm.mesh=mesh; for(int i=0;i<mesh->get_surface_count();i++) { pm.instance_materials.push_back(mi->get_surface_material(i)); } pm.override_material=mi->get_material_override(); p_baker->mesh_list.push_back(pm); } } } for(int i=0;i<p_at_node->get_child_count();i++) { Node *child = p_at_node->get_child(i); if (!child->get_owner()) continue; //maybe a helper _find_meshes(child,p_baker); } }
Node *SceneTreeDock::_duplicate(Node *p_node, Map<Node*,Node*> &duplimap) { Node *node=NULL; if (p_node->get_filename()!="") { //an instance Ref<PackedScene> sd = ResourceLoader::load( p_node->get_filename() ); ERR_FAIL_COND_V(!sd.is_valid(),NULL); node = sd->instance(); ERR_FAIL_COND_V(!node,NULL); node->generate_instance_state(); } else { Object *obj = ObjectTypeDB::instance(p_node->get_type()); ERR_FAIL_COND_V(!obj,NULL); node = obj->cast_to<Node>(); if (!node) memdelete(obj); ERR_FAIL_COND_V(!node,NULL); } List<PropertyInfo> plist; p_node->get_property_list(&plist); for(List<PropertyInfo>::Element *E=plist.front();E;E=E->next()) { if (!(E->get().usage&PROPERTY_USAGE_STORAGE)) continue; String name = E->get().name; node->set( name, p_node->get(name) ); } node->set_name(p_node->get_name()); duplimap[p_node]=node; for(int i=0;i<p_node->get_child_count();i++) { Node *child = p_node->get_child(i); if (p_node->get_owner()!=child->get_owner()) continue; //don't bother with not in-scene nodes. Node *dup = _duplicate(child,duplimap); if (!dup) { memdelete(node); return NULL; } node->add_child(dup); } return node; }
void GroupsEditor::update_tree() { tree->clear(); if (!node) return; List<Node::GroupInfo> groups; node->get_groups(&groups); groups.sort_custom<_GroupInfoComparator>(); TreeItem *root=tree->create_item(); for(List<GroupInfo>::Element *E=groups.front();E;E=E->next()) { Node::GroupInfo gi = E->get(); if (!gi.persistent) continue; Node *n = node; bool can_be_deleted=true; while(n) { Ref<SceneState> ss = (n==EditorNode::get_singleton()->get_edited_scene()) ? n->get_scene_inherited_state() : n->get_scene_instance_state(); if (ss.is_valid()) { int path = ss->find_node_by_path(n->get_path_to(node)); if (path!=-1) { if (ss->is_node_in_group(path,gi.name)) { can_be_deleted=false; } } } n=n->get_owner(); } TreeItem *item=tree->create_item(root); item->set_text(0, gi.name); if (can_be_deleted) { item->add_button(0, get_icon("Remove", "EditorIcons"), 0); } else { item->set_selectable(0,false); } } }
bool GroupDialog::_can_edit(Node *p_node, String p_group) { Node *n = p_node; bool can_edit = true; while (n) { Ref<SceneState> ss = (n == EditorNode::get_singleton()->get_edited_scene()) ? n->get_scene_inherited_state() : n->get_scene_instance_state(); if (ss.is_valid()) { int path = ss->find_node_by_path(n->get_path_to(p_node)); if (path != -1) { if (ss->is_node_in_group(path, p_group)) { can_edit = false; } } } n = n->get_owner(); } return can_edit; }
void EditorSubScene::_fill_tree(Node *p_node, TreeItem *p_parent) { TreeItem *it = tree->create_item(p_parent); it->set_metadata(0, p_node); it->set_text(0, p_node->get_name()); it->set_editable(0, false); it->set_selectable(0, true); it->set_icon(0, EditorNode::get_singleton()->get_object_icon(p_node, "Node")); for (int i = 0; i < p_node->get_child_count(); i++) { Node *c = p_node->get_child(i); if (c->get_owner() != scene) continue; _fill_tree(c, it); } }
void SceneTreeDock::_update_tool_buttons() { Node *sel = scene_tree->get_selected(); bool disable = !sel || (sel!=edited_scene && sel->get_owner()!=edited_scene); bool disable_root = disable || sel->get_parent()==scene_root; tool_buttons[TOOL_INSTANCE]->set_disabled(disable); tool_buttons[TOOL_REPLACE]->set_disabled(disable); tool_buttons[TOOL_CONNECT]->set_disabled(disable); tool_buttons[TOOL_GROUP]->set_disabled(disable); tool_buttons[TOOL_SCRIPT]->set_disabled(disable); tool_buttons[TOOL_MOVE_UP]->set_disabled(disable_root); tool_buttons[TOOL_MOVE_DOWN]->set_disabled(disable_root); tool_buttons[TOOL_DUPLICATE]->set_disabled(disable_root); tool_buttons[TOOL_REPARENT]->set_disabled(disable_root); tool_buttons[TOOL_ERASE]->set_disabled(disable); }
void SceneTreeDock::_update_tool_buttons() { Node *sel = scene_tree->get_selected(); bool disable = !sel || (sel!=edited_scene && sel->get_owner()!=edited_scene) || (edited_scene->get_scene_instance_state().is_valid() && edited_scene->get_scene_instance_state()->find_node_by_path(edited_scene->get_path_to(sel))>=0); bool disable_root = disable || sel->get_parent()==scene_root; bool disable_edit = !sel; tool_buttons[TOOL_INSTANCE]->set_disabled(disable_edit); tool_buttons[TOOL_REPLACE]->set_disabled(disable); tool_buttons[TOOL_CONNECT]->set_disabled(disable_edit); tool_buttons[TOOL_GROUP]->set_disabled(disable_edit); tool_buttons[TOOL_SCRIPT]->set_disabled(disable_edit); tool_buttons[TOOL_MOVE_UP]->set_disabled(disable_root); tool_buttons[TOOL_MOVE_DOWN]->set_disabled(disable_root); tool_buttons[TOOL_DUPLICATE]->set_disabled(disable_root); tool_buttons[TOOL_REPARENT]->set_disabled(disable_root); tool_buttons[TOOL_ERASE]->set_disabled(disable); tool_buttons[TOOL_MULTI_EDIT]->set_disabled(EditorNode::get_singleton()->get_editor_selection()->get_selection().size()<2); }
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); }
void ControlEditor::_input_event(InputEvent p_event) { if (p_event.type==InputEvent::MOUSE_BUTTON) { const InputEventMouseButton &b=p_event.mouse_button; if (b.button_index==BUTTON_RIGHT) { if (controls.size() && drag!=DRAG_NONE) { //cancel drag for(ControlMap::Element *E=controls.front();E;E=E->next()) { Control *control = E->key(); control->set_pos(E->get().drag_pos); control->set_size(E->get().drag_size); } } else if (b.pressed) { popup->set_pos(Point2(b.x,b.y)); popup->popup(); } return; } //if (!controls.size()) // return; if (b.button_index!=BUTTON_LEFT) return; if (!b.pressed) { if (drag!=DRAG_NONE) { if (undo_redo) { undo_redo->create_action(TTR("Edit Control")); for(ControlMap::Element *E=controls.front();E;E=E->next()) { Control *control = E->key(); undo_redo->add_do_method(control,"set_pos",control->get_pos()); undo_redo->add_do_method(control,"set_size",control->get_size()); undo_redo->add_undo_method(control,"set_pos",E->get().drag_pos); undo_redo->add_undo_method(control,"set_size",E->get().drag_size); } undo_redo->commit_action(); } drag=DRAG_NONE; } return; } if (controls.size()==1) { //try single control edit Control *control = controls.front()->key(); ERR_FAIL_COND(!current_window); Rect2 rect=control->get_window_rect(); Point2 ofs=Point2();//get_global_pos(); Rect2 draw_rect=Rect2(rect.pos-ofs,rect.size); Point2 click=Point2(b.x,b.y); click = transform.affine_inverse().xform(click); Size2 handle_size=Size2(handle_len,handle_len); drag = DRAG_NONE; if (Rect2(draw_rect.pos-handle_size,handle_size).has_point(click)) drag=DRAG_TOP_LEFT; else if (Rect2(draw_rect.pos+draw_rect.size,handle_size).has_point(click)) drag=DRAG_BOTTOM_RIGHT; else if(Rect2(draw_rect.pos+Point2(draw_rect.size.width,-handle_size.y),handle_size).has_point(click)) drag=DRAG_TOP_RIGHT; else if (Rect2(draw_rect.pos+Point2(-handle_size.x,draw_rect.size.height),handle_size).has_point(click)) drag=DRAG_BOTTOM_LEFT; else if (Rect2(draw_rect.pos+Point2(Math::floor((draw_rect.size.width-handle_size.x)/2.0),-handle_size.height),handle_size).has_point(click)) drag=DRAG_TOP; else if( Rect2(draw_rect.pos+Point2(-handle_size.width,Math::floor((draw_rect.size.height-handle_size.y)/2.0)),handle_size).has_point(click)) drag=DRAG_LEFT; else if ( Rect2(draw_rect.pos+Point2(Math::floor((draw_rect.size.width-handle_size.x)/2.0),draw_rect.size.height),handle_size).has_point(click)) drag=DRAG_BOTTOM; else if( Rect2(draw_rect.pos+Point2(draw_rect.size.width,Math::floor((draw_rect.size.height-handle_size.y)/2.0)),handle_size).has_point(click)) drag=DRAG_RIGHT; if (drag!=DRAG_NONE) { drag_from=click; controls[control].drag_pos=control->get_pos(); controls[control].drag_size=control->get_size(); controls[control].drag_limit=drag_from+controls[control].drag_size-control->get_minimum_size(); return; } } //multi control edit Point2 click=Point2(b.x,b.y); Node* scene = get_scene()->get_root_node()->cast_to<EditorNode>()->get_edited_scene(); if (!scene) return; /* if (current_window) { //no window.... ? click-=current_window->get_scroll(); }*/ Control *c=_select_control_at_pos(click, scene); Node* n = c; while ((n && n != scene && n->get_owner() != scene) || (n && !n->is_type("Control"))) { n = n->get_parent(); }; c = n->cast_to<Control>(); if (b.mod.control) { //additive selection if (!c) return; //nothing to add if (current_window && controls.size() && c->get_window()!=current_window) return; //cant multiple select from multiple windows if (!controls.size()) current_window=c->get_window(); if (controls.has(c)) { //already in here, erase it _remove_control(c); update(); return; } //check parents! Control *parent = c->get_parent()->cast_to<Control>(); while(parent) { if (controls.has(parent)) return; //a parent is already selected, so this is pointless parent=parent->get_parent()->cast_to<Control>(); } //check childrens of everything! List<Control*> to_erase; for(ControlMap::Element *E=controls.front();E;E=E->next()) { parent = E->key()->get_parent()->cast_to<Control>(); while(parent) { if (parent==c) { to_erase.push_back(E->key()); break; } parent=parent->get_parent()->cast_to<Control>(); } } while(to_erase.size()) { _remove_control(to_erase.front()->get()); to_erase.pop_front(); } _add_control(c,EditInfo()); update(); } else { //regular selection if (!c) { _clear_controls(); update(); return; } if (!controls.has(c)) { _clear_controls(); current_window=c->get_window(); _add_control(c,EditInfo()); //reselect if (get_scene()->is_editor_hint()) { get_scene()->get_root_node()->call("edit_node",c); } } for(ControlMap::Element *E=controls.front();E;E=E->next()) { EditInfo &ei=E->get(); Control *control=E->key(); ei.drag_pos=control->get_pos(); ei.drag_size=control->get_size(); ei.drag_limit=drag_from+ei.drag_size-control->get_minimum_size(); } drag=DRAG_ALL; drag_from=click; update(); } } if (p_event.type==InputEvent::MOUSE_MOTION) { const InputEventMouseMotion &m=p_event.mouse_motion; if (drag==DRAG_NONE || !current_window) return; for(ControlMap::Element *E=controls.front();E;E=E->next()) { Control *control = E->key(); Point2 control_drag_pos=E->get().drag_pos; Point2 control_drag_size=E->get().drag_size; Point2 control_drag_limit=E->get().drag_limit; Point2 pos=Point2(m.x,m.y); pos = transform.affine_inverse().xform(pos); switch(drag) { case DRAG_ALL: { control->set_pos( snapify(control_drag_pos+(pos-drag_from)) ); } break; case DRAG_RIGHT: { control->set_size( snapify(Size2(control_drag_size.width+(pos-drag_from).x,control_drag_size.height)) ); } break; case DRAG_BOTTOM: { control->set_size( snapify(Size2(control_drag_size.width,control_drag_size.height+(pos-drag_from).y)) ); } break; case DRAG_BOTTOM_RIGHT: { control->set_size( snapify(control_drag_size+(pos-drag_from)) ); } break; case DRAG_TOP_LEFT: { if(pos.x>control_drag_limit.x) pos.x=control_drag_limit.x; if(pos.y>control_drag_limit.y) pos.y=control_drag_limit.y; Point2 old_size = control->get_size(); Point2 new_pos = snapify(control_drag_pos+(pos-drag_from)); Point2 new_size = old_size + (control->get_pos() - new_pos); control->set_pos( new_pos ); control->set_size( new_size ); } break; case DRAG_TOP: { if(pos.y>control_drag_limit.y) pos.y=control_drag_limit.y; Point2 old_size = control->get_size(); Point2 new_pos = snapify(control_drag_pos+Point2(0,pos.y-drag_from.y)); Point2 new_size = old_size + (control->get_pos() - new_pos); control->set_pos( new_pos ); control->set_size( new_size ); } break; case DRAG_LEFT: { if(pos.x>control_drag_limit.x) pos.x=control_drag_limit.x; Point2 old_size = control->get_size(); Point2 new_pos = snapify(control_drag_pos+Point2(pos.x-drag_from.x,0)); Point2 new_size = old_size + (control->get_pos() - new_pos); control->set_pos( new_pos ); control->set_size( new_size ); } break; case DRAG_TOP_RIGHT: { if(pos.y>control_drag_limit.y) pos.y=control_drag_limit.y; Point2 old_size = control->get_size(); Point2 new_pos = snapify(control_drag_pos+Point2(0,pos.y-drag_from.y)); float new_size_y = Point2( old_size + (control->get_pos() - new_pos)).y; float new_size_x = snapify(control_drag_size+Point2(pos.x-drag_from.x,0)).x; control->set_pos( new_pos ); control->set_size( Point2(new_size_x, new_size_y) ); } break; case DRAG_BOTTOM_LEFT: { if(pos.x>control_drag_limit.x) pos.x=control_drag_limit.x; Point2 old_size = control->get_size(); Point2 new_pos = snapify(control_drag_pos+Point2(pos.x-drag_from.x,0)); float new_size_y = snapify(control_drag_size+Point2(0,pos.y-drag_from.y)).y; float new_size_x = Point2( old_size + (control->get_pos() - new_pos)).x; control->set_pos( new_pos ); control->set_size( Point2(new_size_x, new_size_y) ); } break; default:{} } } } if (p_event.type==InputEvent::KEY) { const InputEventKey &k=p_event.key; if (k.pressed) { if (k.scancode==KEY_UP) _key_move(Vector2(0,-1),k.mod.shift); else if (k.scancode==KEY_DOWN) _key_move(Vector2(0,1),k.mod.shift); else if (k.scancode==KEY_LEFT) _key_move(Vector2(-1,0),k.mod.shift); else if (k.scancode==KEY_RIGHT) _key_move(Vector2(1,0),k.mod.shift); } } }
void Mesh::formHalo2(){ #ifndef NDEBUG unsigned len45 = element_list.size(); for(unsigned i=0; i<len45; i++) for(unsigned j=0; j<len45; j++) if(i!=j) assert(element_list[i] != element_list[j]); #endif // This is what we are looking for. vector< deque<unsigned> > halo2Elements(NProcs); set<unsigned> dangerElements; { // Wizz through all elements. unsigned pos = 0; for(deque<Element>::const_iterator elm = element_list.begin(); elm != element_list.end(); ++elm, ++pos){ const vector<unn_t>& nodes = (*elm).get_enlist(); vector<bool> halo1(NProcs, false); bool interesting=false; for(int p=0; p<NProcs; p++){ if(p==MyRank) continue; // Record if elm has a halo node with p. for( vector<unn_t>::const_iterator jt = nodes.begin(); jt!=nodes.end(); ++jt){ halo1[p] = (halo_nodes[p].find(*jt)!= halo_nodes[p].end()); // Early exit... if(halo1[p]) break; } if(!halo1[p]){ // Record if elm shares a node with p, but is not itself a halo1 element for p. for(vector<unn_t>::const_iterator jt=nodes.begin(); jt!=nodes.end(); ++jt){ if(shared_nodes[p].find(*jt)!=shared_nodes[p].end()){ interesting = true; halo2Elements[p].push_back(pos); break; } } } } if(interesting){ // A halo2 element may be multiably sent if it contains halo1 // nodes for any domain. for(unsigned p=0;p<(unsigned)NProcs;p++){ if(halo1[p]){ dangerElements.insert( pos ); break; } } } } } // Have halo2 elements and a set of dangerElements. // // Identify all the nodes that must be sent. // vector< set<unsigned> > sendhalo2nodes(NProcs); vector< set<unsigned> > sendhalo2pnodes(NProcs); for(unsigned p=0; p<(unsigned)NProcs; p++){ for(deque<unsigned>::const_iterator elm=halo2Elements[p].begin(); elm!=halo2Elements[p].end(); ++elm){ // It's enough to just check the volume elements if(element_list[*elm].get_flags() & ELM_SURFACE) continue; {// Regular nodes const vector<unn_t>& nodes = element_list[*elm].get_enlist(); for(vector<unn_t>::const_iterator nod=nodes.begin(); nod!=nodes.end(); ++nod){ sendhalo2nodes[p].insert( *nod ); } } {// Pressure nodes const vector<unn_t>& nodes = element_list[*elm].get_MFenlist(); for(vector<unn_t>::const_iterator nod=nodes.begin(); nod!=nodes.end(); ++nod){ sendhalo2pnodes[p].insert( *nod ); } } } {// Remove nodes that p should already know through halo1. set<unsigned> toDel; for(set<unsigned>::const_iterator it=sendhalo2nodes[p].begin(); it != sendhalo2nodes[p].end(); ++it){ if(shared_nodes[p].find( *it ) != shared_nodes[p].end()){ toDel.insert( *it ); } } for(set<unsigned>::const_iterator it=toDel.begin(); it != toDel.end(); ++it){ sendhalo2nodes[p].erase( *it ); } } {// Remove pressure nodes that p should already know through halo1. set<unsigned> toDel; for(set<unsigned>::const_iterator it=sendhalo2pnodes[p].begin(); it != sendhalo2pnodes[p].end(); ++it){ if( shared_pnodes[p].find( *it ) != shared_pnodes[p].end() ){ toDel.insert( *it ); } } for(set<unsigned>::const_iterator it=toDel.begin(); it != toDel.end(); ++it){ sendhalo2pnodes[p].erase( *it ); } } } // // At this point we have identified all the information which we // want to communicate: // vector< deque<unsigned> > elems2send( NProcs ); // vector< set<unsigned> > nodes2send( NProcs ); // // Make the send-packs vector< vector<char> > SendRecvBuffer(NProcs); { // Allocate space for buffers unsigned max_node_size = max_nodepack_size(); unsigned max_pnode_size = max_pressurepack_size(); unsigned max_element_size = max_elementpack_size(); unsigned space_for_unsigned = MPI::UNSIGNED.Pack_size(1, MPI::COMM_WORLD); for(int i=0; i<NProcs; i++){ unsigned nbytes = space_for_unsigned + space_for_unsigned*halo2Elements[i].size() + space_for_unsigned + max_element_size*halo2Elements[i].size() + space_for_unsigned + max_node_size*sendhalo2nodes[i].size() + space_for_unsigned + max_pnode_size*sendhalo2pnodes[i].size(); SendRecvBuffer[i].resize( (unsigned)(1.1*nbytes) ); } } vector<int> offsets(NProcs, 0); // int because of mpi calls // Pack. for(int i=0; i<NProcs; i++){ int len = SendRecvBuffer[i].size(); if( (i == MyRank)||(len == 0) ) continue; char *buff = &(SendRecvBuffer[i][0]); // Elements unsigned cnt = halo2Elements[i].size(); MPI::UNSIGNED.Pack(&cnt, 1, buff, len, offsets[i], MPI::COMM_WORLD); ECHO("Packing "<<cnt<<" halo2 elements for "<<i<<"."); for(unsigned j=0; j<cnt; j++){ // Dangerious? unsigned danger = 0; if( dangerElements.find( halo2Elements[i][j] ) != dangerElements.end() ) danger = 1; MPI::UNSIGNED.Pack(&danger, 1, buff, len, offsets[i], MPI::COMM_WORLD); // Pack element element_list[ halo2Elements[i][j] ].pack(buff, len, offsets[i]); } // Nodes cnt = sendhalo2nodes[i].size(); MPI::UNSIGNED.Pack(&cnt, 1, buff, len, offsets[i], MPI::COMM_WORLD); ECHO("Packing "<<cnt<<" halo2 nodes for "<<i<<"."); for(set<unsigned>::const_iterator it=sendhalo2nodes[i].begin(); it!=sendhalo2nodes[i].end(); ++it){ const Node& node = node_list.unn( *it ); node.pack(buff, len, offsets[i]); } // Pressure nodes cnt = sendhalo2pnodes[i].size(); MPI::UNSIGNED.Pack(&cnt, 1, buff, len, offsets[i], MPI::COMM_WORLD); ECHO("Packing "<<cnt<<" halo2 pressure nodes for "<<i<<"."); for(set<unsigned>::const_iterator it=sendhalo2pnodes[i].begin(); it!=sendhalo2pnodes[i].end(); ++it){ const PressureNode& node = MFnode_list.unn( *it ); node.pack(buff, len, offsets[i]); } assert(offsets[i] <= (int)SendRecvBuffer[i].size()); } // Clean-up. dangerElements.clear(); halo2Elements.clear(); sendhalo2nodes.clear(); sendhalo2pnodes.clear(); // Send/recieve everything. allSendRecv(SendRecvBuffer); { // Unpacking. ECHO("Starting unpacking."); for(int p=0; p<NProcs; p++){ offsets[p] = 0; } set<Element> DangerElements; set<unsigned> ReceivedNodes; set<unsigned> ReceivedPressureNodes; vector< set<unsigned> > extraHalo(NProcs); // Paranoid assert(SendRecvBuffer.size() == (unsigned)NProcs); #ifndef NDEBUG CHECK( element_list.size() ); do_element_headcount(); CHECK( num_elements("total") ); CHECK( num_elements("volume") ); CHECK( num_elements("surface") ); #endif for(int p=0; p<NProcs; p++){ int nbytes = SendRecvBuffer[p].size(); if( (p == MyRank)||(nbytes == 0) ) continue; char *buffer = &(SendRecvBuffer[p][0]); { // elements unsigned cnt; MPI::UNSIGNED.Unpack(buffer, nbytes, &cnt, 1, offsets[p], MPI::COMM_WORLD); ECHO("Unpacking "<<cnt<<" elements from "<<p<<"."); for(unsigned j=0; j<cnt; j++){ Element element; ECHO("Unpacking "<<j<<"..."); // Unpack danger flag. unsigned danger; MPI::UNSIGNED.Unpack(buffer, nbytes, &danger, 1, offsets[p], MPI::COMM_WORLD); CHECK(danger); // Unpack element... element.unpack(buffer, nbytes, offsets[p]); ECHO("unpacked."); if(danger){ ECHO("Danger element...taking evasive action."); DangerElements.insert( element ); }else{ element_list.push_back(element); } } } // finished unpacking elements. { // nodes unsigned cnt; MPI::UNSIGNED.Unpack(buffer, nbytes, &cnt, 1, offsets[p], MPI::COMM_WORLD); ECHO("Unpacking "<<cnt<<" nodes from "<<p<<"."); for(unsigned j=0; j<cnt; j++){ Node node; node.unpack(buffer, nbytes, offsets[p]); unsigned unn = node.get_unn(); unsigned owner = node.get_owner(); if(halo_nodes[owner].find( unn ) == halo_nodes[owner].end()) if(ReceivedNodes.find( unn ) == ReceivedNodes.end()){ assert( !node_list.contains_unn(unn) ); node_list.push_back( node ); ReceivedNodes.insert( unn ); } } } // finished unpacking nodes { // pressure nodes unsigned cnt; MPI::UNSIGNED.Unpack(buffer, nbytes, &cnt, 1, offsets[p], MPI::COMM_WORLD); ECHO("Unpacking "<<cnt<<" pressure nodes from "<<p<<"."); for(unsigned j=0; j<cnt; j++){ PressureNode node; node.unpack(buffer, nbytes, offsets[p]); unsigned unn = node.get_unn(); unsigned owner = node.get_owner(); if(halo_pnodes[owner].find( unn ) == halo_pnodes[owner].end()) if(ReceivedPressureNodes.find( node.get_unn() ) == ReceivedPressureNodes.end()){ assert( !MFnode_list.contains_unn(unn) ); MFnode_list.push_back( node ); ReceivedPressureNodes.insert( node.get_unn() ); // This next line is tricky as "node.get_owner()" is used // rather than p. This is because the owner of this node is // not necessarly the same as the processor that sent // it. extraHalo[owner].insert( node.get_unn() ); } } } // finished unpacking pressure nodes } // // Finally, add in the danger elements // if( !DangerElements.empty() ){ ECHO("Add in danger elements."); for(set<Element>::const_iterator it=DangerElements.begin(); it!=DangerElements.end(); ++it) element_list.push_back( *it ); DangerElements.clear(); } #ifndef NDEBUG CHECK( element_list.size() ); do_element_headcount(); CHECK( num_elements("total") ); CHECK( num_elements("volume") ); CHECK( num_elements("surface") ); #endif // // Communicate extra halo stuff. // vector< set<unsigned> > extraShared(NProcs); ECHO("Communicating the extended halo..."); assert(extraHalo[MyRank].size() == 0); allSendRecv(extraHalo, extraShared); assert(extraShared[MyRank].size() == 0); ECHO("...done."); // // Add in extra halo values... // for(int p=0; p<NProcs; p++){ if(p==MyRank) continue; // add in extra halo values ECHO("Adding halo nodes for "<<p); halo_pnodes[p].insert(extraHalo[p].begin(), extraHalo[p].end()); extraHalo[p].clear(); ECHO("Adding shared nodes for "<<p); shared_pnodes[p].insert(extraShared[p].begin(), extraShared[p].end()); extraShared[p].clear(); } extraHalo.clear(); extraShared.clear(); } // finished unpacking #ifndef NDEBUG len45 = element_list.size(); for(unsigned i=0; i<len45; i++) for(unsigned j=0; j<len45; j++) if(i!=j) assert(element_list[i] != element_list[j]); #endif ECHO("Halo2 created."); return; }
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::_tool_selected(int p_tool, bool p_confirm_override) { current_option=p_tool; switch(p_tool) { case TOOL_NEW: { create_dialog->popup_centered_ratio(); } break; case TOOL_INSTANCE: { Node *scene = edited_scene; if (!scene) { current_option=-1; //confirmation->get_cancel()->hide(); accept->get_ok()->set_text("I see.."); accept->set_text("This operation can't be done without a tree root."); accept->popup_centered(Size2(300,70));; break; } file->set_mode(FileDialog::MODE_OPEN_FILE); List<String> extensions; ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions); file->clear_filters(); for(int i=0;i<extensions.size();i++) { file->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper()); } //file->set_current_path(current_path); file->popup_centered_ratio(); } break; case TOOL_REPLACE: { create_dialog->popup_centered_ratio(); } break; case TOOL_CONNECT: { Node *current = scene_tree->get_selected(); if (!current) break; connect_dialog->popup_centered_ratio(); connect_dialog->set_node(current); } break; case TOOL_GROUP: { Node *current = scene_tree->get_selected(); if (!current) break; groups_editor->set_current(current); groups_editor->popup_centered_ratio(); } break; case TOOL_SCRIPT: { Node *selected = scene_tree->get_selected(); if (!selected) break; Ref<Script> existing = selected->get_script(); if (existing.is_valid()) editor->push_item(existing.ptr()); else { String path = selected->get_filename(); script_create_dialog->config(selected->get_type(),path); script_create_dialog->popup_centered(Size2(300,290)); //script_create_dialog->popup_centered_minsize(); } } break; case TOOL_MOVE_UP: case TOOL_MOVE_DOWN: { if (!scene_tree->get_selected()) break; if (scene_tree->get_selected()==edited_scene) { current_option=-1; //accept->get_cancel()->hide(); accept->get_ok()->set_text("I see.."); accept->set_text("This operation can't be done on the tree root."); accept->popup_centered(Size2(300,70));; break; } Node * node=scene_tree->get_selected(); ERR_FAIL_COND(!node->get_parent()); int current_pos = node->get_index(); int next_pos = current_pos + ((p_tool==TOOL_MOVE_DOWN)?1:-1); if (next_pos< 0 || next_pos>=node->get_parent()->get_child_count()) break; // invalid position editor_data->get_undo_redo().create_action("Move Node In Parent"); editor_data->get_undo_redo().add_do_method(node->get_parent(),"move_child",node,next_pos); editor_data->get_undo_redo().add_undo_method(node->get_parent(),"move_child",node,current_pos); editor_data->get_undo_redo().commit_action(); } break; case TOOL_DUPLICATE: { if (!edited_scene) break; if (editor_selection->is_selected(edited_scene)) { current_option=-1; //accept->get_cancel()->hide(); accept->get_ok()->set_text("I see.."); accept->set_text("This operation can't be done on the tree root."); accept->popup_centered(Size2(300,70));; break; } List<Node*> selection = editor_selection->get_selected_node_list(); List<Node*> reselect; editor_data->get_undo_redo().create_action("Duplicate Node(s)"); editor_data->get_undo_redo().add_do_method(editor_selection,"clear"); Node *dupsingle=NULL; for (List<Node*>::Element *E=selection.front();E;E=E->next()) { Node *node = E->get(); Node *parent = node->get_parent(); List<Node*> owned; node->get_owned_by(node->get_owner(),&owned); Map<Node*,Node*> duplimap; Node * dup = _duplicate(node,duplimap); ERR_CONTINUE(!dup); if (selection.size()==1) dupsingle=dup; String name = node->get_name(); String nums; for(int i=name.length()-1;i>=0;i--) { CharType n=name[i]; if (n>='0' && n<='9') { nums=String::chr(name[i])+nums; } else { break; } } int num=nums.to_int(); if (num<2) num=2; else num++; name=name.substr(0,name.length()-nums.length()).strip_edges(); String attempt=name+" "+itos(num); while(parent->has_node(attempt)) { num++; attempt=name+" "+itos(num); } dup->set_name(attempt); editor_data->get_undo_redo().add_do_method(parent,"add_child",dup); for (List<Node*>::Element *F=owned.front();F;F=F->next()) { if (!duplimap.has(F->get())) { continue; } Node *d=duplimap[F->get()]; editor_data->get_undo_redo().add_do_method(d,"set_owner",node->get_owner()); } editor_data->get_undo_redo().add_do_method(editor_selection,"add_node",dup); editor_data->get_undo_redo().add_undo_method(parent,"remove_child",dup); editor_data->get_undo_redo().add_do_reference(dup); //parent->add_child(dup); //reselect.push_back(dup); } editor_data->get_undo_redo().commit_action(); if (dupsingle) editor->push_item(dupsingle); } break; case TOOL_REPARENT: { if (!scene_tree->get_selected()) break; if (editor_selection->is_selected(edited_scene)) { current_option=-1; //confirmation->get_cancel()->hide(); accept->get_ok()->set_text("I see.."); accept->set_text("This operation can't be done on the tree root."); accept->popup_centered(Size2(300,70));; break; } List<Node*> nodes = editor_selection->get_selected_node_list(); Set<Node*> nodeset; for(List<Node*>::Element *E=nodes.front();E;E=E->next()) { nodeset.insert(E->get()); } reparent_dialog->popup_centered_ratio(); reparent_dialog->set_current( nodeset ); } break; case TOOL_ERASE: { List<Node*> remove_list = editor_selection->get_selected_node_list(); if (remove_list.empty()) return; if (p_confirm_override) { _delete_confirm(); // hack, force 2d editor viewport to refresh after deletion if (CanvasItemEditor *editor = CanvasItemEditor::get_singleton()) editor->get_viewport_control()->update(); } else { delete_dialog->set_text("Delete Node(s)?"); delete_dialog->popup_centered(Size2(200,80)); } } break; } }
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_class("Spatial")) { bool v = bool(n->call("is_visible")); 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_class("CanvasItem")) { bool v = bool(n->call("is_visible")); 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_class("CanvasItem")) { n->set_meta("_edit_lock_", Variant()); _update_tree(); emit_signal("node_changed"); } } else if (p_id == BUTTON_GROUP) { if (n->is_class("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(); } }
void BakedLightmap::_find_meshes_and_lights(Node *p_at_node, List<PlotMesh> &plot_meshes, List<PlotLight> &plot_lights) { MeshInstance *mi = Object::cast_to<MeshInstance>(p_at_node); if (mi && mi->get_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT) && mi->is_visible_in_tree()) { Ref<Mesh> mesh = mi->get_mesh(); if (mesh.is_valid()) { bool all_have_uv2 = true; for (int i = 0; i < mesh->get_surface_count(); i++) { if (!(mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_TEX_UV2)) { all_have_uv2 = false; break; } } if (all_have_uv2 && mesh->get_lightmap_size_hint() != Size2()) { //READY TO BAKE! size hint could be computed if not found, actually.. AABB aabb = mesh->get_aabb(); Transform xf = get_global_transform().affine_inverse() * mi->get_global_transform(); if (AABB(-extents, extents * 2).intersects(xf.xform(aabb))) { PlotMesh pm; pm.local_xform = xf; pm.mesh = mesh; pm.path = get_path_to(mi); pm.instance_idx = -1; for (int i = 0; i < mesh->get_surface_count(); i++) { pm.instance_materials.push_back(mi->get_surface_material(i)); } pm.override_material = mi->get_material_override(); plot_meshes.push_back(pm); } } } } Spatial *s = Object::cast_to<Spatial>(p_at_node); if (!mi && s) { Array meshes = p_at_node->call("get_bake_meshes"); if (meshes.size() && (meshes.size() & 1) == 0) { Transform xf = get_global_transform().affine_inverse() * s->get_global_transform(); for (int i = 0; i < meshes.size(); i += 2) { PlotMesh pm; Transform mesh_xf = meshes[i + 1]; pm.local_xform = xf * mesh_xf; pm.mesh = meshes[i]; pm.instance_idx = i / 2; if (!pm.mesh.is_valid()) continue; pm.path = get_path_to(s); plot_meshes.push_back(pm); } } } Light *light = Object::cast_to<Light>(p_at_node); if (light && light->get_bake_mode() != Light::BAKE_DISABLED) { PlotLight pl; Transform xf = get_global_transform().affine_inverse() * light->get_global_transform(); pl.local_xform = xf; pl.light = light; plot_lights.push_back(pl); } for (int i = 0; i < p_at_node->get_child_count(); i++) { Node *child = p_at_node->get_child(i); if (!child->get_owner()) continue; //maybe a helper _find_meshes_and_lights(child, plot_meshes, plot_lights); } }
void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { current_option=p_tool; switch(p_tool) { case TOOL_NEW: { //if (!_validate_no_foreign()) // break; create_dialog->popup_centered_ratio(); } break; case TOOL_INSTANCE: { Node *scene = edited_scene; if (!scene) { current_option=-1; //confirmation->get_cancel()->hide(); accept->get_ok()->set_text("I see.."); accept->set_text("This operation can't be done without a tree root."); accept->popup_centered_minsize(); break; } //if (!_validate_no_foreign()) // break; file->set_mode(EditorFileDialog::MODE_OPEN_FILE); List<String> extensions; ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions); file->clear_filters(); for(int i=0;i<extensions.size();i++) { file->add_filter("*."+extensions[i]+" ; "+extensions[i].to_upper()); } //file->set_current_path(current_path); file->popup_centered_ratio(); } break; case TOOL_REPLACE: { create_dialog->popup_centered_ratio(); } break; case TOOL_CONNECT: { Node *current = scene_tree->get_selected(); if (!current) break; //if (!_validate_no_foreign()) // break; connect_dialog->popup_centered_ratio(); connect_dialog->set_node(current); } break; case TOOL_GROUP: { Node *current = scene_tree->get_selected(); if (!current) break; //if (!_validate_no_foreign()) // break; groups_editor->set_current(current); groups_editor->popup_centered_ratio(); } break; case TOOL_SCRIPT: { Node *selected = scene_tree->get_selected(); if (!selected) break; //if (!_validate_no_foreign()) // break; Ref<Script> existing = selected->get_script(); if (existing.is_valid()) editor->push_item(existing.ptr()); else { String path = selected->get_filename(); script_create_dialog->config(selected->get_type(),path); script_create_dialog->popup_centered(Size2(300,290)); //script_create_dialog->popup_centered_minsize(); } } break; case TOOL_MOVE_UP: case TOOL_MOVE_DOWN: { if (!scene_tree->get_selected()) break; if (scene_tree->get_selected()==edited_scene) { current_option=-1; //accept->get_cancel()->hide(); accept->get_ok()->set_text("I see.."); accept->set_text("This operation can't be done on the tree root."); accept->popup_centered_minsize(); break; } if (!_validate_no_foreign()) break; bool MOVING_DOWN = (p_tool == TOOL_MOVE_DOWN); bool MOVING_UP = !MOVING_DOWN; Node *common_parent = scene_tree->get_selected()->get_parent(); List<Node*> selection = editor_selection->get_selected_node_list(); selection.sort_custom<Node::Comparator>(); // sort by index if (MOVING_DOWN) selection.invert(); int lowest_id = common_parent->get_child_count() - 1; int highest_id = 0; for (List<Node*>::Element *E = selection.front(); E; E = E->next()) { int index = E->get()->get_index(); if (index > highest_id) highest_id = index; if (index < lowest_id) lowest_id = index; if (E->get()->get_parent() != common_parent) common_parent = NULL; } if (!common_parent || (MOVING_DOWN && highest_id >= common_parent->get_child_count() - MOVING_DOWN) || (MOVING_UP && lowest_id == 0)) break; // one or more nodes can not be moved if (selection.size() == 1) editor_data->get_undo_redo().create_action("Move Node In Parent"); if (selection.size() > 1) editor_data->get_undo_redo().create_action("Move Nodes In Parent"); for (int i = 0; i < selection.size(); i++) { Node *top_node = selection[i]; Node *bottom_node = selection[selection.size() - 1 - i]; ERR_FAIL_COND(!top_node->get_parent()); ERR_FAIL_COND(!bottom_node->get_parent()); int top_node_pos = top_node->get_index(); int bottom_node_pos = bottom_node->get_index(); int top_node_pos_next = top_node_pos + (MOVING_DOWN ? 1 : -1); int bottom_node_pos_next = bottom_node_pos + (MOVING_DOWN ? 1 : -1); editor_data->get_undo_redo().add_do_method(top_node->get_parent(), "move_child", top_node, top_node_pos_next); editor_data->get_undo_redo().add_undo_method(bottom_node->get_parent(), "move_child", bottom_node, bottom_node_pos); } editor_data->get_undo_redo().commit_action(); } break; case TOOL_DUPLICATE: { if (!edited_scene) break; if (editor_selection->is_selected(edited_scene)) { current_option=-1; //accept->get_cancel()->hide(); accept->get_ok()->set_text("I see.."); accept->set_text("This operation can't be done on the tree root."); accept->popup_centered_minsize(); break; } if (!_validate_no_foreign()) break; List<Node*> selection = editor_selection->get_selected_node_list(); List<Node*> reselect; editor_data->get_undo_redo().create_action("Duplicate Node(s)"); editor_data->get_undo_redo().add_do_method(editor_selection,"clear"); Node *dupsingle=NULL; for (List<Node*>::Element *E=selection.front();E;E=E->next()) { Node *node = E->get(); Node *parent = node->get_parent(); List<Node*> owned; node->get_owned_by(node->get_owner(),&owned); Map<Node*,Node*> duplimap; Node * dup = _duplicate(node,duplimap); ERR_CONTINUE(!dup); if (selection.size()==1) dupsingle=dup; String name = node->get_name(); String nums; for(int i=name.length()-1;i>=0;i--) { CharType n=name[i]; if (n>='0' && n<='9') { nums=String::chr(name[i])+nums; } else { break; } } int num=nums.to_int(); if (num<1) num=1; else num++; String nnsep = _get_name_num_separator(); name = name.substr(0,name.length()-nums.length()).strip_edges(); if ( name.substr(name.length()-nnsep.length(),nnsep.length()) == nnsep) { name = name.substr(0,name.length()-nnsep.length()); } String attempt = (name + nnsep + itos(num)).strip_edges(); while(parent->has_node(attempt)) { num++; attempt = (name + nnsep + itos(num)).strip_edges(); } dup->set_name(attempt); editor_data->get_undo_redo().add_do_method(parent,"add_child",dup); for (List<Node*>::Element *F=owned.front();F;F=F->next()) { if (!duplimap.has(F->get())) { continue; } Node *d=duplimap[F->get()]; editor_data->get_undo_redo().add_do_method(d,"set_owner",node->get_owner()); } editor_data->get_undo_redo().add_do_method(editor_selection,"add_node",dup); editor_data->get_undo_redo().add_undo_method(parent,"remove_child",dup); editor_data->get_undo_redo().add_do_reference(dup); ScriptEditorDebugger *sed = ScriptEditor::get_singleton()->get_debugger(); editor_data->get_undo_redo().add_do_method(sed,"live_debug_duplicate_node",edited_scene->get_path_to(node),attempt); editor_data->get_undo_redo().add_undo_method(sed,"live_debug_remove_node",NodePath(String(edited_scene->get_path_to(parent))+"/"+attempt)); //parent->add_child(dup); //reselect.push_back(dup); } editor_data->get_undo_redo().commit_action(); if (dupsingle) editor->push_item(dupsingle); } break; case TOOL_REPARENT: { if (!scene_tree->get_selected()) break; if (editor_selection->is_selected(edited_scene)) { current_option=-1; //confirmation->get_cancel()->hide(); accept->get_ok()->set_text("I see.."); accept->set_text("This operation can't be done on the tree root."); accept->popup_centered_minsize(); break; } if (!_validate_no_foreign()) break; List<Node*> nodes = editor_selection->get_selected_node_list(); Set<Node*> nodeset; for(List<Node*>::Element *E=nodes.front();E;E=E->next()) { nodeset.insert(E->get()); } reparent_dialog->popup_centered_ratio(); reparent_dialog->set_current( nodeset ); } break; case TOOL_MULTI_EDIT: { Node*root=EditorNode::get_singleton()->get_edited_scene(); if (!root) break; Ref<MultiNodeEdit> mne = memnew( MultiNodeEdit ); for (const Map<Node*,Object*>::Element *E=EditorNode::get_singleton()->get_editor_selection()->get_selection().front();E;E=E->next()) { mne->add_node(root->get_path_to(E->key())); } EditorNode::get_singleton()->push_item(mne.ptr()); } break; case TOOL_ERASE: { List<Node*> remove_list = editor_selection->get_selected_node_list(); if (remove_list.empty()) return; if (!_validate_no_foreign()) break; if (p_confirm_override) { _delete_confirm(); // hack, force 2d editor viewport to refresh after deletion if (CanvasItemEditor *editor = CanvasItemEditor::get_singleton()) editor->get_viewport_control()->update(); } else { delete_dialog->set_text("Delete Node(s)?"); delete_dialog->popup_centered_minsize(); } } break; } }