{"id":15030498,"url":"https://github.com/leon-thomm/ryven","last_synced_at":"2025-05-13T00:19:09.070Z","repository":{"id":39830359,"uuid":"249261267","full_name":"leon-thomm/Ryven","owner":"leon-thomm","description":"Flow-based visual scripting for Python","archived":false,"fork":false,"pushed_at":"2025-02-04T08:10:27.000Z","size":108528,"stargazers_count":3941,"open_issues_count":53,"forks_count":450,"subscribers_count":103,"default_branch":"master","last_synced_at":"2025-05-13T00:18:50.429Z","etag":null,"topics":["flow","python"],"latest_commit_sha":null,"homepage":"https://ryven.org","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/leon-thomm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-03-22T19:54:57.000Z","updated_at":"2025-05-12T21:18:15.000Z","dependencies_parsed_at":"2023-11-24T22:20:48.530Z","dependency_job_id":"e0a473e6-d9f7-4385-b6e3-35c8101eb629","html_url":"https://github.com/leon-thomm/Ryven","commit_stats":{"total_commits":725,"total_committers":9,"mean_commits":80.55555555555556,"dds":0.5075862068965518,"last_synced_commit":"bd5a37bf951968431812ff3c595ab427d9c7ba37"},"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leon-thomm%2FRyven","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leon-thomm%2FRyven/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leon-thomm%2FRyven/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leon-thomm%2FRyven/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leon-thomm","download_url":"https://codeload.github.com/leon-thomm/Ryven/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253843419,"owners_count":21972908,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["flow","python"],"created_at":"2024-09-24T20:13:30.891Z","updated_at":"2025-05-13T00:19:09.016Z","avatar_url":"https://github.com/leon-thomm.png","language":"Python","readme":"\u003e This project is not receiving substantial updates, and I'll have limited time for it in the future. With the latest release the project became quite accurately what I want it to be: an easy and flexible editor and framework to explore use cases of flow-based visual scripting in Python. If you have questions or further ideas feel free to open issues or fork the project and try it yourself.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./docs/img/logo.png\" alt=\"drawing\" width=\"70%\"/\u003e\n\u003c/p\u003e\n\nRyven is an experimental node editor written in Python. It implements a Qt-based visual interface for flow-based visual scripting in Python. It provides a powerful system for developing nodes executing any Python code, and an editor for building graphs using those nodes. Ryven features a bunch of configuration options and a headless mode for running graphs without any GUI. Some relevant GitHub repos:\n\n* [ryvencore](https://github.com/leon-thomm/ryvencore): backend / core library\n* [ryven-blender](https://github.com/leon-thomm/ryven-blender), [ryven-unreal](https://github.com/leon-thomm/ryven-unreal): Ryven plugins for Blender and UE4 (_deprecated_)\n* [PythonOCC nodes for Ryven](https://github.com/Tanneguydv/Pythonocc-nodes-for-Ryven): WIP Ryven nodes for PythonOCC (3D CAD) (_deprecated_)\n* [ironflow](https://github.com/pyiron/ironflow): WIP node interface in jupyter for [pyiron](https://github.com/pyiron) based on ryvencore\n\nThe `ryvencore-qt` library adds Qt-based GUI classes for ryvencore (`./ryvencore-qt/`), and the Ryven editor assembles them into a fully-featured cross-platform application (`./ryven-editor/`).\n\n## Installation and Configuration\n\nOnce you have Python and pip installed, Ryven is available on PyPI via\n\n```\npip install ryven\n```\n\nThere is also a [conda-forge package](https://anaconda.org/conda-forge/ryven) (`conda install -c conda-forge ryven`).\n\nRyven can be launched from the command line by typing `ryven`. If you installed Ryven into a Python virtual environment (or a conda environment), the environment needs to be activated first.\n\nRyven itself only comes with some small example nodes. You should use Ryven either to develop nodes, or use a third-party nodes package for your use case if there is one. The example nodes are - indeed - just examples, and not stable in any way, so you should not depend on them.\n\nWhen installed, ryven will create a directory `~/.ryven/` in your user home with the following structure:\n\n```\n~/.ryven\n├── nodes\n│   ├── your_nodes_pkg_1\n│       ├── nodes.py\n│       └── gui.py\n│   └── ...\n├── saves\n│   ├── your_project_1.json\n│   └── ...\n└── ryven.cfg\n```\n\nThe `ryven.cfg` file contains global configurations for Ryven.\n\nRyven can be configured in four ways:\n1. from the command line, e.g. `ryven --nodes your_nodes_pkg_1 --no-animations`\n2. from a configuration file, e.g. in `~/.ryven/ryven.cfg`:\n   \u003e ```\n   \u003e nodes = your_nodes_pkg_1\n   \u003e no_animations = True\n   \u003e ``` \n3. through arguments when it's integrated in another Python application, e.g.\n   \u003e ```python\n   \u003e import ryven\n   \u003e import pathlib\n   \u003e ryven.run_ryven(nodes=pathlib.Path(['your_nodes_pkg_1']), no_animations=True)\n   \u003e ```\n4. using a GUI in the startup dialog\n   * you can also convert the manual configuration to cmd line args (or a config file) in the dialog\n\nType `ryven --help` for a list of available options.\n\nTo deploy a Ryven project headless (without any GUI) use the `ryven-console` command.\n\n\u003cdetails\u003e\n\u003csummary\u003eExample: headless deployment with REPL access\u003c/summary\u003e\n\n```bash\n\u003e ryven-console /home/leon/.ryven/saves/basics.json\nWelcome to the Ryven Console! Your project has been loaded.\nYou can access the ryvencore session by typing `session`.\nFor more information, visit https://leon-thomm.github.io/ryvencore/\n\n\u003e\u003e\u003e f = session.flows[0]\n\u003e\u003e\u003e ctr_var_result_node = f.nodes[2]\n\u003e\u003e\u003e ctr_set_var_node = f.nodes[8]\n\u003e\u003e\u003e ctr_var_result_node.val\n3738\n\u003e\u003e\u003e ctr_set_var_node.update(0)\n\u003e\u003e\u003e ctr_var_result_node.val\n3739\n```\n\n\u003c/details\u003e\n\n## Editor Usage\n\u003cdetails\u003e\n\u003csummary\u003equick start guide\u003c/summary\u003e\n\n* open Ryven by running `ryven` from the command line\n* you should see the startup dialog\n* create a new project\n* import some example nodes\n  * `File -\u003e Import Example Nodes` and select `\u003cinstallation_dir\u003e/example_nodes/std/nodes.py`\n* you should now see a list of nodes on the left\n* drag and drop them into the scene and connect them with your mouse\n* everything is being executed at runtime; try this:\n  * drag two `val` nodes into the scene\n  * wire them together with a `+` node\n  * display the result in a `result` node \n  * now replace one of them with a slider node generating real numbers\n* by right-clicking, you can also get an interactive nodes list preview inside the scene\n* you can pan around also with the right mouse button (hold and drag)\n* and zoom via `ctrl + scroll`\n\n\u003c/details\u003e\n\n## Developing Nodes\n\n\u003cdetails\u003e\n\u003csummary\u003equick start into to developing node packages\u003c/summary\u003e\n\nA Ryven nodes package is simply a typical Python package which contains at least a `nodes.py` file, and calls the Ryven node API to expose node definitions.\n\nNavigate to `~/.ryven/nodes/` and create a sub-directory of the following structure\n\n```\n~/.ryven/nodes\n└── your_nodes_pkg_1\n    ├── __init__.py\n    ├── nodes.py\n    └── gui.py\n```\n\nwith the following contents:\n\n`nodes.py`:\n\n```python\nfrom ryven.node_env import *\n\n# your node definitions go here\n\nexport_nodes([\n    # list your node classes here\n])\n\n\n@on_gui_load\ndef load_gui():\n    # import gui sources here only\n    from . import gui\n```\n\nand `gui.py`:\n\n```python\nfrom ryven.gui_env import *\n\nfrom . import nodes\n\n# your node gui definitions go here\n```\n\nYou can now start defining your own nodes. Let's define two basic nodes. One which generates random numbers...\n\n```python\nfrom random import random\n\nclass RandNode(Node):\n    \"\"\"Generates scaled random float values\"\"\"\n\n    title = 'Rand'\n    tags = ['random', 'numbers']\n    init_inputs = [NodeInputType()]\n    init_outputs = [NodeOutputType()]\n\n    def update_event(self, inp=-1):\n        self.set_output_val(0, \n            Data(random() * self.input(0).payload)\n        )\n```\n\n...and another one which prints them\n\n```python\nclass PrintNode(Node):\n    title = 'Print'\n    init_inputs = [NodeInputType()]\n\n    def update_event(self, inp=-1):\n        print(self.input(0))\n```\n\nand expose them to Ryven\n\n```python\nexport_nodes([\n    RandNode,\n    PrintNode,\n])\n```\n\nThat's it! You can import your nodes package in Ryven (`File -\u003e Import Nodes`), place the nodes in the graph, and wire them up. Add a `val` node and connect it to the `Rand` node, to feed its input with data. If you type a number into the widget of the `val` node and hit enter, it will send the number to the `Rand` node, which will send a scaled random number to the `Print` node, which will print it to the standard output.\n\nNotice that the standard output is by default the in-editor console, which you can access at the very bottom of the editor window (drag the blue handle up to make it visible).\n\n### Adding GUI\n\nYou can now spice up your nodes with some GUI. Ryven runs on Qt, using either PySide2 or PySide6 (through the [qtpy](https://github.com/spyder-ide/qtpy) library). You can configure the GUI of your nodes in a separate file, and add custom Qt widgets to your nodes. Make sure to always clearly separate the node logic from the GUI components. One of the central features of Ryven is to run projects headless (on ryvencore) without any GUI dependencies. In order for this to work, your `nodes.py` files should never depend on Qt directly. Instead, you can attach custom GUI to your nodes from the GUI files as shown below.\n\nLet's give them some color and add a slider to the `Rand` node, in `gui.py`:\n\n```python\nfrom qtpy.QtWidgets import QSlider\nfrom qtpy.QtCore import Qt\n\nfrom ryven.gui_env import *\n\nfrom . import nodes\n\n\nclass RandSliderWidget(NodeInputWidget, QSlider):\n    \"\"\"a standard Qt slider widget, which updates the node\n    input it is attached to, every time the slider value changes\"\"\"\n    \n    def __init__(self, params):\n        NodeInputWidget.__init__(self, params)\n        QSlider.__init__(self)\n        \n        self.setOrientation(Qt.Horizontal)\n        self.setMinimumWidth(100)\n        self.setMinimum(0)\n        self.setMaximum(100)\n        self.setValue(50)\n        self.valueChanged.connect(self.value_changed)\n    \n    def value_changed(self, val):\n        # updates the node input this widget is attached to\n        self.update_node_input(Data(val))\n    \n    def get_state(self) -\u003e dict:\n        # return the state of the widget\n        return {'value': self.value()}\n    \n    def set_state(self, state: dict):\n        # set the state of the widget\n        self.setValue(state['value'])\n    \n\n@node_gui(nodes.RandNode)\nclass RandNodeGui(NodeGUI):\n    color = '#fcba03'\n    \n    # register the input widget class\n    input_widget_classes = { 'slider': RandSliderWidget }\n    \n    # attach the slider widget to the first node input\n    # display it _below_ the input pin\n    init_input_widgets = {\n        0: {'name': 'slider', 'pos': 'below'}\n    }\n```\n\nand this is it! Ryven will now register `RandNodeGui` as \"GUI class\" of the `RandNode` class, which serves as a container for all UI things. Your can add custom primary (\"main\") widgets to your nodes, input widgets, and further customize the look of the nodes.\n\nThe value provided by an input widget (e.g. `self.update_node_input(val)` above) will be returned in the node, when calling `input()` (e.g. `self.input(0)` in the `RandNode`), but only when the corresponding input is _not connected_. Otherwise, the value of the connected output will be returned.\n\n\u003c/details\u003e\n\nPlease find further resources on the GitHub wiki page in this repository.\n\n## Features\n\n- **headless mode** to run projects without GUI dependencies at high performance\n- **sophisticated nodes system** allowing for stateful nodes and widgets\n- **cross-platform**; running anywhere where Qt runs (for GUI), or simply Python (headless)\n- **rendering flow images** into PNGs\n- built-in **exec flow support** (like [UE BluePrints](https://docs.unrealengine.com/5.0/en-US/blueprints-visual-scripting-in-unreal-engine/)) unlike most other node editors\n- **custom Qt widgets support**\n- various **themes**, including light\n- **right-click operations system for nodes**\n- **variables system** with observer mechanism, to build nodes that automatically adapt to change of data\n- basic Python **logging support**\n\u003c!-- - primitive, very experimental **stylus support** for adding handwritten notes on touch devices --\u003e\n\n## License\n\n* This repository is licensed under the MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)\n* The underlying library ryvencore is licensed under LGPL-2.1 (LICENSE-LGPL-2.1 or https://www.gnu.org/licenses/lgpl-2.1.html)\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you shall be licensed as above, without any additional terms or conditions.\n\n## Credits\n\nContributions are highly appreciated. This project does not exist without the open-source community. I want to particularly thank the people listed in the `CREDITS.md` file.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleon-thomm%2Fryven","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleon-thomm%2Fryven","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleon-thomm%2Fryven/lists"}