void AnimationNodeBlendTreeEditor::_node_selected(Object *p_node) {

	GraphNode *gn = Object::cast_to<GraphNode>(p_node);
	ERR_FAIL_COND(!gn);

	String name = gn->get_name();

	Ref<AnimationNode> anode = blend_tree->get_node(name);
	ERR_FAIL_COND(!anode.is_valid());

	EditorNode::get_singleton()->push_item(anode.ptr(), "", true);
}
void VisualShaderEditor::_node_selected(Object *p_node) {

	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());

	GraphNode *gn = Object::cast_to<GraphNode>(p_node);
	ERR_FAIL_COND(!gn);

	int id = String(gn->get_name()).to_int();

	Ref<VisualShaderNode> vsnode = visual_shader->get_node(type, id);
	ERR_FAIL_COND(!vsnode.is_valid());

	//do not rely on this, makes editor more complex
	//EditorNode::get_singleton()->push_item(vsnode.ptr(), "", true);
}
void VisualShaderEditor::_duplicate_nodes() {

	VisualShader::Type type = VisualShader::Type(edit_type->get_selected());

	List<int> nodes;
	Set<int> excluded;

	for (int i = 0; i < graph->get_child_count(); i++) {

		GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i));
		if (gn) {
			int id = String(gn->get_name()).to_int();
			Ref<VisualShaderNode> node = visual_shader->get_node(type, id);
			Ref<VisualShaderNodeOutput> output = node;
			if (output.is_valid()) { // can't duplicate output
				excluded.insert(id);
				continue;
			}
			if (node.is_valid() && gn->is_selected()) {
				nodes.push_back(id);
			}
			excluded.insert(id);
		}
	}

	if (nodes.empty())
		return;

	undo_redo->create_action(TTR("Duplicate Nodes"));

	int base_id = visual_shader->get_valid_node_id(type);
	int id_from = base_id;
	Map<int, int> connection_remap;

	for (List<int>::Element *E = nodes.front(); E; E = E->next()) {

		connection_remap[E->get()] = id_from;
		Ref<VisualShaderNode> node = visual_shader->get_node(type, E->get());

		Ref<VisualShaderNode> dupli = node->duplicate();

		undo_redo->add_do_method(visual_shader.ptr(), "add_node", type, dupli, visual_shader->get_node_position(type, E->get()) + Vector2(10, 10) * EDSCALE, id_from);
		undo_redo->add_undo_method(visual_shader.ptr(), "remove_node", type, id_from);

		id_from++;
	}

	List<VisualShader::Connection> conns;
	visual_shader->get_node_connections(type, &conns);

	for (List<VisualShader::Connection>::Element *E = conns.front(); E; E = E->next()) {
		if (connection_remap.has(E->get().from_node) && connection_remap.has(E->get().to_node)) {
			undo_redo->add_do_method(visual_shader.ptr(), "connect_nodes", type, connection_remap[E->get().from_node], E->get().from_port, connection_remap[E->get().to_node], E->get().to_port);
		}
	}

	undo_redo->add_do_method(this, "_update_graph");
	undo_redo->add_undo_method(this, "_update_graph");
	undo_redo->commit_action();

	// reselect duplicated nodes by excluding the other ones
	for (int i = 0; i < graph->get_child_count(); i++) {

		GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i));
		if (gn) {
			int id = String(gn->get_name()).to_int();
			if (!excluded.has(id)) {
				gn->set_selected(true);
			} else {
				gn->set_selected(false);
			}
		}
	}
}
示例#4
0
void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {

	Ref<InputEventMouseButton> mb = p_ev;
	if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {

		Ref<Texture> port = get_icon("port", "GraphNode");
		Vector2 mpos(mb->get_position().x, mb->get_position().y);
		for (int i = get_child_count() - 1; i >= 0; i--) {

			GraphNode *gn = Object::cast_to<GraphNode>(get_child(i));
			if (!gn)
				continue;

			for (int j = 0; j < gn->get_connection_output_count(); j++) {

				Vector2 pos = gn->get_connection_output_position(j) + gn->get_position();
				if (is_in_hot_zone(pos, mpos)) {

					if (valid_left_disconnect_types.has(gn->get_connection_output_type(j))) {
						//check disconnect
						for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {

							if (E->get().from == gn->get_name() && E->get().from_port == j) {

								Node *to = get_node(String(E->get().to));
								if (Object::cast_to<GraphNode>(to)) {

									connecting_from = E->get().to;
									connecting_index = E->get().to_port;
									connecting_out = false;
									connecting_type = Object::cast_to<GraphNode>(to)->get_connection_input_type(E->get().to_port);
									connecting_color = Object::cast_to<GraphNode>(to)->get_connection_input_color(E->get().to_port);
									connecting_target = false;
									connecting_to = pos;
									just_disconnected = true;

									emit_signal("disconnection_request", E->get().from, E->get().from_port, E->get().to, E->get().to_port);
									to = get_node(String(connecting_from)); //maybe it was erased
									if (Object::cast_to<GraphNode>(to)) {
										connecting = true;
									}
									return;
								}
							}
						}
					}

					connecting = true;
					connecting_from = gn->get_name();
					connecting_index = j;
					connecting_out = true;
					connecting_type = gn->get_connection_output_type(j);
					connecting_color = gn->get_connection_output_color(j);
					connecting_target = false;
					connecting_to = pos;
					just_disconnected = false;
					return;
				}
			}

			for (int j = 0; j < gn->get_connection_input_count(); j++) {

				Vector2 pos = gn->get_connection_input_position(j) + gn->get_position();
				if (is_in_hot_zone(pos, mpos)) {

					if (right_disconnects || valid_right_disconnect_types.has(gn->get_connection_input_type(j))) {
						//check disconnect
						for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {

							if (E->get().to == gn->get_name() && E->get().to_port == j) {

								Node *fr = get_node(String(E->get().from));
								if (Object::cast_to<GraphNode>(fr)) {

									connecting_from = E->get().from;
									connecting_index = E->get().from_port;
									connecting_out = true;
									connecting_type = Object::cast_to<GraphNode>(fr)->get_connection_output_type(E->get().from_port);
									connecting_color = Object::cast_to<GraphNode>(fr)->get_connection_output_color(E->get().from_port);
									connecting_target = false;
									connecting_to = pos;
									just_disconnected = true;

									emit_signal("disconnection_request", E->get().from, E->get().from_port, E->get().to, E->get().to_port);
									fr = get_node(String(connecting_from)); //maybe it was erased
									if (Object::cast_to<GraphNode>(fr)) {
										connecting = true;
									}
									return;
								}
							}
						}
					}

					connecting = true;
					connecting_from = gn->get_name();
					connecting_index = j;
					connecting_out = false;
					connecting_type = gn->get_connection_input_type(j);
					connecting_color = gn->get_connection_input_color(j);
					connecting_target = false;
					connecting_to = pos;
					just_disconnected = true;

					return;
				}
			}
		}
	}

	Ref<InputEventMouseMotion> mm = p_ev;
	if (mm.is_valid() && connecting) {

		connecting_to = mm->get_position();
		connecting_target = false;
		top_layer->update();

		Ref<Texture> port = get_icon("port", "GraphNode");
		Vector2 mpos = mm->get_position();
		for (int i = get_child_count() - 1; i >= 0; i--) {

			GraphNode *gn = Object::cast_to<GraphNode>(get_child(i));
			if (!gn)
				continue;

			if (!connecting_out) {
				for (int j = 0; j < gn->get_connection_output_count(); j++) {

					Vector2 pos = gn->get_connection_output_position(j) + gn->get_position();
					int type = gn->get_connection_output_type(j);
					if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && is_in_hot_zone(pos, mpos)) {

						connecting_target = true;
						connecting_to = pos;
						connecting_target_to = gn->get_name();
						connecting_target_index = j;
						return;
					}
				}
			} else {

				for (int j = 0; j < gn->get_connection_input_count(); j++) {

					Vector2 pos = gn->get_connection_input_position(j) + gn->get_position();
					int type = gn->get_connection_input_type(j);
					if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && is_in_hot_zone(pos, mpos)) {
						connecting_target = true;
						connecting_to = pos;
						connecting_target_to = gn->get_name();
						connecting_target_index = j;
						return;
					}
				}
			}
		}
	}

	if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && !mb->is_pressed()) {

		if (connecting && connecting_target) {

			String from = connecting_from;
			int from_slot = connecting_index;
			String to = connecting_target_to;
			int to_slot = connecting_target_index;

			if (!connecting_out) {
				SWAP(from, to);
				SWAP(from_slot, to_slot);
			}
			emit_signal("connection_request", from, from_slot, to, to_slot);

		} else if (!just_disconnected) {
			String from = connecting_from;
			int from_slot = connecting_index;
			Vector2 ofs = Vector2(mb->get_position().x, mb->get_position().y);
			emit_signal("connection_to_empty", from, from_slot, ofs);
		}
		connecting = false;
		top_layer->update();
		update();
		connections_layer->update();
	}
}
示例#5
0
void GraphEdit::_top_layer_input(const InputEvent &p_ev) {

	float grab_r_extend = 2.0;
	if (p_ev.type == InputEvent::MOUSE_BUTTON && p_ev.mouse_button.button_index == BUTTON_LEFT && p_ev.mouse_button.pressed) {

		Ref<Texture> port = get_icon("port", "GraphNode");
		Vector2 mpos(p_ev.mouse_button.x, p_ev.mouse_button.y);
		float grab_r = port->get_width() * 0.5 * grab_r_extend;
		for (int i = get_child_count() - 1; i >= 0; i--) {

			GraphNode *gn = get_child(i)->cast_to<GraphNode>();
			if (!gn)
				continue;

			for (int j = 0; j < gn->get_connection_output_count(); j++) {

				Vector2 pos = gn->get_connection_output_pos(j) + gn->get_pos();
				if (pos.distance_to(mpos) < grab_r) {

					if (valid_left_disconnect_types.has(gn->get_connection_output_type(j))) {
						//check disconnect
						for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {

							if (E->get().from == gn->get_name() && E->get().from_port == j) {

								Node *to = get_node(String(E->get().to));
								if (to && to->cast_to<GraphNode>()) {

									connecting_from = E->get().to;
									connecting_index = E->get().to_port;
									connecting_out = false;
									connecting_type = to->cast_to<GraphNode>()->get_connection_input_type(E->get().to_port);
									connecting_color = to->cast_to<GraphNode>()->get_connection_input_color(E->get().to_port);
									connecting_target = false;
									connecting_to = pos;
									just_disconected = true;

									emit_signal("disconnection_request", E->get().from, E->get().from_port, E->get().to, E->get().to_port);
									to = get_node(String(connecting_from)); //maybe it was erased
									if (to && to->cast_to<GraphNode>()) {
										connecting = true;
									}
									return;
								}
							}
						}
					}

					connecting = true;
					connecting_from = gn->get_name();
					connecting_index = j;
					connecting_out = true;
					connecting_type = gn->get_connection_output_type(j);
					connecting_color = gn->get_connection_output_color(j);
					connecting_target = false;
					connecting_to = pos;
					just_disconected = false;
					return;
				}
			}

			for (int j = 0; j < gn->get_connection_input_count(); j++) {

				Vector2 pos = gn->get_connection_input_pos(j) + gn->get_pos();

				if (pos.distance_to(mpos) < grab_r) {

					if (right_disconnects || valid_right_disconnect_types.has(gn->get_connection_input_type(j))) {
						//check disconnect
						for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {

							if (E->get().to == gn->get_name() && E->get().to_port == j) {

								Node *fr = get_node(String(E->get().from));
								if (fr && fr->cast_to<GraphNode>()) {

									connecting_from = E->get().from;
									connecting_index = E->get().from_port;
									connecting_out = true;
									connecting_type = fr->cast_to<GraphNode>()->get_connection_output_type(E->get().from_port);
									connecting_color = fr->cast_to<GraphNode>()->get_connection_output_color(E->get().from_port);
									connecting_target = false;
									connecting_to = pos;
									just_disconected = true;

									emit_signal("disconnection_request", E->get().from, E->get().from_port, E->get().to, E->get().to_port);
									fr = get_node(String(connecting_from)); //maybe it was erased
									if (fr && fr->cast_to<GraphNode>()) {
										connecting = true;
									}
									return;
								}
							}
						}
					}

					connecting = true;
					connecting_from = gn->get_name();
					connecting_index = j;
					connecting_out = false;
					connecting_type = gn->get_connection_input_type(j);
					connecting_color = gn->get_connection_input_color(j);
					connecting_target = false;
					connecting_to = pos;
					just_disconected = true;

					return;
				}
			}
		}
	}

	if (p_ev.type == InputEvent::MOUSE_MOTION && connecting) {

		connecting_to = Vector2(p_ev.mouse_motion.x, p_ev.mouse_motion.y);
		connecting_target = false;
		top_layer->update();

		Ref<Texture> port = get_icon("port", "GraphNode");
		Vector2 mpos(p_ev.mouse_button.x, p_ev.mouse_button.y);
		float grab_r = port->get_width() * 0.5 * grab_r_extend;
		for (int i = get_child_count() - 1; i >= 0; i--) {

			GraphNode *gn = get_child(i)->cast_to<GraphNode>();
			if (!gn)
				continue;

			if (!connecting_out) {
				for (int j = 0; j < gn->get_connection_output_count(); j++) {

					Vector2 pos = gn->get_connection_output_pos(j) + gn->get_pos();
					int type = gn->get_connection_output_type(j);
					if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && pos.distance_to(mpos) < grab_r) {

						connecting_target = true;
						connecting_to = pos;
						connecting_target_to = gn->get_name();
						connecting_target_index = j;
						return;
					}
				}
			} else {

				for (int j = 0; j < gn->get_connection_input_count(); j++) {

					Vector2 pos = gn->get_connection_input_pos(j) + gn->get_pos();
					int type = gn->get_connection_input_type(j);
					if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && pos.distance_to(mpos) < grab_r) {
						connecting_target = true;
						connecting_to = pos;
						connecting_target_to = gn->get_name();
						connecting_target_index = j;
						return;
					}
				}
			}
		}
	}

	if (p_ev.type == InputEvent::MOUSE_BUTTON && p_ev.mouse_button.button_index == BUTTON_LEFT && !p_ev.mouse_button.pressed) {

		if (connecting && connecting_target) {

			String from = connecting_from;
			int from_slot = connecting_index;
			String to = connecting_target_to;
			int to_slot = connecting_target_index;

			if (!connecting_out) {
				SWAP(from, to);
				SWAP(from_slot, to_slot);
			}
			emit_signal("connection_request", from, from_slot, to, to_slot);

		} else if (!just_disconected) {
			String from = connecting_from;
			int from_slot = connecting_index;
			Vector2 ofs = Vector2(p_ev.mouse_button.x, p_ev.mouse_button.y);
			emit_signal("connection_to_empty", from, from_slot, ofs);
		}
		connecting = false;
		top_layer->update();
		update();
		connections_layer->update();
	}
}