Skip to content

Commit

Permalink
version bump 1.0.8
Browse files Browse the repository at this point in the history
added persistence of node groups

node groups are also loaded when importing other files
  • Loading branch information
gk646 committed May 23, 2024
1 parent 91c5ba0 commit 8a2df7f
Show file tree
Hide file tree
Showing 29 changed files with 451 additions and 109 deletions.
24 changes: 15 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# raynodes

`raynodes` is a standalone 2D node editor made using [raylib](https://github.com/raysan5/raylib) and [raygui](https://github.com/raysan5/raygui) with a focus
`raynodes` is a standalone 2D node editor made using [raylib](https://github.com/raysan5/raylib)
and [raygui](https://github.com/raysan5/raygui) with a focus
extensibility. It aims to be an attractive tool for any node based task, and supports being integrated into
bigger projects like games, editors...
In many cases it comes close to being a node-editor SDK of sorts.
Expand All @@ -12,14 +13,16 @@ A small showcase of its major features:
- Custom filetype optimized for **low export size**
- **Fast and optimized** import header included for working with project exports!
- Supports both **Windows and Linux** (and possibly macOS)
- **Plugin interface** and capabilities
- **Plugin interface** and capabilities which allows extending the node library
- **Unit testing** of critical parts (importing, persistence...)
- Fully-fledged **User created** nodes in-editor without touching the source code!
- Supports **user-created** nodes inside the editor without touching the source code!
- **Modern code base** using many C++20 and above

For more infos on the design choices go to [Software Design](#Software-Design)
For more information on how to use the editor look at the [raynodes-wiki](https://github.com/gk646/raynodes/wiki).
The other dependencies are [cxstructs](https://github.com/gk646/cxstructs), [tinyfiledialogs](https://sourceforge.net/projects/tinyfiledialogs/) for file dialogs and [catch2](https://github.com/catchorg/Catch2) for testing.
The other dependencies
are [cxstructs](https://github.com/gk646/cxstructs), [tinyfiledialogs](https://sourceforge.net/projects/tinyfiledialogs/)
for file dialogs and [catch2](https://github.com/catchorg/Catch2) for testing.

![Image](.github/fullEditor.png)

Expand All @@ -34,7 +37,8 @@ The other dependencies are [cxstructs](https://github.com/gk646/cxstructs), [tin

### For Users

Just download the .zip for your operating system from the most recent release in the [release page](https://github.com/gk646/raynodes/releases).
Just download the .zip for your operating system from the most recent release in
the [release page](https://github.com/gk646/raynodes/releases).
Unzip and start the executable! Have fun using `raynodes`.

### For Developers
Expand All @@ -49,7 +53,8 @@ To build the project locally you just need to do 4 simple steps:
4. Build the project from inside the build directory with `make ..`

All external dependencies are included in the source!
This model is chosen based on their combined low size (only **14mb**) and the provided simplicity for sharing and integrated testing.
This model is chosen based on their combined low size (only **14mb**) and the provided simplicity for sharing and
integrated testing.

## Editor Features:

Expand All @@ -61,7 +66,6 @@ Files starting with `.` (dot) will be interpreted as relative paths:
Else it will be interpreted as absolute path:
`./raynodes.exe C:\Users\Me\Documents\MyAbsoluteFile.rn`


**On Windows you can also set it as the default executable for ".rn" files, then double click to open any such file!**

### Controls
Expand All @@ -74,10 +78,12 @@ the [shortcuts](https://github.com/gk646/raynodes/wiki/Controls) page in the wik
The user interface takes inspiration from other editors like paint.net. For a comprehensive list checkout
the [user-interface](https://github.com/gk646/raynodes/wiki/User-Interface) page of the wiki!

### User Defined Templates
### User Defined Templates

`raynodes` gives you the ability to create your own nodes without even interacting with the source code!
Open the `Node Creator` window via the button on the left and add a new node by clicking `+Add`. For more in-depth information check out the [User-Created-Nodes](https://github.com/gk646/raynodes/wiki/User-Created-Nodes) page of the wiki!
Open the `Node Creator` window via the button on the left and add a new node by clicking `+Add`. For more in-depth
information check out the [User-Created-Nodes](https://github.com/gk646/raynodes/wiki/User-Created-Nodes) page of the
wiki!

## Custom Components!

Expand Down
File renamed without changes.
12 changes: 6 additions & 6 deletions examples/1BitFullAdder.rn → examples/logic/1BitFullAdder.rn
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
--EditorData--
810-117.000-90.0001.000
810-155.000-306.0000.800
--Templates--
4
0XOR GateGate255
1BoolBool255
2AND GateGate255
3OR GateGate255
--Nodes--
20-309-81
01-305-214
12-616-218
13-619-85
14-62174
20-20150
01-197-83
12-508-87
13-51146
14-196-256
05181-177
2625-35
37176100
Expand Down
65 changes: 65 additions & 0 deletions examples/logic/2BitFullAdder.rn
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
--EditorData--
2328-359.301-355.3030.950
--Templates--
5
0XOR GateGate255
1Bool DisplayDisplay255
2BoolBool255
3AND GateGate255
4OR GateGate255
--Nodes--
30-13-52
01-9-185
22-319-189
23-322-56
24-154-289
05211-302
36218-174
47351-53
38-251-280
09-247-413
210-555-425
211-561-284
212-436-544
013-56-540
314-47-385
41580-281
217-880-513
218-884-367
219-887-237
216-877-633
1212-271
1220-549
1233-412
--Connections--
200100
300000
200001
300101
100500
400601
400501
000701
600700
100600
1100800
1000801
1000900
1100901
9001300
12001301
9001400
12001401
14001500
8001501
16001000
17001100
1800200
1900300
13002200
1500400
5002300
7002100
--Groups--
-596-579Node Group010911814131512
-357-337Node Group021360574
40 changes: 40 additions & 0 deletions examples/quest/SimpleQuest.rn
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
--EditorData--
1120303.237-465.6130.850
--Templates--
3
0Dialog ChoiceNPCTypeDisplayTextChoice1Choice2Choice3Choice4255
1DialogNPCTypeDisplayText255
2QuestHeaderNameDescriptionZoneLevel255
--Nodes--
20TestTestDTEST_ROOM1-807-462
01ARIAWhats your name?NumericNormal nameMehLast one-493-547
02ARIAWhich number?1234-166-862
13ARIA-134-521
14ARIA-126-392
05ARIALast choice huh?Noo never!MaybeIts okOKOKOKOK-124-254
16ARIACool number!235-909
17ARIACool number2238-778
18ARIALooks like your number is too big hehe!224-646
19ARIAOkay, but i gotta go now!774-452
110ARIAWas nice to see you!1140-455
--Connections--
0-101-10
1202-10
1303-10
1404-10
1505-10
2206-10
2307-10
2408-10
2508-10
8-109-10
7-109-10
6-109-10
4-109-10
3-109-10
3-109-10
5209-10
5309-10
5509-10
5409-10
9-1010-10
16 changes: 12 additions & 4 deletions src/external/cxstructs/include/cxutil/cxio.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ inline void io_load_skip_separator(FILE* file) {
}
}
inline bool io_load_inside_section(FILE* file, const char* section) {
long currentPos = ftell(file);
const long currentPos = ftell(file);
if (currentPos == -1) return false; // Error - we return false

char ch;
Expand All @@ -206,23 +206,31 @@ inline bool io_load_inside_section(FILE* file, const char* section) {

char buffer[MAX_SECTION_SIZE] = {};
int count = 0;
int sectionLength = manual_strlen(section);
while (fread(&ch, 1, 1, file) == 1 && count < sectionLength && count < MAX_SECTION_SIZE - 1) {
const int sectionLength = manual_strlen(section);
while (fread(&ch, 1, 1, file) == 1 && ch != '-' && count < sectionLength && count < MAX_SECTION_SIZE - 1) {
buffer[count++] = ch;
}
buffer[count] = '\0'; // Null-terminate the string
if (manual_strncmp(buffer, section, sectionLength) == 0) {
io_load_newline(file, false);
return true; // Found same section
}

io_load_newline(file, false);

return false; // Found new section
}

fseek(file, currentPos, SEEK_SET);
return true; // Still inside same section
}
// Returns true if the next byte is a newline - useful when loading a undefined amount in one line
inline bool io_load_is_newline(FILE* file) {
char c;
fread(&c, 1, 1, file);
const auto result = c == '\n';
fseek(file, -1, SEEK_CUR);
return result;
}
// include <string> to use
# if defined(_STRING_) || defined(_GLIBCXX_STRING)
inline void io_load(FILE* file, std::string& s) {
Expand Down
10 changes: 10 additions & 0 deletions src/external/cxstructs/include/cxutil/cxstring.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,16 @@ inline int str_cmpn_case(const char* s1, const char* s2, int maxCount) {
}
return tolower(*s1) - tolower(*s2);
}
// Case insensitive! - Compares to string with a while loop - stops at max count
inline bool str_cmp_case(const char* s1, const char* s2) {
while (*s1 && *s2) {
const int diff = tolower(*s1) - tolower(*s2);
if (diff != 0) return false;
++s1;
++s2;
}
return tolower(*s1) - tolower(*s2) == 0;
}
// Case insensitive! - Tries to find and return the first occurrence of sequence in string
inline const char* str_substr_case(const char* string, const char* sequence) {
if (!*sequence) return string;
Expand Down
2 changes: 1 addition & 1 deletion src/raynodes/application/EditorContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
#include "context/ContextLogic.h"
#include "context/ContextPersist.h"
#include "context/ContextInput.h"
#include "context/ContextTemplates.h"
#include "context/ContextTemplate.h"
#include "context/ContextPlugin.h"

// We actually wanna keep this as small as possible
Expand Down
2 changes: 1 addition & 1 deletion src/raynodes/application/NodeEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ bool NodeEditor::start() {
c + context.ui.loadUI(context);

// Only load file if path is given - automatically opens picker
if (!context.persist.openedFilePath.empty()) { c + context.persist.importProject(context); }
if (!context.persist.openedFilePath.empty()) c + context.persist.importProject(context);

return c.holds();
}
Expand Down
2 changes: 1 addition & 1 deletion src/raynodes/application/context/ContextCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ struct EXPORT Core final {
if (it != nodeMap.end()) return it->second;
return nullptr;
}
Node* createNode(EditorContext& ec, const char* name, Vector2 worldPos, uint16_t hint = UINT16_MAX);
Node* createAddNode(EditorContext& ec, const char* name, Vector2 worldPos, uint16_t hint = UINT16_MAX);
void insertNode(EditorContext& ec, Node& node);
void removeNode(EditorContext& ec, NodeID id);
void moveToFront(Node* node) {
Expand Down
2 changes: 2 additions & 0 deletions src/raynodes/application/context/ContextPersist.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ struct EXPORT Persist {
bool importProject(EditorContext& ec);
bool saveProject(EditorContext& ec, bool saveAsMode = false);
bool saveUserTemplates(EditorContext& ec);
// Imports only the nodes from another project and calls func for each
bool importNodesFromProject(EditorContext& ec);
};

#endif //RAYNODES_SRC_APPLICATION_CONTEXT_CONTEXTPERSIST_H_
28 changes: 28 additions & 0 deletions src/raynodes/application/context/ContextTerminal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) 2024 gk646
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

#ifndef CONTEXTTERMINAL_H
#define CONTEXTTERMINAL_H

struct Terminal {

};

#endif //CONTEXTTERMINAL_H
6 changes: 5 additions & 1 deletion src/raynodes/application/context/impl/ContextCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ void Core::resetEditor(EditorContext& ec) {
hasUnsavedChanges = false;
}

Node* Core::createNode(EditorContext& ec, const char* name, const Vector2 worldPos, uint16_t hint) {
Node* Core::createAddNode(EditorContext& ec, const char* name, const Vector2 worldPos, uint16_t hint) {
if (name == nullptr) return nullptr;

//Use the hint when provided
Expand All @@ -176,6 +176,7 @@ Node* Core::createNode(EditorContext& ec, const char* name, const Vector2 worldP

return newNode;
}

void Core::insertNode(EditorContext& ec, Node& node) {
if (nodeMap.contains(node.uID)) return;
nodes.push_back(&node);
Expand All @@ -185,10 +186,13 @@ void Core::insertNode(EditorContext& ec, Node& node) {
c->onAddedToScreen(ec, node);
}
}

// Only call with a valid id
void Core::removeNode(EditorContext& ec, const NodeID id) {
if (!nodeMap.contains(id)) return;
const auto node = nodeMap[id];

if (node->isInGroup) [[unlikely]] { NodeGroup::InvokeDelete(ec, *node); }
nodeMap.erase(id);
std::erase(nodes, node);

Expand Down
Loading

0 comments on commit 8a2df7f

Please sign in to comment.