1+ /* *************************************************************************/
2+ /* audio_graph_editor_plugin.h */
3+ /* *************************************************************************/
4+ /* This file is part of: */
5+ /* GODOT ENGINE */
6+ /* https://godotengine.org */
7+ /* *************************************************************************/
8+ /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9+ /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10+ /* */
11+ /* Permission is hereby granted, free of charge, to any person obtaining */
12+ /* a copy of this software and associated documentation files (the */
13+ /* "Software"), to deal in the Software without restriction, including */
14+ /* without limitation the rights to use, copy, modify, merge, publish, */
15+ /* distribute, sublicense, and/or sell copies of the Software, and to */
16+ /* permit persons to whom the Software is furnished to do so, subject to */
17+ /* the following conditions: */
18+ /* */
19+ /* The above copyright notice and this permission notice shall be */
20+ /* included in all copies or substantial portions of the Software. */
21+ /* */
22+ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23+ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24+ /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25+ /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26+ /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27+ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28+ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29+ /* *************************************************************************/
30+
31+ #ifndef AUDIO_GRAPH_EDITOR_PLUGIN
32+ #define AUDIO_GRAPH_EDITOR_PLUGIN
33+
34+ #include " editor/plugins/editor_plugin.h"
35+ #include " scene/gui/graph_edit.h"
36+ #include " scene/resources/audio_stream_graph.h"
37+
38+ class Button ;
39+ class EditorFileDialog ;
40+ class ScrollContainer ;
41+ class Tree ;
42+ class AcceptDialog ;
43+ class LineEdit ;
44+ class RichTextLabel ;
45+ class MenuButton ;
46+ class ConfirmationDialog ;
47+ class GraphEdit ;
48+ class ConfirmationDialog ;
49+ class PopupPanel ;
50+ class EditorProperty ;
51+
52+ class AudioGraphEditorPlugin ;
53+ class AudioGraphEditor ;
54+
55+ class AudioGraphNodePlugin : public RefCounted {
56+ GDCLASS (AudioGraphNodePlugin, RefCounted);
57+
58+ protected:
59+ AudioGraphEditor *ageditor = nullptr ;
60+
61+ protected:
62+ static void _bind_methods ();
63+
64+ GDVIRTUAL2RC (Object *, _create_editor, Ref<Resource>, Ref<AudioGraphNodePlugin>)
65+
66+ public:
67+ void set_editor (AudioGraphEditor *p_editor);
68+ virtual Control *create_editor (const Ref<Resource> &p_parent_resource, const Ref<AudioStreamGraphNode> &p_node);
69+ };
70+
71+ class AudioGraphNodePluginDefault : public AudioGraphNodePlugin {
72+ GDCLASS (AudioGraphNodePluginDefault, AudioGraphNodePlugin);
73+
74+ public:
75+ virtual Control *create_editor (const Ref<Resource> &p_parent_resource, const Ref<AudioStreamGraphNode> &p_node) override ;
76+ };
77+
78+ class AudioGraphEditedProperty : public RefCounted {
79+ GDCLASS (AudioGraphEditedProperty, RefCounted);
80+
81+ private:
82+ Variant edited_property;
83+
84+ protected:
85+ static void _bind_methods ();
86+
87+ public:
88+ void set_edited_property (const Variant &p_variant);
89+ Variant get_edited_property () const ;
90+
91+ AudioGraphEditedProperty () {}
92+ };
93+
94+ class AudioGraphEditor : public Control {
95+ GDCLASS (AudioGraphEditor, Control);
96+ friend class AudioGraphEditorPlugin ;
97+
98+ Vector<String> button_path;
99+ Vector<String> edited_path;
100+
101+ void _update_path ();
102+ void _clear_editors ();
103+ ObjectID current_root;
104+
105+ void _path_button_pressed (int p_path);
106+
107+ PopupPanel *property_editor_popup = nullptr ;
108+ EditorProperty *property_editor = nullptr ;
109+ int editing_node = -1 ;
110+ int editing_port = -1 ;
111+ Ref<AudioGraphEditedProperty> edited_property_holder;
112+
113+ AudioGraphEditorPlugin *graph_plugin = nullptr ;
114+
115+ GraphEdit *graph = nullptr ;
116+ Button *add_node = nullptr ;
117+ Tree *members = nullptr ;
118+ Tree *parameters = nullptr ;
119+ AcceptDialog *alert = nullptr ;
120+ LineEdit *node_filter = nullptr ;
121+ RichTextLabel *node_desc = nullptr ;
122+ MenuButton *tools = nullptr ;
123+ PopupMenu *popup_menu = nullptr ;
124+ PopupMenu *connection_popup_menu = nullptr ;
125+
126+ Point2 saved_node_pos;
127+ Vector2 menu_point;
128+ bool saved_node_pos_dirty = false ;
129+ bool connection_node_insert_requested = false ;
130+ bool updating = false ;
131+ bool drag_dirty = false ;
132+ Ref<GraphEdit::Connection> clicked_connection;
133+ int to_node = -1 ;
134+ int to_slot = -1 ;
135+ int from_node = -1 ;
136+ int from_slot = -1 ;
137+ ConfirmationDialog *members_dialog = nullptr ;
138+ AudioStreamGraphNode::PortType members_input_port_type = AudioStreamGraphNode::PORT_TYPE_MAX;
139+ AudioStreamGraphNode::PortType members_output_port_type = AudioStreamGraphNode::PORT_TYPE_MAX;
140+
141+ AudioStreamGraph *audio_graph = nullptr ;
142+
143+ Variant get_drag_data_fw (const Point2 &p_point, Control *p_from);
144+ bool can_drop_data_fw (const Point2 &p_point, const Variant &p_data, Control *p_from) const ;
145+ void drop_data_fw (const Point2 &p_point, const Variant &p_data, Control *p_from);
146+ void _show_members_dialog (bool at_mouse_pos, AudioStreamGraphNode::PortType p_input_port_type = AudioStreamGraphNode::PORT_TYPE_MAX, AudioStreamGraphNode::PortType p_output_port_type = AudioStreamGraphNode::PORT_TYPE_MAX);
147+
148+ void _member_create ();
149+ void _member_selected ();
150+ void _member_cancel ();
151+ void _update_options_menu ();
152+ void _add_node (int p_idx);
153+ void _sbox_input (const Ref<InputEvent> &p_event);
154+ void _graph_gui_input (const Ref<InputEvent> &p_event);
155+ void _node_menu_id_pressed (int p_idx);
156+ void _connection_menu_id_pressed (int p_idx);
157+ void _connection_request (const String &p_from, int p_from_index, const String &p_to, int p_to_index);
158+ void _disconnection_request (const String &p_from, int p_from_index, const String &p_to, int p_to_index);
159+ void _update_graph ();
160+ void _node_dragged (const Vector2 &p_from, const Vector2 &p_to, int p_node);
161+ void _nodes_dragged ();
162+ void _delete_node_request (int p_node);
163+ void _delete_nodes_request (const TypedArray<StringName> &p_nodes);
164+ void _delete_nodes (const List<int > &p_nodes);
165+ void _edit_port_default_input (Object *p_button, int p_node, int p_port);
166+ void _parameter_line_edit_changed (const String &p_text, int p_node_id);
167+ void _update_parameter_refs (HashSet<String> &p_deleted_names);
168+ void _parameter_line_edit_focus_out (Object *line_edit, int p_node_id);
169+ void _port_edited (const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing);
170+ void _add_input_port (int p_node);
171+ void _remove_input_port (int p_node);
172+ void _script_created (const Ref<Script> &p_script);
173+ void _resource_saved (const Ref<Resource> &p_resource);
174+
175+ void add_plugin (const Ref<AudioGraphNodePlugin> &p_plugin);
176+ void remove_plugin (const Ref<AudioGraphNodePlugin> &p_plugin);
177+
178+ Vector<Ref<AudioGraphNodePlugin>> plugins;
179+
180+ struct CopyItem {
181+ int id;
182+ Ref<AudioStreamGraphNode> node;
183+ Vector2 position;
184+ bool disabled = false ;
185+ };
186+
187+ enum ToolsMenuOptions {
188+ EXPAND_ALL,
189+ COLLAPSE_ALL
190+ };
191+
192+ enum NodeMenuOptions {
193+ ADD,
194+ SEPARATOR, // ignore
195+ CUT,
196+ COPY,
197+ PASTE,
198+ DELETE,
199+ DUPLICATE,
200+ CLEAR_COPY_BUFFER,
201+ };
202+
203+ enum ConnectionMenuOptions {
204+ INSERT_NEW_NODE,
205+ INSERT_NEW_REROUTE,
206+ DISCONNECT,
207+ };
208+
209+ struct AddOption {
210+ String name;
211+ String type;
212+ String description;
213+ Vector<Variant> ops;
214+ Ref<Script> script;
215+ int mode = 0 ;
216+ int return_type = 0 ;
217+ int func = 0 ;
218+ bool is_custom = false ;
219+ bool is_native = false ;
220+ int temp_idx = 0 ;
221+
222+ AddOption (const String &p_name = String(), const String &p_type = String(), const String &p_description = String(), const Vector<Variant> &p_ops = Vector<Variant>(), int p_return_type = -1 , int p_mode = -1 ) {
223+ name = p_name;
224+ type = p_type;
225+ description = p_description;
226+ ops = p_ops;
227+ return_type = p_return_type;
228+ mode = p_mode;
229+ }
230+ };
231+ // struct _OptionComparator {
232+ // _FORCE_INLINE_ bool operator()(const AddOption &a, const AddOption &b) const {
233+ // return a.category.count("/") > b.category.count("/") || (a.category + "/" + a.name).naturalnocasecmp_to(b.category + "/" + b.name) < 0;
234+ // }
235+ // };
236+
237+ Vector<AddOption> add_options;
238+
239+ struct DragOp {
240+ int node = 0 ;
241+ Vector2 from;
242+ Vector2 to;
243+ };
244+ List<DragOp> drag_buffer;
245+
246+ static Vector2 selection_center;
247+ static List<CopyItem> copy_items_buffer;
248+ static List<AudioGraphEditor::Connection> copy_connections_buffer;
249+
250+ protected:
251+ void _notification (int p_what);
252+ static void _bind_methods ();
253+
254+ static AudioGraphEditor *singleton;
255+
256+ public:
257+ bool can_edit (const Ref<AudioStreamGraph> &p_node) const ;
258+
259+ void edit_path (const Vector<String> &p_path);
260+ Vector<String> get_edited_path () const ;
261+
262+ void enter_editor (const String &p_path = " " );
263+ static AudioGraphEditor *get_singleton () { return singleton; }
264+ void edit (AudioStreamGraph *p_audio_graph);
265+ Ref<AudioStreamGraph> get_audio_graph () const ;
266+ AudioGraphEditorPlugin *get_graph_plugin () const ;
267+ AudioGraphEditor ();
268+ };
269+
270+ class AGGraphNode : public GraphNode {
271+ GDCLASS (AGGraphNode, GraphNode);
272+
273+ protected:
274+ void _draw_port (int p_slot_index, Point2i p_pos, bool p_left, const Color &p_color, const Color &p_rim_color);
275+ virtual void draw_port (int p_slot_index, Point2i p_pos, bool p_left, const Color &p_color) override ;
276+ };
277+
278+ class AGRerouteNode : public AGGraphNode {
279+ GDCLASS (AGRerouteNode, GraphNode);
280+
281+ const float FADE_ANIMATION_LENGTH_SEC = 0.3 ;
282+
283+ float icon_opacity = 0.0 ;
284+
285+ protected:
286+ void _notification (int p_what);
287+
288+ virtual void draw_port (int p_slot_index, Point2i p_pos, bool p_left, const Color &p_color) override ;
289+
290+ public:
291+ AGRerouteNode ();
292+ void set_icon_opacity (float p_opacity);
293+
294+ void _on_mouse_entered ();
295+ void _on_mouse_exited ();
296+ };
297+
298+ class AudioGraphEditorPlugin : public EditorPlugin {
299+ GDCLASS (AudioGraphEditorPlugin, EditorPlugin);
300+
301+ AudioGraphEditor *audio_graph_editor = nullptr ;
302+ Button *editor_button = nullptr ;
303+
304+ struct InputPort {
305+ Button *default_input_button = nullptr ;
306+ };
307+
308+ struct Link {
309+ AudioStreamGraphNode *audio_node = nullptr ;
310+ GraphElement *graph_element = nullptr ;
311+ LineEdit *parameter_name = nullptr ;
312+ HashMap<int , InputPort> input_ports;
313+ };
314+
315+ HashMap<int , Link> links;
316+
317+ List<AudioStreamGraph::Connection> connections;
318+
319+ protected:
320+ static void _bind_methods ();
321+
322+ public:
323+ void clear_links ();
324+ void register_link (int p_id, AudioStreamGraphNode *p_audio_node, GraphElement *p_graph_element);
325+ void register_default_input_button (int p_node_id, int p_port_id, Button *p_button);
326+ void register_parameter_name (int p_node_id, LineEdit *p_parameter_name);
327+ bool has_main_screen () const override { return false ; }
328+ void add_node (int p_id, bool p_just_update);
329+ void update_node (int p_node_id);
330+ void update_node_deferred (int p_node_id);
331+ void remove_node (int p_id, bool p_just_update);
332+ void connect_nodes (int p_from_node, int p_from_port, int p_to_node, int p_to_port);
333+ void disconnect_nodes (int p_from_node, int p_from_port, int p_to_node, int p_to_port);
334+ void set_node_position (int p_id, const Vector2 &p_position);
335+ void set_connections (const List<AudioStreamGraph::Connection> &p_connections);
336+ void set_input_port_default_value (int p_node_id, int p_port_id, const Variant &p_value);
337+
338+ virtual String get_name () const override { return " AudioGraph" ; }
339+ virtual void edit (Object *p_object) override ;
340+ virtual bool handles (Object *p_object) const override ;
341+ virtual void make_visible (bool p_visible) override ;
342+
343+ AudioGraphEditorPlugin ();
344+ ~AudioGraphEditorPlugin ();
345+ };
346+
347+ #endif // AUDIO_GRAPH_EDITOR_PLUGIN
0 commit comments