#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