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;
}
Example #2
0
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);

	}
}
Example #3
0
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;

}
Example #4
0
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);
		}

	}
}
Example #5
0
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;
}
Example #6
0
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);
	}
}
Example #7
0
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);

}
Example #8
0
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);


}
Example #9
0
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);
		}

	}


}
Example #11
0
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; 
 
}
Example #12
0
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();

}
Example #13
0
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);
}
Example #14
0
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;

	}

}
Example #15
0
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();
	}
}
Example #16
0
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);
	}
}
Example #17
0
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;

	}

}