OpenShaderDesigner 0.0.1
Loading...
Searching...
No Matches
ShaderGraph.h
1// =====================================================================================================================
2// Copyright 2024 Medusa Slockbower
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14// =====================================================================================================================
15
16#ifndef SHADERGRAPH_H
17#define SHADERGRAPH_H
18
19#include <Editor/EditorWindow.h>
20
21#include <vector>
22#include <unordered_map>
23#include <filesystem>
24#include <unordered_set>
25#include <stack>
26
27#include <open-cpp-utils/startup.h>
28#include <open-cpp-utils/directed_tree.h>
29#include <open-cpp-utils/optional.h>
30
31namespace ocu = open_cpp_utils;
32
33#define RegisterNode(Name, Type) \
34 Node* Create##Type(ShaderGraph& graph, ImVec2 pos) { return new Type(graph, pos); } \
35 STARTUP(_Register##Type) { ShaderGraph::Register(Name, Create##Type); }
36
37namespace OpenShaderDesigner
38{
39 class ShaderGraph;
40 using PinId = uint16_t;
41 using NodeId = uint32_t;
42
43 struct PinPtr
44 {
45 struct Hash
46 {
47 size_t operator()(const PinPtr& p) const
48 {
49 return p.hash();
50 }
51 };
52
53 NodeId Node;
54 PinId Pin;
55 bool Input;
56
57 size_t hash() const { return (Input ? 0 : 0x8000000) | static_cast<size_t>(Node) << 32 | static_cast<size_t>(Pin & 0x7FFFFFFF); }
58
59 bool operator<(const PinPtr& o) const { return hash() < o.hash(); }
60 bool operator==(const PinPtr& o) const { return hash() == o.hash(); }
61 };
62
63 struct Pin
64 {
65 enum PinType
66 {
67 INT = 0
68 , UINT
69 , FLOAT
70 , VECTOR
71
72 , ANY
73 , COUNT
74 };
75
76 enum PinDirection
77 {
78 INPUT
79 , OUTPUT
80 };
81
82 inline const static ImColor Colors[COUNT] = {
83 ImColor(0xB9, 0xF5, 0x94)
84 , ImColor(0x8C, 0xC0, 0x8C)
85 , ImColor(0x37, 0x95, 0x85)
86 , ImColor(0xE3, 0x7D, 0xDC)
87// , ImColor(0xD2, 0x6E, 0x46)
88 , ImColor(0xD2, 0xD5, 0xD3)
89 };
90
91 inline const static std::string TypeNames[COUNT] = {
92 "Int"
93 , "Unsigned Int"
94 , "Float"
95 , "Vector"
96 };
97
98 std::string Name;
99 PinType Type;
100 PinDirection Direction;
101 };
102
103 struct Node
104 {
105 public:
106 ImVec2 Position = { 0, 0 };
107
108 struct
109 {
110 std::string Title = "Node";
111 ImColor Color = Pin::Colors[Pin::VECTOR];
112 bool Enabled = true;
113 } Header;
114
115 struct
116 {
117 std::vector<Pin> Inputs, Outputs;
118 bool DynamicInputs = false;
119 } IO;
120
121 struct
122 {
123 ImVec2 Size;
124 bool Const;
125 } Info;
126
127 Node(
128 ShaderGraph& graph, ImVec2 pos
129 , const std::string& title, ImColor color
130 , const std::vector<Pin>& inputs, bool dyn_inputs
131 , const std::vector<Pin>& outputs
132 , bool constant = false);
133 ~Node() = default;
134
135 virtual Node* Copy(ShaderGraph& graph) const = 0;
136 virtual void Inspect() = 0;
137 };
138
140 : public EditorWindow
141 {
142 private:
143 friend Node;
144
145 using Connection = std::pair<const PinPtr, PinPtr>;
146 using ConnectionMap = std::unordered_multimap<PinPtr, PinPtr, PinPtr::Hash>;
147
148 struct Line
149 {
150 ImColor Color;
151 float Thickness;
152 };
153
154 using ConstructorPtr = Node*(*)(ShaderGraph&, ImVec2);
155 struct ContextMenuItem
156 {
157 std::string Name;
158 ConstructorPtr Constructor;
159 };
160
161 struct GraphState
162 {
163 ShaderGraph& Parent;
164 std::vector<Node*> Nodes;
165 std::unordered_set<PinId> Erased;
166 ConnectionMap Connections;
167
168 GraphState(ShaderGraph& parent);
169 GraphState(const GraphState& other);
170 ~GraphState();
171
172 GraphState& operator=(const GraphState& other);
173 };
174
175 using ContextMenuHierarchy = ocu::directed_tree<ContextMenuItem>;
176 using ContextID = ContextMenuHierarchy::node;
177 inline static ContextMenuHierarchy ContextMenu;
178
179 // Helper functions
180 float CalculateWidth(Node& node);
181 float CalculateHeight(Node& node);
182
183 // Base Draw and Input functions
184 void HandleInput();
185 void DrawGrid();
186 void DrawNode(Node& node, NodeId id);
187 void DrawPin(NodeId node_id, Pin& pin, PinId pin_id, ImVec2 location, bool input);
188 void DrawContextMenu();
189
190 // Connection functions
191 void DrawConnections();
192 void DrawConnection(const PinPtr& a, const PinPtr& b);
193 auto StartConnection(const PinPtr& ptr) -> void;
194 void StopConnection();
195 void CreateConnection(const PinPtr& a, const PinPtr& b);
196 void EraseConnection(const PinPtr& a, const PinPtr& b);
197 void EraseConnections(const PinPtr& a);
198
199 NodeId AddNode(Node* node);
200 void RemoveNode(NodeId id);
201
202 // Clipboard functionality
203 void ClearClipboard();
204 void Copy();
205 void Paste(const ImVec2& location);
206 void EraseSelection();
207
208 // History Functionality
209 void PushState();
210 void PopState();
211
212 // Helper functions
213 float BezierOffset(const ImVec2& out, const ImVec2& in);
214 bool AABB(const ImVec2& a0, const ImVec2& a1, const ImVec2& b0, const ImVec2& b1);
215
216 ImVec2 GridToScreen(const ImVec2& position);
217 ImVec2 ScreenToGrid(const ImVec2& position);
218 ImVec2 SnapToGrid(const ImVec2& position);
219
220 Pin& GetPin(const PinPtr& ptr);
221
222 public:
223 ShaderGraph();
224 ~ShaderGraph();
225
226 void OnOpen() override;
227 void DrawWindow() override;
228
229 static void Register(const std::filesystem::path& path, ConstructorPtr constructor);
230
231 private:
232 GraphState State;
233 std::stack<GraphState> History;
234
235 struct
236 {
237 struct
238 {
239 ImColor BackgroundColor;
240
241 struct
242 {
243 Line Thin, Thick;
244 float Padding;
245 } Lines;
246 } Grid;
247
248 struct
249 {
250 float Rounding;
251 Line Border, SelectedBorder;
252 ImColor Content;
253 ImColor Title;
254
255 struct
256 {
257 float Padding;
258 float BorderThickness;
259 ImColor Background;
260 ImColor Text;
261 Line Connections;
262 } Pins;
263 } Nodes;
264
265 struct
266 {
267 ImColor Background;
268 Line Border;
269 } Selection;
270
271 float FontSize;
272 } Style;
273
274 struct
275 {
276 struct
277 {
278 struct
279 {
280 float Rate, Smoothing;
281 } Scroll;
282 } Input;
283 } Settings;
284
285 struct
286 {
287 ImVec2 Location, ScreenLocation, Delta;
288 float Scroll;
289 bool ClickedSomething;
290
291 ocu::optional<NodeId> FocusedNode;
292 std::unordered_map<NodeId, ImVec2> Locks;
293 std::unordered_set<NodeId> DragSelect;
294 bool LocksDragged, NodeHovered;
295 ocu::optional<PinPtr> NewConnection;
296 std::unordered_set<NodeId> Selected;
297 } Mouse;
298
299 struct
300 {
301 ImVec2 Location;
302 float Zoom, Scroll;
303 } Camera;
304
305 struct
306 {
307 std::vector<Node*> Nodes;
308 ConnectionMap Connections;
309 } Clipboard;
310
311 bool Focused;
312 ImVec2 ContextMenuPosition;
313
314 friend class Inspector;
315 };
316
318 : public EditorWindow
319 {
320 public:
321 Inspector();
322
323 void DrawWindow() override;
324
325 private:
326 ShaderGraph* Graph;
327
328 friend class ShaderGraph;
329 };
330}
331
332#endif //SHADERGRAPH_H
EditorWindow class for wrapping ImGui window functionality.
Definition EditorWindow.h:28
Definition ShaderGraph.h:319
void DrawWindow() override
DrawWindow function for when the EditorWindow is being drawn.
Definition ShaderGraph.cpp:1166
Definition ShaderGraph.h:141
void OnOpen() override
OnOpen callback for when the EditorWindow is opened.
Definition ShaderGraph.cpp:219
void DrawWindow() override
DrawWindow function for when the EditorWindow is being drawn.
Definition ShaderGraph.cpp:227
Definition ShaderGraph.h:104
Definition ShaderGraph.h:64
Definition ShaderGraph.h:46
Definition ShaderGraph.h:44