TerraForge3D  2.3.1
3D Terrain And Landscape Generator
CPUNodeEditor.cpp
1#include "Generators/CPUNodeEditor/CPUNodeEditor.h"
2
3#include "Data/ApplicationState.h"
4#include "Profiler.h"
5#include "Utils/Utils.h"
6#include "Platform.h"
7
8#include "imgui.h"
9#include "Base/ImGuiShapes.h"
10#include "Base/NodeEditor/NodeEditor.h"
11#include "imgui_internal.h"
12
13#include "GLFW/glfw3.h"
14
15// Nodes
16#include "Generators/CPUNodeEditor/Nodes/DummyNode.h"
17#include "Generators/CPUNodeEditor/Nodes/AddNode.h"
18#include "Generators/CPUNodeEditor/Nodes/SubNode.h"
19#include "Generators/CPUNodeEditor/Nodes/MulNode.h"
20#include "Generators/CPUNodeEditor/Nodes/DivNode.h"
21#include "Generators/CPUNodeEditor/Nodes/AbsNode.h"
22#include "Generators/CPUNodeEditor/Nodes/SinNode.h"
23#include "Generators/CPUNodeEditor/Nodes/CosNode.h"
24#include "Generators/CPUNodeEditor/Nodes/TanNode.h"
25#include "Generators/CPUNodeEditor/Nodes/BlendNode.h"
26#include "Generators/CPUNodeEditor/Nodes/CurveNode.h"
27#include "Generators/CPUNodeEditor/Nodes/NoisePerlinNode.h"
28#include "Generators/CPUNodeEditor/Nodes/NoiseCellularNode.h"
29#include "Generators/CPUNodeEditor/Nodes/NoiseValueNode.h"
30#include "Generators/CPUNodeEditor/Nodes/NoiseValueCubicNode.h"
31#include "Generators/CPUNodeEditor/Nodes/NoiseOpenSimplex2Node.h"
32#include "Generators/CPUNodeEditor/Nodes/NoiseOpenSimplex2SNode.h"
33#include "Generators/CPUNodeEditor/Nodes/MeshCoordinatesNode.h"
34#include "Generators/CPUNodeEditor/Nodes/MinMeshCoordinatesNode.h"
35#include "Generators/CPUNodeEditor/Nodes/MaxMeshCoordinatesNode.h"
36#include "Generators/CPUNodeEditor/Nodes/TextureCoordinatesNode.h"
37#include "Generators/CPUNodeEditor/Nodes/TimeBasedSeedNode.h"
38#include "Generators/CPUNodeEditor/Nodes/RandomNumberNode.h"
39#include "Generators/CPUNodeEditor/Nodes/DuplicateNode.h"
40#include "Generators/CPUNodeEditor/Nodes/MathFunctionNode.h"
41#include "Generators/CPUNodeEditor/Nodes/OutputNode.h"
42#include "Generators/CPUNodeEditor/Nodes/PixelateNode.h"
43#include "Generators/CPUNodeEditor/Nodes/VisualizerNode.h"
44#include "Generators/CPUNodeEditor/Nodes/TextureNode.h"
45#include "Generators/CPUNodeEditor/Nodes/HeightmapNode.h"
46#include "Generators/CPUNodeEditor/Nodes/HillNode.h"
47#include "Generators/CPUNodeEditor/Nodes/MinValNode.h"
48#include "Generators/CPUNodeEditor/Nodes/SquareNode.h"
49#include "Generators/CPUNodeEditor/Nodes/ClampNode.h"
50
51
52#include <iostream>
53#include <mutex>
54
55static char *stristr4(const char *str, const char *pattern)
56{
57 size_t i;
58
59 if (!*pattern)
60 {
61 return (char *)str;
62 }
63
64 for (; *str; str++)
65 {
66 if (toupper((unsigned char)*str) == toupper((unsigned char)*pattern))
67 {
68 for (i = 1;; i++)
69 {
70 if (!pattern[i])
71 {
72 return (char *)str;
73 }
74
75 if (toupper((unsigned char)str[i]) != toupper((unsigned char)pattern[i]))
76 {
77 break;
78 }
79 }
80 }
81 }
82
83 return NULL;
84}
85
86#define NODE_MAKER_COND(x) length == 0 || stristr4(x, data)
87#define NODE_MAKER_SHOW(x, y) if (NODE_MAKER_COND(y)) {if (ImGui::Button((y + std::string("##CPUNE") + uid).c_str())) { editor->AddNode(new x()); ImGui::CloseCurrentPopup(); } }
88
89static int count = 1;
90
91static void ShowNodeMaker(std::string &uid, NodeEditor *editor)
92{
93 static char data[1000];
94 ImGui::InputTextWithHint("##SearchMeshNodes", "Search ...", data, sizeof(data));
95 int length = strlen(data);
96 ImGui::BeginChild(("##CPUNE" + uid).c_str(), ImVec2(200, 250));
97 NODE_MAKER_SHOW(DummyNode, "Dummy");
98 NODE_MAKER_SHOW(MeshCoordinatesNode, "Mesh Coordinates");
99 NODE_MAKER_SHOW(MaxMeshCoordinatesNode, "Maximum Mesh Coordinates");
100 NODE_MAKER_SHOW(TextureCoordinatesNode, "Texture Coordinates");
101 NODE_MAKER_SHOW(MinMeshCoordinatesNode, "Minimum Mesh Coordinates");
102 NODE_MAKER_SHOW(TimeBasedSeedNode, "Time Based Seed");
103 NODE_MAKER_SHOW(PixelateNode, "Pixelate");
104 NODE_MAKER_SHOW(TextureNode, "Texture");
105 NODE_MAKER_SHOW(HeightmapNode, "Heightmap");
106 NODE_MAKER_SHOW(HillNode, "Hill");
107 NODE_MAKER_SHOW(AddNode, "Add");
108 NODE_MAKER_SHOW(SubNode, "Subtract");
109 NODE_MAKER_SHOW(MulNode, "Multiply");
110 NODE_MAKER_SHOW(DivNode, "Divide");
111 NODE_MAKER_SHOW(AbsNode, "Absolute Value");
112 NODE_MAKER_SHOW(SinNode, "Sin");
113 NODE_MAKER_SHOW(CosNode, "Cos");
114 NODE_MAKER_SHOW(TanNode, "Tan");
115 NODE_MAKER_SHOW(SquareNode, "Square");
116 NODE_MAKER_SHOW(BlendNode, "Blend");
117 NODE_MAKER_SHOW(ClampNode, "Clamp");
118 NODE_MAKER_SHOW(CurveNode, "Curve Editor");
119 NODE_MAKER_SHOW(RandomNumberNode, "Random Number");
120 NODE_MAKER_SHOW(NoisePerlinNode, "Perlin Noise");
121 NODE_MAKER_SHOW(NoiseCellularNode, "Cellular Noise");
122 NODE_MAKER_SHOW(NoiseValueNode, "Value Noise");
123 NODE_MAKER_SHOW(NoiseOpenSimplex2Node, "Open Simplex 2 Noise");
124 NODE_MAKER_SHOW(NoiseOpenSimplex2SNode, "Open Simplex 2S Noise");
125 NODE_MAKER_SHOW(NoiseValueCubicNode, "Value Cubic Noise");
126 NODE_MAKER_SHOW(DuplicateNode, "Duplicate");
127 NODE_MAKER_SHOW(MathFunctionNode, "Custom Math Funcion");
128 NODE_MAKER_SHOW(MinValNode, "MinVal");
129 NODE_MAKER_SHOW(VisualizerNode, "Visualizer");
130 ImGui::EndChild();
131}
132
133CPUNodeEditor::CPUNodeEditor(ApplicationState *as)
134 :appState(as)
135{
136 uid = GenerateId(32);
137 name.reserve(1024);
138 name = "CPU Node Editor " + std::to_string(count++);
139 NodeEditorConfig config;
140 config.saveFile = GetExecutableDir() + PATH_SEPARATOR "Data" PATH_SEPARATOR "configs" PATH_SEPARATOR "CPUNodeEditorconfigs.terr3d";
141 config.makeNodeFunc = [&]()
142 {
143 ImGuiNodeEditor::Suspend();
144 ImGui::OpenPopup("NodeMakerDropped");
145 ImGuiNodeEditor::Resume();
146 };
147 config.insNodeFunc = [&](nlohmann::json data) -> NodeEditorNode*
148 {
149 NodeEditorNode *node;
150 CPUNodeEditorE::CPUNodeType type = (CPUNodeEditorE::CPUNodeType)data["type"];
151
152 switch (type)
153 {
154 case CPUNodeEditorE::CPUNodeType::Dummy:
155 node = new DummyNode();
156 break;
157
158 case CPUNodeEditorE::CPUNodeType::Output:
159 node = new OutputNode();
160 break;
161
162 case CPUNodeEditorE::CPUNodeType::MeshCoordinates:
163 node = new MeshCoordinatesNode();
164 break;
165
166 case CPUNodeEditorE::CPUNodeType::MaxMeshCoordinates:
167 node = new MaxMeshCoordinatesNode();
168 break;
169
170 case CPUNodeEditorE::CPUNodeType::MinMeshCoordinates:
171 node = new MinMeshCoordinatesNode();
172 break;
173
174 case CPUNodeEditorE::CPUNodeType::TextureCoordinates:
175 node = new TextureCoordinatesNode();
176 break;
177
178 case CPUNodeEditorE::CPUNodeType::TimeBasedSeed:
179 node = new TimeBasedSeedNode();
180 break;
181
182 case CPUNodeEditorE::CPUNodeType::Duplicate:
183 node = new DuplicateNode();
184 break;
185
186 case CPUNodeEditorE::CPUNodeType::Add:
187 node = new AddNode();
188 break;
189
190 case CPUNodeEditorE::CPUNodeType::Sub:
191 node = new SubNode();
192 break;
193
194 case CPUNodeEditorE::CPUNodeType::Mul:
195 node = new MulNode();
196 break;
197
198 case CPUNodeEditorE::CPUNodeType::Div:
199 node = new DivNode();
200 break;
201
202 case CPUNodeEditorE::CPUNodeType::Sin:
203 node = new SinNode();
204 break;
205
206 case CPUNodeEditorE::CPUNodeType::Cos:
207 node = new CosNode();
208 break;
209
210 case CPUNodeEditorE::CPUNodeType::Square:
211 node = new SquareNode();
212 break;
213
214 case CPUNodeEditorE::CPUNodeType::Tan:
215 node = new TanNode();
216 break;
217
218 case CPUNodeEditorE::CPUNodeType::Abs:
219 node = new AbsNode();
220 break;
221
222 case CPUNodeEditorE::CPUNodeType::Blend:
223 node = new BlendNode();
224 break;
225
226 case CPUNodeEditorE::CPUNodeType::Curve:
227 node = new CurveNode();
228 break;
229
230 case CPUNodeEditorE::CPUNodeType::RandomNumber:
231 node = new RandomNumberNode();
232 break;
233
234 case CPUNodeEditorE::CPUNodeType::NoisePerlin:
235 node = new NoisePerlinNode();
236 break;
237
238 case CPUNodeEditorE::CPUNodeType::NoiseCellular:
239 node = new NoiseCellularNode();
240 break;
241
242 case CPUNodeEditorE::CPUNodeType::NoiseOpenSimplex2:
243 node = new NoiseOpenSimplex2Node();
244 break;
245
246 case CPUNodeEditorE::CPUNodeType::NoiseOpenSimplex2S:
247 node = new NoiseOpenSimplex2SNode();
248 break;
249
250 case CPUNodeEditorE::CPUNodeType::NoiseValue:
251 node = new NoiseValueNode();
252 break;
253
254 case CPUNodeEditorE::CPUNodeType::NoiseValueCubic:
255 node = new NoiseValueCubicNode();
256 break;
257
258 case CPUNodeEditorE::CPUNodeType::MathFunction:
259 node = new MathFunctionNode();
260 break;
261
262 case CPUNodeEditorE::CPUNodeType::Texture:
263 node = new TextureNode();
264 break;
265
266 case CPUNodeEditorE::CPUNodeType::Heightmap:
267 node = new HeightmapNode();
268 break;
269
270 case CPUNodeEditorE::CPUNodeType::Pixelate:
271 node = new PixelateNode();
272 break;
273
274 case CPUNodeEditorE::CPUNodeType::Visualizer:
275 node = new VisualizerNode();
276 break;
277
278 case CPUNodeEditorE::CPUNodeType::Hill:
279 node = new HillNode();
280 break;
281
282 case CPUNodeEditorE::CPUNodeType::Clamp:
283 node = new ClampNode();
284 break;
285
286 case CPUNodeEditorE::CPUNodeType::MinVal:
287 node = new MinValNode();
288 break;
289
290 default:
291 node = nullptr;
292 Log("Unknown Node Type!");
293 break;
294 }
295
296 return node;
297 };
298 editor = new NodeEditor(config);
299 editor->name = name;
300 editor->SetOutputNode(new OutputNode());
301}
302
303CPUNodeEditor::~CPUNodeEditor()
304{
305 delete editor;
306}
307
308nlohmann::json CPUNodeEditor::Save()
309{
310 nlohmann::json data;
311 data["nodeEditor"] = editor->Save();
312 data["windowStat"] = windowStat;
313 data["enabled"] = enabled;
314 data["uiActive"] = uiActive;
315 data["uid"] = uid;
316 return data;
317}
318
319void CPUNodeEditor::Load(nlohmann::json data)
320{
321 while(appState->states.remeshing);
322
323 editor->Load(data["nodeEditor"]);
324 windowStat = data["windowStat"];
325 enabled = data["enabled"];
326 uiActive = data["uiActive"];
327 uid = data["uid"];
328}
329
330void CPUNodeEditor::Update()
331{
332 if(windowStat)
333 {
334 ImGui::Begin((name + "##" + uid).c_str(), &windowStat);
335
336 if (ImGui::Button(("Add Node##CPUNE" + uid).c_str()))
337 {
338 ImGui::OpenPopup("NodeMakerDropped");
339 }
340
341 ImGui::SameLine();
342
343 if (ImGui::Button(("Reset##CPUNE" + uid).c_str()))
344 {
345 editor->Reset();
346 }
347
348 ImGui::SameLine();
349
350 if (ImGui::Button(("Export##CPUNE" + uid).c_str()))
351 {
352 std::string file = ShowSaveFileDialog("*.terr3d");
353
354 if (file.size() > 3)
355 {
356 if (file.find(".terr3d") == std::string::npos)
357 {
358 file += ".terr3d";
359 }
360
361 SaveToFile(file, editor->Save().dump(4));
362 }
363 }
364
365 ImGui::SameLine();
366
367 if (ImGui::Button(("Import##CPUNE" + uid).c_str()))
368 {
369 std::string file = ShowOpenFileDialog("*.terr3d");
370
371 if (file.size() > 3)
372 {
373 bool tmp = false;
374 editor->Reset();
375 editor->Load(nlohmann::json::parse(ReadShaderSourceFile(file, &tmp)));
376 }
377 }
378
379 editor->Render();
380
381 if (ImGui::IsWindowFocused() && (((IsKeyDown(TERR3D_KEY_RIGHT_SHIFT) || IsKeyDown(TERR3D_KEY_LEFT_SHIFT)) && IsKeyDown(TERR3D_KEY_A)) || IsMouseButtonDown(TERR3D_MOUSE_BUTTON_MIDDLE)))
382 {
383 ImGui::OpenPopup("NodeMakerDropped");
384 }
385
386 if(ImGui::BeginPopup("NodeMakerDropped"))
387 {
388 ShowNodeMaker(uid, editor);
389
390 if (ImGui::Button(("Close##CPUNE" + uid).c_str()))
391 {
392 ImGui::CloseCurrentPopup();
393 }
394
395 ImGui::EndPopup();
396 }
397
398 ImGui::End();
399 }
400}
401
402float CPUNodeEditor::EvaluateAt(NodeInputParam param)
403{
404 //m.lock();
405 //NodeOutput o;
406 return editor->outputNode->Evaluate(param, nullptr).value;
407 //m.unlock();
408 //return o.value;
409}
410
411void CPUNodeEditor::ShowSetting(int id)
412{
413 ImGui::InputText(("Name##CPUNE" + uid).c_str(), name.data(), 1024);
414 ImGui::Checkbox(("Enabled##CPUNE" + uid).c_str(), &enabled);
415
416 if (ImGui::Button(("Edit##CPUNE" + uid).c_str()))
417 {
418 windowStat = true;
419 }
420
421 ImGui::Text("UID : %s", uid.data());
422 ImGui::Text("Time : %lf ms", time);
423}
Definition: AbsNode.h:7
Definition: AddNode.h:7
Definition: CosNode.h:7
Definition: DivNode.h:7
Definition: MulNode.h:7
Definition: SinNode.h:7
Definition: SubNode.h:7
Definition: TanNode.h:7
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json parse(InputType &&i, const parser_callback_t cb=nullptr, const bool allow_exceptions=true, const bool ignore_comments=false)
deserialize from a compatible input
Definition: json.hpp:24605
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
Definition: json.hpp:20117
a class to store JSON values
Definition: json.hpp:17860