OverviewFilesCommitsIssuesDocsReleasesPeers

proc-nodes / src / editor / proc_graph_edit.h

114 lines · c ref:
#ifndef PROC_GRAPH_EDIT_H
#define PROC_GRAPH_EDIT_H

#ifdef TOOLS_ENABLED

#include "../graph/proc_node_graph.h"
#include "../scene/proc_geometry_node.h"
#include <godot_cpp/classes/button.hpp>
#include <godot_cpp/classes/editor_undo_redo_manager.hpp>
#include <godot_cpp/classes/graph_edit.hpp>
#include <godot_cpp/classes/graph_frame.hpp>
#include <godot_cpp/classes/graph_node.hpp>
#include <godot_cpp/classes/check_box.hpp>
#include <godot_cpp/classes/color_picker_button.hpp>
#include <godot_cpp/classes/input_event.hpp>
#include <godot_cpp/classes/line_edit.hpp>
#include <godot_cpp/classes/popup_panel.hpp>
#include <godot_cpp/classes/spin_box.hpp>
#include <godot_cpp/classes/file_dialog.hpp>
#include <godot_cpp/classes/option_button.hpp>
#include <godot_cpp/classes/tree.hpp>

namespace godot {

// Node type entry for palette
struct ProcNodeEntry {
	String type_name;  // e.g. "MeshCube"
	String title;      // e.g. "Mesh Cube"
	String category;   // e.g. "Mesh"
};

class ProcGraphEdit : public GraphEdit {
	GDCLASS(ProcGraphEdit, GraphEdit);

protected:
	static void _bind_methods();
	void _notification(int p_what);

	ProcGeometryNode *edited_node = nullptr;

	// Node palette (PopupPanel auto-closes on click outside)
	PopupPanel *palette_popup = nullptr;
	Tree *palette_tree = nullptr;
	LineEdit *palette_search = nullptr;
	Vector2 palette_spawn_position;
	Vector<ProcNodeEntry> node_entries;
	void _build_node_entries();
	void _populate_palette_tree(const String &p_filter = "");
	void _show_palette(const Vector2 &p_screen_position, const Vector2 &p_graph_position);

	// Graph rebuild
	void _rebuild_graph();
	GraphNode *_create_graph_node(int p_node_idx, const Ref<ProcNode> &p_node);
	Color _socket_color(SocketType p_type) const;
	void _register_connection_types();

	// Zone frames
	void _rebuild_zone_frames();

	// Undo/redo
	EditorUndoRedoManager *_get_undo_redo() const;

	// Toolbar — graph management
	Button *new_button = nullptr;
	Button *save_button = nullptr;
	Button *load_button = nullptr;
	Button *bake_button = nullptr;
	FileDialog *load_dialog = nullptr;
	FileDialog *save_dialog = nullptr;
	String _current_graph_path;

	// Clipboard for copy/paste
	Vector<Ref<ProcNode>> clipboard_nodes;
	Vector<ProcConnection> clipboard_connections;
	Vector2 clipboard_center;

	// Deferred graph refresh (avoids re-entrancy)
	bool _refresh_pending = false;
	void _schedule_refresh();
	void _do_refresh();
	void _sync_defaults_from_graph(); // Rebuild UI only (no invalidate_plan)

public:
	void set_edited_node(ProcGeometryNode *p_node);

	// Right-click → palette
	void _gui_input(const Ref<InputEvent> &p_event) override;

	// Signal callbacks
	void _on_connection_request(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port);
	void _on_disconnection_request(const StringName &p_from, int p_from_port, const StringName &p_to, int p_to_port);
	void _on_delete_nodes_request(const TypedArray<StringName> &p_nodes);
	void _on_node_selected(Node *p_node);
	void _on_end_node_move();
	void _on_palette_item_activated();
	void _on_palette_search_changed(const String &p_text);
	void _on_new_pressed();
	void _on_save_pressed();
	void _on_load_pressed();
	void _on_save_file_selected(const String &p_path);
	void _on_load_file_selected(const String &p_path);
	void _on_bake_pressed();
	void _on_default_value_changed(const Variant &p_value, int p_node_idx, int p_socket_idx);
	void _on_node_property_changed(const Variant &p_value, int p_node_idx, const String &p_property);

	ProcGraphEdit();
	~ProcGraphEdit();
};

} // namespace godot

#endif // TOOLS_ENABLED
#endif // PROC_GRAPH_EDIT_H