Skip to content

Commit 97bc0c2

Browse files
warriormaster12Alexander Streng
authored andcommitted
Add audio_stream_graph
1 parent 1f47e4c commit 97bc0c2

File tree

8 files changed

+4356
-0
lines changed

8 files changed

+4356
-0
lines changed

editor/plugins/audio_graph_editor_plugin.cpp

Lines changed: 1873 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 347 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,347 @@
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

editor/register_editor_types.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
#include "editor/import/resource_importer_texture_atlas.h"
6969
#include "editor/import/resource_importer_wav.h"
7070
#include "editor/plugins/animation_tree_editor_plugin.h"
71+
#include "editor/plugins/audio_graph_editor_plugin.h"
7172
#include "editor/plugins/audio_stream_editor_plugin.h"
7273
#include "editor/plugins/audio_stream_randomizer_editor_plugin.h"
7374
#include "editor/plugins/bit_map_editor_plugin.h"
@@ -207,6 +208,7 @@ void register_editor_types() {
207208

208209
// This list is alphabetized, and plugins that depend on Node2D are in their own section below.
209210
EditorPlugins::add_by_type<AnimationTreeEditorPlugin>();
211+
EditorPlugins::add_by_type<AudioGraphEditorPlugin>();
210212
EditorPlugins::add_by_type<AudioStreamEditorPlugin>();
211213
EditorPlugins::add_by_type<AudioStreamRandomizerEditorPlugin>();
212214
EditorPlugins::add_by_type<BitMapEditorPlugin>();

scene/register_scene_types.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@
107107
#include "scene/resources/animated_texture.h"
108108
#include "scene/resources/animation_library.h"
109109
#include "scene/resources/atlas_texture.h"
110+
#include "scene/resources/audio_stream_graph.h"
111+
#include "scene/resources/audio_stream_graph_nodes.h"
110112
#include "scene/resources/audio_stream_polyphonic.h"
111113
#include "scene/resources/audio_stream_wav.h"
112114
#include "scene/resources/bit_map.h"
@@ -996,6 +998,17 @@ void register_scene_types() {
996998
GDREGISTER_CLASS(AudioStreamPlayer);
997999
GDREGISTER_CLASS(AudioStreamWAV);
9981000
GDREGISTER_CLASS(AudioStreamPolyphonic);
1001+
GDREGISTER_CLASS(AudioStreamGraph);
1002+
GDREGISTER_ABSTRACT_CLASS(AudioStreamGraphNode);
1003+
GDREGISTER_ABSTRACT_CLASS(AudioStreamGraphNodePlayback);
1004+
GDREGISTER_ABSTRACT_CLASS(AudioStreamGraphNodeParameter);
1005+
GDREGISTER_ABSTRACT_CLASS(AudioStreamPlaybackGraph);
1006+
GDREGISTER_CLASS(AudioStreamGraphInputNode);
1007+
GDREGISTER_CLASS(AudioStreamGraphOutputNode);
1008+
GDREGISTER_CLASS(AudioStreamGraphRandomizerNode);
1009+
GDREGISTER_CLASS(AudioStreamGraphMixerNode);
1010+
GDREGISTER_CLASS(AudioStreamGraphModulatorNode);
1011+
GDREGISTER_CLASS(AudioStreamGraphNodeFloatParameter);
9991012
GDREGISTER_ABSTRACT_CLASS(AudioStreamPlaybackPolyphonic);
10001013

10011014
OS::get_singleton()->yield(); // may take time to init

0 commit comments

Comments
 (0)